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