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 (QThread *thr = thread(); thr && !thr->isCurrentThread()) {
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",
1081 auto lastMode = mode;
1083 qDeleteAll(cachedMetaObjects);
1085 if (lastMode == ClientMode || lastMode == PeerMode) {
1088 Q_ASSERT(ref.loadRelaxed() == 0);
1089 QObject *obj = (QObject *)busService;
1091 disconnect(obj,
nullptr,
this,
nullptr);
1095 q_dbus_connection_unref(connection);
1096 connection =
nullptr;
1097 }
else if (lastMode == ServerMode) {
1099 q_dbus_server_unref(server);
1104void QDBusConnectionPrivate::collectAllObjects(QDBusConnectionPrivate::ObjectTreeNode &haystack,
1105 QSet<QObject *> &set)
1107 for (ObjectTreeNode &child : haystack.children)
1108 collectAllObjects(child, set);
1111 set.insert(haystack.obj);
1114void QDBusConnectionPrivate::closeConnection()
1116 QDBusWriteLocker locker(CloseConnectionAction,
this);
1118 ConnectionMode oldMode = mode;
1120 baseService.clear();
1122 if (oldMode == ServerMode && server) {
1123 q_dbus_server_disconnect(server);
1124 q_dbus_server_free_data_slot(&server_slot);
1127 if (oldMode == ClientMode || oldMode == PeerMode) {
1129 q_dbus_connection_close(connection);
1131 while (q_dbus_connection_dispatch(connection) == DBUS_DISPATCH_DATA_REMAINS)
1136 for (QDBusPendingCallPrivate *call : std::as_const(pendingCalls)) {
1137 if (!call->ref.deref())
1140 pendingCalls.clear();
1147 QSet<QObject *> allObjects;
1148 collectAllObjects(rootNode, allObjects);
1149 for (
const SignalHook &signalHook : std::as_const(signalHooks))
1150 allObjects.insert(signalHook.obj);
1153 for (QObject *obj : std::as_const(allObjects))
1154 obj->disconnect(
this);
1157void QDBusConnectionPrivate::handleDBusDisconnection()
1159 while (!pendingCalls.isEmpty())
1160 processFinishedCall(pendingCalls.first());
1163void QDBusConnectionPrivate::checkThread()
1165 Q_ASSERT(thread() == QDBusConnectionManager::instance());
1166 Q_ASSERT(QThread::currentThread() == thread());
1169bool QDBusConnectionPrivate::handleError(
const QDBusErrorInternal &error)
1180void QDBusConnectionPrivate::timerEvent(QTimerEvent *e)
1183 DBusTimeout *timeout = timeouts.value(e->timerId(),
nullptr);
1185 q_dbus_timeout_handle(timeout);
1191void QDBusConnectionPrivate::doDispatch()
1193 if (mode == ClientMode || mode == PeerMode) {
1194 if (dispatchEnabled && !pendingMessages.isEmpty()) {
1196 for (QDBusMessage &message : pendingMessages) {
1197 qDBusDebug() <<
this <<
"dequeueing message" << message;
1198 handleMessage(std::move(message));
1200 pendingMessages.clear();
1202 while (q_dbus_connection_dispatch(connection) == DBUS_DISPATCH_DATA_REMAINS) ;
1206void QDBusConnectionPrivate::socketRead(qintptr fd)
1208 WatcherHash::ConstIterator it = watchers.constFind(fd);
1209 while (it != watchers.constEnd() && it.key() == fd) {
1210 if (it->watch && it->read && it->read->isEnabled()) {
1211 if (!q_dbus_watch_handle(it.value().watch, DBUS_WATCH_READABLE))
1212 qDebug(
"OUT OF MEM");
1217 if ((mode == ClientMode || mode == PeerMode) && !isAuthenticated
1218 && q_dbus_connection_get_is_authenticated(connection))
1219 handleAuthentication();
1223void QDBusConnectionPrivate::socketWrite(qintptr fd)
1225 WatcherHash::ConstIterator it = watchers.constFind(fd);
1226 while (it != watchers.constEnd() && it.key() == fd) {
1227 if (it->watch && it->write && it->write->isEnabled()) {
1228 if (!q_dbus_watch_handle(it.value().watch, DBUS_WATCH_WRITABLE))
1229 qDebug(
"OUT OF MEM");
1234 if ((mode == ClientMode || mode == PeerMode) && !isAuthenticated
1235 && q_dbus_connection_get_is_authenticated(connection))
1236 handleAuthentication();
1239void QDBusConnectionPrivate::objectDestroyed(QObject *obj)
1241 QDBusWriteLocker locker(ObjectDestroyedAction,
this);
1242 huntAndDestroy(obj, rootNode);
1244 SignalHookHash::iterator sit = signalHooks.begin();
1245 while (sit != signalHooks.end()) {
1246 if (
static_cast<QObject *>(sit.value().obj) == obj)
1247 sit = removeSignalHookNoLock(sit);
1252 obj->disconnect(
this);
1255void QDBusConnectionPrivate::relaySignal(QObject *obj,
const QMetaObject *mo,
int signalId,
1256 const QVariantList &args)
1258 QString interface = qDBusInterfaceFromMetaObject(mo);
1260 QMetaMethod mm = mo->method(signalId);
1261 QByteArray memberName = mm.name();
1264 bool isScriptable = mm.attributes() & QMetaMethod::Scriptable;
1265 bool isAdaptor =
false;
1266 for ( ; mo; mo = mo->superClass())
1267 if (mo == &QDBusAbstractAdaptor::staticMetaObject) {
1273 QDBusReadLocker locker(RelaySignalAction,
this);
1274 QDBusMessage message = QDBusMessage::createSignal(
"/"_L1, interface,
1275 QLatin1StringView(memberName));
1276 QDBusMessagePrivate::setParametersValidated(message,
true);
1277 message.setArguments(args);
1280 QDBusMessagePrivate::toDBusMessage(message, connectionCapabilities(), &error);
1282 qCWarning(dbusIntegration,
"QDBusConnection: Could not emit signal %s.%s: %s",
1290 q_dbus_message_set_no_reply(msg,
true);
1291 huntAndEmit(connection, msg, obj, rootNode, isScriptable, isAdaptor);
1292 q_dbus_message_unref(msg);
1295void QDBusConnectionPrivate::serviceOwnerChangedNoLock(
const QString &name,
1296 const QString &oldOwner,
const QString &newOwner)
1299 WatchedServicesHash::Iterator it = watchedServices.find(name);
1300 if (it == watchedServices.end())
1302 if (oldOwner != it->owner)
1304 "QDBusConnection: name '%s' had owner '%s' but we thought it was '%s'",
1307 qDBusDebug() <<
this <<
"Updating name" << name <<
"from" << oldOwner <<
"to" << newOwner;
1308 it->owner = newOwner;
1311int QDBusConnectionPrivate::findSlot(QObject *obj,
const QByteArray &normalizedName,
1312 QList<QMetaType> ¶ms, QString &errorMsg)
1315 int midx = obj->metaObject()->indexOfMethod(normalizedName);
1319 int inputCount = qDBusParametersForMethod(obj->metaObject()->method(midx), params, errorMsg);
1320 if (inputCount == -1 || inputCount + 1 != params.size())
1326bool QDBusConnectionPrivate::prepareHook(QDBusConnectionPrivate::SignalHook &hook, QString &key,
1327 const QString &service,
const QString &path,
1328 const QString &interface,
const QString &name,
1329 const ArgMatchRules &argMatch, QObject *receiver,
1330 const char *signal,
int minMIdx,
bool buildSignature,
1333 QByteArray normalizedName = signal + 1;
1334 hook.midx = findSlot(receiver, signal + 1, hook.params, errorMsg);
1335 if (hook.midx == -1) {
1336 normalizedName = QMetaObject::normalizedSignature(signal + 1);
1337 hook.midx = findSlot(receiver, normalizedName, hook.params, errorMsg);
1339 if (hook.midx < minMIdx) {
1343 hook.service = service;
1345 hook.obj = receiver;
1346 hook.argumentMatch = argMatch;
1351 QString mname = name;
1352 if (buildSignature && mname.isNull()) {
1353 normalizedName.truncate(normalizedName.indexOf(
'('));
1354 mname = QString::fromUtf8(normalizedName);
1357 key.reserve(interface.size() + 1 + mname.size());
1361 if (buildSignature) {
1362 hook.signature.clear();
1363 for (
int i = 1; i < hook.params.size(); ++i)
1364 if (hook.params.at(i) != QDBusMetaTypeId::message())
1365 hook.signature += QLatin1StringView(QDBusMetaType::typeToSignature(hook.params.at(i)));
1368 hook.matchRule = buildMatchRule(service, path, interface, mname, argMatch, hook.signature);
1372void QDBusConnectionPrivate::sendError(
const QDBusMessage &msg, QDBusError::ErrorType code)
1374 if (code == QDBusError::UnknownMethod) {
1375 QString interfaceMsg;
1376 if (msg.interface().isEmpty())
1377 interfaceMsg =
"any interface"_L1;
1379 interfaceMsg =
"interface '%1'"_L1.arg(msg.interface());
1381 send(msg.createErrorReply(code,
"No such method '%1' in %2 at object path '%3' "
1382 "(signature '%4')"_L1
1383 .arg(msg.member(), interfaceMsg, msg.path(), msg.signature())));
1384 }
else if (code == QDBusError::UnknownInterface) {
1385 send(msg.createErrorReply(QDBusError::UnknownInterface,
1386 "No such interface '%1' at object path '%2'"_L1
1387 .arg(msg.interface(), msg.path())));
1388 }
else if (code == QDBusError::UnknownObject) {
1389 send(msg.createErrorReply(QDBusError::UnknownObject,
1390 "No such object path '%1'"_L1.arg(msg.path())));
1394bool QDBusConnectionPrivate::activateInternalFilters(
const ObjectTreeNode &node,
1395 const QDBusMessage &msg)
1398 const QString interface = msg.interface();
1400 if (interface.isEmpty() || interface == QDBusUtil::dbusInterfaceIntrospectable()) {
1401 if (msg.member() ==
"Introspect"_L1 && msg.signature().isEmpty()) {
1403 QDBusMessage reply = msg.createReply(qDBusIntrospectObject(node, msg.path()));
1408 if (!interface.isEmpty()) {
1409 sendError(msg, QDBusError::UnknownMethod);
1414 if (node.obj && (interface.isEmpty() ||
1415 interface == QDBusUtil::dbusInterfaceProperties())) {
1418 QDBusContextPrivate context(QDBusConnection(
this), msg);
1419 QDBusContextPrivate *old = QDBusContextPrivate::set(node.obj, &context);
1420 auto guard = qScopeGuard([&node, old]{
1421 QDBusContextPrivate::set(node.obj, old);
1424 if (msg.member() ==
"Get"_L1 && msg.signature() ==
"ss"_L1) {
1425 QDBusMessage reply = qDBusPropertyGet(node, msg);
1426 if (!msg.isDelayedReply()) {
1430 }
else if (msg.member() ==
"Set"_L1 && msg.signature() ==
"ssv"_L1) {
1431 QDBusMessage reply = qDBusPropertySet(node, msg);
1432 if (!msg.isDelayedReply()) {
1436 }
else if (msg.member() ==
"GetAll"_L1 && msg.signature() ==
"s"_L1) {
1437 QDBusMessage reply = qDBusPropertyGetAll(node, msg);
1438 if (!msg.isDelayedReply()) {
1444 if (!interface.isEmpty()) {
1445 sendError(msg, QDBusError::UnknownMethod);
1453void QDBusConnectionPrivate::activateObject(ObjectTreeNode &node,
const QDBusMessage &msg,
1463 if (node.flags & QDBusConnectionPrivate::VirtualObject) {
1464 if (node.treeNode->handleMessage(msg, q(
this))) {
1467 if (activateInternalFilters(node, msg))
1472 if (pathStartPos != msg.path().size()) {
1473 node.flags &= ~QDBusConnection::ExportAllSignals;
1474 node.obj = findChildObject(&node, msg.path(), pathStartPos);
1476 sendError(msg, QDBusError::UnknownObject);
1481 QDBusAdaptorConnector *connector;
1482 if (node.flags & QDBusConnection::ExportAdaptors &&
1483 (connector = qDBusFindAdaptorConnector(node.obj))) {
1484 auto newflags = node.flags | QDBusConnection::ExportAllSlots;
1486 if (msg.interface().isEmpty()) {
1489 for (
const QDBusAdaptorConnector::AdaptorData &adaptorData :
1490 std::as_const(connector->adaptors)) {
1491 if (activateCall(adaptorData.adaptor, newflags, msg))
1496 QDBusAdaptorConnector::AdaptorMap::ConstIterator it;
1497 it = std::lower_bound(connector->adaptors.constBegin(), connector->adaptors.constEnd(),
1499 if (it != connector->adaptors.constEnd() && msg.interface() == QLatin1StringView(it->interface)) {
1500 if (!activateCall(it->adaptor, newflags, msg))
1501 sendError(msg, QDBusError::UnknownMethod);
1509 if (activateInternalFilters(node, msg))
1513 if (node.flags & (QDBusConnection::ExportScriptableSlots|QDBusConnection::ExportNonScriptableSlots) ||
1514 node.flags & (QDBusConnection::ExportScriptableInvokables|QDBusConnection::ExportNonScriptableInvokables)) {
1515 bool interfaceFound =
true;
1516 if (!msg.interface().isEmpty()) {
1517 if (!node.interfaceName.isEmpty())
1518 interfaceFound = msg.interface() == node.interfaceName;
1520 interfaceFound = qDBusInterfaceInObject(node.obj, msg.interface());
1523 if (interfaceFound) {
1524 if (!activateCall(node.obj, node.flags, msg))
1525 sendError(msg, QDBusError::UnknownMethod);
1531 if (msg.interface().isEmpty())
1532 sendError(msg, QDBusError::UnknownMethod);
1534 sendError(msg, QDBusError::UnknownInterface);
1537void QDBusConnectionPrivate::handleObjectCall(
const QDBusMessage &msg)
1546 ObjectTreeNode result;
1548 QThread *objThread =
nullptr;
1553 QDBusReadLocker locker(HandleObjectCallAction,
this);
1554 if (!findObject(&rootNode, msg.path(), usedLength, result)) {
1556 sendError(msg, QDBusError::UnknownObject);
1563 activateObject(result, msg, usedLength);
1567 objThread = result.obj->thread();
1569 send(msg.createErrorReply(QDBusError::InternalError,
1570 "Object '%1' (at path '%2')"
1571 " has no thread. Cannot deliver message."_L1
1572 .arg(result.obj->objectName(), msg.path())));
1576 if (!QDBusMessagePrivate::isLocal(msg)) {
1579 postEventToThread(HandleObjectCallPostEventAction, result.obj,
1580 new QDBusActivateObjectEvent(QDBusConnection(
this),
this, result,
1583 }
else if (!objThread->isCurrentThread()) {
1586 postEventToThread(HandleObjectCallPostEventAction, result.obj,
1587 new QDBusActivateObjectEvent(QDBusConnection(
this),
this, result,
1588 usedLength, msg, &latch));
1599 activateObject(result, msg, usedLength);
1607 QDBusConnectionPrivate *that = QDBusConnectionPrivate::d(connection);
1608 that->sendError(message, QDBusError::UnknownObject);
1616 QDBusConnectionPrivate *that = QDBusConnectionPrivate::d(connection);
1620 that->activateObject(node, message, pathStartPos);
1627void QDBusConnectionPrivate::handleSignal(
const QString &key,
const QDBusMessage& msg)
1629 SignalHookHash::const_iterator it = signalHooks.constFind(key);
1630 SignalHookHash::const_iterator end = signalHooks.constEnd();
1633 for ( ; it != end && it.key() == key; ++it) {
1634 const SignalHook &hook = it.value();
1635 if (!hook.service.isEmpty()) {
1636 QString owner = watchedServices.value(hook.service, WatchedServiceData(hook.service)).owner;
1637 if (owner != msg.service())
1640 if (!hook.path.isEmpty() && hook.path != msg.path())
1642 if (!hook.signature.isEmpty() && hook.signature != msg.signature())
1644 if (hook.signature.isEmpty() && !hook.signature.isNull() && !msg.signature().isEmpty())
1646 if (!hook.argumentMatch.args.isEmpty()) {
1647 const QVariantList arguments = msg.arguments();
1648 if (hook.argumentMatch.args.size() > arguments.size())
1651 bool matched =
true;
1652 for (
int i = 0; i < hook.argumentMatch.args.size(); ++i) {
1653 const QString ¶m = hook.argumentMatch.args.at(i);
1656 if (param == arguments.at(i).toString())
1664 if (!hook.argumentMatch.arg0namespace.isEmpty()) {
1665 const QVariantList arguments = msg.arguments();
1666 if (arguments.size() < 1)
1668 const QString param = arguments.at(0).toString();
1669 const QStringView ns = hook.argumentMatch.arg0namespace;
1670 if (!param.startsWith(ns) || (param.size() != ns.size() && param[ns.size()] != u'.'))
1673 activateSignal(hook, msg);
1677void QDBusConnectionPrivate::handleSignal(
const QDBusMessage& msg)
1686 QString key = msg.member();
1687 key.reserve(key.size() + 1 + msg.interface().size());
1689 key += msg.interface();
1691 QDBusWriteLocker locker(HandleSignalAction,
this);
1692 handleSignal(key, msg);
1694 key.truncate(msg.member().size() + 1);
1695 handleSignal(key, msg);
1698 key += msg.interface();
1699 handleSignal(key, msg);
1702void QDBusConnectionPrivate::watchForDBusDisconnection()
1706 hook.service.clear();
1707 hook.path = QDBusUtil::dbusPathLocal();
1709 hook.params << QMetaType(QMetaType::Void);
1710 hook.midx = staticMetaObject.indexOfSlot(
"handleDBusDisconnection()");
1711 Q_ASSERT(hook.midx != -1);
1715void QDBusConnectionPrivate::setServer(QDBusServer *object, DBusServer *s,
const QDBusErrorInternal &error)
1718 serverObject = object;
1727 dbus_bool_t data_allocated = q_dbus_server_allocate_data_slot(&server_slot);
1728 if (data_allocated && server_slot < 0)
1731 dbus_bool_t watch_functions_set = q_dbus_server_set_watch_functions(server,
1737 Q_UNUSED(watch_functions_set);
1739 dbus_bool_t time_functions_set = q_dbus_server_set_timeout_functions(server,
1745 Q_UNUSED(time_functions_set);
1747 q_dbus_server_set_new_connection_function(server, qDBusNewConnection,
this,
nullptr);
1749 dbus_bool_t data_set = q_dbus_server_set_data(server, server_slot,
this,
nullptr);
1754void QDBusConnectionPrivate::setPeer(DBusConnection *c,
const QDBusErrorInternal &error)
1764 q_dbus_connection_set_exit_on_disconnect(connection,
false);
1765 q_dbus_connection_set_watch_functions(connection,
1770 q_dbus_connection_set_timeout_functions(connection,
1775 q_dbus_connection_set_dispatch_status_function(connection, qDBusUpdateDispatchStatus,
this,
nullptr);
1776 q_dbus_connection_add_filter(connection,
1780 watchForDBusDisconnection();
1782 QMetaObject::invokeMethod(
this, &QDBusConnectionPrivate::doDispatch, Qt::QueuedConnection);
1787 QDBusConnection::ConnectionCapabilities result;
1788 typedef dbus_bool_t (*can_send_type_t)(DBusConnection *,
int);
1789 static can_send_type_t can_send_type =
nullptr;
1791#if defined(QT_LINKED_LIBDBUS)
1792# if DBUS_VERSION-0
>= 0x010400
1793 can_send_type = dbus_connection_can_send_type;
1795#elif QT_CONFIG(library)
1797 can_send_type = (can_send_type_t)qdbus_resolve_conditionally(
"dbus_connection_can_send_type");
1801# define DBUS_TYPE_UNIX_FD int('h')
1804 result |= QDBusConnection::UnixFileDescriptorPassing;
1809void QDBusConnectionPrivate::handleAuthentication()
1811 capabilities.storeRelaxed(::connectionCapabilities(connection));
1812 isAuthenticated =
true;
1815void QDBusConnectionPrivate::setConnection(DBusConnection *dbc,
const QDBusErrorInternal &error)
1825 const char *service = q_dbus_bus_get_unique_name(connection);
1827 baseService = QString::fromUtf8(service);
1829 handleAuthentication();
1831 q_dbus_connection_set_exit_on_disconnect(connection,
false);
1832 q_dbus_connection_set_watch_functions(connection, qDBusAddWatch, qDBusRemoveWatch,
1833 qDBusToggleWatch,
this,
nullptr);
1834 q_dbus_connection_set_timeout_functions(connection, qDBusAddTimeout, qDBusRemoveTimeout,
1835 qDBusToggleTimeout,
this,
nullptr);
1836 q_dbus_connection_set_dispatch_status_function(connection, qDBusUpdateDispatchStatus,
this,
nullptr);
1837 q_dbus_connection_add_filter(connection, qDBusSignalFilter,
this,
nullptr);
1843 hook.service = QDBusUtil::dbusService();
1846 hook.params << QMetaType(QMetaType::Void) << QMetaType(QMetaType::QString);
1848 hook.midx = staticMetaObject.indexOfSlot(
"registerServiceNoLock(QString)");
1849 Q_ASSERT(hook.midx != -1);
1852 hook.midx = staticMetaObject.indexOfSlot(
"unregisterServiceNoLock(QString)");
1853 Q_ASSERT(hook.midx != -1);
1858 hook.params.clear();
1859 hook.params.reserve(4);
1860 hook.params << QMetaType(QMetaType::Void) << QMetaType(QMetaType::QString) << QMetaType(QMetaType::QString) << QMetaType(QMetaType::QString);
1861 hook.midx = staticMetaObject.indexOfSlot(
"serviceOwnerChangedNoLock(QString,QString,QString)");
1862 Q_ASSERT(hook.midx != -1);
1865 watchForDBusDisconnection();
1867 qDBusDebug() <<
this <<
": connected successfully";
1870 QMetaObject::invokeMethod(
this, &QDBusConnectionPrivate::doDispatch, Qt::QueuedConnection);
1878 QDBusConnectionPrivate::processFinishedCall(call);
1882void QDBusConnectionPrivate::processFinishedCall(QDBusPendingCallPrivate *call)
1884 QDBusConnectionPrivate *connection =
const_cast<QDBusConnectionPrivate *>(call->connection);
1886 auto locker = qt_unique_lock(call->mutex);
1888 connection->pendingCalls.removeOne(call);
1890 QDBusMessage &msg = call->replyMessage;
1891 if (call->pending) {
1894 if (q_dbus_pending_call_get_completed(call->pending)) {
1896 DBusMessage *reply = q_dbus_pending_call_steal_reply(call->pending);
1897 msg = QDBusMessagePrivate::fromDBusMessage(reply, connection->connectionCapabilities());
1898 q_dbus_message_unref(reply);
1900 msg = QDBusMessage::createError(QDBusError::Disconnected, QDBusUtil::disconnectedErrorMessage());
1903 qDBusDebug() << connection <<
"got message reply:" << msg;
1906 call->checkReceivedSignature();
1908 if (!call->receiver.isNull() && call->methodIdx != -1 && msg.type() == QDBusMessage::ReplyMessage) {
1917 QDBusCallDeliveryEvent *e = prepareReply(connection, call->receiver, call->methodIdx,
1918 call->metaTypes, msg);
1920 connection->postEventToThread(MessageResultReceivedAction, call->receiver, e);
1925 if (call->pending) {
1926 q_dbus_pending_call_unref(call->pending);
1927 call->pending =
nullptr;
1931 if (call->watcherHelper)
1932 call->watcherHelper->emitSignals(msg, call->sentMessage);
1934 call->waitForFinishedCondition.wakeAll();
1937 if (msg.type() == QDBusMessage::ErrorMessage)
1938 emit connection->callWithCallbackFailed(QDBusError(msg), call->sentMessage);
1940 if (!call->ref.deref())
1944bool QDBusConnectionPrivate::send(
const QDBusMessage& message)
1946 if (QDBusMessagePrivate::isLocal(message))
1952 QDBusMessagePrivate::toDBusMessage(message, connectionCapabilities(), &error);
1954 if (message.type() == QDBusMessage::MethodCallMessage)
1956 "QDBusConnection: error: could not send message to service \"%s\" path "
1957 "\"%s\" interface \"%s\" member \"%s\": %s",
1961 else if (message.type() == QDBusMessage::SignalMessage)
1963 "QDBusConnection: error: could not send signal to service \"%s\" path \"%s\" "
1964 "interface \"%s\" member \"%s\": %s",
1970 "QDBusConnection: error: could not send %s message to service \"%s\": %s",
1971 message.type() == QDBusMessage::ReplyMessage ?
"reply"
1972 : message.type() == QDBusMessage::ErrorMessage ?
"error"
1979 q_dbus_message_set_no_reply(msg,
true);
1980 qDBusDebug() <<
this <<
"sending message (no reply):" << message;
1981 emit messageNeedsSending(
nullptr, msg);
1997#if defined(QT_NO_DEBUG)
2015 env =
qgetenv(
"Q_DBUS_BLOCKING_CALL_MAIN_THREAD_WARNING_MS");
2023 "QDBusBlockingCallWatcher: Q_DBUS_BLOCKING_CALL_MAIN_THREAD_WARNING_MS "
2024 "must be an integer; value ignored");
2027 env =
qgetenv(
"Q_DBUS_BLOCKING_CALL_OTHER_THREAD_WARNING_MS");
2034 "QDBusBlockingCallWatcher: "
2035 "Q_DBUS_BLOCKING_CALL_OTHER_THREAD_WARNING_MS must be an integer; "
2057 if (m_maxCallTimeoutMs < 0)
2060 if (m_callTimer.elapsed() >= m_maxCallTimeoutMs) {
2063 "QDBusConnection: warning: blocking call took a long time (%d ms, max for this "
2064 "thread is %d ms) to service \"%s\" path \"%s\" interface \"%s\" member \"%s\"",
2065 int(m_callTimer.elapsed()), m_maxCallTimeoutMs,
qPrintable(m_message.service()),
2072 QDBusMessage m_message;
2073 int m_maxCallTimeoutMs;
2074 QElapsedTimer m_callTimer;
2077QDBusMessage QDBusConnectionPrivate::sendWithReply(
const QDBusMessage &message,
2078 QDBus::CallMode mode,
int timeout)
2080 QDBusBlockingCallWatcher watcher(message);
2082 QDBusPendingCallPrivate *pcall = sendWithReplyAsync(message,
nullptr,
nullptr,
nullptr, timeout);
2085 if (mode == QDBus::BlockWithGui)
2086 pcall->waitForFinishedWithGui();
2088 pcall->waitForFinished();
2090 QDBusMessage reply = pcall->replyMessage;
2091 lastError = QDBusError(reply);
2093 if (!pcall->ref.deref())
2098QDBusMessage QDBusConnectionPrivate::sendWithReplyLocal(
const QDBusMessage &message)
2100 qDBusDebug() <<
this <<
"sending message via local-loop:" << message;
2102 QDBusMessage localCallMsg = QDBusMessagePrivate::makeLocal(*
this, message);
2103 bool handled = handleMessage(localCallMsg);
2106 QString interface = message.interface();
2107 if (interface.isEmpty())
2108 interface =
"<no-interface>"_L1;
2109 return QDBusMessage::createError(QDBusError::InternalError,
2110 "Internal error trying to call %1.%2 at %3 (signature '%4'"_L1
2111 .arg(interface, message.member(),
2112 message.path(), message.signature()));
2116 QDBusMessage localReplyMsg = QDBusMessagePrivate::makeLocalReply(*
this, localCallMsg);
2117 if (localReplyMsg.type() == QDBusMessage::InvalidMessage) {
2120 "QDBusConnection: cannot call local method '%s' at object %s (with signature '%s') "
2124 return QDBusMessage::createError(
2125 QDBusError(QDBusError::InternalError,
2126 "local-loop message cannot have delayed replies"_L1));
2130 qDBusDebug() <<
this <<
"got message via local-loop:" << localReplyMsg;
2131 return localReplyMsg;
2134QDBusPendingCallPrivate *QDBusConnectionPrivate::sendWithReplyAsync(
const QDBusMessage &message,
2135 QObject *receiver,
const char *returnMethod,
2136 const char *errorMethod,
int timeout)
2138 QDBusPendingCallPrivate *pcall =
new QDBusPendingCallPrivate(message,
this);
2140 if ((isLoopback = isServiceRegisteredByThread(message.service()))) {
2142 pcall->replyMessage = sendWithReplyLocal(message);
2145 if (receiver && returnMethod)
2146 pcall->setReplyCallback(receiver, returnMethod);
2149 Q_ASSERT(!pcall->watcherHelper);
2150 pcall->watcherHelper =
new QDBusPendingCallWatcherHelper;
2151 connect(pcall->watcherHelper, SIGNAL(error(QDBusError,QDBusMessage)), receiver, errorMethod,
2152 Qt::QueuedConnection);
2153 pcall->watcherHelper->moveToThread(thread());
2156 if ((receiver && returnMethod) || errorMethod) {
2158 pcall->ref.storeRelaxed(1);
2162 pcall->ref.storeRelaxed(2);
2167 processFinishedCall(pcall);
2173 QDBusMessagePrivate::toDBusMessage(message, connectionCapabilities(), &error);
2176 "QDBusConnection: error: could not send message to service \"%s\" path \"%s\" "
2177 "interface \"%s\" member \"%s\": %s",
2181 pcall->replyMessage = QDBusMessage::createError(error);
2183 processFinishedCall(pcall);
2185 qDBusDebug() <<
this <<
"sending message:" << message;
2186 emit messageNeedsSending(pcall, msg, timeout);
2191void QDBusConnectionPrivate::sendInternal(QDBusPendingCallPrivate *pcall,
void *message,
int timeout)
2194 DBusPendingCall *pending =
nullptr;
2195 DBusMessage *msg =
static_cast<DBusMessage *>(message);
2196 bool isNoReply = !pcall;
2197 Q_ASSERT(isNoReply == !!q_dbus_message_get_no_reply(msg));
2201 if (isNoReply && q_dbus_connection_send(connection, msg,
nullptr)) {
2203 }
else if (!isNoReply && q_dbus_connection_send_with_reply(connection, msg, &pending, timeout)) {
2205 q_dbus_message_unref(msg);
2207 pcall->pending = pending;
2208 q_dbus_pending_call_set_notify(pending, qDBusResultReceived, pcall,
nullptr);
2211 if (mode == QDBusConnectionPrivate::PeerMode || mode == QDBusConnectionPrivate::ClientMode)
2212 pendingCalls.append(pcall);
2217 lastError = error = QDBusError(QDBusError::Disconnected, QDBusUtil::disconnectedErrorMessage());
2220 lastError = error = QDBusError(QDBusError::NoMemory,
QStringLiteral(
"Out of memory"));
2223 q_dbus_message_unref(msg);
2225 pcall->replyMessage = QDBusMessage::createError(error);
2226 processFinishedCall(pcall);
2231bool QDBusConnectionPrivate::connectSignal(
const QString &service,
2232 const QString &path,
const QString &interface,
const QString &name,
2233 const QStringList &argumentMatch,
const QString &signature,
2234 QObject *receiver,
const char *slot)
2236 ArgMatchRules rules;
2237 rules.args = argumentMatch;
2238 return connectSignal(service, path, interface, name, rules, signature, receiver, slot);
2241bool QDBusConnectionPrivate::connectSignal(
const QString &service,
2242 const QString &path,
const QString &interface,
const QString &name,
2243 const ArgMatchRules &argumentMatch,
const QString &signature,
2244 QObject *receiver,
const char *slot)
2247 QDBusConnectionPrivate::SignalHook hook;
2250 hook.signature = signature;
2252 if (!prepareHook(hook, key, service, path, interface, name, argumentMatch, receiver, slot, 0,
2255 <<
"Could not connect" << interface <<
"to" << slot + 1 <<
":" <<
qPrintable(errorMsg);
2259 Q_ASSERT(thread() != QThread::currentThread());
2260 return addSignalHook(key, hook);
2263bool QDBusConnectionPrivate::addSignalHook(
const QString &key,
const SignalHook &hook)
2265 bool result =
false;
2267 QMetaObject::invokeMethod(
this, &QDBusConnectionPrivate::addSignalHookImpl,
2268 Qt::BlockingQueuedConnection, qReturnArg(result), key, hook);
2273bool QDBusConnectionPrivate::addSignalHookImpl(
const QString &key,
const SignalHook &hook)
2275 QDBusWriteLocker locker(ConnectAction,
this);
2278 QDBusConnectionPrivate::SignalHookHash::ConstIterator it = signalHooks.constFind(key);
2279 QDBusConnectionPrivate::SignalHookHash::ConstIterator end = signalHooks.constEnd();
2280 for ( ; it != end && it.key() == key; ++it) {
2281 const QDBusConnectionPrivate::SignalHook &entry = it.value();
2282 if (entry.service == hook.service &&
2283 entry.path == hook.path &&
2284 entry.signature == hook.signature &&
2285 entry.obj == hook.obj &&
2286 entry.midx == hook.midx &&
2287 entry.argumentMatch == hook.argumentMatch) {
2293 signalHooks.insert(key, hook);
2294 connect(hook.obj, &QObject::destroyed,
this, &QDBusConnectionPrivate::objectDestroyed,
2295 Qt::ConnectionType(Qt::BlockingQueuedConnection | Qt::UniqueConnection));
2297 MatchRefCountHash::iterator mit = matchRefCounts.find(hook.matchRule);
2299 if (mit != matchRefCounts.end()) {
2300 mit.value() = mit.value() + 1;
2304 matchRefCounts.insert(hook.matchRule, 1);
2307 if (mode != QDBusConnectionPrivate::PeerMode) {
2308 qDBusDebug() <<
this <<
"Adding rule:" << hook.matchRule;
2309 q_dbus_bus_add_match(connection, hook.matchRule,
nullptr);
2313 if (shouldWatchService(hook.service)) {
2314 WatchedServicesHash::mapped_type &data = watchedServices[hook.service];
2315 if (++data.refcount == 1) {
2317 ArgMatchRules rules;
2318 rules.args << hook.service;
2319 q_dbus_bus_add_match(connection,
2320 buildMatchRule(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(),
2321 QDBusUtil::nameOwnerChanged(), rules, QString()),
2323 data.owner = getNameOwnerNoCache(hook.service);
2324 qDBusDebug() <<
this <<
"Watching service" << hook.service <<
"for owner changes (current owner:"
2325 << data.owner <<
")";
2333bool QDBusConnectionPrivate::disconnectSignal(
const QString &service,
2334 const QString &path,
const QString &interface,
const QString &name,
2335 const QStringList &argumentMatch,
const QString &signature,
2336 QObject *receiver,
const char *slot)
2338 ArgMatchRules rules;
2339 rules.args = argumentMatch;
2340 return disconnectSignal(service, path, interface, name, rules, signature, receiver, slot);
2343bool QDBusConnectionPrivate::disconnectSignal(
const QString &service,
2344 const QString &path,
const QString &interface,
const QString &name,
2345 const ArgMatchRules &argumentMatch,
const QString &signature,
2346 QObject *receiver,
const char *slot)
2349 QDBusConnectionPrivate::SignalHook hook;
2351 QString name2 = name;
2355 hook.signature = signature;
2357 if (!prepareHook(hook, key, service, path, interface, name, argumentMatch, receiver, slot, 0,
2360 <<
"Could not disconnect" << interface <<
"to" << slot + 1 <<
":" <<
qPrintable(errorMsg);
2364 Q_ASSERT(thread() != QThread::currentThread());
2365 return removeSignalHook(key, hook);
2368bool QDBusConnectionPrivate::removeSignalHook(
const QString &key,
const SignalHook &hook)
2370 bool result =
false;
2372 QMetaObject::invokeMethod(
this, &QDBusConnectionPrivate::removeSignalHookImpl,
2373 Qt::BlockingQueuedConnection, qReturnArg(result), key, hook);
2378bool QDBusConnectionPrivate::removeSignalHookImpl(
const QString &key,
const SignalHook &hook)
2381 QDBusWriteLocker locker(ConnectAction,
this);
2382 QDBusConnectionPrivate::SignalHookHash::Iterator it = signalHooks.find(key);
2383 QDBusConnectionPrivate::SignalHookHash::Iterator end = signalHooks.end();
2384 for ( ; it != end && it.key() == key; ++it) {
2385 const QDBusConnectionPrivate::SignalHook &entry = it.value();
2386 if (entry.service == hook.service &&
2387 entry.path == hook.path &&
2388 entry.signature == hook.signature &&
2389 entry.obj == hook.obj &&
2390 entry.midx == hook.midx &&
2391 entry.argumentMatch.args == hook.argumentMatch.args) {
2393 removeSignalHookNoLock(it);
2402QDBusConnectionPrivate::SignalHookHash::Iterator
2403QDBusConnectionPrivate::removeSignalHookNoLock(SignalHookHash::Iterator it)
2405 const SignalHook &hook = it.value();
2408 MatchRefCountHash::iterator i = matchRefCounts.find(hook.matchRule);
2409 if (i == matchRefCounts.end()) {
2411 "QDBusConnectionPrivate::disconnectSignal: MatchRule not found in "
2412 "matchRefCounts!!");
2414 if (i.value() == 1) {
2416 matchRefCounts.erase(i);
2419 i.value() = i.value() - 1;
2424 if (connection && erase) {
2425 if (mode != QDBusConnectionPrivate::PeerMode) {
2426 qDBusDebug() <<
this <<
"Removing rule:" << hook.matchRule;
2427 q_dbus_bus_remove_match(connection, hook.matchRule,
nullptr);
2431 WatchedServicesHash::Iterator sit = watchedServices.find(hook.service);
2432 if (sit != watchedServices.end()) {
2433 if (--sit.value().refcount == 0) {
2434 watchedServices.erase(sit);
2435 ArgMatchRules rules;
2436 rules.args << hook.service;
2437 q_dbus_bus_remove_match(connection,
2438 buildMatchRule(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(),
2439 QDBusUtil::nameOwnerChanged(), rules, QString()),
2447 return signalHooks.erase(it);
2450void QDBusConnectionPrivate::registerObject(
const ObjectTreeNode *node)
2452 connect(node->obj, &QObject::destroyed,
this, &QDBusConnectionPrivate::objectDestroyed,
2453 Qt::ConnectionType(Qt::BlockingQueuedConnection | Qt::UniqueConnection));
2455 if (node->flags & (QDBusConnection::ExportAdaptors
2456 | QDBusConnection::ExportScriptableSignals
2457 | QDBusConnection::ExportNonScriptableSignals)) {
2458 QDBusAdaptorConnector *connector = qDBusCreateAdaptorConnector(node->obj);
2460 if (node->flags & (QDBusConnection::ExportScriptableSignals
2461 | QDBusConnection::ExportNonScriptableSignals)) {
2462 connector->disconnectAllSignals(node->obj);
2463 connector->connectAllSignals(node->obj);
2466 connect(connector, &QDBusAdaptorConnector::relaySignal,
this,
2467 &QDBusConnectionPrivate::relaySignal,
2468 Qt::ConnectionType(Qt::QueuedConnection | Qt::UniqueConnection));
2472void QDBusConnectionPrivate::unregisterObject(
const QString &path, QDBusConnection::UnregisterMode mode)
2474 QDBusConnectionPrivate::ObjectTreeNode *node = &rootNode;
2475 QList<QStringView> pathComponents;
2477 if (path ==
"/"_L1) {
2480 pathComponents = QStringView{path}.split(u'/');
2484 huntAndUnregister(pathComponents, i, mode, node);
2487void QDBusConnectionPrivate::connectRelay(
const QString &service,
2488 const QString &path,
const QString &interface,
2489 QDBusAbstractInterface *receiver,
2490 const QMetaMethod &signal)
2498 sig.append(QSIGNAL_CODE +
'0');
2499 sig.append(signal.methodSignature());
2501 if (!prepareHook(hook, key, service, path, interface, QString(), ArgMatchRules(), receiver, sig,
2502 QDBusAbstractInterface::staticMetaObject.methodCount(),
true, errorMsg)) {
2504 <<
"Could not connect" << interface <<
"to" << signal.name() <<
":" <<
qPrintable(errorMsg);
2508 Q_ASSERT(thread() != QThread::currentThread());
2509 addSignalHook(key, hook);
2512void QDBusConnectionPrivate::disconnectRelay(
const QString &service,
2513 const QString &path,
const QString &interface,
2514 QDBusAbstractInterface *receiver,
2515 const QMetaMethod &signal)
2523 sig.append(QSIGNAL_CODE +
'0');
2524 sig.append(signal.methodSignature());
2526 if (!prepareHook(hook, key, service, path, interface, QString(), ArgMatchRules(), receiver, sig,
2527 QDBusAbstractInterface::staticMetaObject.methodCount(),
true, errorMsg)) {
2528 qCWarning(dbusIntegration) <<
"Could not disconnect" << interface <<
"to"
2529 << signal.methodSignature() <<
":" <<
qPrintable(errorMsg);
2533 Q_ASSERT(thread() != QThread::currentThread());
2534 removeSignalHook(key, hook);
2537bool QDBusConnectionPrivate::shouldWatchService(
const QString &service)
2540 if (mode != ClientMode)
2543 if (service.isEmpty())
2546 if (service == QDBusUtil::dbusService())
2552
2553
2554
2555
2556
2557
2558
2559
2560void QDBusConnectionPrivate::watchService(
const QString &service, QDBusServiceWatcher::WatchMode mode, QObject *obj,
const char *member)
2562 ArgMatchRules matchArgs = matchArgsForService(service, mode);
2563 connectSignal(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(), QDBusUtil::nameOwnerChanged(),
2564 matchArgs, QString(), obj, member);
2568
2569
2570
2571
2572
2573
2574
2575void QDBusConnectionPrivate::unwatchService(
const QString &service, QDBusServiceWatcher::WatchMode mode, QObject *obj,
const char *member)
2577 ArgMatchRules matchArgs = matchArgsForService(service, mode);
2578 disconnectSignal(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(), QDBusUtil::nameOwnerChanged(),
2579 matchArgs, QString(), obj, member);
2582QString QDBusConnectionPrivate::getNameOwner(
const QString& serviceName)
2584 if (QDBusUtil::isValidUniqueConnectionName(serviceName))
2591 QReadLocker locker(&lock);
2592 WatchedServicesHash::ConstIterator it = watchedServices.constFind(serviceName);
2593 if (it != watchedServices.constEnd())
2598 return getNameOwnerNoCache(serviceName);
2601QString QDBusConnectionPrivate::getNameOwnerNoCache(
const QString &serviceName)
2603 QDBusMessage msg = QDBusMessage::createMethodCall(QDBusUtil::dbusService(),
2604 QDBusUtil::dbusPath(), QDBusUtil::dbusInterface(),
2606 QDBusMessagePrivate::setParametersValidated(msg,
true);
2609 QDBusPendingCallPrivate *pcall = sendWithReplyAsync(msg,
nullptr,
nullptr,
nullptr);
2610 if (pcall->replyMessage.type() == QDBusMessage::InvalidMessage) {
2611 if (QThread *thr = thread(); thr && thr->isCurrentThread()) {
2614 q_dbus_pending_call_block(pcall->pending);
2616 pcall->waitForFinished();
2618 msg = pcall->replyMessage;
2620 if (!pcall->ref.deref())
2623 if (msg.type() == QDBusMessage::ReplyMessage)
2624 return msg.arguments().at(0).toString();
2629QDBusConnectionPrivate::findMetaObject(
const QString &service,
const QString &path,
2630 const QString &interface, QDBusError &error)
2633 if (!interface.isEmpty()) {
2634 QDBusReadLocker locker(FindMetaObject1Action,
this);
2635 QDBusMetaObject *mo = cachedMetaObjects.value(interface,
nullptr);
2639 if (path.isEmpty()) {
2640 error = QDBusError(QDBusError::InvalidObjectPath,
"Object path cannot be empty"_L1);
2646 QDBusMessage msg = QDBusMessage::createMethodCall(service, path,
2647 QDBusUtil::dbusInterfaceIntrospectable(),
2649 QDBusMessagePrivate::setParametersValidated(msg,
true);
2651 QDBusMessage reply = sendWithReply(msg, QDBus::Block);
2654 QDBusWriteLocker locker(FindMetaObject2Action,
this);
2655 QDBusMetaObject *mo =
nullptr;
2656 if (!interface.isEmpty())
2657 mo = cachedMetaObjects.value(interface,
nullptr);
2663 if (reply.type() == QDBusMessage::ReplyMessage) {
2664 if (reply.signature() ==
"s"_L1)
2666 xml = reply.arguments().at(0).toString();
2668 error = QDBusError(reply);
2670 if (reply.type() != QDBusMessage::ErrorMessage || error.type() != QDBusError::UnknownMethod)
2675 QDBusMetaObject *result = QDBusMetaObject::createMetaObject(interface, xml,
2676 cachedMetaObjects, error);
2681void QDBusConnectionPrivate::registerService(
const QString &serviceName)
2683 QDBusWriteLocker locker(RegisterServiceAction,
this);
2684 registerServiceNoLock(serviceName);
2687void QDBusConnectionPrivate::registerServiceNoLock(
const QString &serviceName)
2689 serviceNames.append(serviceName);
2692void QDBusConnectionPrivate::unregisterService(
const QString &serviceName)
2694 QDBusWriteLocker locker(UnregisterServiceAction,
this);
2695 unregisterServiceNoLock(serviceName);
2698void QDBusConnectionPrivate::unregisterServiceNoLock(
const QString &serviceName)
2700 serviceNames.removeAll(serviceName);
2703bool QDBusConnectionPrivate::isServiceRegisteredByThread(
const QString &serviceName)
2705 if (!serviceName.isEmpty() && serviceName == baseService)
2707 if (serviceName == QDBusUtil::dbusService())
2710 QDBusReadLocker locker(UnregisterServiceAction,
this);
2711 return serviceNames.contains(serviceName);
2714void QDBusConnectionPrivate::postEventToThread(
int action, QObject *object, QEvent *ev)
2716 QDBusLockerBase::reportThreadAction(action, QDBusLockerBase::BeforePost,
this);
2717 QCoreApplication::postEvent(object, ev);
2718 QDBusLockerBase::reportThreadAction(action, QDBusLockerBase::AfterPost,
this);
2722
2723
2724
2725
2726void QDBusConnectionPrivate::enableDispatchDelayed(QObject *context)
2729 QMetaObject::invokeMethod(
2735 QMetaObject::invokeMethod(
this, &QDBusConnectionPrivate::setDispatchEnabled,
2736 Qt::QueuedConnection,
true);
2740 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 *)