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