1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "dbus/message.h" 6 7 #include <string> 8 9 #include "base/format_macros.h" 10 #include "base/logging.h" 11 #include "base/numerics/safe_conversions.h" 12 #include "base/strings/string_number_conversions.h" 13 #include "base/strings/string_util.h" 14 #include "base/strings/stringprintf.h" 15 #include "dbus/object_path.h" 16 #include "third_party/protobuf/src/google/protobuf/message_lite.h" 17 18 namespace { 19 20 // Appends the header name and the value to |output|, if the value is 21 // not empty. 22 void AppendStringHeader(const std::string& header_name, 23 const std::string& header_value, 24 std::string* output) { 25 if (!header_value.empty()) { 26 *output += header_name + ": " + header_value + "\n"; 27 } 28 } 29 30 // Appends the header name and the value to |output|, if the value is 31 // nonzero. 32 void AppendUint32Header(const std::string& header_name, 33 uint32_t header_value, 34 std::string* output) { 35 if (header_value != 0) { 36 *output += (header_name + ": " + base::UintToString(header_value) + "\n"); 37 } 38 } 39 40 } // namespace 41 42 namespace dbus { 43 44 bool IsDBusTypeUnixFdSupported() { 45 int major = 0, minor = 0, micro = 0; 46 dbus_get_version(&major, &minor, µ); 47 return major >= 1 && minor >= 4; 48 } 49 50 Message::Message() : raw_message_(nullptr) {} 51 52 Message::~Message() { 53 if (raw_message_) 54 dbus_message_unref(raw_message_); 55 } 56 57 void Message::Init(DBusMessage* raw_message) { 58 DCHECK(!raw_message_); 59 raw_message_ = raw_message; 60 } 61 62 Message::MessageType Message::GetMessageType() { 63 if (!raw_message_) 64 return MESSAGE_INVALID; 65 const int type = dbus_message_get_type(raw_message_); 66 return static_cast<Message::MessageType>(type); 67 } 68 69 std::string Message::GetMessageTypeAsString() { 70 switch (GetMessageType()) { 71 case MESSAGE_INVALID: 72 return "MESSAGE_INVALID"; 73 case MESSAGE_METHOD_CALL: 74 return "MESSAGE_METHOD_CALL"; 75 case MESSAGE_METHOD_RETURN: 76 return "MESSAGE_METHOD_RETURN"; 77 case MESSAGE_SIGNAL: 78 return "MESSAGE_SIGNAL"; 79 case MESSAGE_ERROR: 80 return "MESSAGE_ERROR"; 81 } 82 NOTREACHED(); 83 return std::string(); 84 } 85 86 std::string Message::ToStringInternal(const std::string& indent, 87 MessageReader* reader) { 88 const char* kBrokenMessage = "[broken message]"; 89 std::string output; 90 while (reader->HasMoreData()) { 91 const DataType type = reader->GetDataType(); 92 switch (type) { 93 case BYTE: { 94 uint8_t value = 0; 95 if (!reader->PopByte(&value)) 96 return kBrokenMessage; 97 output += indent + "byte " + base::UintToString(value) + "\n"; 98 break; 99 } 100 case BOOL: { 101 bool value = false; 102 if (!reader->PopBool(&value)) 103 return kBrokenMessage; 104 output += indent + "bool " + (value ? "true" : "false") + "\n"; 105 break; 106 } 107 case INT16: { 108 int16_t value = 0; 109 if (!reader->PopInt16(&value)) 110 return kBrokenMessage; 111 output += indent + "int16_t " + base::IntToString(value) + "\n"; 112 break; 113 } 114 case UINT16: { 115 uint16_t value = 0; 116 if (!reader->PopUint16(&value)) 117 return kBrokenMessage; 118 output += indent + "uint16_t " + base::UintToString(value) + "\n"; 119 break; 120 } 121 case INT32: { 122 int32_t value = 0; 123 if (!reader->PopInt32(&value)) 124 return kBrokenMessage; 125 output += indent + "int32_t " + base::IntToString(value) + "\n"; 126 break; 127 } 128 case UINT32: { 129 uint32_t value = 0; 130 if (!reader->PopUint32(&value)) 131 return kBrokenMessage; 132 output += indent + "uint32_t " + base::UintToString(value) + "\n"; 133 break; 134 } 135 case INT64: { 136 int64_t value = 0; 137 if (!reader->PopInt64(&value)) 138 return kBrokenMessage; 139 output += (indent + "int64_t " + base::Int64ToString(value) + "\n"); 140 break; 141 } 142 case UINT64: { 143 uint64_t value = 0; 144 if (!reader->PopUint64(&value)) 145 return kBrokenMessage; 146 output += (indent + "uint64_t " + base::NumberToString(value) + "\n"); 147 break; 148 } 149 case DOUBLE: { 150 double value = 0; 151 if (!reader->PopDouble(&value)) 152 return kBrokenMessage; 153 output += indent + "double " + base::NumberToString(value) + "\n"; 154 break; 155 } 156 case STRING: { 157 std::string value; 158 if (!reader->PopString(&value)) 159 return kBrokenMessage; 160 // Truncate if the string is longer than the limit. 161 const size_t kTruncateLength = 100; 162 if (value.size() < kTruncateLength) { 163 output += indent + "string \"" + value + "\"\n"; 164 } else { 165 std::string truncated; 166 base::TruncateUTF8ToByteSize(value, kTruncateLength, &truncated); 167 base::StringAppendF(&truncated, "... (%" PRIuS " bytes in total)", 168 value.size()); 169 output += indent + "string \"" + truncated + "\"\n"; 170 } 171 break; 172 } 173 case OBJECT_PATH: { 174 ObjectPath value; 175 if (!reader->PopObjectPath(&value)) 176 return kBrokenMessage; 177 output += indent + "object_path \"" + value.value() + "\"\n"; 178 break; 179 } 180 case ARRAY: { 181 MessageReader sub_reader(this); 182 if (!reader->PopArray(&sub_reader)) 183 return kBrokenMessage; 184 output += indent + "array [\n"; 185 output += ToStringInternal(indent + " ", &sub_reader); 186 output += indent + "]\n"; 187 break; 188 } 189 case STRUCT: { 190 MessageReader sub_reader(this); 191 if (!reader->PopStruct(&sub_reader)) 192 return kBrokenMessage; 193 output += indent + "struct {\n"; 194 output += ToStringInternal(indent + " ", &sub_reader); 195 output += indent + "}\n"; 196 break; 197 } 198 case DICT_ENTRY: { 199 MessageReader sub_reader(this); 200 if (!reader->PopDictEntry(&sub_reader)) 201 return kBrokenMessage; 202 output += indent + "dict entry {\n"; 203 output += ToStringInternal(indent + " ", &sub_reader); 204 output += indent + "}\n"; 205 break; 206 } 207 case VARIANT: { 208 MessageReader sub_reader(this); 209 if (!reader->PopVariant(&sub_reader)) 210 return kBrokenMessage; 211 output += indent + "variant "; 212 output += ToStringInternal(indent + " ", &sub_reader); 213 break; 214 } 215 case UNIX_FD: { 216 CHECK(IsDBusTypeUnixFdSupported()); 217 218 base::ScopedFD file_descriptor; 219 if (!reader->PopFileDescriptor(&file_descriptor)) 220 return kBrokenMessage; 221 output += 222 indent + "fd#" + base::IntToString(file_descriptor.get()) + "\n"; 223 break; 224 } 225 default: 226 LOG(FATAL) << "Unknown type: " << type; 227 } 228 } 229 return output; 230 } 231 232 // The returned string consists of message headers such as 233 // destination if any, followed by a blank line, and the message 234 // payload. For example, a MethodCall's ToString() will look like: 235 // 236 // destination: com.example.Service 237 // path: /com/example/Object 238 // interface: com.example.Interface 239 // member: SomeMethod 240 // 241 // string \"payload\" 242 // ... 243 std::string Message::ToString() { 244 if (!raw_message_) 245 return std::string(); 246 247 // Generate headers first. 248 std::string headers; 249 AppendStringHeader("message_type", GetMessageTypeAsString(), &headers); 250 AppendStringHeader("destination", GetDestination(), &headers); 251 AppendStringHeader("path", GetPath().value(), &headers); 252 AppendStringHeader("interface", GetInterface(), &headers); 253 AppendStringHeader("member", GetMember(), &headers); 254 AppendStringHeader("error_name", GetErrorName(), &headers); 255 AppendStringHeader("sender", GetSender(), &headers); 256 AppendStringHeader("signature", GetSignature(), &headers); 257 AppendUint32Header("serial", GetSerial(), &headers); 258 AppendUint32Header("reply_serial", GetReplySerial(), &headers); 259 260 // Generate the payload. 261 MessageReader reader(this); 262 return headers + "\n" + ToStringInternal(std::string(), &reader); 263 } 264 265 bool Message::SetDestination(const std::string& destination) { 266 return dbus_message_set_destination(raw_message_, destination.c_str()); 267 } 268 269 bool Message::SetPath(const ObjectPath& path) { 270 return dbus_message_set_path(raw_message_, path.value().c_str()); 271 } 272 273 bool Message::SetInterface(const std::string& interface) { 274 return dbus_message_set_interface(raw_message_, interface.c_str()); 275 } 276 277 bool Message::SetMember(const std::string& member) { 278 return dbus_message_set_member(raw_message_, member.c_str()); 279 } 280 281 bool Message::SetErrorName(const std::string& error_name) { 282 return dbus_message_set_error_name(raw_message_, error_name.c_str()); 283 } 284 285 bool Message::SetSender(const std::string& sender) { 286 return dbus_message_set_sender(raw_message_, sender.c_str()); 287 } 288 289 void Message::SetSerial(uint32_t serial) { 290 dbus_message_set_serial(raw_message_, serial); 291 } 292 293 void Message::SetReplySerial(uint32_t reply_serial) { 294 dbus_message_set_reply_serial(raw_message_, reply_serial); 295 } 296 297 std::string Message::GetDestination() { 298 const char* destination = dbus_message_get_destination(raw_message_); 299 return destination ? destination : ""; 300 } 301 302 ObjectPath Message::GetPath() { 303 const char* path = dbus_message_get_path(raw_message_); 304 return ObjectPath(path ? path : ""); 305 } 306 307 std::string Message::GetInterface() { 308 const char* interface = dbus_message_get_interface(raw_message_); 309 return interface ? interface : ""; 310 } 311 312 std::string Message::GetMember() { 313 const char* member = dbus_message_get_member(raw_message_); 314 return member ? member : ""; 315 } 316 317 std::string Message::GetErrorName() { 318 const char* error_name = dbus_message_get_error_name(raw_message_); 319 return error_name ? error_name : ""; 320 } 321 322 std::string Message::GetSender() { 323 const char* sender = dbus_message_get_sender(raw_message_); 324 return sender ? sender : ""; 325 } 326 327 std::string Message::GetSignature() { 328 const char* signature = dbus_message_get_signature(raw_message_); 329 return signature ? signature : ""; 330 } 331 332 uint32_t Message::GetSerial() { 333 return dbus_message_get_serial(raw_message_); 334 } 335 336 uint32_t Message::GetReplySerial() { 337 return dbus_message_get_reply_serial(raw_message_); 338 } 339 340 // 341 // MethodCall implementation. 342 // 343 344 MethodCall::MethodCall(const std::string& interface_name, 345 const std::string& method_name) { 346 Init(dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL)); 347 348 CHECK(SetInterface(interface_name)); 349 CHECK(SetMember(method_name)); 350 } 351 352 MethodCall::MethodCall() = default; 353 354 std::unique_ptr<MethodCall> MethodCall::FromRawMessage( 355 DBusMessage* raw_message) { 356 DCHECK_EQ(DBUS_MESSAGE_TYPE_METHOD_CALL, dbus_message_get_type(raw_message)); 357 358 std::unique_ptr<MethodCall> method_call(new MethodCall()); 359 method_call->Init(raw_message); 360 return method_call; 361 } 362 363 // 364 // Signal implementation. 365 // 366 Signal::Signal(const std::string& interface_name, 367 const std::string& method_name) { 368 Init(dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL)); 369 370 CHECK(SetInterface(interface_name)); 371 CHECK(SetMember(method_name)); 372 } 373 374 Signal::Signal() = default; 375 376 std::unique_ptr<Signal> Signal::FromRawMessage(DBusMessage* raw_message) { 377 DCHECK_EQ(DBUS_MESSAGE_TYPE_SIGNAL, dbus_message_get_type(raw_message)); 378 379 std::unique_ptr<Signal> signal(new Signal()); 380 signal->Init(raw_message); 381 return signal; 382 } 383 384 // 385 // Response implementation. 386 // 387 388 Response::Response() = default; 389 390 std::unique_ptr<Response> Response::FromRawMessage(DBusMessage* raw_message) { 391 DCHECK_EQ(DBUS_MESSAGE_TYPE_METHOD_RETURN, 392 dbus_message_get_type(raw_message)); 393 394 std::unique_ptr<Response> response(new Response()); 395 response->Init(raw_message); 396 return response; 397 } 398 399 std::unique_ptr<Response> Response::FromMethodCall(MethodCall* method_call) { 400 std::unique_ptr<Response> response(new Response()); 401 response->Init(dbus_message_new_method_return(method_call->raw_message())); 402 return response; 403 } 404 405 std::unique_ptr<Response> Response::CreateEmpty() { 406 std::unique_ptr<Response> response(new Response()); 407 response->Init(dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN)); 408 return response; 409 } 410 411 // 412 // ErrorResponse implementation. 413 // 414 415 ErrorResponse::ErrorResponse() = default; 416 417 std::unique_ptr<ErrorResponse> ErrorResponse::FromRawMessage( 418 DBusMessage* raw_message) { 419 DCHECK_EQ(DBUS_MESSAGE_TYPE_ERROR, dbus_message_get_type(raw_message)); 420 421 std::unique_ptr<ErrorResponse> response(new ErrorResponse()); 422 response->Init(raw_message); 423 return response; 424 } 425 426 std::unique_ptr<ErrorResponse> ErrorResponse::FromMethodCall( 427 MethodCall* method_call, 428 const std::string& error_name, 429 const std::string& error_message) { 430 std::unique_ptr<ErrorResponse> response(new ErrorResponse()); 431 response->Init(dbus_message_new_error( 432 method_call->raw_message(), error_name.c_str(), error_message.c_str())); 433 return response; 434 } 435 436 // 437 // MessageWriter implementation. 438 // 439 440 MessageWriter::MessageWriter(Message* message) 441 : message_(message), container_is_open_(false) { 442 memset(&raw_message_iter_, 0, sizeof(raw_message_iter_)); 443 if (message) 444 dbus_message_iter_init_append(message_->raw_message(), &raw_message_iter_); 445 } 446 447 MessageWriter::~MessageWriter() = default; 448 449 void MessageWriter::AppendByte(uint8_t value) { 450 AppendBasic(DBUS_TYPE_BYTE, &value); 451 } 452 453 void MessageWriter::AppendBool(bool value) { 454 // The size of dbus_bool_t and the size of bool are different. The 455 // former is always 4 per dbus-types.h, whereas the latter is usually 1. 456 // dbus_message_iter_append_basic() used in AppendBasic() expects four 457 // bytes for DBUS_TYPE_BOOLEAN, so we must pass a dbus_bool_t, instead 458 // of a bool, to AppendBasic(). 459 dbus_bool_t dbus_value = value ? 1 : 0; 460 AppendBasic(DBUS_TYPE_BOOLEAN, &dbus_value); 461 } 462 463 void MessageWriter::AppendInt16(int16_t value) { 464 AppendBasic(DBUS_TYPE_INT16, &value); 465 } 466 467 void MessageWriter::AppendUint16(uint16_t value) { 468 AppendBasic(DBUS_TYPE_UINT16, &value); 469 } 470 471 void MessageWriter::AppendInt32(int32_t value) { 472 AppendBasic(DBUS_TYPE_INT32, &value); 473 } 474 475 void MessageWriter::AppendUint32(uint32_t value) { 476 AppendBasic(DBUS_TYPE_UINT32, &value); 477 } 478 479 void MessageWriter::AppendInt64(int64_t value) { 480 AppendBasic(DBUS_TYPE_INT64, &value); 481 } 482 483 void MessageWriter::AppendUint64(uint64_t value) { 484 AppendBasic(DBUS_TYPE_UINT64, &value); 485 } 486 487 void MessageWriter::AppendDouble(double value) { 488 AppendBasic(DBUS_TYPE_DOUBLE, &value); 489 } 490 491 void MessageWriter::AppendString(const std::string& value) { 492 // D-Bus Specification (0.19) says a string "must be valid UTF-8". 493 CHECK(base::IsStringUTF8(value)); 494 const char* pointer = value.c_str(); 495 AppendBasic(DBUS_TYPE_STRING, &pointer); 496 // TODO(satorux): It may make sense to return an error here, as the 497 // input string can be large. If needed, we could add something like 498 // bool AppendStringWithErrorChecking(). 499 } 500 501 void MessageWriter::AppendObjectPath(const ObjectPath& value) { 502 CHECK(value.IsValid()); 503 const char* pointer = value.value().c_str(); 504 AppendBasic(DBUS_TYPE_OBJECT_PATH, &pointer); 505 } 506 507 // Ideally, client shouldn't need to supply the signature string, but 508 // the underlying D-Bus library requires us to supply this before 509 // appending contents to array and variant. It's technically possible 510 // for us to design API that doesn't require the signature but it will 511 // complicate the implementation so we decided to have the signature 512 // parameter. Hopefully, variants are less used in request messages from 513 // client side than response message from server side, so this should 514 // not be a big issue. 515 void MessageWriter::OpenArray(const std::string& signature, 516 MessageWriter* writer) { 517 DCHECK(!container_is_open_); 518 519 const bool success = dbus_message_iter_open_container( 520 &raw_message_iter_, DBUS_TYPE_ARRAY, signature.c_str(), 521 &writer->raw_message_iter_); 522 CHECK(success) << "Unable to allocate memory"; 523 container_is_open_ = true; 524 } 525 526 void MessageWriter::OpenVariant(const std::string& signature, 527 MessageWriter* writer) { 528 DCHECK(!container_is_open_); 529 530 const bool success = dbus_message_iter_open_container( 531 &raw_message_iter_, DBUS_TYPE_VARIANT, signature.c_str(), 532 &writer->raw_message_iter_); 533 CHECK(success) << "Unable to allocate memory"; 534 container_is_open_ = true; 535 } 536 537 void MessageWriter::OpenStruct(MessageWriter* writer) { 538 DCHECK(!container_is_open_); 539 540 const bool success = 541 dbus_message_iter_open_container(&raw_message_iter_, DBUS_TYPE_STRUCT, 542 nullptr, // Signature should be nullptr. 543 &writer->raw_message_iter_); 544 CHECK(success) << "Unable to allocate memory"; 545 container_is_open_ = true; 546 } 547 548 void MessageWriter::OpenDictEntry(MessageWriter* writer) { 549 DCHECK(!container_is_open_); 550 551 const bool success = 552 dbus_message_iter_open_container(&raw_message_iter_, DBUS_TYPE_DICT_ENTRY, 553 nullptr, // Signature should be nullptr. 554 &writer->raw_message_iter_); 555 CHECK(success) << "Unable to allocate memory"; 556 container_is_open_ = true; 557 } 558 559 void MessageWriter::CloseContainer(MessageWriter* writer) { 560 DCHECK(container_is_open_); 561 562 const bool success = dbus_message_iter_close_container( 563 &raw_message_iter_, &writer->raw_message_iter_); 564 CHECK(success) << "Unable to allocate memory"; 565 container_is_open_ = false; 566 } 567 568 void MessageWriter::AppendArrayOfBytes(const uint8_t* values, size_t length) { 569 DCHECK(!container_is_open_); 570 MessageWriter array_writer(message_); 571 OpenArray("y", &array_writer); 572 const bool success = dbus_message_iter_append_fixed_array( 573 &(array_writer.raw_message_iter_), DBUS_TYPE_BYTE, &values, 574 static_cast<int>(length)); 575 CHECK(success) << "Unable to allocate memory"; 576 CloseContainer(&array_writer); 577 } 578 579 void MessageWriter::AppendArrayOfInt32s(const int32_t* values, size_t length) { 580 DCHECK(!container_is_open_); 581 MessageWriter array_writer(message_); 582 OpenArray("i", &array_writer); 583 const bool success = dbus_message_iter_append_fixed_array( 584 &(array_writer.raw_message_iter_), DBUS_TYPE_INT32, &values, 585 static_cast<int>(length)); 586 CHECK(success) << "Unable to allocate memory"; 587 CloseContainer(&array_writer); 588 } 589 590 void MessageWriter::AppendArrayOfUint32s(const uint32_t* values, 591 size_t length) { 592 DCHECK(!container_is_open_); 593 MessageWriter array_writer(message_); 594 OpenArray("u", &array_writer); 595 const bool success = dbus_message_iter_append_fixed_array( 596 &(array_writer.raw_message_iter_), DBUS_TYPE_UINT32, &values, 597 static_cast<int>(length)); 598 CHECK(success) << "Unable to allocate memory"; 599 CloseContainer(&array_writer); 600 } 601 602 void MessageWriter::AppendArrayOfDoubles(const double* values, size_t length) { 603 DCHECK(!container_is_open_); 604 MessageWriter array_writer(message_); 605 OpenArray("d", &array_writer); 606 const bool success = dbus_message_iter_append_fixed_array( 607 &(array_writer.raw_message_iter_), DBUS_TYPE_DOUBLE, &values, 608 static_cast<int>(length)); 609 CHECK(success) << "Unable to allocate memory"; 610 CloseContainer(&array_writer); 611 } 612 613 void MessageWriter::AppendArrayOfStrings( 614 const std::vector<std::string>& strings) { 615 DCHECK(!container_is_open_); 616 MessageWriter array_writer(message_); 617 OpenArray("s", &array_writer); 618 for (size_t i = 0; i < strings.size(); ++i) { 619 array_writer.AppendString(strings[i]); 620 } 621 CloseContainer(&array_writer); 622 } 623 624 void MessageWriter::AppendArrayOfObjectPaths( 625 const std::vector<ObjectPath>& object_paths) { 626 DCHECK(!container_is_open_); 627 MessageWriter array_writer(message_); 628 OpenArray("o", &array_writer); 629 for (size_t i = 0; i < object_paths.size(); ++i) { 630 array_writer.AppendObjectPath(object_paths[i]); 631 } 632 CloseContainer(&array_writer); 633 } 634 635 bool MessageWriter::AppendProtoAsArrayOfBytes( 636 const google::protobuf::MessageLite& protobuf) { 637 std::string serialized_proto; 638 if (!protobuf.SerializeToString(&serialized_proto)) { 639 LOG(ERROR) << "Unable to serialize supplied protocol buffer"; 640 return false; 641 } 642 AppendArrayOfBytes(reinterpret_cast<const uint8_t*>(serialized_proto.data()), 643 serialized_proto.size()); 644 return true; 645 } 646 647 void MessageWriter::AppendVariantOfByte(uint8_t value) { 648 AppendVariantOfBasic(DBUS_TYPE_BYTE, &value); 649 } 650 651 void MessageWriter::AppendVariantOfBool(bool value) { 652 // See the comment at MessageWriter::AppendBool(). 653 dbus_bool_t dbus_value = value; 654 AppendVariantOfBasic(DBUS_TYPE_BOOLEAN, &dbus_value); 655 } 656 657 void MessageWriter::AppendVariantOfInt16(int16_t value) { 658 AppendVariantOfBasic(DBUS_TYPE_INT16, &value); 659 } 660 661 void MessageWriter::AppendVariantOfUint16(uint16_t value) { 662 AppendVariantOfBasic(DBUS_TYPE_UINT16, &value); 663 } 664 665 void MessageWriter::AppendVariantOfInt32(int32_t value) { 666 AppendVariantOfBasic(DBUS_TYPE_INT32, &value); 667 } 668 669 void MessageWriter::AppendVariantOfUint32(uint32_t value) { 670 AppendVariantOfBasic(DBUS_TYPE_UINT32, &value); 671 } 672 673 void MessageWriter::AppendVariantOfInt64(int64_t value) { 674 AppendVariantOfBasic(DBUS_TYPE_INT64, &value); 675 } 676 677 void MessageWriter::AppendVariantOfUint64(uint64_t value) { 678 AppendVariantOfBasic(DBUS_TYPE_UINT64, &value); 679 } 680 681 void MessageWriter::AppendVariantOfDouble(double value) { 682 AppendVariantOfBasic(DBUS_TYPE_DOUBLE, &value); 683 } 684 685 void MessageWriter::AppendVariantOfString(const std::string& value) { 686 const char* pointer = value.c_str(); 687 AppendVariantOfBasic(DBUS_TYPE_STRING, &pointer); 688 } 689 690 void MessageWriter::AppendVariantOfObjectPath(const ObjectPath& value) { 691 const char* pointer = value.value().c_str(); 692 AppendVariantOfBasic(DBUS_TYPE_OBJECT_PATH, &pointer); 693 } 694 695 void MessageWriter::AppendBasic(int dbus_type, const void* value) { 696 DCHECK(!container_is_open_); 697 698 const bool success = 699 dbus_message_iter_append_basic(&raw_message_iter_, dbus_type, value); 700 // dbus_message_iter_append_basic() fails only when there is not enough 701 // memory. We don't return this error as there is nothing we can do when 702 // it fails to allocate memory for a byte etc. 703 CHECK(success) << "Unable to allocate memory"; 704 } 705 706 void MessageWriter::AppendVariantOfBasic(int dbus_type, const void* value) { 707 const std::string signature(1u, // length 708 base::checked_cast<char>(dbus_type)); 709 MessageWriter variant_writer(message_); 710 OpenVariant(signature, &variant_writer); 711 variant_writer.AppendBasic(dbus_type, value); 712 CloseContainer(&variant_writer); 713 } 714 715 void MessageWriter::AppendFileDescriptor(int value) { 716 CHECK(IsDBusTypeUnixFdSupported()); 717 AppendBasic(DBUS_TYPE_UNIX_FD, &value); // This duplicates the FD. 718 } 719 720 // 721 // MessageReader implementation. 722 // 723 724 MessageReader::MessageReader(Message* message) : message_(message) { 725 memset(&raw_message_iter_, 0, sizeof(raw_message_iter_)); 726 if (message) 727 dbus_message_iter_init(message_->raw_message(), &raw_message_iter_); 728 } 729 730 MessageReader::~MessageReader() = default; 731 732 bool MessageReader::HasMoreData() { 733 const int dbus_type = dbus_message_iter_get_arg_type(&raw_message_iter_); 734 return dbus_type != DBUS_TYPE_INVALID; 735 } 736 737 bool MessageReader::PopByte(uint8_t* value) { 738 return PopBasic(DBUS_TYPE_BYTE, value); 739 } 740 741 bool MessageReader::PopBool(bool* value) { 742 // Like MessageWriter::AppendBool(), we should copy |value| to 743 // dbus_bool_t, as dbus_message_iter_get_basic() used in PopBasic() 744 // expects four bytes for DBUS_TYPE_BOOLEAN. 745 dbus_bool_t dbus_value = FALSE; 746 const bool success = PopBasic(DBUS_TYPE_BOOLEAN, &dbus_value); 747 *value = static_cast<bool>(dbus_value); 748 return success; 749 } 750 751 bool MessageReader::PopInt16(int16_t* value) { 752 return PopBasic(DBUS_TYPE_INT16, value); 753 } 754 755 bool MessageReader::PopUint16(uint16_t* value) { 756 return PopBasic(DBUS_TYPE_UINT16, value); 757 } 758 759 bool MessageReader::PopInt32(int32_t* value) { 760 return PopBasic(DBUS_TYPE_INT32, value); 761 } 762 763 bool MessageReader::PopUint32(uint32_t* value) { 764 return PopBasic(DBUS_TYPE_UINT32, value); 765 } 766 767 bool MessageReader::PopInt64(int64_t* value) { 768 return PopBasic(DBUS_TYPE_INT64, value); 769 } 770 771 bool MessageReader::PopUint64(uint64_t* value) { 772 return PopBasic(DBUS_TYPE_UINT64, value); 773 } 774 775 bool MessageReader::PopDouble(double* value) { 776 return PopBasic(DBUS_TYPE_DOUBLE, value); 777 } 778 779 bool MessageReader::PopString(std::string* value) { 780 char* tmp_value = nullptr; 781 const bool success = PopBasic(DBUS_TYPE_STRING, &tmp_value); 782 if (success) 783 value->assign(tmp_value); 784 return success; 785 } 786 787 bool MessageReader::PopObjectPath(ObjectPath* value) { 788 char* tmp_value = nullptr; 789 const bool success = PopBasic(DBUS_TYPE_OBJECT_PATH, &tmp_value); 790 if (success) 791 *value = ObjectPath(tmp_value); 792 return success; 793 } 794 795 bool MessageReader::PopArray(MessageReader* sub_reader) { 796 return PopContainer(DBUS_TYPE_ARRAY, sub_reader); 797 } 798 799 bool MessageReader::PopStruct(MessageReader* sub_reader) { 800 return PopContainer(DBUS_TYPE_STRUCT, sub_reader); 801 } 802 803 bool MessageReader::PopDictEntry(MessageReader* sub_reader) { 804 return PopContainer(DBUS_TYPE_DICT_ENTRY, sub_reader); 805 } 806 807 bool MessageReader::PopVariant(MessageReader* sub_reader) { 808 return PopContainer(DBUS_TYPE_VARIANT, sub_reader); 809 } 810 811 bool MessageReader::PopArrayOfBytes(const uint8_t** bytes, size_t* length) { 812 MessageReader array_reader(message_); 813 if (!PopArray(&array_reader)) 814 return false; 815 // An empty array is allowed. 816 if (!array_reader.HasMoreData()) { 817 *length = 0; 818 *bytes = nullptr; 819 return true; 820 } 821 if (!array_reader.CheckDataType(DBUS_TYPE_BYTE)) 822 return false; 823 int int_length = 0; 824 dbus_message_iter_get_fixed_array(&array_reader.raw_message_iter_, bytes, 825 &int_length); 826 *length = static_cast<size_t>(int_length); 827 return true; 828 } 829 830 bool MessageReader::PopArrayOfInt32s(const int32_t** signed_ints, 831 size_t* length) { 832 MessageReader array_reader(message_); 833 if (!PopArray(&array_reader)) 834 return false; 835 // An empty array is allowed. 836 if (!array_reader.HasMoreData()) { 837 *length = 0; 838 *signed_ints = nullptr; 839 return true; 840 } 841 if (!array_reader.CheckDataType(DBUS_TYPE_INT32)) 842 return false; 843 int int_length = 0; 844 dbus_message_iter_get_fixed_array(&array_reader.raw_message_iter_, 845 signed_ints, &int_length); 846 *length = static_cast<size_t>(int_length); 847 return true; 848 } 849 850 bool MessageReader::PopArrayOfUint32s(const uint32_t** unsigned_ints, 851 size_t* length) { 852 MessageReader array_reader(message_); 853 if (!PopArray(&array_reader)) 854 return false; 855 // An empty array is allowed. 856 if (!array_reader.HasMoreData()) { 857 *length = 0; 858 *unsigned_ints = nullptr; 859 return true; 860 } 861 if (!array_reader.CheckDataType(DBUS_TYPE_UINT32)) 862 return false; 863 int int_length = 0; 864 dbus_message_iter_get_fixed_array(&array_reader.raw_message_iter_, 865 unsigned_ints, &int_length); 866 *length = static_cast<size_t>(int_length); 867 return true; 868 } 869 870 bool MessageReader::PopArrayOfDoubles(const double** doubles, size_t* length) { 871 MessageReader array_reader(message_); 872 if (!PopArray(&array_reader)) 873 return false; 874 if (!array_reader.HasMoreData()) { 875 *length = 0; 876 *doubles = nullptr; 877 return true; 878 } 879 if (!array_reader.CheckDataType(DBUS_TYPE_DOUBLE)) 880 return false; 881 int int_length = 0; 882 dbus_message_iter_get_fixed_array(&array_reader.raw_message_iter_, doubles, 883 &int_length); 884 *length = static_cast<size_t>(int_length); 885 return true; 886 } 887 888 bool MessageReader::PopArrayOfStrings(std::vector<std::string>* strings) { 889 strings->clear(); 890 MessageReader array_reader(message_); 891 if (!PopArray(&array_reader)) 892 return false; 893 while (array_reader.HasMoreData()) { 894 std::string string; 895 if (!array_reader.PopString(&string)) 896 return false; 897 strings->push_back(string); 898 } 899 return true; 900 } 901 902 bool MessageReader::PopArrayOfObjectPaths( 903 std::vector<ObjectPath>* object_paths) { 904 object_paths->clear(); 905 MessageReader array_reader(message_); 906 if (!PopArray(&array_reader)) 907 return false; 908 while (array_reader.HasMoreData()) { 909 ObjectPath object_path; 910 if (!array_reader.PopObjectPath(&object_path)) 911 return false; 912 object_paths->push_back(object_path); 913 } 914 return true; 915 } 916 917 bool MessageReader::PopArrayOfBytesAsProto( 918 google::protobuf::MessageLite* protobuf) { 919 DCHECK(protobuf); 920 const char* serialized_buf = nullptr; 921 size_t buf_size = 0; 922 if (!PopArrayOfBytes(reinterpret_cast<const uint8_t**>(&serialized_buf), 923 &buf_size)) { 924 LOG(ERROR) << "Error reading array of bytes"; 925 return false; 926 } 927 if (!protobuf->ParseFromArray(serialized_buf, buf_size)) { 928 LOG(ERROR) << "Failed to parse protocol buffer from array"; 929 return false; 930 } 931 return true; 932 } 933 934 bool MessageReader::PopVariantOfByte(uint8_t* value) { 935 return PopVariantOfBasic(DBUS_TYPE_BYTE, value); 936 } 937 938 bool MessageReader::PopVariantOfBool(bool* value) { 939 // See the comment at MessageReader::PopBool(). 940 dbus_bool_t dbus_value = FALSE; 941 const bool success = PopVariantOfBasic(DBUS_TYPE_BOOLEAN, &dbus_value); 942 *value = static_cast<bool>(dbus_value); 943 return success; 944 } 945 946 bool MessageReader::PopVariantOfInt16(int16_t* value) { 947 return PopVariantOfBasic(DBUS_TYPE_INT16, value); 948 } 949 950 bool MessageReader::PopVariantOfUint16(uint16_t* value) { 951 return PopVariantOfBasic(DBUS_TYPE_UINT16, value); 952 } 953 954 bool MessageReader::PopVariantOfInt32(int32_t* value) { 955 return PopVariantOfBasic(DBUS_TYPE_INT32, value); 956 } 957 958 bool MessageReader::PopVariantOfUint32(uint32_t* value) { 959 return PopVariantOfBasic(DBUS_TYPE_UINT32, value); 960 } 961 962 bool MessageReader::PopVariantOfInt64(int64_t* value) { 963 return PopVariantOfBasic(DBUS_TYPE_INT64, value); 964 } 965 966 bool MessageReader::PopVariantOfUint64(uint64_t* value) { 967 return PopVariantOfBasic(DBUS_TYPE_UINT64, value); 968 } 969 970 bool MessageReader::PopVariantOfDouble(double* value) { 971 return PopVariantOfBasic(DBUS_TYPE_DOUBLE, value); 972 } 973 974 bool MessageReader::PopVariantOfString(std::string* value) { 975 char* tmp_value = nullptr; 976 const bool success = PopVariantOfBasic(DBUS_TYPE_STRING, &tmp_value); 977 if (success) 978 value->assign(tmp_value); 979 return success; 980 } 981 982 bool MessageReader::PopVariantOfObjectPath(ObjectPath* value) { 983 char* tmp_value = nullptr; 984 const bool success = PopVariantOfBasic(DBUS_TYPE_OBJECT_PATH, &tmp_value); 985 if (success) 986 *value = ObjectPath(tmp_value); 987 return success; 988 } 989 990 Message::DataType MessageReader::GetDataType() { 991 const int dbus_type = dbus_message_iter_get_arg_type(&raw_message_iter_); 992 return static_cast<Message::DataType>(dbus_type); 993 } 994 995 std::string MessageReader::GetDataSignature() { 996 std::string signature; 997 char* raw_signature = dbus_message_iter_get_signature(&raw_message_iter_); 998 if (raw_signature) { 999 signature = raw_signature; 1000 dbus_free(raw_signature); 1001 } 1002 return signature; 1003 } 1004 1005 bool MessageReader::CheckDataType(int dbus_type) { 1006 const int actual_type = dbus_message_iter_get_arg_type(&raw_message_iter_); 1007 if (actual_type != dbus_type) { 1008 VLOG(1) << "Type " << dbus_type << " is expected but got " << actual_type; 1009 return false; 1010 } 1011 return true; 1012 } 1013 1014 bool MessageReader::PopBasic(int dbus_type, void* value) { 1015 if (!CheckDataType(dbus_type)) 1016 return false; 1017 // dbus_message_iter_get_basic() here should always work, as we have 1018 // already checked the next item's data type in CheckDataType(). Note 1019 // that dbus_message_iter_get_basic() is a void function. 1020 dbus_message_iter_get_basic(&raw_message_iter_, value); 1021 DCHECK(value); 1022 dbus_message_iter_next(&raw_message_iter_); 1023 return true; 1024 } 1025 1026 bool MessageReader::PopContainer(int dbus_type, MessageReader* sub_reader) { 1027 DCHECK_NE(this, sub_reader); 1028 1029 if (!CheckDataType(dbus_type)) 1030 return false; 1031 dbus_message_iter_recurse(&raw_message_iter_, &sub_reader->raw_message_iter_); 1032 dbus_message_iter_next(&raw_message_iter_); 1033 return true; 1034 } 1035 1036 bool MessageReader::PopVariantOfBasic(int dbus_type, void* value) { 1037 MessageReader variant_reader(message_); 1038 if (!PopVariant(&variant_reader)) 1039 return false; 1040 return variant_reader.PopBasic(dbus_type, value); 1041 } 1042 1043 bool MessageReader::PopFileDescriptor(base::ScopedFD* value) { 1044 CHECK(IsDBusTypeUnixFdSupported()); 1045 1046 int fd = -1; 1047 const bool success = PopBasic(DBUS_TYPE_UNIX_FD, &fd); 1048 if (!success) 1049 return false; 1050 1051 *value = base::ScopedFD(fd); 1052 return true; 1053 } 1054 1055 } // namespace dbus 1056