sdbus-c++  1.2.0
High-level C++ D-Bus library based on systemd D-Bus implementation
Message.h
Go to the documentation of this file.
1 
27 #ifndef SDBUS_CXX_MESSAGE_H_
28 #define SDBUS_CXX_MESSAGE_H_
29 
30 #include <sdbus-c++/TypeTraits.h>
31 #include <sdbus-c++/Error.h>
32 #include <string>
33 #include <vector>
34 #include <map>
35 #include <utility>
36 #include <cstdint>
37 #include <cassert>
38 #include <functional>
39 #include <sys/types.h>
40 
41 // Forward declarations
42 namespace sdbus {
43  class Variant;
44  class ObjectPath;
45  class Signature;
46  template <typename... _ValueTypes> class Struct;
47  class UnixFd;
48  class MethodReply;
49  namespace internal {
50  class ISdBus;
51  class IConnection;
52  }
53 }
54 
55 namespace sdbus {
56 
57  /********************************************/
70  class [[nodiscard]] Message
71  {
72  public:
73  Message& operator<<(bool item);
74  Message& operator<<(int16_t item);
75  Message& operator<<(int32_t item);
76  Message& operator<<(int64_t item);
77  Message& operator<<(uint8_t item);
78  Message& operator<<(uint16_t item);
79  Message& operator<<(uint32_t item);
80  Message& operator<<(uint64_t item);
81  Message& operator<<(double item);
82  Message& operator<<(const char *item);
83  Message& operator<<(const std::string &item);
84  Message& operator<<(const Variant &item);
85  Message& operator<<(const ObjectPath &item);
86  Message& operator<<(const Signature &item);
87  Message& operator<<(const UnixFd &item);
88 
89  Message& operator>>(bool& item);
90  Message& operator>>(int16_t& item);
91  Message& operator>>(int32_t& item);
92  Message& operator>>(int64_t& item);
93  Message& operator>>(uint8_t& item);
94  Message& operator>>(uint16_t& item);
95  Message& operator>>(uint32_t& item);
96  Message& operator>>(uint64_t& item);
97  Message& operator>>(double& item);
98  Message& operator>>(char*& item);
99  Message& operator>>(std::string &item);
100  Message& operator>>(Variant &item);
101  Message& operator>>(ObjectPath &item);
102  Message& operator>>(Signature &item);
103  Message& operator>>(UnixFd &item);
104 
105  Message& openContainer(const std::string& signature);
106  Message& closeContainer();
107  Message& openDictEntry(const std::string& signature);
108  Message& closeDictEntry();
109  Message& openVariant(const std::string& signature);
110  Message& closeVariant();
111  Message& openStruct(const std::string& signature);
112  Message& closeStruct();
113 
114  Message& enterContainer(const std::string& signature);
115  Message& exitContainer();
116  Message& enterDictEntry(const std::string& signature);
117  Message& exitDictEntry();
118  Message& enterVariant(const std::string& signature);
119  Message& exitVariant();
120  Message& enterStruct(const std::string& signature);
121  Message& exitStruct();
122 
123  explicit operator bool() const;
124  void clearFlags();
125 
126  std::string getInterfaceName() const;
127  std::string getMemberName() const;
128  std::string getSender() const;
129  std::string getPath() const;
130  std::string getDestination() const;
131  void peekType(std::string& type, std::string& contents) const;
132  bool isValid() const;
133  bool isEmpty() const;
134 
135  void copyTo(Message& destination, bool complete) const;
136  void seal();
137  void rewind(bool complete);
138 
139  pid_t getCredsPid() const;
140  uid_t getCredsUid() const;
141  uid_t getCredsEuid() const;
142  gid_t getCredsGid() const;
143  gid_t getCredsEgid() const;
144  std::vector<gid_t> getCredsSupplementaryGids() const;
145  std::string getSELinuxContext() const;
146 
147  class Factory;
148 
149  protected:
150  Message() = default;
151  explicit Message(internal::ISdBus* sdbus) noexcept;
152  Message(void *msg, internal::ISdBus* sdbus) noexcept;
153  Message(void *msg, internal::ISdBus* sdbus, adopt_message_t) noexcept;
154 
155  Message(const Message&) noexcept;
156  Message& operator=(const Message&) noexcept;
157  Message(Message&& other) noexcept;
158  Message& operator=(Message&& other) noexcept;
159 
160  ~Message();
161 
162  friend Factory;
163 
164  protected:
165  void* msg_{};
166  internal::ISdBus* sdbus_{};
167  mutable bool ok_{true};
168  };
169 
170  class MethodCall : public Message
171  {
172  using Message::Message;
173  friend Factory;
174 
175  public:
176  MethodCall() = default;
177 
178  MethodReply send(uint64_t timeout) const;
179  [[deprecated("Use send overload with floating_slot instead")]] void send(void* callback, void* userData, uint64_t timeout, dont_request_slot_t) const;
180  void send(void* callback, void* userData, uint64_t timeout, floating_slot_t) const;
181  [[nodiscard]] Slot send(void* callback, void* userData, uint64_t timeout) const;
182 
183  MethodReply createReply() const;
184  MethodReply createErrorReply(const sdbus::Error& error) const;
185 
186  void dontExpectReply();
187  bool doesntExpectReply() const;
188 
189  protected:
190  MethodCall(void *msg, internal::ISdBus* sdbus, const internal::IConnection* connection, adopt_message_t) noexcept;
191 
192  private:
193  MethodReply sendWithReply(uint64_t timeout = 0) const;
194  MethodReply sendWithNoReply() const;
195  const internal::IConnection* connection_{};
196  };
197 
198  class MethodReply : public Message
199  {
200  using Message::Message;
201  friend Factory;
202 
203  public:
204  MethodReply() = default;
205  void send() const;
206  };
207 
208  class Signal : public Message
209  {
210  using Message::Message;
211  friend Factory;
212 
213  public:
214  Signal() = default;
215  void setDestination(const std::string& destination);
216  void send() const;
217  };
218 
219  class PropertySetCall : public Message
220  {
221  using Message::Message;
222  friend Factory;
223 
224  public:
225  PropertySetCall() = default;
226  };
227 
228  class PropertyGetReply : public Message
229  {
230  using Message::Message;
231  friend Factory;
232 
233  public:
234  PropertyGetReply() = default;
235  };
236 
237  // Represents any of the above message types, or just a message that serves as a container for data
238  class PlainMessage : public Message
239  {
240  using Message::Message;
241  friend Factory;
242 
243  public:
244  PlainMessage() = default;
245  };
246 
247  template <typename _Element>
248  inline Message& operator<<(Message& msg, const std::vector<_Element>& items)
249  {
250  msg.openContainer(signature_of<_Element>::str());
251 
252  for (const auto& item : items)
253  msg << item;
254 
255  msg.closeContainer();
256 
257  return msg;
258  }
259 
260  template <typename _Key, typename _Value>
261  inline Message& operator<<(Message& msg, const std::map<_Key, _Value>& items)
262  {
263  const std::string dictEntrySignature = signature_of<_Key>::str() + signature_of<_Value>::str();
264  const std::string arraySignature = "{" + dictEntrySignature + "}";
265 
266  msg.openContainer(arraySignature);
267 
268  for (const auto& item : items)
269  {
270  msg.openDictEntry(dictEntrySignature);
271  msg << item.first;
272  msg << item.second;
273  msg.closeDictEntry();
274  }
275 
276  msg.closeContainer();
277 
278  return msg;
279  }
280 
281  namespace detail
282  {
283  template <typename... _Args>
284  void serialize_pack(Message& msg, _Args&&... args)
285  {
286  (void)(msg << ... << args);
287  }
288 
289  template <class _Tuple, std::size_t... _Is>
290  void serialize_tuple( Message& msg
291  , const _Tuple& t
292  , std::index_sequence<_Is...>)
293  {
294  serialize_pack(msg, std::get<_Is>(t)...);
295  }
296  }
297 
298  template <typename... _ValueTypes>
299  inline Message& operator<<(Message& msg, const Struct<_ValueTypes...>& item)
300  {
301  auto structSignature = signature_of<Struct<_ValueTypes...>>::str();
302  assert(structSignature.size() > 2);
303  // Remove opening and closing parenthesis from the struct signature to get contents signature
304  auto structContentSignature = structSignature.substr(1, structSignature.size()-2);
305 
306  msg.openStruct(structContentSignature);
307  detail::serialize_tuple(msg, item, std::index_sequence_for<_ValueTypes...>{});
308  msg.closeStruct();
309 
310  return msg;
311  }
312 
313  template <typename... _ValueTypes>
314  inline Message& operator<<(Message& msg, const std::tuple<_ValueTypes...>& item)
315  {
316  detail::serialize_tuple(msg, item, std::index_sequence_for<_ValueTypes...>{});
317  return msg;
318  }
319 
320 
321  template <typename _Element>
322  inline Message& operator>>(Message& msg, std::vector<_Element>& items)
323  {
324  if(!msg.enterContainer(signature_of<_Element>::str()))
325  return msg;
326 
327  while (true)
328  {
329  _Element elem;
330  if (msg >> elem)
331  items.emplace_back(std::move(elem));
332  else
333  break;
334  }
335 
336  msg.clearFlags();
337 
338  msg.exitContainer();
339 
340  return msg;
341  }
342 
343  template <typename _Key, typename _Value>
344  inline Message& operator>>(Message& msg, std::map<_Key, _Value>& items)
345  {
346  const std::string dictEntrySignature = signature_of<_Key>::str() + signature_of<_Value>::str();
347  const std::string arraySignature = "{" + dictEntrySignature + "}";
348 
349  if (!msg.enterContainer(arraySignature))
350  return msg;
351 
352  while (true)
353  {
354  if (!msg.enterDictEntry(dictEntrySignature))
355  break;
356 
357  _Key key;
358  _Value value;
359  msg >> key >> value;
360 
361  items.emplace(std::move(key), std::move(value));
362 
363  msg.exitDictEntry();
364  }
365 
366  msg.clearFlags();
367 
368  msg.exitContainer();
369 
370  return msg;
371  }
372 
373  namespace detail
374  {
375  template <typename... _Args>
376  void deserialize_pack(Message& msg, _Args&... args)
377  {
378  (void)(msg >> ... >> args);
379  }
380 
381  template <class _Tuple, std::size_t... _Is>
382  void deserialize_tuple( Message& msg
383  , _Tuple& t
384  , std::index_sequence<_Is...> )
385  {
386  deserialize_pack(msg, std::get<_Is>(t)...);
387  }
388  }
389 
390  template <typename... _ValueTypes>
391  inline Message& operator>>(Message& msg, Struct<_ValueTypes...>& item)
392  {
393  auto structSignature = signature_of<Struct<_ValueTypes...>>::str();
394  // Remove opening and closing parenthesis from the struct signature to get contents signature
395  auto structContentSignature = structSignature.substr(1, structSignature.size()-2);
396 
397  if (!msg.enterStruct(structContentSignature))
398  return msg;
399 
400  detail::deserialize_tuple(msg, item, std::index_sequence_for<_ValueTypes...>{});
401 
402  msg.exitStruct();
403 
404  return msg;
405  }
406 
407  template <typename... _ValueTypes>
408  inline Message& operator>>(Message& msg, std::tuple<_ValueTypes...>& item)
409  {
410  detail::deserialize_tuple(msg, item, std::index_sequence_for<_ValueTypes...>{});
411  return msg;
412  }
413 
414 }
415 
416 #endif /* SDBUS_CXX_MESSAGE_H_ */
Definition: Error.h:44
Definition: Message.h:71
Definition: Message.h:171
Definition: Message.h:199
Definition: Types.h:153
Definition: Message.h:239
Definition: Message.h:229
Definition: Message.h:220
Definition: Message.h:209
Definition: Types.h:174
Definition: Types.h:200
Definition: Types.h:54
Definition: TypeTraits.h:79
Definition: TypeTraits.h:76
Definition: TypeTraits.h:73
Definition: TypeTraits.h:88