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> &params){    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 + -
显示快捷键?