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