summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@nokia.com>2011-02-16 14:04:57 (GMT)
committerThiago Macieira <thiago.macieira@nokia.com>2011-04-13 12:56:22 (GMT)
commit6d325d6f70c419d1fee49da1738633a3e03b46d4 (patch)
tree60924397e8048d9f38c077275b09282909f48c9f
parent8334e79a0340c9fcd5ccedeb867a84044d4d83dd (diff)
downloadQt-6d325d6f70c419d1fee49da1738633a3e03b46d4.zip
Qt-6d325d6f70c419d1fee49da1738633a3e03b46d4.tar.gz
Qt-6d325d6f70c419d1fee49da1738633a3e03b46d4.tar.bz2
Add support for Unix file-descriptor passing to QtDBus
Task-number: QTBUG-17477
-rw-r--r--src/dbus/qdbusargument.cpp28
-rw-r--r--src/dbus/qdbusargument.h4
-rw-r--r--src/dbus/qdbusargument_p.h8
-rw-r--r--src/dbus/qdbusdemarshaller.cpp17
-rw-r--r--src/dbus/qdbusmarshaller.cpp20
-rw-r--r--src/dbus/qdbusmetatype.cpp1
-rw-r--r--src/dbus/qdbusunixfiledescriptor.h1
-rw-r--r--tests/auto/qdbusmarshall/common.h11
-rw-r--r--tests/auto/qdbusmarshall/qdbusmarshall.pro2
-rw-r--r--tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp23
10 files changed, 114 insertions, 1 deletions
diff --git a/src/dbus/qdbusargument.cpp b/src/dbus/qdbusargument.cpp
index 09f0e82..806b7fe 100644
--- a/src/dbus/qdbusargument.cpp
+++ b/src/dbus/qdbusargument.cpp
@@ -487,6 +487,20 @@ QDBusArgument &QDBusArgument::operator<<(const QDBusSignature &arg)
/*!
\overload
+ \since 4.8
+ \internal
+ Appends the primitive value \a arg of type \c{UNIX_FILE_DESCRIPTOR} (Unix
+ File Descriptor) to the D-Bus stream.
+*/
+QDBusArgument &QDBusArgument::operator<<(const QDBusUnixFileDescriptor &arg)
+{
+ if (QDBusArgumentPrivate::checkWrite(d))
+ d->marshaller()->append(arg);
+ return *this;
+}
+
+/*!
+ \overload
Appends the primitive value \a arg of type \c{VARIANT} to the D-Bus stream.
A D-Bus variant type can contain any type, including other
@@ -729,6 +743,20 @@ const QDBusArgument &QDBusArgument::operator>>(QDBusSignature &arg) const
/*!
\overload
+ \since 4.8
+ \internal
+ Extracts one D-Bus primitive argument of type \c{UNIX_FILE_DESCRIPTOR}
+ (Unix file descriptor) from the D-Bus stream.
+*/
+const QDBusArgument &QDBusArgument::operator>>(QDBusUnixFileDescriptor &arg) const
+{
+ if (QDBusArgumentPrivate::checkReadAndDetach(d))
+ arg = d->demarshaller()->toUnixFileDescriptor();
+ return *this;
+}
+
+/*!
+ \overload
Extracts one D-Bus primitive argument of type \c{VARIANT} from the
D-Bus stream.
diff --git a/src/dbus/qdbusargument.h b/src/dbus/qdbusargument.h
index e331d8f..f80723e 100644
--- a/src/dbus/qdbusargument.h
+++ b/src/dbus/qdbusargument.h
@@ -61,6 +61,8 @@ QT_BEGIN_NAMESPACE
QT_MODULE(DBus)
+class QDBusUnixFileDescriptor;
+
class QDBusArgumentPrivate;
class QDBusDemarshaller;
class QDBusMarshaller;
@@ -96,6 +98,7 @@ public:
QDBusArgument &operator<<(const QDBusVariant &arg);
QDBusArgument &operator<<(const QDBusObjectPath &arg);
QDBusArgument &operator<<(const QDBusSignature &arg);
+ QDBusArgument &operator<<(const QDBusUnixFileDescriptor &arg);
QDBusArgument &operator<<(const QStringList &arg);
QDBusArgument &operator<<(const QByteArray &arg);
@@ -127,6 +130,7 @@ public:
const QDBusArgument &operator>>(QDBusVariant &arg) const;
const QDBusArgument &operator>>(QDBusObjectPath &arg) const;
const QDBusArgument &operator>>(QDBusSignature &arg) const;
+ const QDBusArgument &operator>>(QDBusUnixFileDescriptor &arg) const;
const QDBusArgument &operator>>(QStringList &arg) const;
const QDBusArgument &operator>>(QByteArray &arg) const;
diff --git a/src/dbus/qdbusargument_p.h b/src/dbus/qdbusargument_p.h
index 89a383f..1c713a3 100644
--- a/src/dbus/qdbusargument_p.h
+++ b/src/dbus/qdbusargument_p.h
@@ -54,10 +54,16 @@
//
#include <qdbusargument.h>
+#include "qdbusunixfiledescriptor.h"
#include "qdbus_symbols_p.h"
#ifndef QT_NO_DBUS
+#ifndef DBUS_TYPE_UNIX_FD
+# define DBUS_TYPE_UNIX_FD int('h')
+# define DBUS_TYPE_UNIX_FD_AS_STRING "h"
+#endif
+
QT_BEGIN_NAMESPACE
class QDBusMarshaller;
@@ -117,6 +123,7 @@ public:
void append(const QString &arg);
void append(const QDBusObjectPath &arg);
void append(const QDBusSignature &arg);
+ void append(const QDBusUnixFileDescriptor &arg);
void append(const QStringList &arg);
void append(const QByteArray &arg);
bool append(const QDBusVariant &arg); // this one can fail
@@ -172,6 +179,7 @@ public:
QString toString();
QDBusObjectPath toObjectPath();
QDBusSignature toSignature();
+ QDBusUnixFileDescriptor toUnixFileDescriptor();
QDBusVariant toVariant();
QStringList toStringList();
QByteArray toByteArray();
diff --git a/src/dbus/qdbusdemarshaller.cpp b/src/dbus/qdbusdemarshaller.cpp
index 111122e..3910381 100644
--- a/src/dbus/qdbusdemarshaller.cpp
+++ b/src/dbus/qdbusdemarshaller.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qdbusargument_p.h"
+#include "qdbusconnection.h"
#include <stdlib.h>
QT_BEGIN_NAMESPACE
@@ -126,6 +127,13 @@ inline QDBusSignature QDBusDemarshaller::toSignature()
return QDBusSignature(QString::fromUtf8(qIterGet<char *>(&iterator)));
}
+inline QDBusUnixFileDescriptor QDBusDemarshaller::toUnixFileDescriptor()
+{
+ QDBusUnixFileDescriptor fd;
+ fd.giveFileDescriptor(qIterGet<dbus_int32_t>(&iterator));
+ return fd;
+}
+
inline QDBusVariant QDBusDemarshaller::toVariant()
{
QDBusDemarshaller sub(capabilities);
@@ -173,6 +181,10 @@ QDBusArgument::ElementType QDBusDemarshaller::currentType()
case DBUS_TYPE_DICT_ENTRY:
return QDBusArgument::MapEntryType;
+ case DBUS_TYPE_UNIX_FD:
+ return capabilities & QDBusConnection::UnixFileDescriptorPassing ?
+ QDBusArgument::BasicType : QDBusArgument::UnknownType;
+
case DBUS_TYPE_INVALID:
return QDBusArgument::UnknownType;
@@ -231,6 +243,11 @@ QVariant QDBusDemarshaller::toVariantInternal()
case DBUS_TYPE_STRUCT:
return QVariant::fromValue(duplicate());
+ case DBUS_TYPE_UNIX_FD:
+ if (capabilities & QDBusConnection::UnixFileDescriptorPassing)
+ return qVariantFromValue(toUnixFileDescriptor());
+ // fall through
+
default:
// qWarning("QDBusDemarshaller: Found unknown D-Bus type %d '%c'",
// q_dbus_message_iter_get_arg_type(&iterator),
diff --git a/src/dbus/qdbusmarshaller.cpp b/src/dbus/qdbusmarshaller.cpp
index 76d76cc..edf743e 100644
--- a/src/dbus/qdbusmarshaller.cpp
+++ b/src/dbus/qdbusmarshaller.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qdbusargument_p.h"
+#include "qdbusconnection.h"
#include "qdbusmetatype_p.h"
#include "qdbusutil_p.h"
@@ -138,6 +139,16 @@ inline void QDBusMarshaller::append(const QDBusSignature &arg)
qIterAppend(&iterator, ba, DBUS_TYPE_SIGNATURE, &cdata);
}
+inline void QDBusMarshaller::append(const QDBusUnixFileDescriptor &arg)
+{
+ int fd = arg.fileDescriptor();
+ if (!ba && fd == -1) {
+ error(QLatin1String("Invalid file descriptor passed in arguments"));
+ } else {
+ qIterAppend(&iterator, ba, DBUS_TYPE_UNIX_FD, &fd);
+ }
+}
+
inline void QDBusMarshaller::append(const QByteArray &arg)
{
if (ba) {
@@ -474,6 +485,13 @@ bool QDBusMarshaller::appendVariantInternal(const QVariant &arg)
qFatal("QDBusMarshaller::appendVariantInternal got a DICT_ENTRY!");
return false;
+ case DBUS_TYPE_UNIX_FD:
+ if (capabilities & QDBusConnection::UnixFileDescriptorPassing || ba) {
+ append(qvariant_cast<QDBusUnixFileDescriptor>(arg));
+ return true;
+ }
+ // fall through
+
default:
qWarning("QDBusMarshaller::appendVariantInternal: Found unknown D-BUS type '%s'",
signature);
@@ -507,7 +525,7 @@ bool QDBusMarshaller::appendCrossMarshalling(QDBusDemarshaller *demarshaller)
if (code == DBUS_TYPE_ARRAY) {
int element = q_dbus_message_iter_get_element_type(&demarshaller->iterator);
- if (q_dbus_type_is_fixed(element)) {
+ if (q_dbus_type_is_fixed(element) && element != DBUS_TYPE_UNIX_FD) {
// another optimization: fixed size arrays
// code is exactly like QDBusDemarshaller::toByteArray
DBusMessageIter sub;
diff --git a/src/dbus/qdbusmetatype.cpp b/src/dbus/qdbusmetatype.cpp
index a361762..9d9112c 100644
--- a/src/dbus/qdbusmetatype.cpp
+++ b/src/dbus/qdbusmetatype.cpp
@@ -147,6 +147,7 @@ void QDBusMetaTypeId::init()
qDBusRegisterMetaType<QList<double> >();
qDBusRegisterMetaType<QList<QDBusObjectPath> >();
qDBusRegisterMetaType<QList<QDBusSignature> >();
+ qDBusRegisterMetaType<QList<QDBusUnixFileDescriptor> >();
#endif
initialized = true;
diff --git a/src/dbus/qdbusunixfiledescriptor.h b/src/dbus/qdbusunixfiledescriptor.h
index 3ac3f9f..92a770c 100644
--- a/src/dbus/qdbusunixfiledescriptor.h
+++ b/src/dbus/qdbusunixfiledescriptor.h
@@ -96,6 +96,7 @@ protected:
QT_END_NAMESPACE
Q_DECLARE_METATYPE(QDBusUnixFileDescriptor)
+Q_DECLARE_METATYPE(QList<QDBusUnixFileDescriptor>)
QT_END_HEADER
diff --git a/tests/auto/qdbusmarshall/common.h b/tests/auto/qdbusmarshall/common.h
index 532394a..b32b581 100644
--- a/tests/auto/qdbusmarshall/common.h
+++ b/tests/auto/qdbusmarshall/common.h
@@ -377,6 +377,14 @@ bool compare(const QHash<Key, T> &m1, const QHash<Key, T> &m2)
return true;
}
+bool compare(const QDBusUnixFileDescriptor &t1, const QDBusUnixFileDescriptor &t2)
+{
+ int fd1 = t1.fileDescriptor();
+ int fd2 = t2.fileDescriptor();
+
+ return (fd1 == -1) == (fd2 == -1);
+}
+
template<typename T>
inline bool compare(const QDBusArgument &arg, const QVariant &v2, T * = 0)
{
@@ -563,6 +571,9 @@ template<> bool compare(const QVariant &v1, const QVariant &v2)
else if (id == qMetaTypeId<QDBusSignature>())
return qvariant_cast<QDBusSignature>(v1).signature() == qvariant_cast<QDBusSignature>(v2).signature();
+ else if (id == qMetaTypeId<QDBusUnixFileDescriptor>())
+ return compare(qvariant_cast<QDBusUnixFileDescriptor>(v1), qvariant_cast<QDBusUnixFileDescriptor>(v2));
+
else if (id == qMetaTypeId<QDBusVariant>())
return compare(qvariant_cast<QDBusVariant>(v1).variant(), qvariant_cast<QDBusVariant>(v2).variant());
diff --git a/tests/auto/qdbusmarshall/qdbusmarshall.pro b/tests/auto/qdbusmarshall/qdbusmarshall.pro
index f8e0875..ad40c0d 100644
--- a/tests/auto/qdbusmarshall/qdbusmarshall.pro
+++ b/tests/auto/qdbusmarshall/qdbusmarshall.pro
@@ -3,6 +3,8 @@ contains(QT_CONFIG,dbus): {
TEMPLATE = subdirs
CONFIG += ordered
SUBDIRS = qpong test
+
+ requires(contains(QT_CONFIG,private_tests))
} else {
SOURCES += dummy.cpp
}
diff --git a/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp b/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp
index 9bae6af..828a807 100644
--- a/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp
+++ b/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp
@@ -42,6 +42,7 @@
#include <QtTest/QtTest>
#include <QtDBus/QtDBus>
#include <QtDBus/private/qdbusutil_p.h>
+#include <QtDBus/private/qdbusconnection_p.h>
#include "common.h"
#include <limits>
@@ -167,6 +168,9 @@ void tst_QDBusMarshall::sendBasic_data()
QTest::newRow("signature") << qVariantFromValue(QDBusSignature("g")) << "g" << "[Signature: g]";
QTest::newRow("emptystring") << QVariant("") << "s" << "\"\"";
QTest::newRow("nullstring") << QVariant(QString()) << "s" << "\"\"";
+
+ if (QDBusConnection::sessionBus().connectionCapabilities() & QDBusConnection::UnixFileDescriptorPassing)
+ QTest::newRow("file-descriptor") << qVariantFromValue(QDBusUnixFileDescriptor(0)) << "h" << "[Unix FD: valid]";
#endif
}
@@ -967,6 +971,21 @@ typedef QScopedPointer<DBusConnection, DisconnectRawDBus> ScopedDBusConnection;
typedef QScopedPointer<DBusMessage, GenericUnref<DBusMessage, dbus_message_unref> > ScopedDBusMessage;
typedef QScopedPointer<DBusPendingCall, GenericUnref<DBusPendingCall, dbus_pending_call_unref> > ScopedDBusPendingCall;
+template <typename T> struct SetResetValue
+{
+ const T oldValue;
+ T &value;
+public:
+ SetResetValue(T &v, T newValue) : oldValue(v), value(v)
+ {
+ value = newValue;
+ }
+ ~SetResetValue()
+ {
+ value = oldValue;
+ }
+};
+
void tst_QDBusMarshall::receiveUnknownType()
{
#ifndef DBUS_TYPE_UNIX_FD
@@ -986,6 +1005,10 @@ void tst_QDBusMarshall::receiveUnknownType()
if (!dbus_connection_can_send_type(rawcon.data(), DBUS_TYPE_UNIX_FD))
QSKIP("Your session bus does not allow sending Unix file descriptors", SkipAll);
+ // make sure this QDBusConnection won't handle Unix file descriptors
+ QDBusConnection::ConnectionCapabilities &capabRef = QDBusConnectionPrivate::d(con)->capabilities;
+ SetResetValue<QDBusConnection::ConnectionCapabilities> resetter(capabRef, capabRef & ~QDBusConnection::UnixFileDescriptorPassing);
+
if (qstrcmp(QTest::currentDataTag(), "in-call") == 0) {
// create a call back to us containing a file descriptor
QDBusMessageSpy spy;