void ObjectEndPoint::propertyCall(const QServicePackage& p) { if(p.d->responseType == QServicePackage::NotAResponse) { //service side Q_ASSERT(d->endPointType == ObjectEndPoint::Service); QByteArray data = p.d->payload.toByteArray(); QDataStream stream(&data, QIODevice::ReadOnly); int metaIndex = -1; QVariant arg; int callType; stream >> metaIndex; stream >> arg; stream >> callType; const QMetaObject::Call c = (QMetaObject::Call) callType; QVariant result; QMetaProperty property = service->metaObject()->property(metaIndex); if (property.isValid()) { switch(c) { case QMetaObject::ReadProperty: result = property.read(service); break; case QMetaObject::WriteProperty: property.write(service, arg); break; case QMetaObject::ResetProperty: property.reset(service); break; default: break; } } if (c == QMetaObject::ReadProperty) { QServicePackage response = p.createResponse(); if (property.isValid()) { response.d->responseType = QServicePackage::Success; response.d->payload = result; } else { response.d->responseType = QServicePackage::Failed; } dispatch->writePackage(response); } } else {
/*! Service finds existing objects or spawns new object instances and registers them on DBus using a hash of the unique instance ID. This registered object has a special metaobject representation of the service that is compatible with the QDBus type system. Client receives a package containing the information to connect an interface to the registered DBus object. */ void ObjectEndPoint::objectRequest(const QServicePackage& p, QServiceClientCredentials& creds) { if (p.d->responseType != QServicePackage::NotAResponse ) { // Client side Q_ASSERT(d->endPointType == ObjectEndPoint::Client); d->serviceInstanceId = p.d->instanceId; d->entry = p.d->entry; Response* response = openRequests()->value(p.d->messageId); if (p.d->responseType == QServicePackage::Failed) { response->result = 0; response->isFinished = true; QTimer::singleShot(0, this, SIGNAL(pendingRequestFinished())); qWarning() << "Service instantiation failed"; return; } // Deserialize meta object and create proxy object QServiceProxy* proxy = new QServiceProxy(p.d->payload.toByteArray(), this); response->result = reinterpret_cast<void *>(proxy); response->isFinished = true; // Create DBUS interface by using a hash of the service instance ID QString serviceName = QStringLiteral("com.nokia.qtmobility.sfw.") + p.d->entry.serviceName(); uint hash = qHash(d->serviceInstanceId.toString()); QString objPath = QLatin1Char('/') + p.d->entry.interfaceName() + QLatin1Char('/') + p.d->entry.version() + QLatin1Char('/') + QString::number(hash); objPath.replace(QLatin1Char('.'), QLatin1Char('/')); #ifdef DEBUG qDebug() << "Client Interface ObjectPath:" << objPath; #endif // Instantiate our DBus interface and its corresponding signals object if (!iface) iface = new QDBusInterface(serviceName, objPath, QString(), QDBusConnection::sessionBus(), this); signalsObject = new QServiceMetaObjectDBus(iface, true); // Wake up waiting proxy construction code QTimer::singleShot(0, this, SIGNAL(pendingRequestFinished())); } else { // Service side Q_ASSERT(d->endPointType == ObjectEndPoint::Service); QServicePackage response = p.createResponse(); InstanceManager* iManager = InstanceManager::instance(); if (!creds.isValid()) { qWarning() << "SFW Unable to get socket credentials client asking for" << p.d->entry.interfaceName() << p.d->entry.serviceName() << "this may fail in the future"; } // Instantiate service object from type register service = iManager->createObjectInstance(p.d->entry, d->serviceInstanceId, creds); if (!service) { qWarning() << "Cannot instantiate service object"; dispatch->writePackage(response); return; } if (!creds.isClientAccepted()) { qWarning() << "SFW Security failure by" << creds.getProcessIdentifier() << creds.getUserIdentifier() << creds.getGroupIdentifier() << "requesting" << p.d->entry.interfaceName() << p.d->entry.serviceName(); iManager->removeObjectInstance(p.d->entry, d->serviceInstanceId); dispatch->writePackage(response); return; } // Start DBus connection and register proxy service if (!QDBusConnection::sessionBus().isConnected()) { qWarning() << "Cannot connect to DBus"; } // DBus registration path uses a hash of the service instance ID QString serviceName = QStringLiteral("com.nokia.qtmobility.sfw.") + p.d->entry.serviceName(); uint hash = qHash(d->serviceInstanceId.toString()); QString objPath = QLatin1Char('/') + p.d->entry.interfaceName() + QLatin1Char('/') + p.d->entry.version() + QLatin1Char('/') + QString::number(hash); objPath.replace(QLatin1Char('.'), QLatin1Char('/')); QServiceMetaObjectDBus *serviceDBus = new QServiceMetaObjectDBus(service); QDBusConnection::sessionBus().registerObject(objPath, serviceDBus, QDBusConnection::ExportAllContents); QString clientId = p.d->payload.toString(); int exists = 0; for (int i=d->clientList.size()-1; i>=0; i--) { // Find right client process if (d->clientList[i].clientId == clientId) { d->clientList[i].ref++; exists = 1; break; } } if (!exists) { // Add new instance to client ownership list ClientInstance c; c.clientId = clientId; c.entry = p.d->entry; c.instanceId = d->serviceInstanceId; c.ref = 1; d->clientList << c; } #ifdef DEBUG qDebug() << "Service Interface ObjectPath:" << objPath; const QMetaObject *s_meta = service->metaObject(); qDebug() << "+++++++++++++++++++++SERVICE+++++++++++++++++++++++"; qDebug() << s_meta->className(); qDebug() << "METHOD COUNT: " << s_meta->methodCount(); for (int i=0; i<s_meta->methodCount(); i++) { QMetaMethod mm = s_meta->method(i); QString type; switch (mm.methodType()) { case QMetaMethod::Method: type = "Q_INVOKABLE"; break; case QMetaMethod::Signal: type = "SIGNAL"; break; case QMetaMethod::Slot: type = "SLOT"; break; default: break; } QString returnType = mm.typeName(); if (returnType == "") returnType = "void"; qDebug() << "METHOD" << type << ":" << returnType << mm.methodSignature(); } qDebug() << "++++++++++++++++++++++++++++++++++++++++++++++++++++"; if (!iface) iface = new QDBusInterface(serviceName, objPath, "", QDBusConnection::sessionBus(), this); const QMetaObject *i_meta = iface->metaObject(); qDebug() << "++++++++++++++++++++DBUS SERVICE++++++++++++++++++++"; qDebug() << i_meta->className(); qDebug() << "METHOD COUNT: " << i_meta->methodCount(); for (int i=0; i<i_meta->methodCount(); i++) { QMetaMethod mm = i_meta->method(i); QString type; switch (mm.methodType()) { case QMetaMethod::Method: type = "Q_INVOKABLE"; break; case QMetaMethod::Signal: type = "SIGNAL"; break; case QMetaMethod::Slot: type = "SLOT"; break; default: break; } QString returnType = mm.typeName(); if (returnType == "") returnType = "void"; qDebug() << "METHOD" << type << ":" << returnType << mm.methodSignature(); } qDebug() << "+++++++++++++++++++++++++++++++++++++++++++++++++++"; #endif // Get meta object from type register const QMetaObject* meta = iManager->metaObject(p.d->entry); if (!meta) { qDebug() << "Unknown type" << p.d->entry; dispatch->writePackage(response); return; } // Serialize meta object QByteArray data; QDataStream stream( &data, QIODevice::WriteOnly | QIODevice::Append ); QMetaObjectBuilder builder(meta); builder.serialize(stream); // Send meta object and instance ID to the client for processing d->entry = p.d->entry; response.d->instanceId = d->serviceInstanceId; response.d->entry = p.d->entry; response.d->responseType = QServicePackage::Success; response.d->payload = QVariant(data); dispatch->writePackage(response); } }