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 | |
27 | QT_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 | */ |
151 | QDBusConnection::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 | */ |
170 | QDBusConnection::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 | */ |
181 | QDBusConnection::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 | */ |
192 | QDBusConnection::~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 | */ |
205 | QDBusConnection &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 | */ |
220 | QDBusConnection 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 | */ |
235 | QDBusConnection 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 | */ |
252 | QDBusConnection 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 | */ |
272 | void 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 | */ |
291 | void 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 | */ |
307 | bool 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 | */ |
338 | bool 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 | */ |
369 | bool 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 | */ |
398 | QDBusMessage 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 | */ |
438 | QDBusPendingCall 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 | */ |
459 | bool 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 | */ |
482 | bool 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 | */ |
512 | bool 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 | */ |
550 | bool 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 | */ |
566 | bool 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 | */ |
584 | bool 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 | */ |
614 | bool 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 | */ |
638 | bool 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 | */ |
721 | bool 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 | */ |
734 | void 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 | */ |
747 | QObject *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 | */ |
786 | QDBusConnectionInterface *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 | */ |
803 | void *QDBusConnection::internalPointer() const |
804 | { |
805 | return d ? d->connection : nullptr; |
806 | } |
807 | |
808 | /*! |
809 | Returns \c true if this QDBusConnection object is connected. |
810 | */ |
811 | bool 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 | */ |
825 | QDBusError 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 | */ |
840 | QString 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 | */ |
862 | QString 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 | */ |
874 | QDBusConnection::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 | */ |
888 | bool 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 | */ |
904 | bool 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 | */ |
920 | QDBusConnection 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 | */ |
936 | QDBusConnection 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 | */ |
948 | void 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 | */ |
974 | QByteArray 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 | |
1015 | QT_END_NAMESPACE |
1016 | |
1017 | #include "moc_qdbusconnection_p.cpp" |
1018 | #include "moc_qdbusconnection.cpp" |
1019 | |
1020 | #endif // QT_NO_DBUS |
1021 |
Definitions
- QDBusConnection
- QDBusConnection
- QDBusConnection
- ~QDBusConnection
- operator=
- connectToBus
- connectToBus
- connectToPeer
- disconnectFromBus
- disconnectFromPeer
- send
- callWithCallback
- callWithCallback
- call
- asyncCall
- connect
- connect
- connect
- disconnect
- disconnect
- disconnect
- registerObject
- registerObject
- registerVirtualObject
- unregisterObject
- objectRegisteredAt
- interface
- internalPointer
- isConnected
- lastError
- baseService
- name
- connectionCapabilities
- registerService
- unregisterService
- sessionBus
- systemBus
- createBusService
Start learning QML with our Intro Training
Find out more