qdbusintegrator.cpp
来自「奇趣公司比较新的qt/emd版本」· C++ 代码 · 共 1,726 行 · 第 1/5 页
CPP
1,726 行
else ++sit; } obj->disconnect(this);}void QDBusConnectionPrivate::relaySignal(QObject *obj, const QMetaObject *mo, int signalId, const QVariantList &args){ int mciid = mo->indexOfClassInfo(QCLASSINFO_DBUS_INTERFACE); Q_ASSERT(mciid != -1); QMetaClassInfo mci = mo->classInfo(mciid); Q_ASSERT(mci.value()); const char *interface = mci.value(); QMetaMethod mm = mo->method(signalId); QByteArray memberName = mm.signature(); memberName.truncate(memberName.indexOf('(')); // check if it's scriptable bool isScriptable = mm.attributes() & QMetaMethod::Scriptable; bool isAdaptor = false; for ( ; mo; mo = mo->superClass()) if (mo == &QDBusAbstractAdaptor::staticMetaObject) { isAdaptor = true; break; } QDBusReadLocker locker(RelaySignalAction, this); QDBusMessage message = QDBusMessage::createSignal(QLatin1String("/"), QLatin1String(interface), QLatin1String(memberName)); message.setArguments(args); DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message); if (!msg) { qWarning("QDBusConnection: Could not emit signal %s.%s", interface, memberName.constData()); return; } //qDBusDebug() << "Emitting signal" << message; //qDBusDebug() << "for paths:"; dbus_message_set_no_reply(msg, true); // the reply would not be delivered to anything huntAndEmit(connection, msg, obj, rootNode, isScriptable, isAdaptor); dbus_message_unref(msg);}void QDBusConnectionPrivate::_q_serviceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner){ if (oldOwner == baseService) unregisterService(name); if (newOwner == baseService) registerService(name); QDBusWriteLocker locker(UpdateSignalHookOwnerAction, this); QMutableHashIterator<QString, SignalHook> it(signalHooks); it.toFront(); while (it.hasNext()) if (it.next().value().service == name) it.value().owner = newOwner;}int QDBusConnectionPrivate::findSlot(QObject* obj, const QByteArray &normalizedName, QList<int> ¶ms){ int midx = obj->metaObject()->indexOfMethod(normalizedName); if (midx == -1) return -1; int inputCount = qDBusParametersForMethod(obj->metaObject()->method(midx), params); if ( inputCount == -1 || inputCount + 1 != params.count() ) return -1; // failed to parse or invalid arguments or output arguments return midx;}bool QDBusConnectionPrivate::prepareHook(QDBusConnectionPrivate::SignalHook &hook, QString &key, const QString &service, const QString &owner, const QString &path, const QString &interface, const QString &name, QObject *receiver, const char *signal, int minMIdx, bool buildSignature){ QByteArray normalizedName = signal + 1; hook.midx = findSlot(receiver, signal + 1, hook.params); if (hook.midx == -1) { normalizedName = QMetaObject::normalizedSignature(signal + 1); hook.midx = findSlot(receiver, normalizedName, hook.params); } if (hook.midx < minMIdx) { if (hook.midx == -1) {} return false; } hook.service = service; hook.owner = owner; // we don't care if the service has an owner yet hook.path = path; hook.obj = receiver; // build the D-Bus signal name and signature // This should not happen for QDBusConnection::connect, use buildSignature here, since // QDBusConnection::connect passes false and everything else uses true QString mname = name; if (buildSignature && mname.isNull()) { normalizedName.truncate(normalizedName.indexOf('(')); mname = QString::fromUtf8(normalizedName); } key = mname; key.reserve(interface.length() + 1 + mname.length()); key += QLatin1Char(':'); key += interface; if (buildSignature) { hook.signature.clear(); for (int i = 1; i < hook.params.count(); ++i) if (hook.params.at(i) != QDBusMetaTypeId::message) hook.signature += QLatin1String( QDBusMetaType::typeToSignature( hook.params.at(i) ) ); } hook.matchRule = buildMatchRule(service, owner, path, interface, mname, hook.signature); return true; // connect to this signal}void QDBusConnectionPrivate::sendError(const QDBusMessage &msg, QDBusError::ErrorType code){ if (code == QDBusError::UnknownMethod) { QString interfaceMsg; if (msg.interface().isEmpty()) interfaceMsg = QLatin1String("any interface"); else interfaceMsg = QString::fromLatin1("interface '%1'").arg(msg.interface()); send(msg.createErrorReply(code, QString::fromLatin1("No such method '%1' in %2 at object path '%3' " "(signature '%4')") .arg(msg.member(), interfaceMsg, msg.path(), msg.signature()))); } else if (code == QDBusError::UnknownInterface) { send(msg.createErrorReply(QDBusError::UnknownInterface, QString::fromLatin1("No such interface '%1' at object path '%2'") .arg(msg.interface(), msg.path()))); } else if (code == QDBusError::UnknownObject) { send(msg.createErrorReply(QDBusError::UnknownObject, QString::fromLatin1("No such object path '%1'").arg(msg.path()))); }}bool QDBusConnectionPrivate::activateInternalFilters(const ObjectTreeNode &node, const QDBusMessage &msg){ // object may be null const QString interface = msg.interface(); if (interface.isEmpty() || interface == QLatin1String(DBUS_INTERFACE_INTROSPECTABLE)) { if (msg.member() == QLatin1String("Introspect") && msg.signature().isEmpty()) { //qDebug() << "QDBusConnectionPrivate::activateInternalFilters introspect" << msg.d_ptr->msg; QDBusMessage reply = msg.createReply(qDBusIntrospectObject(node)); send(reply); return true; } if (!interface.isEmpty()) { sendError(msg, QDBusError::UnknownMethod); return true; } } if (node.obj && (interface.isEmpty() || interface == QLatin1String(DBUS_INTERFACE_PROPERTIES))) { //qDebug() << "QDBusConnectionPrivate::activateInternalFilters properties" << msg.d_ptr->msg; if (msg.member() == QLatin1String("Get") && msg.signature() == QLatin1String("ss")) { QDBusMessage reply = qDBusPropertyGet(node, msg); send(reply); return true; } else if (msg.member() == QLatin1String("Set") && msg.signature() == QLatin1String("ssv")) { QDBusMessage reply = qDBusPropertySet(node, msg); send(reply); return true; } if (!interface.isEmpty()) { sendError(msg, QDBusError::UnknownMethod); return true; } } return false;}void QDBusConnectionPrivate::activateObject(ObjectTreeNode &node, const QDBusMessage &msg, int pathStartPos){ // This is called by QDBusConnectionPrivate::handleObjectCall to place a call to a slot // on the object. // // The call is routed through the adaptor sub-objects if we have any // object may be null if (pathStartPos != msg.path().length()) { node.flags &= ~QDBusConnection::ExportAllSignals; node.obj = findChildObject(&node, msg.path(), pathStartPos); if (!node.obj) { sendError(msg, QDBusError::UnknownObject); return; } } QDBusAdaptorConnector *connector; if (node.flags & QDBusConnection::ExportAdaptors && (connector = qDBusFindAdaptorConnector(node.obj))) { int newflags = node.flags | QDBusConnection::ExportAllSlots; if (msg.interface().isEmpty()) { // place the call in all interfaces // let the first one that handles it to work QDBusAdaptorConnector::AdaptorMap::ConstIterator it = connector->adaptors.constBegin(); QDBusAdaptorConnector::AdaptorMap::ConstIterator end = connector->adaptors.constEnd(); for ( ; it != end; ++it) if (activateCall(it->adaptor, newflags, msg)) return; } else { // check if we have an interface matching the name that was asked: QDBusAdaptorConnector::AdaptorMap::ConstIterator it; it = qLowerBound(connector->adaptors.constBegin(), connector->adaptors.constEnd(), msg.interface()); if (it != connector->adaptors.constEnd() && msg.interface() == QLatin1String(it->interface)) { if (!activateCall(it->adaptor, newflags, msg)) sendError(msg, QDBusError::UnknownMethod); return; } } } // no adaptors matched or were exported // try our standard filters if (activateInternalFilters(node, msg)) return; // internal filters have already run or an error has been sent // try the object itself: if (node.flags & (QDBusConnection::ExportScriptableSlots|QDBusConnection::ExportNonScriptableSlots)) { bool interfaceFound = true; if (!msg.interface().isEmpty()) interfaceFound = msg.interface() == qDBusInterfaceFromMetaObject(node.obj->metaObject()); if (interfaceFound) { if (!activateCall(node.obj, node.flags, msg)) sendError(msg, QDBusError::UnknownMethod); return; } } // nothing matched, send an error code if (msg.interface().isEmpty()) sendError(msg, QDBusError::UnknownMethod); else sendError(msg, QDBusError::UnknownInterface);}void QDBusConnectionPrivate::handleObjectCall(const QDBusMessage &msg){ // if the msg is external, we were called from inside doDispatch // that means the dispatchLock mutex is locked // must not call out to user code in that case // // however, if the message is internal, handleMessage was called // directly and no lock is in place. We can therefore call out to // user code, if necessary ObjectTreeNode result; int usedLength; QThread *objThread = 0; QSemaphore sem; bool semWait; { QDBusReadLocker locker(HandleObjectCallAction, this); if (!findObject(&rootNode, msg.path(), usedLength, result)) { // qDebug("Call failed: no object found at %s", qPrintable(msg.path())); sendError(msg, QDBusError::UnknownObject); return; } if (!result.obj) { // no object -> no threading issues // it's either going to be an error, or an internal filter activateObject(result, msg, usedLength); return; } objThread = result.obj->thread(); if (!objThread) { send(msg.createErrorReply(QDBusError::InternalError, QString::fromLatin1("Object '%1' (at path '%2')" " has no thread. Cannot deliver message.") .arg(result.obj->objectName(), msg.path()))); return; } if (!QDBusMessagePrivate::isLocal(msg)) { // external incoming message // post it and forget postEventToThread(HandleObjectCallPostEventAction, result.obj, new QDBusActivateObjectEvent(QDBusConnection(this), this, result, usedLength, msg)); return; } else if (objThread != QThread::currentThread()) { // synchronize with other thread postEventToThread(HandleObjectCallPostEventAction, result.obj, new QDBusActivateObjectEvent(QDBusConnection(this), this, result, usedLength, msg, &sem)); semWait = true; } else { semWait = false; } } // release the lock if (semWait) SEM_ACQUIRE(HandleObjectCallSemaphoreAction, sem); else activateObject(result, msg, usedLength);}QDBusActivateObjectEvent::~QDBusActivateObjectEvent(){ if (!handled) { // we're being destroyed without delivering // it means the object was deleted between posting and delivering QDBusConnectionPrivate *that = QDBusConnectionPrivate::d(connection); that->sendError(message, QDBusError::UnknownObject); } // semaphore releasing happens in ~QMetaCallEvent}int QDBusActivateObjectEvent::placeMetaCall(QObject *){ QDBusConnectionPrivate *that = QDBusConnectionPrivate::d(connection); QDBusLockerBase::reportThreadAction(HandleObjectCallPostEventAction, QDBusLockerBase::BeforeDeliver, that); that->activateObject(node, message, pathStartPos); QDBusLockerBase::reportThreadAction(HandleObjectCallPostEventAction, QDBusLockerBase::AfterDeliver, that);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?