123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523 |
- // Copyright (c) 2012 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #ifndef DBUS_MESSAGE_H_
- #define DBUS_MESSAGE_H_
- #include <dbus/dbus.h>
- #include <stddef.h>
- #include <stdint.h>
- #include <memory>
- #include <string>
- #include <vector>
- #include "base/files/scoped_file.h"
- #include "base/memory/raw_ptr.h"
- #include "base/strings/string_piece.h"
- #include "dbus/dbus_export.h"
- #include "dbus/object_path.h"
- namespace google {
- namespace protobuf {
- class MessageLite;
- } // namespace protobuf
- } // namespace google
- namespace dbus {
- class MessageWriter;
- class MessageReader;
- // DBUS_TYPE_UNIX_FD was added in D-Bus version 1.4
- #if !defined(DBUS_TYPE_UNIX_FD)
- #define DBUS_TYPE_UNIX_FD ((int)'h')
- #endif
- // Returns true if Unix FD passing is supported in libdbus.
- // The check is done runtime rather than compile time as the libdbus
- // version used at runtime may be different from the one used at compile time.
- CHROME_DBUS_EXPORT bool IsDBusTypeUnixFdSupported();
- // Message is the base class of D-Bus message types. Client code must use
- // sub classes such as MethodCall and Response instead.
- //
- // The class name Message is very generic, but there should be no problem
- // as the class is inside 'dbus' namespace. We chose to name this way, as
- // libdbus defines lots of types starting with DBus, such as
- // DBusMessage. We should avoid confusion and conflict with these types.
- class CHROME_DBUS_EXPORT Message {
- public:
- // The message type used in D-Bus. Redefined here so client code
- // doesn't need to use raw D-Bus macros. DBUS_MESSAGE_TYPE_INVALID
- // etc. are #define macros. Having an enum type here makes code a bit
- // more type-safe.
- enum MessageType {
- MESSAGE_INVALID = DBUS_MESSAGE_TYPE_INVALID,
- MESSAGE_METHOD_CALL = DBUS_MESSAGE_TYPE_METHOD_CALL,
- MESSAGE_METHOD_RETURN = DBUS_MESSAGE_TYPE_METHOD_RETURN,
- MESSAGE_SIGNAL = DBUS_MESSAGE_TYPE_SIGNAL,
- MESSAGE_ERROR = DBUS_MESSAGE_TYPE_ERROR,
- };
- // The data type used in the D-Bus type system. See the comment at
- // MessageType for why we are redefining data types here.
- enum DataType {
- INVALID_DATA = DBUS_TYPE_INVALID,
- BYTE = DBUS_TYPE_BYTE,
- BOOL = DBUS_TYPE_BOOLEAN,
- INT16 = DBUS_TYPE_INT16,
- UINT16 = DBUS_TYPE_UINT16,
- INT32 = DBUS_TYPE_INT32,
- UINT32 = DBUS_TYPE_UINT32,
- INT64 = DBUS_TYPE_INT64,
- UINT64 = DBUS_TYPE_UINT64,
- DOUBLE = DBUS_TYPE_DOUBLE,
- STRING = DBUS_TYPE_STRING,
- OBJECT_PATH = DBUS_TYPE_OBJECT_PATH,
- ARRAY = DBUS_TYPE_ARRAY,
- STRUCT = DBUS_TYPE_STRUCT,
- DICT_ENTRY = DBUS_TYPE_DICT_ENTRY,
- VARIANT = DBUS_TYPE_VARIANT,
- UNIX_FD = DBUS_TYPE_UNIX_FD,
- };
- Message(const Message&) = delete;
- Message& operator=(const Message&) = delete;
- // Returns the type of the message. Returns MESSAGE_INVALID if
- // raw_message_ is NULL.
- MessageType GetMessageType();
- // Returns the type of the message as string like "MESSAGE_METHOD_CALL"
- // for instance.
- std::string GetMessageTypeAsString();
- DBusMessage* raw_message() { return raw_message_; }
- // Sets the destination, the path, the interface, the member, etc.
- bool SetDestination(const std::string& destination);
- bool SetPath(const ObjectPath& path);
- bool SetInterface(const std::string& interface);
- bool SetMember(const std::string& member);
- bool SetErrorName(const std::string& error_name);
- bool SetSender(const std::string& sender);
- void SetSerial(uint32_t serial);
- void SetReplySerial(uint32_t reply_serial);
- // SetSignature() does not exist as we cannot do it.
- // Gets the destination, the path, the interface, the member, etc.
- // If not set, an empty string is returned.
- std::string GetDestination();
- ObjectPath GetPath();
- std::string GetInterface();
- std::string GetMember();
- std::string GetErrorName();
- std::string GetSender();
- std::string GetSignature();
- // Gets the serial and reply serial numbers. Returns 0 if not set.
- uint32_t GetSerial();
- uint32_t GetReplySerial();
- // Returns the string representation of this message. Useful for
- // debugging. The output is truncated as needed (ex. strings are truncated
- // if longer than a certain limit defined in the .cc file).
- std::string ToString();
- protected:
- // This class cannot be instantiated. Use sub classes instead.
- Message();
- virtual ~Message();
- // Initializes the message with the given raw message.
- void Init(DBusMessage* raw_message);
- private:
- // Helper function used in ToString().
- std::string ToStringInternal(const std::string& indent,
- MessageReader* reader);
- raw_ptr<DBusMessage, DanglingUntriaged> raw_message_;
- };
- // MessageCall is a type of message used for calling a method via D-Bus.
- class CHROME_DBUS_EXPORT MethodCall : public Message {
- public:
- // Creates a method call message for the specified interface name and
- // the method name.
- //
- // For instance, to call "Get" method of DBUS_INTERFACE_INTROSPECTABLE
- // interface ("org.freedesktop.DBus.Introspectable"), create a method
- // call like this:
- //
- // MethodCall method_call(DBUS_INTERFACE_INTROSPECTABLE, "Get");
- //
- // The constructor creates the internal raw message.
- MethodCall(const std::string& interface_name, const std::string& method_name);
- MethodCall(const MethodCall&) = delete;
- MethodCall& operator=(const MethodCall&) = delete;
- // Returns a newly created MethodCall from the given raw message of the
- // type DBUS_MESSAGE_TYPE_METHOD_CALL. Takes the ownership of |raw_message|.
- static std::unique_ptr<MethodCall> FromRawMessage(DBusMessage* raw_message);
- private:
- // Creates a method call message. The internal raw message is NULL.
- // Only used internally.
- MethodCall();
- };
- // Signal is a type of message used to send a signal.
- class CHROME_DBUS_EXPORT Signal : public Message {
- public:
- // Creates a signal message for the specified interface name and the
- // method name.
- //
- // For instance, to send "PropertiesChanged" signal of
- // DBUS_INTERFACE_INTROSPECTABLE interface
- // ("org.freedesktop.DBus.Introspectable"), create a signal like this:
- //
- // Signal signal(DBUS_INTERFACE_INTROSPECTABLE, "PropertiesChanged");
- //
- // The constructor creates the internal raw_message_.
- Signal(const std::string& interface_name, const std::string& method_name);
- Signal(const Signal&) = delete;
- Signal& operator=(const Signal&) = delete;
- // Returns a newly created SIGNAL from the given raw message of the type
- // DBUS_MESSAGE_TYPE_SIGNAL. Takes the ownership of |raw_message|.
- static std::unique_ptr<Signal> FromRawMessage(DBusMessage* raw_message);
- private:
- // Creates a signal message. The internal raw message is NULL.
- // Only used internally.
- Signal();
- };
- // Response is a type of message used for receiving a response from a
- // method via D-Bus.
- class CHROME_DBUS_EXPORT Response : public Message {
- public:
- // Returns a newly created Response from the given raw message of the
- // type DBUS_MESSAGE_TYPE_METHOD_RETURN. Takes the ownership of |raw_message|.
- static std::unique_ptr<Response> FromRawMessage(DBusMessage* raw_message);
- // Returns a newly created Response from the given method call.
- // Used for implementing exported methods. Does NOT take the ownership of
- // |method_call|.
- static std::unique_ptr<Response> FromMethodCall(MethodCall* method_call);
- // Returns a newly created Response with an empty payload.
- // Useful for testing.
- static std::unique_ptr<Response> CreateEmpty();
- Response(const Response&) = delete;
- Response& operator=(const Response&) = delete;
- protected:
- // Creates a Response message. The internal raw message is NULL.
- Response();
- };
- // ErrorResponse is a type of message used to return an error to the
- // caller of a method.
- class CHROME_DBUS_EXPORT ErrorResponse : public Response {
- public:
- // Returns a newly created Response from the given raw message of the
- // type DBUS_MESSAGE_TYPE_METHOD_RETURN. Takes the ownership of |raw_message|.
- static std::unique_ptr<ErrorResponse> FromRawMessage(
- DBusMessage* raw_message);
- // Returns a newly created ErrorResponse from the given method call, the
- // error name, and the error message. The error name looks like
- // "org.freedesktop.DBus.Error.Failed". Used for returning an error to a
- // failed method call. Does NOT take the ownership of |method_call|.
- static std::unique_ptr<ErrorResponse> FromMethodCall(
- MethodCall* method_call,
- const std::string& error_name,
- const std::string& error_message);
- ErrorResponse(const ErrorResponse&) = delete;
- ErrorResponse& operator=(const ErrorResponse&) = delete;
- private:
- // Creates an ErrorResponse message. The internal raw message is NULL.
- ErrorResponse();
- };
- // MessageWriter is used to write outgoing messages for calling methods
- // and sending signals.
- //
- // The main design goal of MessageReader and MessageWriter classes is to
- // provide a type safe API. In the past, there was a Chrome OS blocker
- // bug, that took days to fix, that would have been prevented if the API
- // was type-safe.
- //
- // For instance, instead of doing something like:
- //
- // // We shouldn't add '&' to str here, but it compiles with '&' added.
- // dbus_g_proxy_call(..., G_TYPE_STRING, str, G_TYPE_INVALID, ...)
- //
- // We want to do something like:
- //
- // writer.AppendString(str);
- //
- class CHROME_DBUS_EXPORT MessageWriter {
- public:
- // Data added with Append* will be written to |message|, which may be NULL
- // to create a sub-writer for passing to OpenArray, etc.
- explicit MessageWriter(Message* message);
- MessageWriter(const MessageWriter&) = delete;
- MessageWriter& operator=(const MessageWriter&) = delete;
- ~MessageWriter();
- // Appends a byte to the message.
- void AppendByte(uint8_t value);
- void AppendBool(bool value);
- void AppendInt16(int16_t value);
- void AppendUint16(uint16_t value);
- void AppendInt32(int32_t value);
- void AppendUint32(uint32_t value);
- void AppendInt64(int64_t value);
- void AppendUint64(uint64_t value);
- void AppendDouble(double value);
- void AppendString(base::StringPiece value);
- void AppendObjectPath(const ObjectPath& value);
- // Appends a file descriptor to the message.
- // The FD will be duplicated so you still have to close the original FD.
- void AppendFileDescriptor(int value);
- // Opens an array. The array contents can be added to the array with
- // |sub_writer|. The client code must close the array with
- // CloseContainer(), once all contents are added.
- //
- // |signature| parameter is used to supply the D-Bus type signature of
- // the array contents. For instance, if you want an array of strings,
- // then you pass "s" as the signature.
- //
- // See the spec for details about the type signatures.
- // http://dbus.freedesktop.org/doc/dbus-specification.html
- // #message-protocol-signatures
- //
- void OpenArray(const std::string& signature, MessageWriter* sub_writer);
- // Do the same for a variant.
- void OpenVariant(const std::string& signature, MessageWriter* sub_writer);
- // Do the same for Struct and dict entry. They don't need the signature.
- void OpenStruct(MessageWriter* sub_writer);
- void OpenDictEntry(MessageWriter* sub_writer);
- // Close the container for a array/variant/struct/dict entry.
- void CloseContainer(MessageWriter* sub_writer);
- // Appends the array of bytes. Arrays of bytes are often used for
- // exchanging binary blobs hence it's worth having a specialized
- // function.
- void AppendArrayOfBytes(const uint8_t* values, size_t length);
- // Appends array of int32_ts.
- void AppendArrayOfInt32s(const int32_t* values, size_t length);
- // Appends array of uint32_ts.
- void AppendArrayOfUint32s(const uint32_t* values, size_t length);
- // Appends the array of doubles. Used for audio mixer matrix doubles.
- void AppendArrayOfDoubles(const double* values, size_t length);
- // Appends the array of strings. Arrays of strings are often used for
- // exchanging lists of names hence it's worth having a specialized
- // function.
- void AppendArrayOfStrings(const std::vector<std::string>& strings);
- // Appends the array of object paths. Arrays of object paths are often
- // used when exchanging object paths, hence it's worth having a
- // specialized function.
- void AppendArrayOfObjectPaths(const std::vector<ObjectPath>& object_paths);
- // Appends the protocol buffer as an array of bytes. The buffer is serialized
- // into an array of bytes before communication, since protocol buffers are not
- // a native dbus type. On the receiving size the array of bytes needs to be
- // read and deserialized into a protocol buffer of the correct type. There are
- // methods in MessageReader to assist in this. Return true on success and
- // false when serialization fails.
- bool AppendProtoAsArrayOfBytes(const google::protobuf::MessageLite& protobuf);
- // Appends the byte wrapped in a variant data container. Variants are
- // widely used in D-Bus services so it's worth having a specialized
- // function. For instance, The third parameter of
- // "org.freedesktop.DBus.Properties.Set" is a variant.
- void AppendVariantOfByte(uint8_t value);
- void AppendVariantOfBool(bool value);
- void AppendVariantOfInt16(int16_t value);
- void AppendVariantOfUint16(uint16_t value);
- void AppendVariantOfInt32(int32_t value);
- void AppendVariantOfUint32(uint32_t value);
- void AppendVariantOfInt64(int64_t value);
- void AppendVariantOfUint64(uint64_t value);
- void AppendVariantOfDouble(double value);
- void AppendVariantOfString(const std::string& value);
- void AppendVariantOfObjectPath(const ObjectPath& value);
- private:
- // Helper function used to implement AppendByte etc.
- void AppendBasic(int dbus_type, const void* value);
- // Helper function used to implement AppendVariantOfByte() etc.
- void AppendVariantOfBasic(int dbus_type, const void* value);
- raw_ptr<Message, DanglingUntriaged> message_;
- DBusMessageIter raw_message_iter_;
- bool container_is_open_;
- };
- // MessageReader is used to read incoming messages such as responses for
- // method calls.
- //
- // MessageReader manages an internal iterator to read data. All functions
- // starting with Pop advance the iterator on success.
- class CHROME_DBUS_EXPORT MessageReader {
- public:
- // The data will be read from the given |message|, which may be NULL to
- // create a sub-reader for passing to PopArray, etc.
- explicit MessageReader(Message* message);
- MessageReader(const MessageReader&) = delete;
- MessageReader& operator=(const MessageReader&) = delete;
- ~MessageReader();
- // Returns true if the reader has more data to read. The function is
- // used to iterate contents in a container like:
- //
- // while (reader.HasMoreData())
- // reader.PopString(&value);
- bool HasMoreData();
- // Gets the byte at the current iterator position.
- // Returns true and advances the iterator on success.
- // Returns false if the data type is not a byte.
- bool PopByte(uint8_t* value);
- bool PopBool(bool* value);
- bool PopInt16(int16_t* value);
- bool PopUint16(uint16_t* value);
- bool PopInt32(int32_t* value);
- bool PopUint32(uint32_t* value);
- bool PopInt64(int64_t* value);
- bool PopUint64(uint64_t* value);
- bool PopDouble(double* value);
- bool PopString(std::string* value);
- bool PopObjectPath(ObjectPath* value);
- bool PopFileDescriptor(base::ScopedFD* value);
- // Sets up the given message reader to read an array at the current
- // iterator position.
- // Returns true and advances the iterator on success.
- // Returns false if the data type is not an array
- bool PopArray(MessageReader* sub_reader);
- bool PopStruct(MessageReader* sub_reader);
- bool PopDictEntry(MessageReader* sub_reader);
- bool PopVariant(MessageReader* sub_reader);
- // Gets the array of bytes at the current iterator position.
- // Returns true and advances the iterator on success.
- //
- // Arrays of bytes are often used for exchanging binary blobs hence it's
- // worth having a specialized function.
- //
- // Ownership of the memory pointed to by |bytes| remains with the
- // MessageReader; |bytes| must be copied if the contents will be referenced
- // after the MessageReader is destroyed.
- bool PopArrayOfBytes(const uint8_t** bytes, size_t* length);
- // Gets the array of int32_ts at the current iterator position.
- bool PopArrayOfInt32s(const int32_t** signed_ints, size_t* length);
- // Gets the array of uint32_ts at the current iterator position.
- bool PopArrayOfUint32s(const uint32_t** unsigned_ints, size_t* length);
- // Gets the array of doubles at the current iterator position.
- bool PopArrayOfDoubles(const double** doubles, size_t* length);
- // Gets the array of strings at the current iterator position. |strings| is
- // cleared before being modified. Returns true and advances the iterator on
- // success.
- //
- // Arrays of strings are often used to communicate with D-Bus
- // services like KWallet, hence it's worth having a specialized
- // function.
- bool PopArrayOfStrings(std::vector<std::string>* strings);
- // Gets the array of object paths at the current iterator position.
- // |object_paths| is cleared before being modified. Returns true and advances
- // the iterator on success.
- //
- // Arrays of object paths are often used to communicate with D-Bus
- // services like NetworkManager, hence it's worth having a specialized
- // function.
- bool PopArrayOfObjectPaths(std::vector<ObjectPath>* object_paths);
- // Gets the array of bytes at the current iterator position. It then parses
- // this binary blob into the protocol buffer supplied.
- // Returns true and advances the iterator on success. On failure returns false
- // and emits an error message on the source of the failure. The two most
- // common errors come from the iterator not currently being at a byte array or
- // the wrong type of protocol buffer is passed in and the parse fails.
- bool PopArrayOfBytesAsProto(google::protobuf::MessageLite* protobuf);
- // Gets the byte from the variant data container at the current iterator
- // position.
- // Returns true and advances the iterator on success.
- //
- // Variants are widely used in D-Bus services so it's worth having a
- // specialized function. For instance, The return value type of
- // "org.freedesktop.DBus.Properties.Get" is a variant.
- bool PopVariantOfByte(uint8_t* value);
- bool PopVariantOfBool(bool* value);
- bool PopVariantOfInt16(int16_t* value);
- bool PopVariantOfUint16(uint16_t* value);
- bool PopVariantOfInt32(int32_t* value);
- bool PopVariantOfUint32(uint32_t* value);
- bool PopVariantOfInt64(int64_t* value);
- bool PopVariantOfUint64(uint64_t* value);
- bool PopVariantOfDouble(double* value);
- bool PopVariantOfString(std::string* value);
- bool PopVariantOfObjectPath(ObjectPath* value);
- // Get the data type of the value at the current iterator
- // position. INVALID_DATA will be returned if the iterator points to the
- // end of the message.
- Message::DataType GetDataType();
- // Get the DBus signature of the value at the current iterator position.
- // An empty string will be returned if the iterator points to the end of
- // the message.
- std::string GetDataSignature();
- private:
- // Returns true if the data type at the current iterator position
- // matches the given D-Bus type, such as DBUS_TYPE_BYTE.
- bool CheckDataType(int dbus_type);
- // Helper function used to implement PopByte() etc.
- bool PopBasic(int dbus_type, void* value);
- // Helper function used to implement PopArray() etc.
- bool PopContainer(int dbus_type, MessageReader* sub_reader);
- // Helper function used to implement PopVariantOfByte() etc.
- bool PopVariantOfBasic(int dbus_type, void* value);
- raw_ptr<Message, DanglingUntriaged> message_;
- DBusMessageIter raw_message_iter_;
- };
- } // namespace dbus
- #endif // DBUS_MESSAGE_H_
|