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 void qDBusBindToApplication()
90 manager()->bindToApplication();
93 void QDBusConnectionManager::setConnection(const QString &name, QDBusConnectionPrivate *c)
95 connectionHash[name] = c;
100 \fn QDBusConnection QDBus::sessionBus()
101 \relates QDBusConnection
103 Returns a QDBusConnection object opened with the session bus. The object reference returned
104 by this function is valid until the QCoreApplication's destructor is run, when the
105 connection will be closed and the object, deleted.
108 \fn QDBusConnection QDBus::systemBus()
109 \relates QDBusConnection
111 Returns a QDBusConnection object opened with the system bus. The object reference returned
112 by this function is valid until the QCoreApplication's destructor is run, when the
113 connection will be closed and the object, deleted.
117 \class QDBusConnection
118 \brief A connection to the D-Bus bus daemon.
120 This class is the initial point in a D-Bus session. Using it, you can get access to remote
121 objects, interfaces; connect remote signals to your object's slots; register objects, etc.
123 D-Bus connections are created using the QDBusConnection::addConnection() function, which opens a
124 connection to the server daemon and does the initial handshaking, associating that connection
125 with a name. Further attempts to connect using the same name will return the same
128 The connection is then torn down using the QDBusConnection::closeConnection() function.
130 As a convenience for the two most common connection types, the QDBus::sessionBus() and
131 QDBus::systemBus() functions return open connections to the session server daemon and the system
132 server daemon, respectively. Those connections are opened when first used and are closed when
133 the QCoreApplication destructor is run.
135 D-Bus also supports peer-to-peer connections, without the need for a bus server daemon. Using
136 this facility, two applications can talk to each other and exchange messages. This can be
137 achieved by passing an address to QDBusConnection::addConnection()
138 function, which was opened by another D-Bus application using QDBusServer.
142 \enum QDBusConnection::BusType
143 Specifies the type of the bus connection. The valid bus types are:
145 \value SessionBus the session bus, associated with the running desktop session
146 \value SystemBus the system bus, used to communicate with system-wide processes
147 \value ActivationBus the activation bus, whose purpose I have no idea...
149 On the Session Bus, one can find other applications by the same user that are sharing the same
150 desktop session (hence the name). On the System Bus, however, processes shared for the whole
151 system are usually found.
155 \enum QDBusConnection::WaitMode
156 Specifies the call waiting mode.
158 \value UseEventLoop use the Qt Event Loop to wait for the reply
159 \value NoUseEventLoop don't use the event loop
161 The \c UseEventLoop option allows for the application to continue to update its UI while the
162 call is performed, but it also opens up the possibility for reentrancy: socket notifiers may
163 fire, signals may be delivered and other D-Bus calls may be processed. The \c NoUseEventLoop
164 does not use the event loop, thus being safe from those problems, but it may block the
165 application for a noticeable period of time, in case the remote application fails to respond.
167 Also note that calls that go back to the local application can only be placed in \c UseEventLoop
172 \enum QDBusConnection::RegisterOption
173 Specifies the options for registering objects with the connection. The possible values are:
175 \value ExportAdaptors export the contents of adaptors found in this object
177 \value ExportSlots export this object's scriptable slots
178 \value ExportSignals export this object's scriptable signals
179 \value ExportProperties export this object's scriptable properties
180 \value ExportContents shorthand form for ExportSlots | ExportSignals |
183 \value ExportAllSlots export all of this object's slots, including
185 \value ExportAllSignals export all of this object's signals, including
187 \value ExportAllProperties export all of this object's properties, including
189 \value ExportAllContents export all of this object's slots, signals and
190 properties, including non-scriptable ones
192 \value ExportChildObjects export this object's child objects
194 \warning It is currently not possible to export signals from objects. If you pass the flag
195 ExportSignals or ExportAllSignals, the registerObject() function will print a warning.
197 \sa registerObject(), QDBusAbstractAdaptor, {usingadaptors.html}{Using adaptors}
201 \enum QDBusConnection::UnregisterMode
202 The mode for unregistering an object path:
204 \value UnregisterNode unregister this node only: do not unregister child objects
205 \value UnregisterTree unregister this node and all its sub-tree
207 Note, however, if this object was registered with the ExportChildObjects option, UnregisterNode
208 will unregister the child objects too.
212 Creates a QDBusConnection object attached to the connection with name \a name.
214 This does not open the connection. You have to call QDBusConnection::addConnection to open it.
216 QDBusConnection::QDBusConnection(const QString &name)
218 d = manager()->connection(name);
224 Creates a copy of the \a other connection.
226 QDBusConnection::QDBusConnection(const QDBusConnection &other)
234 Disposes of this object. This does not close the connection: you have to call
235 QDBusConnection::closeConnection to do that.
237 QDBusConnection::~QDBusConnection()
239 if (d && !d->ref.deref())
244 Creates a copy of the connection \a other in this object. The connection this object referenced
245 before the copy is not spontaneously disconnected. See QDBusConnection::closeConnection for more
248 QDBusConnection &QDBusConnection::operator=(const QDBusConnection &other)
252 QDBusConnectionPrivate *old = static_cast<QDBusConnectionPrivate *>(
253 q_atomic_set_ptr(&d, other.d));
254 if (old && !old->ref.deref())
261 Opens a connection of type \a type to one of the known busses and associate with it the
262 connection name \a name. Returns a QDBusConnection object associated with that connection.
264 QDBusConnection QDBusConnection::addConnection(BusType type, const QString &name)
266 // Q_ASSERT_X(QCoreApplication::instance(), "QDBusConnection::addConnection",
267 // "Cannot create connection without a Q[Core]Application instance");
269 QDBusConnectionPrivate *d = manager()->connection(name);
270 if (d || name.isEmpty())
271 return QDBusConnection(name);
273 d = new QDBusConnectionPrivate;
274 DBusConnection *c = 0;
277 c = dbus_bus_get(DBUS_BUS_SYSTEM, &d->error);
280 c = dbus_bus_get(DBUS_BUS_SESSION, &d->error);
283 c = dbus_bus_get(DBUS_BUS_STARTER, &d->error);
286 d->setConnection(c); //setConnection does the error handling for us
288 manager()->setConnection(name, d);
290 QDBusConnection retval(name);
292 // create the bus service
293 QDBusAbstractInterfacePrivate *p;
294 p = retval.findInterface_helper(QLatin1String(DBUS_SERVICE_DBUS),
295 QLatin1String(DBUS_PATH_DBUS),
296 QLatin1String(DBUS_INTERFACE_DBUS));
298 d->busService = new QDBusBusService(p);
299 d->busService->setParent(d); // auto-deletion
300 d->ref.deref(); // busService has a increased the refcounting to us
307 Opens a peer-to-peer connection on address \a address and associate with it the
308 connection name \a name. Returns a QDBusConnection object associated with that connection.
310 QDBusConnection QDBusConnection::addConnection(const QString &address,
313 // Q_ASSERT_X(QCoreApplication::instance(), "QDBusConnection::addConnection",
314 // "Cannot create connection without a Q[Core]Application instance");
316 QDBusConnectionPrivate *d = manager()->connection(name);
317 if (d || name.isEmpty())
318 return QDBusConnection(name);
320 d = new QDBusConnectionPrivate;
321 // setConnection does the error handling for us
322 d->setConnection(dbus_connection_open(address.toUtf8().constData(), &d->error));
324 manager()->setConnection(name, d);
326 QDBusConnection retval(name);
328 // create the bus service
329 QDBusAbstractInterfacePrivate *p;
330 p = retval.findInterface_helper(QLatin1String(DBUS_SERVICE_DBUS),
331 QLatin1String(DBUS_PATH_DBUS),
332 QLatin1String(DBUS_INTERFACE_DBUS));
334 d->busService = new QDBusBusService(p);
335 d->busService->setParent(d); // auto-deletion
336 d->ref.deref(); // busService has a increased the refcounting to us
343 Closes the connection of name \a name.
345 Note that if there are still QDBusConnection objects associated with the same connection, the
346 connection will not be closed until all references are dropped. However, no further references
347 can be created using the QDBusConnection::QDBusConnection constructor.
349 void QDBusConnection::closeConnection(const QString &name)
351 manager()->removeConnection(name);
354 void QDBusConnectionPrivate::timerEvent(QTimerEvent *e)
356 DBusTimeout *timeout = timeouts.value(e->timerId(), 0);
357 dbus_timeout_handle(timeout);
361 Sends the \a message over this connection, without waiting for a reply. This is suitable for
362 errors, signals, and return values as well as calls whose return values are not necessary.
364 Returns true if the message was queued successfully, false otherwise.
366 bool QDBusConnection::send(const QDBusMessage &message) const
368 if (!d || !d->connection)
370 return d->send(message);
374 Sends the \a message over this connection and returns immediately after queueing it. When the
375 reply is received, the slot \a method is called in the object \a receiver. This function is
376 suitable for method calls only.
378 This function guarantees that the slot will be called exactly once with the reply, as long as
379 the parameter types match. If they don't, the reply cannot be delivered.
381 Returns the identification of the message that was sent or 0 if nothing was sent.
383 int QDBusConnection::sendWithReplyAsync(const QDBusMessage &message, QObject *receiver,
384 const char *method) const
386 if (!d || !d->connection)
389 return d->sendWithReplyAsync(message, receiver, method);
393 Sends the \a message over this connection and blocks, waiting for a reply. This function is
394 suitable for method calls only. It returns the reply message as its return value, which will be
395 either of type QDBusMessage::ReplyMessage or QDBusMessage::ErrorMessage.
397 See the QDBusInterface::call function for a more friendly way of placing calls.
399 \warning If \a mode is \c UseEventLoop, this function will reenter the Qt event loop in order to
400 wait for the reply. During the wait, it may deliver signals and other method calls to
401 your application. Therefore, it must be prepared to handle a reentrancy whenever a call
402 is placed with sendWithReply.
404 QDBusMessage QDBusConnection::sendWithReply(const QDBusMessage &message, WaitMode mode) const
406 if (!d || !d->connection)
407 return QDBusMessage();
408 return d->sendWithReply(message, mode);
412 Connects the signal specified by the \a service, \a path, \a interface and \a name parameters to
413 the slot \a slot in object \a receiver. The arguments \a service and \a path can be empty,
414 denoting a connection to any signal of the \a interface - \a name pair, from any remote
417 Returns true if the connection was successful.
419 \warning The signal will only be delivered to the slot if the parameters match. This verification
420 can be done only when the signal is received, not at connection time.
422 bool QDBusConnection::connect(const QString &service, const QString &path, const QString& interface,
423 const QString &name, QObject *receiver, const char *slot)
425 return connect(service, path, interface, name, QString(), receiver, slot);
430 Connects the signal to the slot \a slot in object \a receiver. Unlike the other
431 QDBusConnection::connect overload, this function allows one to specify the parameter signature
432 to be connected using the \a signature variable. The function will then verify that this
433 signature can be delivered to the slot specified by \a slot and return false otherwise.
435 bool QDBusConnection::connect(const QString &service, const QString &path, const QString& interface,
436 const QString &name, const QString &signature,
437 QObject *receiver, const char *slot)
439 if (!receiver || !slot || !d || !d->connection || !QDBusUtil::isValidInterfaceName(interface))
443 if (!service.isEmpty()) {
444 source = d->getNameOwner(service);
445 if (source.isEmpty())
451 QDBusConnectionPrivate::SignalHook hook;
452 if ((hook.midx = QDBusConnectionPrivate::findSlot(receiver, slot + 1, hook.params)) == -1)
455 hook.interface = interface;
457 hook.signature = signature;
460 // avoid duplicating:
461 QWriteLocker locker(&d->lock);
462 QDBusConnectionPrivate::SignalHookHash::ConstIterator it = d->signalHooks.find(source);
463 for ( ; it != d->signalHooks.end() && it.key() == source; ++it) {
464 const QDBusConnectionPrivate::SignalHook &entry = it.value();
465 if (entry.interface == hook.interface &&
466 entry.name == hook.name &&
467 entry.signature == hook.signature &&
468 entry.obj == hook.obj &&
469 entry.midx == hook.midx) {
470 // no need to compare the parameters if it's the same slot
471 return true; // already there
476 d->connectSignal(source, hook);
481 Registers the object \a object at path \a path and returns true if the registration was
482 successful. The \a options parameter specifies how much of the object \a object will be exposed
485 This function does not replace existing objects: if there is already an object registered at
486 path \a path, this function will return false. Use unregisterObject() to unregister it first.
488 You cannot register an object as a child object of an object that was registered with
489 QDBusConnection::ExportChildObjects.
491 bool QDBusConnection::registerObject(const QString &path, QObject *object, RegisterOptions options)
493 if (!d || !d->connection || !object || !options || !QDBusUtil::isValidObjectPath(path))
496 if (options & ExportSignals) {
497 qWarning("Cannot export signals from objects. Use an adaptor for that purpose.");
501 QStringList pathComponents = path.split(QLatin1Char('/'));
502 if (pathComponents.last().isEmpty())
503 pathComponents.removeLast();
504 QWriteLocker locker(&d->lock);
506 // lower-bound search for where this object should enter in the tree
507 QDBusConnectionPrivate::ObjectTreeNode *node = &d->rootNode;
510 if (pathComponents.count() == i) {
512 // consider it free if there's no object here and the user is not trying to
513 // replace the object sub-tree
514 if ((options & ExportChildObjects && !node->children.isEmpty()) || node->obj)
517 // we can add the object here
519 node->flags = options;
521 d->registerObject(node);
522 qDebug("REGISTERED FOR %s", path.toLocal8Bit().constData());
526 // find the position where we'd insert the node
527 QVector<QDBusConnectionPrivate::ObjectTreeNode::Data>::Iterator it =
528 qLowerBound(node->children.begin(), node->children.end(), pathComponents.at(i));
529 if (it != node->children.constEnd() && it->name == pathComponents.at(i)) {
530 // match: this node exists
533 // are we allowed to go deeper?
534 if (node->flags & ExportChildObjects) {
536 qDebug("Cannot register object at %s because %s exports its own child objects",
537 qPrintable(path), qPrintable(pathComponents.at(i)));
542 QDBusConnectionPrivate::ObjectTreeNode::Data entry;
543 entry.name = pathComponents.at(i);
544 entry.node = new QDBusConnectionPrivate::ObjectTreeNode;
545 node->children.insert(it, entry);
554 Q_ASSERT_X(false, "QDBusConnection::registerObject", "The impossible happened");
559 Unregisters an object that was registered with the registerObject() at the object path given by
560 \a path and, if \a mode is QDBusConnection::UnregisterTree, all of its sub-objects too.
562 Note that you cannot unregister objects that were not registered with registerObject().
564 void QDBusConnection::unregisterObject(const QString &path, UnregisterMode mode)
566 if (!d || !d->connection || !QDBusUtil::isValidObjectPath(path))
569 QStringList pathComponents = path.split(QLatin1Char('/'));
570 QWriteLocker locker(&d->lock);
571 QDBusConnectionPrivate::ObjectTreeNode *node = &d->rootNode;
576 if (pathComponents.count() == i) {
581 if (mode == UnregisterTree) {
582 // clear the sub-tree as well
583 node->clear(); // can't disconnect the objects because we really don't know if they can
584 // be found somewhere else in the path too
590 QVector<QDBusConnectionPrivate::ObjectTreeNode::Data>::ConstIterator it =
591 qLowerBound(node->children.constBegin(), node->children.constEnd(), pathComponents.at(i));
592 if (it == node->children.constEnd() || it->name != pathComponents.at(i))
593 break; // node not found
601 Returns a dynamic QDBusInterface associated with the interface \a interface on object at path \a
602 path on service \a service.
604 This function creates a new object. It is your resposibility to ensure it is properly deleted
605 (you can use all normal QObject deletion mechanisms, including the QObject::deleteLater() slot
606 and QObject::setParent()).
608 If the searching for this interface on the remote object failed, this function returns 0.
610 QDBusInterface *QDBusConnection::findInterface(const QString& service, const QString& path,
611 const QString& interface)
616 QDBusInterfacePrivate *p = d->findInterface(service, path, interface);
619 QDBusInterface *retval = new QDBusInterface(p);
620 retval->setParent(d);
625 \fn QDBusConnection::findInterface(const QString &service, const QString &path)
626 Returns an interface of type \c Interface associated with the object on path \a path at service
629 \c Interface must be a class generated by \l {dbusidl2cpp.html}.
631 This function creates a new object. It is your resposibility to ensure it is properly deleted
632 (you can use all normal QObject deletion mechanisms, including the QObject::deleteLater() slot
633 and QObject::setParent()).
637 Returns a QDBusBusService object that represents the D-Bus bus service on this connection.
639 This function returns 0 for peer-to-peer connections.
641 QDBusBusService *QDBusConnection::busService() const
645 return d->busService;
648 QDBusAbstractInterfacePrivate *
649 QDBusConnection::findInterface_helper(const QString &service, const QString &path,
650 const QString &interface)
654 if (!interface.isEmpty() && !QDBusUtil::isValidInterfaceName(interface))
658 if (!service.isEmpty()) {
659 if (!QDBusUtil::isValidObjectPath(path))
662 // check if it's there first -- FIXME: add binding mode
663 owner = d->getNameOwner(service);
666 } else if (!path.isEmpty())
669 return new QDBusAbstractInterfacePrivate(*this, d, owner, path, interface);
673 Returns true if this QDBusConnection object is connected.
675 If it isn't connected, calling QDBusConnection::addConnection on the same connection name
676 will not make be connected. You need to call the QDBusConnection constructor again.
678 bool QDBusConnection::isConnected( ) const
680 return d && d->connection && dbus_connection_get_is_connected(d->connection);
684 Returns the last error that happened in this connection.
686 This function is provided for low-level code. If you're using QDBusInterface::call, error codes are
687 reported by its return value.
689 \sa QDBusInterface, QDBusMessage
691 QDBusError QDBusConnection::lastError() const
693 return d ? d->lastError : QDBusError();
697 Returns the unique connection name for this connection, if this QDBusConnection object is
698 connected, or an empty QString otherwise.
700 A Unique Connection Name is a string in the form ":x.xxx" (where x are decimal digits) that is
701 assigned by the D-Bus server daemon upon connection. It uniquely identifies this client in the
704 This function returns an empty QString for peer-to-peer connections.
706 QString QDBusConnection::baseService() const
708 return d && d->connection ?
709 QString::fromUtf8(dbus_bus_get_unique_name(d->connection))
713 Q_GLOBAL_STATIC(QMutex, defaultBussesMutex);
714 static const char sessionBusName[] = "qt_default_session_bus";
715 static const char systemBusName[] = "qt_default_system_bus";
716 static QDBusConnection *sessionBus = 0;
717 static QDBusConnection *systemBus = 0;
719 static void closeConnections()
721 QMutexLocker locker(defaultBussesMutex());
724 QDBusConnection::closeConnection(QLatin1String(sessionBusName));
725 QDBusConnection::closeConnection(QLatin1String(systemBusName));
726 sessionBus = systemBus = 0;
729 static QDBusConnection *openConnection(QDBusConnection::BusType type)
731 QMutexLocker locker(defaultBussesMutex());
732 qAddPostRoutine(closeConnections);
734 if (type == QDBusConnection::SystemBus) {
736 // maybe it got created before we locked the mutex
738 systemBus = new QDBusConnection(QDBusConnection::addConnection(QDBusConnection::SystemBus,
739 QLatin1String(systemBusName)));
743 // maybe it got created before we locked the mutex
745 sessionBus = new QDBusConnection(QDBusConnection::addConnection(QDBusConnection::SessionBus,
746 QLatin1String(sessionBusName)));
752 QDBusConnection &sessionBus()
754 if (::sessionBus) return *::sessionBus;
755 return *openConnection(QDBusConnection::SessionBus);
758 QDBusConnection &systemBus()
760 if (::systemBus) return *::systemBus;
761 return *openConnection(QDBusConnection::SystemBus);