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

Provided by KDAB

Privacy Policy
Start learning QML with our Intro Training
Find out more

source code of qtbase/src/dbus/qdbusconnection.cpp