8#include <qcoreapplication.h>
9#include <qelapsedtimer.h>
10#include <private/qlatch_p.h>
11#include <qloggingcategory.h>
12#include <qmetaobject.h>
14#include <qsocketnotifier.h>
15#include <qstringlist.h>
17#include <private/qlocking_p.h>
18#include <QtCore/qset.h>
47using namespace Qt::StringLiterals;
49QT_IMPL_METATYPE_EXTERN(QDBusSlotCache)
56Q_CONSTINIT
static QBasicAtomicInt isDebugging = Q_BASIC_ATOMIC_INITIALIZER(-1);
57#define qDBusDebug if (::isDebugging.loadRelaxed() == 0
); else qDebug
59static inline QDebug operator<<(QDebug dbg,
const QThread *th)
61 QDebugStateSaver saver(dbg);
62 dbg.nospace() <<
"QThread(ptr=" << (
const void*)th;
63 if (th && !th->objectName().isEmpty())
64 dbg.nospace() <<
", name=" << th->objectName();
66 dbg.nospace() <<
", name=" << th->metaObject()->className();
72static inline QDebug operator<<(QDebug dbg,
const QDBusConnectionPrivate *conn)
74 QDebugStateSaver saver(dbg);
75 dbg.nospace() <<
"QDBusConnection("
76 <<
"ptr=" << (
const void*)conn
77 <<
", name=" << conn->name
78 <<
", baseService=" << conn->baseService
83void qdbusDefaultThreadDebug(
int action,
int condition, QDBusConnectionPrivate *conn)
85 qDBusDebug() << QThread::currentThread()
86 <<
"Qt D-Bus threading action" << action
87 << (condition == QDBusLockerBase::BeforeLock ?
"before lock" :
88 condition == QDBusLockerBase::AfterLock ?
"after lock" :
89 condition == QDBusLockerBase::BeforeUnlock ?
"before unlock" :
90 condition == QDBusLockerBase::AfterUnlock ?
"after unlock" :
91 condition == QDBusLockerBase::BeforePost ?
"before event posting" :
92 condition == QDBusLockerBase::AfterPost ?
"after event posting" :
93 condition == QDBusLockerBase::BeforeDeliver ?
"before event delivery" :
94 condition == QDBusLockerBase::AfterDeliver ?
"after event delivery" :
95 condition == QDBusLockerBase::BeforeAcquire ?
"before acquire" :
96 condition == QDBusLockerBase::AfterAcquire ?
"after acquire" :
97 condition == QDBusLockerBase::BeforeRelease ?
"before release" :
98 condition == QDBusLockerBase::AfterRelease ?
"after release" :
100 <<
"in connection" << conn;
102qdbusThreadDebugFunc qdbusThreadDebug =
nullptr;
110 const auto locker = qt_scoped_lock(lock);
120 const auto locker = qt_scoped_lock(lock);
124 for (
auto hook : std::as_const(hookListCopy))
146 QDBusConnectionPrivate *d =
static_cast<QDBusConnectionPrivate *>(data);
147 Q_ASSERT(QThread::currentThread() == d->thread());
153 Q_ASSERT(d->timeouts.key(timeout, 0) == 0);
155 using namespace std::chrono_literals;
156 int timerId = d->startTimer(q_dbus_timeout_get_interval(timeout) * 1ms);
160 d->timeouts[timerId] = timeout;
171 QDBusConnectionPrivate *d =
static_cast<QDBusConnectionPrivate *>(data);
172 Q_ASSERT(QThread::currentThread() == d->thread());
174 QDBusConnectionPrivate::TimeoutHash::iterator it = d->timeouts.begin();
175 while (it != d->timeouts.end()) {
176 if (it.value() == timeout) {
177 d->killTimer(it.key());
178 it = d->timeouts.erase(it);
202 QDBusConnectionPrivate *d =
static_cast<QDBusConnectionPrivate *>(data);
203 Q_ASSERT(QThread::currentThread() == d->thread());
205 int flags = q_dbus_watch_get_flags(watch);
208 QDBusConnectionPrivate::Watcher watcher;
212 watcher.watch = watch;
213 watcher.read =
new QSocketNotifier(fd, QSocketNotifier::Read, d);
214 watcher.read->setEnabled(q_dbus_watch_get_enabled(watch));
215 d->connect(watcher.read, &QSocketNotifier::activated, d, &QDBusConnectionPrivate::socketRead);
219 watcher.watch = watch;
220 watcher.write =
new QSocketNotifier(fd, QSocketNotifier::Write, d);
221 watcher.write->setEnabled(q_dbus_watch_get_enabled(watch));
222 d->connect(watcher.write, &QSocketNotifier::activated, d, &QDBusConnectionPrivate::socketWrite);
224 d->watchers.insert(fd, watcher);
236 QDBusConnectionPrivate *d =
static_cast<QDBusConnectionPrivate *>(data);
237 Q_ASSERT(QThread::currentThread() == d->thread());
240 QDBusConnectionPrivate::WatcherHash::iterator i = d->watchers.find(fd);
241 while (i != d->watchers.end() && i.key() == fd) {
242 if (i.value().watch == watch) {
243 delete i.value().read;
244 delete i.value().write;
245 i = d->watchers.erase(i);
257 QDBusConnectionPrivate *d =
static_cast<QDBusConnectionPrivate *>(data);
258 Q_ASSERT(QThread::currentThread() == d->thread());
261 QDBusConnectionPrivate::WatcherHash::iterator i = d->watchers.find(fd);
262 while (i != d->watchers.end() && i.key() == fd) {
263 if (i.value().watch == watch) {
264 bool enabled = q_dbus_watch_get_enabled(watch);
265 int flags = q_dbus_watch_get_flags(watch);
270 i.value().read->setEnabled(enabled);
272 i.value().write->setEnabled(enabled);
281 Q_ASSERT(connection);
282 QDBusConnectionPrivate *d =
static_cast<QDBusConnectionPrivate *>(data);
284 emit d->dispatchStatusChanged();
291 Q_ASSERT(connection);
299 q_dbus_connection_ref(connection);
300 QDBusConnectionPrivate *serverConnection =
static_cast<QDBusConnectionPrivate *>(data);
303 if (serverConnection->anonymousAuthenticationAllowed)
304 q_dbus_connection_set_allow_anonymous(connection,
true);
306 QDBusConnectionPrivate *newConnection =
new QDBusConnectionPrivate;
308 manager->addConnection(
309 "QDBusServer-"_L1 + QString::number(
reinterpret_cast<qulonglong>(newConnection), 16),
312 QWriteLocker locker(&serverConnection->lock);
313 serverConnection->serverConnectionNames << newConnection->name;
318 newConnection->setPeer(connection, error);
319 newConnection->setDispatchEnabled(
false);
321 QReadLocker serverLock(&serverConnection->lock);
322 if (!serverConnection->serverObject)
326 QMetaObject::invokeMethod(serverConnection->serverObject, &QDBusServer::newConnection,
327 Qt::QueuedConnection, QDBusConnectionPrivate::q(newConnection));
334 newConnection->enableDispatchDelayed(serverConnection->serverObject);
340 const QString &objectPath,
const QString &interface,
341 const QString &member,
const QDBusConnectionPrivate::ArgMatchRules &argMatch,
const QString & )
344 result +=
"type='signal',"_L1;
345 const auto keyValue =
"%1='%2',"_L1;
347 if (!service.isEmpty())
348 result += keyValue.arg(
"sender"_L1, service);
349 if (!objectPath.isEmpty())
350 result += keyValue.arg(
"path"_L1, objectPath);
351 if (!interface.isEmpty())
352 result += keyValue.arg(
"interface"_L1, interface);
353 if (!member.isEmpty())
354 result += keyValue.arg(
"member"_L1, member);
357 if (!argMatch.args.isEmpty()) {
358 const QString keyValue =
"arg%1='%2',"_L1;
359 for (
int i = 0; i < argMatch.args.size(); ++i)
360 if (!argMatch.args.at(i).isNull())
361 result += keyValue.arg(i).arg(argMatch.args.at(i));
363 if (!argMatch.arg0namespace.isEmpty()) {
364 result +=
"arg0namespace='%1',"_L1.arg(argMatch.arg0namespace);
368 return result.toLatin1();
371static bool findObject(
const QDBusConnectionPrivate::ObjectTreeNode *root,
372 const QString &fullpath,
int &usedLength,
373 QDBusConnectionPrivate::ObjectTreeNode &result)
375 if (!fullpath.compare(
"/"_L1) && root->obj) {
381 int length = fullpath.size();
382 if (fullpath.at(0) == u'/')
386 const QDBusConnectionPrivate::ObjectTreeNode *node = root;
387 while (start < length && node) {
388 if (node->flags & QDBusConnection::ExportChildObjects)
390 if ((node->flags & QDBusConnectionPrivate::VirtualObject) && (node->flags & QDBusConnection::SubPath))
392 int end = fullpath.indexOf(u'/', start);
393 end = (end == -1 ? length : end);
394 QStringView pathComponent = QStringView{fullpath}.mid(start, end - start);
396 QDBusConnectionPrivate::ObjectTreeNode::DataList::ConstIterator it =
397 std::lower_bound(node->children.constBegin(), node->children.constEnd(), pathComponent);
398 if (it != node->children.constEnd() && it->name == pathComponent)
408 usedLength = (start > length ? length : start);
410 if (node->obj || !node->children.isEmpty())
421 const QString &fullpath,
int start)
423 int length = fullpath.size();
426 const QDBusConnectionPrivate::ObjectTreeNode *node = root;
427 if (node && node->flags & QDBusConnection::ExportChildObjects) {
428 QObject *obj = node->obj;
435 int pos = fullpath.indexOf(u'/', start);
436 pos = (pos == -1 ? length : pos);
437 auto pathComponent = QStringView{fullpath}.mid(start, pos - start);
440 QObject *next =
nullptr;
441 for (QObject *child : std::as_const(obj->children())) {
442 if (child->objectName() == pathComponent) {
462 QDBusConnectionPrivate::ArgMatchRules matchArgs;
463 if (service.endsWith(u'*')) {
464 matchArgs.arg0namespace = service.chopped(1);
465 matchArgs.args << QString();
468 matchArgs.args << service;
471 case QDBusServiceWatcher::WatchForOwnerChange:
474 case QDBusServiceWatcher::WatchForRegistration:
475 matchArgs.args << QString::fromLatin1(
"", 0);
478 case QDBusServiceWatcher::WatchForUnregistration:
479 matchArgs.args << QString() << QString::fromLatin1(
"", 0);
489 auto *hooks = qDBusSpyHookList();
501 QDBusConnectionPrivate *d =
static_cast<QDBusConnectionPrivate *>(
const_cast<QObject *>(sender()));
502 qDBusDebug() << d <<
"message spies done for" << msg;
503 emit d->spyHooksFinished(msg);
513 if (!qDBusSpyHookList.exists())
516 qDBusSpyHookList->invoke(msg);
520static DBusHandlerResult
524 Q_UNUSED(connection);
525 QDBusConnectionPrivate *d =
static_cast<QDBusConnectionPrivate *>(data);
526 if (d->mode == QDBusConnectionPrivate::InvalidMode)
529 QDBusMessage amsg = QDBusMessagePrivate::fromDBusMessage(message, d->connectionCapabilities());
530 qDBusDebug() << d <<
"got message (signal):" << amsg;
532 return d->handleMessage(amsg) ?
538bool QDBusConnectionPrivate::handleMessage(
const QDBusMessage &amsg)
540 if (!ref.loadRelaxed())
545 bool isLocal = QDBusMessagePrivate::isLocal(amsg);
547 if (!dispatchEnabled && !isLocal) {
549 qDBusDebug() <<
this <<
"delivery is suspended";
550 pendingMessages << amsg;
551 return amsg.type() == QDBusMessage::MethodCallMessage;
554 switch (amsg.type()) {
555 case QDBusMessage::SignalMessage:
560 case QDBusMessage::MethodCallMessage:
564 if (Q_UNLIKELY(qDBusSpyHookList.exists()) && QCoreApplication::instanceExists()) {
566 Q_ASSERT(QThread::currentThread() != thread());
567 qDBusDebug() <<
this <<
"invoking message spies directly";
568 QDBusSpyCallEvent::invokeSpyHooks(amsg);
570 qDBusDebug() <<
this <<
"invoking message spies via event";
571 QCoreApplication::postEvent(
572 qApp,
new QDBusSpyCallEvent(
this, QDBusConnection(
this), amsg));
579 handleObjectCall(amsg);
581 case QDBusMessage::ReplyMessage:
582 case QDBusMessage::ErrorMessage:
583 case QDBusMessage::InvalidMessage:
590static void huntAndDestroy(QObject *needle, QDBusConnectionPrivate::ObjectTreeNode &haystack)
592 for (QDBusConnectionPrivate::ObjectTreeNode &node : haystack.children)
593 huntAndDestroy(needle, node);
595 auto isInactive = [](
const QDBusConnectionPrivate::ObjectTreeNode &node) {
return !node.isActive(); };
596 haystack.children.removeIf(isInactive);
598 if (needle == haystack.obj) {
599 haystack.obj =
nullptr;
605 QDBusConnection::UnregisterMode mode,
606 QDBusConnectionPrivate::ObjectTreeNode *node)
608 if (pathComponents.size() == i) {
613 if (mode == QDBusConnection::UnregisterTree) {
615 node->children.clear();
620 QDBusConnectionPrivate::ObjectTreeNode::DataList::Iterator end = node->children.end();
621 QDBusConnectionPrivate::ObjectTreeNode::DataList::Iterator it =
622 std::lower_bound(node->children.begin(), end, pathComponents.at(i));
623 if (it == end || it->name != pathComponents.at(i))
626 huntAndUnregister(pathComponents, i + 1, mode, &(*it));
628 node->children.erase(it);
632static void huntAndEmit(DBusConnection *connection, DBusMessage *msg,
633 QObject *needle,
const QDBusConnectionPrivate::ObjectTreeNode &haystack,
634 bool isScriptable,
bool isAdaptor,
const QString &path = QString())
636 for (
const QDBusConnectionPrivate::ObjectTreeNode &node : std::as_const(haystack.children)) {
637 if (node.isActive()) {
638 huntAndEmit(connection, msg, needle, node, isScriptable, isAdaptor,
639 path + u'/' + node.name);
643 if (needle == haystack.obj) {
645 if (isAdaptor && (haystack.flags & QDBusConnection::ExportAdaptors) == 0)
647 else if (!isAdaptor) {
648 int mask = isScriptable
649 ? QDBusConnection::ExportScriptableSignals
650 : QDBusConnection::ExportNonScriptableSignals;
651 if ((haystack.flags & mask) == 0)
655 QByteArray p = path.toLatin1();
658 qDBusDebug() << QThread::currentThread() <<
"emitting signal at" << p;
660 q_dbus_message_set_path(msg2, p);
666static int findSlot(
const QMetaObject *mo,
const QByteArray &name,
int flags,
667 const QString &signature_, QList<QMetaType> &metaTypes)
669 QByteArray msgSignature = signature_.toLatin1();
670 QString parametersErrorMsg;
672 for (
int idx = mo->methodCount() - 1 ; idx >= QObject::staticMetaObject.methodCount(); --idx) {
673 QMetaMethod mm = mo->method(idx);
676 if (mm.access() != QMetaMethod::Public)
680 if (mm.methodType() != QMetaMethod::Slot && mm.methodType() != QMetaMethod::Method)
684 if (mm.name() != name)
687 QMetaType returnType = mm.returnMetaType();
688 bool isAsync = qDBusCheckAsyncTag(mm.tag());
689 bool isScriptable = mm.attributes() & QMetaMethod::Scriptable;
692 if (isAsync && returnType.id() != QMetaType::Void)
696 int inputCount = qDBusParametersForMethod(mm, metaTypes, errorMsg);
697 if (inputCount == -1) {
698 parametersErrorMsg = errorMsg;
702 metaTypes[0] = returnType;
703 bool hasMessage =
false;
704 if (inputCount > 0 &&
705 metaTypes.at(inputCount) == QDBusMetaTypeId::message()) {
713 QByteArray reconstructedSignature;
714 for (i = 1; i <= inputCount; ++i) {
715 const char *typeSignature = QDBusMetaType::typeToSignature( metaTypes.at(i) );
719 reconstructedSignature += typeSignature;
720 if (!msgSignature.startsWith(reconstructedSignature))
724 if (reconstructedSignature != msgSignature)
731 if (returnType.isValid() && returnType.id() != QMetaType::Void && QDBusMetaType::typeToSignature(returnType) ==
nullptr)
735 for (
int j = i; ok && j < metaTypes.size(); ++j)
736 if (QDBusMetaType::typeToSignature(metaTypes.at(i)) ==
nullptr)
742 if (isAsync && metaTypes.size() > i + 1)
745 if (mm.methodType() == QMetaMethod::Slot) {
746 if (isScriptable && (flags & QDBusConnection::ExportScriptableSlots) == 0)
748 if (!isScriptable && (flags & QDBusConnection::ExportNonScriptableSlots) == 0)
751 if (isScriptable && (flags & QDBusConnection::ExportScriptableInvokables) == 0)
753 if (!isScriptable && (flags & QDBusConnection::ExportNonScriptableInvokables) == 0)
762 if (!parametersErrorMsg.isEmpty()) {
763 qCWarning(dbusIntegration,
"QDBusConnection: couldn't handle call to %s: %ls",
766 qCWarning(dbusIntegration,
"QDBusConnection: couldn't handle call to %s, no slot matched",
773
774
775
776
777
778void QDBusConnectionPrivate::setDispatchEnabled(
bool enable)
781 dispatchEnabled = enable;
783 emit dispatchStatusChanged();
788QDBusCallDeliveryEvent *QDBusConnectionPrivate::prepareReply(QDBusConnectionPrivate *target,
789 QObject *object,
int idx,
790 const QList<QMetaType> &metaTypes,
791 const QDBusMessage &msg)
795 int n = metaTypes.size() - 1;
796 if (metaTypes[n] == QDBusMetaTypeId::message())
799 if (msg.arguments().size() < n)
803 for (
int i = 0; i < n; ++i)
804 if (metaTypes.at(i + 1) != msg.arguments().at(i).metaType() &&
805 msg.arguments().at(i).metaType() != QMetaType::fromType<QDBusArgument>())
810 if (target == object)
811 return DIRECT_DELIVERY;
812 return new QDBusCallDeliveryEvent(QDBusConnection(target), idx, target, msg, metaTypes);
815void QDBusConnectionPrivate::activateSignal(
const QDBusConnectionPrivate::SignalHook& hook,
816 const QDBusMessage &msg)
825 QDBusCallDeliveryEvent *call = prepareReply(
this, hook.obj, hook.midx, hook.params, msg);
826 if (call == DIRECT_DELIVERY) {
828 Q_ASSERT(
this == hook.obj);
829 deliverCall(
this, msg, hook.params, hook.midx);
833 postEventToThread(ActivateSignalAction, hook.obj, call);
836bool QDBusConnectionPrivate::activateCall(QObject *object, QDBusConnection::RegisterOptions flags,
837 const QDBusMessage &msg)
859 static const char cachePropertyName[] =
"_qdbus_slotCache";
864 Q_ASSERT_X(QThread::currentThread() == object->thread(),
865 "QDBusConnection: internal threading error",
866 "function called for an object that is in another thread!!");
868 QDBusSlotCache slotCache =
869 qvariant_cast<QDBusSlotCache>(object->property(cachePropertyName));
870 QString cacheKey = msg.member(), signature = msg.signature();
871 if (!signature.isEmpty()) {
872 cacheKey.reserve(cacheKey.size() + 1 + signature.size());
874 cacheKey += signature;
877 QDBusSlotCache::Key compoundKey{ std::move(cacheKey), flags };
878 QDBusSlotCache::Hash::ConstIterator cacheIt = slotCache.hash.constFind(compoundKey);
879 if (cacheIt == slotCache.hash.constEnd()) {
881 const QMetaObject *mo = object->metaObject();
882 QByteArray memberName = msg.member().toUtf8();
885 QDBusSlotCache::Data slotData;
886 slotData.slotIdx = ::findSlot(mo, memberName, flags, msg.signature(), slotData.metaTypes);
887 if (slotData.slotIdx == -1) {
890 slotData.slotIdx = ::findSlot(mo, memberName, flags, QString(), slotData.metaTypes);
891 if (slotData.metaTypes.size() != 2 ||
892 slotData.metaTypes.at(1) != QDBusMetaTypeId::message()) {
895 slotData.slotIdx = -1;
896 slotData.metaTypes.clear();
897 slotCache.hash.insert(compoundKey, slotData);
898 object->setProperty(cachePropertyName, QVariant::fromValue(slotCache));
900 qCWarning(dbusIntegration).nospace() <<
"Could not find slot " << mo->className()
901 <<
"::" << memberName.constData();
907 slotCache.hash.insert(compoundKey, slotData);
908 object->setProperty(cachePropertyName, QVariant::fromValue(slotCache));
911 deliverCall(object, msg, slotData.metaTypes, slotData.slotIdx);
913 }
else if (cacheIt->slotIdx == -1) {
918 deliverCall(object, msg, cacheIt->metaTypes, cacheIt->slotIdx);
924void QDBusConnectionPrivate::deliverCall(QObject *object,
const QDBusMessage &msg,
925 const QList<QMetaType> &metaTypes,
int slotIdx)
927 Q_ASSERT_X(!object || QThread::currentThread() == object->thread(),
928 "QDBusConnection: internal threading error",
929 "function called for an object that is in another thread!!");
931 QVarLengthArray<
void *, 10> params;
932 params.reserve(metaTypes.size());
934 QVarLengthArray<QVariant, 10> auxParameters;
935 auxParameters.reserve(metaTypes.size());
940 params.append(
nullptr);
944 int pCount = qMin(msg.arguments().size(), metaTypes.size() - 1);
945 for (i = 1; i <= pCount; ++i) {
946 auto id = metaTypes[i];
947 if (id == QDBusMetaTypeId::message())
950 const QList<QVariant> args = msg.arguments();
951 const QVariant &arg = args.at(i - 1);
952 if (arg.metaType() == id)
954 params.append(
const_cast<
void *>(arg.constData()));
955 else if (arg.metaType() == QMetaType::fromType<QDBusArgument>()) {
957 auxParameters.append(QVariant(QMetaType(id)));
959 const QDBusArgument &in =
960 *
reinterpret_cast<
const QDBusArgument *>(arg.constData());
961 QVariant &out = auxParameters[auxParameters.size() - 1];
963 if (Q_UNLIKELY(!QDBusMetaType::demarshall(in, out.metaType(), out.data())))
964 qFatal(
"Internal error: demarshalling function for type '%s' (%d) failed!",
965 out.typeName(), out.metaType().id());
967 params.append(
const_cast<
void *>(out.constData()));
969 qFatal(
"Internal error: got invalid meta type %d (%s) "
970 "when trying to convert to meta type %d (%s)",
971 arg.metaType().id(), arg.metaType().name(),
976 if (metaTypes.size() > i && metaTypes[i] == QDBusMetaTypeId::message()) {
977 params.append(
const_cast<
void*>(
static_cast<
const void*>(&msg)));
982 const int numMetaTypes = metaTypes.size();
983 QVariantList outputArgs;
984 if (metaTypes[0].id() != QMetaType::Void && metaTypes[0].isValid()) {
985 outputArgs.reserve(numMetaTypes - i + 1);
986 QVariant arg{QMetaType(metaTypes[0])};
987 outputArgs.append( arg );
988 params[0] =
const_cast<
void*>(outputArgs.at( outputArgs.size() - 1 ).constData());
990 outputArgs.reserve(numMetaTypes - i);
993 for ( ; i < numMetaTypes; ++i) {
994 QVariant arg{QMetaType(metaTypes[i])};
995 outputArgs.append( arg );
996 params.append(
const_cast<
void*>(outputArgs.at( outputArgs.size() - 1 ).constData()));
1005 QDBusContextPrivate context(QDBusConnection(
this), msg);
1006 QDBusContextPrivate *old = QDBusContextPrivate::set(object, &context);
1008 QPointer<QObject> ptr = object;
1009 fail = object->qt_metacall(QMetaObject::InvokeMetaMethod,
1010 slotIdx, params.data()) >= 0;
1013 QDBusContextPrivate::set(object, old);
1018 if (msg.isReplyRequired() && !msg.isDelayedReply()) {
1021 qDBusDebug() <<
this <<
"Automatically sending reply:" << outputArgs;
1022 send(msg.createReply(outputArgs));
1025 qCWarning(dbusIntegration,
"Internal error: Failed to deliver message");
1026 send(msg.createErrorReply(QDBusError::InternalError,
"Failed to deliver message"_L1));
1033QDBusConnectionPrivate::QDBusConnectionPrivate()
1036 busService(
nullptr),
1037 connection(
nullptr),
1039 anonymousAuthenticationAllowed(
false),
1040 dispatchEnabled(
true),
1041 isAuthenticated(
false)
1043 static const bool threads = q_dbus_threads_init_default();
1045 if (::isDebugging.loadRelaxed() == -1)
1046 ::isDebugging.storeRelaxed(qEnvironmentVariableIntValue(
"QDBUS_DEBUG"));
1048#ifdef QDBUS_THREAD_DEBUG
1049 if (::isDebugging.loadRelaxed() > 1)
1050 qdbusThreadDebug = qdbusDefaultThreadDebug;
1053 QDBusMetaTypeId::init();
1054 connect(
this, &QDBusConnectionPrivate::dispatchStatusChanged,
1055 this, &QDBusConnectionPrivate::doDispatch, Qt::QueuedConnection);
1056 connect(
this, &QDBusConnectionPrivate::spyHooksFinished,
1057 this, &QDBusConnectionPrivate::handleObjectCall, Qt::QueuedConnection);
1058 connect(
this, &QDBusConnectionPrivate::messageNeedsSending,
1059 this, &QDBusConnectionPrivate::sendInternal);
1061 rootNode.flags = {};
1065 watchedServices.insert(QDBusUtil::dbusService(), WatchedServiceData(QDBusUtil::dbusService(), 1));
1069 matchRefCounts.insert(
"type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='NameOwnerChanged',arg0='org.freedesktop.DBus'", 1);
1072QDBusConnectionPrivate::~QDBusConnectionPrivate()
1074 if (thread() && thread() != QThread::currentThread())
1076 "QDBusConnection(name=\"%s\")'s last reference in not in its creation thread! "
1077 "Timer and socket errors will follow and the program will probably crash",
1080 auto lastMode = mode;
1082 qDeleteAll(cachedMetaObjects);
1084 if (lastMode == ClientMode || lastMode == PeerMode) {
1087 Q_ASSERT(ref.loadRelaxed() == 0);
1088 QObject *obj = (QObject *)busService;
1090 disconnect(obj,
nullptr,
this,
nullptr);
1094 q_dbus_connection_unref(connection);
1095 connection =
nullptr;
1096 }
else if (lastMode == ServerMode) {
1098 q_dbus_server_unref(server);
1103void QDBusConnectionPrivate::collectAllObjects(QDBusConnectionPrivate::ObjectTreeNode &haystack,
1104 QSet<QObject *> &set)
1106 for (ObjectTreeNode &child : haystack.children)
1107 collectAllObjects(child, set);
1110 set.insert(haystack.obj);
1113void QDBusConnectionPrivate::closeConnection()
1115 QDBusWriteLocker locker(CloseConnectionAction,
this);
1117 ConnectionMode oldMode = mode;
1119 baseService.clear();
1121 if (oldMode == ServerMode && server) {
1122 q_dbus_server_disconnect(server);
1123 q_dbus_server_free_data_slot(&server_slot);
1126 if (oldMode == ClientMode || oldMode == PeerMode) {
1128 q_dbus_connection_close(connection);
1130 while (q_dbus_connection_dispatch(connection) == DBUS_DISPATCH_DATA_REMAINS)
1135 for (QDBusPendingCallPrivate *call : std::as_const(pendingCalls)) {
1136 if (!call->ref.deref())
1139 pendingCalls.clear();
1146 QSet<QObject *> allObjects;
1147 collectAllObjects(rootNode, allObjects);
1148 for (
const SignalHook &signalHook : std::as_const(signalHooks))
1149 allObjects.insert(signalHook.obj);
1152 for (QObject *obj : std::as_const(allObjects))
1153 obj->disconnect(
this);
1156void QDBusConnectionPrivate::handleDBusDisconnection()
1158 while (!pendingCalls.isEmpty())
1159 processFinishedCall(pendingCalls.first());
1162void QDBusConnectionPrivate::checkThread()
1164 Q_ASSERT(thread() == QDBusConnectionManager::instance());
1165 Q_ASSERT(QThread::currentThread() == thread());
1168bool QDBusConnectionPrivate::handleError(
const QDBusErrorInternal &error)
1179void QDBusConnectionPrivate::timerEvent(QTimerEvent *e)
1182 DBusTimeout *timeout = timeouts.value(e->timerId(),
nullptr);
1184 q_dbus_timeout_handle(timeout);
1190void QDBusConnectionPrivate::doDispatch()
1192 if (mode == ClientMode || mode == PeerMode) {
1193 if (dispatchEnabled && !pendingMessages.isEmpty()) {
1195 for (QDBusMessage &message : pendingMessages) {
1196 qDBusDebug() <<
this <<
"dequeueing message" << message;
1197 handleMessage(std::move(message));
1199 pendingMessages.clear();
1201 while (q_dbus_connection_dispatch(connection) == DBUS_DISPATCH_DATA_REMAINS) ;
1205void QDBusConnectionPrivate::socketRead(qintptr fd)
1207 WatcherHash::ConstIterator it = watchers.constFind(fd);
1208 while (it != watchers.constEnd() && it.key() == fd) {
1209 if (it->watch && it->read && it->read->isEnabled()) {
1210 if (!q_dbus_watch_handle(it.value().watch, DBUS_WATCH_READABLE))
1211 qDebug(
"OUT OF MEM");
1216 if ((mode == ClientMode || mode == PeerMode) && !isAuthenticated
1217 && q_dbus_connection_get_is_authenticated(connection))
1218 handleAuthentication();
1222void QDBusConnectionPrivate::socketWrite(qintptr fd)
1224 WatcherHash::ConstIterator it = watchers.constFind(fd);
1225 while (it != watchers.constEnd() && it.key() == fd) {
1226 if (it->watch && it->write && it->write->isEnabled()) {
1227 if (!q_dbus_watch_handle(it.value().watch, DBUS_WATCH_WRITABLE))
1228 qDebug(
"OUT OF MEM");
1233 if ((mode == ClientMode || mode == PeerMode) && !isAuthenticated
1234 && q_dbus_connection_get_is_authenticated(connection))
1235 handleAuthentication();
1238void QDBusConnectionPrivate::objectDestroyed(QObject *obj)
1240 QDBusWriteLocker locker(ObjectDestroyedAction,
this);
1241 huntAndDestroy(obj, rootNode);
1243 SignalHookHash::iterator sit = signalHooks.begin();
1244 while (sit != signalHooks.end()) {
1245 if (
static_cast<QObject *>(sit.value().obj) == obj)
1246 sit = removeSignalHookNoLock(sit);
1251 obj->disconnect(
this);
1254void QDBusConnectionPrivate::relaySignal(QObject *obj,
const QMetaObject *mo,
int signalId,
1255 const QVariantList &args)
1257 QString interface = qDBusInterfaceFromMetaObject(mo);
1259 QMetaMethod mm = mo->method(signalId);
1260 QByteArray memberName = mm.name();
1263 bool isScriptable = mm.attributes() & QMetaMethod::Scriptable;
1264 bool isAdaptor =
false;
1265 for ( ; mo; mo = mo->superClass())
1266 if (mo == &QDBusAbstractAdaptor::staticMetaObject) {
1272 QDBusReadLocker locker(RelaySignalAction,
this);
1273 QDBusMessage message = QDBusMessage::createSignal(
"/"_L1, interface,
1274 QLatin1StringView(memberName));
1275 QDBusMessagePrivate::setParametersValidated(message,
true);
1276 message.setArguments(args);
1279 QDBusMessagePrivate::toDBusMessage(message, connectionCapabilities(), &error);
1281 qCWarning(dbusIntegration,
"QDBusConnection: Could not emit signal %s.%s: %s",
1289 q_dbus_message_set_no_reply(msg,
true);
1290 huntAndEmit(connection, msg, obj, rootNode, isScriptable, isAdaptor);
1291 q_dbus_message_unref(msg);
1294void QDBusConnectionPrivate::serviceOwnerChangedNoLock(
const QString &name,
1295 const QString &oldOwner,
const QString &newOwner)
1298 WatchedServicesHash::Iterator it = watchedServices.find(name);
1299 if (it == watchedServices.end())
1301 if (oldOwner != it->owner)
1303 "QDBusConnection: name '%s' had owner '%s' but we thought it was '%s'",
1306 qDBusDebug() <<
this <<
"Updating name" << name <<
"from" << oldOwner <<
"to" << newOwner;
1307 it->owner = newOwner;
1310int QDBusConnectionPrivate::findSlot(QObject *obj,
const QByteArray &normalizedName,
1311 QList<QMetaType> ¶ms, QString &errorMsg)
1314 int midx = obj->metaObject()->indexOfMethod(normalizedName);
1318 int inputCount = qDBusParametersForMethod(obj->metaObject()->method(midx), params, errorMsg);
1319 if (inputCount == -1 || inputCount + 1 != params.size())
1325bool QDBusConnectionPrivate::prepareHook(QDBusConnectionPrivate::SignalHook &hook, QString &key,
1326 const QString &service,
const QString &path,
1327 const QString &interface,
const QString &name,
1328 const ArgMatchRules &argMatch, QObject *receiver,
1329 const char *signal,
int minMIdx,
bool buildSignature,
1332 QByteArray normalizedName = signal + 1;
1333 hook.midx = findSlot(receiver, signal + 1, hook.params, errorMsg);
1334 if (hook.midx == -1) {
1335 normalizedName = QMetaObject::normalizedSignature(signal + 1);
1336 hook.midx = findSlot(receiver, normalizedName, hook.params, errorMsg);
1338 if (hook.midx < minMIdx) {
1342 hook.service = service;
1344 hook.obj = receiver;
1345 hook.argumentMatch = argMatch;
1350 QString mname = name;
1351 if (buildSignature && mname.isNull()) {
1352 normalizedName.truncate(normalizedName.indexOf(
'('));
1353 mname = QString::fromUtf8(normalizedName);
1356 key.reserve(interface.size() + 1 + mname.size());
1360 if (buildSignature) {
1361 hook.signature.clear();
1362 for (
int i = 1; i < hook.params.size(); ++i)
1363 if (hook.params.at(i) != QDBusMetaTypeId::message())
1364 hook.signature += QLatin1StringView(QDBusMetaType::typeToSignature(hook.params.at(i)));
1367 hook.matchRule = buildMatchRule(service, path, interface, mname, argMatch, hook.signature);
1371void QDBusConnectionPrivate::sendError(
const QDBusMessage &msg, QDBusError::ErrorType code)
1373 if (code == QDBusError::UnknownMethod) {
1374 QString interfaceMsg;
1375 if (msg.interface().isEmpty())
1376 interfaceMsg =
"any interface"_L1;
1378 interfaceMsg =
"interface '%1'"_L1.arg(msg.interface());
1380 send(msg.createErrorReply(code,
"No such method '%1' in %2 at object path '%3' "
1381 "(signature '%4')"_L1
1382 .arg(msg.member(), interfaceMsg, msg.path(), msg.signature())));
1383 }
else if (code == QDBusError::UnknownInterface) {
1384 send(msg.createErrorReply(QDBusError::UnknownInterface,
1385 "No such interface '%1' at object path '%2'"_L1
1386 .arg(msg.interface(), msg.path())));
1387 }
else if (code == QDBusError::UnknownObject) {
1388 send(msg.createErrorReply(QDBusError::UnknownObject,
1389 "No such object path '%1'"_L1.arg(msg.path())));
1393bool QDBusConnectionPrivate::activateInternalFilters(
const ObjectTreeNode &node,
1394 const QDBusMessage &msg)
1397 const QString interface = msg.interface();
1399 if (interface.isEmpty() || interface == QDBusUtil::dbusInterfaceIntrospectable()) {
1400 if (msg.member() ==
"Introspect"_L1 && msg.signature().isEmpty()) {
1402 QDBusMessage reply = msg.createReply(qDBusIntrospectObject(node, msg.path()));
1407 if (!interface.isEmpty()) {
1408 sendError(msg, QDBusError::UnknownMethod);
1413 if (node.obj && (interface.isEmpty() ||
1414 interface == QDBusUtil::dbusInterfaceProperties())) {
1417 QDBusContextPrivate context(QDBusConnection(
this), msg);
1418 QDBusContextPrivate *old = QDBusContextPrivate::set(node.obj, &context);
1419 auto guard = qScopeGuard([&node, old]{
1420 QDBusContextPrivate::set(node.obj, old);
1423 if (msg.member() ==
"Get"_L1 && msg.signature() ==
"ss"_L1) {
1424 QDBusMessage reply = qDBusPropertyGet(node, msg);
1425 if (!msg.isDelayedReply()) {
1429 }
else if (msg.member() ==
"Set"_L1 && msg.signature() ==
"ssv"_L1) {
1430 QDBusMessage reply = qDBusPropertySet(node, msg);
1431 if (!msg.isDelayedReply()) {
1435 }
else if (msg.member() ==
"GetAll"_L1 && msg.signature() ==
"s"_L1) {
1436 QDBusMessage reply = qDBusPropertyGetAll(node, msg);
1437 if (!msg.isDelayedReply()) {
1443 if (!interface.isEmpty()) {
1444 sendError(msg, QDBusError::UnknownMethod);
1452void QDBusConnectionPrivate::activateObject(ObjectTreeNode &node,
const QDBusMessage &msg,
1462 if (node.flags & QDBusConnectionPrivate::VirtualObject) {
1463 if (node.treeNode->handleMessage(msg, q(
this))) {
1466 if (activateInternalFilters(node, msg))
1471 if (pathStartPos != msg.path().size()) {
1472 node.flags &= ~QDBusConnection::ExportAllSignals;
1473 node.obj = findChildObject(&node, msg.path(), pathStartPos);
1475 sendError(msg, QDBusError::UnknownObject);
1480 QDBusAdaptorConnector *connector;
1481 if (node.flags & QDBusConnection::ExportAdaptors &&
1482 (connector = qDBusFindAdaptorConnector(node.obj))) {
1483 auto newflags = node.flags | QDBusConnection::ExportAllSlots;
1485 if (msg.interface().isEmpty()) {
1488 for (
const QDBusAdaptorConnector::AdaptorData &adaptorData :
1489 std::as_const(connector->adaptors)) {
1490 if (activateCall(adaptorData.adaptor, newflags, msg))
1495 QDBusAdaptorConnector::AdaptorMap::ConstIterator it;
1496 it = std::lower_bound(connector->adaptors.constBegin(), connector->adaptors.constEnd(),
1498 if (it != connector->adaptors.constEnd() && msg.interface() == QLatin1StringView(it->interface)) {
1499 if (!activateCall(it->adaptor, newflags, msg))
1500 sendError(msg, QDBusError::UnknownMethod);
1508 if (activateInternalFilters(node, msg))
1512 if (node.flags & (QDBusConnection::ExportScriptableSlots|QDBusConnection::ExportNonScriptableSlots) ||
1513 node.flags & (QDBusConnection::ExportScriptableInvokables|QDBusConnection::ExportNonScriptableInvokables)) {
1514 bool interfaceFound =
true;
1515 if (!msg.interface().isEmpty()) {
1516 if (!node.interfaceName.isEmpty())
1517 interfaceFound = msg.interface() == node.interfaceName;
1519 interfaceFound = qDBusInterfaceInObject(node.obj, msg.interface());
1522 if (interfaceFound) {
1523 if (!activateCall(node.obj, node.flags, msg))
1524 sendError(msg, QDBusError::UnknownMethod);
1530 if (msg.interface().isEmpty())
1531 sendError(msg, QDBusError::UnknownMethod);
1533 sendError(msg, QDBusError::UnknownInterface);
1536void QDBusConnectionPrivate::handleObjectCall(
const QDBusMessage &msg)
1545 ObjectTreeNode result;
1547 QThread *objThread =
nullptr;
1552 QDBusReadLocker locker(HandleObjectCallAction,
this);
1553 if (!findObject(&rootNode, msg.path(), usedLength, result)) {
1555 sendError(msg, QDBusError::UnknownObject);
1562 activateObject(result, msg, usedLength);
1566 objThread = result.obj->thread();
1568 send(msg.createErrorReply(QDBusError::InternalError,
1569 "Object '%1' (at path '%2')"
1570 " has no thread. Cannot deliver message."_L1
1571 .arg(result.obj->objectName(), msg.path())));
1575 if (!QDBusMessagePrivate::isLocal(msg)) {
1578 postEventToThread(HandleObjectCallPostEventAction, result.obj,
1579 new QDBusActivateObjectEvent(QDBusConnection(
this),
this, result,
1582 }
else if (objThread != QThread::currentThread()) {
1585 postEventToThread(HandleObjectCallPostEventAction, result.obj,
1586 new QDBusActivateObjectEvent(QDBusConnection(
this),
this, result,
1587 usedLength, msg, &latch));
1598 activateObject(result, msg, usedLength);
1606 QDBusConnectionPrivate *that = QDBusConnectionPrivate::d(connection);
1607 that->sendError(message, QDBusError::UnknownObject);
1615 QDBusConnectionPrivate *that = QDBusConnectionPrivate::d(connection);
1619 that->activateObject(node, message, pathStartPos);
1626void QDBusConnectionPrivate::handleSignal(
const QString &key,
const QDBusMessage& msg)
1628 SignalHookHash::const_iterator it = signalHooks.constFind(key);
1629 SignalHookHash::const_iterator end = signalHooks.constEnd();
1632 for ( ; it != end && it.key() == key; ++it) {
1633 const SignalHook &hook = it.value();
1634 if (!hook.service.isEmpty()) {
1635 QString owner = watchedServices.value(hook.service, WatchedServiceData(hook.service)).owner;
1636 if (owner != msg.service())
1639 if (!hook.path.isEmpty() && hook.path != msg.path())
1641 if (!hook.signature.isEmpty() && hook.signature != msg.signature())
1643 if (hook.signature.isEmpty() && !hook.signature.isNull() && !msg.signature().isEmpty())
1645 if (!hook.argumentMatch.args.isEmpty()) {
1646 const QVariantList arguments = msg.arguments();
1647 if (hook.argumentMatch.args.size() > arguments.size())
1650 bool matched =
true;
1651 for (
int i = 0; i < hook.argumentMatch.args.size(); ++i) {
1652 const QString ¶m = hook.argumentMatch.args.at(i);
1655 if (param == arguments.at(i).toString())
1663 if (!hook.argumentMatch.arg0namespace.isEmpty()) {
1664 const QVariantList arguments = msg.arguments();
1665 if (arguments.size() < 1)
1667 const QString param = arguments.at(0).toString();
1668 const QStringView ns = hook.argumentMatch.arg0namespace;
1669 if (!param.startsWith(ns) || (param.size() != ns.size() && param[ns.size()] != u'.'))
1672 activateSignal(hook, msg);
1676void QDBusConnectionPrivate::handleSignal(
const QDBusMessage& msg)
1685 QString key = msg.member();
1686 key.reserve(key.size() + 1 + msg.interface().size());
1688 key += msg.interface();
1690 QDBusWriteLocker locker(HandleSignalAction,
this);
1691 handleSignal(key, msg);
1693 key.truncate(msg.member().size() + 1);
1694 handleSignal(key, msg);
1697 key += msg.interface();
1698 handleSignal(key, msg);
1701void QDBusConnectionPrivate::watchForDBusDisconnection()
1705 hook.service.clear();
1706 hook.path = QDBusUtil::dbusPathLocal();
1708 hook.params << QMetaType(QMetaType::Void);
1709 hook.midx = staticMetaObject.indexOfSlot(
"handleDBusDisconnection()");
1710 Q_ASSERT(hook.midx != -1);
1714void QDBusConnectionPrivate::setServer(QDBusServer *object, DBusServer *s,
const QDBusErrorInternal &error)
1717 serverObject = object;
1726 dbus_bool_t data_allocated = q_dbus_server_allocate_data_slot(&server_slot);
1727 if (data_allocated && server_slot < 0)
1730 dbus_bool_t watch_functions_set = q_dbus_server_set_watch_functions(server,
1736 Q_UNUSED(watch_functions_set);
1738 dbus_bool_t time_functions_set = q_dbus_server_set_timeout_functions(server,
1744 Q_UNUSED(time_functions_set);
1746 q_dbus_server_set_new_connection_function(server, qDBusNewConnection,
this,
nullptr);
1748 dbus_bool_t data_set = q_dbus_server_set_data(server, server_slot,
this,
nullptr);
1753void QDBusConnectionPrivate::setPeer(DBusConnection *c,
const QDBusErrorInternal &error)
1763 q_dbus_connection_set_exit_on_disconnect(connection,
false);
1764 q_dbus_connection_set_watch_functions(connection,
1769 q_dbus_connection_set_timeout_functions(connection,
1774 q_dbus_connection_set_dispatch_status_function(connection, qDBusUpdateDispatchStatus,
this,
nullptr);
1775 q_dbus_connection_add_filter(connection,
1779 watchForDBusDisconnection();
1781 QMetaObject::invokeMethod(
this, &QDBusConnectionPrivate::doDispatch, Qt::QueuedConnection);
1786 QDBusConnection::ConnectionCapabilities result;
1787 typedef dbus_bool_t (*can_send_type_t)(DBusConnection *,
int);
1788 static can_send_type_t can_send_type =
nullptr;
1790#if defined(QT_LINKED_LIBDBUS)
1791# if DBUS_VERSION-0
>= 0x010400
1792 can_send_type = dbus_connection_can_send_type;
1794#elif QT_CONFIG(library)
1796 can_send_type = (can_send_type_t)qdbus_resolve_conditionally(
"dbus_connection_can_send_type");
1800# define DBUS_TYPE_UNIX_FD int('h')
1803 result |= QDBusConnection::UnixFileDescriptorPassing;
1808void QDBusConnectionPrivate::handleAuthentication()
1810 capabilities.storeRelaxed(::connectionCapabilities(connection));
1811 isAuthenticated =
true;
1814void QDBusConnectionPrivate::setConnection(DBusConnection *dbc,
const QDBusErrorInternal &error)
1824 const char *service = q_dbus_bus_get_unique_name(connection);
1826 baseService = QString::fromUtf8(service);
1828 handleAuthentication();
1830 q_dbus_connection_set_exit_on_disconnect(connection,
false);
1831 q_dbus_connection_set_watch_functions(connection, qDBusAddWatch, qDBusRemoveWatch,
1832 qDBusToggleWatch,
this,
nullptr);
1833 q_dbus_connection_set_timeout_functions(connection, qDBusAddTimeout, qDBusRemoveTimeout,
1834 qDBusToggleTimeout,
this,
nullptr);
1835 q_dbus_connection_set_dispatch_status_function(connection, qDBusUpdateDispatchStatus,
this,
nullptr);
1836 q_dbus_connection_add_filter(connection, qDBusSignalFilter,
this,
nullptr);
1842 hook.service = QDBusUtil::dbusService();
1845 hook.params << QMetaType(QMetaType::Void) << QMetaType(QMetaType::QString);
1847 hook.midx = staticMetaObject.indexOfSlot(
"registerServiceNoLock(QString)");
1848 Q_ASSERT(hook.midx != -1);
1851 hook.midx = staticMetaObject.indexOfSlot(
"unregisterServiceNoLock(QString)");
1852 Q_ASSERT(hook.midx != -1);
1857 hook.params.clear();
1858 hook.params.reserve(4);
1859 hook.params << QMetaType(QMetaType::Void) << QMetaType(QMetaType::QString) << QMetaType(QMetaType::QString) << QMetaType(QMetaType::QString);
1860 hook.midx = staticMetaObject.indexOfSlot(
"serviceOwnerChangedNoLock(QString,QString,QString)");
1861 Q_ASSERT(hook.midx != -1);
1864 watchForDBusDisconnection();
1866 qDBusDebug() <<
this <<
": connected successfully";
1869 QMetaObject::invokeMethod(
this, &QDBusConnectionPrivate::doDispatch, Qt::QueuedConnection);
1877 QDBusConnectionPrivate::processFinishedCall(call);
1881void QDBusConnectionPrivate::processFinishedCall(QDBusPendingCallPrivate *call)
1883 QDBusConnectionPrivate *connection =
const_cast<QDBusConnectionPrivate *>(call->connection);
1885 auto locker = qt_unique_lock(call->mutex);
1887 connection->pendingCalls.removeOne(call);
1889 QDBusMessage &msg = call->replyMessage;
1890 if (call->pending) {
1893 if (q_dbus_pending_call_get_completed(call->pending)) {
1895 DBusMessage *reply = q_dbus_pending_call_steal_reply(call->pending);
1896 msg = QDBusMessagePrivate::fromDBusMessage(reply, connection->connectionCapabilities());
1897 q_dbus_message_unref(reply);
1899 msg = QDBusMessage::createError(QDBusError::Disconnected, QDBusUtil::disconnectedErrorMessage());
1902 qDBusDebug() << connection <<
"got message reply:" << msg;
1905 call->checkReceivedSignature();
1907 if (!call->receiver.isNull() && call->methodIdx != -1 && msg.type() == QDBusMessage::ReplyMessage) {
1916 QDBusCallDeliveryEvent *e = prepareReply(connection, call->receiver, call->methodIdx,
1917 call->metaTypes, msg);
1919 connection->postEventToThread(MessageResultReceivedAction, call->receiver, e);
1924 if (call->pending) {
1925 q_dbus_pending_call_unref(call->pending);
1926 call->pending =
nullptr;
1930 if (call->watcherHelper)
1931 call->watcherHelper->emitSignals(msg, call->sentMessage);
1933 call->waitForFinishedCondition.wakeAll();
1936 if (msg.type() == QDBusMessage::ErrorMessage)
1937 emit connection->callWithCallbackFailed(QDBusError(msg), call->sentMessage);
1939 if (!call->ref.deref())
1943bool QDBusConnectionPrivate::send(
const QDBusMessage& message)
1945 if (QDBusMessagePrivate::isLocal(message))
1951 QDBusMessagePrivate::toDBusMessage(message, connectionCapabilities(), &error);
1953 if (message.type() == QDBusMessage::MethodCallMessage)
1955 "QDBusConnection: error: could not send message to service \"%s\" path "
1956 "\"%s\" interface \"%s\" member \"%s\": %s",
1960 else if (message.type() == QDBusMessage::SignalMessage)
1962 "QDBusConnection: error: could not send signal to service \"%s\" path \"%s\" "
1963 "interface \"%s\" member \"%s\": %s",
1969 "QDBusConnection: error: could not send %s message to service \"%s\": %s",
1970 message.type() == QDBusMessage::ReplyMessage ?
"reply"
1971 : message.type() == QDBusMessage::ErrorMessage ?
"error"
1978 q_dbus_message_set_no_reply(msg,
true);
1979 qDBusDebug() <<
this <<
"sending message (no reply):" << message;
1980 emit messageNeedsSending(
nullptr, msg);
1996#if defined(QT_NO_DEBUG)
2014 env =
qgetenv(
"Q_DBUS_BLOCKING_CALL_MAIN_THREAD_WARNING_MS");
2022 "QDBusBlockingCallWatcher: Q_DBUS_BLOCKING_CALL_MAIN_THREAD_WARNING_MS "
2023 "must be an integer; value ignored");
2026 env =
qgetenv(
"Q_DBUS_BLOCKING_CALL_OTHER_THREAD_WARNING_MS");
2033 "QDBusBlockingCallWatcher: "
2034 "Q_DBUS_BLOCKING_CALL_OTHER_THREAD_WARNING_MS must be an integer; "
2056 if (m_maxCallTimeoutMs < 0)
2059 if (m_callTimer.elapsed() >= m_maxCallTimeoutMs) {
2062 "QDBusConnection: warning: blocking call took a long time (%d ms, max for this "
2063 "thread is %d ms) to service \"%s\" path \"%s\" interface \"%s\" member \"%s\"",
2064 int(m_callTimer.elapsed()), m_maxCallTimeoutMs,
qPrintable(m_message.service()),
2071 QDBusMessage m_message;
2072 int m_maxCallTimeoutMs;
2073 QElapsedTimer m_callTimer;
2076QDBusMessage QDBusConnectionPrivate::sendWithReply(
const QDBusMessage &message,
2077 QDBus::CallMode mode,
int timeout)
2079 QDBusBlockingCallWatcher watcher(message);
2081 QDBusPendingCallPrivate *pcall = sendWithReplyAsync(message,
nullptr,
nullptr,
nullptr, timeout);
2084 if (mode == QDBus::BlockWithGui)
2085 pcall->waitForFinishedWithGui();
2087 pcall->waitForFinished();
2089 QDBusMessage reply = pcall->replyMessage;
2090 lastError = QDBusError(reply);
2092 if (!pcall->ref.deref())
2097QDBusMessage QDBusConnectionPrivate::sendWithReplyLocal(
const QDBusMessage &message)
2099 qDBusDebug() <<
this <<
"sending message via local-loop:" << message;
2101 QDBusMessage localCallMsg = QDBusMessagePrivate::makeLocal(*
this, message);
2102 bool handled = handleMessage(localCallMsg);
2105 QString interface = message.interface();
2106 if (interface.isEmpty())
2107 interface =
"<no-interface>"_L1;
2108 return QDBusMessage::createError(QDBusError::InternalError,
2109 "Internal error trying to call %1.%2 at %3 (signature '%4'"_L1
2110 .arg(interface, message.member(),
2111 message.path(), message.signature()));
2115 QDBusMessage localReplyMsg = QDBusMessagePrivate::makeLocalReply(*
this, localCallMsg);
2116 if (localReplyMsg.type() == QDBusMessage::InvalidMessage) {
2119 "QDBusConnection: cannot call local method '%s' at object %s (with signature '%s') "
2123 return QDBusMessage::createError(
2124 QDBusError(QDBusError::InternalError,
2125 "local-loop message cannot have delayed replies"_L1));
2129 qDBusDebug() <<
this <<
"got message via local-loop:" << localReplyMsg;
2130 return localReplyMsg;
2133QDBusPendingCallPrivate *QDBusConnectionPrivate::sendWithReplyAsync(
const QDBusMessage &message,
2134 QObject *receiver,
const char *returnMethod,
2135 const char *errorMethod,
int timeout)
2137 QDBusPendingCallPrivate *pcall =
new QDBusPendingCallPrivate(message,
this);
2139 if ((isLoopback = isServiceRegisteredByThread(message.service()))) {
2141 pcall->replyMessage = sendWithReplyLocal(message);
2144 if (receiver && returnMethod)
2145 pcall->setReplyCallback(receiver, returnMethod);
2148 Q_ASSERT(!pcall->watcherHelper);
2149 pcall->watcherHelper =
new QDBusPendingCallWatcherHelper;
2150 connect(pcall->watcherHelper, SIGNAL(error(QDBusError,QDBusMessage)), receiver, errorMethod,
2151 Qt::QueuedConnection);
2152 pcall->watcherHelper->moveToThread(thread());
2155 if ((receiver && returnMethod) || errorMethod) {
2157 pcall->ref.storeRelaxed(1);
2161 pcall->ref.storeRelaxed(2);
2166 processFinishedCall(pcall);
2172 QDBusMessagePrivate::toDBusMessage(message, connectionCapabilities(), &error);
2175 "QDBusConnection: error: could not send message to service \"%s\" path \"%s\" "
2176 "interface \"%s\" member \"%s\": %s",
2180 pcall->replyMessage = QDBusMessage::createError(error);
2182 processFinishedCall(pcall);
2184 qDBusDebug() <<
this <<
"sending message:" << message;
2185 emit messageNeedsSending(pcall, msg, timeout);
2190void QDBusConnectionPrivate::sendInternal(QDBusPendingCallPrivate *pcall,
void *message,
int timeout)
2193 DBusPendingCall *pending =
nullptr;
2194 DBusMessage *msg =
static_cast<DBusMessage *>(message);
2195 bool isNoReply = !pcall;
2196 Q_ASSERT(isNoReply == !!q_dbus_message_get_no_reply(msg));
2200 if (isNoReply && q_dbus_connection_send(connection, msg,
nullptr)) {
2202 }
else if (!isNoReply && q_dbus_connection_send_with_reply(connection, msg, &pending, timeout)) {
2204 q_dbus_message_unref(msg);
2206 pcall->pending = pending;
2207 q_dbus_pending_call_set_notify(pending, qDBusResultReceived, pcall,
nullptr);
2210 if (mode == QDBusConnectionPrivate::PeerMode || mode == QDBusConnectionPrivate::ClientMode)
2211 pendingCalls.append(pcall);
2216 lastError = error = QDBusError(QDBusError::Disconnected, QDBusUtil::disconnectedErrorMessage());
2219 lastError = error = QDBusError(QDBusError::NoMemory,
QStringLiteral(
"Out of memory"));
2222 q_dbus_message_unref(msg);
2224 pcall->replyMessage = QDBusMessage::createError(error);
2225 processFinishedCall(pcall);
2230bool QDBusConnectionPrivate::connectSignal(
const QString &service,
2231 const QString &path,
const QString &interface,
const QString &name,
2232 const QStringList &argumentMatch,
const QString &signature,
2233 QObject *receiver,
const char *slot)
2235 ArgMatchRules rules;
2236 rules.args = argumentMatch;
2237 return connectSignal(service, path, interface, name, rules, signature, receiver, slot);
2240bool QDBusConnectionPrivate::connectSignal(
const QString &service,
2241 const QString &path,
const QString &interface,
const QString &name,
2242 const ArgMatchRules &argumentMatch,
const QString &signature,
2243 QObject *receiver,
const char *slot)
2246 QDBusConnectionPrivate::SignalHook hook;
2249 hook.signature = signature;
2251 if (!prepareHook(hook, key, service, path, interface, name, argumentMatch, receiver, slot, 0,
2254 <<
"Could not connect" << interface <<
"to" << slot + 1 <<
":" <<
qPrintable(errorMsg);
2258 Q_ASSERT(thread() != QThread::currentThread());
2259 return addSignalHook(key, hook);
2262bool QDBusConnectionPrivate::addSignalHook(
const QString &key,
const SignalHook &hook)
2264 bool result =
false;
2266 QMetaObject::invokeMethod(
this, &QDBusConnectionPrivate::addSignalHookImpl,
2267 Qt::BlockingQueuedConnection, qReturnArg(result), key, hook);
2272bool QDBusConnectionPrivate::addSignalHookImpl(
const QString &key,
const SignalHook &hook)
2274 QDBusWriteLocker locker(ConnectAction,
this);
2277 QDBusConnectionPrivate::SignalHookHash::ConstIterator it = signalHooks.constFind(key);
2278 QDBusConnectionPrivate::SignalHookHash::ConstIterator end = signalHooks.constEnd();
2279 for ( ; it != end && it.key() == key; ++it) {
2280 const QDBusConnectionPrivate::SignalHook &entry = it.value();
2281 if (entry.service == hook.service &&
2282 entry.path == hook.path &&
2283 entry.signature == hook.signature &&
2284 entry.obj == hook.obj &&
2285 entry.midx == hook.midx &&
2286 entry.argumentMatch == hook.argumentMatch) {
2292 signalHooks.insert(key, hook);
2293 connect(hook.obj, &QObject::destroyed,
this, &QDBusConnectionPrivate::objectDestroyed,
2294 Qt::ConnectionType(Qt::BlockingQueuedConnection | Qt::UniqueConnection));
2296 MatchRefCountHash::iterator mit = matchRefCounts.find(hook.matchRule);
2298 if (mit != matchRefCounts.end()) {
2299 mit.value() = mit.value() + 1;
2303 matchRefCounts.insert(hook.matchRule, 1);
2306 if (mode != QDBusConnectionPrivate::PeerMode) {
2307 qDBusDebug() <<
this <<
"Adding rule:" << hook.matchRule;
2308 q_dbus_bus_add_match(connection, hook.matchRule,
nullptr);
2312 if (shouldWatchService(hook.service)) {
2313 WatchedServicesHash::mapped_type &data = watchedServices[hook.service];
2314 if (++data.refcount == 1) {
2316 ArgMatchRules rules;
2317 rules.args << hook.service;
2318 q_dbus_bus_add_match(connection,
2319 buildMatchRule(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(),
2320 QDBusUtil::nameOwnerChanged(), rules, QString()),
2322 data.owner = getNameOwnerNoCache(hook.service);
2323 qDBusDebug() <<
this <<
"Watching service" << hook.service <<
"for owner changes (current owner:"
2324 << data.owner <<
")";
2332bool QDBusConnectionPrivate::disconnectSignal(
const QString &service,
2333 const QString &path,
const QString &interface,
const QString &name,
2334 const QStringList &argumentMatch,
const QString &signature,
2335 QObject *receiver,
const char *slot)
2337 ArgMatchRules rules;
2338 rules.args = argumentMatch;
2339 return disconnectSignal(service, path, interface, name, rules, signature, receiver, slot);
2342bool QDBusConnectionPrivate::disconnectSignal(
const QString &service,
2343 const QString &path,
const QString &interface,
const QString &name,
2344 const ArgMatchRules &argumentMatch,
const QString &signature,
2345 QObject *receiver,
const char *slot)
2348 QDBusConnectionPrivate::SignalHook hook;
2350 QString name2 = name;
2354 hook.signature = signature;
2356 if (!prepareHook(hook, key, service, path, interface, name, argumentMatch, receiver, slot, 0,
2359 <<
"Could not disconnect" << interface <<
"to" << slot + 1 <<
":" <<
qPrintable(errorMsg);
2363 Q_ASSERT(thread() != QThread::currentThread());
2364 return removeSignalHook(key, hook);
2367bool QDBusConnectionPrivate::removeSignalHook(
const QString &key,
const SignalHook &hook)
2369 bool result =
false;
2371 QMetaObject::invokeMethod(
this, &QDBusConnectionPrivate::removeSignalHookImpl,
2372 Qt::BlockingQueuedConnection, qReturnArg(result), key, hook);
2377bool QDBusConnectionPrivate::removeSignalHookImpl(
const QString &key,
const SignalHook &hook)
2380 QDBusWriteLocker locker(ConnectAction,
this);
2381 QDBusConnectionPrivate::SignalHookHash::Iterator it = signalHooks.find(key);
2382 QDBusConnectionPrivate::SignalHookHash::Iterator end = signalHooks.end();
2383 for ( ; it != end && it.key() == key; ++it) {
2384 const QDBusConnectionPrivate::SignalHook &entry = it.value();
2385 if (entry.service == hook.service &&
2386 entry.path == hook.path &&
2387 entry.signature == hook.signature &&
2388 entry.obj == hook.obj &&
2389 entry.midx == hook.midx &&
2390 entry.argumentMatch.args == hook.argumentMatch.args) {
2392 removeSignalHookNoLock(it);
2401QDBusConnectionPrivate::SignalHookHash::Iterator
2402QDBusConnectionPrivate::removeSignalHookNoLock(SignalHookHash::Iterator it)
2404 const SignalHook &hook = it.value();
2407 MatchRefCountHash::iterator i = matchRefCounts.find(hook.matchRule);
2408 if (i == matchRefCounts.end()) {
2410 "QDBusConnectionPrivate::disconnectSignal: MatchRule not found in "
2411 "matchRefCounts!!");
2413 if (i.value() == 1) {
2415 matchRefCounts.erase(i);
2418 i.value() = i.value() - 1;
2423 if (connection && erase) {
2424 if (mode != QDBusConnectionPrivate::PeerMode) {
2425 qDBusDebug() <<
this <<
"Removing rule:" << hook.matchRule;
2426 q_dbus_bus_remove_match(connection, hook.matchRule,
nullptr);
2430 WatchedServicesHash::Iterator sit = watchedServices.find(hook.service);
2431 if (sit != watchedServices.end()) {
2432 if (--sit.value().refcount == 0) {
2433 watchedServices.erase(sit);
2434 ArgMatchRules rules;
2435 rules.args << hook.service;
2436 q_dbus_bus_remove_match(connection,
2437 buildMatchRule(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(),
2438 QDBusUtil::nameOwnerChanged(), rules, QString()),
2446 return signalHooks.erase(it);
2449void QDBusConnectionPrivate::registerObject(
const ObjectTreeNode *node)
2451 connect(node->obj, &QObject::destroyed,
this, &QDBusConnectionPrivate::objectDestroyed,
2452 Qt::ConnectionType(Qt::BlockingQueuedConnection | Qt::UniqueConnection));
2454 if (node->flags & (QDBusConnection::ExportAdaptors
2455 | QDBusConnection::ExportScriptableSignals
2456 | QDBusConnection::ExportNonScriptableSignals)) {
2457 QDBusAdaptorConnector *connector = qDBusCreateAdaptorConnector(node->obj);
2459 if (node->flags & (QDBusConnection::ExportScriptableSignals
2460 | QDBusConnection::ExportNonScriptableSignals)) {
2461 connector->disconnectAllSignals(node->obj);
2462 connector->connectAllSignals(node->obj);
2465 connect(connector, &QDBusAdaptorConnector::relaySignal,
this,
2466 &QDBusConnectionPrivate::relaySignal,
2467 Qt::ConnectionType(Qt::QueuedConnection | Qt::UniqueConnection));
2471void QDBusConnectionPrivate::unregisterObject(
const QString &path, QDBusConnection::UnregisterMode mode)
2473 QDBusConnectionPrivate::ObjectTreeNode *node = &rootNode;
2474 QList<QStringView> pathComponents;
2476 if (path ==
"/"_L1) {
2479 pathComponents = QStringView{path}.split(u'/');
2483 huntAndUnregister(pathComponents, i, mode, node);
2486void QDBusConnectionPrivate::connectRelay(
const QString &service,
2487 const QString &path,
const QString &interface,
2488 QDBusAbstractInterface *receiver,
2489 const QMetaMethod &signal)
2497 sig.append(QSIGNAL_CODE +
'0');
2498 sig.append(signal.methodSignature());
2500 if (!prepareHook(hook, key, service, path, interface, QString(), ArgMatchRules(), receiver, sig,
2501 QDBusAbstractInterface::staticMetaObject.methodCount(),
true, errorMsg)) {
2503 <<
"Could not connect" << interface <<
"to" << signal.name() <<
":" <<
qPrintable(errorMsg);
2507 Q_ASSERT(thread() != QThread::currentThread());
2508 addSignalHook(key, hook);
2511void QDBusConnectionPrivate::disconnectRelay(
const QString &service,
2512 const QString &path,
const QString &interface,
2513 QDBusAbstractInterface *receiver,
2514 const QMetaMethod &signal)
2522 sig.append(QSIGNAL_CODE +
'0');
2523 sig.append(signal.methodSignature());
2525 if (!prepareHook(hook, key, service, path, interface, QString(), ArgMatchRules(), receiver, sig,
2526 QDBusAbstractInterface::staticMetaObject.methodCount(),
true, errorMsg)) {
2527 qCWarning(dbusIntegration) <<
"Could not disconnect" << interface <<
"to"
2528 << signal.methodSignature() <<
":" <<
qPrintable(errorMsg);
2532 Q_ASSERT(thread() != QThread::currentThread());
2533 removeSignalHook(key, hook);
2536bool QDBusConnectionPrivate::shouldWatchService(
const QString &service)
2539 if (mode != ClientMode)
2542 if (service.isEmpty())
2545 if (service == QDBusUtil::dbusService())
2551
2552
2553
2554
2555
2556
2557
2558
2559void QDBusConnectionPrivate::watchService(
const QString &service, QDBusServiceWatcher::WatchMode mode, QObject *obj,
const char *member)
2561 ArgMatchRules matchArgs = matchArgsForService(service, mode);
2562 connectSignal(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(), QDBusUtil::nameOwnerChanged(),
2563 matchArgs, QString(), obj, member);
2567
2568
2569
2570
2571
2572
2573
2574void QDBusConnectionPrivate::unwatchService(
const QString &service, QDBusServiceWatcher::WatchMode mode, QObject *obj,
const char *member)
2576 ArgMatchRules matchArgs = matchArgsForService(service, mode);
2577 disconnectSignal(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(), QDBusUtil::nameOwnerChanged(),
2578 matchArgs, QString(), obj, member);
2581QString QDBusConnectionPrivate::getNameOwner(
const QString& serviceName)
2583 if (QDBusUtil::isValidUniqueConnectionName(serviceName))
2590 QReadLocker locker(&lock);
2591 WatchedServicesHash::ConstIterator it = watchedServices.constFind(serviceName);
2592 if (it != watchedServices.constEnd())
2597 return getNameOwnerNoCache(serviceName);
2600QString QDBusConnectionPrivate::getNameOwnerNoCache(
const QString &serviceName)
2602 QDBusMessage msg = QDBusMessage::createMethodCall(QDBusUtil::dbusService(),
2603 QDBusUtil::dbusPath(), QDBusUtil::dbusInterface(),
2605 QDBusMessagePrivate::setParametersValidated(msg,
true);
2608 QDBusPendingCallPrivate *pcall = sendWithReplyAsync(msg,
nullptr,
nullptr,
nullptr);
2609 if (thread() == QThread::currentThread()) {
2612 q_dbus_pending_call_block(pcall->pending);
2614 pcall->waitForFinished();
2615 msg = pcall->replyMessage;
2617 if (!pcall->ref.deref())
2620 if (msg.type() == QDBusMessage::ReplyMessage)
2621 return msg.arguments().at(0).toString();
2626QDBusConnectionPrivate::findMetaObject(
const QString &service,
const QString &path,
2627 const QString &interface, QDBusError &error)
2630 if (!interface.isEmpty()) {
2631 QDBusReadLocker locker(FindMetaObject1Action,
this);
2632 QDBusMetaObject *mo = cachedMetaObjects.value(interface,
nullptr);
2636 if (path.isEmpty()) {
2637 error = QDBusError(QDBusError::InvalidObjectPath,
"Object path cannot be empty"_L1);
2643 QDBusMessage msg = QDBusMessage::createMethodCall(service, path,
2644 QDBusUtil::dbusInterfaceIntrospectable(),
2646 QDBusMessagePrivate::setParametersValidated(msg,
true);
2648 QDBusMessage reply = sendWithReply(msg, QDBus::Block);
2651 QDBusWriteLocker locker(FindMetaObject2Action,
this);
2652 QDBusMetaObject *mo =
nullptr;
2653 if (!interface.isEmpty())
2654 mo = cachedMetaObjects.value(interface,
nullptr);
2660 if (reply.type() == QDBusMessage::ReplyMessage) {
2661 if (reply.signature() ==
"s"_L1)
2663 xml = reply.arguments().at(0).toString();
2665 error = QDBusError(reply);
2667 if (reply.type() != QDBusMessage::ErrorMessage || error.type() != QDBusError::UnknownMethod)
2672 QDBusMetaObject *result = QDBusMetaObject::createMetaObject(interface, xml,
2673 cachedMetaObjects, error);
2678void QDBusConnectionPrivate::registerService(
const QString &serviceName)
2680 QDBusWriteLocker locker(RegisterServiceAction,
this);
2681 registerServiceNoLock(serviceName);
2684void QDBusConnectionPrivate::registerServiceNoLock(
const QString &serviceName)
2686 serviceNames.append(serviceName);
2689void QDBusConnectionPrivate::unregisterService(
const QString &serviceName)
2691 QDBusWriteLocker locker(UnregisterServiceAction,
this);
2692 unregisterServiceNoLock(serviceName);
2695void QDBusConnectionPrivate::unregisterServiceNoLock(
const QString &serviceName)
2697 serviceNames.removeAll(serviceName);
2700bool QDBusConnectionPrivate::isServiceRegisteredByThread(
const QString &serviceName)
2702 if (!serviceName.isEmpty() && serviceName == baseService)
2704 if (serviceName == QDBusUtil::dbusService())
2707 QDBusReadLocker locker(UnregisterServiceAction,
this);
2708 return serviceNames.contains(serviceName);
2711void QDBusConnectionPrivate::postEventToThread(
int action, QObject *object, QEvent *ev)
2713 QDBusLockerBase::reportThreadAction(action, QDBusLockerBase::BeforePost,
this);
2714 QCoreApplication::postEvent(object, ev);
2715 QDBusLockerBase::reportThreadAction(action, QDBusLockerBase::AfterPost,
this);
2719
2720
2721
2722
2723void QDBusConnectionPrivate::enableDispatchDelayed(QObject *context)
2726 QMetaObject::invokeMethod(
2732 QMetaObject::invokeMethod(
this, &QDBusConnectionPrivate::setDispatchEnabled,
2733 Qt::QueuedConnection,
true);
2737 Qt::QueuedConnection);
~QDBusActivateObjectEvent() override
void placeMetaCall(QObject *) override
~QDBusBlockingCallWatcher()
static QDBusConnectionManager * instance()
DBusPendingCall * pending
~QDBusSpyCallEvent() override
void placeMetaCall(QObject *) override
static void invokeSpyHooks(const QDBusMessage &msg)
void(* Hook)(const QDBusMessage &)
void add(QDBusSpyCallEvent::Hook hook)
void invoke(const QDBusMessage &msg)
#define DBUS_TYPE_UNIX_FD
dbus_uint32_t dbus_bool_t
@ DBUS_HANDLER_RESULT_HANDLED
@ DBUS_HANDLER_RESULT_NOT_YET_HANDLED
#define DBUS_INTERFACE_LOCAL
#define DBUS_INTERFACE_DBUS
@ DBUS_DISPATCH_DATA_REMAINS
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return dbus_watch_get_unix_fd
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return dbus_connection_send
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction dbus_timeout_get_enabled
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return dbus_message_unref
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return dbus_message_copy
static void qDBusNewConnection(DBusServer *server, DBusConnection *connection, void *data)
static QDBusConnectionPrivate::ArgMatchRules matchArgsForService(const QString &service, QDBusServiceWatcher::WatchMode mode)
static bool findObject(const QDBusConnectionPrivate::ObjectTreeNode *root, const QString &fullpath, int &usedLength, QDBusConnectionPrivate::ObjectTreeNode &result)
static void qDBusUpdateDispatchStatus(DBusConnection *connection, DBusDispatchStatus new_status, void *data)
static void qDBusRemoveWatch(DBusWatch *watch, void *data)
static dbus_int32_t server_slot
static void qDBusResultReceived(DBusPendingCall *pending, void *user_data)
static void qDBusToggleTimeout(DBusTimeout *timeout, void *data)
static void huntAndUnregister(const QList< QStringView > &pathComponents, int i, QDBusConnection::UnregisterMode mode, QDBusConnectionPrivate::ObjectTreeNode *node)
static dbus_bool_t qDBusAddWatch(DBusWatch *watch, void *data)
static QDBusConnection::ConnectionCapabilities connectionCapabilities(DBusConnection *connection)
static dbus_bool_t qDBusAddTimeout(DBusTimeout *timeout, void *data)
static QObject * findChildObject(const QDBusConnectionPrivate::ObjectTreeNode *root, const QString &fullpath, int start)
Q_DBUS_EXPORT void qDBusAddSpyHook(QDBusSpyCallEvent::Hook)
static QDBusCallDeliveryEvent *const DIRECT_DELIVERY
static void huntAndEmit(DBusConnection *connection, DBusMessage *msg, QObject *needle, const QDBusConnectionPrivate::ObjectTreeNode &haystack, bool isScriptable, bool isAdaptor, const QString &path=QString())
static void qDBusRemoveTimeout(DBusTimeout *timeout, void *data)
static QByteArray buildMatchRule(const QString &service, const QString &objectPath, const QString &interface, const QString &member, const QDBusConnectionPrivate::ArgMatchRules &argMatch, const QString &)
static DBusHandlerResult qDBusSignalFilter(DBusConnection *connection, DBusMessage *message, void *data)
static void qDBusToggleWatch(DBusWatch *watch, void *data)
static int findSlot(const QMetaObject *mo, const QByteArray &name, int flags, const QString &signature_, QList< QMetaType > &metaTypes)
static void huntAndDestroy(QObject *needle, QDBusConnectionPrivate::ObjectTreeNode &haystack)
@ HandleObjectCallPostEventAction
#define qCWarning(category,...)
#define Q_STATIC_LOGGING_CATEGORY(name,...)
#define qPrintable(string)
#define QStringLiteral(str)
#define qUtf16Printable(string)
static void reportThreadAction(int, int, QDBusConnectionPrivate *)