summaryrefslogtreecommitdiffstats
path: root/src/dbus
diff options
context:
space:
mode:
authorQt Continuous Integration System <qt-info@nokia.com>2011-04-18 22:17:02 (GMT)
committerQt Continuous Integration System <qt-info@nokia.com>2011-04-18 22:17:02 (GMT)
commit685df07ff7e357f6848c50cffa311641afdca307 (patch)
tree760e1e6f7189513785133071ab408260f09210b4 /src/dbus
parenta359d21a84acc4b7eb73931e47acd4440327be19 (diff)
parent4c8c5ef3866723124fe8cf2c8bdd3b846549b129 (diff)
downloadQt-685df07ff7e357f6848c50cffa311641afdca307.zip
Qt-685df07ff7e357f6848c50cffa311641afdca307.tar.gz
Qt-685df07ff7e357f6848c50cffa311641afdca307.tar.bz2
Merge branch 'master' of scm.dev.nokia.troll.no:qt/oslo-staging-1 into master-integration
* 'master' of scm.dev.nokia.troll.no:qt/oslo-staging-1: QtDBus: Add unit tests for QDBusAbstractAdaptor QtDBus: Add unit tests for QDBusInterface QtDBus: Add unit tests for QDBusAbstractInterface QtDBus: Register QDBusServer connection name in QDBusConnectionManager QtDBus: Skip bus name check for peer-to-peer connection QtDBus: Fix minor coding style issues QtDBus: Add default constructor to QDBusServer QtDBus: Add unit tests for peer-to-peer connection QtDBus: Add method QDBusConnection::disconnectFromPeer() QtDBus: Add method QDBusConnection::connectToPeer() QtDBus: Fix QDBusConnection::disconnectFromBus() for peer-to-peer connections QtDBus: Fix bus in peer-to-peer connections should not be used QtDBus: Fix empty service name in peer-to-peer connections QtDBus: Fix registering objects using path '/' in peer-to-peer connections QtDBus: Fix QDBusServer to handle correctly new dbus connections QtDBus: Cleaning comments, spacing, etc.
Diffstat (limited to 'src/dbus')
-rw-r--r--src/dbus/qdbusabstractinterface.cpp9
-rw-r--r--src/dbus/qdbusconnection.cpp93
-rw-r--r--src/dbus/qdbusconnection.h2
-rw-r--r--src/dbus/qdbusconnection_p.h2
-rw-r--r--src/dbus/qdbusconnectionmanager_p.h88
-rw-r--r--src/dbus/qdbusintegrator.cpp93
-rw-r--r--src/dbus/qdbusserver.cpp25
-rw-r--r--src/dbus/qdbusserver.h3
8 files changed, 234 insertions, 81 deletions
diff --git a/src/dbus/qdbusabstractinterface.cpp b/src/dbus/qdbusabstractinterface.cpp
index e48e1c0..9e82c09 100644
--- a/src/dbus/qdbusabstractinterface.cpp
+++ b/src/dbus/qdbusabstractinterface.cpp
@@ -58,7 +58,7 @@
QT_BEGIN_NAMESPACE
static QDBusError checkIfValid(const QString &service, const QString &path,
- const QString &interface, bool isDynamic)
+ const QString &interface, bool isDynamic, bool isPeer)
{
// We should be throwing exceptions here... oh well
QDBusError error;
@@ -69,7 +69,7 @@ static QDBusError checkIfValid(const QString &service, const QString &path,
// use assertion here because this should never happen, at all
Q_ASSERT_X(!interface.isEmpty(), "QDBusAbstractInterface", "Interface name cannot be empty");
}
- if (!QDBusUtil::checkBusName(service, isDynamic ? QDBusUtil::EmptyNotAllowed : QDBusUtil::EmptyAllowed, &error))
+ if (!QDBusUtil::checkBusName(service, (isDynamic && !isPeer) ? QDBusUtil::EmptyNotAllowed : QDBusUtil::EmptyAllowed, &error))
return error;
if (!QDBusUtil::checkObjectPath(path, isDynamic ? QDBusUtil::EmptyNotAllowed : QDBusUtil::EmptyAllowed, &error))
return error;
@@ -86,7 +86,8 @@ QDBusAbstractInterfacePrivate::QDBusAbstractInterfacePrivate(const QString &serv
const QDBusConnection& con,
bool isDynamic)
: connection(con), service(serv), path(p), interface(iface),
- lastError(checkIfValid(serv, p, iface, isDynamic)),
+ lastError(checkIfValid(serv, p, iface, isDynamic, (connectionPrivate() &&
+ connectionPrivate()->mode == QDBusConnectionPrivate::PeerMode))),
isValid(!lastError.isValid())
{
if (!isValid)
@@ -107,7 +108,7 @@ bool QDBusAbstractInterfacePrivate::canMakeCalls() const
{
// recheck only if we have a wildcard (i.e. empty) service or path
// if any are empty, set the error message according to QDBusUtil
- if (service.isEmpty())
+ if (service.isEmpty() && connectionPrivate()->mode != QDBusConnectionPrivate::PeerMode)
return QDBusUtil::checkBusName(service, QDBusUtil::EmptyNotAllowed, &lastError);
if (path.isEmpty())
return QDBusUtil::checkObjectPath(path, QDBusUtil::EmptyNotAllowed, &lastError);
diff --git a/src/dbus/qdbusconnection.cpp b/src/dbus/qdbusconnection.cpp
index 4883a4d..c8cf6ea 100644
--- a/src/dbus/qdbusconnection.cpp
+++ b/src/dbus/qdbusconnection.cpp
@@ -52,6 +52,7 @@
#include "qdbusconnection_p.h"
#include "qdbusinterface_p.h"
#include "qdbusutil_p.h"
+#include "qdbusconnectionmanager_p.h"
#include "qdbusthreaddebug_p.h"
@@ -59,27 +60,6 @@
QT_BEGIN_NAMESPACE
-class QDBusConnectionManager
-{
-public:
- QDBusConnectionManager() {}
- ~QDBusConnectionManager();
-
- QDBusConnectionPrivate *connection(const QString &name) const;
- void removeConnection(const QString &name);
- void setConnection(const QString &name, QDBusConnectionPrivate *c);
-
- QDBusConnectionPrivate *sender() const;
- void setSender(const QDBusConnectionPrivate *s);
-
- mutable QMutex mutex;
-private:
- QHash<QString, QDBusConnectionPrivate *> connectionHash;
-
- mutable QMutex senderMutex;
- QString senderName; // internal; will probably change
-};
-
Q_GLOBAL_STATIC(QDBusConnectionManager, _q_manager)
QDBusConnectionPrivate *QDBusConnectionManager::sender() const
@@ -126,6 +106,11 @@ QDBusConnectionManager::~QDBusConnectionManager()
connectionHash.clear();
}
+QDBusConnectionManager* QDBusConnectionManager::instance()
+{
+ return _q_manager();
+}
+
Q_DBUS_EXPORT void qDBusBindToApplication();
void qDBusBindToApplication()
{
@@ -371,7 +356,7 @@ QDBusConnection QDBusConnection::connectToBus(BusType type, const QString &name)
}
/*!
- Opens a peer-to-peer connection on address \a address and associate with it the
+ Opens a connection to a private bus on address \a address and associate with it the
connection name \a name. Returns a QDBusConnection object associated with that connection.
*/
QDBusConnection QDBusConnection::connectToBus(const QString &address,
@@ -379,7 +364,7 @@ QDBusConnection QDBusConnection::connectToBus(const QString &address,
{
// Q_ASSERT_X(QCoreApplication::instance(), "QDBusConnection::addConnection",
// "Cannot create connection without a Q[Core]Application instance");
- if (!qdbus_loadLibDBus()){
+ if (!qdbus_loadLibDBus()) {
QDBusConnectionPrivate *d = 0;
return QDBusConnection(d);
}
@@ -411,9 +396,43 @@ QDBusConnection QDBusConnection::connectToBus(const QString &address,
return retval;
}
+/*!
+ \since 4.8
+
+ Opens a peer-to-peer connection on address \a address and associate with it the
+ connection name \a name. Returns a QDBusConnection object associated with that connection.
+*/
+QDBusConnection QDBusConnection::connectToPeer(const QString &address,
+ const QString &name)
+{
+// Q_ASSERT_X(QCoreApplication::instance(), "QDBusConnection::addConnection",
+// "Cannot create connection without a Q[Core]Application instance");
+ if (!qdbus_loadLibDBus()) {
+ QDBusConnectionPrivate *d = 0;
+ return QDBusConnection(d);
+ }
+
+ QMutexLocker locker(&_q_manager()->mutex);
+
+ QDBusConnectionPrivate *d = _q_manager()->connection(name);
+ if (d || name.isEmpty())
+ return QDBusConnection(d);
+
+ d = new QDBusConnectionPrivate;
+ // setPeer does the error handling for us
+ QDBusErrorInternal error;
+ DBusConnection *c = q_dbus_connection_open_private(address.toUtf8().constData(), error);
+
+ d->setPeer(c, error);
+ _q_manager()->setConnection(name, d);
+
+ QDBusConnection retval(d);
+
+ return retval;
+}
/*!
- Closes the connection of name \a name.
+ Closes the bus connection of name \a name.
Note that if there are still QDBusConnection objects associated
with the same connection, the connection will not be closed until
@@ -424,6 +443,30 @@ void QDBusConnection::disconnectFromBus(const QString &name)
{
if (_q_manager()) {
QMutexLocker locker(&_q_manager()->mutex);
+ QDBusConnectionPrivate *d = _q_manager()->connection(name);
+ if (d && d->mode != QDBusConnectionPrivate::ClientMode)
+ return;
+ _q_manager()->removeConnection(name);
+ }
+}
+
+/*!
+ \since 4.8
+
+ Closes the peer connection of name \a name.
+
+ Note that if there are still QDBusConnection objects associated
+ with the same connection, the connection will not be closed until
+ all references are dropped. However, no further references can be
+ created using the QDBusConnection constructor.
+*/
+void QDBusConnection::disconnectFromPeer(const QString &name)
+{
+ if (_q_manager()) {
+ QMutexLocker locker(&_q_manager()->mutex);
+ QDBusConnectionPrivate *d = _q_manager()->connection(name);
+ if (d && d->mode != QDBusConnectionPrivate::PeerMode)
+ return;
_q_manager()->removeConnection(name);
}
}
@@ -814,7 +857,7 @@ void QDBusConnection::unregisterObject(const QString &path, UnregisterMode mode)
// find the object
while (node) {
- if (pathComponents.count() == i) {
+ if (pathComponents.count() == i || !path.compare(QLatin1String("/"))) {
// found it
node->obj = 0;
node->flags = 0;
diff --git a/src/dbus/qdbusconnection.h b/src/dbus/qdbusconnection.h
index 6ab0ea2..15e08a7 100644
--- a/src/dbus/qdbusconnection.h
+++ b/src/dbus/qdbusconnection.h
@@ -172,7 +172,9 @@ public:
static QDBusConnection connectToBus(BusType type, const QString &name);
static QDBusConnection connectToBus(const QString &address, const QString &name);
+ static QDBusConnection connectToPeer(const QString &address, const QString &name);
static void disconnectFromBus(const QString &name);
+ static void disconnectFromPeer(const QString &name);
static QDBusConnection sessionBus();
static QDBusConnection systemBus();
diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h
index 36f7c53..355a6e6 100644
--- a/src/dbus/qdbusconnection_p.h
+++ b/src/dbus/qdbusconnection_p.h
@@ -216,7 +216,7 @@ public:
inline void serverConnection(const QDBusConnection &connection)
{ emit newServerConnection(connection); }
-
+
private:
void checkThread();
bool handleError(const QDBusErrorInternal &error);
diff --git a/src/dbus/qdbusconnectionmanager_p.h b/src/dbus/qdbusconnectionmanager_p.h
new file mode 100644
index 0000000..dd8b4aa
--- /dev/null
+++ b/src/dbus/qdbusconnectionmanager_p.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDBus module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the public API. This header file may
+// change from version to version without notice, or even be
+// removed.
+//
+// We mean it.
+//
+//
+
+#ifndef QDBUSCONNECTIONMANAGER_P_H
+#define QDBUSCONNECTIONMANAGER_P_H
+
+#include "qdbusconnection_p.h"
+
+#ifndef QT_NO_DBUS
+
+QT_BEGIN_NAMESPACE
+
+class QDBusConnectionManager
+{
+public:
+ QDBusConnectionManager() {}
+ ~QDBusConnectionManager();
+ static QDBusConnectionManager* instance();
+
+ QDBusConnectionPrivate *connection(const QString &name) const;
+ void removeConnection(const QString &name);
+ void setConnection(const QString &name, QDBusConnectionPrivate *c);
+
+ QDBusConnectionPrivate *sender() const;
+ void setSender(const QDBusConnectionPrivate *s);
+
+ mutable QMutex mutex;
+private:
+ QHash<QString, QDBusConnectionPrivate *> connectionHash;
+
+ mutable QMutex senderMutex;
+ QString senderName; // internal; will probably change
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_DBUS
+#endif
diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp
index 5d53390..b2095c7 100644
--- a/src/dbus/qdbusintegrator.cpp
+++ b/src/dbus/qdbusintegrator.cpp
@@ -377,28 +377,23 @@ static void qDBusUpdateDispatchStatus(DBusConnection *connection, DBusDispatchSt
static void qDBusNewConnection(DBusServer *server, DBusConnection *connection, void *data)
{
- // ### We may want to separate the server from the QDBusConnectionPrivate
+ // ### We may want to separate the server from the QDBusConnectionPrivate
Q_ASSERT(server); Q_UNUSED(server);
Q_ASSERT(connection);
Q_ASSERT(data);
// keep the connection alive
q_dbus_connection_ref(connection);
- QDBusConnectionPrivate *d = new QDBusConnectionPrivate;
-
- // setConnection does the error handling for us
+ QDBusConnectionPrivate *d = static_cast<QDBusConnectionPrivate *>(data);
+
+ // setPeer does the error handling for us
QDBusErrorInternal error;
d->setPeer(connection, error);
QDBusConnection retval = QDBusConnectionPrivate::q(d);
- d->setBusService(retval);
-
- //d->name = QString::number(reinterpret_cast<int>(d));
- //d->setConnection(d->name, d);
// make QDBusServer emit the newConnection signal
- QDBusConnectionPrivate *server_d = static_cast<QDBusConnectionPrivate *>(data);
- server_d->serverConnection(retval);
+ d->serverConnection(retval);
}
} // extern "C"
@@ -435,6 +430,11 @@ static bool findObject(const QDBusConnectionPrivate::ObjectTreeNode *root,
const QString &fullpath, int &usedLength,
QDBusConnectionPrivate::ObjectTreeNode &result)
{
+ if (!fullpath.compare(QLatin1String("/")) && root->obj) {
+ usedLength = 1;
+ result = *root;
+ return root;
+ }
int start = 0;
int length = fullpath.length();
if (fullpath.at(0) == QLatin1Char('/'))
@@ -1036,11 +1036,10 @@ void QDBusConnectionPrivate::closeConnection()
mode = InvalidMode; // prevent reentrancy
baseService.clear();
- if (oldMode == ServerMode) {
- if (server) {
- q_dbus_server_disconnect(server);
- }
- } else if (oldMode == ClientMode || oldMode == PeerMode) {
+ if (server)
+ q_dbus_server_disconnect(server);
+
+ if (oldMode == ClientMode || oldMode == PeerMode) {
if (connection) {
q_dbus_connection_close(connection);
// send the "close" message
@@ -1629,7 +1628,7 @@ void QDBusConnectionPrivate::setServer(DBusServer *s, const QDBusErrorInternal &
this, 0);
//qDebug() << "time_functions_set" << time_functions_set;
Q_UNUSED(time_functions_set);
-
+
q_dbus_server_set_new_connection_function(server, qDBusNewConnection, this, 0);
dbus_bool_t data_set = q_dbus_server_set_data(server, server_slot, this, 0);
@@ -1646,7 +1645,7 @@ void QDBusConnectionPrivate::setPeer(DBusConnection *c, const QDBusErrorInternal
connection = c;
mode = PeerMode;
-
+
q_dbus_connection_set_exit_on_disconnect(connection, false);
q_dbus_connection_set_watch_functions(connection,
qDBusAddWatch,
@@ -2098,21 +2097,23 @@ void QDBusConnectionPrivate::connectSignal(const QString &key, const SignalHook
matchRefCounts.insert(hook.matchRule, 1);
if (connection) {
- qDBusDebug("Adding rule: %s", hook.matchRule.constData());
- q_dbus_bus_add_match(connection, hook.matchRule, NULL);
-
- // Successfully connected the signal
- // Do we need to watch for this name?
- if (shouldWatchService(hook.service)) {
- WatchedServicesHash::mapped_type &data = watchedServices[hook.service];
- if (++data.refcount == 1) {
- // we need to watch for this service changing
- connectSignal(dbusServiceString(), QString(), dbusInterfaceString(),
- QLatin1String("NameOwnerChanged"), QStringList() << hook.service, QString(),
- this, SLOT(serviceOwnerChangedNoLock(QString,QString,QString)));
- data.owner = getNameOwnerNoCache(hook.service);
- qDBusDebug() << this << "Watching service" << hook.service << "for owner changes (current owner:"
- << data.owner << ")";
+ if (mode != QDBusConnectionPrivate::PeerMode) {
+ qDBusDebug("Adding rule: %s", hook.matchRule.constData());
+ q_dbus_bus_add_match(connection, hook.matchRule, NULL);
+
+ // Successfully connected the signal
+ // Do we need to watch for this name?
+ if (shouldWatchService(hook.service)) {
+ WatchedServicesHash::mapped_type &data = watchedServices[hook.service];
+ if (++data.refcount == 1) {
+ // we need to watch for this service changing
+ connectSignal(dbusServiceString(), QString(), dbusInterfaceString(),
+ QLatin1String("NameOwnerChanged"), QStringList() << hook.service, QString(),
+ this, SLOT(serviceOwnerChangedNoLock(QString,QString,QString)));
+ data.owner = getNameOwnerNoCache(hook.service);
+ qDBusDebug() << this << "Watching service" << hook.service << "for owner changes (current owner:"
+ << data.owner << ")";
+ }
}
}
}
@@ -2176,18 +2177,20 @@ QDBusConnectionPrivate::disconnectSignal(SignalHookHash::Iterator &it)
// we don't care about errors here
if (connection && erase) {
- qDBusDebug("Removing rule: %s", hook.matchRule.constData());
- q_dbus_bus_remove_match(connection, hook.matchRule, NULL);
-
- // Successfully disconnected the signal
- // Were we watching for this name?
- WatchedServicesHash::Iterator sit = watchedServices.find(hook.service);
- if (sit != watchedServices.end()) {
- if (--sit.value().refcount == 0) {
- watchedServices.erase(sit);
- disconnectSignal(dbusServiceString(), QString(), dbusInterfaceString(),
- QLatin1String("NameOwnerChanged"), QStringList() << hook.service, QString(),
- this, SLOT(_q_serviceOwnerChanged(QString,QString,QString)));
+ if (mode != QDBusConnectionPrivate::PeerMode) {
+ qDBusDebug("Removing rule: %s", hook.matchRule.constData());
+ q_dbus_bus_remove_match(connection, hook.matchRule, NULL);
+
+ // Successfully disconnected the signal
+ // Were we watching for this name?
+ WatchedServicesHash::Iterator sit = watchedServices.find(hook.service);
+ if (sit != watchedServices.end()) {
+ if (--sit.value().refcount == 0) {
+ watchedServices.erase(sit);
+ disconnectSignal(dbusServiceString(), QString(), dbusInterfaceString(),
+ QLatin1String("NameOwnerChanged"), QStringList() << hook.service, QString(),
+ this, SLOT(_q_serviceOwnerChanged(QString,QString,QString)));
+ }
}
}
@@ -2390,7 +2393,7 @@ void QDBusConnectionPrivate::unregisterServiceNoLock(const QString &serviceName)
bool QDBusConnectionPrivate::isServiceRegisteredByThread(const QString &serviceName) const
{
- if (serviceName == baseService)
+ if (!serviceName.isEmpty() && serviceName == baseService)
return true;
QStringList copy = serviceNames;
return copy.contains(serviceName);
diff --git a/src/dbus/qdbusserver.cpp b/src/dbus/qdbusserver.cpp
index 9b61555..abc5cb3 100644
--- a/src/dbus/qdbusserver.cpp
+++ b/src/dbus/qdbusserver.cpp
@@ -41,6 +41,7 @@
#include "qdbusserver.h"
#include "qdbusconnection_p.h"
+#include "qdbusconnectionmanager_p.h"
#ifndef QT_NO_DBUS
@@ -62,24 +63,37 @@ QT_BEGIN_NAMESPACE
QDBusServer::QDBusServer(const QString &address, QObject *parent)
: QObject(parent)
{
+ if (address.isEmpty())
+ return;
+
if (!qdbus_loadLibDBus()) {
d = 0;
return;
}
d = new QDBusConnectionPrivate(this);
- if (address.isEmpty())
- return;
+ QMutexLocker locker(&QDBusConnectionManager::instance()->mutex);
+ QDBusConnectionManager::instance()->setConnection(QLatin1String("QDBusServer-") + QString::number(reinterpret_cast<qulonglong>(d)), d);
QObject::connect(d, SIGNAL(newServerConnection(QDBusConnection)),
this, SIGNAL(newConnection(QDBusConnection)));
- // server = q_dbus_server_listen( "unix:tmpdir=/tmp", &error);
QDBusErrorInternal error;
d->setServer(q_dbus_server_listen(address.toUtf8().constData(), error), error);
}
/*!
+ Destructs a QDBusServer
+*/
+QDBusServer::~QDBusServer()
+{
+ if (QDBusConnectionManager::instance()) {
+ QMutexLocker locker(&QDBusConnectionManager::instance()->mutex);
+ QDBusConnectionManager::instance()->removeConnection(d->name);
+ }
+}
+
+/*!
Returns true if this QDBusServer object is connected.
If it isn't connected, you need to call the constructor again.
@@ -113,11 +127,12 @@ QString QDBusServer::address() const
return addr;
}
+
/*!
\fn void QDBusServer::newConnection(const QDBusConnection &connection)
- This signal is currently not used, but if and when it is
- used, \a connection will be the new connection.
+ This signal is emitted when a new client connection \a connection is
+ established to the server.
*/
QT_END_NAMESPACE
diff --git a/src/dbus/qdbusserver.h b/src/dbus/qdbusserver.h
index f101011..fcb78bd 100644
--- a/src/dbus/qdbusserver.h
+++ b/src/dbus/qdbusserver.h
@@ -61,7 +61,8 @@ class Q_DBUS_EXPORT QDBusServer: public QObject
{
Q_OBJECT
public:
- QDBusServer(const QString &address, QObject *parent = 0);
+ QDBusServer(const QString &address = "unix:tmpdir=/tmp", QObject *parent = 0);
+ virtual ~QDBusServer();
bool isConnected() const;
QDBusError lastError() const;