1 /**
2 * (C) 2016 - 2017 KISTLER INSTRUMENTE AG, Winterthur, Switzerland
3 * (C) 2016 - 2019 Stanislav Angelovic <angelovic.s@gmail.com>
4 *
5 * @file Message.cpp
6 *
7 * Created on: Nov 9, 2016
8 * Project: sdbus-c++
9 * Description: High-level D-Bus IPC C++ library based on sd-bus
10 *
11 * This file is part of sdbus-c++.
12 *
13 * sdbus-c++ is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU Lesser General Public License as published by
15 * the Free Software Foundation, either version 2.1 of the License, or
16 * (at your option) any later version.
17 *
18 * sdbus-c++ is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License for more details.
22 *
23 * You should have received a copy of the GNU Lesser General Public License
24 * along with sdbus-c++. If not, see <http://www.gnu.org/licenses/>.
25 */
26
27 #include <sdbus-c++/Message.h>
28 #include <sdbus-c++/Types.h>
29 #include <sdbus-c++/Error.h>
30 #include "MessageUtils.h"
31 #include "ISdBus.h"
32 #include "IConnection.h"
33 #include "ScopeGuard.h"
34 #include <basu/sd-bus.h>
35 #include <cassert>
36
37 namespace sdbus {
38
Message(internal::ISdBus * sdbus)39 Message::Message(internal::ISdBus* sdbus) noexcept
40 : sdbus_(sdbus)
41 {
42 assert(sdbus_ != nullptr);
43 }
44
Message(void * msg,internal::ISdBus * sdbus)45 Message::Message(void *msg, internal::ISdBus* sdbus) noexcept
46 : msg_(msg)
47 , sdbus_(sdbus)
48 {
49 assert(msg_ != nullptr);
50 assert(sdbus_ != nullptr);
51 sdbus_->sd_bus_message_ref((sd_bus_message*)msg_);
52 }
53
Message(void * msg,internal::ISdBus * sdbus,adopt_message_t)54 Message::Message(void *msg, internal::ISdBus* sdbus, adopt_message_t) noexcept
55 : msg_(msg)
56 , sdbus_(sdbus)
57 {
58 assert(msg_ != nullptr);
59 assert(sdbus_ != nullptr);
60 }
61
Message(const Message & other)62 Message::Message(const Message& other) noexcept
63 {
64 *this = other;
65 }
66
operator =(const Message & other)67 Message& Message::operator=(const Message& other) noexcept
68 {
69 if (msg_)
70 sdbus_->sd_bus_message_unref((sd_bus_message*)msg_);
71
72 msg_ = other.msg_;
73 sdbus_ = other.sdbus_;
74 ok_ = other.ok_;
75
76 sdbus_->sd_bus_message_ref((sd_bus_message*)msg_);
77
78 return *this;
79 }
80
Message(Message && other)81 Message::Message(Message&& other) noexcept
82 {
83 *this = std::move(other);
84 }
85
operator =(Message && other)86 Message& Message::operator=(Message&& other) noexcept
87 {
88 if (msg_)
89 sdbus_->sd_bus_message_unref((sd_bus_message*)msg_);
90
91 msg_ = other.msg_;
92 other.msg_ = nullptr;
93 sdbus_ = other.sdbus_;
94 other.sdbus_ = nullptr;
95 ok_ = other.ok_;
96 other.ok_ = true;
97
98 return *this;
99 }
100
~Message()101 Message::~Message()
102 {
103 if (msg_)
104 sdbus_->sd_bus_message_unref((sd_bus_message*)msg_);
105 }
106
operator <<(bool item)107 Message& Message::operator<<(bool item)
108 {
109 int intItem = item;
110
111 auto r = sd_bus_message_append_basic((sd_bus_message*)msg_, SD_BUS_TYPE_BOOLEAN, &intItem);
112 SDBUS_THROW_ERROR_IF(r < 0, "Failed to serialize a bool value", -r);
113
114 return *this;
115 }
116
operator <<(int16_t item)117 Message& Message::operator<<(int16_t item)
118 {
119 auto r = sd_bus_message_append_basic((sd_bus_message*)msg_, SD_BUS_TYPE_INT16, &item);
120 SDBUS_THROW_ERROR_IF(r < 0, "Failed to serialize a int16_t value", -r);
121
122 return *this;
123 }
124
operator <<(int32_t item)125 Message& Message::operator<<(int32_t item)
126 {
127 auto r = sd_bus_message_append_basic((sd_bus_message*)msg_, SD_BUS_TYPE_INT32, &item);
128 SDBUS_THROW_ERROR_IF(r < 0, "Failed to serialize a int32_t value", -r);
129
130 return *this;
131 }
132
operator <<(int64_t item)133 Message& Message::operator<<(int64_t item)
134 {
135 auto r = sd_bus_message_append_basic((sd_bus_message*)msg_, SD_BUS_TYPE_INT64, &item);
136 SDBUS_THROW_ERROR_IF(r < 0, "Failed to serialize a int64_t value", -r);
137
138 return *this;
139 }
140
operator <<(uint8_t item)141 Message& Message::operator<<(uint8_t item)
142 {
143 auto r = sd_bus_message_append_basic((sd_bus_message*)msg_, SD_BUS_TYPE_BYTE, &item);
144 SDBUS_THROW_ERROR_IF(r < 0, "Failed to serialize a byte value", -r);
145
146 return *this;
147 }
148
operator <<(uint16_t item)149 Message& Message::operator<<(uint16_t item)
150 {
151 auto r = sd_bus_message_append_basic((sd_bus_message*)msg_, SD_BUS_TYPE_UINT16, &item);
152 SDBUS_THROW_ERROR_IF(r < 0, "Failed to serialize a uint16_t value", -r);
153
154 return *this;
155 }
156
operator <<(uint32_t item)157 Message& Message::operator<<(uint32_t item)
158 {
159 auto r = sd_bus_message_append_basic((sd_bus_message*)msg_, SD_BUS_TYPE_UINT32, &item);
160 SDBUS_THROW_ERROR_IF(r < 0, "Failed to serialize a uint32_t value", -r);
161
162 return *this;
163 }
164
operator <<(uint64_t item)165 Message& Message::operator<<(uint64_t item)
166 {
167 auto r = sd_bus_message_append_basic((sd_bus_message*)msg_, SD_BUS_TYPE_UINT64, &item);
168 SDBUS_THROW_ERROR_IF(r < 0, "Failed to serialize a uint64_t value", -r);
169
170 return *this;
171 }
172
operator <<(double item)173 Message& Message::operator<<(double item)
174 {
175 auto r = sd_bus_message_append_basic((sd_bus_message*)msg_, SD_BUS_TYPE_DOUBLE, &item);
176 SDBUS_THROW_ERROR_IF(r < 0, "Failed to serialize a double value", -r);
177
178 return *this;
179 }
180
operator <<(const char * item)181 Message& Message::operator<<(const char* item)
182 {
183 auto r = sd_bus_message_append_basic((sd_bus_message*)msg_, SD_BUS_TYPE_STRING, item);
184 SDBUS_THROW_ERROR_IF(r < 0, "Failed to serialize a C-string value", -r);
185
186 return *this;
187 }
188
operator <<(const std::string & item)189 Message& Message::operator<<(const std::string& item)
190 {
191 auto r = sd_bus_message_append_basic((sd_bus_message*)msg_, SD_BUS_TYPE_STRING, item.c_str());
192 SDBUS_THROW_ERROR_IF(r < 0, "Failed to serialize a string value", -r);
193
194 return *this;
195 }
196
operator <<(const Variant & item)197 Message& Message::operator<<(const Variant &item)
198 {
199 item.serializeTo(*this);
200
201 return *this;
202 }
203
operator <<(const ObjectPath & item)204 Message& Message::operator<<(const ObjectPath &item)
205 {
206 auto r = sd_bus_message_append_basic((sd_bus_message*)msg_, SD_BUS_TYPE_OBJECT_PATH, item.c_str());
207 SDBUS_THROW_ERROR_IF(r < 0, "Failed to serialize an ObjectPath value", -r);
208
209 return *this;
210 }
211
operator <<(const Signature & item)212 Message& Message::operator<<(const Signature &item)
213 {
214 auto r = sd_bus_message_append_basic((sd_bus_message*)msg_, SD_BUS_TYPE_SIGNATURE, item.c_str());
215 SDBUS_THROW_ERROR_IF(r < 0, "Failed to serialize a Signature value", -r);
216
217 return *this;
218 }
219
operator <<(const UnixFd & item)220 Message& Message::operator<<(const UnixFd &item)
221 {
222 auto fd = item.get();
223 auto r = sd_bus_message_append_basic((sd_bus_message*)msg_, SD_BUS_TYPE_UNIX_FD, &fd);
224 SDBUS_THROW_ERROR_IF(r < 0, "Failed to serialize a UnixFd value", -r);
225
226 return *this;
227 }
228
229
operator >>(bool & item)230 Message& Message::operator>>(bool& item)
231 {
232 int intItem;
233 auto r = sd_bus_message_read_basic((sd_bus_message*)msg_, SD_BUS_TYPE_BOOLEAN, &intItem);
234 if (r == 0)
235 ok_ = false;
236
237 SDBUS_THROW_ERROR_IF(r < 0, "Failed to deserialize a bool value", -r);
238
239 item = static_cast<bool>(intItem);
240
241 return *this;
242 }
243
operator >>(int16_t & item)244 Message& Message::operator>>(int16_t& item)
245 {
246 auto r = sd_bus_message_read_basic((sd_bus_message*)msg_, SD_BUS_TYPE_INT16, &item);
247 if (r == 0)
248 ok_ = false;
249
250 SDBUS_THROW_ERROR_IF(r < 0, "Failed to deserialize a int16_t value", -r);
251
252 return *this;
253 }
254
operator >>(int32_t & item)255 Message& Message::operator>>(int32_t& item)
256 {
257 auto r = sd_bus_message_read_basic((sd_bus_message*)msg_, SD_BUS_TYPE_INT32, &item);
258 if (r == 0)
259 ok_ = false;
260
261 SDBUS_THROW_ERROR_IF(r < 0, "Failed to deserialize a int32_t value", -r);
262
263 return *this;
264 }
265
operator >>(int64_t & item)266 Message& Message::operator>>(int64_t& item)
267 {
268 auto r = sd_bus_message_read_basic((sd_bus_message*)msg_, SD_BUS_TYPE_INT64, &item);
269 if (r == 0)
270 ok_ = false;
271
272 SDBUS_THROW_ERROR_IF(r < 0, "Failed to deserialize a bool value", -r);
273
274 return *this;
275 }
276
operator >>(uint8_t & item)277 Message& Message::operator>>(uint8_t& item)
278 {
279 auto r = sd_bus_message_read_basic((sd_bus_message*)msg_, SD_BUS_TYPE_BYTE, &item);
280 if (r == 0)
281 ok_ = false;
282
283 SDBUS_THROW_ERROR_IF(r < 0, "Failed to deserialize a byte value", -r);
284
285 return *this;
286 }
287
operator >>(uint16_t & item)288 Message& Message::operator>>(uint16_t& item)
289 {
290 auto r = sd_bus_message_read_basic((sd_bus_message*)msg_, SD_BUS_TYPE_UINT16, &item);
291 if (r == 0)
292 ok_ = false;
293
294 SDBUS_THROW_ERROR_IF(r < 0, "Failed to deserialize a uint16_t value", -r);
295
296 return *this;
297 }
298
operator >>(uint32_t & item)299 Message& Message::operator>>(uint32_t& item)
300 {
301 auto r = sd_bus_message_read_basic((sd_bus_message*)msg_, SD_BUS_TYPE_UINT32, &item);
302 if (r == 0)
303 ok_ = false;
304
305 SDBUS_THROW_ERROR_IF(r < 0, "Failed to deserialize a uint32_t value", -r);
306
307 return *this;
308 }
309
operator >>(uint64_t & item)310 Message& Message::operator>>(uint64_t& item)
311 {
312 auto r = sd_bus_message_read_basic((sd_bus_message*)msg_, SD_BUS_TYPE_UINT64, &item);
313 if (r == 0)
314 ok_ = false;
315
316 SDBUS_THROW_ERROR_IF(r < 0, "Failed to deserialize a uint64_t value", -r);
317
318 return *this;
319 }
320
operator >>(double & item)321 Message& Message::operator>>(double& item)
322 {
323 auto r = sd_bus_message_read_basic((sd_bus_message*)msg_, SD_BUS_TYPE_DOUBLE, &item);
324 if (r == 0)
325 ok_ = false;
326
327 SDBUS_THROW_ERROR_IF(r < 0, "Failed to deserialize a double value", -r);
328
329 return *this;
330 }
331
operator >>(char * & item)332 Message& Message::operator>>(char*& item)
333 {
334 auto r = sd_bus_message_read_basic((sd_bus_message*)msg_, SD_BUS_TYPE_STRING, &item);
335 if (r == 0)
336 ok_ = false;
337
338 SDBUS_THROW_ERROR_IF(r < 0, "Failed to deserialize a string value", -r);
339
340 return *this;
341 }
342
operator >>(std::string & item)343 Message& Message::operator>>(std::string& item)
344 {
345 char* str{};
346 (*this) >> str;
347
348 if (str != nullptr)
349 item = str;
350
351 return *this;
352 }
353
operator >>(Variant & item)354 Message& Message::operator>>(Variant &item)
355 {
356 item.deserializeFrom(*this);
357
358 // Empty variant is normally prohibited. Users cannot send empty variants.
359 // Therefore in this context an empty variant means that we are at the end
360 // of deserializing a container, and thus we shall set ok_ flag to false.
361 if (item.isEmpty())
362 ok_ = false;
363
364 return *this;
365 }
366
operator >>(ObjectPath & item)367 Message& Message::operator>>(ObjectPath &item)
368 {
369 char* str{};
370 auto r = sd_bus_message_read_basic((sd_bus_message*)msg_, SD_BUS_TYPE_OBJECT_PATH, &str);
371 if (r == 0)
372 ok_ = false;
373
374 SDBUS_THROW_ERROR_IF(r < 0, "Failed to deserialize an ObjectPath value", -r);
375
376 if (str != nullptr)
377 item = str;
378
379 return *this;
380 }
381
operator >>(Signature & item)382 Message& Message::operator>>(Signature &item)
383 {
384 char* str{};
385 auto r = sd_bus_message_read_basic((sd_bus_message*)msg_, SD_BUS_TYPE_SIGNATURE, &str);
386 if (r == 0)
387 ok_ = false;
388
389 SDBUS_THROW_ERROR_IF(r < 0, "Failed to deserialize a Signature value", -r);
390
391 if (str != nullptr)
392 item = str;
393
394 return *this;
395 }
396
operator >>(UnixFd & item)397 Message& Message::operator>>(UnixFd &item)
398 {
399 int fd = -1;
400 auto r = sd_bus_message_read_basic((sd_bus_message*)msg_, SD_BUS_TYPE_UNIX_FD, &fd);
401 if (r == 0)
402 ok_ = false;
403
404 SDBUS_THROW_ERROR_IF(r < 0, "Failed to deserialize a UnixFd value", -r);
405
406 item.reset(fd);
407
408 return *this;
409 }
410
411
openContainer(const std::string & signature)412 Message& Message::openContainer(const std::string& signature)
413 {
414 auto r = sd_bus_message_open_container((sd_bus_message*)msg_, SD_BUS_TYPE_ARRAY, signature.c_str());
415 SDBUS_THROW_ERROR_IF(r < 0, "Failed to open a container", -r);
416
417 return *this;
418 }
419
closeContainer()420 Message& Message::closeContainer()
421 {
422 auto r = sd_bus_message_close_container((sd_bus_message*)msg_);
423 SDBUS_THROW_ERROR_IF(r < 0, "Failed to close a container", -r);
424
425 return *this;
426 }
427
openDictEntry(const std::string & signature)428 Message& Message::openDictEntry(const std::string& signature)
429 {
430 auto r = sd_bus_message_open_container((sd_bus_message*)msg_, SD_BUS_TYPE_DICT_ENTRY, signature.c_str());
431 SDBUS_THROW_ERROR_IF(r < 0, "Failed to open a dictionary entry", -r);
432
433 return *this;
434 }
435
closeDictEntry()436 Message& Message::closeDictEntry()
437 {
438 auto r = sd_bus_message_close_container((sd_bus_message*)msg_);
439 SDBUS_THROW_ERROR_IF(r < 0, "Failed to close a dictionary entry", -r);
440
441 return *this;
442 }
443
openVariant(const std::string & signature)444 Message& Message::openVariant(const std::string& signature)
445 {
446 auto r = sd_bus_message_open_container((sd_bus_message*)msg_, SD_BUS_TYPE_VARIANT, signature.c_str());
447 SDBUS_THROW_ERROR_IF(r < 0, "Failed to open a variant", -r);
448
449 return *this;
450 }
451
closeVariant()452 Message& Message::closeVariant()
453 {
454 auto r = sd_bus_message_close_container((sd_bus_message*)msg_);
455 SDBUS_THROW_ERROR_IF(r < 0, "Failed to close a variant", -r);
456
457 return *this;
458 }
459
openStruct(const std::string & signature)460 Message& Message::openStruct(const std::string& signature)
461 {
462 auto r = sd_bus_message_open_container((sd_bus_message*)msg_, SD_BUS_TYPE_STRUCT, signature.c_str());
463 SDBUS_THROW_ERROR_IF(r < 0, "Failed to open a struct", -r);
464
465 return *this;
466 }
467
closeStruct()468 Message& Message::closeStruct()
469 {
470 auto r = sd_bus_message_close_container((sd_bus_message*)msg_);
471 SDBUS_THROW_ERROR_IF(r < 0, "Failed to close a struct", -r);
472
473 return *this;
474 }
475
476
enterContainer(const std::string & signature)477 Message& Message::enterContainer(const std::string& signature)
478 {
479 auto r = sd_bus_message_enter_container((sd_bus_message*)msg_, SD_BUS_TYPE_ARRAY, signature.c_str());
480 if (r == 0)
481 ok_ = false;
482
483 SDBUS_THROW_ERROR_IF(r < 0, "Failed to enter a container", -r);
484
485 return *this;
486 }
487
exitContainer()488 Message& Message::exitContainer()
489 {
490 auto r = sd_bus_message_exit_container((sd_bus_message*)msg_);
491 SDBUS_THROW_ERROR_IF(r < 0, "Failed to exit a container", -r);
492
493 return *this;
494 }
495
enterDictEntry(const std::string & signature)496 Message& Message::enterDictEntry(const std::string& signature)
497 {
498 auto r = sd_bus_message_enter_container((sd_bus_message*)msg_, SD_BUS_TYPE_DICT_ENTRY, signature.c_str());
499 if (r == 0)
500 ok_ = false;
501
502 SDBUS_THROW_ERROR_IF(r < 0, "Failed to enter a dictionary entry", -r);
503
504 return *this;
505 }
506
exitDictEntry()507 Message& Message::exitDictEntry()
508 {
509 auto r = sd_bus_message_exit_container((sd_bus_message*)msg_);
510 SDBUS_THROW_ERROR_IF(r < 0, "Failed to exit a dictionary entry", -r);
511
512 return *this;
513 }
514
enterVariant(const std::string & signature)515 Message& Message::enterVariant(const std::string& signature)
516 {
517 auto r = sd_bus_message_enter_container((sd_bus_message*)msg_, SD_BUS_TYPE_VARIANT, signature.c_str());
518 if (r == 0)
519 ok_ = false;
520
521 SDBUS_THROW_ERROR_IF(r < 0, "Failed to enter a variant", -r);
522
523 return *this;
524 }
525
exitVariant()526 Message& Message::exitVariant()
527 {
528 auto r = sd_bus_message_exit_container((sd_bus_message*)msg_);
529 SDBUS_THROW_ERROR_IF(r < 0, "Failed to exit a variant", -r);
530
531 return *this;
532 }
533
enterStruct(const std::string & signature)534 Message& Message::enterStruct(const std::string& signature)
535 {
536 auto r = sd_bus_message_enter_container((sd_bus_message*)msg_, SD_BUS_TYPE_STRUCT, signature.c_str());
537 if (r == 0)
538 ok_ = false;
539
540 SDBUS_THROW_ERROR_IF(r < 0, "Failed to enter a struct", -r);
541
542 return *this;
543 }
544
exitStruct()545 Message& Message::exitStruct()
546 {
547 auto r = sd_bus_message_exit_container((sd_bus_message*)msg_);
548 SDBUS_THROW_ERROR_IF(r < 0, "Failed to exit a struct", -r);
549
550 return *this;
551 }
552
553
operator bool() const554 Message::operator bool() const
555 {
556 return ok_;
557 }
558
clearFlags()559 void Message::clearFlags()
560 {
561 ok_ = true;
562 }
563
copyTo(Message & destination,bool complete) const564 void Message::copyTo(Message& destination, bool complete) const
565 {
566 auto r = sd_bus_message_copy((sd_bus_message*)destination.msg_, (sd_bus_message*)msg_, complete);
567 SDBUS_THROW_ERROR_IF(r < 0, "Failed to copy the message", -r);
568 }
569
seal()570 void Message::seal()
571 {
572 const auto messageCookie = 1;
573 const auto sealTimeout = 0;
574 auto r = sd_bus_message_seal((sd_bus_message*)msg_, messageCookie, sealTimeout);
575 SDBUS_THROW_ERROR_IF(r < 0, "Failed to seal the message", -r);
576 }
577
rewind(bool complete)578 void Message::rewind(bool complete)
579 {
580 auto r = sd_bus_message_rewind((sd_bus_message*)msg_, complete);
581 SDBUS_THROW_ERROR_IF(r < 0, "Failed to rewind the message", -r);
582 }
583
getInterfaceName() const584 std::string Message::getInterfaceName() const
585 {
586 auto interface = sd_bus_message_get_interface((sd_bus_message*)msg_);
587 return interface != nullptr ? interface : "";
588 }
589
getMemberName() const590 std::string Message::getMemberName() const
591 {
592 auto member = sd_bus_message_get_member((sd_bus_message*)msg_);
593 return member != nullptr ? member : "";
594 }
595
getSender() const596 std::string Message::getSender() const
597 {
598 return sd_bus_message_get_sender((sd_bus_message*)msg_);
599 }
600
getPath() const601 std::string Message::getPath() const
602 {
603 auto path = sd_bus_message_get_path((sd_bus_message*)msg_);
604 return path != nullptr ? path : "";
605 }
606
getDestination() const607 std::string Message::getDestination() const
608 {
609 auto destination = sd_bus_message_get_destination((sd_bus_message*)msg_);
610 return destination != nullptr ? destination : "";
611 }
612
peekType(std::string & type,std::string & contents) const613 void Message::peekType(std::string& type, std::string& contents) const
614 {
615 char typeSig;
616 const char* contentsSig;
617 auto r = sd_bus_message_peek_type((sd_bus_message*)msg_, &typeSig, &contentsSig);
618 SDBUS_THROW_ERROR_IF(r < 0, "Failed to peek message type", -r);
619 type = typeSig;
620 contents = contentsSig ? contentsSig : "";
621 }
622
isValid() const623 bool Message::isValid() const
624 {
625 return msg_ != nullptr && sdbus_ != nullptr;
626 }
627
isEmpty() const628 bool Message::isEmpty() const
629 {
630 return sd_bus_message_is_empty((sd_bus_message*)msg_) != 0;
631 }
632
getCredsPid() const633 pid_t Message::getCredsPid() const
634 {
635 uint64_t mask = SD_BUS_CREDS_PID | SD_BUS_CREDS_AUGMENT;
636 sd_bus_creds *creds = nullptr;
637 SCOPE_EXIT{ sdbus_->sd_bus_creds_unref(creds); };
638
639 int r = sdbus_->sd_bus_query_sender_creds((sd_bus_message*)msg_, mask, &creds);
640 SDBUS_THROW_ERROR_IF(r < 0, "Failed to get bus creds", -r);
641
642 pid_t pid = 0;
643 r = sdbus_->sd_bus_creds_get_pid(creds, &pid);
644 SDBUS_THROW_ERROR_IF(r < 0, "Failed to get bus cred pid", -r);
645 return pid;
646 }
647
getCredsUid() const648 uid_t Message::getCredsUid() const
649 {
650 uint64_t mask = SD_BUS_CREDS_UID | SD_BUS_CREDS_AUGMENT;
651 sd_bus_creds *creds = nullptr;
652 SCOPE_EXIT{ sdbus_->sd_bus_creds_unref(creds); };
653 int r = sdbus_->sd_bus_query_sender_creds((sd_bus_message*)msg_, mask, &creds);
654 SDBUS_THROW_ERROR_IF(r < 0, "Failed to get bus creds", -r);
655
656 uid_t uid = (uid_t)-1;
657 r = sdbus_->sd_bus_creds_get_uid(creds, &uid);
658 SDBUS_THROW_ERROR_IF(r < 0, "Failed to get bus cred uid", -r);
659 return uid;
660 }
661
getCredsEuid() const662 uid_t Message::getCredsEuid() const
663 {
664 uint64_t mask = SD_BUS_CREDS_EUID | SD_BUS_CREDS_AUGMENT;
665 sd_bus_creds *creds = nullptr;
666 SCOPE_EXIT{ sdbus_->sd_bus_creds_unref(creds); };
667 int r = sdbus_->sd_bus_query_sender_creds((sd_bus_message*)msg_, mask, &creds);
668 SDBUS_THROW_ERROR_IF(r < 0, "Failed to get bus creds", -r);
669
670 uid_t euid = (uid_t)-1;
671 r = sdbus_->sd_bus_creds_get_euid(creds, &euid);
672 SDBUS_THROW_ERROR_IF(r < 0, "Failed to get bus cred euid", -r);
673 return euid;
674 }
675
getCredsGid() const676 gid_t Message::getCredsGid() const
677 {
678 uint64_t mask = SD_BUS_CREDS_GID | SD_BUS_CREDS_AUGMENT;
679 sd_bus_creds *creds = nullptr;
680 SCOPE_EXIT{ sdbus_->sd_bus_creds_unref(creds); };
681 int r = sdbus_->sd_bus_query_sender_creds((sd_bus_message*)msg_, mask, &creds);
682 SDBUS_THROW_ERROR_IF(r < 0, "Failed to get bus creds", -r);
683
684 gid_t gid = (gid_t)-1;
685 r = sdbus_->sd_bus_creds_get_gid(creds, &gid);
686 SDBUS_THROW_ERROR_IF(r < 0, "Failed to get bus cred gid", -r);
687 return gid;
688 }
689
getCredsEgid() const690 gid_t Message::getCredsEgid() const
691 {
692 uint64_t mask = SD_BUS_CREDS_EGID | SD_BUS_CREDS_AUGMENT;
693 sd_bus_creds *creds = nullptr;
694 SCOPE_EXIT{ sdbus_->sd_bus_creds_unref(creds); };
695 int r = sdbus_->sd_bus_query_sender_creds((sd_bus_message*)msg_, mask, &creds);
696 SDBUS_THROW_ERROR_IF(r < 0, "Failed to get bus creds", -r);
697
698 gid_t egid = (gid_t)-1;
699 r = sdbus_->sd_bus_creds_get_egid(creds, &egid);
700 SDBUS_THROW_ERROR_IF(r < 0, "Failed to get bus cred egid", -r);
701 return egid;
702 }
703
getCredsSupplementaryGids() const704 std::vector<gid_t> Message::getCredsSupplementaryGids() const
705 {
706 uint64_t mask = SD_BUS_CREDS_SUPPLEMENTARY_GIDS | SD_BUS_CREDS_AUGMENT;
707 sd_bus_creds *creds = nullptr;
708 SCOPE_EXIT{ sdbus_->sd_bus_creds_unref(creds); };
709 int r = sdbus_->sd_bus_query_sender_creds((sd_bus_message*)msg_, mask, &creds);
710 SDBUS_THROW_ERROR_IF(r < 0, "Failed to get bus creds", -r);
711
712 const gid_t *cGids = nullptr;
713 r = sdbus_->sd_bus_creds_get_supplementary_gids(creds, &cGids);
714 SDBUS_THROW_ERROR_IF(r < 0, "Failed to get bus cred supplementary gids", -r);
715
716 std::vector<gid_t> gids{};
717 if (cGids != nullptr)
718 {
719 for (int i = 0; i < r; i++)
720 gids.push_back(cGids[i]);
721 }
722
723 return gids;
724 }
725
getSELinuxContext() const726 std::string Message::getSELinuxContext() const
727 {
728 uint64_t mask = SD_BUS_CREDS_AUGMENT | SD_BUS_CREDS_SELINUX_CONTEXT;
729 sd_bus_creds *creds = nullptr;
730 SCOPE_EXIT{ sdbus_->sd_bus_creds_unref(creds); };
731 int r = sdbus_->sd_bus_query_sender_creds((sd_bus_message*)msg_, mask, &creds);
732 SDBUS_THROW_ERROR_IF(r < 0, "Failed to get bus creds", -r);
733
734 const char *cLabel = nullptr;
735 r = sdbus_->sd_bus_creds_get_selinux_context(creds, &cLabel);
736 SDBUS_THROW_ERROR_IF(r < 0, "Failed to get bus cred selinux context", -r);
737 return cLabel;
738 }
739
740
MethodCall(void * msg,internal::ISdBus * sdbus,const internal::IConnection * connection,adopt_message_t)741 MethodCall::MethodCall( void *msg
742 , internal::ISdBus *sdbus
743 , const internal::IConnection *connection
744 , adopt_message_t) noexcept
745 : Message(msg, sdbus, adopt_message)
746 , connection_(connection)
747 {
748 assert(connection_ != nullptr);
749 }
750
dontExpectReply()751 void MethodCall::dontExpectReply()
752 {
753 auto r = sd_bus_message_set_expect_reply((sd_bus_message*)msg_, 0);
754 SDBUS_THROW_ERROR_IF(r < 0, "Failed to set the dont-expect-reply flag", -r);
755 }
756
doesntExpectReply() const757 bool MethodCall::doesntExpectReply() const
758 {
759 auto r = sd_bus_message_get_expect_reply((sd_bus_message*)msg_);
760 SDBUS_THROW_ERROR_IF(r < 0, "Failed to get the dont-expect-reply flag", -r);
761 return r == 0;
762 }
763
send(uint64_t timeout) const764 MethodReply MethodCall::send(uint64_t timeout) const
765 {
766 if (!doesntExpectReply())
767 return sendWithReply(timeout);
768 else
769 return sendWithNoReply();
770 }
771
sendWithReply(uint64_t timeout) const772 MethodReply MethodCall::sendWithReply(uint64_t timeout) const
773 {
774 sd_bus_error sdbusError = SD_BUS_ERROR_NULL;
775 SCOPE_EXIT{ sd_bus_error_free(&sdbusError); };
776
777 sd_bus_message* sdbusReply{};
778 auto r = sdbus_->sd_bus_call(nullptr, (sd_bus_message*)msg_, timeout, &sdbusError, &sdbusReply);
779
780 if (sd_bus_error_is_set(&sdbusError))
781 throw sdbus::Error(sdbusError.name, sdbusError.message);
782
783 SDBUS_THROW_ERROR_IF(r < 0, "Failed to call method", -r);
784
785 return Factory::create<MethodReply>(sdbusReply, sdbus_, adopt_message);
786 }
787
sendWithNoReply() const788 MethodReply MethodCall::sendWithNoReply() const
789 {
790 auto r = sdbus_->sd_bus_send(nullptr, (sd_bus_message*)msg_, nullptr);
791 SDBUS_THROW_ERROR_IF(r < 0, "Failed to call method with no reply", -r);
792
793 return Factory::create<MethodReply>(); // No reply
794 }
795
send(void * callback,void * userData,uint64_t timeout,dont_request_slot_t) const796 void MethodCall::send(void* callback, void* userData, uint64_t timeout, dont_request_slot_t) const
797 {
798 auto r = sdbus_->sd_bus_call_async(nullptr, nullptr, (sd_bus_message*)msg_, (sd_bus_message_handler_t)callback, userData, timeout);
799 SDBUS_THROW_ERROR_IF(r < 0, "Failed to call method", -r);
800
801 // Force event loop to re-enter polling with the async call timeout if that is less than the one used in current poll
802 SDBUS_THROW_ERROR_IF(connection_ == nullptr, "Invalid use of MethodCall API", ENOTSUP);
803 connection_->notifyEventLoopNewTimeout();
804 }
805
send(void * callback,void * userData,uint64_t timeout) const806 MethodCall::Slot MethodCall::send(void* callback, void* userData, uint64_t timeout) const
807 {
808 sd_bus_slot* slot;
809
810 auto r = sdbus_->sd_bus_call_async(nullptr, &slot, (sd_bus_message*)msg_, (sd_bus_message_handler_t)callback, userData, timeout);
811 SDBUS_THROW_ERROR_IF(r < 0, "Failed to call method asynchronously", -r);
812
813 // Force event loop to re-enter polling with the async call timeout if that is less than the one used in current poll
814 SDBUS_THROW_ERROR_IF(connection_ == nullptr, "Invalid use of MethodCall API", ENOTSUP);
815 connection_->notifyEventLoopNewTimeout();
816
817 return Slot{slot, [sdbus_ = sdbus_](void *slot){ sdbus_->sd_bus_slot_unref((sd_bus_slot*)slot); }};
818 }
819
createReply() const820 MethodReply MethodCall::createReply() const
821 {
822 sd_bus_message* sdbusReply{};
823 auto r = sdbus_->sd_bus_message_new_method_return((sd_bus_message*)msg_, &sdbusReply);
824 SDBUS_THROW_ERROR_IF(r < 0, "Failed to create method reply", -r);
825
826 return Factory::create<MethodReply>(sdbusReply, sdbus_, adopt_message);
827 }
828
createErrorReply(const Error & error) const829 MethodReply MethodCall::createErrorReply(const Error& error) const
830 {
831 sd_bus_error sdbusError = SD_BUS_ERROR_NULL;
832 SCOPE_EXIT{ sd_bus_error_free(&sdbusError); };
833 sd_bus_error_set(&sdbusError, error.getName().c_str(), error.getMessage().c_str());
834
835 sd_bus_message* sdbusErrorReply{};
836 auto r = sdbus_->sd_bus_message_new_method_error((sd_bus_message*)msg_, &sdbusErrorReply, &sdbusError);
837 SDBUS_THROW_ERROR_IF(r < 0, "Failed to create method error reply", -r);
838
839 return Factory::create<MethodReply>(sdbusErrorReply, sdbus_, adopt_message);
840 }
841
send() const842 void MethodReply::send() const
843 {
844 auto r = sdbus_->sd_bus_send(nullptr, (sd_bus_message*)msg_, nullptr);
845 SDBUS_THROW_ERROR_IF(r < 0, "Failed to send reply", -r);
846 }
847
send() const848 void Signal::send() const
849 {
850 auto r = sdbus_->sd_bus_send(nullptr, (sd_bus_message*)msg_, nullptr);
851 SDBUS_THROW_ERROR_IF(r < 0, "Failed to emit signal", -r);
852 }
853
setDestination(const std::string & destination)854 void Signal::setDestination(const std::string& destination)
855 {
856 auto r = sdbus_->sd_bus_message_set_destination((sd_bus_message*)msg_, destination.c_str());
857 SDBUS_THROW_ERROR_IF(r < 0, "Failed to set signal destination", -r);
858 }
859
createPlainMessage()860 PlainMessage createPlainMessage()
861 {
862 static auto connection = internal::createConnection();
863 return connection->createPlainMessage();
864 }
865
866
867 }
868