OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2011 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 #pragma once |
| 8 |
| 9 #include <string> |
| 10 #include <vector> |
| 11 #include <dbus/dbus.h> |
| 12 |
| 13 #include "base/basictypes.h" |
| 14 |
| 15 namespace dbus { |
| 16 |
| 17 class MessageWriter; |
| 18 class MessageReader; |
| 19 |
| 20 // Message is the base class of D-Bus message types. Client code should |
| 21 // usually use sub classes such as MethodCall and Response instead. |
| 22 // |
| 23 // The class name Message is very generic, but there should be no problem |
| 24 // as the class is inside 'dbus' namespace. We chose to name this way, as |
| 25 // libdbus defines lots of types starting with DBus, such as |
| 26 // DBusMessage. We should avoid confusion and conflict with these types. |
| 27 class Message { |
| 28 public: |
| 29 // The message type used in D-Bus. Redefined here so client code |
| 30 // doesn't need to use raw D-Bus macros. DBUS_MESSAGE_TYPE_INVALID |
| 31 // etc. are #define macros. Having an enum type here makes code a bit |
| 32 // more type-safe. |
| 33 enum MessageType { |
| 34 MESSAGE_INVALID = DBUS_MESSAGE_TYPE_INVALID, |
| 35 MESSAGE_METHOD_CALL = DBUS_MESSAGE_TYPE_METHOD_CALL, |
| 36 MESSAGE_METHOD_RETURN = DBUS_MESSAGE_TYPE_METHOD_RETURN, |
| 37 MESSAGE_SIGNAL = DBUS_MESSAGE_TYPE_SIGNAL, |
| 38 MESSAGE_ERROR = DBUS_MESSAGE_TYPE_ERROR, |
| 39 }; |
| 40 |
| 41 // The data type used in the D-Bus type system. See the comment at |
| 42 // MessageType for why we are redefining data types here. |
| 43 enum DataType { |
| 44 INVALID_DATA = DBUS_TYPE_INVALID, |
| 45 BYTE = DBUS_TYPE_BYTE, |
| 46 BOOL = DBUS_TYPE_BOOLEAN, |
| 47 INT16 = DBUS_TYPE_INT16, |
| 48 UINT16 = DBUS_TYPE_UINT16, |
| 49 INT32 = DBUS_TYPE_INT32, |
| 50 UINT32 = DBUS_TYPE_UINT32, |
| 51 INT64 = DBUS_TYPE_INT64, |
| 52 UINT64 = DBUS_TYPE_UINT64, |
| 53 DOUBLE = DBUS_TYPE_DOUBLE, |
| 54 STRING = DBUS_TYPE_STRING, |
| 55 OBJECT_PATH = DBUS_TYPE_OBJECT_PATH, |
| 56 ARRAY = DBUS_TYPE_ARRAY, |
| 57 STRUCT = DBUS_TYPE_STRUCT, |
| 58 DICT_ENTRY = DBUS_TYPE_DICT_ENTRY, |
| 59 VARIANT = DBUS_TYPE_VARIANT, |
| 60 }; |
| 61 |
| 62 // Creates a Message. The internal raw message is NULL until it's set |
| 63 // from outside by reset_raw_message(). |
| 64 Message(); |
| 65 virtual ~Message(); |
| 66 |
| 67 // Returns the type of the message. Returns MESSAGE_INVALID if |
| 68 // raw_message_ is NULL. |
| 69 MessageType GetMessageType(); |
| 70 |
| 71 DBusMessage* raw_message() { return raw_message_; } |
| 72 |
| 73 // Resets raw_message_ with the given raw message. Takes the ownership |
| 74 // of raw_message. raw_message_ will be unref'ed in the destructor. |
| 75 void reset_raw_message(DBusMessage* raw_message); |
| 76 |
| 77 // Returns the string representation of this message. Useful for |
| 78 // debugging. |
| 79 std::string ToString(); |
| 80 |
| 81 private: |
| 82 // Helper function used in ToString(). |
| 83 std::string ToStringInternal(const std::string& indent, |
| 84 MessageReader* reader); |
| 85 |
| 86 DBusMessage* raw_message_; |
| 87 DISALLOW_COPY_AND_ASSIGN(Message); |
| 88 }; |
| 89 |
| 90 // MessageCall is a type of message used for calling a method via D-Bus. |
| 91 class MethodCall : public Message { |
| 92 public: |
| 93 // Creates a method call message for the specified interface name and |
| 94 // the method name. |
| 95 // |
| 96 // For instance, to call "Get" method of DBUS_INTERFACE_INTROSPECTABLE |
| 97 // interface ("org.freedesktop.DBus.Introspectable"), create a method |
| 98 // call like this: |
| 99 // |
| 100 // MethodCall method_call(DBUS_INTERFACE_INTROSPECTABLE, "Get"); |
| 101 // |
| 102 // The constructor creates the internal raw_message_, so the client |
| 103 // doesn't need to set this with reset_raw_message(). |
| 104 MethodCall(const std::string& interface_name, |
| 105 const std::string& method_name); |
| 106 |
| 107 const std::string& interface_name() { return interface_name_; } |
| 108 const std::string& method_name() { return method_name_; } |
| 109 |
| 110 // Sets the service name. This will be handled by the object proxy. |
| 111 void SetServiceName(const std::string& service_name); |
| 112 // Sets the object path. This will be handled by the object proxy. |
| 113 void SetObjectPath(const std::string& object_path); |
| 114 |
| 115 std::string interface_name_; |
| 116 std::string method_name_; |
| 117 |
| 118 DISALLOW_COPY_AND_ASSIGN(MethodCall); |
| 119 }; |
| 120 |
| 121 // Response is a type of message used for receiving a response from a |
| 122 // method via D-Bus. |
| 123 class Response : public Message { |
| 124 public: |
| 125 // Creates a Response message. The internal raw message is NULL. |
| 126 // Classes that implment method calls need to set the raw message once a |
| 127 // response is received from the server. See object_proxy.h. |
| 128 Response(); |
| 129 |
| 130 private: |
| 131 DISALLOW_COPY_AND_ASSIGN(Response); |
| 132 }; |
| 133 |
| 134 // MessageWriter is used to write outgoing messages for calling methods |
| 135 // and sending signals. |
| 136 // |
| 137 // The main design goal of MessageReader and MessageWriter classes is to |
| 138 // provide a type safe API. In the past, there was a Chrome OS blocker |
| 139 // bug, that took days to fix, that would have been prevented if the API |
| 140 // was type-safe. |
| 141 // |
| 142 // For instance, instead of doing something like: |
| 143 // |
| 144 // // We shouldn't add '&' to str here, but it compiles with '&' added. |
| 145 // dbus_g_proxy_call(..., G_TYPE_STRING, str, G_TYPE_INVALID, ...) |
| 146 // |
| 147 // We want to do something like: |
| 148 // |
| 149 // writer.AppendString(str); |
| 150 // |
| 151 class MessageWriter { |
| 152 public: |
| 153 // Data added with Append* will be written to |message|. |
| 154 MessageWriter(Message* message); |
| 155 ~MessageWriter(); |
| 156 |
| 157 // Appends a byte to the message. |
| 158 void AppendByte(uint8 value); |
| 159 void AppendBool(bool value); |
| 160 void AppendInt16(int16 value); |
| 161 void AppendUint16(uint16 value); |
| 162 void AppendInt32(int32 value); |
| 163 void AppendUint32(uint32 value); |
| 164 void AppendInt64(int64 value); |
| 165 void AppendUint64(uint64 value); |
| 166 void AppendDouble(double value); |
| 167 void AppendString(const std::string& value); |
| 168 void AppendObjectPath(const std::string& value); |
| 169 |
| 170 // Opens an array. The array contents can be added to the array with |
| 171 // |sub_writer|. The client code must close the array with |
| 172 // CloseContainer(), once all contents are added. |
| 173 // |
| 174 // |signature| parameter is used to supply the D-Bus type signature of |
| 175 // the array contents. For instance, if you want an array of strings, |
| 176 // then you pass "s" as the signature. |
| 177 // |
| 178 // See the spec for details about the type signatures. |
| 179 // http://dbus.freedesktop.org/doc/dbus-specification.html |
| 180 // #message-protocol-signatures |
| 181 // |
| 182 void OpenArray(const std::string& signature, MessageWriter* sub_writer); |
| 183 // Do the same for a variant. |
| 184 void OpenVariant(const std::string& signature, MessageWriter* sub_writer); |
| 185 // Do the same for Struct and dict entry. They don't need the signature. |
| 186 void OpenStruct(MessageWriter* sub_writer); |
| 187 void OpenDictEntry(MessageWriter* sub_writer); |
| 188 |
| 189 // Close the container for a array/variant/struct/dict entry. |
| 190 void CloseContainer(MessageWriter* sub_writer); |
| 191 |
| 192 // Appends the array of bytes. Arrays of bytes are often used for |
| 193 // exchanging binary blobs hence it's worth having a specialized |
| 194 // function. |
| 195 void AppendArrayOfBytes(const uint8* values, size_t length); |
| 196 |
| 197 // Appends the byte wrapped in a variant data container. Variants are |
| 198 // widely used in D-Bus services so it's worth having a specialized |
| 199 // function. For instance, The third parameter of |
| 200 // "org.freedesktop.DBus.Properties.Set" is a variant. |
| 201 void AppendVariantOfByte(uint8 value); |
| 202 void AppendVariantOfBool(bool value); |
| 203 void AppendVariantOfInt16(int16 value); |
| 204 void AppendVariantOfUint16(uint16 value); |
| 205 void AppendVariantOfInt32(int32 value); |
| 206 void AppendVariantOfUint32(uint32 value); |
| 207 void AppendVariantOfInt64(int64 value); |
| 208 void AppendVariantOfUint64(uint64 value); |
| 209 void AppendVariantOfDouble(double value); |
| 210 void AppendVariantOfString(const std::string& value); |
| 211 void AppendVariantOfObjectPath(const std::string& value); |
| 212 |
| 213 private: |
| 214 // Helper function used to implement AppendByte etc. |
| 215 void AppendBasic(int dbus_type, const void* value); |
| 216 |
| 217 // Helper function used to implement AppendVariantOfByte() etc. |
| 218 void AppendVariantOfBasic(int dbus_type, const void* value); |
| 219 |
| 220 Message* message_; |
| 221 DBusMessageIter raw_message_iter_; |
| 222 bool container_is_open_; |
| 223 |
| 224 DISALLOW_COPY_AND_ASSIGN(MessageWriter); |
| 225 }; |
| 226 |
| 227 // MessageReader is used to read incoming messages such as responses for |
| 228 // method calls. |
| 229 // |
| 230 // MessageReader manages an internal iterator to read data. All functions |
| 231 // starting with Pop advance the iterator on success. |
| 232 class MessageReader { |
| 233 public: |
| 234 // The data will be read from the given message. |
| 235 MessageReader(Message* message); |
| 236 ~MessageReader(); |
| 237 |
| 238 // Returns true if the reader has more data to read. The function is |
| 239 // used to iterate contents in a container like: |
| 240 // |
| 241 // while (reader.HasMoreData()) |
| 242 // reader.PopString(&value); |
| 243 bool HasMoreData(); |
| 244 |
| 245 // Gets the byte at the current iterator position. |
| 246 // Returns true and advances the iterator on success. |
| 247 // Returns false if the data type is not a byte. |
| 248 bool PopByte(uint8* value); |
| 249 bool PopBool(bool* value); |
| 250 bool PopInt16(int16* value); |
| 251 bool PopUint16(uint16* value); |
| 252 bool PopInt32(int32* value); |
| 253 bool PopUint32(uint32* value); |
| 254 bool PopInt64(int64* value); |
| 255 bool PopUint64(uint64* value); |
| 256 bool PopDouble(double* value); |
| 257 bool PopString(std::string* value); |
| 258 bool PopObjectPath(std::string* value); |
| 259 |
| 260 // Sets up the given message reader to read an array at the current |
| 261 // iterator position. |
| 262 // Returns true and advances the iterator on success. |
| 263 // Returns false if the data type is not an array |
| 264 bool PopArray(MessageReader* sub_reader); |
| 265 bool PopStruct(MessageReader* sub_reader); |
| 266 bool PopDictEntry(MessageReader* sub_reader); |
| 267 bool PopVariant(MessageReader* sub_reader); |
| 268 |
| 269 // Gets the array of bytes at the current iterator position. |
| 270 // Returns true and advances the iterator on success. |
| 271 // |
| 272 // Arrays of bytes are often used for exchanging binary blobs hence it's |
| 273 // worth having a specialized function. |
| 274 // |
| 275 // |bytes| must be copied if the contents will be referenced after the |
| 276 // |MessageReader is destroyed. |
| 277 bool PopArrayOfBytes(uint8** bytes, size_t* length); |
| 278 |
| 279 // Gets the array of object paths at the current iterator position. |
| 280 // Returns true and advances the iterator on success. |
| 281 // |
| 282 // Arrays of object paths are often used to communicate with D-Bus |
| 283 // services like NetworkManager, hence it's worth having a specialized |
| 284 // function. |
| 285 bool PopArrayOfObjectPaths(std::vector<std::string>* object_paths); |
| 286 |
| 287 // Gets the byte from the variant data container at the current iterator |
| 288 // position. |
| 289 // Returns true and advances the iterator on success. |
| 290 // |
| 291 // Variants are widely used in D-Bus services so it's worth having a |
| 292 // specialized function. For instance, The return value type of |
| 293 // "org.freedesktop.DBus.Properties.Get" is a variant. |
| 294 bool PopVariantOfByte(uint8* value); |
| 295 bool PopVariantOfBool(bool* value); |
| 296 bool PopVariantOfInt16(int16* value); |
| 297 bool PopVariantOfUint16(uint16* value); |
| 298 bool PopVariantOfInt32(int32* value); |
| 299 bool PopVariantOfUint32(uint32* value); |
| 300 bool PopVariantOfInt64(int64* value); |
| 301 bool PopVariantOfUint64(uint64* value); |
| 302 bool PopVariantOfDouble(double* value); |
| 303 bool PopVariantOfString(std::string* value); |
| 304 bool PopVariantOfObjectPath(std::string* value); |
| 305 |
| 306 // Get the data type of the value at the current iterator |
| 307 // position. INVALID_DATA will be returned if the iterator points to the |
| 308 // end of the message. |
| 309 Message::DataType GetDataType(); |
| 310 |
| 311 private: |
| 312 // Returns true if the data type at the current iterator position |
| 313 // matches the given D-Bus type, such as DBUS_TYPE_BYTE. |
| 314 bool CheckDataType(int dbus_type); |
| 315 |
| 316 // Helper function used to implement PopByte() etc. |
| 317 bool PopBasic(int dbus_type, void *value); |
| 318 |
| 319 // Helper function used to implement PopArray() etc. |
| 320 bool PopContainer(int dbus_type, MessageReader* sub_reader); |
| 321 |
| 322 // Helper function used to implement PopVariantOfByte() etc. |
| 323 bool PopVariantOfBasic(int dbus_type, void* value); |
| 324 |
| 325 Message* message_; |
| 326 DBusMessageIter raw_message_iter_; |
| 327 |
| 328 DISALLOW_COPY_AND_ASSIGN(MessageReader); |
| 329 }; |
| 330 |
| 331 } // namespace dbus |
| 332 |
| 333 #endif // DBUS_MESSAGE_H_ |
OLD | NEW |