diff options
author | Qt Continuous Integration System <qt-info@nokia.com> | 2011-04-18 22:17:02 (GMT) |
---|---|---|
committer | Qt Continuous Integration System <qt-info@nokia.com> | 2011-04-18 22:17:02 (GMT) |
commit | 685df07ff7e357f6848c50cffa311641afdca307 (patch) | |
tree | 760e1e6f7189513785133071ab408260f09210b4 /src/dbus | |
parent | a359d21a84acc4b7eb73931e47acd4440327be19 (diff) | |
parent | 4c8c5ef3866723124fe8cf2c8bdd3b846549b129 (diff) | |
download | Qt-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.cpp | 9 | ||||
-rw-r--r-- | src/dbus/qdbusconnection.cpp | 93 | ||||
-rw-r--r-- | src/dbus/qdbusconnection.h | 2 | ||||
-rw-r--r-- | src/dbus/qdbusconnection_p.h | 2 | ||||
-rw-r--r-- | src/dbus/qdbusconnectionmanager_p.h | 88 | ||||
-rw-r--r-- | src/dbus/qdbusintegrator.cpp | 93 | ||||
-rw-r--r-- | src/dbus/qdbusserver.cpp | 25 | ||||
-rw-r--r-- | src/dbus/qdbusserver.h | 3 |
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; |