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 #ifndef DBUS_MESSAGE_H_ 6 #define DBUS_MESSAGE_H_ 7 8 #include <dbus/dbus.h> 9 #include <stddef.h> 10 #include <stdint.h> 11 12 #include <memory> 13 #include <string> 14 #include <vector> 15 16 #include "base/files/scoped_file.h" 17 #include "base/macros.h" 18 #include "dbus/dbus_export.h" 19 #include "dbus/object_path.h" 20 21 namespace google { 22 namespace protobuf { 23 24 class MessageLite; 25 26 } // namespace protobuf 27 } // namespace google 28 29 namespace dbus { 30 31 class MessageWriter; 32 class MessageReader; 33 34 // DBUS_TYPE_UNIX_FD was added in D-Bus version 1.4 35 #if !defined(DBUS_TYPE_UNIX_FD) 36 #define DBUS_TYPE_UNIX_FD ((int)'h') 37 #endif 38 39 // Returns true if Unix FD passing is supported in libdbus. 40 // The check is done runtime rather than compile time as the libdbus 41 // version used at runtime may be different from the one used at compile time. 42 CHROME_DBUS_EXPORT bool IsDBusTypeUnixFdSupported(); 43 44 // Message is the base class of D-Bus message types. Client code must use 45 // sub classes such as MethodCall and Response instead. 46 // 47 // The class name Message is very generic, but there should be no problem 48 // as the class is inside 'dbus' namespace. We chose to name this way, as 49 // libdbus defines lots of types starting with DBus, such as 50 // DBusMessage. We should avoid confusion and conflict with these types. 51 class CHROME_DBUS_EXPORT Message { 52 public: 53 // The message type used in D-Bus. Redefined here so client code 54 // doesn't need to use raw D-Bus macros. DBUS_MESSAGE_TYPE_INVALID 55 // etc. are #define macros. Having an enum type here makes code a bit 56 // more type-safe. 57 enum MessageType { 58 MESSAGE_INVALID = DBUS_MESSAGE_TYPE_INVALID, 59 MESSAGE_METHOD_CALL = DBUS_MESSAGE_TYPE_METHOD_CALL, 60 MESSAGE_METHOD_RETURN = DBUS_MESSAGE_TYPE_METHOD_RETURN, 61 MESSAGE_SIGNAL = DBUS_MESSAGE_TYPE_SIGNAL, 62 MESSAGE_ERROR = DBUS_MESSAGE_TYPE_ERROR, 63 }; 64 65 // The data type used in the D-Bus type system. See the comment at 66 // MessageType for why we are redefining data types here. 67 enum DataType { 68 INVALID_DATA = DBUS_TYPE_INVALID, 69 BYTE = DBUS_TYPE_BYTE, 70 BOOL = DBUS_TYPE_BOOLEAN, 71 INT16 = DBUS_TYPE_INT16, 72 UINT16 = DBUS_TYPE_UINT16, 73 INT32 = DBUS_TYPE_INT32, 74 UINT32 = DBUS_TYPE_UINT32, 75 INT64 = DBUS_TYPE_INT64, 76 UINT64 = DBUS_TYPE_UINT64, 77 DOUBLE = DBUS_TYPE_DOUBLE, 78 STRING = DBUS_TYPE_STRING, 79 OBJECT_PATH = DBUS_TYPE_OBJECT_PATH, 80 ARRAY = DBUS_TYPE_ARRAY, 81 STRUCT = DBUS_TYPE_STRUCT, 82 DICT_ENTRY = DBUS_TYPE_DICT_ENTRY, 83 VARIANT = DBUS_TYPE_VARIANT, 84 UNIX_FD = DBUS_TYPE_UNIX_FD, 85 }; 86 87 // Returns the type of the message. Returns MESSAGE_INVALID if 88 // raw_message_ is NULL. 89 MessageType GetMessageType(); 90 91 // Returns the type of the message as string like "MESSAGE_METHOD_CALL" 92 // for instance. 93 std::string GetMessageTypeAsString(); 94 raw_message()95 DBusMessage* raw_message() { return raw_message_; } 96 97 // Sets the destination, the path, the interface, the member, etc. 98 bool SetDestination(const std::string& destination); 99 bool SetPath(const ObjectPath& path); 100 bool SetInterface(const std::string& interface); 101 bool SetMember(const std::string& member); 102 bool SetErrorName(const std::string& error_name); 103 bool SetSender(const std::string& sender); 104 void SetSerial(uint32_t serial); 105 void SetReplySerial(uint32_t reply_serial); 106 // SetSignature() does not exist as we cannot do it. 107 108 // Gets the destination, the path, the interface, the member, etc. 109 // If not set, an empty string is returned. 110 std::string GetDestination(); 111 ObjectPath GetPath(); 112 std::string GetInterface(); 113 std::string GetMember(); 114 std::string GetErrorName(); 115 std::string GetSender(); 116 std::string GetSignature(); 117 // Gets the serial and reply serial numbers. Returns 0 if not set. 118 uint32_t GetSerial(); 119 uint32_t GetReplySerial(); 120 121 // Returns the string representation of this message. Useful for 122 // debugging. The output is truncated as needed (ex. strings are truncated 123 // if longer than a certain limit defined in the .cc file). 124 std::string ToString(); 125 126 protected: 127 // This class cannot be instantiated. Use sub classes instead. 128 Message(); 129 virtual ~Message(); 130 131 // Initializes the message with the given raw message. 132 void Init(DBusMessage* raw_message); 133 134 private: 135 // Helper function used in ToString(). 136 std::string ToStringInternal(const std::string& indent, 137 MessageReader* reader); 138 139 DBusMessage* raw_message_; 140 DISALLOW_COPY_AND_ASSIGN(Message); 141 }; 142 143 // MessageCall is a type of message used for calling a method via D-Bus. 144 class CHROME_DBUS_EXPORT MethodCall : public Message { 145 public: 146 // Creates a method call message for the specified interface name and 147 // the method name. 148 // 149 // For instance, to call "Get" method of DBUS_INTERFACE_INTROSPECTABLE 150 // interface ("org.freedesktop.DBus.Introspectable"), create a method 151 // call like this: 152 // 153 // MethodCall method_call(DBUS_INTERFACE_INTROSPECTABLE, "Get"); 154 // 155 // The constructor creates the internal raw message. 156 MethodCall(const std::string& interface_name, const std::string& method_name); 157 158 // Returns a newly created MethodCall from the given raw message of the 159 // type DBUS_MESSAGE_TYPE_METHOD_CALL. Takes the ownership of |raw_message|. 160 static std::unique_ptr<MethodCall> FromRawMessage(DBusMessage* raw_message); 161 162 private: 163 // Creates a method call message. The internal raw message is NULL. 164 // Only used internally. 165 MethodCall(); 166 167 DISALLOW_COPY_AND_ASSIGN(MethodCall); 168 }; 169 170 // Signal is a type of message used to send a signal. 171 class CHROME_DBUS_EXPORT Signal : public Message { 172 public: 173 // Creates a signal message for the specified interface name and the 174 // method name. 175 // 176 // For instance, to send "PropertiesChanged" signal of 177 // DBUS_INTERFACE_INTROSPECTABLE interface 178 // ("org.freedesktop.DBus.Introspectable"), create a signal like this: 179 // 180 // Signal signal(DBUS_INTERFACE_INTROSPECTABLE, "PropertiesChanged"); 181 // 182 // The constructor creates the internal raw_message_. 183 Signal(const std::string& interface_name, const std::string& method_name); 184 185 // Returns a newly created SIGNAL from the given raw message of the type 186 // DBUS_MESSAGE_TYPE_SIGNAL. Takes the ownership of |raw_message|. 187 static std::unique_ptr<Signal> FromRawMessage(DBusMessage* raw_message); 188 189 private: 190 // Creates a signal message. The internal raw message is NULL. 191 // Only used internally. 192 Signal(); 193 194 DISALLOW_COPY_AND_ASSIGN(Signal); 195 }; 196 197 // Response is a type of message used for receiving a response from a 198 // method via D-Bus. 199 class CHROME_DBUS_EXPORT Response : public Message { 200 public: 201 // Returns a newly created Response from the given raw message of the 202 // type DBUS_MESSAGE_TYPE_METHOD_RETURN. Takes the ownership of |raw_message|. 203 static std::unique_ptr<Response> FromRawMessage(DBusMessage* raw_message); 204 205 // Returns a newly created Response from the given method call. 206 // Used for implementing exported methods. Does NOT take the ownership of 207 // |method_call|. 208 static std::unique_ptr<Response> FromMethodCall(MethodCall* method_call); 209 210 // Returns a newly created Response with an empty payload. 211 // Useful for testing. 212 static std::unique_ptr<Response> CreateEmpty(); 213 214 protected: 215 // Creates a Response message. The internal raw message is NULL. 216 Response(); 217 218 private: 219 DISALLOW_COPY_AND_ASSIGN(Response); 220 }; 221 222 // ErrorResponse is a type of message used to return an error to the 223 // caller of a method. 224 class CHROME_DBUS_EXPORT ErrorResponse : public Response { 225 public: 226 // Returns a newly created Response from the given raw message of the 227 // type DBUS_MESSAGE_TYPE_METHOD_RETURN. Takes the ownership of |raw_message|. 228 static std::unique_ptr<ErrorResponse> FromRawMessage( 229 DBusMessage* raw_message); 230 231 // Returns a newly created ErrorResponse from the given method call, the 232 // error name, and the error message. The error name looks like 233 // "org.freedesktop.DBus.Error.Failed". Used for returning an error to a 234 // failed method call. Does NOT take the ownership of |method_call|. 235 static std::unique_ptr<ErrorResponse> FromMethodCall( 236 MethodCall* method_call, 237 const std::string& error_name, 238 const std::string& error_message); 239 240 private: 241 // Creates an ErrorResponse message. The internal raw message is NULL. 242 ErrorResponse(); 243 244 DISALLOW_COPY_AND_ASSIGN(ErrorResponse); 245 }; 246 247 // MessageWriter is used to write outgoing messages for calling methods 248 // and sending signals. 249 // 250 // The main design goal of MessageReader and MessageWriter classes is to 251 // provide a type safe API. In the past, there was a Chrome OS blocker 252 // bug, that took days to fix, that would have been prevented if the API 253 // was type-safe. 254 // 255 // For instance, instead of doing something like: 256 // 257 // // We shouldn't add '&' to str here, but it compiles with '&' added. 258 // dbus_g_proxy_call(..., G_TYPE_STRING, str, G_TYPE_INVALID, ...) 259 // 260 // We want to do something like: 261 // 262 // writer.AppendString(str); 263 // 264 class CHROME_DBUS_EXPORT MessageWriter { 265 public: 266 // Data added with Append* will be written to |message|, which may be NULL 267 // to create a sub-writer for passing to OpenArray, etc. 268 explicit MessageWriter(Message* message); 269 ~MessageWriter(); 270 271 // Appends a byte to the message. 272 void AppendByte(uint8_t value); 273 void AppendBool(bool value); 274 void AppendInt16(int16_t value); 275 void AppendUint16(uint16_t value); 276 void AppendInt32(int32_t value); 277 void AppendUint32(uint32_t value); 278 void AppendInt64(int64_t value); 279 void AppendUint64(uint64_t value); 280 void AppendDouble(double value); 281 void AppendString(const std::string& value); 282 void AppendObjectPath(const ObjectPath& value); 283 284 // Appends a file descriptor to the message. 285 // The FD will be duplicated so you still have to close the original FD. 286 void AppendFileDescriptor(int value); 287 288 // Opens an array. The array contents can be added to the array with 289 // |sub_writer|. The client code must close the array with 290 // CloseContainer(), once all contents are added. 291 // 292 // |signature| parameter is used to supply the D-Bus type signature of 293 // the array contents. For instance, if you want an array of strings, 294 // then you pass "s" as the signature. 295 // 296 // See the spec for details about the type signatures. 297 // http://dbus.freedesktop.org/doc/dbus-specification.html 298 // #message-protocol-signatures 299 // 300 void OpenArray(const std::string& signature, MessageWriter* sub_writer); 301 // Do the same for a variant. 302 void OpenVariant(const std::string& signature, MessageWriter* sub_writer); 303 // Do the same for Struct and dict entry. They don't need the signature. 304 void OpenStruct(MessageWriter* sub_writer); 305 void OpenDictEntry(MessageWriter* sub_writer); 306 307 // Close the container for a array/variant/struct/dict entry. 308 void CloseContainer(MessageWriter* sub_writer); 309 310 // Appends the array of bytes. Arrays of bytes are often used for 311 // exchanging binary blobs hence it's worth having a specialized 312 // function. 313 void AppendArrayOfBytes(const uint8_t* values, size_t length); 314 315 // Appends array of int32_ts. 316 void AppendArrayOfInt32s(const int32_t* values, size_t length); 317 318 // Appends array of uint32_ts. 319 void AppendArrayOfUint32s(const uint32_t* values, size_t length); 320 321 // Appends the array of doubles. Used for audio mixer matrix doubles. 322 void AppendArrayOfDoubles(const double* values, size_t length); 323 324 // Appends the array of strings. Arrays of strings are often used for 325 // exchanging lists of names hence it's worth having a specialized 326 // function. 327 void AppendArrayOfStrings(const std::vector<std::string>& strings); 328 329 // Appends the array of object paths. Arrays of object paths are often 330 // used when exchanging object paths, hence it's worth having a 331 // specialized function. 332 void AppendArrayOfObjectPaths(const std::vector<ObjectPath>& object_paths); 333 334 // Appends the protocol buffer as an array of bytes. The buffer is serialized 335 // into an array of bytes before communication, since protocol buffers are not 336 // a native dbus type. On the receiving size the array of bytes needs to be 337 // read and deserialized into a protocol buffer of the correct type. There are 338 // methods in MessageReader to assist in this. Return true on success and 339 // false when serialization fails. 340 bool AppendProtoAsArrayOfBytes(const google::protobuf::MessageLite& protobuf); 341 342 // Appends the byte wrapped in a variant data container. Variants are 343 // widely used in D-Bus services so it's worth having a specialized 344 // function. For instance, The third parameter of 345 // "org.freedesktop.DBus.Properties.Set" is a variant. 346 void AppendVariantOfByte(uint8_t value); 347 void AppendVariantOfBool(bool value); 348 void AppendVariantOfInt16(int16_t value); 349 void AppendVariantOfUint16(uint16_t value); 350 void AppendVariantOfInt32(int32_t value); 351 void AppendVariantOfUint32(uint32_t value); 352 void AppendVariantOfInt64(int64_t value); 353 void AppendVariantOfUint64(uint64_t value); 354 void AppendVariantOfDouble(double value); 355 void AppendVariantOfString(const std::string& value); 356 void AppendVariantOfObjectPath(const ObjectPath& value); 357 358 private: 359 // Helper function used to implement AppendByte etc. 360 void AppendBasic(int dbus_type, const void* value); 361 362 // Helper function used to implement AppendVariantOfByte() etc. 363 void AppendVariantOfBasic(int dbus_type, const void* value); 364 365 Message* message_; 366 DBusMessageIter raw_message_iter_; 367 bool container_is_open_; 368 369 DISALLOW_COPY_AND_ASSIGN(MessageWriter); 370 }; 371 372 // MessageReader is used to read incoming messages such as responses for 373 // method calls. 374 // 375 // MessageReader manages an internal iterator to read data. All functions 376 // starting with Pop advance the iterator on success. 377 class CHROME_DBUS_EXPORT MessageReader { 378 public: 379 // The data will be read from the given |message|, which may be NULL to 380 // create a sub-reader for passing to PopArray, etc. 381 explicit MessageReader(Message* message); 382 ~MessageReader(); 383 384 // Returns true if the reader has more data to read. The function is 385 // used to iterate contents in a container like: 386 // 387 // while (reader.HasMoreData()) 388 // reader.PopString(&value); 389 bool HasMoreData(); 390 391 // Gets the byte at the current iterator position. 392 // Returns true and advances the iterator on success. 393 // Returns false if the data type is not a byte. 394 bool PopByte(uint8_t* value); 395 bool PopBool(bool* value); 396 bool PopInt16(int16_t* value); 397 bool PopUint16(uint16_t* value); 398 bool PopInt32(int32_t* value); 399 bool PopUint32(uint32_t* value); 400 bool PopInt64(int64_t* value); 401 bool PopUint64(uint64_t* value); 402 bool PopDouble(double* value); 403 bool PopString(std::string* value); 404 bool PopObjectPath(ObjectPath* value); 405 bool PopFileDescriptor(base::ScopedFD* value); 406 407 // Sets up the given message reader to read an array at the current 408 // iterator position. 409 // Returns true and advances the iterator on success. 410 // Returns false if the data type is not an array 411 bool PopArray(MessageReader* sub_reader); 412 bool PopStruct(MessageReader* sub_reader); 413 bool PopDictEntry(MessageReader* sub_reader); 414 bool PopVariant(MessageReader* sub_reader); 415 416 // Gets the array of bytes at the current iterator position. 417 // Returns true and advances the iterator on success. 418 // 419 // Arrays of bytes are often used for exchanging binary blobs hence it's 420 // worth having a specialized function. 421 // 422 // Ownership of the memory pointed to by |bytes| remains with the 423 // MessageReader; |bytes| must be copied if the contents will be referenced 424 // after the MessageReader is destroyed. 425 bool PopArrayOfBytes(const uint8_t** bytes, size_t* length); 426 427 // Gets the array of int32_ts at the current iterator position. 428 bool PopArrayOfInt32s(const int32_t** signed_ints, size_t* length); 429 430 // Gets the array of uint32_ts at the current iterator position. 431 bool PopArrayOfUint32s(const uint32_t** unsigned_ints, size_t* length); 432 433 // Gets the array of doubles at the current iterator position. 434 bool PopArrayOfDoubles(const double** doubles, size_t* length); 435 436 // Gets the array of strings at the current iterator position. |strings| is 437 // cleared before being modified. Returns true and advances the iterator on 438 // success. 439 // 440 // Arrays of strings are often used to communicate with D-Bus 441 // services like KWallet, hence it's worth having a specialized 442 // function. 443 bool PopArrayOfStrings(std::vector<std::string>* strings); 444 445 // Gets the array of object paths at the current iterator position. 446 // |object_paths| is cleared before being modified. Returns true and advances 447 // the iterator on success. 448 // 449 // Arrays of object paths are often used to communicate with D-Bus 450 // services like NetworkManager, hence it's worth having a specialized 451 // function. 452 bool PopArrayOfObjectPaths(std::vector<ObjectPath>* object_paths); 453 454 // Gets the array of bytes at the current iterator position. It then parses 455 // this binary blob into the protocol buffer supplied. 456 // Returns true and advances the iterator on success. On failure returns false 457 // and emits an error message on the source of the failure. The two most 458 // common errors come from the iterator not currently being at a byte array or 459 // the wrong type of protocol buffer is passed in and the parse fails. 460 bool PopArrayOfBytesAsProto(google::protobuf::MessageLite* protobuf); 461 462 // Gets the byte from the variant data container at the current iterator 463 // position. 464 // Returns true and advances the iterator on success. 465 // 466 // Variants are widely used in D-Bus services so it's worth having a 467 // specialized function. For instance, The return value type of 468 // "org.freedesktop.DBus.Properties.Get" is a variant. 469 bool PopVariantOfByte(uint8_t* value); 470 bool PopVariantOfBool(bool* value); 471 bool PopVariantOfInt16(int16_t* value); 472 bool PopVariantOfUint16(uint16_t* value); 473 bool PopVariantOfInt32(int32_t* value); 474 bool PopVariantOfUint32(uint32_t* value); 475 bool PopVariantOfInt64(int64_t* value); 476 bool PopVariantOfUint64(uint64_t* value); 477 bool PopVariantOfDouble(double* value); 478 bool PopVariantOfString(std::string* value); 479 bool PopVariantOfObjectPath(ObjectPath* value); 480 481 // Get the data type of the value at the current iterator 482 // position. INVALID_DATA will be returned if the iterator points to the 483 // end of the message. 484 Message::DataType GetDataType(); 485 486 // Get the DBus signature of the value at the current iterator position. 487 // An empty string will be returned if the iterator points to the end of 488 // the message. 489 std::string GetDataSignature(); 490 491 private: 492 // Returns true if the data type at the current iterator position 493 // matches the given D-Bus type, such as DBUS_TYPE_BYTE. 494 bool CheckDataType(int dbus_type); 495 496 // Helper function used to implement PopByte() etc. 497 bool PopBasic(int dbus_type, void* value); 498 499 // Helper function used to implement PopArray() etc. 500 bool PopContainer(int dbus_type, MessageReader* sub_reader); 501 502 // Helper function used to implement PopVariantOfByte() etc. 503 bool PopVariantOfBasic(int dbus_type, void* value); 504 505 Message* message_; 506 DBusMessageIter raw_message_iter_; 507 508 DISALLOW_COPY_AND_ASSIGN(MessageReader); 509 }; 510 511 } // namespace dbus 512 513 #endif // DBUS_MESSAGE_H_ 514