3 * Copyright (C) 2005 Harald Fernengel <harry@kdevelop.org>
4 * Copyright (C) 2006 Trolltech AS. All rights reserved.
5 * Author: Thiago Macieira <thiago.macieira@trolltech.com>
7 * Licensed under the Academic Free License version 2.1
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software Foundation
21 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26 #include <qcoreapplication.h>
27 #include <qstringlist.h>
30 #include "qdbusconnection.h"
31 #include "qdbuserror.h"
32 #include "qdbusmessage.h"
33 #include "qdbusconnection_p.h"
34 #include "qdbusinterface_p.h"
35 #include "qdbusutil.h"
37 class QDBusConnectionManager
40 QDBusConnectionManager() {}
41 ~QDBusConnectionManager();
42 void bindToApplication();
43 QDBusConnectionPrivate *connection(const QString &name) const;
44 void removeConnection(const QString &name);
45 void setConnection(const QString &name, QDBusConnectionPrivate *c);
49 QHash<QString, QDBusConnectionPrivate *> connectionHash;
52 Q_GLOBAL_STATIC(QDBusConnectionManager, manager)
54 QDBusConnectionPrivate *QDBusConnectionManager::connection(const QString &name) const
56 QMutexLocker locker(&mutex);
57 return connectionHash.value(name, 0);
60 void QDBusConnectionManager::removeConnection(const QString &name)
62 QMutexLocker locker(&mutex);
64 QDBusConnectionPrivate *d = 0;
65 d = connectionHash.take(name);
66 if (d && !d->ref.deref())
70 QDBusConnectionManager::~QDBusConnectionManager()
72 for (QHash<QString, QDBusConnectionPrivate *>::const_iterator it = connectionHash.constBegin();
73 it != connectionHash.constEnd(); ++it) {
76 connectionHash.clear();
79 void QDBusConnectionManager::bindToApplication()
81 QMutexLocker locker(&mutex);
82 for (QHash<QString, QDBusConnectionPrivate *>::const_iterator it = connectionHash.constBegin();
83 it != connectionHash.constEnd(); ++it) {
84 (*it)->bindToApplication();
88 QDBUS_EXPORT void qDBusBindToApplication();
89 void qDBusBindToApplication()
91 manager()->bindToApplication();
94 void QDBusConnectionManager::setConnection(const QString &name, QDBusConnectionPrivate *c)
96 connectionHash[name] = c;
101 \fn QDBusConnection QDBus::sessionBus()
102 \relates QDBusConnection
104 Returns a QDBusConnection object opened with the session bus. The object reference returned
105 by this function is valid until the QCoreApplication's destructor is run, when the
106 connection will be closed and the object, deleted.
109 \fn QDBusConnection QDBus::systemBus()
110 \relates QDBusConnection
112 Returns a QDBusConnection object opened with the system bus. The object reference returned
113 by this function is valid until the QCoreApplication's destructor is run, when the
114 connection will be closed and the object, deleted.
118 \class QDBusConnection
119 \brief A connection to the D-Bus bus daemon.
121 This class is the initial point in a D-Bus session. Using it, you can get access to remote
122 objects, interfaces; connect remote signals to your object's slots; register objects, etc.
124 D-Bus connections are created using the QDBusConnection::addConnection() function, which opens a
125 connection to the server daemon and does the initial handshaking, associating that connection
126 with a name. Further attempts to connect using the same name will return the same
129 The connection is then torn down using the QDBusConnection::closeConnection() function.
131 As a convenience for the two most common connection types, the QDBus::sessionBus() and
132 QDBus::systemBus() functions return open connections to the session server daemon and the system
133 server daemon, respectively. Those connections are opened when first used and are closed when
134 the QCoreApplication destructor is run.
136 D-Bus also supports peer-to-peer connections, without the need for a bus server daemon. Using
137 this facility, two applications can talk to each other and exchange messages. This can be
138 achieved by passing an address to QDBusConnection::addConnection()
139 function, which was opened by another D-Bus application using QDBusServer.
143 \enum QDBusConnection::BusType
144 Specifies the type of the bus connection. The valid bus types are:
146 \value SessionBus the session bus, associated with the running desktop session
147 \value SystemBus the system bus, used to communicate with system-wide processes
148 \value ActivationBus the activation bus, whose purpose I have no idea...
150 On the Session Bus, one can find other applications by the same user that are sharing the same
151 desktop session (hence the name). On the System Bus, however, processes shared for the whole
152 system are usually found.
156 \enum QDBusConnection::WaitMode
157 Specifies the call waiting mode.
159 \value UseEventLoop use the Qt Event Loop to wait for the reply
160 \value NoUseEventLoop don't use the event loop
162 The \c UseEventLoop option allows for the application to continue to update its UI while the
163 call is performed, but it also opens up the possibility for reentrancy: socket notifiers may
164 fire, signals may be delivered and other D-Bus calls may be processed. The \c NoUseEventLoop
165 does not use the event loop, thus being safe from those problems, but it may block the
166 application for a noticeable period of time, in case the remote application fails to respond.
168 Also note that calls that go back to the local application can only be placed in \c UseEventLoop
173 \enum QDBusConnection::RegisterOption
174 Specifies the options for registering objects with the connection. The possible values are:
176 \value ExportAdaptors export the contents of adaptors found in this object
178 \value ExportSlots export this object's scriptable slots
179 \value ExportSignals export this object's scriptable signals
180 \value ExportProperties export this object's scriptable properties
181 \value ExportContents shorthand form for ExportSlots | ExportSignals |
184 \value ExportAllSlots export all of this object's slots, including
186 \value ExportAllSignals export all of this object's signals, including
188 \value ExportAllProperties export all of this object's properties, including
190 \value ExportAllContents export all of this object's slots, signals and
191 properties, including non-scriptable ones
193 \value ExportChildObjects export this object's child objects
195 \warning It is currently not possible to export signals from objects. If you pass the flag
196 ExportSignals or ExportAllSignals, the registerObject() function will print a warning.
198 \sa registerObject(), QDBusAbstractAdaptor, {usingadaptors.html}{Using adaptors}
202 \enum QDBusConnection::UnregisterMode
203 The mode for unregistering an object path:
205 \value UnregisterNode unregister this node only: do not unregister child objects
206 \value UnregisterTree unregister this node and all its sub-tree
208 Note, however, if this object was registered with the ExportChildObjects option, UnregisterNode
209 will unregister the child objects too.
213 Creates a QDBusConnection object attached to the connection with name \a name.
215 This does not open the connection. You have to call QDBusConnection::addConnection to open it.
217 QDBusConnection::QDBusConnection(const QString &name)
219 d = manager()->connection(name);
225 Creates a copy of the \a other connection.
227 QDBusConnection::QDBusConnection(const QDBusConnection &other)
235 Disposes of this object. This does not close the connection: you have to call
236 QDBusConnection::closeConnection to do that.
238 QDBusConnection::~QDBusConnection()
240 if (d && !d->ref.deref())
245 Creates a copy of the connection \a other in this object. The connection this object referenced
246 before the copy is not spontaneously disconnected. See QDBusConnection::closeConnection for more
249 QDBusConnection &QDBusConnection::operator=(const QDBusConnection &other)
253 QDBusConnectionPrivate *old = static_cast<QDBusConnectionPrivate *>(
254 q_atomic_set_ptr(&d, other.d));
255 if (old && !old->ref.deref())
262 Opens a connection of type \a type to one of the known busses and associate with it the
263 connection name \a name. Returns a QDBusConnection object associated with that connection.
265 QDBusConnection QDBusConnection::addConnection(BusType type, const QString &name)
267 // Q_ASSERT_X(QCoreApplication::instance(), "QDBusConnection::addConnection",
268 // "Cannot create connection without a Q[Core]Application instance");
270 QDBusConnectionPrivate *d = manager()->connection(name);
271 if (d || name.isEmpty())
272 return QDBusConnection(name);
274 d = new QDBusConnectionPrivate;
275 DBusConnection *c = 0;
278 c = dbus_bus_get_private(DBUS_BUS_SYSTEM, &d->error);
281 c = dbus_bus_get_private(DBUS_BUS_SESSION, &d->error);
284 c = dbus_bus_get_private(DBUS_BUS_STARTER, &d->error);
287 d->setConnection(c); //setConnection does the error handling for us
289 manager()->setConnection(name, d);
291 QDBusConnection retval(name);
293 // create the bus service
294 QDBusAbstractInterfacePrivate *p;
295 p = retval.findInterface_helper(QLatin1String(DBUS_SERVICE_DBUS),
296 QLatin1String(DBUS_PATH_DBUS),
297 QLatin1String(DBUS_INTERFACE_DBUS));
299 d->busService = new QDBusBusService(p);
300 d->busService->setParent(d); // auto-deletion
301 d->ref.deref(); // busService has a increased the refcounting to us
308 Opens a peer-to-peer connection on address \a address and associate with it the
309 connection name \a name. Returns a QDBusConnection object associated with that connection.
311 QDBusConnection QDBusConnection::addConnection(const QString &address,
314 // Q_ASSERT_X(QCoreApplication::instance(), "QDBusConnection::addConnection",
315 // "Cannot create connection without a Q[Core]Application instance");
317 QDBusConnectionPrivate *d = manager()->connection(name);
318 if (d || name.isEmpty())
319 return QDBusConnection(name);
321 d = new QDBusConnectionPrivate;
322 // setConnection does the error handling for us
323 d->setConnection(dbus_connection_open(address.toUtf8().constData(), &d->error));
325 manager()->setConnection(name, d);
327 QDBusConnection retval(name);
329 // create the bus service
330 QDBusAbstractInterfacePrivate *p;
331 p = retval.findInterface_helper(QLatin1String(DBUS_SERVICE_DBUS),
332 QLatin1String(DBUS_PATH_DBUS),
333 QLatin1String(DBUS_INTERFACE_DBUS));
335 d->busService = new QDBusBusService(p);
336 d->busService->setParent(d); // auto-deletion
337 d->ref.deref(); // busService has a increased the refcounting to us
344 Closes the connection of name \a name.
346 Note that if there are still QDBusConnection objects associated with the same connection, the
347 connection will not be closed until all references are dropped. However, no further references
348 can be created using the QDBusConnection::QDBusConnection constructor.
350 void QDBusConnection::closeConnection(const QString &name)
352 manager()->removeConnection(name);
356 Sends the \a message over this connection, without waiting for a reply. This is suitable for
357 errors, signals, and return values as well as calls whose return values are not necessary.
359 Returns true if the message was queued successfully, false otherwise.
361 bool QDBusConnection::send(const QDBusMessage &message) const
363 if (!d || !d->connection)
365 return d->send(message) != 0;
369 Sends the \a message over this connection and returns immediately after queueing it. When the
370 reply is received, the slot \a method is called in the object \a receiver. This function is
371 suitable for method calls only.
373 This function guarantees that the slot will be called exactly once with the reply, as long as
374 the parameter types match. If they don't, the reply cannot be delivered.
376 Returns the identification of the message that was sent or 0 if nothing was sent.
378 int QDBusConnection::sendWithReplyAsync(const QDBusMessage &message, QObject *receiver,
379 const char *method) const
381 if (!d || !d->connection)
384 return d->sendWithReplyAsync(message, receiver, method);
388 Sends the \a message over this connection and blocks, waiting for a reply. This function is
389 suitable for method calls only. It returns the reply message as its return value, which will be
390 either of type QDBusMessage::ReplyMessage or QDBusMessage::ErrorMessage.
392 See the QDBusInterface::call function for a more friendly way of placing calls.
394 \warning If \a mode is \c UseEventLoop, this function will reenter the Qt event loop in order to
395 wait for the reply. During the wait, it may deliver signals and other method calls to
396 your application. Therefore, it must be prepared to handle a reentrancy whenever a call
397 is placed with sendWithReply.
399 QDBusMessage QDBusConnection::sendWithReply(const QDBusMessage &message, WaitMode mode) const
401 if (!d || !d->connection)
402 return QDBusMessage();
403 return d->sendWithReply(message, mode);
407 Connects the signal specified by the \a service, \a path, \a interface and \a name parameters to
408 the slot \a slot in object \a receiver. The arguments \a service and \a path can be empty,
409 denoting a connection to any signal of the \a interface - \a name pair, from any remote
412 Returns true if the connection was successful.
414 \warning The signal will only be delivered to the slot if the parameters match. This verification
415 can be done only when the signal is received, not at connection time.
417 bool QDBusConnection::connect(const QString &service, const QString &path, const QString& interface,
418 const QString &name, QObject *receiver, const char *slot)
420 return connect(service, path, interface, name, QString(), receiver, slot);
425 Connects the signal to the slot \a slot in object \a receiver. Unlike the other
426 QDBusConnection::connect overload, this function allows one to specify the parameter signature
427 to be connected using the \a signature variable. The function will then verify that this
428 signature can be delivered to the slot specified by \a slot and return false otherwise.
430 bool QDBusConnection::connect(const QString &service, const QString &path, const QString& interface,
431 const QString &name, const QString &signature,
432 QObject *receiver, const char *slot)
434 if (!receiver || !slot || !d || !d->connection || !QDBusUtil::isValidInterfaceName(interface))
438 if (!service.isEmpty()) {
439 source = d->getNameOwner(service);
440 if (source.isEmpty())
445 QDBusConnectionPrivate::SignalHook hook;
447 hook.signature = signature;
448 if (!d->prepareHook(hook, key, source, path, interface, name, receiver, slot, 0, false))
449 return false; // don't connect
451 // avoid duplicating:
452 QWriteLocker locker(&d->lock);
453 QDBusConnectionPrivate::SignalHookHash::ConstIterator it = d->signalHooks.find(key);
454 for ( ; it != d->signalHooks.end() && it.key() == key; ++it) {
455 const QDBusConnectionPrivate::SignalHook &entry = it.value();
456 if (entry.sender == hook.sender &&
457 entry.path == hook.path &&
458 entry.signature == hook.signature &&
459 entry.obj == hook.obj &&
460 entry.midx == hook.midx) {
461 // no need to compare the parameters if it's the same slot
462 return true; // already there
467 d->connectSignal(key, hook);
472 Registers the object \a object at path \a path and returns true if the registration was
473 successful. The \a options parameter specifies how much of the object \a object will be exposed
476 This function does not replace existing objects: if there is already an object registered at
477 path \a path, this function will return false. Use unregisterObject() to unregister it first.
479 You cannot register an object as a child object of an object that was registered with
480 QDBusConnection::ExportChildObjects.
482 bool QDBusConnection::registerObject(const QString &path, QObject *object, RegisterOptions options)
484 if (!d || !d->connection || !object || !options || !QDBusUtil::isValidObjectPath(path))
487 if (options & ExportSignals) {
488 qWarning("Cannot export signals from objects. Use an adaptor for that purpose.");
492 QStringList pathComponents = path.split(QLatin1Char('/'));
493 if (pathComponents.last().isEmpty())
494 pathComponents.removeLast();
495 QWriteLocker locker(&d->lock);
497 // lower-bound search for where this object should enter in the tree
498 QDBusConnectionPrivate::ObjectTreeNode *node = &d->rootNode;
501 if (pathComponents.count() == i) {
503 // consider it free if there's no object here and the user is not trying to
504 // replace the object sub-tree
505 if ((options & ExportChildObjects && !node->children.isEmpty()) || node->obj)
508 // we can add the object here
510 node->flags = options;
512 d->registerObject(node);
513 qDebug("REGISTERED FOR %s", path.toLocal8Bit().constData());
517 // find the position where we'd insert the node
518 QVector<QDBusConnectionPrivate::ObjectTreeNode::Data>::Iterator it =
519 qLowerBound(node->children.begin(), node->children.end(), pathComponents.at(i));
520 if (it != node->children.constEnd() && it->name == pathComponents.at(i)) {
521 // match: this node exists
524 // are we allowed to go deeper?
525 if (node->flags & ExportChildObjects) {
527 qDebug("Cannot register object at %s because %s exports its own child objects",
528 qPrintable(path), qPrintable(pathComponents.at(i)));
533 QDBusConnectionPrivate::ObjectTreeNode::Data entry;
534 entry.name = pathComponents.at(i);
535 entry.node = new QDBusConnectionPrivate::ObjectTreeNode;
536 node->children.insert(it, entry);
545 Q_ASSERT_X(false, "QDBusConnection::registerObject", "The impossible happened");
550 Unregisters an object that was registered with the registerObject() at the object path given by
551 \a path and, if \a mode is QDBusConnection::UnregisterTree, all of its sub-objects too.
553 Note that you cannot unregister objects that were not registered with registerObject().
555 void QDBusConnection::unregisterObject(const QString &path, UnregisterMode mode)
557 if (!d || !d->connection || !QDBusUtil::isValidObjectPath(path))
560 QStringList pathComponents = path.split(QLatin1Char('/'));
561 QWriteLocker locker(&d->lock);
562 QDBusConnectionPrivate::ObjectTreeNode *node = &d->rootNode;
567 if (pathComponents.count() == i) {
572 if (mode == UnregisterTree) {
573 // clear the sub-tree as well
574 node->clear(); // can't disconnect the objects because we really don't know if they can
575 // be found somewhere else in the path too
581 QVector<QDBusConnectionPrivate::ObjectTreeNode::Data>::ConstIterator it =
582 qLowerBound(node->children.constBegin(), node->children.constEnd(), pathComponents.at(i));
583 if (it == node->children.constEnd() || it->name != pathComponents.at(i))
584 break; // node not found
592 Returns a dynamic QDBusInterface associated with the interface \a interface on object at path \a
593 path on service \a service.
595 This function creates a new object. It is your resposibility to ensure it is properly deleted
596 (you can use all normal QObject deletion mechanisms, including the QObject::deleteLater() slot
597 and QObject::setParent()).
599 If the searching for this interface on the remote object failed, this function returns 0.
601 QDBusInterface *QDBusConnection::findInterface(const QString& service, const QString& path,
602 const QString& interface)
607 QDBusInterfacePrivate *p = d->findInterface(service, path, interface);
608 QDBusInterface *retval = new QDBusInterface(p);
609 retval->setParent(d);
614 \fn QDBusConnection::findInterface(const QString &service, const QString &path)
615 Returns an interface of type \c Interface associated with the object on path \a path at service
618 \c Interface must be a class generated by \l {dbusidl2cpp.html}.
620 This function creates a new object. It is your resposibility to ensure it is properly deleted
621 (you can use all normal QObject deletion mechanisms, including the QObject::deleteLater() slot
622 and QObject::setParent()).
626 Returns a QDBusBusService object that represents the D-Bus bus service on this connection.
628 This function returns 0 for peer-to-peer connections.
630 QDBusBusService *QDBusConnection::busService() const
634 return d->busService;
637 QDBusAbstractInterfacePrivate *
638 QDBusConnection::findInterface_helper(const QString &service, const QString &path,
639 const QString &interface)
643 if (!interface.isEmpty() && !QDBusUtil::isValidInterfaceName(interface))
647 if (!service.isEmpty()) {
648 if (!QDBusUtil::isValidObjectPath(path))
651 // check if it's there first -- FIXME: add binding mode
652 owner = d->getNameOwner(service);
655 } else if (!path.isEmpty())
658 return new QDBusAbstractInterfacePrivate(*this, d, owner, path, interface);
662 Returns true if this QDBusConnection object is connected.
664 If it isn't connected, calling QDBusConnection::addConnection on the same connection name
665 will not make be connected. You need to call the QDBusConnection constructor again.
667 bool QDBusConnection::isConnected( ) const
669 return d && d->connection && dbus_connection_get_is_connected(d->connection);
673 Returns the last error that happened in this connection.
675 This function is provided for low-level code. If you're using QDBusInterface::call, error codes are
676 reported by its return value.
678 \sa QDBusInterface, QDBusMessage
680 QDBusError QDBusConnection::lastError() const
682 return d ? d->lastError : QDBusError();
686 Returns the unique connection name for this connection, if this QDBusConnection object is
687 connected, or an empty QString otherwise.
689 A Unique Connection Name is a string in the form ":x.xxx" (where x are decimal digits) that is
690 assigned by the D-Bus server daemon upon connection. It uniquely identifies this client in the
693 This function returns an empty QString for peer-to-peer connections.
695 QString QDBusConnection::baseService() const
697 return d && d->connection ?
698 QString::fromUtf8(dbus_bus_get_unique_name(d->connection))
702 Q_GLOBAL_STATIC(QMutex, defaultBussesMutex)
703 static const char sessionBusName[] = "qt_default_session_bus";
704 static const char systemBusName[] = "qt_default_system_bus";
705 static QDBusConnection *sessionBus = 0;
706 static QDBusConnection *systemBus = 0;
708 static void closeConnections()
710 QMutexLocker locker(defaultBussesMutex());
713 QDBusConnection::closeConnection(QLatin1String(sessionBusName));
714 QDBusConnection::closeConnection(QLatin1String(systemBusName));
715 sessionBus = systemBus = 0;
718 static QDBusConnection *openConnection(QDBusConnection::BusType type)
720 QMutexLocker locker(defaultBussesMutex());
721 qAddPostRoutine(closeConnections);
723 if (type == QDBusConnection::SystemBus) {
725 // maybe it got created before we locked the mutex
727 systemBus = new QDBusConnection(QDBusConnection::addConnection(QDBusConnection::SystemBus,
728 QLatin1String(systemBusName)));
732 // maybe it got created before we locked the mutex
734 sessionBus = new QDBusConnection(QDBusConnection::addConnection(QDBusConnection::SessionBus,
735 QLatin1String(sessionBusName)));
741 QDBusConnection &sessionBus()
743 if (::sessionBus) return *::sessionBus;
744 return *openConnection(QDBusConnection::SessionBus);
747 QDBusConnection &systemBus()
749 if (::systemBus) return *::systemBus;
750 return *openConnection(QDBusConnection::SystemBus);