1 // Copyright (c) Benjamin Kietzman (github.com/bkietz) 2 // 3 // Distributed under the Boost Software License, Version 1.0. (See accompanying 4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 6 #ifndef DBUS_MESSAGE_HPP 7 #define DBUS_MESSAGE_HPP 8 9 #include <dbus/dbus.h> 10 #include <dbus/element.hpp> 11 #include <dbus/endpoint.hpp> 12 #include <dbus/impl/message_iterator.hpp> 13 #include <iostream> 14 #include <boost/intrusive_ptr.hpp> 15 #include <boost/utility/enable_if.hpp> 16 17 inline void intrusive_ptr_add_ref(DBusMessage* m) { dbus_message_ref(m); } 18 19 inline void intrusive_ptr_release(DBusMessage* m) { dbus_message_unref(m); } 20 21 namespace dbus { 22 23 class message { 24 boost::intrusive_ptr<DBusMessage> message_; 25 26 public: 27 /// Create a method call message 28 static message new_call(const endpoint& destination, 29 const string& method_name) { 30 return dbus_message_new_method_call( 31 destination.get_process_name().c_str(), destination.get_path().c_str(), 32 destination.get_interface().c_str(), method_name.c_str()); 33 } 34 35 /// Create a method return message 36 static message new_return(message& call) { 37 return dbus_message_new_method_return(call); 38 } 39 40 /// Create an error message 41 static message new_error(message& call, const string& error_name, 42 const string& error_message) { 43 return dbus_message_new_error(call, error_name.c_str(), 44 error_message.c_str()); 45 } 46 47 /// Create a signal message 48 static message new_signal(const endpoint& origin, const string& signal_name) { 49 return dbus_message_new_signal(origin.get_path().c_str(), 50 origin.get_interface().c_str(), 51 signal_name.c_str()); 52 } 53 54 message() {} 55 56 message(DBusMessage* m) : message_(dbus_message_ref(m)) {} 57 58 operator DBusMessage*() { return message_.get(); } 59 60 operator const DBusMessage*() const { return message_.get(); } 61 62 string get_path() const { 63 return sanitize(dbus_message_get_path(message_.get())); 64 } 65 66 string get_interface() const { 67 return sanitize(dbus_message_get_interface(message_.get())); 68 } 69 70 string get_member() const { 71 return sanitize(dbus_message_get_member(message_.get())); 72 } 73 74 string get_type() const { 75 return sanitize( 76 dbus_message_type_to_string(dbus_message_get_type(message_.get()))); 77 } 78 79 string get_sender() const { 80 return sanitize(dbus_message_get_sender(message_.get())); 81 } 82 83 string get_destination() const { 84 return sanitize(dbus_message_get_destination(message_.get())); 85 } 86 87 uint32 get_serial() { return dbus_message_get_serial(message_.get()); } 88 89 message& set_serial(uint32 serial) { 90 dbus_message_set_serial(message_.get(), serial); 91 return *this; 92 } 93 94 uint32 get_reply_serial() { 95 return dbus_message_get_reply_serial(message_.get()); 96 } 97 98 message& set_reply_serial(uint32 reply_serial) { 99 dbus_message_set_reply_serial(message_.get(), reply_serial); 100 return *this; 101 } 102 103 struct packer { 104 impl::message_iterator iter_; 105 packer(message& m) { impl::message_iterator::init_append(m, iter_); } 106 template <typename Element> 107 packer& pack(const Element& e) { 108 return *this << e; 109 } 110 }; 111 struct unpacker { 112 impl::message_iterator iter_; 113 unpacker(message& m) { impl::message_iterator::init(m, iter_); } 114 template <typename Element> 115 unpacker& unpack(Element& e) { 116 return *this >> e; 117 } 118 }; 119 120 template <typename Element> 121 packer pack(const Element& e) { 122 return packer(*this).pack(e); 123 } 124 125 template <typename Element> 126 unpacker unpack(Element& e) { 127 return unpacker(*this).unpack(e); 128 } 129 130 private: 131 static std::string sanitize(const char* str) { 132 return (str == NULL) ? "(null)" : str; 133 } 134 }; 135 136 template <typename Element> 137 message::packer operator<<(message m, const Element& e) { 138 return message::packer(m).pack(e); 139 } 140 141 template <typename Element> 142 typename boost::enable_if<is_fixed_type<Element>, message::packer&>::type 143 operator<<(message::packer& p, const Element& e) { 144 p.iter_.append_basic(element<Element>::code, &e); 145 return p; 146 } 147 148 inline message::packer& operator<<(message::packer& p, const char* c) { 149 p.iter_.append_basic(element<string>::code, &c); 150 return p; 151 } 152 153 inline message::packer& operator<<(message::packer& p, const string& e) { 154 const char* c = e.c_str(); 155 return p << c; 156 } 157 158 template <typename Element> 159 message::unpacker operator>>(message m, Element& e) { 160 return message::unpacker(m).unpack(e); 161 } 162 163 template <typename Element> 164 typename boost::enable_if<is_fixed_type<Element>, message::unpacker&>::type 165 operator>>(message::unpacker& u, Element& e) { 166 u.iter_.get_basic(&e); 167 u.iter_.next(); 168 return u; 169 } 170 171 inline message::unpacker& operator>>(message::unpacker& u, string& s) { 172 const char* c; 173 u.iter_.get_basic(&c); 174 s.assign(c); 175 u.iter_.next(); 176 return u; 177 } 178 179 inline std::ostream& operator<<(std::ostream& os, const message& m) { 180 os << "type='" << m.get_type() << "'," 181 << "sender='" << m.get_sender() << "'," 182 << "interface='" << m.get_interface() << "'," 183 << "member='" << m.get_member() << "'," 184 << "path='" << m.get_path() << "'," 185 << "destination='" << m.get_destination() << "'"; 186 return os; 187 } 188 189 } // namespace dbus 190 191 #include <dbus/impl/message_iterator.ipp> 192 193 #endif // DBUS_MESSAGE_HPP 194