xref: /openbmc/boost-dbus/include/dbus/message.hpp (revision da3eeb6a)
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