src/dbus/qdbusconnection.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtDBus module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include <qdebug.h>
       
    43 #include <qcoreapplication.h>
       
    44 #include <qstringlist.h>
       
    45 
       
    46 #include "qdbusconnection.h"
       
    47 #include "qdbusconnectioninterface.h"
       
    48 #include "qdbuserror.h"
       
    49 #include "qdbusmessage.h"
       
    50 #include "qdbusmessage_p.h"
       
    51 #include "qdbusconnection_p.h"
       
    52 #include "qdbusinterface_p.h"
       
    53 #include "qdbusutil_p.h"
       
    54 
       
    55 #include "qdbusthreaddebug_p.h"
       
    56 
       
    57 QT_BEGIN_NAMESPACE
       
    58 
       
    59 class QDBusConnectionManager
       
    60 {
       
    61 public:
       
    62     QDBusConnectionManager() {}
       
    63     ~QDBusConnectionManager();
       
    64 
       
    65     QDBusConnectionPrivate *connection(const QString &name) const;
       
    66     void removeConnection(const QString &name);
       
    67     void setConnection(const QString &name, QDBusConnectionPrivate *c);
       
    68 
       
    69     QDBusConnectionPrivate *sender() const;
       
    70     void setSender(const QDBusConnectionPrivate *s);
       
    71 
       
    72     mutable QMutex mutex;
       
    73 private:
       
    74     QHash<QString, QDBusConnectionPrivate *> connectionHash;
       
    75 
       
    76     mutable QMutex senderMutex;
       
    77     QString senderName; // internal; will probably change
       
    78 };
       
    79 
       
    80 Q_GLOBAL_STATIC(QDBusConnectionManager, _q_manager)
       
    81 
       
    82 QDBusConnectionPrivate *QDBusConnectionManager::sender() const
       
    83 {
       
    84     QMutexLocker locker(&senderMutex);
       
    85     return connection(senderName);
       
    86 }
       
    87 
       
    88 void QDBusConnectionManager::setSender(const QDBusConnectionPrivate *s)
       
    89 {
       
    90     QMutexLocker locker(&senderMutex);
       
    91     senderName = (s ? s->name : QString());
       
    92 }
       
    93 
       
    94 QDBusConnectionPrivate *QDBusConnectionManager::connection(const QString &name) const
       
    95 {
       
    96     return connectionHash.value(name, 0);
       
    97 }
       
    98 
       
    99 void QDBusConnectionManager::removeConnection(const QString &name)
       
   100 {
       
   101     QDBusConnectionPrivate *d = 0;
       
   102     d = connectionHash.take(name);
       
   103     if (d && !d->ref.deref())
       
   104         d->deleteYourself();
       
   105 
       
   106     // Static objects may be keeping the connection open.
       
   107     // However, it is harmless to have outstanding references to a connection that is
       
   108     // closing as long as those references will be soon dropped without being used.
       
   109 
       
   110     // ### Output a warning if connections are being used after they have been removed.
       
   111 }
       
   112 
       
   113 QDBusConnectionManager::~QDBusConnectionManager()
       
   114 {
       
   115     for (QHash<QString, QDBusConnectionPrivate *>::const_iterator it = connectionHash.constBegin();
       
   116          it != connectionHash.constEnd(); ++it) {
       
   117         QDBusConnectionPrivate *d = it.value();
       
   118         if (!d->ref.deref())
       
   119             d->deleteYourself();
       
   120         else
       
   121             d->closeConnection();
       
   122     }
       
   123     connectionHash.clear();
       
   124 }
       
   125 
       
   126 QDBUS_EXPORT void qDBusBindToApplication();
       
   127 void qDBusBindToApplication()
       
   128 {
       
   129 }
       
   130 
       
   131 void QDBusConnectionManager::setConnection(const QString &name, QDBusConnectionPrivate *c)
       
   132 {
       
   133     connectionHash[name] = c;
       
   134     c->name = name;
       
   135 }
       
   136 
       
   137 /*!
       
   138     \fn QDBusConnection &QDBusConnection::sessionBus()
       
   139     \relates QDBusConnection
       
   140 
       
   141     Returns a QDBusConnection object opened with the session bus. The object reference returned
       
   142     by this function is valid until the QCoreApplication's destructor is run, when the
       
   143     connection will be closed and the object, deleted.
       
   144 */
       
   145 /*!
       
   146     \fn QDBusConnection &QDBusConnection::systemBus()
       
   147     \relates QDBusConnection
       
   148 
       
   149     Returns a QDBusConnection object opened with the system bus. The object reference returned
       
   150     by this function is valid until the QCoreApplication's destructor is run, when the
       
   151     connection will be closed and the object, deleted.
       
   152 */
       
   153 
       
   154 /*!
       
   155     \class QDBusConnection
       
   156     \inmodule QtDBus
       
   157     \since 4.2
       
   158 
       
   159     \brief The QDBusConnection class represents a connection to the D-Bus bus daemon.
       
   160 
       
   161     This class is the initial point in a D-Bus session. Using it, you
       
   162     can get access to remote objects, interfaces; connect remote
       
   163     signals to your object's slots; register objects, etc.
       
   164 
       
   165     D-Bus connections are created using the connectToBus() function,
       
   166     which opens a connection to the server daemon and does the initial
       
   167     handshaking, associating that connection with a name. Further
       
   168     attempts to connect using the same name will return the same
       
   169     connection.
       
   170 
       
   171     The connection is then torn down using the disconnectFromBus()
       
   172     function.
       
   173 
       
   174     As a convenience for the two most common connection types, the
       
   175     sessionBus() and systemBus() functions return open connections to
       
   176     the session server daemon and the system server daemon,
       
   177     respectively. Those connections are opened when first used and are
       
   178     closed when the QCoreApplication destructor is run.
       
   179 
       
   180     D-Bus also supports peer-to-peer connections, without the need for
       
   181     a bus server daemon. Using this facility, two applications can
       
   182     talk to each other and exchange messages. This can be achieved by
       
   183     passing an address to connectToBus() function, which was opened by
       
   184     another D-Bus application using QDBusServer.
       
   185 */
       
   186 
       
   187 /*!
       
   188     \enum QDBusConnection::BusType
       
   189     Specifies the type of the bus connection. The valid bus types are:
       
   190 
       
   191     \value SessionBus           the session bus, associated with the running desktop session
       
   192     \value SystemBus            the system bus, used to communicate with system-wide processes
       
   193     \value ActivationBus        the activation bus, the "alias" for the bus that started the
       
   194                                 service
       
   195 
       
   196     On the Session Bus, one can find other applications by the same user that are sharing the same
       
   197     desktop session (hence the name). On the System Bus, however, processes shared for the whole
       
   198     system are usually found.
       
   199 */
       
   200 
       
   201 /*!
       
   202     \enum QDBusConnection::RegisterOption
       
   203     Specifies the options for registering objects with the connection. The possible values are:
       
   204 
       
   205     \value ExportAdaptors                       export the contents of adaptors found in this object
       
   206 
       
   207     \value ExportScriptableSlots                export this object's scriptable slots
       
   208     \value ExportScriptableSignals              export this object's scriptable signals
       
   209     \value ExportScriptableProperties           export this object's scriptable properties
       
   210     \value ExportScriptableContents             shorthand form for ExportScriptableSlots |
       
   211                                                 ExportScriptableSignals |
       
   212                                                 ExportScriptableProperties
       
   213 
       
   214     \value ExportNonScriptableSlots             export this object's non-scriptable slots
       
   215     \value ExportNonScriptableSignals           export this object's non-scriptable signals
       
   216     \value ExportNonScriptableProperties        export this object's non-scriptable properties
       
   217     \value ExportNonScriptableContents          shorthand form for ExportNonScriptableSlots |
       
   218                                                 ExportNonScriptableSignals |
       
   219                                                 ExportNonScriptableProperties
       
   220 
       
   221     \value ExportAllSlots                       export all of this object's slots
       
   222     \value ExportAllSignals                     export all of this object's signals
       
   223     \value ExportAllProperties                  export all of this object's properties
       
   224     \value ExportAllContents                    export all of this object's contents
       
   225 
       
   226     \value ExportChildObjects                   export this object's child objects
       
   227 
       
   228     \sa registerObject(), QDBusAbstractAdaptor, {usingadaptors.html}{Using adaptors}
       
   229 */
       
   230 
       
   231 /*!
       
   232     \enum QDBusConnection::UnregisterMode
       
   233     The mode for unregistering an object path:
       
   234 
       
   235     \value UnregisterNode       unregister this node only: do not unregister child objects
       
   236     \value UnregisterTree       unregister this node and all its sub-tree
       
   237 
       
   238     Note, however, if this object was registered with the ExportChildObjects option, UnregisterNode
       
   239     will unregister the child objects too.
       
   240 */
       
   241 
       
   242 /*!
       
   243     Creates a QDBusConnection object attached to the connection with name \a name.
       
   244 
       
   245     This does not open the connection. You have to call connectToBus() to open it.
       
   246 */
       
   247 QDBusConnection::QDBusConnection(const QString &name)
       
   248 {
       
   249     if (name.isEmpty()) {
       
   250         d = 0;
       
   251     } else {
       
   252         QMutexLocker locker(&_q_manager()->mutex);
       
   253         d = _q_manager()->connection(name);
       
   254         if (d)
       
   255             d->ref.ref();
       
   256     }
       
   257 }
       
   258 
       
   259 /*!
       
   260     Creates a copy of the \a other connection.
       
   261 */
       
   262 QDBusConnection::QDBusConnection(const QDBusConnection &other)
       
   263 {
       
   264     d = other.d;
       
   265     if (d)
       
   266         d->ref.ref();
       
   267 }
       
   268 
       
   269 /*!
       
   270   \internal
       
   271    Creates a connection object with the given \a dd as private object.
       
   272 */
       
   273 QDBusConnection::QDBusConnection(QDBusConnectionPrivate *dd)
       
   274 {
       
   275     d = dd;
       
   276     if (d)
       
   277         d->ref.ref();
       
   278 }
       
   279 
       
   280 /*!
       
   281     Disposes of this object. This does not close the connection: you
       
   282     have to call disconnectFromBus() to do that.
       
   283 */
       
   284 QDBusConnection::~QDBusConnection()
       
   285 {
       
   286     if (d && !d->ref.deref())
       
   287         d->deleteYourself();
       
   288 }
       
   289 
       
   290 /*!
       
   291     Creates a copy of the connection \a other in this object. Note
       
   292     that the connection this object referenced before the copy, is not
       
   293     spontaneously disconnected.
       
   294 
       
   295     \sa disconnectFromBus()
       
   296 */
       
   297 QDBusConnection &QDBusConnection::operator=(const QDBusConnection &other)
       
   298 {
       
   299     if (other.d)
       
   300         other.d->ref.ref();
       
   301     if (d && !d->ref.deref())
       
   302         d->deleteYourself();
       
   303     d = other.d;
       
   304     return *this;
       
   305 }
       
   306 
       
   307 /*!
       
   308     Opens a connection of type \a type to one of the known busses and
       
   309     associate with it the connection name \a name. Returns a
       
   310     QDBusConnection object associated with that connection.
       
   311 */
       
   312 QDBusConnection QDBusConnection::connectToBus(BusType type, const QString &name)
       
   313 {
       
   314 //    Q_ASSERT_X(QCoreApplication::instance(), "QDBusConnection::addConnection",
       
   315 //               "Cannot create connection without a Q[Core]Application instance");
       
   316     if (!qdbus_loadLibDBus()) {
       
   317         QDBusConnectionPrivate *d = 0;
       
   318         return QDBusConnection(d);
       
   319     }
       
   320 
       
   321     QMutexLocker locker(&_q_manager()->mutex);
       
   322 
       
   323     QDBusConnectionPrivate *d = _q_manager()->connection(name);
       
   324     if (d || name.isEmpty())
       
   325         return QDBusConnection(d);
       
   326 
       
   327     d = new QDBusConnectionPrivate;
       
   328     DBusConnection *c = 0;
       
   329     QDBusErrorInternal error;
       
   330     switch (type) {
       
   331         case SystemBus:
       
   332             c = q_dbus_bus_get_private(DBUS_BUS_SYSTEM, error);
       
   333             break;
       
   334         case SessionBus:
       
   335             c = q_dbus_bus_get_private(DBUS_BUS_SESSION, error);
       
   336             break;
       
   337         case ActivationBus:
       
   338             c = q_dbus_bus_get_private(DBUS_BUS_STARTER, error);
       
   339             break;
       
   340     }
       
   341     d->setConnection(c, error); //setConnection does the error handling for us
       
   342 
       
   343     _q_manager()->setConnection(name, d);
       
   344 
       
   345     QDBusConnection retval(d);
       
   346 
       
   347     // create the bus service
       
   348     // will lock in QDBusConnectionPrivate::connectRelay()
       
   349     d->setBusService(retval);
       
   350 
       
   351     return retval;
       
   352 }
       
   353 
       
   354 /*!
       
   355     Opens a peer-to-peer connection on address \a address and associate with it the
       
   356     connection name \a name. Returns a QDBusConnection object associated with that connection.
       
   357 */
       
   358 QDBusConnection QDBusConnection::connectToBus(const QString &address,
       
   359                                               const QString &name)
       
   360 {
       
   361 //    Q_ASSERT_X(QCoreApplication::instance(), "QDBusConnection::addConnection",
       
   362 //               "Cannot create connection without a Q[Core]Application instance");
       
   363     if (!qdbus_loadLibDBus()){
       
   364         QDBusConnectionPrivate *d = 0;
       
   365         return QDBusConnection(d);
       
   366     }
       
   367 
       
   368     QMutexLocker locker(&_q_manager()->mutex);
       
   369 
       
   370     QDBusConnectionPrivate *d = _q_manager()->connection(name);
       
   371     if (d || name.isEmpty())
       
   372         return QDBusConnection(d);
       
   373 
       
   374     d = new QDBusConnectionPrivate;
       
   375     // setConnection does the error handling for us
       
   376     QDBusErrorInternal error;
       
   377     DBusConnection *c = q_dbus_connection_open_private(address.toUtf8().constData(), error);
       
   378     if (c) {
       
   379         if (!q_dbus_bus_register(c, error)) {
       
   380             q_dbus_connection_unref(c);
       
   381             c = 0;
       
   382         }
       
   383     }
       
   384     d->setConnection(c, error);
       
   385     _q_manager()->setConnection(name, d);
       
   386 
       
   387     QDBusConnection retval(d);
       
   388 
       
   389     // create the bus service
       
   390     // will lock in QDBusConnectionPrivate::connectRelay()
       
   391     d->setBusService(retval);
       
   392 
       
   393     return retval;
       
   394 }
       
   395 
       
   396 /*!
       
   397     Closes the connection of name \a name.
       
   398 
       
   399     Note that if there are still QDBusConnection objects associated
       
   400     with the same connection, the connection will not be closed until
       
   401     all references are dropped. However, no further references can be
       
   402     created using the QDBusConnection constructor.
       
   403 */
       
   404 void QDBusConnection::disconnectFromBus(const QString &name)
       
   405 {
       
   406     if (_q_manager()) {
       
   407         QMutexLocker locker(&_q_manager()->mutex);
       
   408         _q_manager()->removeConnection(name);
       
   409     }
       
   410 }
       
   411 
       
   412 /*!
       
   413     Sends the \a message over this connection, without waiting for a
       
   414     reply. This is suitable for errors, signals, and return values as
       
   415     well as calls whose return values are not necessary.
       
   416 
       
   417     Returns true if the message was queued successfully, false otherwise.
       
   418 */
       
   419 bool QDBusConnection::send(const QDBusMessage &message) const
       
   420 {
       
   421     if (!d || !d->connection) {
       
   422         QDBusError err = QDBusError(QDBusError::Disconnected,
       
   423                                     QLatin1String("Not connected to D-BUS server"));
       
   424         if (d)
       
   425             d->lastError = err;
       
   426         return false;
       
   427     }
       
   428     return d->send(message) != 0;
       
   429 }
       
   430 
       
   431 /*!
       
   432     Sends the \a message over this connection and returns immediately.
       
   433     When the reply is received, the method \a returnMethod is called in
       
   434     the \a receiver object. If an error occurs, the method \a errorMethod
       
   435     will be called instead.
       
   436 
       
   437     If no reply is received within \a timeout milliseconds, an automatic
       
   438     error will be delivered indicating the expiration of the call.
       
   439     The default \a timeout is -1, which will be replaced with an
       
   440     implementation-defined value that is suitable for inter-process
       
   441     communications (generally, 25 seconds).
       
   442 
       
   443     This function is suitable for method calls only. It is guaranteed
       
   444     that the slot will be called exactly once with the reply, as long
       
   445     as the parameter types match and no error occurs.
       
   446 
       
   447     Returns true if the message was sent, or false if the message could
       
   448     not be sent.
       
   449 */
       
   450 bool QDBusConnection::callWithCallback(const QDBusMessage &message, QObject *receiver,
       
   451                                        const char *returnMethod, const char *errorMethod,
       
   452                                        int timeout) const
       
   453 {
       
   454     if (!d || !d->connection) {
       
   455         QDBusError err = QDBusError(QDBusError::Disconnected,
       
   456                                     QLatin1String("Not connected to D-BUS server"));
       
   457         if (d)
       
   458             d->lastError = err;
       
   459         return false;
       
   460     }
       
   461     return d->sendWithReplyAsync(message, receiver, returnMethod, errorMethod, timeout) != 0;
       
   462 }
       
   463 
       
   464 /*!
       
   465     \overload
       
   466     \deprecated
       
   467     Sends the \a message over this connection and returns immediately.
       
   468     When the reply is received, the method \a returnMethod is called in
       
   469     the \a receiver object.
       
   470 
       
   471     This function is suitable for method calls only. It is guaranteed
       
   472     that the slot will be called exactly once with the reply, as long
       
   473     as the parameter types match and no error occurs.
       
   474 
       
   475     This function is dangerous because it cannot report errors, including
       
   476     the expiration of the timeout.
       
   477 
       
   478     Returns true if the message was sent, or false if the message could
       
   479     not be sent.
       
   480 */
       
   481 bool QDBusConnection::callWithCallback(const QDBusMessage &message, QObject *receiver,
       
   482                                        const char *returnMethod, int timeout) const
       
   483 {
       
   484     return callWithCallback(message, receiver, returnMethod, 0, timeout);
       
   485 }
       
   486 
       
   487 /*!
       
   488     Sends the \a message over this connection and blocks, waiting for
       
   489     a reply, for at most \a timeout milliseconds. This function is
       
   490     suitable for method calls only. It returns the reply message as
       
   491     its return value, which will be either of type
       
   492     QDBusMessage::ReplyMessage or QDBusMessage::ErrorMessage.
       
   493 
       
   494     See the QDBusInterface::call() function for a more friendly way
       
   495     of placing calls.
       
   496 
       
   497     \warning If \a mode is QDBus::BlockWithGui, this function will
       
   498              reenter the Qt event loop in order to wait for the
       
   499              reply. During the wait, it may deliver signals and other
       
   500              method calls to your application. Therefore, it must be
       
   501              prepared to handle a reentrancy whenever a call is
       
   502              placed with call().
       
   503 */
       
   504 QDBusMessage QDBusConnection::call(const QDBusMessage &message, QDBus::CallMode mode, int timeout) const
       
   505 {
       
   506     if (!d || !d->connection) {
       
   507         QDBusError err = QDBusError(QDBusError::Disconnected,
       
   508                                     QLatin1String("Not connected to D-Bus server"));
       
   509         if (d)
       
   510             d->lastError = err;
       
   511 
       
   512         return QDBusMessage::createError(err);
       
   513     }
       
   514 
       
   515     if (mode != QDBus::NoBlock)
       
   516         return d->sendWithReply(message, mode, timeout);
       
   517 
       
   518     d->send(message);
       
   519     QDBusMessage retval;
       
   520     retval << QVariant(); // add one argument (to avoid .at(0) problems)
       
   521     return retval;
       
   522 }
       
   523 
       
   524 /*!
       
   525     \since 4.5
       
   526     Sends the \a message over this connection and returns
       
   527     immediately. This function is suitable for method calls only. It
       
   528     returns an object of type QDBusPendingCall which can be used to
       
   529     track the status of the reply. The \a timeout parameter is used to
       
   530     determine when an auto-generated error reply may be emitted and is
       
   531     also the upper limit for waiting in QDBusPendingCall::waitForFinished().
       
   532 
       
   533     See the QDBusInterface::asyncCall() function for a more friendly way
       
   534     of placing calls.
       
   535 */
       
   536 QDBusPendingCall QDBusConnection::asyncCall(const QDBusMessage &message, int timeout) const
       
   537 {
       
   538     if (!d || !d->connection) {
       
   539         return QDBusPendingCall(0); // null pointer -> disconnected
       
   540     }
       
   541 
       
   542     QDBusPendingCallPrivate *priv = d->sendWithReplyAsync(message, timeout);
       
   543     return QDBusPendingCall(priv);
       
   544 }
       
   545 
       
   546 /*!
       
   547     Connects the signal specified by the \a service, \a path, \a interface and \a name parameters to
       
   548     the slot \a slot in object \a receiver. The arguments \a service and \a path can be empty,
       
   549     denoting a connection to any signal of the (\a interface, \a name) pair, from any remote
       
   550     application.
       
   551 
       
   552     Returns true if the connection was successful.
       
   553 
       
   554     \warning The signal will only be delivered to the slot if the parameters match. This verification
       
   555              can be done only when the signal is received, not at connection time.
       
   556 */
       
   557 bool QDBusConnection::connect(const QString &service, const QString &path, const QString& interface,
       
   558                               const QString &name, QObject *receiver, const char *slot)
       
   559 {
       
   560     return connect(service, path, interface, name, QString(), receiver, slot);
       
   561 }
       
   562 
       
   563 /*!
       
   564     Disconnects the signal specified by the \a service, \a path, \a interface and \a name parameters from
       
   565     the slot \a slot in object \a receiver. The arguments \a service and \a path can be empty,
       
   566     denoting a disconnection from all signals of the (\a interface, \a name) pair, from all remote
       
   567     applications.
       
   568 
       
   569     Returns true if the disconnection was successful.
       
   570 */
       
   571 bool QDBusConnection::disconnect(const QString &service, const QString &path, const QString &interface,
       
   572                                  const QString &name, QObject *receiver, const char *slot)
       
   573 {
       
   574     return disconnect(service, path, interface, name, QString(), receiver, slot);
       
   575 }
       
   576 
       
   577 /*!
       
   578     \overload
       
   579 
       
   580     Connects the signal to the slot \a slot in object \a
       
   581     receiver. Unlike the other connect() overload, this function
       
   582     allows one to specify the parameter signature to be connected
       
   583     using the \a signature variable. The function will then verify
       
   584     that this signature can be delivered to the slot specified by \a
       
   585     slot and return false otherwise.
       
   586 
       
   587     \note This function verifies that the signal signature matches the
       
   588           slot's parameters, but it does not verify that the actual
       
   589           signal exists with the given signature in the remote
       
   590           service.
       
   591 */
       
   592 bool QDBusConnection::connect(const QString &service, const QString &path, const QString& interface,
       
   593                               const QString &name, const QString &signature,
       
   594                               QObject *receiver, const char *slot)
       
   595 {
       
   596     if (!receiver || !slot || !d || !d->connection)
       
   597         return false;
       
   598     if (!interface.isEmpty() && !QDBusUtil::isValidInterfaceName(interface))
       
   599         return false;
       
   600     if (interface.isEmpty() && name.isEmpty())
       
   601         return false;
       
   602 
       
   603     // check the slot
       
   604     QDBusConnectionPrivate::SignalHook hook;
       
   605     QString key;
       
   606     QString name2 = name;
       
   607     if (name2.isNull())
       
   608         name2.detach();
       
   609 
       
   610     QString owner = d->getNameOwner(service); // we don't care if the owner is empty
       
   611     hook.signature = signature;               // it might get started later
       
   612     if (!d->prepareHook(hook, key, service, owner, path, interface, name, receiver, slot, 0, false))
       
   613         return false;           // don't connect
       
   614 
       
   615     // avoid duplicating:
       
   616     QDBusWriteLocker locker(ConnectAction, d);
       
   617     QDBusConnectionPrivate::SignalHookHash::ConstIterator it = d->signalHooks.find(key);
       
   618     QDBusConnectionPrivate::SignalHookHash::ConstIterator end = d->signalHooks.constEnd();
       
   619     for ( ; it != end && it.key() == key; ++it) {
       
   620         const QDBusConnectionPrivate::SignalHook &entry = it.value();
       
   621         if (entry.service == hook.service &&
       
   622             entry.owner == hook.owner &&
       
   623             entry.path == hook.path &&
       
   624             entry.signature == hook.signature &&
       
   625             entry.obj == hook.obj &&
       
   626             entry.midx == hook.midx) {
       
   627             // no need to compare the parameters if it's the same slot
       
   628             return true;        // already there
       
   629         }
       
   630     }
       
   631 
       
   632     d->connectSignal(key, hook);
       
   633     return true;
       
   634 }
       
   635 
       
   636 /*!
       
   637     \overload
       
   638 
       
   639     Disconnects the signal from the slot \a slot in object \a
       
   640     receiver. Unlike the other disconnect() overload, this function
       
   641     allows one to specify the parameter signature to be disconnected
       
   642     using the \a signature variable. The function will then verify
       
   643     that this signature is connected to the slot specified by \a slot
       
   644     and return false otherwise.
       
   645 */
       
   646 bool QDBusConnection::disconnect(const QString &service, const QString &path, const QString& interface,
       
   647                                  const QString &name, const QString &signature,
       
   648                                  QObject *receiver, const char *slot)
       
   649 {
       
   650     if (!receiver || !slot || !d || !d->connection)
       
   651         return false;
       
   652     if (!interface.isEmpty() && !QDBusUtil::isValidInterfaceName(interface))
       
   653         return false;
       
   654     if (interface.isEmpty() && name.isEmpty())
       
   655         return false;
       
   656 
       
   657     // check the slot
       
   658     QDBusConnectionPrivate::SignalHook hook;
       
   659     QString key;
       
   660     QString name2 = name;
       
   661     if (name2.isNull())
       
   662         name2.detach();
       
   663 
       
   664     QString owner = d->getNameOwner(service); // we don't care of owner is empty
       
   665     hook.signature = signature;
       
   666     if (!d->prepareHook(hook, key, service, owner, path, interface, name, receiver, slot, 0, false))
       
   667         return false;           // don't disconnect
       
   668 
       
   669     // avoid duplicating:
       
   670     QDBusWriteLocker locker(DisconnectAction, d);
       
   671     QDBusConnectionPrivate::SignalHookHash::Iterator it = d->signalHooks.find(key);
       
   672     QDBusConnectionPrivate::SignalHookHash::Iterator end = d->signalHooks.end();
       
   673     for ( ; it != end && it.key() == key; ++it) {
       
   674         const QDBusConnectionPrivate::SignalHook &entry = it.value();
       
   675         if (entry.service == hook.service &&
       
   676             entry.owner == hook.owner &&
       
   677             entry.path == hook.path &&
       
   678             entry.signature == hook.signature &&
       
   679             entry.obj == hook.obj &&
       
   680             entry.midx == hook.midx) {
       
   681             // no need to compare the parameters if it's the same slot
       
   682             d->disconnectSignal(it);
       
   683             return true;        // it was there
       
   684         }
       
   685     }
       
   686 
       
   687     // the slot was not found
       
   688     return false;
       
   689 }
       
   690 
       
   691 /*!
       
   692     Registers the object \a object at path \a path and returns true if
       
   693     the registration was successful. The \a options parameter
       
   694     specifies how much of the object \a object will be exposed through
       
   695     D-Bus.
       
   696 
       
   697     This function does not replace existing objects: if there is already an object registered at
       
   698     path \a path, this function will return false. Use unregisterObject() to unregister it first.
       
   699 
       
   700     You cannot register an object as a child object of an object that
       
   701     was registered with QDBusConnection::ExportChildObjects.
       
   702 */
       
   703 bool QDBusConnection::registerObject(const QString &path, QObject *object, RegisterOptions options)
       
   704 {
       
   705     Q_ASSERT_X(QDBusUtil::isValidObjectPath(path), "QDBusConnection::registerObject",
       
   706                "Invalid object path given");
       
   707     if (!d || !d->connection || !object || !options || !QDBusUtil::isValidObjectPath(path))
       
   708         return false;
       
   709 
       
   710     QStringList pathComponents = path.split(QLatin1Char('/'));
       
   711     if (pathComponents.last().isEmpty())
       
   712         pathComponents.removeLast();
       
   713     QDBusWriteLocker locker(RegisterObjectAction, d);
       
   714 
       
   715     // lower-bound search for where this object should enter in the tree
       
   716     QDBusConnectionPrivate::ObjectTreeNode *node = &d->rootNode;
       
   717     int i = 1;
       
   718     while (node) {
       
   719         if (pathComponents.count() == i) {
       
   720             // this node exists
       
   721             // consider it free if there's no object here and the user is not trying to
       
   722             // replace the object sub-tree
       
   723             if ((options & ExportChildObjects && !node->children.isEmpty()) || node->obj)
       
   724                 return false;
       
   725 
       
   726             // we can add the object here
       
   727             node->obj = object;
       
   728             node->flags = options;
       
   729 
       
   730             d->registerObject(node);
       
   731             //qDebug("REGISTERED FOR %s", path.toLocal8Bit().constData());
       
   732             return true;
       
   733         }
       
   734 
       
   735         // find the position where we'd insert the node
       
   736         QDBusConnectionPrivate::ObjectTreeNode::DataList::Iterator it =
       
   737             qLowerBound(node->children.begin(), node->children.end(), pathComponents.at(i));
       
   738         if (it != node->children.end() && it->name == pathComponents.at(i)) {
       
   739             // match: this node exists
       
   740             node = it;
       
   741 
       
   742             // are we allowed to go deeper?
       
   743             if (node->flags & ExportChildObjects) {
       
   744                 // we're not
       
   745                 qDebug("Cannot register object at %s because %s exports its own child objects",
       
   746                        qPrintable(path), qPrintable(pathComponents.at(i)));
       
   747                 return false;
       
   748             }
       
   749         } else {
       
   750             // add entry
       
   751             node = node->children.insert(it, pathComponents.at(i));
       
   752         }
       
   753 
       
   754         // iterate
       
   755         ++i;
       
   756     }
       
   757 
       
   758     Q_ASSERT_X(false, "QDBusConnection::registerObject", "The impossible happened");
       
   759     return false;
       
   760 }
       
   761 
       
   762 /*!
       
   763     Unregisters an object that was registered with the registerObject() at the object path given by
       
   764     \a path and, if \a mode is QDBusConnection::UnregisterTree, all of its sub-objects too.
       
   765 
       
   766     Note that you cannot unregister objects that were not registered with registerObject().
       
   767 */
       
   768 void QDBusConnection::unregisterObject(const QString &path, UnregisterMode mode)
       
   769 {
       
   770     if (!d || !d->connection || !QDBusUtil::isValidObjectPath(path))
       
   771         return;
       
   772 
       
   773     QStringList pathComponents = path.split(QLatin1Char('/'));
       
   774     QDBusWriteLocker locker(UnregisterObjectAction, d);
       
   775     QDBusConnectionPrivate::ObjectTreeNode *node = &d->rootNode;
       
   776     int i = 1;
       
   777 
       
   778     // find the object
       
   779     while (node) {
       
   780         if (pathComponents.count() == i) {
       
   781             // found it
       
   782             node->obj = 0;
       
   783             node->flags = 0;
       
   784 
       
   785             if (mode == UnregisterTree) {
       
   786                 // clear the sub-tree as well
       
   787                 node->children.clear();  // can't disconnect the objects because we really don't know if they can
       
   788                                 // be found somewhere else in the path too
       
   789             }
       
   790 
       
   791             return;
       
   792         }
       
   793 
       
   794         QDBusConnectionPrivate::ObjectTreeNode::DataList::Iterator it =
       
   795             qLowerBound(node->children.begin(), node->children.end(), pathComponents.at(i));
       
   796         if (it == node->children.end() || it->name != pathComponents.at(i))
       
   797             break;              // node not found
       
   798 
       
   799         node = it;
       
   800         ++i;
       
   801     }
       
   802 }
       
   803 
       
   804 /*!
       
   805     Return the object that was registered with the registerObject() at the object path given by
       
   806     \a path.
       
   807 */
       
   808 QObject *QDBusConnection::objectRegisteredAt(const QString &path) const
       
   809 {
       
   810     Q_ASSERT_X(QDBusUtil::isValidObjectPath(path), "QDBusConnection::registeredObject",
       
   811                "Invalid object path given");
       
   812     if (!d || !d->connection || !QDBusUtil::isValidObjectPath(path))
       
   813         return false;
       
   814 
       
   815     QStringList pathComponents = path.split(QLatin1Char('/'));
       
   816     if (pathComponents.last().isEmpty())
       
   817         pathComponents.removeLast();
       
   818 
       
   819     // lower-bound search for where this object should enter in the tree
       
   820     QDBusReadLocker lock(ObjectRegisteredAtAction, d);
       
   821     const QDBusConnectionPrivate::ObjectTreeNode *node = &d->rootNode;
       
   822 
       
   823     int i = 1;
       
   824     while (node) {
       
   825         if (pathComponents.count() == i)
       
   826             return node->obj;
       
   827 
       
   828         QDBusConnectionPrivate::ObjectTreeNode::DataList::ConstIterator it =
       
   829             qLowerBound(node->children.constBegin(), node->children.constEnd(), pathComponents.at(i));
       
   830         if (it == node->children.constEnd() || it->name != pathComponents.at(i))
       
   831             break;              // node not found
       
   832 
       
   833         node = it;
       
   834         ++i;
       
   835     }
       
   836     return 0;
       
   837 }
       
   838 
       
   839 /*!
       
   840     Returns a QDBusConnectionInterface object that represents the
       
   841     D-Bus server interface on this connection.
       
   842 */
       
   843 QDBusConnectionInterface *QDBusConnection::interface() const
       
   844 {
       
   845     if (!d)
       
   846         return 0;
       
   847     return d->busService;
       
   848 }
       
   849 
       
   850 /*!
       
   851     Returns true if this QDBusConnection object is connected.
       
   852 
       
   853     If it isn't connected, calling connectToBus() on the same
       
   854     connection name will not make be connected. You need to call the
       
   855     QDBusConnection constructor again.
       
   856 */
       
   857 bool QDBusConnection::isConnected() const
       
   858 {
       
   859     return d && d->connection && q_dbus_connection_get_is_connected(d->connection);
       
   860 }
       
   861 
       
   862 /*!
       
   863     Returns the last error that happened in this connection.
       
   864 
       
   865     This function is provided for low-level code. If you're using
       
   866     QDBusInterface::call(), error codes are reported by its return
       
   867     value.
       
   868 
       
   869     \sa QDBusInterface, QDBusMessage
       
   870 */
       
   871 QDBusError QDBusConnection::lastError() const
       
   872 {
       
   873     return d ? d->lastError : QDBusError();
       
   874 }
       
   875 
       
   876 /*!
       
   877     Returns the unique connection name for this connection, if this QDBusConnection object is
       
   878     connected, or an empty QString otherwise.
       
   879 
       
   880     A Unique Connection Name is a string in the form ":x.xxx" (where x
       
   881     are decimal digits) that is assigned by the D-Bus server daemon
       
   882     upon connection. It uniquely identifies this client in the bus.
       
   883 
       
   884     This function returns an empty QString for peer-to-peer connections.
       
   885 */
       
   886 QString QDBusConnection::baseService() const
       
   887 {
       
   888     return d ? d->baseService : QString();
       
   889 }
       
   890 
       
   891 /*!
       
   892     \since 4.5
       
   893 
       
   894     Returns the connection name for this connection, as given as the
       
   895     name parameter to connectToBus().
       
   896 
       
   897     The connection name can be used to uniquely identify actual
       
   898     underlying connections to buses.  Copies made from a single
       
   899     connection will always implicitly share the underlying connection,
       
   900     and hence will have the same connection name.
       
   901 
       
   902     Inversely, two connections having different connection names will
       
   903     always either be connected to different buses, or have a different
       
   904     unique name (as returned by baseService()) on that bus.
       
   905 
       
   906     \sa connectToBus(), disconnectFromBus()
       
   907 */
       
   908 QString QDBusConnection::name() const
       
   909 {
       
   910     return d ? d->name : QString();
       
   911 }
       
   912 
       
   913 /*!
       
   914     Attempts to register the \a serviceName on the D-Bus server and
       
   915     returns true if the registration succeded. The registration will
       
   916     fail if the name is already registered by another application.
       
   917 
       
   918     \sa unregisterService(), QDBusConnectionInterface::registerService()
       
   919 */
       
   920 bool QDBusConnection::registerService(const QString &serviceName)
       
   921 {
       
   922     if (interface() && interface()->registerService(serviceName)) {
       
   923         if (d) d->registerService(serviceName);
       
   924         return true;
       
   925     }
       
   926     return false;
       
   927 }
       
   928 
       
   929 /*!
       
   930     Unregisters the service \a serviceName that was previously
       
   931     registered with registerService() and returns true if it
       
   932     succeeded.
       
   933 
       
   934     \sa registerService(), QDBusConnectionInterface::unregisterService()
       
   935 */
       
   936 bool QDBusConnection::unregisterService(const QString &serviceName)
       
   937 {
       
   938     if (interface()->unregisterService(serviceName)) {
       
   939         if (d) d->unregisterService(serviceName);
       
   940         return true;
       
   941     }
       
   942     return false;
       
   943 }
       
   944 
       
   945 static const char _q_sessionBusName[] = "qt_default_session_bus";
       
   946 static const char _q_systemBusName[] = "qt_default_system_bus";
       
   947 
       
   948 class QDBusDefaultConnection: public QDBusConnection
       
   949 {
       
   950     const char *ownName;
       
   951 public:
       
   952     inline QDBusDefaultConnection(BusType type, const char *name)
       
   953         : QDBusConnection(connectToBus(type, QString::fromLatin1(name))), ownName(name)
       
   954     { }
       
   955 
       
   956     inline ~QDBusDefaultConnection()
       
   957     { disconnectFromBus(QString::fromLatin1(ownName)); }
       
   958 };
       
   959 
       
   960 Q_GLOBAL_STATIC_WITH_ARGS(QDBusDefaultConnection, _q_sessionBus,
       
   961                           (QDBusConnection::SessionBus, _q_sessionBusName))
       
   962 Q_GLOBAL_STATIC_WITH_ARGS(QDBusDefaultConnection, _q_systemBus,
       
   963                           (QDBusConnection::SystemBus, _q_systemBusName))
       
   964 
       
   965 QDBusConnection QDBusConnection::sessionBus()
       
   966 {
       
   967     return *_q_sessionBus();
       
   968 }
       
   969 
       
   970 QDBusConnection QDBusConnection::systemBus()
       
   971 {
       
   972     return *_q_systemBus();
       
   973 }
       
   974 
       
   975 /*!
       
   976   \nonreentrant
       
   977 
       
   978   Returns the connection that sent the signal, if called in a slot activated
       
   979   by QDBus; otherwise it returns 0.
       
   980 
       
   981   \note Please avoid this function. This function is not thread-safe, so if
       
   982   there's any other thread delivering a D-Bus call, this function may return
       
   983   the wrong connection. In new code, please use QDBusContext::connection()
       
   984   (see that class for a description on how to use it).
       
   985 */
       
   986 QDBusConnection QDBusConnection::sender()
       
   987 {
       
   988     return QDBusConnection(_q_manager()->sender());
       
   989 }
       
   990 
       
   991 /*!
       
   992   \internal
       
   993 */
       
   994 void QDBusConnectionPrivate::setSender(const QDBusConnectionPrivate *s)
       
   995 {
       
   996     _q_manager()->setSender(s);
       
   997 }
       
   998 
       
   999 /*!
       
  1000   \internal
       
  1001 */
       
  1002 void QDBusConnectionPrivate::setConnection(const QString &name, QDBusConnectionPrivate *c)
       
  1003 {
       
  1004     _q_manager()->setConnection(name, c);
       
  1005 }
       
  1006 
       
  1007 /*!
       
  1008   \internal
       
  1009 */
       
  1010 void QDBusConnectionPrivate::setBusService(const QDBusConnection &connection)
       
  1011 {
       
  1012     busService = new QDBusConnectionInterface(connection, this);
       
  1013     ref.deref(); // busService has increased the refcounting to us
       
  1014                  // avoid cyclic refcounting
       
  1015 //    if (mode != PeerMode)
       
  1016     QObject::connect(busService, SIGNAL(serviceOwnerChanged(QString,QString,QString)),
       
  1017                      this, SIGNAL(serviceOwnerChanged(QString,QString,QString)));
       
  1018 
       
  1019     QObject::connect(this, SIGNAL(callWithCallbackFailed(QDBusError,QDBusMessage)),
       
  1020                      busService, SIGNAL(callWithCallbackFailed(QDBusError,QDBusMessage)),
       
  1021                      Qt::QueuedConnection);
       
  1022 
       
  1023 }
       
  1024 
       
  1025 /*!
       
  1026     \namespace QDBus
       
  1027     \inmodule QtDBus
       
  1028 
       
  1029     \brief The QDBus namespace contains miscellaneous identifiers used
       
  1030     throughout the QtDBus library.
       
  1031 */
       
  1032 
       
  1033 /*!
       
  1034     \enum QDBus::CallMode
       
  1035 
       
  1036     This enum describes the various ways of placing a function call. The valid modes are:
       
  1037 
       
  1038     \value NoBlock              Place the call but don't wait for the reply (the reply's contents
       
  1039                                 will be discarded).
       
  1040     \value Block                Don't use an event loop to wait for a reply, but instead block on
       
  1041                                 network operations while waiting. This means the
       
  1042                                 user-interface may not be updated until the function returns.
       
  1043     \value BlockWithGui         Use the Qt event loop to wait for a reply. This means that the
       
  1044                                 user-interface will stay responsive (processing input events),
       
  1045                                 but it also means other events may happen, like signal delivery
       
  1046                                 and other D-Bus method calls.
       
  1047     \value AutoDetect           Automatically detect if the called function has a reply.
       
  1048 
       
  1049     When using BlockWithGui, applications must be prepared for reentrancy in any function.
       
  1050 */
       
  1051 
       
  1052 QT_END_NAMESPACE