qdbusintegrator.cpp

Switch to Source codePreprocessed file
LineSource CodeCoverage
1 -
2 -
3 -
4 -
5 -
6 -
7 -
8 -
9 -
10 -
11 -
12 -
13static bool isDebugging; -
14 -
15 -
16static const QString *orgFreedesktopDBusString() { static QGlobalStatic<const QString > thisGlobalStatic = { { (0) }, false }; if (!thisGlobalStatic.pointer.load() && !thisGlobalStatic.destroyed) { const QString *x = new const QString (QLatin1String("org.freedesktop.DBus")); if (!thisGlobalStatic.pointer.testAndSetOrdered(0, x)) delete x; else static QGlobalStaticDeleter<const QString > cleanup(thisGlobalStatic); } return thisGlobalStatic.pointer.load(); }
-
17 -
18static inline QString dbusServiceString() -
19{ return *orgFreedesktopDBusString(); }
-
20static inline QString dbusInterfaceString() -
21{ -
22 -
23 qt_noop(); -
24 return *orgFreedesktopDBusString();
-
25} -
26 -
27static inline QDebug operator<<(QDebug dbg, const QThread *th) -
28{ -
29 dbg.nospace() << "QThread(ptr=" << (void*)th; -
30 if (th && !th->objectName().isEmpty())
-
31 dbg.nospace() << ", name=" << th->objectName();
-
32 dbg.nospace() << ')'; -
33 return dbg.space();
-
34} -
35typedef void (*QDBusSpyHook)(const QDBusMessage&); -
36typedef QVarLengthArray<QDBusSpyHook, 4> QDBusSpyHookList; -
37static QDBusSpyHookList *qDBusSpyHookList() { static QGlobalStatic<QDBusSpyHookList > thisGlobalStatic = { { (0) }, false }; if (!thisGlobalStatic.pointer.load() && !thisGlobalStatic.destroyed) { QDBusSpyHookList *x = new QDBusSpyHookList; if (!thisGlobalStatic.pointer.testAndSetOrdered(0, x)) delete x; else static QGlobalStaticDeleter<QDBusSpyHookList > cleanup(thisGlobalStatic); } return thisGlobalStatic.pointer.load(); }
-
38 -
39extern "C" { -
40 -
41 -
42 -
43static bool qDBusRealAddTimeout(QDBusConnectionPrivate *d, DBusTimeout *timeout, int ms); -
44static dbus_bool_t qDBusAddTimeout(DBusTimeout *timeout, void *data) -
45{ -
46 qt_noop(); -
47 qt_noop(); -
48 -
49 -
50 -
51 QDBusConnectionPrivate *d = static_cast<QDBusConnectionPrivate *>(data); -
52 -
53 if (!q_dbus_timeout_get_enabled(timeout))
-
54 return true;
-
55 -
56 QDBusWatchAndTimeoutLocker locker(AddTimeoutAction, d); -
57 if (QCoreApplication::instance() && QThread::currentThread() == d->thread()) {
-
58 -
59 return qDBusRealAddTimeout(d, timeout, q_dbus_timeout_get_interval(timeout));
-
60 } else { -
61 -
62 QDBusConnectionCallbackEvent *ev = new QDBusConnectionCallbackEvent; -
63 ev->subtype = QDBusConnectionCallbackEvent::AddTimeout; -
64 d->timeoutsPendingAdd.append(qMakePair(timeout, q_dbus_timeout_get_interval(timeout))); -
65 d->postEventToThread(AddTimeoutAction, d, ev); -
66 return true;
-
67 } -
68} -
69 -
70static bool qDBusRealAddTimeout(QDBusConnectionPrivate *d, DBusTimeout *timeout, int ms) -
71{ -
72 qt_noop(); -
73 -
74 int timerId = d->startTimer(ms); -
75 if (!timerId)
-
76 return false;
-
77 -
78 d->timeouts[timerId] = timeout; -
79 return true;
-
80} -
81 -
82static void qDBusRemoveTimeout(DBusTimeout *timeout, void *data) -
83{ -
84 qt_noop(); -
85 qt_noop(); -
86 -
87 -
88 -
89 QDBusConnectionPrivate *d = static_cast<QDBusConnectionPrivate *>(data); -
90 -
91 QDBusWatchAndTimeoutLocker locker(RemoveTimeoutAction, d); -
92 -
93 -
94 QDBusConnectionPrivate::PendingTimeoutList::iterator pit = d->timeoutsPendingAdd.begin(); -
95 while (pit != d->timeoutsPendingAdd.end()) {
-
96 if (pit->first == timeout)
-
97 pit = d->timeoutsPendingAdd.erase(pit);
-
98 else -
99 ++pit;
-
100 } -
101 -
102 -
103 bool correctThread = QCoreApplication::instance() && QThread::currentThread() == d->thread();
-
104 QDBusConnectionPrivate::TimeoutHash::iterator it = d->timeouts.begin(); -
105 while (it != d->timeouts.end()) {
-
106 if (it.value() == timeout) {
-
107 if (correctThread) {
-
108 -
109 d->killTimer(it.key()); -
110 } else {
-
111 -
112 QDBusConnectionCallbackEvent *ev = new QDBusConnectionCallbackEvent; -
113 ev->subtype = QDBusConnectionCallbackEvent::KillTimer; -
114 ev->timerId = it.key(); -
115 d->postEventToThread(KillTimerAction, d, ev); -
116 }
-
117 it = d->timeouts.erase(it); -
118 break;
-
119 } else { -
120 ++it; -
121 }
-
122 } -
123}
-
124 -
125static void qDBusToggleTimeout(DBusTimeout *timeout, void *data) -
126{ -
127 qt_noop(); -
128 qt_noop(); -
129 -
130 -
131 -
132 qDBusRemoveTimeout(timeout, data); -
133 qDBusAddTimeout(timeout, data); -
134}
-
135 -
136static bool qDBusRealAddWatch(QDBusConnectionPrivate *d, DBusWatch *watch, int flags, int fd); -
137static dbus_bool_t qDBusAddWatch(DBusWatch *watch, void *data) -
138{ -
139 qt_noop(); -
140 qt_noop(); -
141 -
142 QDBusConnectionPrivate *d = static_cast<QDBusConnectionPrivate *>(data); -
143 -
144 int flags = q_dbus_watch_get_flags(watch); -
145 int fd = q_dbus_watch_get_fd(watch); -
146 -
147 if (QCoreApplication::instance() && QThread::currentThread() == d->thread()) {
-
148 return qDBusRealAddWatch(d, watch, flags, fd);
-
149 } else { -
150 QDBusConnectionCallbackEvent *ev = new QDBusConnectionCallbackEvent; -
151 ev->subtype = QDBusConnectionCallbackEvent::AddWatch; -
152 ev->watch = watch; -
153 ev->fd = fd; -
154 ev->extra = flags; -
155 d->postEventToThread(AddWatchAction, d, ev); -
156 return true;
-
157 } -
158} -
159 -
160static bool qDBusRealAddWatch(QDBusConnectionPrivate *d, DBusWatch *watch, int flags, int fd) -
161{ -
162 QDBusConnectionPrivate::Watcher watcher; -
163 -
164 QDBusWatchAndTimeoutLocker locker(AddWatchAction, d); -
165 if (flags & DBUS_WATCH_READABLE) {
-
166 -
167 watcher.watch = watch; -
168 if (QCoreApplication::instance()) {
-
169 watcher.read = new QSocketNotifier(fd, QSocketNotifier::Read, d); -
170 watcher.read->setEnabled(q_dbus_watch_get_enabled(watch)); -
171 d->connect(watcher.read, "2""activated(int)", "1""socketRead(int)"); -
172 }
-
173 }
-
174 if (flags & DBUS_WATCH_WRITABLE) {
-
175 -
176 watcher.watch = watch; -
177 if (QCoreApplication::instance()) {
-
178 watcher.write = new QSocketNotifier(fd, QSocketNotifier::Write, d); -
179 watcher.write->setEnabled(q_dbus_watch_get_enabled(watch)); -
180 d->connect(watcher.write, "2""activated(int)", "1""socketWrite(int)"); -
181 }
-
182 }
-
183 d->watchers.insertMulti(fd, watcher); -
184 -
185 return true;
-
186} -
187 -
188static void qDBusRemoveWatch(DBusWatch *watch, void *data) -
189{ -
190 qt_noop(); -
191 qt_noop(); -
192 -
193 -
194 -
195 QDBusConnectionPrivate *d = static_cast<QDBusConnectionPrivate *>(data); -
196 int fd = q_dbus_watch_get_fd(watch); -
197 -
198 QDBusWatchAndTimeoutLocker locker(RemoveWatchAction, d); -
199 QDBusConnectionPrivate::WatcherHash::iterator i = d->watchers.find(fd); -
200 while (i != d->watchers.end() && i.key() == fd) {
-
201 if (i.value().watch == watch) {
-
202 if (QCoreApplication::instance() && QThread::currentThread() == d->thread()) {
-
203 -
204 delete i.value().read; -
205 delete i.value().write; -
206 } else {
-
207 -
208 if (i->read)
-
209 i->read->deleteLater();
-
210 if (i->write)
-
211 i->write->deleteLater();
-
212 }
-
213 i = d->watchers.erase(i); -
214 } else {
-
215 ++i; -
216 }
-
217 } -
218}
-
219 -
220static void qDBusRealToggleWatch(QDBusConnectionPrivate *d, DBusWatch *watch, int fd); -
221static void qDBusToggleWatch(DBusWatch *watch, void *data) -
222{ -
223 qt_noop(); -
224 qt_noop(); -
225 -
226 QDBusConnectionPrivate *d = static_cast<QDBusConnectionPrivate *>(data); -
227 int fd = q_dbus_watch_get_fd(watch); -
228 -
229 if (QCoreApplication::instance() && QThread::currentThread() == d->thread()) {
-
230 qDBusRealToggleWatch(d, watch, fd); -
231 } else {
-
232 QDBusConnectionCallbackEvent *ev = new QDBusConnectionCallbackEvent; -
233 ev->subtype = QDBusConnectionCallbackEvent::ToggleWatch; -
234 ev->watch = watch; -
235 ev->fd = fd; -
236 d->postEventToThread(ToggleWatchAction, d, ev); -
237 }
-
238} -
239 -
240static void qDBusRealToggleWatch(QDBusConnectionPrivate *d, DBusWatch *watch, int fd) -
241{ -
242 QDBusWatchAndTimeoutLocker locker(ToggleWatchAction, d); -
243 -
244 QDBusConnectionPrivate::WatcherHash::iterator i = d->watchers.find(fd); -
245 while (i != d->watchers.end() && i.key() == fd) {
-
246 if (i.value().watch == watch) {
-
247 bool enabled = q_dbus_watch_get_enabled(watch); -
248 int flags = q_dbus_watch_get_flags(watch); -
249 -
250 -
251 -
252 if (flags & DBUS_WATCH_READABLE && i.value().read)
-
253 i.value().read->setEnabled(enabled);
-
254 if (flags & DBUS_WATCH_WRITABLE && i.value().write)
-
255 i.value().write->setEnabled(enabled);
-
256 return;
-
257 } -
258 ++i; -
259 }
-
260}
-
261 -
262static void qDBusUpdateDispatchStatus(DBusConnection *connection, DBusDispatchStatus new_status, void *data) -
263{ -
264 qt_noop(); -
265 (void)connection;; -
266 QDBusConnectionPrivate *d = static_cast<QDBusConnectionPrivate *>(data); -
267 -
268 static int slotId; -
269 if (!slotId) {
-
270 -
271 -
272 slotId = QDBusConnectionPrivate::staticMetaObject.indexOfSlot("doDispatch()"); -
273 }
-
274 -
275 -
276 if (new_status == DBUS_DISPATCH_DATA_REMAINS)
-
277 QDBusConnectionPrivate::staticMetaObject.method(slotId). -
278 invoke(d, Qt::QueuedConnection);
-
279}
-
280 -
281static void qDBusNewConnection(DBusServer *server, DBusConnection *connection, void *data) -
282{ -
283 -
284 qt_noop(); (void)server;; -
285 qt_noop(); -
286 qt_noop(); -
287 -
288 -
289 q_dbus_connection_ref(connection); -
290 QDBusConnectionPrivate *serverConnection = static_cast<QDBusConnectionPrivate *>(data); -
291 -
292 QDBusConnectionPrivate *newConnection = new QDBusConnectionPrivate(serverConnection->parent()); -
293 QMutexLocker locker(&QDBusConnectionManager::instance()->mutex); -
294 QDBusConnectionManager::instance()->setConnection(QLatin1String("QDBusServer-") + QString::number(reinterpret_cast<qulonglong>(newConnection)), newConnection); -
295 serverConnection->serverConnectionNames << newConnection->name; -
296 -
297 -
298 QDBusErrorInternal error; -
299 newConnection->setPeer(connection, error); -
300 -
301 QDBusConnection retval = QDBusConnectionPrivate::q(newConnection); -
302 -
303 -
304 serverConnection->serverConnection(retval); -
305}
-
306 -
307} -
308 -
309static QByteArray buildMatchRule(const QString &service, -
310 const QString &objectPath, const QString &interface, -
311 const QString &member, const QStringList &argMatch, const QString & ) -
312{ -
313 QString result = QLatin1String("type='signal',"); -
314 QString keyValue = QLatin1String("%1='%2',"); -
315 -
316 if (!service.isEmpty())
-
317 result += keyValue.arg(QLatin1String("sender"), service);
-
318 if (!objectPath.isEmpty())
-
319 result += keyValue.arg(QLatin1String("path"), objectPath);
-
320 if (!interface.isEmpty())
-
321 result += keyValue.arg(QLatin1String("interface"), interface);
-
322 if (!member.isEmpty())
-
323 result += keyValue.arg(QLatin1String("member"), member);
-
324 -
325 -
326 if (!argMatch.isEmpty()) {
-
327 keyValue = QLatin1String("arg%1='%2',"); -
328 for (int i = 0; i < argMatch.count(); ++i)
-
329 if (!argMatch.at(i).isNull())
-
330 result += keyValue.arg(i).arg(argMatch.at(i));
-
331 }
-
332 -
333 result.chop(1); -
334 return result.toLatin1();
-
335} -
336 -
337static bool findObject(const QDBusConnectionPrivate::ObjectTreeNode *root, -
338 const QString &fullpath, int &usedLength, -
339 QDBusConnectionPrivate::ObjectTreeNode &result) -
340{ -
341 if (!fullpath.compare(QLatin1String("/")) && root->obj) {
-
342 usedLength = 1; -
343 result = *root; -
344 return root;
-
345 } -
346 int start = 0; -
347 int length = fullpath.length(); -
348 if (fullpath.at(0) == QLatin1Char('/'))
-
349 start = 1;
-
350 -
351 -
352 QDBusConnectionPrivate::ObjectTreeNode::DataList::ConstIterator node = root; -
353 while (start < length && node) {
-
354 if (node->flags & QDBusConnection::ExportChildObjects)
-
355 break;
-
356 if ((node->flags & QDBusConnectionPrivate::VirtualObject) && (node->flags & QDBusConnection::SubPath))
-
357 break;
-
358 int end = fullpath.indexOf(QLatin1Char('/'), start); -
359 end = (end == -1 ? length : end);
-
360 QStringRef pathComponent(&fullpath, start, end - start); -
361 -
362 QDBusConnectionPrivate::ObjectTreeNode::DataList::ConstIterator it = -
363 std::lower_bound(node->children.constBegin(), node->children.constEnd(), pathComponent); -
364 if (it != node->children.constEnd() && it->name == pathComponent)
-
365 -
366 node = it;
-
367 else -
368 node = 0;
-
369 -
370 start = end + 1; -
371 }
-
372 -
373 -
374 usedLength = (start > length ? length : start);
-
375 if (node) {
-
376 if (node->obj || !node->children.isEmpty())
-
377 result = *node;
-
378 else -
379 -
380 -
381 node = 0;
-
382 } -
383 return node;
-
384} -
385 -
386static QObject *findChildObject(const QDBusConnectionPrivate::ObjectTreeNode *root, -
387 const QString &fullpath, int start) -
388{ -
389 int length = fullpath.length(); -
390 -
391 -
392 const QDBusConnectionPrivate::ObjectTreeNode *node = root; -
393 if (node && node->flags & QDBusConnection::ExportChildObjects) {
-
394 QObject *obj = node->obj; -
395 -
396 while (obj) {
-
397 if (start >= length)
-
398 -
399 return obj;
-
400 -
401 int pos = fullpath.indexOf(QLatin1Char('/'), start); -
402 pos = (pos == -1 ? length : pos);
-
403 QStringRef pathComponent(&fullpath, start, pos - start); -
404 -
405 const QObjectList children = obj->children(); -
406 -
407 -
408 QObject *next = 0; -
409 QObjectList::ConstIterator it = children.constBegin(); -
410 QObjectList::ConstIterator end = children.constEnd(); -
411 for ( ; it != end; ++it)
-
412 if ((*it)->objectName() == pathComponent) {
-
413 next = *it; -
414 break;
-
415 } -
416 -
417 if (!next)
-
418 break;
-
419 -
420 obj = next; -
421 start = pos + 1; -
422 }
-
423 }
-
424 -
425 -
426 return 0;
-
427} -
428 -
429static bool shouldWatchService(const QString &service) -
430{ -
431 return !service.isEmpty() && !service.startsWith(QLatin1Char(':'));
-
432} -
433 -
434extern __attribute__((visibility("default"))) void qDBusAddSpyHook(QDBusSpyHook); -
435void qDBusAddSpyHook(QDBusSpyHook hook) -
436{ -
437 qDBusSpyHookList()->append(hook); -
438}
-
439 -
440extern "C" { -
441static DBusHandlerResult -
442qDBusSignalFilter(DBusConnection *connection, DBusMessage *message, void *data) -
443{ -
444 qt_noop(); -
445 (void)connection;; -
446 QDBusConnectionPrivate *d = static_cast<QDBusConnectionPrivate *>(data); -
447 if (d->mode == QDBusConnectionPrivate::InvalidMode)
-
448 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-
449 -
450 QDBusMessage amsg = QDBusMessagePrivate::fromDBusMessage(message, d->capabilities); -
451 if (!::isDebugging); else QMessageLogger("qdbusintegrator.cpp", 553, __PRETTY_FUNCTION__).debug() << d << "got message (signal):" << amsg;
-
452 -
453 return d->handleMessage(amsg) ? -
454 DBUS_HANDLER_RESULT_HANDLED : -
455 DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-
456} -
457} -
458 -
459bool QDBusConnectionPrivate::handleMessage(const QDBusMessage &amsg) -
460{ -
461 const QDBusSpyHookList *list = qDBusSpyHookList(); -
462 for (int i = 0; i < list->size(); ++i) {
-
463 if (!::isDebugging); else QMessageLogger("qdbusintegrator.cpp", 565, __PRETTY_FUNCTION__).debug() << "calling the message spy hook";
-
464 (*(*list)[i])(amsg); -
465 }
-
466 -
467 if (!ref.load())
-
468 return false;
-
469 -
470 switch (amsg.type()) { -
471 case QDBusMessage::SignalMessage: -
472 handleSignal(amsg); -
473 -
474 -
475 return false;
-
476 case QDBusMessage::MethodCallMessage: -
477 handleObjectCall(amsg); -
478 return true;
-
479 case QDBusMessage::ReplyMessage: -
480 case QDBusMessage::ErrorMessage: -
481 case QDBusMessage::InvalidMessage: -
482 return false;
-
483 } -
484 -
485 return false;
-
486} -
487 -
488static void huntAndDestroy(QObject *needle, QDBusConnectionPrivate::ObjectTreeNode &haystack) -
489{ -
490 QDBusConnectionPrivate::ObjectTreeNode::DataList::Iterator it = haystack.children.begin(); -
491 QDBusConnectionPrivate::ObjectTreeNode::DataList::Iterator end = haystack.children.end(); -
492 for ( ; it != end; ++it)
-
493 huntAndDestroy(needle, *it);
-
494 -
495 if (needle == haystack.obj) {
-
496 haystack.obj = 0; -
497 haystack.flags = 0; -
498 }
-
499}
-
500 -
501static void huntAndEmit(DBusConnection *connection, DBusMessage *msg, -
502 QObject *needle, const QDBusConnectionPrivate::ObjectTreeNode &haystack, -
503 bool isScriptable, bool isAdaptor, const QString &path = QString()) -
504{ -
505 QDBusConnectionPrivate::ObjectTreeNode::DataList::ConstIterator it = haystack.children.constBegin(); -
506 QDBusConnectionPrivate::ObjectTreeNode::DataList::ConstIterator end = haystack.children.constEnd(); -
507 for ( ; it != end; ++it)
-
508 huntAndEmit(connection, msg, needle, *it, isScriptable, isAdaptor, path + QLatin1Char('/') + it->name);
-
509 -
510 if (needle == haystack.obj) {
-
511 -
512 if (isAdaptor && (haystack.flags & QDBusConnection::ExportAdaptors) == 0)
-
513 return;
-
514 else if (!isAdaptor) {
-
515 int mask = isScriptable
-
516 ? QDBusConnection::ExportScriptableSignals -
517 : QDBusConnection::ExportNonScriptableSignals; -
518 if ((haystack.flags & mask) == 0)
-
519 return;
-
520 }
-
521 -
522 QByteArray p = path.toLatin1(); -
523 if (p.isEmpty())
-
524 p = "/";
-
525 if (!::isDebugging); else QMessageLogger("qdbusintegrator.cpp", 627, __PRETTY_FUNCTION__).debug() << QThread::currentThread() << "emitting signal at" << p;
-
526 DBusMessage *msg2 = q_dbus_message_copy(msg); -
527 q_dbus_message_set_path(msg2, p); -
528 q_dbus_connection_send(connection, msg2, 0); -
529 q_dbus_message_unref(msg2); -
530 }
-
531}
-
532 -
533static int findSlot(const QMetaObject *mo, const QByteArray &name, int flags, -
534 const QString &signature_, QVector<int> &metaTypes) -
535{ -
536 QByteArray msgSignature = signature_.toLatin1(); -
537 -
538 for (int idx = mo->methodCount() - 1 ; idx >= QObject::staticMetaObject.methodCount(); --idx) {
-
539 QMetaMethod mm = mo->method(idx); -
540 -
541 -
542 if (mm.access() != QMetaMethod::Public)
-
543 continue;
-
544 -
545 -
546 if (mm.methodType() != QMetaMethod::Slot && mm.methodType() != QMetaMethod::Method)
-
547 continue;
-
548 -
549 -
550 if (mm.name() != name)
-
551 continue;
-
552 -
553 int returnType = mm.returnType(); -
554 bool isAsync = qDBusCheckAsyncTag(mm.tag()); -
555 bool isScriptable = mm.attributes() & QMetaMethod::Scriptable; -
556 -
557 -
558 if (isAsync && returnType != QMetaType::Void)
-
559 continue;
-
560 -
561 int inputCount = qDBusParametersForMethod(mm, metaTypes); -
562 if (inputCount == -1)
-
563 continue;
-
564 -
565 metaTypes[0] = returnType; -
566 bool hasMessage = false; -
567 if (inputCount > 0 &&
-
568 metaTypes.at(inputCount) == QDBusMetaTypeId::message()) {
-
569 -
570 hasMessage = true; -
571 --inputCount; -
572 }
-
573 -
574 -
575 int i; -
576 QByteArray reconstructedSignature; -
577 for (i = 1; i <= inputCount; ++i) {
-
578 const char *typeSignature = QDBusMetaType::typeToSignature( metaTypes.at(i) ); -
579 if (!typeSignature)
-
580 break;
-
581 -
582 reconstructedSignature += typeSignature; -
583 if (!msgSignature.startsWith(reconstructedSignature))
-
584 break;
-
585 }
-
586 -
587 if (reconstructedSignature != msgSignature)
-
588 continue;
-
589 -
590 if (hasMessage)
-
591 ++i;
-
592 -
593 -
594 if (returnType != QMetaType::UnknownType && returnType != QMetaType::Void && QDBusMetaType::typeToSignature(returnType) == 0)
-
595 continue;
-
596 -
597 bool ok = true; -
598 for (int j = i; ok && j < metaTypes.count(); ++j)
-
599 if (QDBusMetaType::typeToSignature(metaTypes.at(i)) == 0)
-
600 ok = false;
-
601 if (!ok)
-
602 continue;
-
603 -
604 -
605 if (isAsync && metaTypes.count() > i + 1)
-
606 continue;
-
607 -
608 if (mm.methodType() == QMetaMethod::Slot) {
-
609 if (isScriptable && (flags & QDBusConnection::ExportScriptableSlots) == 0)
-
610 continue;
-
611 if (!isScriptable && (flags & QDBusConnection::ExportNonScriptableSlots) == 0)
-
612 continue;
-
613 } else {
-
614 if (isScriptable && (flags & QDBusConnection::ExportScriptableInvokables) == 0)
-
615 continue;
-
616 if (!isScriptable && (flags & QDBusConnection::ExportNonScriptableInvokables) == 0)
-
617 continue;
-
618 }
-
619 -
620 -
621 return idx;
-
622 } -
623 -
624 -
625 return -1;
-
626} -
627 -
628static QDBusCallDeliveryEvent * const DIRECT_DELIVERY = (QDBusCallDeliveryEvent *)1; -
629 -
630QDBusCallDeliveryEvent* QDBusConnectionPrivate::prepareReply(QDBusConnectionPrivate *target, -
631 QObject *object, int idx, -
632 const QVector<int> &metaTypes, -
633 const QDBusMessage &msg) -
634{ -
635 qt_noop(); -
636 (void)object;; -
637 -
638 int n = metaTypes.count() - 1; -
639 if (metaTypes[n] == QDBusMetaTypeId::message())
-
640 --n;
-
641 -
642 if (msg.arguments().count() < n)
-
643 return 0;
-
644 -
645 -
646 for (int i = 0; i < n; ++i)
-
647 if (metaTypes.at(i + 1) != msg.arguments().at(i).userType() &&
-
648 msg.arguments().at(i).userType() != qMetaTypeId<QDBusArgument>())
-
649 return 0;
-
650 -
651 -
652 -
653 if (target == object)
-
654 return DIRECT_DELIVERY;
-
655 return new QDBusCallDeliveryEvent(QDBusConnection(target), idx, target, msg, metaTypes);
-
656} -
657 -
658void QDBusConnectionPrivate::activateSignal(const QDBusConnectionPrivate::SignalHook& hook, -
659 const QDBusMessage &msg) -
660{ -
661 -
662 -
663 -
664 -
665 -
666 -
667 -
668 QDBusCallDeliveryEvent *call = prepareReply(this, hook.obj, hook.midx, hook.params, msg); -
669 if (call == DIRECT_DELIVERY) {
-
670 -
671 qt_noop(); -
672 deliverCall(this, 0, msg, hook.params, hook.midx); -
673 return;
-
674 } -
675 if (call)
-
676 postEventToThread(ActivateSignalAction, hook.obj, call);
-
677}
-
678 -
679bool QDBusConnectionPrivate::activateCall(QObject* object, int flags, const QDBusMessage &msg) -
680{ -
681 static const char cachePropertyName[] = "_qdbus_slotCache"; -
682 -
683 if (!object)
-
684 return false;
-
685 -
686 -
687 qt_noop(); -
688 -
689 -
690 -
691 QDBusSlotCache slotCache = -
692 qvariant_cast<QDBusSlotCache>(object->property(cachePropertyName)); -
693 QString cacheKey = msg.member(), signature = msg.signature(); -
694 if (!signature.isEmpty()) {
-
695 cacheKey.reserve(cacheKey.length() + 1 + signature.length()); -
696 cacheKey += QLatin1Char('.'); -
697 cacheKey += signature; -
698 }
-
699 -
700 QDBusSlotCache::Hash::ConstIterator cacheIt = slotCache.hash.constFind(cacheKey); -
701 while (cacheIt != slotCache.hash.constEnd() && cacheIt->flags != flags &&
-
702 cacheIt.key() == cacheKey)
-
703 ++cacheIt;
-
704 if (cacheIt == slotCache.hash.constEnd() || cacheIt.key() != cacheKey)
-
705 { -
706 -
707 const QMetaObject *mo = object->metaObject(); -
708 QByteArray memberName = msg.member().toUtf8(); -
709 -
710 -
711 QDBusSlotCache::Data slotData; -
712 slotData.flags = flags; -
713 slotData.slotIdx = ::findSlot(mo, memberName, flags, msg.signature(), slotData.metaTypes); -
714 if (slotData.slotIdx == -1) {
-
715 -
716 -
717 slotData.slotIdx = ::findSlot(mo, memberName, flags, QString(), slotData.metaTypes); -
718 if (slotData.metaTypes.count() != 2 ||
-
719 slotData.metaTypes.at(1) != QDBusMetaTypeId::message()) {
-
720 -
721 -
722 slotData.slotIdx = -1; -
723 slotData.metaTypes.clear(); -
724 slotCache.hash.insert(cacheKey, slotData); -
725 object->setProperty(cachePropertyName, QVariant::fromValue(slotCache)); -
726 return false;
-
727 } -
728 }
-
729 -
730 -
731 slotCache.hash.insert(cacheKey, slotData); -
732 object->setProperty(cachePropertyName, QVariant::fromValue(slotCache)); -
733 -
734 -
735 deliverCall(object, flags, msg, slotData.metaTypes, slotData.slotIdx); -
736 return true;
-
737 } else if (cacheIt->slotIdx == -1) {
-
738 -
739 return false;
-
740 } else { -
741 -
742 deliverCall(object, flags, msg, cacheIt->metaTypes, cacheIt->slotIdx); -
743 return true;
-
744 } -
745 -
746 return false;
dead code: return false;
-
747} -
748 -
749void QDBusConnectionPrivate::deliverCall(QObject *object, int , const QDBusMessage &msg, -
750 const QVector<int> &metaTypes, int slotIdx) -
751{ -
752 qt_noop(); -
753 -
754 -
755 -
756 QVarLengthArray<void *, 10> params; -
757 params.reserve(metaTypes.count()); -
758 -
759 QVariantList auxParameters; -
760 -
761 -
762 -
763 params.append(0); -
764 -
765 -
766 int i; -
767 int pCount = qMin(msg.arguments().count(), metaTypes.count() - 1); -
768 for (i = 1; i <= pCount; ++i) {
-
769 int id = metaTypes[i]; -
770 if (id == QDBusMetaTypeId::message())
-
771 break;
-
772 -
773 const QVariant &arg = msg.arguments().at(i - 1); -
774 if (arg.userType() == id)
-
775 -
776 params.append(const_cast<void *>(arg.constData()));
-
777 else if (arg.userType() == qMetaTypeId<QDBusArgument>()) {
-
778 -
779 void *null = 0; -
780 auxParameters.append(QVariant(id, null)); -
781 -
782 const QDBusArgument &in = -
783 *reinterpret_cast<const QDBusArgument *>(arg.constData()); -
784 QVariant &out = auxParameters[auxParameters.count() - 1]; -
785 -
786 if (!QDBusMetaType::demarshall(in, out.userType(), out.data()))
-
787 QMessageLogger("qdbusintegrator.cpp", 909, __PRETTY_FUNCTION__).fatal("Internal error: demarshalling function for type '%s' (%d) failed!", -
788 out.typeName(), out.userType());
-
789 -
790 params.append(const_cast<void *>(out.constData())); -
791 } else {
-
792 QMessageLogger("qdbusintegrator.cpp", 914, __PRETTY_FUNCTION__).fatal("Internal error: got invalid meta type %d (%s) " -
793 "when trying to convert to meta type %d (%s)", -
794 arg.userType(), QMetaType::typeName(arg.userType()), -
795 id, QMetaType::typeName(id)); -
796 }
-
797 } -
798 -
799 if (metaTypes.count() > i && metaTypes[i] == QDBusMetaTypeId::message()) {
-
800 params.append(const_cast<void*>(static_cast<const void*>(&msg))); -
801 ++i; -
802 }
-
803 -
804 -
805 QVariantList outputArgs; -
806 void *null = 0; -
807 if (metaTypes[0] != QMetaType::Void && metaTypes[0] != QMetaType::UnknownType) {
-
808 QVariant arg(metaTypes[0], null); -
809 outputArgs.append( arg ); -
810 params[0] = const_cast<void*>(outputArgs.at( outputArgs.count() - 1 ).constData()); -
811 }
-
812 for ( ; i < metaTypes.count(); ++i) {
-
813 QVariant arg(metaTypes[i], null); -
814 outputArgs.append( arg ); -
815 params.append(const_cast<void*>(outputArgs.at( outputArgs.count() - 1 ).constData())); -
816 }
-
817 -
818 -
819 bool fail; -
820 if (!object) {
-
821 fail = true; -
822 } else {
-
823 -
824 QDBusContextPrivate context(QDBusConnection(this), msg); -
825 QDBusContextPrivate *old = QDBusContextPrivate::set(object, &context); -
826 QDBusConnectionPrivate::setSender(this); -
827 -
828 QPointer<QObject> ptr = object; -
829 fail = object->qt_metacall(QMetaObject::InvokeMetaMethod, -
830 slotIdx, params.data()) >= 0; -
831 QDBusConnectionPrivate::setSender(0); -
832 -
833 if (!ptr.isNull())
-
834 QDBusContextPrivate::set(object, old);
-
835 }
-
836 -
837 -
838 -
839 if (msg.isReplyRequired() && !msg.isDelayedReply()) {
-
840 if (!fail) {
-
841 -
842 if (!::isDebugging); else QMessageLogger("qdbusintegrator.cpp", 964, __PRETTY_FUNCTION__).debug() << this << "Automatically sending reply:" << outputArgs;
-
843 send(msg.createReply(outputArgs)); -
844 } else {
-
845 -
846 QMessageLogger("qdbusintegrator.cpp", 968, __PRETTY_FUNCTION__).warning("Internal error: Failed to deliver message"); -
847 send(msg.createErrorReply(QDBusError::InternalError, -
848 QLatin1String("Failed to deliver message"))); -
849 }
-
850 } -
851 -
852 return;
-
853} -
854 -
855extern bool qDBusInitThreads(); -
856 -
857QDBusConnectionPrivate::QDBusConnectionPrivate(QObject *p) -
858 : QObject(p), ref(1), capabilities(0), mode(InvalidMode), connection(0), server(0), busService(0), -
859 watchAndTimeoutLock(QMutex::Recursive), -
860 rootNode(QString(QLatin1Char('/'))) -
861{ -
862 static const bool threads = q_dbus_threads_init_default(); -
863 static const int debugging = qgetenv("QDBUS_DEBUG").toInt(); -
864 ::isDebugging = debugging; -
865 (void)threads; -
866 (void)debugging; -
867 -
868 -
869 -
870 -
871 -
872 -
873 QDBusMetaTypeId::init(); -
874 -
875 rootNode.flags = 0; -
876 -
877 -
878 -
879 watchedServices.insert(dbusServiceString(), WatchedServiceData(dbusServiceString(), 1)); -
880 -
881 -
882 -
883 matchRefCounts.insert("type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='NameOwnerChanged',arg0='org.freedesktop.DBus'", 1); -
884}
-
885 -
886QDBusConnectionPrivate::~QDBusConnectionPrivate() -
887{ -
888 if (thread() && thread() != QThread::currentThread())
-
889 QMessageLogger("qdbusintegrator.cpp", 1011, __PRETTY_FUNCTION__).warning("QDBusConnection(name=\"%s\")'s last reference in not in its creation thread! " -
890 "Timer and socket errors will follow and the program will probably crash", -
891 QString(name).toLocal8Bit().constData());
-
892 -
893 closeConnection(); -
894 rootNode.children.clear(); -
895 qDeleteAll(cachedMetaObjects); -
896 -
897 if (server)
-
898 q_dbus_server_unref(server);
-
899 if (connection)
-
900 q_dbus_connection_unref(connection);
-
901 -
902 connection = 0; -
903 server = 0; -
904}
-
905 -
906void QDBusConnectionPrivate::deleteYourself() -
907{ -
908 if (thread() && thread() != QThread::currentThread()) {
-
909 -
910 -
911 -
912 -
913 -
914 deleteLater(); -
915 } else {
-
916 delete this; -
917 }
-
918} -
919 -
920void QDBusConnectionPrivate::closeConnection() -
921{ -
922 QDBusWriteLocker locker(CloseConnectionAction, this); -
923 ConnectionMode oldMode = mode; -
924 mode = InvalidMode; -
925 baseService.clear(); -
926 -
927 if (server)
-
928 q_dbus_server_disconnect(server);
-
929 -
930 if (oldMode == ClientMode || oldMode == PeerMode) {
-
931 if (connection) {
-
932 q_dbus_connection_close(connection); -
933 -
934 while (q_dbus_connection_dispatch(connection) == DBUS_DISPATCH_DATA_REMAINS)
-
935 ;
-
936 }
-
937 }
-
938 if (!::isDebugging); else QMessageLogger("qdbusintegrator.cpp", 1060, __PRETTY_FUNCTION__).debug() << this << "Disconnected";
-
939} -
940 -
941void QDBusConnectionPrivate::checkThread() -
942{ -
943 if (!thread()) {
-
944 if (QCoreApplication::instance())
-
945 moveToThread(QCoreApplication::instance()->thread());
-
946 else -
947 QMessageLogger("qdbusintegrator.cpp", 1069, __PRETTY_FUNCTION__).warning("The thread that had QDBusConnection('%s') has died and there is no main thread", -
948 QString(name).toLocal8Bit().constData());
-
949 } -
950}
-
951 -
952bool QDBusConnectionPrivate::handleError(const QDBusErrorInternal &error) -
953{ -
954 if (!error)
-
955 return false;
-
956 -
957 -
958 lastError = error; -
959 -
960 return true;
-
961} -
962 -
963void QDBusConnectionPrivate::timerEvent(QTimerEvent *e) -
964{ -
965 { -
966 QDBusWatchAndTimeoutLocker locker(TimerEventAction, this); -
967 DBusTimeout *timeout = timeouts.value(e->timerId(), 0); -
968 if (timeout)
-
969 q_dbus_timeout_handle(timeout);
-
970 } -
971 -
972 doDispatch(); -
973}
-
974 -
975void QDBusConnectionPrivate::customEvent(QEvent *e) -
976{ -
977 qt_noop(); -
978 -
979 QDBusConnectionCallbackEvent *ev = static_cast<QDBusConnectionCallbackEvent *>(e); -
980 QDBusLockerBase::reportThreadAction(int(AddTimeoutAction) + int(ev->subtype), -
981 QDBusLockerBase::BeforeDeliver, this); -
982 switch (ev->subtype) -
983 { -
984 case QDBusConnectionCallbackEvent::AddTimeout: { -
985 QDBusWatchAndTimeoutLocker locker(RealAddTimeoutAction, this); -
986 while (!timeoutsPendingAdd.isEmpty()) {
-
987 QPair<DBusTimeout *, int> entry = timeoutsPendingAdd.takeFirst(); -
988 qDBusRealAddTimeout(this, entry.first, entry.second); -
989 }
-
990 break;
-
991 } -
992 -
993 case QDBusConnectionCallbackEvent::KillTimer: -
994 killTimer(ev->timerId); -
995 break;
-
996 -
997 case QDBusConnectionCallbackEvent::AddWatch: -
998 qDBusRealAddWatch(this, ev->watch, ev->extra, ev->fd); -
999 break;
-
1000 -
1001 case QDBusConnectionCallbackEvent::ToggleWatch: -
1002 qDBusRealToggleWatch(this, ev->watch, ev->fd); -
1003 break;
-
1004 } -
1005 QDBusLockerBase::reportThreadAction(int(AddTimeoutAction) + int(ev->subtype), -
1006 QDBusLockerBase::AfterDeliver, this); -
1007}
-
1008 -
1009void QDBusConnectionPrivate::doDispatch() -
1010{ -
1011 QDBusDispatchLocker locker(DoDispatchAction, this); -
1012 if (mode == ClientMode || mode == PeerMode)
-
1013 while (q_dbus_connection_dispatch(connection) == DBUS_DISPATCH_DATA_REMAINS) ;
-
1014}
-
1015 -
1016void QDBusConnectionPrivate::socketRead(int fd) -
1017{ -
1018 QVarLengthArray<DBusWatch *, 2> pendingWatches; -
1019 -
1020 { -
1021 QDBusWatchAndTimeoutLocker locker(SocketReadAction, this); -
1022 WatcherHash::ConstIterator it = watchers.constFind(fd); -
1023 while (it != watchers.constEnd() && it.key() == fd) {
-
1024 if (it->watch && it->read && it->read->isEnabled())
-
1025 pendingWatches.append(it.value().watch);
-
1026 ++it; -
1027 }
-
1028 } -
1029 -
1030 for (int i = 0; i < pendingWatches.size(); ++i)
-
1031 if (!q_dbus_watch_handle(pendingWatches[i], DBUS_WATCH_READABLE))
-
1032 QMessageLogger("qdbusintegrator.cpp", 1154, __PRETTY_FUNCTION__).debug("OUT OF MEM");
-
1033 doDispatch(); -
1034}
-
1035 -
1036void QDBusConnectionPrivate::socketWrite(int fd) -
1037{ -
1038 QVarLengthArray<DBusWatch *, 2> pendingWatches; -
1039 -
1040 { -
1041 QDBusWatchAndTimeoutLocker locker(SocketWriteAction, this); -
1042 WatcherHash::ConstIterator it = watchers.constFind(fd); -
1043 while (it != watchers.constEnd() && it.key() == fd) {
-
1044 if (it->watch && it->write && it->write->isEnabled())
-
1045 pendingWatches.append(it.value().watch);
-
1046 ++it; -
1047 }
-
1048 } -
1049 -
1050 for (int i = 0; i < pendingWatches.size(); ++i)
-
1051 if (!q_dbus_watch_handle(pendingWatches[i], DBUS_WATCH_WRITABLE))
-
1052 QMessageLogger("qdbusintegrator.cpp", 1174, __PRETTY_FUNCTION__).debug("OUT OF MEM");
-
1053}
-
1054 -
1055void QDBusConnectionPrivate::objectDestroyed(QObject *obj) -
1056{ -
1057 QDBusWriteLocker locker(ObjectDestroyedAction, this); -
1058 huntAndDestroy(obj, rootNode); -
1059 -
1060 SignalHookHash::iterator sit = signalHooks.begin(); -
1061 while (sit != signalHooks.end()) {
-
1062 if (static_cast<QObject *>(sit.value().obj) == obj)
-
1063 sit = disconnectSignal(sit);
-
1064 else -
1065 ++sit;
-
1066 } -
1067 -
1068 obj->disconnect(this); -
1069}
-
1070 -
1071void QDBusConnectionPrivate::relaySignal(QObject *obj, const QMetaObject *mo, int signalId, -
1072 const QVariantList &args) -
1073{ -
1074 QString interface = qDBusInterfaceFromMetaObject(mo); -
1075 -
1076 QMetaMethod mm = mo->method(signalId); -
1077 QByteArray memberName = mm.name(); -
1078 -
1079 -
1080 bool isScriptable = mm.attributes() & QMetaMethod::Scriptable; -
1081 bool isAdaptor = false; -
1082 for ( ; mo; mo = mo->superClass())
-
1083 if (mo == &QDBusAbstractAdaptor::staticMetaObject) {
-
1084 isAdaptor = true; -
1085 break;
-
1086 } -
1087 -
1088 QDBusReadLocker locker(RelaySignalAction, this); -
1089 QDBusMessage message = QDBusMessage::createSignal(QLatin1String("/"), interface, -
1090 QLatin1String(memberName)); -
1091 QDBusMessagePrivate::setParametersValidated(message, true); -
1092 message.setArguments(args); -
1093 QDBusError error; -
1094 DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message, capabilities, &error); -
1095 if (!msg) {
-
1096 QMessageLogger("qdbusintegrator.cpp", 1218, __PRETTY_FUNCTION__).warning("QDBusConnection: Could not emit signal %s.%s: %s", QString(interface).toLocal8Bit().constData(), memberName.constData(), -
1097 QString(error.message()).toLocal8Bit().constData()); -
1098 lastError = error; -
1099 return;
-
1100 } -
1101 -
1102 -
1103 -
1104 q_dbus_message_set_no_reply(msg, true); -
1105 huntAndEmit(connection, msg, obj, rootNode, isScriptable, isAdaptor); -
1106 q_dbus_message_unref(msg); -
1107}
-
1108 -
1109void QDBusConnectionPrivate::serviceOwnerChangedNoLock(const QString &name, -
1110 const QString &oldOwner, const QString &newOwner) -
1111{ -
1112 (void)oldOwner;; -
1113 -
1114 WatchedServicesHash::Iterator it = watchedServices.find(name); -
1115 if (it == watchedServices.end())
-
1116 return;
-
1117 if (oldOwner != it->owner)
-
1118 QMessageLogger("qdbusintegrator.cpp", 1240, __PRETTY_FUNCTION__).warning("QDBusConnection: name '%s' had owner '%s' but we thought it was '%s'", -
1119 QString(name).toLocal8Bit().constData(), QString(oldOwner).toLocal8Bit().constData(), QString(it->owner).toLocal8Bit().constData());
-
1120 -
1121 if (!::isDebugging); else QMessageLogger("qdbusintegrator.cpp", 1243, __PRETTY_FUNCTION__).debug() << this << "Updating name" << name << "from" << oldOwner << "to" << newOwner;
-
1122 it->owner = newOwner; -
1123}
-
1124 -
1125int QDBusConnectionPrivate::findSlot(QObject* obj, const QByteArray &normalizedName, -
1126 QVector<int> &params) -
1127{ -
1128 int midx = obj->metaObject()->indexOfMethod(normalizedName); -
1129 if (midx == -1)
-
1130 return -1;
-
1131 -
1132 int inputCount = qDBusParametersForMethod(obj->metaObject()->method(midx), params); -
1133 if ( inputCount == -1 || inputCount + 1 != params.count() )
-
1134 return -1;
-
1135 -
1136 return midx;
-
1137} -
1138 -
1139bool QDBusConnectionPrivate::prepareHook(QDBusConnectionPrivate::SignalHook &hook, QString &key, -
1140 const QString &service, -
1141 const QString &path, const QString &interface, const QString &name, -
1142 const QStringList &argMatch, -
1143 QObject *receiver, const char *signal, int minMIdx, -
1144 bool buildSignature) -
1145{ -
1146 QByteArray normalizedName = signal + 1; -
1147 hook.midx = findSlot(receiver, signal + 1, hook.params); -
1148 if (hook.midx == -1) {
-
1149 normalizedName = QMetaObject::normalizedSignature(signal + 1); -
1150 hook.midx = findSlot(receiver, normalizedName, hook.params); -
1151 }
-
1152 if (hook.midx < minMIdx) {
-
1153 if (hook.midx == -1)
-
1154 {}
-
1155 return false;
-
1156 } -
1157 -
1158 hook.service = service; -
1159 hook.path = path; -
1160 hook.obj = receiver; -
1161 hook.argumentMatch = argMatch; -
1162 -
1163 -
1164 -
1165 -
1166 QString mname = name; -
1167 if (buildSignature && mname.isNull()) {
-
1168 normalizedName.truncate(normalizedName.indexOf('(')); -
1169 mname = QString::fromUtf8(normalizedName); -
1170 }
-
1171 key = mname; -
1172 key.reserve(interface.length() + 1 + mname.length()); -
1173 key += QLatin1Char(':'); -
1174 key += interface; -
1175 -
1176 if (buildSignature) {
-
1177 hook.signature.clear(); -
1178 for (int i = 1; i < hook.params.count(); ++i)
-
1179 if (hook.params.at(i) != QDBusMetaTypeId::message())
-
1180 hook.signature += QLatin1String( QDBusMetaType::typeToSignature( hook.params.at(i) ) );
-
1181 }
-
1182 -
1183 hook.matchRule = buildMatchRule(service, path, interface, mname, argMatch, hook.signature); -
1184 return true;
-
1185} -
1186 -
1187void QDBusConnectionPrivate::sendError(const QDBusMessage &msg, QDBusError::ErrorType code) -
1188{ -
1189 if (code == QDBusError::UnknownMethod) {
-
1190 QString interfaceMsg; -
1191 if (msg.interface().isEmpty())
-
1192 interfaceMsg = QLatin1String("any interface");
-
1193 else -
1194 interfaceMsg = QString::fromLatin1("interface '%1'").arg(msg.interface());
-
1195 -
1196 send(msg.createErrorReply(code, -
1197 QString::fromLatin1("No such method '%1' in %2 at object path '%3' " -
1198 "(signature '%4')") -
1199 .arg(msg.member(), interfaceMsg, msg.path(), msg.signature()))); -
1200 } else if (code == QDBusError::UnknownInterface) {
-
1201 send(msg.createErrorReply(QDBusError::UnknownInterface, -
1202 QString::fromLatin1("No such interface '%1' at object path '%2'") -
1203 .arg(msg.interface(), msg.path()))); -
1204 } else if (code == QDBusError::UnknownObject) {
-
1205 send(msg.createErrorReply(QDBusError::UnknownObject, -
1206 QString::fromLatin1("No such object path '%1'").arg(msg.path()))); -
1207 }
-
1208} -
1209 -
1210bool QDBusConnectionPrivate::activateInternalFilters(const ObjectTreeNode &node, -
1211 const QDBusMessage &msg) -
1212{ -
1213 -
1214 const QString interface = msg.interface(); -
1215 -
1216 if (interface.isEmpty() || interface == QLatin1String("org.freedesktop.DBus.Introspectable")) {
-
1217 if (msg.member() == QLatin1String("Introspect") && msg.signature().isEmpty()) {
-
1218 -
1219 QDBusMessage reply = msg.createReply(qDBusIntrospectObject(node, msg.path())); -
1220 send(reply); -
1221 return true;
-
1222 } -
1223 -
1224 if (!interface.isEmpty()) {
-
1225 sendError(msg, QDBusError::UnknownMethod); -
1226 return true;
-
1227 } -
1228 }
-
1229 -
1230 if (node.obj && (interface.isEmpty() ||
-
1231 interface == QLatin1String("org.freedesktop.DBus.Properties"))) {
-
1232 -
1233 if (msg.member() == QLatin1String("Get") && msg.signature() == QLatin1String("ss")) {
-
1234 QDBusMessage reply = qDBusPropertyGet(node, msg); -
1235 send(reply); -
1236 return true;
-
1237 } else if (msg.member() == QLatin1String("Set") && msg.signature() == QLatin1String("ssv")) {
-
1238 QDBusMessage reply = qDBusPropertySet(node, msg); -
1239 send(reply); -
1240 return true;
-
1241 } else if (msg.member() == QLatin1String("GetAll") && msg.signature() == QLatin1String("s")) {
-
1242 QDBusMessage reply = qDBusPropertyGetAll(node, msg); -
1243 send(reply); -
1244 return true;
-
1245 } -
1246 -
1247 if (!interface.isEmpty()) {
-
1248 sendError(msg, QDBusError::UnknownMethod); -
1249 return true;
-
1250 } -
1251 }
-
1252 -
1253 return false;
-
1254} -
1255 -
1256void QDBusConnectionPrivate::activateObject(ObjectTreeNode &node, const QDBusMessage &msg, -
1257 int pathStartPos) -
1258{ -
1259 -
1260 -
1261 -
1262 -
1263 -
1264 -
1265 -
1266 if (node.flags & QDBusConnectionPrivate::VirtualObject) {
-
1267 if (node.treeNode->handleMessage(msg, q(this))) {
-
1268 return;
-
1269 } else { -
1270 if (activateInternalFilters(node, msg))
-
1271 return;
-
1272 }
-
1273 } -
1274 -
1275 if (pathStartPos != msg.path().length()) {
-
1276 node.flags &= ~QDBusConnection::ExportAllSignals; -
1277 node.obj = findChildObject(&node, msg.path(), pathStartPos); -
1278 if (!node.obj) {
-
1279 sendError(msg, QDBusError::UnknownObject); -
1280 return;
-
1281 } -
1282 }
-
1283 -
1284 QDBusAdaptorConnector *connector; -
1285 if (node.flags & QDBusConnection::ExportAdaptors &&
-
1286 (connector = qDBusFindAdaptorConnector(node.obj))) {
-
1287 int newflags = node.flags | QDBusConnection::ExportAllSlots; -
1288 -
1289 if (msg.interface().isEmpty()) {
-
1290 -
1291 -
1292 QDBusAdaptorConnector::AdaptorMap::ConstIterator it = -
1293 connector->adaptors.constBegin(); -
1294 QDBusAdaptorConnector::AdaptorMap::ConstIterator end = -
1295 connector->adaptors.constEnd(); -
1296 -
1297 for ( ; it != end; ++it)
-
1298 if (activateCall(it->adaptor, newflags, msg))
-
1299 return;
-
1300 } else {
-
1301 -
1302 QDBusAdaptorConnector::AdaptorMap::ConstIterator it; -
1303 it = std::lower_bound(connector->adaptors.constBegin(), connector->adaptors.constEnd(), -
1304 msg.interface()); -
1305 if (it != connector->adaptors.constEnd() && msg.interface() == QLatin1String(it->interface)) {
-
1306 if (!activateCall(it->adaptor, newflags, msg))
-
1307 sendError(msg, QDBusError::UnknownMethod);
-
1308 return;
-
1309 } -
1310 }
-
1311 } -
1312 -
1313 -
1314 -
1315 if (activateInternalFilters(node, msg))
-
1316 return;
-
1317 -
1318 -
1319 if (node.flags & (QDBusConnection::ExportScriptableSlots|QDBusConnection::ExportNonScriptableSlots) ||
-
1320 node.flags & (QDBusConnection::ExportScriptableInvokables|QDBusConnection::ExportNonScriptableInvokables)) {
-
1321 bool interfaceFound = true; -
1322 if (!msg.interface().isEmpty())
-
1323 interfaceFound = qDBusInterfaceInObject(node.obj, msg.interface());
-
1324 -
1325 if (interfaceFound) {
-
1326 if (!activateCall(node.obj, node.flags, msg))
-
1327 sendError(msg, QDBusError::UnknownMethod);
-
1328 return;
-
1329 } -
1330 }
-
1331 -
1332 -
1333 if (msg.interface().isEmpty())
-
1334 sendError(msg, QDBusError::UnknownMethod);
-
1335 else -
1336 sendError(msg, QDBusError::UnknownInterface);
-
1337} -
1338 -
1339void QDBusConnectionPrivate::handleObjectCall(const QDBusMessage &msg) -
1340{ -
1341 -
1342 -
1343 -
1344 -
1345 -
1346 -
1347 -
1348 ObjectTreeNode result; -
1349 int usedLength; -
1350 QThread *objThread = 0; -
1351 QSemaphore sem; -
1352 bool semWait; -
1353 -
1354 { -
1355 QDBusReadLocker locker(HandleObjectCallAction, this); -
1356 if (!findObject(&rootNode, msg.path(), usedLength, result)) {
-
1357 -
1358 sendError(msg, QDBusError::UnknownObject); -
1359 return;
-
1360 } -
1361 -
1362 if (!result.obj) {
-
1363 -
1364 -
1365 activateObject(result, msg, usedLength); -
1366 return;
-
1367 } -
1368 -
1369 objThread = result.obj->thread(); -
1370 if (!objThread) {
-
1371 send(msg.createErrorReply(QDBusError::InternalError, -
1372 QString::fromLatin1("Object '%1' (at path '%2')" -
1373 " has no thread. Cannot deliver message.") -
1374 .arg(result.obj->objectName(), msg.path()))); -
1375 return;
-
1376 } -
1377 -
1378 if (!QDBusMessagePrivate::isLocal(msg)) {
-
1379 -
1380 -
1381 postEventToThread(HandleObjectCallPostEventAction, result.obj, -
1382 new QDBusActivateObjectEvent(QDBusConnection(this), this, result, -
1383 usedLength, msg)); -
1384 return;
-
1385 } else if (objThread != QThread::currentThread()) {
-
1386 -
1387 postEventToThread(HandleObjectCallPostEventAction, result.obj, -
1388 new QDBusActivateObjectEvent(QDBusConnection(this), this, result, -
1389 usedLength, msg, &sem)); -
1390 semWait = true; -
1391 } else {
-
1392 semWait = false; -
1393 }
-
1394 } -
1395 -
1396 if (semWait)
-
1397 sem.acquire();
-
1398 else -
1399 activateObject(result, msg, usedLength);
-
1400} -
1401 -
1402QDBusActivateObjectEvent::~QDBusActivateObjectEvent() -
1403{ -
1404 if (!handled) {
-
1405 -
1406 -
1407 QDBusConnectionPrivate *that = QDBusConnectionPrivate::d(connection); -
1408 that->sendError(message, QDBusError::UnknownObject); -
1409 }
-
1410 -
1411 -
1412}
-
1413 -
1414void QDBusActivateObjectEvent::placeMetaCall(QObject *) -
1415{ -
1416 QDBusConnectionPrivate *that = QDBusConnectionPrivate::d(connection); -
1417 -
1418 QDBusLockerBase::reportThreadAction(HandleObjectCallPostEventAction, -
1419 QDBusLockerBase::BeforeDeliver, that); -
1420 that->activateObject(node, message, pathStartPos); -
1421 QDBusLockerBase::reportThreadAction(HandleObjectCallPostEventAction, -
1422 QDBusLockerBase::AfterDeliver, that); -
1423 -
1424 handled = true; -
1425}
-
1426 -
1427void QDBusConnectionPrivate::handleSignal(const QString &key, const QDBusMessage& msg) -
1428{ -
1429 SignalHookHash::const_iterator it = signalHooks.constFind(key); -
1430 SignalHookHash::const_iterator end = signalHooks.constEnd(); -
1431 -
1432 -
1433 for ( ; it != end && it.key() == key; ++it) {
-
1434 const SignalHook &hook = it.value(); -
1435 if (!hook.service.isEmpty()) {
-
1436 const QString owner = -
1437 shouldWatchService(hook.service) ?
-
1438 watchedServices.value(hook.service).owner : -
1439 hook.service; -
1440 if (owner != msg.service())
-
1441 continue;
-
1442 }
-
1443 if (!hook.path.isEmpty() && hook.path != msg.path())
-
1444 continue;
-
1445 if (!hook.signature.isEmpty() && hook.signature != msg.signature())
-
1446 continue;
-
1447 if (hook.signature.isEmpty() && !hook.signature.isNull() && !msg.signature().isEmpty())
-
1448 continue;
-
1449 if (!hook.argumentMatch.isEmpty()) {
-
1450 const QVariantList arguments = msg.arguments(); -
1451 if (hook.argumentMatch.size() > arguments.size())
-
1452 continue;
-
1453 -
1454 bool matched = true; -
1455 for (int i = 0; i < hook.argumentMatch.size(); ++i) {
-
1456 const QString &param = hook.argumentMatch.at(i); -
1457 if (param.isNull())
-
1458 continue;
-
1459 if (param == arguments.at(i).toString())
-
1460 continue;
-
1461 matched = false; -
1462 break;
-
1463 } -
1464 if (!matched)
-
1465 continue;
-
1466 }
-
1467 -
1468 activateSignal(hook, msg); -
1469 }
-
1470}
-
1471 -
1472void QDBusConnectionPrivate::handleSignal(const QDBusMessage& msg) -
1473{ -
1474 -
1475 -
1476 -
1477 -
1478 -
1479 -
1480 -
1481 QString key = msg.member(); -
1482 key.reserve(key.length() + 1 + msg.interface().length()); -
1483 key += QLatin1Char(':'); -
1484 key += msg.interface(); -
1485 -
1486 QDBusReadLocker locker(HandleSignalAction, this); -
1487 handleSignal(key, msg); -
1488 -
1489 key.truncate(msg.member().length() + 1); -
1490 handleSignal(key, msg); -
1491 -
1492 key = QLatin1Char(':'); -
1493 key += msg.interface(); -
1494 handleSignal(key, msg); -
1495}
-
1496 -
1497static dbus_int32_t server_slot = -1; -
1498 -
1499void QDBusConnectionPrivate::setServer(DBusServer *s, const QDBusErrorInternal &error) -
1500{ -
1501 if (!s) {
-
1502 handleError(error); -
1503 return;
-
1504 } -
1505 -
1506 server = s; -
1507 mode = ServerMode; -
1508 -
1509 dbus_bool_t data_allocated = q_dbus_server_allocate_data_slot(&server_slot); -
1510 if (data_allocated && server_slot < 0)
-
1511 return;
-
1512 -
1513 dbus_bool_t watch_functions_set = q_dbus_server_set_watch_functions(server, -
1514 qDBusAddWatch, -
1515 qDBusRemoveWatch, -
1516 qDBusToggleWatch, -
1517 this, 0); -
1518 -
1519 (void)watch_functions_set;; -
1520 -
1521 dbus_bool_t time_functions_set = q_dbus_server_set_timeout_functions(server, -
1522 qDBusAddTimeout, -
1523 qDBusRemoveTimeout, -
1524 qDBusToggleTimeout, -
1525 this, 0); -
1526 -
1527 (void)time_functions_set;; -
1528 -
1529 q_dbus_server_set_new_connection_function(server, qDBusNewConnection, this, 0); -
1530 -
1531 dbus_bool_t data_set = q_dbus_server_set_data(server, server_slot, this, 0); -
1532 -
1533 (void)data_set;; -
1534}
-
1535 -
1536void QDBusConnectionPrivate::setPeer(DBusConnection *c, const QDBusErrorInternal &error) -
1537{ -
1538 if (!c) {
-
1539 handleError(error); -
1540 return;
-
1541 } -
1542 -
1543 connection = c; -
1544 mode = PeerMode; -
1545 -
1546 q_dbus_connection_set_exit_on_disconnect(connection, false); -
1547 q_dbus_connection_set_watch_functions(connection, -
1548 qDBusAddWatch, -
1549 qDBusRemoveWatch, -
1550 qDBusToggleWatch, -
1551 this, 0); -
1552 q_dbus_connection_set_timeout_functions(connection, -
1553 qDBusAddTimeout, -
1554 qDBusRemoveTimeout, -
1555 qDBusToggleTimeout, -
1556 this, 0); -
1557 q_dbus_connection_set_dispatch_status_function(connection, qDBusUpdateDispatchStatus, this, 0); -
1558 q_dbus_connection_add_filter(connection, -
1559 qDBusSignalFilter, -
1560 this, 0); -
1561 -
1562 QMetaObject::invokeMethod(this, "doDispatch", Qt::QueuedConnection); -
1563}
-
1564 -
1565static QDBusConnection::ConnectionCapabilities connectionCapabilies(DBusConnection *connection) -
1566{ -
1567 QDBusConnection::ConnectionCapabilities result = 0; -
1568 typedef dbus_bool_t (*can_send_type_t)(DBusConnection *, int); -
1569 static can_send_type_t can_send_type = 0; -
1570 -
1571 -
1572 -
1573 -
1574 -
1575 -
1576 -
1577 can_send_type = (can_send_type_t)qdbus_resolve_conditionally("dbus_connection_can_send_type"); -
1578 -
1579 -
1580 -
1581 -
1582 -
1583 if (can_send_type && can_send_type(connection, int('h')))
-
1584 result |= QDBusConnection::UnixFileDescriptorPassing;
-
1585 -
1586 return result;
-
1587} -
1588 -
1589void QDBusConnectionPrivate::setConnection(DBusConnection *dbc, const QDBusErrorInternal &error) -
1590{ -
1591 if (!dbc) {
-
1592 handleError(error); -
1593 return;
-
1594 } -
1595 -
1596 connection = dbc; -
1597 mode = ClientMode; -
1598 -
1599 const char *service = q_dbus_bus_get_unique_name(connection); -
1600 qt_noop(); -
1601 baseService = QString::fromUtf8(service); -
1602 capabilities = connectionCapabilies(connection); -
1603 -
1604 q_dbus_connection_set_exit_on_disconnect(connection, false); -
1605 q_dbus_connection_set_watch_functions(connection, qDBusAddWatch, qDBusRemoveWatch, -
1606 qDBusToggleWatch, this, 0); -
1607 q_dbus_connection_set_timeout_functions(connection, qDBusAddTimeout, qDBusRemoveTimeout, -
1608 qDBusToggleTimeout, this, 0); -
1609 q_dbus_connection_set_dispatch_status_function(connection, qDBusUpdateDispatchStatus, this, 0); -
1610 q_dbus_connection_add_filter(connection, qDBusSignalFilter, this, 0); -
1611 -
1612 -
1613 -
1614 -
1615 SignalHook hook; -
1616 hook.service = dbusServiceString(); -
1617 hook.path.clear(); -
1618 hook.obj = this; -
1619 hook.params << QMetaType::Void << QVariant::String; -
1620 -
1621 hook.midx = staticMetaObject.indexOfSlot("registerServiceNoLock(QString)"); -
1622 qt_noop(); -
1623 signalHooks.insert(QLatin1String("NameAcquired:" "org.freedesktop.DBus"), hook); -
1624 -
1625 hook.midx = staticMetaObject.indexOfSlot("unregisterServiceNoLock(QString)"); -
1626 qt_noop(); -
1627 signalHooks.insert(QLatin1String("NameLost:" "org.freedesktop.DBus"), hook); -
1628 -
1629 if (!::isDebugging); else QMessageLogger("qdbusintegrator.cpp", 1751, __PRETTY_FUNCTION__).debug() << this << ": connected successfully";
-
1630 -
1631 -
1632 QMetaObject::invokeMethod(this, "doDispatch", Qt::QueuedConnection); -
1633}
-
1634 -
1635extern "C"{ -
1636static void qDBusResultReceived(DBusPendingCall *pending, void *user_data) -
1637{ -
1638 QDBusPendingCallPrivate *call = reinterpret_cast<QDBusPendingCallPrivate *>(user_data); -
1639 qt_noop(); -
1640 (void)pending;; -
1641 QDBusConnectionPrivate::processFinishedCall(call); -
1642}
-
1643} -
1644 -
1645void QDBusConnectionPrivate::waitForFinished(QDBusPendingCallPrivate *pcall) -
1646{ -
1647 qt_noop(); -
1648 qt_noop(); -
1649 -
1650 -
1651 if (pcall->waitingForFinished) {
-
1652 -
1653 pcall->waitForFinishedCondition.wait(&pcall->mutex); -
1654 } else {
-
1655 pcall->waitingForFinished = true; -
1656 pcall->mutex.unlock(); -
1657 -
1658 { -
1659 QDBusDispatchLocker locker(PendingCallBlockAction, this); -
1660 q_dbus_pending_call_block(pcall->pending); -
1661 -
1662 } -
1663 pcall->mutex.lock(); -
1664 pcall->waitForFinishedCondition.wakeAll(); -
1665 }
-
1666} -
1667 -
1668static inline bool waitingForFinishedIsSet(QDBusPendingCallPrivate *call) -
1669{ -
1670 const QMutexLocker locker(&call->mutex); -
1671 return call->waitingForFinished;
-
1672} -
1673 -
1674void QDBusConnectionPrivate::processFinishedCall(QDBusPendingCallPrivate *call) -
1675{ -
1676 QDBusConnectionPrivate *connection = const_cast<QDBusConnectionPrivate *>(call->connection); -
1677 -
1678 QMutexLocker locker(&call->mutex); -
1679 -
1680 QDBusMessage &msg = call->replyMessage; -
1681 if (call->pending) {
-
1682 -
1683 DBusMessage *reply = q_dbus_pending_call_steal_reply(call->pending); -
1684 msg = QDBusMessagePrivate::fromDBusMessage(reply, connection->capabilities); -
1685 q_dbus_message_unref(reply); -
1686 }
-
1687 if (!::isDebugging); else QMessageLogger("qdbusintegrator.cpp", 1809, __PRETTY_FUNCTION__).debug() << connection << "got message reply (async):" << msg;
-
1688 -
1689 -
1690 call->checkReceivedSignature(); -
1691 -
1692 if (!call->receiver.isNull() && call->methodIdx != -1 && msg.type() == QDBusMessage::ReplyMessage) {
-
1693 QDBusCallDeliveryEvent *e = prepareReply(connection, call->receiver, call->methodIdx, -
1694 call->metaTypes, msg); -
1695 if (e)
-
1696 connection->postEventToThread(MessageResultReceivedAction, call->receiver, e);
-
1697 else -
1698 if (!::isDebugging); else QMessageLogger("qdbusintegrator.cpp", 1828, __PRETTY_FUNCTION__).debug() << "Deliver failed!";
-
1699 } -
1700 -
1701 if (call->pending)
-
1702 q_dbus_pending_call_unref(call->pending);
-
1703 call->pending = 0; -
1704 -
1705 locker.unlock(); -
1706 -
1707 -
1708 if (call->watcherHelper)
-
1709 call->watcherHelper->emitSignals(msg, call->sentMessage);
-
1710 -
1711 if (msg.type() == QDBusMessage::ErrorMessage)
-
1712 connection->callWithCallbackFailed(QDBusError(msg), call->sentMessage);
-
1713 -
1714 if (call->autoDelete) {
-
1715 qt_noop(); -
1716 delete call; -
1717 }
-
1718}
-
1719 -
1720int QDBusConnectionPrivate::send(const QDBusMessage& message) -
1721{ -
1722 if (QDBusMessagePrivate::isLocal(message))
-
1723 return -1;
-
1724 -
1725 -
1726 QDBusError error; -
1727 DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message, capabilities, &error); -
1728 if (!msg) {
-
1729 if (message.type() == QDBusMessage::MethodCallMessage)
-
1730 QMessageLogger("qdbusintegrator.cpp", 1860, __PRETTY_FUNCTION__).warning("QDBusConnection: error: could not send message to service \"%s\" path \"%s\" interface \"%s\" member \"%s\": %s", -
1731 QString(message.service()).toLocal8Bit().constData(), QString(message.path()).toLocal8Bit().constData(), -
1732 QString(message.interface()).toLocal8Bit().constData(), QString(message.member()).toLocal8Bit().constData(), -
1733 QString(error.message()).toLocal8Bit().constData());
-
1734 else if (message.type() == QDBusMessage::SignalMessage)
-
1735 QMessageLogger("qdbusintegrator.cpp", 1865, __PRETTY_FUNCTION__).warning("QDBusConnection: error: could not send signal path \"%s\" interface \"%s\" member \"%s\": %s", -
1736 QString(message.path()).toLocal8Bit().constData(), QString(message.interface()).toLocal8Bit().constData(), -
1737 QString(message.member()).toLocal8Bit().constData(), -
1738 QString(error.message()).toLocal8Bit().constData());
-
1739 else -
1740 QMessageLogger("qdbusintegrator.cpp", 1870, __PRETTY_FUNCTION__).warning("QDBusConnection: error: could not send %s message to service \"%s\": %s", -
1741 message.type() == QDBusMessage::ReplyMessage ? "reply" : -
1742 message.type() == QDBusMessage::ErrorMessage ? "error" : -
1743 "invalid", QString(message.service()).toLocal8Bit().constData(), -
1744 QString(error.message()).toLocal8Bit().constData());
-
1745 lastError = error; -
1746 return 0;
-
1747 } -
1748 -
1749 q_dbus_message_set_no_reply(msg, true); -
1750 -
1751 if (!::isDebugging); else QMessageLogger("qdbusintegrator.cpp", 1881, __PRETTY_FUNCTION__).debug() << this << "sending message (no reply):" << message;
-
1752 checkThread(); -
1753 bool isOk = q_dbus_connection_send(connection, msg, 0); -
1754 int serial = 0; -
1755 if (isOk)
-
1756 serial = q_dbus_message_get_serial(msg);
-
1757 -
1758 q_dbus_message_unref(msg); -
1759 return serial;
-
1760} -
1761 -
1762QDBusMessage QDBusConnectionPrivate::sendWithReply(const QDBusMessage &message, -
1763 int sendMode, int timeout) -
1764{ -
1765 checkThread(); -
1766 if ((sendMode == QDBus::BlockWithGui || sendMode == QDBus::Block)
-
1767 && isServiceRegisteredByThread(message.service()))
-
1768 -
1769 return sendWithReplyLocal(message);
-
1770 -
1771 if (!QCoreApplication::instance() || sendMode == QDBus::Block) {
-
1772 QDBusError err; -
1773 DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message, capabilities, &err); -
1774 if (!msg) {
-
1775 QMessageLogger("qdbusintegrator.cpp", 1905, __PRETTY_FUNCTION__).warning("QDBusConnection: error: could not send message to service \"%s\" path \"%s\" interface \"%s\" member \"%s\": %s", -
1776 QString(message.service()).toLocal8Bit().constData(), QString(message.path()).toLocal8Bit().constData(), -
1777 QString(message.interface()).toLocal8Bit().constData(), QString(message.member()).toLocal8Bit().constData(), -
1778 QString(err.message()).toLocal8Bit().constData()); -
1779 lastError = err; -
1780 return QDBusMessage::createError(err);
-
1781 } -
1782 -
1783 if (!::isDebugging); else QMessageLogger("qdbusintegrator.cpp", 1913, __PRETTY_FUNCTION__).debug() << this << "sending message (blocking):" << message;
-
1784 QDBusErrorInternal error; -
1785 DBusMessage *reply = q_dbus_connection_send_with_reply_and_block(connection, msg, timeout, error); -
1786 -
1787 q_dbus_message_unref(msg); -
1788 -
1789 if (!!error) {
-
1790 lastError = err = error; -
1791 return QDBusMessage::createError(err);
-
1792 } -
1793 -
1794 QDBusMessage amsg = QDBusMessagePrivate::fromDBusMessage(reply, capabilities); -
1795 q_dbus_message_unref(reply); -
1796 if (!::isDebugging); else QMessageLogger("qdbusintegrator.cpp", 1926, __PRETTY_FUNCTION__).debug() << this << "got message reply (blocking):" << amsg;
-
1797 -
1798 return amsg;
-
1799 } else { -
1800 QDBusPendingCallPrivate *pcall = sendWithReplyAsync(message, timeout); -
1801 qt_noop(); -
1802 -
1803 if (pcall->replyMessage.type() == QDBusMessage::InvalidMessage) {
-
1804 pcall->watcherHelper = new QDBusPendingCallWatcherHelper; -
1805 QEventLoop loop; -
1806 loop.connect(pcall->watcherHelper, "2""reply(QDBusMessage)", "1""quit()"); -
1807 loop.connect(pcall->watcherHelper, "2""error(QDBusError,QDBusMessage)", "1""quit()"); -
1808 -
1809 -
1810 loop.exec(QEventLoop::ExcludeUserInputEvents | QEventLoop::WaitForMoreEvents); -
1811 }
-
1812 -
1813 QDBusMessage reply = pcall->replyMessage; -
1814 lastError = QDBusError(reply); -
1815 -
1816 delete pcall; -
1817 return reply;
-
1818 } -
1819} -
1820 -
1821QDBusMessage QDBusConnectionPrivate::sendWithReplyLocal(const QDBusMessage &message) -
1822{ -
1823 if (!::isDebugging); else QMessageLogger("qdbusintegrator.cpp", 1953, __PRETTY_FUNCTION__).debug() << this << "sending message via local-loop:" << message;
-
1824 -
1825 QDBusMessage localCallMsg = QDBusMessagePrivate::makeLocal(*this, message); -
1826 bool handled = handleMessage(localCallMsg); -
1827 -
1828 if (!handled) {
-
1829 QString interface = message.interface(); -
1830 if (interface.isEmpty())
-
1831 interface = QLatin1String("<no-interface>");
-
1832 return QDBusMessage::createError(QDBusError::InternalError, -
1833 QString::fromLatin1("Internal error trying to call %1.%2 at %3 (signature '%4'") -
1834 .arg(interface, message.member(), -
1835 message.path(), message.signature()));
-
1836 } -
1837 -
1838 -
1839 QDBusMessage localReplyMsg = QDBusMessagePrivate::makeLocalReply(*this, localCallMsg); -
1840 if (localReplyMsg.type() == QDBusMessage::InvalidMessage) {
-
1841 QMessageLogger("qdbusintegrator.cpp", 1971, __PRETTY_FUNCTION__).warning("QDBusConnection: cannot call local method '%s' at object %s (with signature '%s') " -
1842 "on blocking mode", QString(message.member()).toLocal8Bit().constData(), QString(message.path()).toLocal8Bit().constData(), -
1843 QString(message.signature()).toLocal8Bit().constData()); -
1844 return QDBusMessage::createError( -
1845 QDBusError(QDBusError::InternalError, -
1846 QLatin1String("local-loop message cannot have delayed replies")));
-
1847 } -
1848 -
1849 -
1850 if (!::isDebugging); else QMessageLogger("qdbusintegrator.cpp", 1980, __PRETTY_FUNCTION__).debug() << this << "got message via local-loop:" << localReplyMsg;
-
1851 return localReplyMsg;
-
1852} -
1853 -
1854QDBusPendingCallPrivate *QDBusConnectionPrivate::sendWithReplyAsync(const QDBusMessage &message, -
1855 int timeout) -
1856{ -
1857 if (isServiceRegisteredByThread(message.service())) {
-
1858 -
1859 QDBusPendingCallPrivate *pcall = new QDBusPendingCallPrivate(message, this); -
1860 pcall->replyMessage = sendWithReplyLocal(message); -
1861 -
1862 return pcall;
-
1863 } -
1864 -
1865 checkThread(); -
1866 QDBusPendingCallPrivate *pcall = new QDBusPendingCallPrivate(message, this); -
1867 pcall->ref.store(0); -
1868 -
1869 QDBusError error; -
1870 DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message, capabilities, &error); -
1871 if (!msg) {
-
1872 QMessageLogger("qdbusintegrator.cpp", 2002, __PRETTY_FUNCTION__).warning("QDBusConnection: error: could not send message to service \"%s\" path \"%s\" interface \"%s\" member \"%s\": %s", -
1873 QString(message.service()).toLocal8Bit().constData(), QString(message.path()).toLocal8Bit().constData(), -
1874 QString(message.interface()).toLocal8Bit().constData(), QString(message.member()).toLocal8Bit().constData(), -
1875 QString(error.message()).toLocal8Bit().constData()); -
1876 pcall->replyMessage = QDBusMessage::createError(error); -
1877 lastError = error; -
1878 return pcall;
-
1879 } -
1880 -
1881 if (!::isDebugging); else QMessageLogger("qdbusintegrator.cpp", 2011, __PRETTY_FUNCTION__).debug() << this << "sending message (async):" << message;
-
1882 DBusPendingCall *pending = 0; -
1883 -
1884 QDBusDispatchLocker locker(SendWithReplyAsyncAction, this); -
1885 if (q_dbus_connection_send_with_reply(connection, msg, &pending, timeout)) {
-
1886 if (pending) {
-
1887 q_dbus_message_unref(msg); -
1888 -
1889 pcall->pending = pending; -
1890 q_dbus_pending_call_set_notify(pending, qDBusResultReceived, pcall, 0); -
1891 -
1892 return pcall;
-
1893 } else { -
1894 -
1895 lastError = error = QDBusError(QDBusError::Disconnected, QLatin1String("Not connected to server")); -
1896 }
-
1897 } else { -
1898 lastError = error = QDBusError(QDBusError::NoMemory, QLatin1String("Out of memory")); -
1899 }
-
1900 -
1901 q_dbus_message_unref(msg); -
1902 pcall->replyMessage = QDBusMessage::createError(error); -
1903 return pcall;
-
1904} -
1905 -
1906int QDBusConnectionPrivate::sendWithReplyAsync(const QDBusMessage &message, QObject *receiver, -
1907 const char *returnMethod, const char *errorMethod, -
1908 int timeout) -
1909{ -
1910 QDBusPendingCallPrivate *pcall = sendWithReplyAsync(message, timeout); -
1911 qt_noop(); -
1912 -
1913 -
1914 if (pcall->replyMessage.type() == QDBusMessage::ReplyMessage) {
-
1915 pcall->setReplyCallback(receiver, returnMethod); -
1916 processFinishedCall(pcall); -
1917 delete pcall; -
1918 return 1;
-
1919 } -
1920 -
1921 -
1922 if (errorMethod) {
-
1923 pcall->watcherHelper = new QDBusPendingCallWatcherHelper; -
1924 connect(pcall->watcherHelper, "2""error(QDBusError,QDBusMessage)", receiver, errorMethod, -
1925 Qt::QueuedConnection); -
1926 pcall->watcherHelper->moveToThread(thread()); -
1927 }
-
1928 -
1929 -
1930 if (pcall->replyMessage.type() == QDBusMessage::ErrorMessage) {
-
1931 processFinishedCall(pcall); -
1932 delete pcall; -
1933 return 1;
-
1934 } -
1935 -
1936 pcall->autoDelete = true; -
1937 pcall->ref.ref(); -
1938 pcall->setReplyCallback(receiver, returnMethod); -
1939 -
1940 return 1;
-
1941} -
1942 -
1943bool QDBusConnectionPrivate::connectSignal(const QString &service, -
1944 const QString &path, const QString &interface, const QString &name, -
1945 const QStringList &argumentMatch, const QString &signature, -
1946 QObject *receiver, const char *slot) -
1947{ -
1948 -
1949 QDBusConnectionPrivate::SignalHook hook; -
1950 QString key; -
1951 QString name2 = name; -
1952 if (name2.isNull())
-
1953 name2.detach();
-
1954 -
1955 hook.signature = signature; -
1956 if (!prepareHook(hook, key, service, path, interface, name, argumentMatch, receiver, slot, 0, false))
-
1957 return false;
-
1958 -
1959 -
1960 QDBusConnectionPrivate::SignalHookHash::ConstIterator it = signalHooks.constFind(key); -
1961 QDBusConnectionPrivate::SignalHookHash::ConstIterator end = signalHooks.constEnd(); -
1962 for ( ; it != end && it.key() == key; ++it) {
-
1963 const QDBusConnectionPrivate::SignalHook &entry = it.value(); -
1964 if (entry.service == hook.service &&
-
1965 entry.path == hook.path &&
-
1966 entry.signature == hook.signature &&
-
1967 entry.obj == hook.obj &&
-
1968 entry.midx == hook.midx &&
-
1969 entry.argumentMatch == hook.argumentMatch) {
-
1970 -
1971 return true;
-
1972 } -
1973 }
-
1974 -
1975 connectSignal(key, hook); -
1976 return true;
-
1977} -
1978 -
1979void QDBusConnectionPrivate::connectSignal(const QString &key, const SignalHook &hook) -
1980{ -
1981 signalHooks.insertMulti(key, hook); -
1982 connect(hook.obj, "2""destroyed(QObject*)", "1""objectDestroyed(QObject*)", -
1983 Qt::ConnectionType(Qt::DirectConnection | Qt::UniqueConnection)); -
1984 -
1985 MatchRefCountHash::iterator it = matchRefCounts.find(hook.matchRule); -
1986 -
1987 if (it != matchRefCounts.end()) {
-
1988 it.value() = it.value() + 1; -
1989 return;
-
1990 } -
1991 -
1992 matchRefCounts.insert(hook.matchRule, 1); -
1993 -
1994 if (connection) {
-
1995 if (mode != QDBusConnectionPrivate::PeerMode) {
-
1996 if (!::isDebugging); else QMessageLogger("qdbusintegrator.cpp", 2126, __PRETTY_FUNCTION__).debug("Adding rule: %s", hook.matchRule.constData());
-
1997 q_dbus_bus_add_match(connection, hook.matchRule, __null); -
1998 -
1999 -
2000 -
2001 if (shouldWatchService(hook.service)) {
-
2002 WatchedServicesHash::mapped_type &data = watchedServices[hook.service]; -
2003 if (++data.refcount == 1) {
-
2004 -
2005 connectSignal(dbusServiceString(), QString(), dbusInterfaceString(), -
2006 QLatin1String("NameOwnerChanged"), QStringList() << hook.service, QString(), -
2007 this, "1""serviceOwnerChangedNoLock(QString,QString,QString)"); -
2008 data.owner = getNameOwnerNoCache(hook.service); -
2009 if (!::isDebugging); else QMessageLogger("qdbusintegrator.cpp", 2139, __PRETTY_FUNCTION__).debug() << this << "Watching service" << hook.service << "for owner changes (current owner:"
-
2010 << data.owner << ")";
-
2011 } -
2012 }
-
2013 }
-
2014 }
-
2015}
-
2016 -
2017bool QDBusConnectionPrivate::disconnectSignal(const QString &service, -
2018 const QString &path, const QString &interface, const QString &name, -
2019 const QStringList &argumentMatch, const QString &signature, -
2020 QObject *receiver, const char *slot) -
2021{ -
2022 -
2023 QDBusConnectionPrivate::SignalHook hook; -
2024 QString key; -
2025 QString name2 = name; -
2026 if (name2.isNull())
-
2027 name2.detach();
-
2028 -
2029 hook.signature = signature; -
2030 if (!prepareHook(hook, key, service, path, interface, name, argumentMatch, receiver, slot, 0, false))
-
2031 return false;
-
2032 -
2033 -
2034 QDBusConnectionPrivate::SignalHookHash::Iterator it = signalHooks.find(key); -
2035 QDBusConnectionPrivate::SignalHookHash::Iterator end = signalHooks.end(); -
2036 for ( ; it != end && it.key() == key; ++it) {
-
2037 const QDBusConnectionPrivate::SignalHook &entry = it.value(); -
2038 if (entry.service == hook.service &&
-
2039 entry.path == hook.path &&
-
2040 entry.signature == hook.signature &&
-
2041 entry.obj == hook.obj &&
-
2042 entry.midx == hook.midx &&
-
2043 entry.argumentMatch == hook.argumentMatch) {
-
2044 -
2045 disconnectSignal(it); -
2046 return true;
-
2047 } -
2048 }
-
2049 -
2050 -
2051 return false;
-
2052} -
2053 -
2054QDBusConnectionPrivate::SignalHookHash::Iterator -
2055QDBusConnectionPrivate::disconnectSignal(SignalHookHash::Iterator &it) -
2056{ -
2057 const SignalHook &hook = it.value(); -
2058 -
2059 bool erase = false; -
2060 MatchRefCountHash::iterator i = matchRefCounts.find(hook.matchRule); -
2061 if (i == matchRefCounts.end()) {
-
2062 QMessageLogger("qdbusintegrator.cpp", 2192, __PRETTY_FUNCTION__).warning("QDBusConnectionPrivate::disconnectSignal: MatchRule not found in matchRefCounts!!"); -
2063 } else {
-
2064 if (i.value() == 1) {
-
2065 erase = true; -
2066 matchRefCounts.erase(i); -
2067 }
-
2068 else { -
2069 i.value() = i.value() - 1; -
2070 }
-
2071 } -
2072 -
2073 -
2074 if (connection && erase) {
-
2075 if (mode != QDBusConnectionPrivate::PeerMode) {
-
2076 if (!::isDebugging); else QMessageLogger("qdbusintegrator.cpp", 2206, __PRETTY_FUNCTION__).debug("Removing rule: %s", hook.matchRule.constData());
-
2077 q_dbus_bus_remove_match(connection, hook.matchRule, __null); -
2078 -
2079 -
2080 -
2081 WatchedServicesHash::Iterator sit = watchedServices.find(hook.service); -
2082 if (sit != watchedServices.end()) {
-
2083 if (--sit.value().refcount == 0) {
-
2084 watchedServices.erase(sit); -
2085 disconnectSignal(dbusServiceString(), QString(), dbusInterfaceString(), -
2086 QLatin1String("NameOwnerChanged"), QStringList() << hook.service, QString(), -
2087 this, "1""_q_serviceOwnerChanged(QString,QString,QString)"); -
2088 }
-
2089 }
-
2090 }
-
2091 -
2092 }
-
2093 -
2094 return signalHooks.erase(it);
-
2095} -
2096 -
2097void QDBusConnectionPrivate::registerObject(const ObjectTreeNode *node) -
2098{ -
2099 connect(node->obj, "2""destroyed(QObject*)", "1""objectDestroyed(QObject*)", -
2100 Qt::DirectConnection); -
2101 -
2102 if (node->flags & (QDBusConnection::ExportAdaptors -
2103 | QDBusConnection::ExportScriptableSignals -
2104 | QDBusConnection::ExportNonScriptableSignals)) {
-
2105 QDBusAdaptorConnector *connector = qDBusCreateAdaptorConnector(node->obj); -
2106 -
2107 if (node->flags & (QDBusConnection::ExportScriptableSignals -
2108 | QDBusConnection::ExportNonScriptableSignals)) {
-
2109 connector->disconnectAllSignals(node->obj); -
2110 connector->connectAllSignals(node->obj); -
2111 }
-
2112 -
2113 -
2114 connector->disconnect("2""relaySignal(QObject*,const QMetaObject*,int,QVariantList)", -
2115 this, "1""relaySignal(QObject*,const QMetaObject*,int,QVariantList)"); -
2116 connect(connector, "2""relaySignal(QObject*,const QMetaObject*,int,QVariantList)", -
2117 this, "1""relaySignal(QObject*,const QMetaObject*,int,QVariantList)", -
2118 Qt::DirectConnection); -
2119 }
-
2120}
-
2121 -
2122void QDBusConnectionPrivate::connectRelay(const QString &service, -
2123 const QString &path, const QString &interface, -
2124 QDBusAbstractInterface *receiver, -
2125 const QMetaMethod &signal) -
2126{ -
2127 -
2128 -
2129 SignalHook hook; -
2130 QString key; -
2131 -
2132 QByteArray sig; -
2133 sig.append(2 + '0'); -
2134 sig.append(signal.methodSignature()); -
2135 if (!prepareHook(hook, key, service, path, interface, QString(), QStringList(), receiver, sig, -
2136 QDBusAbstractInterface::staticMetaObject.methodCount(), true))
-
2137 return;
-
2138 -
2139 -
2140 QDBusWriteLocker locker(ConnectRelayAction, this); -
2141 SignalHookHash::ConstIterator it = signalHooks.constFind(key); -
2142 SignalHookHash::ConstIterator end = signalHooks.constEnd(); -
2143 for ( ; it != end && it.key() == key; ++it) {
-
2144 const SignalHook &entry = it.value(); -
2145 if (entry.service == hook.service &&
-
2146 entry.path == hook.path &&
-
2147 entry.signature == hook.signature &&
-
2148 entry.obj == hook.obj &&
-
2149 entry.midx == hook.midx)
-
2150 return;
-
2151 }
-
2152 -
2153 connectSignal(key, hook); -
2154}
-
2155 -
2156void QDBusConnectionPrivate::disconnectRelay(const QString &service, -
2157 const QString &path, const QString &interface, -
2158 QDBusAbstractInterface *receiver, -
2159 const QMetaMethod &signal) -
2160{ -
2161 -
2162 -
2163 SignalHook hook; -
2164 QString key; -
2165 -
2166 QByteArray sig; -
2167 sig.append(2 + '0'); -
2168 sig.append(signal.methodSignature()); -
2169 if (!prepareHook(hook, key, service, path, interface, QString(), QStringList(), receiver, sig, -
2170 QDBusAbstractInterface::staticMetaObject.methodCount(), true))
-
2171 return;
-
2172 -
2173 -
2174 QDBusWriteLocker locker(DisconnectRelayAction, this); -
2175 SignalHookHash::Iterator it = signalHooks.find(key); -
2176 SignalHookHash::Iterator end = signalHooks.end(); -
2177 for ( ; it != end && it.key() == key; ++it) {
-
2178 const SignalHook &entry = it.value(); -
2179 if (entry.service == hook.service &&
-
2180 entry.path == hook.path &&
-
2181 entry.signature == hook.signature &&
-
2182 entry.obj == hook.obj &&
-
2183 entry.midx == hook.midx) {
-
2184 -
2185 disconnectSignal(it); -
2186 return;
-
2187 } -
2188 }
-
2189 -
2190 QMessageLogger("qdbusintegrator.cpp", 2320, __PRETTY_FUNCTION__).warning("QDBusConnectionPrivate::disconnectRelay called for a signal that was not found"); -
2191}
-
2192 -
2193QString QDBusConnectionPrivate::getNameOwner(const QString& serviceName) -
2194{ -
2195 if (QDBusUtil::isValidUniqueConnectionName(serviceName))
-
2196 return serviceName;
-
2197 if (!connection)
-
2198 return QString();
-
2199 -
2200 { -
2201 -
2202 QReadLocker locker(&lock); -
2203 WatchedServicesHash::ConstIterator it = watchedServices.constFind(serviceName); -
2204 if (it != watchedServices.constEnd())
-
2205 return it->owner;
-
2206 } -
2207 -
2208 -
2209 return getNameOwnerNoCache(serviceName);
-
2210} -
2211 -
2212QString QDBusConnectionPrivate::getNameOwnerNoCache(const QString &serviceName) -
2213{ -
2214 QDBusMessage msg = QDBusMessage::createMethodCall(dbusServiceString(), -
2215 QLatin1String("/org/freedesktop/DBus"), dbusInterfaceString(), -
2216 QLatin1String("GetNameOwner")); -
2217 QDBusMessagePrivate::setParametersValidated(msg, true); -
2218 msg << serviceName; -
2219 QDBusMessage reply = sendWithReply(msg, QDBus::Block); -
2220 if (reply.type() == QDBusMessage::ReplyMessage)
-
2221 return reply.arguments().at(0).toString();
-
2222 return QString();
-
2223} -
2224 -
2225QDBusMetaObject * -
2226QDBusConnectionPrivate::findMetaObject(const QString &service, const QString &path, -
2227 const QString &interface, QDBusError &error) -
2228{ -
2229 -
2230 if (!interface.isEmpty()) {
-
2231 QDBusReadLocker locker(FindMetaObject1Action, this); -
2232 QDBusMetaObject *mo = cachedMetaObjects.value(interface, 0); -
2233 if (mo)
-
2234 return mo;
-
2235 }
-
2236 -
2237 -
2238 QDBusMessage msg = QDBusMessage::createMethodCall(service, path, -
2239 QLatin1String("org.freedesktop.DBus.Introspectable"), -
2240 QLatin1String("Introspect")); -
2241 QDBusMessagePrivate::setParametersValidated(msg, true); -
2242 -
2243 QDBusMessage reply = sendWithReply(msg, QDBus::Block); -
2244 -
2245 -
2246 QDBusWriteLocker locker(FindMetaObject2Action, this); -
2247 QDBusMetaObject *mo = 0; -
2248 if (!interface.isEmpty())
-
2249 mo = cachedMetaObjects.value(interface, 0);
-
2250 if (mo)
-
2251 -
2252 return mo;
-
2253 -
2254 QString xml; -
2255 if (reply.type() == QDBusMessage::ReplyMessage) {
-
2256 if (reply.signature() == QLatin1String("s"))
-
2257 -
2258 xml = reply.arguments().at(0).toString();
-
2259 } else {
-
2260 error = QDBusError(reply); -
2261 lastError = error; -
2262 if (reply.type() != QDBusMessage::ErrorMessage || error.type() != QDBusError::UnknownMethod)
-
2263 return 0;
-
2264 }
-
2265 -
2266 -
2267 QDBusMetaObject *result = QDBusMetaObject::createMetaObject(interface, xml, -
2268 cachedMetaObjects, error); -
2269 lastError = error; -
2270 return result;
-
2271} -
2272 -
2273void QDBusConnectionPrivate::registerService(const QString &serviceName) -
2274{ -
2275 QDBusWriteLocker locker(RegisterServiceAction, this); -
2276 registerServiceNoLock(serviceName); -
2277}
-
2278 -
2279void QDBusConnectionPrivate::registerServiceNoLock(const QString &serviceName) -
2280{ -
2281 serviceNames.append(serviceName); -
2282}
-
2283 -
2284void QDBusConnectionPrivate::unregisterService(const QString &serviceName) -
2285{ -
2286 QDBusWriteLocker locker(UnregisterServiceAction, this); -
2287 unregisterServiceNoLock(serviceName); -
2288}
-
2289 -
2290void QDBusConnectionPrivate::unregisterServiceNoLock(const QString &serviceName) -
2291{ -
2292 serviceNames.removeAll(serviceName); -
2293}
-
2294 -
2295bool QDBusConnectionPrivate::isServiceRegisteredByThread(const QString &serviceName) const -
2296{ -
2297 if (!serviceName.isEmpty() && serviceName == baseService)
-
2298 return true;
-
2299 QStringList copy = serviceNames; -
2300 return copy.contains(serviceName);
-
2301} -
2302 -
2303void QDBusConnectionPrivate::postEventToThread(int action, QObject *object, QEvent *ev) -
2304{ -
2305 QDBusLockerBase::reportThreadAction(action, QDBusLockerBase::BeforePost, this); -
2306 QCoreApplication::postEvent(object, ev); -
2307 QDBusLockerBase::reportThreadAction(action, QDBusLockerBase::AfterPost, this); -
2308}
-
2309 -
2310 -
2311 -
Switch to Source codePreprocessed file

Generated by Squish Coco Non-Commercial