From 9ed6a6fa482545f6238d1719bce7681737e2c1d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffen=20Kie=C3=9F?= Date: Fri, 13 Oct 2017 11:23:58 +0200 Subject: [PATCH] Add support for Unix FDs --- include/dbus-c++/message.h | 4 +++ include/dbus-c++/types.h | 34 ++++++++++++++++++++++ src/message.cpp | 31 +++++++++++++++++++- src/types.cpp | 58 ++++++++++++++++++++++++++++++++++++++ tools/generator_utils.cpp | 1 + 5 files changed, 127 insertions(+), 1 deletion(-) diff --git a/include/dbus-c++/message.h b/include/dbus-c++/message.h index a9041d8..1d07fdd 100644 --- a/include/dbus-c++/message.h +++ b/include/dbus-c++/message.h @@ -107,6 +107,10 @@ class DXXAPI MessageIter char *signature() const; //returned string must be manually free()'d + bool append_unix_fd(int fd); + + int get_unix_fd(); + MessageIter recurse(); bool append_array(char type, const void *ptr, size_t length); diff --git a/include/dbus-c++/types.h b/include/dbus-c++/types.h index 7b3108f..b5d798e 100644 --- a/include/dbus-c++/types.h +++ b/include/dbus-c++/types.h @@ -64,6 +64,21 @@ struct DXXAPI Signature : public std::string struct DXXAPI Invalid {}; +class DXXAPI UnixFD +{ +public: + UnixFD(); + explicit UnixFD(int fd); + ~UnixFD(); + UnixFD(const UnixFD& o); + UnixFD& operator = (const UnixFD& o); + + int fd() const { return _fd; } + +private: + int _fd; +}; + class DXXAPI Variant { public: @@ -241,6 +256,13 @@ template <> struct type return "g"; } }; +template <> struct type +{ + static std::string sig() + { + return "h"; + } +}; template <> struct type { static std::string sig() @@ -389,6 +411,12 @@ inline DBus::MessageIter &operator << (DBus::MessageIter &iter, const DBus::Sign return iter; } +inline DBus::MessageIter &operator << (DBus::MessageIter &iter, const DBus::UnixFD &val) +{ + iter.append_unix_fd(val.fd()); + return iter; +} + template inline DBus::MessageIter &operator << (DBus::MessageIter &iter, const std::vector& val) { @@ -545,6 +573,12 @@ inline DBus::MessageIter &operator >> (DBus::MessageIter &iter, DBus::Signature return ++iter; } +inline DBus::MessageIter &operator >> (DBus::MessageIter &iter, DBus::UnixFD &val) +{ + val = DBus::UnixFD(iter.get_unix_fd()); + return ++iter; +} + extern DXXAPI DBus::MessageIter &operator >> (DBus::MessageIter &iter, DBus::Variant &val); template diff --git a/src/message.cpp b/src/message.cpp index eacea92..34ecca2 100644 --- a/src/message.cpp +++ b/src/message.cpp @@ -30,6 +30,10 @@ #include #include +#if !HAVE_WIN32 +#include +#endif + #include "internalerror.h" #include "message_p.h" @@ -224,6 +228,18 @@ const char *MessageIter::get_signature() return chars; } +bool MessageIter::append_unix_fd(int fd) +{ + return append_basic(DBUS_TYPE_UNIX_FD, &fd); +} + +int MessageIter::get_unix_fd() +{ + int fd; + get_basic(DBUS_TYPE_UNIX_FD, &fd); + return fd; +} + MessageIter MessageIter::recurse() { MessageIter iter(msg()); @@ -320,6 +336,7 @@ static bool is_basic_type(int typecode) case 's': case 'o': case 'g': + case 'h': return true; default: return false; @@ -330,7 +347,19 @@ void MessageIter::copy_data(MessageIter &to) { for (MessageIter &from = *this; !from.at_end(); ++from) { - if (is_basic_type(from.type())) + if (from.type() == 'h') + { +#if HAVE_WIN32 + throw ErrorInvalidArgs("Unix FDs not supported under windows"); +#else + debug_log("copying unix fd"); + + int fd = from.get_unix_fd(); + to.append_unix_fd(fd); + close(fd); +#endif + } + else if (is_basic_type(from.type())) { debug_log("copying basic type: %c", from.type()); diff --git a/src/types.cpp b/src/types.cpp index 70f9ac0..88013cb 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -31,11 +31,69 @@ #include #include +#if !HAVE_WIN32 +#include +#include +#endif + #include "message_p.h" #include "internalerror.h" namespace DBus { +UnixFD::UnixFD() + : _fd(-1) +{ +} + +UnixFD::UnixFD(int fd) + : _fd(fd) +{ +#if HAVE_WIN32 + if (_fd != -1) + throw ErrorInvalidArgs("Unix FDs not supported under windows"); +#endif +} + +UnixFD::~UnixFD() +{ +#if !HAVE_WIN32 + if (_fd != -1) + close (_fd); +#endif +} + +UnixFD::UnixFD(const UnixFD &o) +{ + _fd = -1; +#if !HAVE_WIN32 + if (o._fd != -1) { + _fd = dup(o._fd); + if (_fd == -1) + throw Error("dup:errno", toString(errno).c_str()); + } +#endif +} + +UnixFD &UnixFD::operator=(const UnixFD &o) +{ + if (this == &o) + return *this; + +#if !HAVE_WIN32 + if (_fd != -1) { + close (_fd); + _fd = -1; + } + if (o._fd != -1) { + _fd = dup(o._fd); + if (_fd == -1) + throw Error("dup:errno", toString(errno).c_str()); + } +#endif + return *this; +} + Variant::Variant() : _msg(CallMessage()) // dummy message used as temporary storage for variant data { diff --git a/tools/generator_utils.cpp b/tools/generator_utils.cpp index 5686f6b..74499e3 100644 --- a/tools/generator_utils.cpp +++ b/tools/generator_utils.cpp @@ -69,6 +69,7 @@ const char *atomic_type_to_string(char t) { 's', "std::string" }, { 'o', "::DBus::Path" }, { 'g', "::DBus::Signature" }, + { 'h', "::DBus::UnixFD" }, { 'v', "::DBus::Variant" }, { '\0', "" } };