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