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 #include <string> 12 #include <vector> 13 14 #include "base/macros.h" 15 #include "base/memory/scoped_ptr.h" 16 #include "dbus/dbus_export.h" 17 #include "dbus/file_descriptor.h" 18 #include "dbus/object_path.h" 19 20 namespace google { 21 namespace protobuf { 22 23 class MessageLite; 24 25 } // namespace protobuf 26 } // namespace google 27 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, 157 const std::string& method_name); 158 159 // Returns a newly created MethodCall from the given raw message of the 160 // type DBUS_MESSAGE_TYPE_METHOD_CALL. The caller must delete the 161 // returned object. Takes the ownership of |raw_message|. 162 static MethodCall* FromRawMessage(DBusMessage* raw_message); 163 164 private: 165 // Creates a method call message. The internal raw message is NULL. 166 // Only used internally. 167 MethodCall(); 168 169 DISALLOW_COPY_AND_ASSIGN(MethodCall); 170 }; 171 172 // Signal is a type of message used to send a signal. 173 class CHROME_DBUS_EXPORT Signal : public Message { 174 public: 175 // Creates a signal message for the specified interface name and the 176 // method name. 177 // 178 // For instance, to send "PropertiesChanged" signal of 179 // DBUS_INTERFACE_INTROSPECTABLE interface 180 // ("org.freedesktop.DBus.Introspectable"), create a signal like this: 181 // 182 // Signal signal(DBUS_INTERFACE_INTROSPECTABLE, "PropertiesChanged"); 183 // 184 // The constructor creates the internal raw_message_. 185 Signal(const std::string& interface_name, 186 const std::string& method_name); 187 188 // Returns a newly created SIGNAL from the given raw message of the type 189 // DBUS_MESSAGE_TYPE_SIGNAL. The caller must delete the returned 190 // object. Takes the ownership of |raw_message|. 191 static Signal* FromRawMessage(DBusMessage* raw_message); 192 193 private: 194 // Creates a signal message. The internal raw message is NULL. 195 // Only used internally. 196 Signal(); 197 198 DISALLOW_COPY_AND_ASSIGN(Signal); 199 }; 200 201 // Response is a type of message used for receiving a response from a 202 // method via D-Bus. 203 class CHROME_DBUS_EXPORT Response : public Message { 204 public: 205 // Returns a newly created Response from the given raw message of the 206 // type DBUS_MESSAGE_TYPE_METHOD_RETURN. Takes the ownership of |raw_message|. 207 static scoped_ptr<Response> FromRawMessage(DBusMessage* raw_message); 208 209 // Returns a newly created Response from the given method call. 210 // Used for implementing exported methods. Does NOT take the ownership of 211 // |method_call|. 212 static scoped_ptr<Response> FromMethodCall(MethodCall* method_call); 213 214 // Returns a newly created Response with an empty payload. 215 // Useful for testing. 216 static scoped_ptr<Response> CreateEmpty(); 217 218 protected: 219 // Creates a Response message. The internal raw message is NULL. 220 Response(); 221 222 private: 223 DISALLOW_COPY_AND_ASSIGN(Response); 224 }; 225 226 // ErrorResponse is a type of message used to return an error to the 227 // caller of a method. 228 class CHROME_DBUS_EXPORT ErrorResponse: public Response { 229 public: 230 // Returns a newly created Response from the given raw message of the 231 // type DBUS_MESSAGE_TYPE_METHOD_RETURN. Takes the ownership of |raw_message|. 232 static scoped_ptr<ErrorResponse> FromRawMessage(DBusMessage* raw_message); 233 234 // Returns a newly created ErrorResponse from the given method call, the 235 // error name, and the error message. The error name looks like 236 // "org.freedesktop.DBus.Error.Failed". Used for returning an error to a 237 // failed method call. Does NOT take the ownership of |method_call|. 238 static scoped_ptr<ErrorResponse> FromMethodCall( 239 MethodCall* method_call, 240 const std::string& error_name, 241 const std::string& error_message); 242 243 private: 244 // Creates an ErrorResponse message. The internal raw message is NULL. 245 ErrorResponse(); 246 247 DISALLOW_COPY_AND_ASSIGN(ErrorResponse); 248 }; 249 250 // MessageWriter is used to write outgoing messages for calling methods 251 // and sending signals. 252 // 253 // The main design goal of MessageReader and MessageWriter classes is to 254 // provide a type safe API. In the past, there was a Chrome OS blocker 255 // bug, that took days to fix, that would have been prevented if the API 256 // was type-safe. 257 // 258 // For instance, instead of doing something like: 259 // 260 // // We shouldn't add '&' to str here, but it compiles with '&' added. 261 // dbus_g_proxy_call(..., G_TYPE_STRING, str, G_TYPE_INVALID, ...) 262 // 263 // We want to do something like: 264 // 265 // writer.AppendString(str); 266 // 267 class CHROME_DBUS_EXPORT MessageWriter { 268 public: 269 // Data added with Append* will be written to |message|, which may be NULL 270 // to create a sub-writer for passing to OpenArray, etc. 271 explicit MessageWriter(Message* message); 272 ~MessageWriter(); 273 274 // Appends a byte to the message. 275 void AppendByte(uint8_t value); 276 void AppendBool(bool value); 277 void AppendInt16(int16_t value); 278 void AppendUint16(uint16_t value); 279 void AppendInt32(int32_t value); 280 void AppendUint32(uint32_t value); 281 void AppendInt64(int64_t value); 282 void AppendUint64(uint64_t value); 283 void AppendDouble(double value); 284 void AppendString(const std::string& value); 285 void AppendObjectPath(const ObjectPath& value); 286 void AppendFileDescriptor(const FileDescriptor& 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 the array of strings. Arrays of strings are often used for 316 // exchanging lists of names hence it's worth having a specialized 317 // function. 318 void AppendArrayOfStrings(const std::vector<std::string>& strings); 319 320 // Appends the array of object paths. Arrays of object paths are often 321 // used when exchanging object paths, hence it's worth having a 322 // specialized function. 323 void AppendArrayOfObjectPaths(const std::vector<ObjectPath>& object_paths); 324 325 // Appends the protocol buffer as an array of bytes. The buffer is serialized 326 // into an array of bytes before communication, since protocol buffers are not 327 // a native dbus type. On the receiving size the array of bytes needs to be 328 // read and deserialized into a protocol buffer of the correct type. There are 329 // methods in MessageReader to assist in this. Return true on succes and fail 330 // when serialization is not successful. 331 bool AppendProtoAsArrayOfBytes(const google::protobuf::MessageLite& protobuf); 332 333 // Appends the byte wrapped in a variant data container. Variants are 334 // widely used in D-Bus services so it's worth having a specialized 335 // function. For instance, The third parameter of 336 // "org.freedesktop.DBus.Properties.Set" is a variant. 337 void AppendVariantOfByte(uint8_t value); 338 void AppendVariantOfBool(bool value); 339 void AppendVariantOfInt16(int16_t value); 340 void AppendVariantOfUint16(uint16_t value); 341 void AppendVariantOfInt32(int32_t value); 342 void AppendVariantOfUint32(uint32_t value); 343 void AppendVariantOfInt64(int64_t value); 344 void AppendVariantOfUint64(uint64_t value); 345 void AppendVariantOfDouble(double value); 346 void AppendVariantOfString(const std::string& value); 347 void AppendVariantOfObjectPath(const ObjectPath& value); 348 349 private: 350 // Helper function used to implement AppendByte etc. 351 void AppendBasic(int dbus_type, const void* value); 352 353 // Helper function used to implement AppendVariantOfByte() etc. 354 void AppendVariantOfBasic(int dbus_type, const void* value); 355 356 Message* message_; 357 DBusMessageIter raw_message_iter_; 358 bool container_is_open_; 359 360 DISALLOW_COPY_AND_ASSIGN(MessageWriter); 361 }; 362 363 // MessageReader is used to read incoming messages such as responses for 364 // method calls. 365 // 366 // MessageReader manages an internal iterator to read data. All functions 367 // starting with Pop advance the iterator on success. 368 class CHROME_DBUS_EXPORT MessageReader { 369 public: 370 // The data will be read from the given |message|, which may be NULL to 371 // create a sub-reader for passing to PopArray, etc. 372 explicit MessageReader(Message* message); 373 ~MessageReader(); 374 375 // Returns true if the reader has more data to read. The function is 376 // used to iterate contents in a container like: 377 // 378 // while (reader.HasMoreData()) 379 // reader.PopString(&value); 380 bool HasMoreData(); 381 382 // Gets the byte at the current iterator position. 383 // Returns true and advances the iterator on success. 384 // Returns false if the data type is not a byte. 385 bool PopByte(uint8_t* value); 386 bool PopBool(bool* value); 387 bool PopInt16(int16_t* value); 388 bool PopUint16(uint16_t* value); 389 bool PopInt32(int32_t* value); 390 bool PopUint32(uint32_t* value); 391 bool PopInt64(int64_t* value); 392 bool PopUint64(uint64_t* value); 393 bool PopDouble(double* value); 394 bool PopString(std::string* value); 395 bool PopObjectPath(ObjectPath* value); 396 bool PopFileDescriptor(FileDescriptor* value); 397 398 // Sets up the given message reader to read an array at the current 399 // iterator position. 400 // Returns true and advances the iterator on success. 401 // Returns false if the data type is not an array 402 bool PopArray(MessageReader* sub_reader); 403 bool PopStruct(MessageReader* sub_reader); 404 bool PopDictEntry(MessageReader* sub_reader); 405 bool PopVariant(MessageReader* sub_reader); 406 407 // Gets the array of bytes at the current iterator position. 408 // Returns true and advances the iterator on success. 409 // 410 // Arrays of bytes are often used for exchanging binary blobs hence it's 411 // worth having a specialized function. 412 // 413 // Ownership of the memory pointed to by |bytes| remains with the 414 // MessageReader; |bytes| must be copied if the contents will be referenced 415 // after the MessageReader is destroyed. 416 bool PopArrayOfBytes(const uint8_t** bytes, size_t* length); 417 418 // Gets the array of strings at the current iterator position. |strings| is 419 // cleared before being modified. Returns true and advances the iterator on 420 // success. 421 // 422 // Arrays of strings are often used to communicate with D-Bus 423 // services like KWallet, hence it's worth having a specialized 424 // function. 425 bool PopArrayOfStrings(std::vector<std::string>* strings); 426 427 // Gets the array of object paths at the current iterator position. 428 // |object_paths| is cleared before being modified. Returns true and advances 429 // the iterator on success. 430 // 431 // Arrays of object paths are often used to communicate with D-Bus 432 // services like NetworkManager, hence it's worth having a specialized 433 // function. 434 bool PopArrayOfObjectPaths(std::vector<ObjectPath>* object_paths); 435 436 // Gets the array of bytes at the current iterator position. It then parses 437 // this binary blob into the protocol buffer supplied. 438 // Returns true and advances the iterator on success. On failure returns false 439 // and emits an error message on the source of the failure. The two most 440 // common errors come from the iterator not currently being at a byte array or 441 // the wrong type of protocol buffer is passed in and the parse fails. 442 bool PopArrayOfBytesAsProto(google::protobuf::MessageLite* protobuf); 443 444 // Gets the byte from the variant data container at the current iterator 445 // position. 446 // Returns true and advances the iterator on success. 447 // 448 // Variants are widely used in D-Bus services so it's worth having a 449 // specialized function. For instance, The return value type of 450 // "org.freedesktop.DBus.Properties.Get" is a variant. 451 bool PopVariantOfByte(uint8_t* value); 452 bool PopVariantOfBool(bool* value); 453 bool PopVariantOfInt16(int16_t* value); 454 bool PopVariantOfUint16(uint16_t* value); 455 bool PopVariantOfInt32(int32_t* value); 456 bool PopVariantOfUint32(uint32_t* value); 457 bool PopVariantOfInt64(int64_t* value); 458 bool PopVariantOfUint64(uint64_t* value); 459 bool PopVariantOfDouble(double* value); 460 bool PopVariantOfString(std::string* value); 461 bool PopVariantOfObjectPath(ObjectPath* value); 462 463 // Get the data type of the value at the current iterator 464 // position. INVALID_DATA will be returned if the iterator points to the 465 // end of the message. 466 Message::DataType GetDataType(); 467 468 // Get the DBus signature of the value at the current iterator position. 469 // An empty string will be returned if the iterator points to the end of 470 // the message. 471 std::string GetDataSignature(); 472 473 private: 474 // Returns true if the data type at the current iterator position 475 // matches the given D-Bus type, such as DBUS_TYPE_BYTE. 476 bool CheckDataType(int dbus_type); 477 478 // Helper function used to implement PopByte() etc. 479 bool PopBasic(int dbus_type, void *value); 480 481 // Helper function used to implement PopArray() etc. 482 bool PopContainer(int dbus_type, MessageReader* sub_reader); 483 484 // Helper function used to implement PopVariantOfByte() etc. 485 bool PopVariantOfBasic(int dbus_type, void* value); 486 487 Message* message_; 488 DBusMessageIter raw_message_iter_; 489 490 DISALLOW_COPY_AND_ASSIGN(MessageReader); 491 }; 492 493 } // namespace dbus 494 495 #endif // DBUS_MESSAGE_H_ 496