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