diff --git a/include/sdbus-c++/Message.h b/include/sdbus-c++/Message.h index 5f20257..fc834d3 100644 --- a/include/sdbus-c++/Message.h +++ b/include/sdbus-c++/Message.h @@ -43,6 +43,7 @@ namespace sdbus { class ObjectPath; class Signature; template class Struct; + struct UnixFd; class MethodReply; namespace internal { class ISdBus; @@ -100,6 +101,7 @@ namespace sdbus { Message& operator<<(const Variant &item); Message& operator<<(const ObjectPath &item); Message& operator<<(const Signature &item); + Message& operator<<(const UnixFd &item); Message& operator>>(bool& item); Message& operator>>(int16_t& item); @@ -115,6 +117,7 @@ namespace sdbus { Message& operator>>(Variant &item); Message& operator>>(ObjectPath &item); Message& operator>>(Signature &item); + Message& operator>>(UnixFd &item); Message& openContainer(const std::string& signature); Message& closeContainer(); diff --git a/include/sdbus-c++/TypeTraits.h b/include/sdbus-c++/TypeTraits.h index 47c3807..f7bde84 100644 --- a/include/sdbus-c++/TypeTraits.h +++ b/include/sdbus-c++/TypeTraits.h @@ -40,6 +40,7 @@ namespace sdbus { template class Struct; class ObjectPath; class Signature; + struct UnixFd; class Message; class MethodCall; class MethodReply; @@ -285,6 +286,17 @@ namespace sdbus { } }; + template <> + struct signature_of + { + static constexpr bool is_valid = true; + + static const std::string str() + { + return "h"; + } + }; + template struct signature_of> { diff --git a/include/sdbus-c++/Types.h b/include/sdbus-c++/Types.h index b6e755c..fe19f81 100644 --- a/include/sdbus-c++/Types.h +++ b/include/sdbus-c++/Types.h @@ -97,6 +97,12 @@ namespace sdbus { mutable Message msg_{}; }; + /********************************************//** + * @class Struct + * + * Representation of struct D-Bus type + * + ***********************************************/ template class Struct : public std::tuple<_ValueTypes...> @@ -135,6 +141,12 @@ namespace sdbus { return result_type(std::forward<_Elements>(args)...); } + /********************************************//** + * @class ObjectPath + * + * Representation of object path D-Bus type + * + ***********************************************/ class ObjectPath : public std::string { public: @@ -146,6 +158,12 @@ namespace sdbus { using std::string::operator=; }; + /********************************************//** + * @class Signature + * + * Representation of Signature D-Bus type + * + ***********************************************/ class Signature : public std::string { public: @@ -157,6 +175,27 @@ namespace sdbus { using std::string::operator=; }; + /********************************************//** + * @struct UnixFd + * + * Representation of Unix file descriptor D-Bus type + * + ***********************************************/ + struct UnixFd + { + int fd_ = -1; + + UnixFd() = default; + UnixFd(int fd) + : fd_(fd) + {} + + operator int() const + { + return fd_; + } + }; + } #endif /* SDBUS_CXX_TYPES_H_ */ diff --git a/src/Message.cpp b/src/Message.cpp index 2a7294d..f4c11d2 100644 --- a/src/Message.cpp +++ b/src/Message.cpp @@ -210,7 +210,15 @@ Message& Message::operator<<(const ObjectPath &item) Message& Message::operator<<(const Signature &item) { auto r = sd_bus_message_append_basic((sd_bus_message*)msg_, SD_BUS_TYPE_SIGNATURE, item.c_str()); - SDBUS_THROW_ERROR_IF(r < 0, "Failed to serialize an Signature value", -r); + SDBUS_THROW_ERROR_IF(r < 0, "Failed to serialize a Signature value", -r); + + return *this; +} + +Message& Message::operator<<(const UnixFd &item) +{ + auto r = sd_bus_message_append_basic((sd_bus_message*)msg_, SD_BUS_TYPE_UNIX_FD, &item.fd_); + SDBUS_THROW_ERROR_IF(r < 0, "Failed to serialize a UnixFd value", -r); return *this; } @@ -383,6 +391,17 @@ Message& Message::operator>>(Signature &item) return *this; } +Message& Message::operator>>(UnixFd &item) +{ + auto r = sd_bus_message_read_basic((sd_bus_message*)msg_, SD_BUS_TYPE_UNIX_FD, &item.fd_); + if (r == 0) + ok_ = false; + + SDBUS_THROW_ERROR_IF(r < 0, "Failed to deserialize a UnixFd value", -r); + + return *this; +} + Message& Message::openContainer(const std::string& signature) { diff --git a/tests/integrationtests/AdaptorAndProxy_test.cpp b/tests/integrationtests/AdaptorAndProxy_test.cpp index 815c4c1..e682b0d 100644 --- a/tests/integrationtests/AdaptorAndProxy_test.cpp +++ b/tests/integrationtests/AdaptorAndProxy_test.cpp @@ -209,6 +209,12 @@ TEST_F(SdbusTestObject, CallsMethodWithObjectPathSuccesfully) ASSERT_THAT(resObjectPath, Eq(OBJECT_PATH_VALUE)); } +TEST_F(SdbusTestObject, CallsMethodWithUnixFdSuccesfully) +{ + auto resUnixFd = m_proxy->getUnixFd(); + ASSERT_THAT(resUnixFd, Gt(UNIX_FD_VALUE)); +} + TEST_F(SdbusTestObject, CallsMethodWithComplexTypeSuccesfully) { auto resComplex = m_proxy->getComplex(); diff --git a/tests/integrationtests/TestingAdaptor.h b/tests/integrationtests/TestingAdaptor.h index f518e91..311409b 100644 --- a/tests/integrationtests/TestingAdaptor.h +++ b/tests/integrationtests/TestingAdaptor.h @@ -157,6 +157,10 @@ protected: { return OBJECT_PATH_VALUE; } + sdbus::UnixFd getUnixFd() const + { + return UNIX_FD_VALUE; + } ComplexType getComplex() const { diff --git a/tests/integrationtests/adaptor-glue.h b/tests/integrationtests/adaptor-glue.h index 63a09cc..b882c3b 100644 --- a/tests/integrationtests/adaptor-glue.h +++ b/tests/integrationtests/adaptor-glue.h @@ -97,6 +97,7 @@ protected: object_.registerMethod("getSignature").onInterface(INTERFACE_NAME).implementedAs([this](){ return this->getSignature(); }); object_.registerMethod("getObjectPath").onInterface(INTERFACE_NAME).implementedAs([this](){ return this->getObjectPath(); }); + object_.registerMethod("getUnixFd").onInterface(INTERFACE_NAME).implementedAs([this](){ return this->getUnixFd(); }); object_.registerMethod("getComplex").onInterface(INTERFACE_NAME).implementedAs([this](){ return this->getComplex(); }).markAsDeprecated(); @@ -163,6 +164,7 @@ protected: virtual void doOperationAsync(uint32_t param, sdbus::Result result) = 0; virtual sdbus::Signature getSignature() const = 0; virtual sdbus::ObjectPath getObjectPath() const = 0; + virtual sdbus::UnixFd getUnixFd() const = 0; virtual ComplexType getComplex() const = 0; virtual void throwError() const = 0; @@ -266,6 +268,9 @@ R"delimiter( + + + diff --git a/tests/integrationtests/defs.h b/tests/integrationtests/defs.h index 304678e..3cdf8b7 100644 --- a/tests/integrationtests/defs.h +++ b/tests/integrationtests/defs.h @@ -40,6 +40,7 @@ constexpr const int32_t INT64_VALUE{-1024}; const std::string STRING_VALUE{"sdbus-c++-testing"}; const sdbus::Signature SIGNATURE_VALUE{"a{is}"}; const sdbus::ObjectPath OBJECT_PATH_VALUE{"/"}; +const int UNIX_FD_VALUE = 0; const std::string DEFAULT_STATE_VALUE{"default-state-value"}; const uint32_t DEFAULT_ACTION_VALUE{999}; diff --git a/tests/integrationtests/proxy-glue.h b/tests/integrationtests/proxy-glue.h index 1c8971b..e2e4bcb 100644 --- a/tests/integrationtests/proxy-glue.h +++ b/tests/integrationtests/proxy-glue.h @@ -175,6 +175,13 @@ public: return result; } + sdbus::UnixFd getUnixFd() + { + sdbus::UnixFd result; + object_.callMethod("getUnixFd").onInterface(INTERFACE_NAME).storeResultsTo(result); + return result; + } + ComplexType getComplex() { ComplexType result; diff --git a/tests/unittests/Message_test.cpp b/tests/unittests/Message_test.cpp index 91a94d6..8d96d7e 100644 --- a/tests/unittests/Message_test.cpp +++ b/tests/unittests/Message_test.cpp @@ -30,6 +30,7 @@ #include using ::testing::Eq; +using ::testing::Gt; using ::testing::DoubleEq; using namespace std::string_literals; @@ -125,6 +126,21 @@ TEST(AMessage, CanCarryASimpleInteger) ASSERT_THAT(dataRead, Eq(dataWritten)); } +TEST(AMessage, CanCarryAUnixFd) +{ + sdbus::Message msg{sdbus::createPlainMessage()}; + + sdbus::UnixFd dataWritten = 0; + msg << dataWritten; + + msg.seal(); + + sdbus::UnixFd dataRead; + msg >> dataRead; + + ASSERT_THAT(dataRead, Gt(dataWritten)); +} + TEST(AMessage, CanCarryAVariant) { sdbus::Message msg{sdbus::createPlainMessage()}; diff --git a/tests/unittests/TypeTraits_test.cpp b/tests/unittests/TypeTraits_test.cpp index db95db0..3dabad2 100644 --- a/tests/unittests/TypeTraits_test.cpp +++ b/tests/unittests/TypeTraits_test.cpp @@ -72,6 +72,7 @@ namespace TYPE(sdbus::ObjectPath)HAS_DBUS_TYPE_SIGNATURE("o") TYPE(sdbus::Signature)HAS_DBUS_TYPE_SIGNATURE("g") TYPE(sdbus::Variant)HAS_DBUS_TYPE_SIGNATURE("v") + TYPE(sdbus::UnixFd)HAS_DBUS_TYPE_SIGNATURE("h") TYPE(sdbus::Struct)HAS_DBUS_TYPE_SIGNATURE("(b)") TYPE(sdbus::Struct)HAS_DBUS_TYPE_SIGNATURE("(qdsv)") TYPE(std::vector)HAS_DBUS_TYPE_SIGNATURE("an") @@ -91,10 +92,11 @@ namespace > >, sdbus::Signature, + sdbus::UnixFd, const char* > >; - TYPE(ComplexType)HAS_DBUS_TYPE_SIGNATURE("a{t(a{ya(obva{is})}gs)}") + TYPE(ComplexType)HAS_DBUS_TYPE_SIGNATURE("a{t(a{ya(obva{is})}ghs)}") typedef ::testing::Types< bool , uint8_t @@ -110,6 +112,7 @@ namespace , sdbus::ObjectPath , sdbus::Signature , sdbus::Variant + , sdbus::UnixFd , sdbus::Struct , sdbus::Struct , std::vector diff --git a/tests/unittests/Types_test.cpp b/tests/unittests/Types_test.cpp index 8928995..77301c3 100644 --- a/tests/unittests/Types_test.cpp +++ b/tests/unittests/Types_test.cpp @@ -240,3 +240,10 @@ TEST(ASignature, CanBeConstructedFromStdString) ASSERT_THAT(sdbus::Signature{aSignature}, Eq(aSignature)); } + +TEST(AUnixFd, CanBeConstructedFromInt) +{ + int fd{2}; + + ASSERT_THAT((int)sdbus::UnixFd{fd}, Eq(fd)); +} diff --git a/tools/xml2cpp-codegen/generator_utils.cpp b/tools/xml2cpp-codegen/generator_utils.cpp index 27eccb5..cb8a403 100644 --- a/tools/xml2cpp-codegen/generator_utils.cpp +++ b/tools/xml2cpp-codegen/generator_utils.cpp @@ -44,6 +44,7 @@ const char *atomic_type_to_string(char t) { 'o', "sdbus::ObjectPath" }, { 'g', "sdbus::Signature" }, { 'v', "sdbus::Variant" }, + { 'h', "sdbus::UnixFd" }, { '\0', "" } };