source: trunk/src/dbus/qdbusconnection.cpp@ 276

Last change on this file since 276 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 36.6 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information (qt-info@nokia.com)
5**
6** This file is part of the QtDBus module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at qt-sales@nokia.com.
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
57QT_BEGIN_NAMESPACE
58
59class QDBusConnectionManager
60{
61public:
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;
73private:
74 QHash<QString, QDBusConnectionPrivate *> connectionHash;
75
76 mutable QMutex senderMutex;
77 QString senderName; // internal; will probably change
78};
79
80Q_GLOBAL_STATIC(QDBusConnectionManager, _q_manager)
81
82QDBusConnectionPrivate *QDBusConnectionManager::sender() const
83{
84 QMutexLocker locker(&senderMutex);
85 return connection(senderName);
86}
87
88void QDBusConnectionManager::setSender(const QDBusConnectionPrivate *s)
89{
90 QMutexLocker locker(&senderMutex);
91 senderName = (s ? s->name : QString());
92}
93
94QDBusConnectionPrivate *QDBusConnectionManager::connection(const QString &name) const
95{
96 return connectionHash.value(name, 0);
97}
98
99void 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
113QDBusConnectionManager::~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
126QDBUS_EXPORT void qDBusBindToApplication();
127void qDBusBindToApplication()
128{
129}
130
131void 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*/
247QDBusConnection::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*/
262QDBusConnection::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*/
273QDBusConnection::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*/
284QDBusConnection::~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*/
297QDBusConnection &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*/
312QDBusConnection 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*/
358QDBusConnection 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*/
404void 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*/
419bool 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*/
450bool 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*/
481bool 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*/
504QDBusMessage 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*/
536QDBusPendingCall 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*/
557bool 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*/
571bool 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*/
592bool 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*/
646bool 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*/
703bool 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*/
768void 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*/
808QObject *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*/
843QDBusConnectionInterface *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*/
857bool 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*/
871QDBusError 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*/
886QString 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*/
908QString 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*/
920bool 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*/
936bool 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
945static const char _q_sessionBusName[] = "qt_default_session_bus";
946static const char _q_systemBusName[] = "qt_default_system_bus";
947
948class QDBusDefaultConnection: public QDBusConnection
949{
950 const char *ownName;
951public:
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
960Q_GLOBAL_STATIC_WITH_ARGS(QDBusDefaultConnection, _q_sessionBus,
961 (QDBusConnection::SessionBus, _q_sessionBusName))
962Q_GLOBAL_STATIC_WITH_ARGS(QDBusDefaultConnection, _q_systemBus,
963 (QDBusConnection::SystemBus, _q_systemBusName))
964
965QDBusConnection QDBusConnection::sessionBus()
966{
967 return *_q_sessionBus();
968}
969
970QDBusConnection QDBusConnection::systemBus()
971{
972 return *_q_systemBus();
973}
974
975/*!
976 Returns the connection that sent the signal, if called in a slot activated
977 by QDBus; otherwise it returns 0.
978*/
979QDBusConnection QDBusConnection::sender()
980{
981 return QDBusConnection(_q_manager()->sender());
982}
983
984/*!
985 \internal
986*/
987void QDBusConnectionPrivate::setSender(const QDBusConnectionPrivate *s)
988{
989 _q_manager()->setSender(s);
990}
991
992/*!
993 \internal
994*/
995void QDBusConnectionPrivate::setConnection(const QString &name, QDBusConnectionPrivate *c)
996{
997 _q_manager()->setConnection(name, c);
998}
999
1000/*!
1001 \internal
1002*/
1003void QDBusConnectionPrivate::setBusService(const QDBusConnection &connection)
1004{
1005 busService = new QDBusConnectionInterface(connection, this);
1006 ref.deref(); // busService has increased the refcounting to us
1007 // avoid cyclic refcounting
1008// if (mode != PeerMode)
1009 QObject::connect(busService, SIGNAL(serviceOwnerChanged(QString,QString,QString)),
1010 this, SIGNAL(serviceOwnerChanged(QString,QString,QString)));
1011
1012 QObject::connect(this, SIGNAL(callWithCallbackFailed(QDBusError,QDBusMessage)),
1013 busService, SIGNAL(callWithCallbackFailed(QDBusError,QDBusMessage)),
1014 Qt::QueuedConnection);
1015
1016}
1017
1018/*!
1019 \namespace QDBus
1020 \inmodule QtDBus
1021
1022 \brief The QDBus namespace contains miscellaneous identifiers used
1023 throughout the QtDBus library.
1024*/
1025
1026/*!
1027 \enum QDBus::CallMode
1028
1029 This enum describes the various ways of placing a function call. The valid modes are:
1030
1031 \value NoBlock Place the call but don't wait for the reply (the reply's contents
1032 will be discarded).
1033 \value Block Don't use an event loop to wait for a reply, but instead block on
1034 network operations while waiting. This means the
1035 user-interface may not be updated until the function returns.
1036 \value BlockWithGui Use the Qt event loop to wait for a reply. This means that the
1037 user-interface will stay responsive (processing input events),
1038 but it also means other events may happen, like signal delivery
1039 and other D-Bus method calls.
1040 \value AutoDetect Automatically detect if the called function has a reply.
1041
1042 When using BlockWithGui, applications must be prepared for reentrancy in any function.
1043*/
1044
1045QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.