summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvan Nguyen <evan.nguyen@nokia.com>2010-07-14 14:12:28 +1000
committerEvan Nguyen <evan.nguyen@nokia.com>2010-07-14 14:29:45 +1000
commit748905bc110ec05b22edca052d6058fc82b98b0b (patch)
treed46842a20bb08bcad0ec0a9ea5bef662b4b17428
parent0def0c80661a6e8573a43ab6301ab06fe4e67117 (diff)
DBus backend publish services on DBUS for direct use
(cherry picked from commit c5d5c874b116d2f4d1e5f6268a6b93563e34168d)
-rw-r--r--src/serviceframework/ipc/ipc.pri20
-rw-r--r--src/serviceframework/ipc/objectendpoint_dbus.cpp710
-rw-r--r--src/serviceframework/ipc/objectendpoint_dbus_p.h101
-rw-r--r--src/serviceframework/ipc/proxyobject_dbus.cpp254
-rw-r--r--src/serviceframework/ipc/proxyobject_dbus_p.h76
-rw-r--r--src/serviceframework/ipc/qremoteservicecontrol_dbus_p.cpp75
-rw-r--r--src/serviceframework/ipc/qservicepackage.cpp3
-rw-r--r--src/serviceframework/ipc/qservicepackage_p.h6
-rw-r--r--tests/auto/qservicemanager_ipc/client/tst_qservicemanager_ipc.cpp18
-rw-r--r--tests/auto/qservicemanager_ipc/service/main.cpp1
10 files changed, 1204 insertions, 60 deletions
diff --git a/src/serviceframework/ipc/ipc.pri b/src/serviceframework/ipc/ipc.pri
index 57ba7fae5d..911ba503e5 100644
--- a/src/serviceframework/ipc/ipc.pri
+++ b/src/serviceframework/ipc/ipc.pri
@@ -8,14 +8,22 @@ symbian {
contains(QT_CONFIG,dbus) {
QT += dbus network
- PRIVATE_HEADERS += ipc/qremoteservicecontrol_dbus_p.h
- SOURCES += ipc/qremoteservicecontrol_dbus_p.cpp
+ PRIVATE_HEADERS += ipc/qremoteservicecontrol_dbus_p.h \
+ ipc/objectendpoint_dbus_p.h \
+ ipc/proxyobject_dbus_p.h
+ SOURCES += ipc/qremoteservicecontrol_dbus_p.cpp \
+ ipc/objectendpoint_dbus.cpp \
+ ipc/proxyobject_dbus.cpp
} else {
QT += network
- PRIVATE_HEADERS += ipc/qremoteservicecontrol_p.h
- SOURCES += ipc/qremoteservicecontrol_p.cpp
+ PRIVATE_HEADERS += ipc/qremoteservicecontrol_p.h \
+ ipc/objectendpoint_p.h \
+ ipc/proxyobject_p.h
+ SOURCES += ipc/qremoteservicecontrol_p.cpp \
+ ipc/objectendpoint.cpp \
+ ipc/proxyobject.cpp
}
}
@@ -25,9 +33,7 @@ PRIVATE_HEADERS += \
ipc/qmetaobjectbuilder_p.h \
ipc/instancemanager_p.h \
ipc/qservicepackage_p.h \
- ipc/objectendpoint_p.h \
ipc/ipcendpoint_p.h \
- ipc/proxyobject_p.h
SOURCES += \
ipc/qslotinvoker.cpp \
@@ -35,6 +41,4 @@ SOURCES += \
ipc/qmetaobjectbuilder.cpp \
ipc/instancemanager.cpp \
ipc/qservicepackage.cpp \
- ipc/objectendpoint.cpp \
ipc/ipcendpoint.cpp \
- ipc/proxyobject.cpp
diff --git a/src/serviceframework/ipc/objectendpoint_dbus.cpp b/src/serviceframework/ipc/objectendpoint_dbus.cpp
new file mode 100644
index 0000000000..9a75eb1fe9
--- /dev/null
+++ b/src/serviceframework/ipc/objectendpoint_dbus.cpp
@@ -0,0 +1,710 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "objectendpoint_dbus_p.h"
+#include "instancemanager_p.h"
+#include "qmetaobjectbuilder_p.h"
+#include "proxyobject_dbus_p.h"
+#include "qsignalintercepter_p.h"
+#include <QTimer>
+#include <QEventLoop>
+#include <QVarLengthArray>
+
+QTM_BEGIN_NAMESPACE
+
+class Response
+{
+public:
+ Response() : isFinished(false), result(0)
+ { }
+
+ bool isFinished;
+ void* result;
+};
+
+typedef QHash<QUuid, Response*> Replies;
+Q_GLOBAL_STATIC(Replies, openRequests);
+
+class ServiceSignalIntercepter : public QSignalIntercepter
+{
+ //Do not put Q_OBJECT here
+public:
+ ServiceSignalIntercepter(QObject* sender, const QByteArray& signal,
+ ObjectEndPoint* parent)
+ : QSignalIntercepter(sender, signal, parent), endPoint(parent)
+ {
+
+ }
+
+ void setMetaIndex(int index)
+ {
+ metaIndex = index;
+ }
+
+protected:
+ void activated( const QList<QVariant>& args )
+ {
+ endPoint->invokeRemote(metaIndex, args, QMetaType::Void);
+ }
+private:
+ ObjectEndPoint* endPoint;
+ int metaIndex;
+
+};
+
+class ObjectEndPointPrivate
+{
+public:
+ ObjectEndPointPrivate()
+ {
+ }
+
+ ~ObjectEndPointPrivate()
+ {
+ }
+
+ //service side
+ void setupSignalIntercepters(QObject * service)
+ {
+ Q_ASSERT(endPointType == ObjectEndPoint::Service);
+
+ //create a signal intercepter for each signal
+ //offered by service
+ //exclude QObject signals
+ const QMetaObject* mo = service->metaObject();
+ while (mo && strcmp(mo->className(), "QObject"))
+ {
+ for (int i = mo->methodOffset(); i < mo->methodCount(); ++i) {
+ const QMetaMethod method = mo->method(i);
+ if (method.methodType() == QMetaMethod::Signal) {
+ QByteArray signal = method.signature();
+ //add '2' for signal - see QSIGNAL_CODE
+ ServiceSignalIntercepter* intercept =
+ new ServiceSignalIntercepter(service, "2"+signal, parent );
+ intercept->setMetaIndex(i);
+ }
+ }
+ mo = mo->superClass();
+ }
+ }
+
+ /*!
+ Activate slots connected to given signal. Unfortunately we can only do this
+ using the signal index relative to the meta object defining the signal.
+ */
+ int triggerConnectedSlots(QObject* service, const QMetaObject* meta, int id, void **args)
+ {
+ Q_ASSERT(endPointType == ObjectEndPoint::Client);
+
+ const QMetaObject* parentMeta = meta->superClass();
+ if (parentMeta)
+ id = triggerConnectedSlots(service, parentMeta, id, args);
+
+ if (id < 0)
+ return id;
+
+ const int methodsThisType = meta->methodCount() - meta->methodOffset();
+ if (id >= 0 && id < methodsThisType)
+ QMetaObject::activate(service, meta, id, args);
+
+ id -= methodsThisType;
+ return id;
+ }
+
+ //used on client and service side
+ ObjectEndPoint::Type endPointType;
+ ObjectEndPoint* parent;
+
+ //used on service side
+ QRemoteServiceIdentifier typeIdent;
+ QUuid serviceInstanceId;
+};
+
+//TODO list:
+/*
+ - Why do we need typeIdent and serviceInstanceId on service side. The instance id should be sufficient.
+ - Consider merging invokeRemoteProperty() and invokeRemote()
+ - QMetaClassInfo support
+
+*/
+
+ObjectEndPoint::ObjectEndPoint(Type type, QServiceIpcEndPoint* comm, QObject* parent)
+ : QObject(parent), dispatch(comm), service(0)
+{
+ Q_ASSERT(dispatch);
+ d = new ObjectEndPointPrivate;
+ d->parent = this;
+ d->endPointType = type;
+
+ dispatch->setParent(this);
+ connect(dispatch, SIGNAL(readyRead()), this, SLOT(newPackageReady()));
+ connect(dispatch, SIGNAL(disconnected()), this, SLOT(disconnected()));
+ if (type == Client) {
+ return; //we are waiting for conctructProxy() call
+ } else {
+ if (dispatch->packageAvailable())
+ QTimer::singleShot(0, this, SLOT(newPackageReady()));
+ }
+}
+
+ObjectEndPoint::~ObjectEndPoint()
+{
+ if (d->endPointType == Service) {
+ InstanceManager::instance()->removeObjectInstance(d->typeIdent, d->serviceInstanceId);
+ }
+
+ delete d;
+}
+
+void ObjectEndPoint::disconnected()
+{
+ deleteLater();
+}
+
+/*!
+ Client requests proxy object. The proxy is owned by calling
+ code and this object must clean itself up upon destruction of
+ proxy.
+*/
+QObject* ObjectEndPoint::constructProxy(const QRemoteServiceIdentifier& ident)
+{
+ //client side
+ Q_ASSERT(d->endPointType == ObjectEndPoint::Client);
+
+ //ask for serialized meta object
+ //get proxy based on meta object
+ //return meta object
+ QServicePackage p;
+ p.d = new QServicePackagePrivate();
+ p.d->messageId = QUuid::createUuid();
+ p.d->typeId = ident;
+
+ Response* response = new Response();
+ openRequests()->insert(p.d->messageId, response);
+
+ dispatch->writePackage(p);
+ waitForResponse(p.d->messageId);
+
+ if (response->isFinished) {
+ if (response->result == 0)
+ qWarning() << "Request for remote service failed";
+ else
+ service = reinterpret_cast<QServiceProxy* >(response->result);
+ } else {
+ qDebug() << "response passed but not finished";
+ }
+
+ openRequests()->take(p.d->messageId);
+ delete response;
+
+ return service;
+}
+
+void ObjectEndPoint::newPackageReady()
+{
+ //client and service side
+
+ while(dispatch->packageAvailable())
+ {
+ QServicePackage p = dispatch->nextPackage();
+ if (!p.isValid())
+ continue;
+
+ switch(p.d->packageType) {
+ case QServicePackage::ObjectCreation:
+ objectRequest(p);
+ break;
+ case QServicePackage::MethodCall:
+ methodCall(p);
+ break;
+ case QServicePackage::PropertyCall:
+ propertyCall(p);
+ break;
+ default:
+ qWarning() << "Unknown package type received.";
+ }
+ }
+}
+
+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 {
+ //client side
+ Q_ASSERT(d->endPointType == ObjectEndPoint::Client);
+
+
+ Response* response = openRequests()->value(p.d->messageId);
+ response->isFinished = true;
+ if (p.d->responseType == QServicePackage::Failed) {
+ response->result = 0;
+ QTimer::singleShot(0, this, SIGNAL(pendingRequestFinished()));
+ qWarning() << "Service method call failed";
+ return;
+ }
+ QVariant* variant = new QVariant(p.d->payload);
+ response->result = reinterpret_cast<void *>(variant);
+
+ QTimer::singleShot(0, this, SIGNAL(pendingRequestFinished()));
+ }
+}
+
+QUuid ObjectEndPoint::myInstanceID()
+{
+ return d->serviceInstanceId;
+}
+
+void ObjectEndPoint::objectRequest(const QServicePackage& p)
+{
+ if (p.d->responseType != QServicePackage::NotAResponse ) {
+ //client side
+ Q_ASSERT(d->endPointType == ObjectEndPoint::Client);
+
+ d->serviceInstanceId = p.d->instanceId;
+
+ qDebug() << "MY UUID IS" << d->serviceInstanceId;
+
+ 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);
+ //QServiceProxy* proxy = new QServiceProxy(p.d->typeId, p.d->payload.toByteArray(), this);
+ response->result = reinterpret_cast<void *>(proxy);
+ response->isFinished = true;
+
+ //Create DBUS interface
+ QString serviceName = "com.nokia.qtmobility.sfw." + p.d->typeId.name;
+ uint hash = qHash(d->serviceInstanceId.toString());
+ QString objPath = "/" + p.d->typeId.interface + "/" + p.d->typeId.version + "/" + QString::number(hash);
+ objPath.replace(QString("."), QString("/"));
+
+ qDebug() << "CLIENT PATH: " << objPath;
+
+ iface = new QDBusInterface(serviceName, objPath, "", QDBusConnection::sessionBus());
+
+ //wake up waiting code
+ QTimer::singleShot(0, this, SIGNAL(pendingRequestFinished()));
+
+ } else {
+ //service side
+ Q_ASSERT(d->endPointType == ObjectEndPoint::Service);
+
+ QServicePackage response = p.createResponse();
+ InstanceManager* m = InstanceManager::instance();
+
+ //get meta object from type register
+ const QMetaObject* meta = m->metaObject(p.d->typeId);
+ if (!meta) {
+ qDebug() << "Unknown type" << p.d->typeId;
+ dispatch->writePackage(response);
+ return;
+ }
+
+ //serialize meta object
+ QByteArray data;
+ QDataStream stream( &data, QIODevice::WriteOnly | QIODevice::Append );
+ QMetaObjectBuilder builder(meta);
+ builder.serialize(stream);
+
+ //instantiate service object from type register
+ service = m->createObjectInstance(p.d->typeId, d->serviceInstanceId);
+ if (!service) {
+ qWarning() << "Cannot instanciate service object";
+ dispatch->writePackage(response);
+ return;
+ }
+ d->setupSignalIntercepters(service);
+
+ // DBUSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
+ QDBusConnection *connection = new QDBusConnection(QDBusConnection::sessionBus());
+ if (!connection->isConnected()) {
+ qWarning() << "Cannot connect to DBus";
+ }
+
+ // Register proxy service to DBus
+ QString serviceName = "com.nokia.qtmobility.sfw." + p.d->typeId.name;
+ uint hash = qHash(d->serviceInstanceId.toString());
+ QString objPath = "/" + p.d->typeId.interface + "/" + p.d->typeId.version + "/" + QString::number(hash);
+ objPath.replace(QString("."), QString("/"));
+
+ qDebug() << "SERVICE PATH: " << objPath;
+
+ connection->registerObject(objPath, service, QDBusConnection::ExportAllSlots |
+ QDBusConnection::ExportAllProperties |
+ QDBusConnection::ExportAllSignals |
+ QDBusConnection::ExportAllContents);
+
+ iface = new QDBusInterface(serviceName, objPath, "", QDBusConnection::sessionBus());
+ ////////////////////////////////////////
+
+ //send meta object
+ d->typeIdent = p.d->typeId;
+ response.d->instanceId = d->serviceInstanceId;
+ response.d->typeId = p.d->typeId;
+ response.d->responseType = QServicePackage::Success;
+ response.d->payload = QVariant(data);
+ dispatch->writePackage(response);
+ }
+}
+
+void ObjectEndPoint::methodCall(const QServicePackage& p)
+{
+ if (p.d->responseType == QServicePackage::NotAResponse ) {
+ //service side if slot invocation
+ //client side if signal emission (isSignal==true)
+
+ QByteArray data = p.d->payload.toByteArray();
+ QDataStream stream(&data, QIODevice::ReadOnly);
+ int metaIndex = -1;
+ QVariantList args;
+ stream >> metaIndex;
+ stream >> args;
+
+ qDebug() << "METHOD CALL" << metaIndex << args;
+
+ QMetaMethod method = service->metaObject()->method(metaIndex);
+ const bool isSignal = (method.methodType() == QMetaMethod::Signal);
+ const int returnType = QMetaType::type(method.typeName());
+
+ if (isSignal) {
+ qDebug() << " I AM A SIGNAL ";
+ Q_ASSERT(d->endPointType == ObjectEndPoint::Client);
+ // Construct the raw argument list.
+ /* we ignore a possible return type of the signal. The value is
+ not deterministic and it can actually create memory leaks
+ in moc generated code.
+ */
+ const int numArgs = args.size();
+ QVarLengthArray<void *, 32> a( numArgs+1 );
+ a[0] = 0;
+
+ const QList<QByteArray> pTypes = method.parameterTypes();
+ for ( int arg = 0; arg < numArgs; ++arg ) {
+ if (pTypes.at(arg) == "QVariant")
+ a[arg+1] = (void *)&( args[arg] );
+ else
+ a[arg+1] = (void *)( args[arg].data() );
+ }
+
+ d->triggerConnectedSlots(service, service->metaObject(), metaIndex, a.data());
+ return;
+ }
+
+ //service side
+ Q_ASSERT(d->endPointType == ObjectEndPoint::Service);
+
+ const char* typenames[] = {0,0,0,0,0,0,0,0,0,0};
+ const void* param[] = {0,0,0,0,0,0,0,0,0,0};
+
+ for(int i=0; i<args.size(); i++) {
+ if (args[i].isValid()) {
+ typenames[i] = args[i].typeName();
+ } else {
+ if (method.parameterTypes().at(i) == "QVariant")
+ typenames[i] = "QVariant";
+ }
+ param[i] = args[i].constData();
+ }
+
+ QString methodName(method.signature());
+ int index = methodName.indexOf("(");
+ methodName.chop(methodName.size()-index);
+
+ qDebug() << "VOID METHOD CALL: " << methodName;
+ qDebug() << "VOID METHOD ARGS: " << args;
+
+ bool result = false;
+ if (returnType == QMetaType::Void && strcmp(method.typeName(), "QVariant")) {
+ // void method call
+ QDBusMessage msg = iface->callWithArgumentList(QDBus::Block, methodName, args);
+ if (msg.type() == QDBusMessage::ErrorMessage) {
+ // Q_INVOKABLE method
+ result = method.invoke(service,
+ QGenericArgument(typenames[0], param[0]),
+ QGenericArgument(typenames[1], param[1]),
+ QGenericArgument(typenames[2], param[2]),
+ QGenericArgument(typenames[3], param[3]),
+ QGenericArgument(typenames[4], param[4]),
+ QGenericArgument(typenames[5], param[5]),
+ QGenericArgument(typenames[6], param[6]),
+ QGenericArgument(typenames[7], param[7]),
+ QGenericArgument(typenames[8], param[8]),
+ QGenericArgument(typenames[9], param[9]));
+ } else {
+ result = true;
+ }
+ } else {
+ //result buffer
+ QVariant returnValue;
+ //ignore whether QVariant is a declared meta type or not
+ if (returnType != QVariant::Invalid && strcmp(method.typeName(), "QVariant")) {
+ returnValue = QVariant(returnType, (const void*) 0);
+ }
+
+ //QDBusReply<QVariant> reply = iface->callWithArgumentList(QDBus::Block, methodName, args);
+ QDBusReply<QVariant> reply = iface->callWithArgumentList(QDBus::Block, methodName, args);
+ qDebug() << reply.isValid();
+ if (!reply.isValid()) {
+ qDebug() << "NOT VALID";
+ QGenericReturnArgument ret(method.typeName(), returnValue.data());
+ result = method.invoke(service, ret,
+ QGenericArgument(typenames[0], param[0]),
+ QGenericArgument(typenames[1], param[1]),
+ QGenericArgument(typenames[2], param[2]),
+ QGenericArgument(typenames[3], param[3]),
+ QGenericArgument(typenames[4], param[4]),
+ QGenericArgument(typenames[5], param[5]),
+ QGenericArgument(typenames[6], param[6]),
+ QGenericArgument(typenames[7], param[7]),
+ QGenericArgument(typenames[8], param[8]),
+ QGenericArgument(typenames[9], param[9]));
+ } else {
+ qDebug() << "++++++++++++++++++++++++++++++++++++++++++++++++++++++";
+ }
+
+ QServicePackage response = p.createResponse();
+
+ if (result) {
+ response.d->responseType = QServicePackage::Success;
+ response.d->payload = returnValue;
+ } else {
+ response.d->responseType = QServicePackage::Failed;
+ }
+ dispatch->writePackage(response);
+
+ }
+ if (!result)
+ qWarning( "%s::%s cannot be called.", service->metaObject()->className(), method.signature());
+ } else {
+ //client side
+ Q_ASSERT(d->endPointType == ObjectEndPoint::Client);
+
+ Response* response = openRequests()->value(p.d->messageId);
+ response->isFinished = true;
+ if (p.d->responseType == QServicePackage::Failed) {
+ response->result = 0;
+ QTimer::singleShot(0, this, SIGNAL(pendingRequestFinished()));
+ return;
+ }
+ QVariant* variant = new QVariant(p.d->payload);
+ response->result = reinterpret_cast<void *>(variant);
+
+ QTimer::singleShot(0, this, SIGNAL(pendingRequestFinished()));
+ }
+}
+
+/*!
+ Will block if return value expected
+ Handles property calls
+*/
+QVariant ObjectEndPoint::invokeRemoteProperty(int metaIndex, const QVariant& arg, int /*returnType*/, QMetaObject::Call c )
+{
+ //client and service side
+ Q_ASSERT(d->endPointType == ObjectEndPoint::Client
+ || d->endPointType == ObjectEndPoint::Service);
+
+ QServicePackage p;
+ p.d = new QServicePackagePrivate();
+ p.d->packageType = QServicePackage::PropertyCall;
+ p.d->messageId = QUuid::createUuid();
+
+ QByteArray data;
+ QDataStream stream(&data, QIODevice::WriteOnly|QIODevice::Append);
+ stream << metaIndex << arg << c;
+ p.d->payload = data;
+
+ if (c == QMetaObject::ReadProperty) {
+ //create response and block for answer
+ Response* response = new Response();
+ openRequests()->insert(p.d->messageId, response);
+
+ dispatch->writePackage(p);
+ waitForResponse(p.d->messageId);
+
+ QVariant result;
+ QVariant* resultPointer;
+ if (response->isFinished) {
+ if (response->result == 0) {
+ qWarning() << "Service property call failed";
+ } else {
+ resultPointer = reinterpret_cast<QVariant* >(response->result);
+ result = (*resultPointer);
+ }
+ } else {
+ qDebug() << "response passed but not finished";
+ }
+
+ openRequests()->take(p.d->messageId);
+ delete resultPointer;
+ delete response;
+
+ return result;
+ } else {
+ dispatch->writePackage(p);
+ }
+
+ return QVariant();
+}
+
+/*!
+ Will block if return value expected
+ Handles signal/slots
+*/
+QVariant ObjectEndPoint::invokeRemote(int metaIndex, const QVariantList& args, int returnType)
+{
+ qDebug() << "INVOKE REMOTE" << metaIndex << args;
+
+ //client side
+ //Q_ASSERT(d->endPointType == ObjectEndPoint::Client);
+
+ QServicePackage p;
+ p.d = new QServicePackagePrivate();
+ p.d->packageType = QServicePackage::MethodCall;
+ p.d->messageId = QUuid::createUuid();
+
+ QByteArray data;
+ QDataStream stream(&data, QIODevice::WriteOnly|QIODevice::Append);
+ stream << metaIndex << args;
+ p.d->payload = data;
+
+ if (returnType == QMetaType::Void) {
+ dispatch->writePackage(p);
+ } else {
+ //create response and block for answer
+ Response* response = new Response();
+ openRequests()->insert(p.d->messageId, response);
+
+ dispatch->writePackage(p);
+ waitForResponse(p.d->messageId);
+
+ QVariant result;
+ QVariant* resultPointer;
+ if (response->isFinished) {
+ if (response->result == 0) {
+ qWarning() << "Remote function call failed";
+ } else {
+ resultPointer = reinterpret_cast<QVariant* >(response->result);
+ result = (*resultPointer);
+ }
+ } else {
+ qDebug() << "response passed but not finished";
+ }
+
+ openRequests()->take(p.d->messageId);
+ delete resultPointer;
+ delete response;
+
+ return result;
+
+ }
+
+ return QVariant();
+}
+
+void ObjectEndPoint::waitForResponse(const QUuid& requestId)
+{
+ Q_ASSERT(d->endPointType == ObjectEndPoint::Client);
+
+ if (openRequests()->contains(requestId) ) {
+ Response* response = openRequests()->value(requestId);
+ QEventLoop* loop = new QEventLoop( this );
+ connect(this, SIGNAL(pendingRequestFinished()), loop, SLOT(quit()));
+
+ while(!response->isFinished) {
+ loop->exec();
+ }
+
+ delete loop;
+ }
+}
+
+#include "moc_objectendpoint_dbus_p.cpp"
+
+QTM_END_NAMESPACE
diff --git a/src/serviceframework/ipc/objectendpoint_dbus_p.h b/src/serviceframework/ipc/objectendpoint_dbus_p.h
new file mode 100644
index 0000000000..780b17f221
--- /dev/null
+++ b/src/serviceframework/ipc/objectendpoint_dbus_p.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef OBJECT_ENDPOINT_DBUS_H
+#define OBJECT_ENDPOINT_DBUS_H
+
+#include "qmobilityglobal.h"
+#include "ipcendpoint_p.h"
+#include "qremoteserviceclassregister.h"
+#include "qservice.h"
+#include <QPointer>
+#include <QHash>
+#include <QtDBus>
+
+QTM_BEGIN_NAMESPACE
+
+class ObjectEndPointPrivate;
+class ObjectEndPoint : public QObject
+{
+ Q_OBJECT
+public:
+ enum Type {
+ Service = 0,
+ Client
+ };
+
+ ObjectEndPoint(Type type, QServiceIpcEndPoint* comm, QObject* parent = 0);
+ ~ObjectEndPoint();
+
+ QObject* constructProxy(const QRemoteServiceIdentifier& ident);
+
+ // DBUS OVERLOAD
+ //QObject* constructProxy();
+
+ void objectRequest(const QServicePackage& p);
+ void methodCall(const QServicePackage& p);
+ void propertyCall(const QServicePackage& p);
+
+ QVariant invokeRemote(int metaIndex, const QVariantList& args, int returnType);
+ QVariant invokeRemoteProperty(int metaIndex, const QVariant& arg, int returnType, QMetaObject::Call c);
+
+ QUuid myInstanceID();
+
+Q_SIGNALS:
+ void pendingRequestFinished();
+
+public Q_SLOTS:
+ void newPackageReady();
+ void disconnected();
+
+//private:
+public:
+ void waitForResponse(const QUuid& requestId);
+
+ QServiceIpcEndPoint* dispatch;
+ QPointer<QObject> service;
+ ObjectEndPointPrivate* d;
+ QDBusInterface *iface;
+};
+
+QTM_END_NAMESPACE
+
+#endif //OBJECT_ENDPOINT_DBUS_H
diff --git a/src/serviceframework/ipc/proxyobject_dbus.cpp b/src/serviceframework/ipc/proxyobject_dbus.cpp
new file mode 100644
index 0000000000..6c0337b3ef
--- /dev/null
+++ b/src/serviceframework/ipc/proxyobject_dbus.cpp
@@ -0,0 +1,254 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "proxyobject_dbus_p.h"
+#include "qmetaobjectbuilder_p.h"
+
+#include <QDebug>
+#include <QtDBus>
+
+QTM_BEGIN_NAMESPACE
+
+class QServiceProxyPrivate
+{
+public:
+ //QRemoteServiceIdentifier ident;
+ QByteArray metadata;
+ QMetaObject* meta;
+ ObjectEndPoint* endPoint;
+};
+
+QServiceProxy::QServiceProxy(const QByteArray& metadata, ObjectEndPoint* endPoint, QObject* parent)
+ : QObject(parent)
+{
+ Q_ASSERT(endPoint);
+ d = new QServiceProxyPrivate();
+ //d->ident = ident;
+ d->metadata = metadata;
+ d->meta = 0;
+ d->endPoint = endPoint;
+
+ /*
+ QDBusConnection *connection = new QDBusConnection(QDBusConnection::sessionBus());
+ if (!connection->isConnected()) {
+ qWarning() << "Cannot connect to DBus";
+ }
+
+ QString serviceName = "com.nokia.qtmobility.sfw." + d->ident.name;
+ uint hash = qHash(endPoint->myInstanceID());
+ QString objPath = "/" + d->ident.interface + "/" + d->ident.version + "/" + QString::number(hash);
+ objPath.replace(QString("."), QString("/"));
+
+ QDBusInterface *iface = new QDBusInterface(serviceName, objPath, "", QDBusConnection::sessionBus());
+ */
+
+ QDataStream stream(d->metadata);
+ QMetaObjectBuilder builder;
+ QMap<QByteArray, const QMetaObject*> refs;
+
+ builder.deserialize(stream, refs);
+ if (stream.status() != QDataStream::Ok) {
+ qWarning() << "Invalid metaObject for service received";
+ } else {
+ QMetaMethodBuilder b = builder.addSignal("errorUnrecoverableIPCFault(QService::UnrecoverableIPCError)");
+
+ // After all methods are filled in, otherwise qvector won't be big enough
+ localSignals.fill(false, builder.methodCount());
+ localSignals.replace(b.index(), true); // Call activate locally
+
+ d->meta = builder.toMetaObject();
+
+ qWarning() << "Proxy object for" << d->meta->className() << "created.";
+ }
+
+ QMetaObject *fun = d->meta;
+ QMetaProperty prop = fun->property(1);
+ prop.write(endPoint->service, "YOHOHO");
+
+
+ qDebug() << "PROP READ" << prop.read(endPoint->service);
+
+
+}
+
+QServiceProxy::~QServiceProxy()
+{
+ if (d->meta)
+ delete d->meta;
+ delete d;
+}
+
+//provide custom Q_OBJECT implementation
+const QMetaObject* QServiceProxy::metaObject() const
+{
+ return d->meta;
+}
+
+int QServiceProxy::qt_metacall(QMetaObject::Call c, int id, void **a)
+{
+ id = QObject::qt_metacall(c, id, a);
+ if (id < 0 || !d->meta)
+ return id;
+
+ if(localSignals.at(id)){
+ QMetaObject::activate(this, d->meta, id, a);
+ return id;
+ }
+
+ if (c == QMetaObject::InvokeMetaMethod) {
+ const int mcount = d->meta->methodCount() - d->meta->methodOffset();
+ const int metaIndex = id + d->meta->methodOffset();
+
+ QMetaMethod method = d->meta->method(metaIndex);
+
+ const int returnType = QMetaType::type(method.typeName());
+
+ //process arguments
+ const QList<QByteArray> pTypes = method.parameterTypes();
+ const int pTypesCount = pTypes.count();
+ QVariantList args ;
+ if (pTypesCount > 10) {
+ qWarning() << "Cannot call" << method.signature() << ". More than 10 parameter.";
+ return id;
+ }
+
+
+ for (int i=0; i < pTypesCount; i++) {
+ const QByteArray& t = pTypes[i];
+
+ int variantType = QVariant::nameToType(t);
+ if (variantType == QVariant::UserType)
+ variantType = QMetaType::type(t);
+
+ if (t == "QVariant") { //ignore whether QVariant is declared as metatype
+ args << *reinterpret_cast<const QVariant(*)>(a[i+1]);
+ } else if ( variantType == 0 ){
+ qWarning("%s: argument %s has unknown type. Use qRegisterMetaType to register it.",
+ method.signature(), t.data());
+ return id;
+ } else {
+ args << QVariant(variantType, a[i+1]);
+ }
+ }
+
+ //QVariant looks the same as Void type. we need to distinguish them
+ if (returnType == QMetaType::Void && strcmp(method.typeName(),"QVariant") ) {
+ d->endPoint->invokeRemote(metaIndex, args, returnType);
+ } else {
+ //TODO: ugly but works
+ //add +1 if we have a variant return type to avoid triggering of void
+ //code path
+ //invokeRemote() parameter list needs review
+ QVariant result = d->endPoint->invokeRemote(metaIndex, args,
+ returnType==0 ? returnType+1: returnType);
+ if (returnType != 0 && strcmp(method.typeName(),"QVariant")) {
+ QByteArray buffer;
+ QDataStream stream(&buffer, QIODevice::ReadWrite);
+ QMetaType::save(stream, returnType, result.constData());
+ stream.device()->seek(0);
+ QMetaType::load(stream, returnType, a[0]);
+ } else {
+ if (a[0]) *reinterpret_cast< QVariant*>(a[0]) = result;
+ }
+ }
+ id-=mcount;
+ } else if ( c == QMetaObject::ReadProperty
+ || c == QMetaObject::WriteProperty
+ || c == QMetaObject::ResetProperty ) {
+ const int pCount = d->meta->propertyCount() - d->meta->propertyOffset();
+ const int metaIndex = id + d->meta->propertyOffset();
+ QMetaProperty property = d->meta->property(metaIndex);
+ if (property.isValid()) {
+ int pType = property.type();
+ if (pType == QVariant::UserType)
+ pType = QMetaType::type(property.typeName());
+
+ QVariant arg;
+ if ( c == QMetaObject::WriteProperty ) {
+ if (pType == QVariant::Invalid && QByteArray(property.typeName()) == "QVariant")
+ arg = *reinterpret_cast<const QVariant(*)>(a[0]);
+ else if (pType == 0) {
+ qWarning("%s: property %s has unkown type", property.name(), property.typeName());
+ return id;
+ } else {
+ arg = QVariant(pType, a[0]);
+ }
+ }
+ QVariant result;
+ if (c == QMetaObject::ReadProperty) {
+ result = d->endPoint->invokeRemoteProperty(metaIndex, arg, pType, c);
+ //wrap result for client
+ if (pType != 0) {
+ QByteArray buffer;
+ QDataStream stream(&buffer, QIODevice::ReadWrite);
+ QMetaType::save(stream, pType, result.constData());
+ stream.device()->seek(0);
+ QMetaType::load(stream, pType, a[0]);
+ } else {
+ if (a[0]) *reinterpret_cast< QVariant*>(a[0]) = result;
+ }
+ } else {
+ d->endPoint->invokeRemoteProperty(metaIndex, arg, pType, c);
+ }
+ }
+ id-=pCount;
+ } else if ( c == QMetaObject::QueryPropertyDesignable
+ || c == QMetaObject::QueryPropertyScriptable
+ || c == QMetaObject::QueryPropertyStored
+ || c == QMetaObject::QueryPropertyEditable
+ || c == QMetaObject::QueryPropertyUser )
+ {
+ //Nothing to do?
+ //These values are part of the transferred meta object already
+ } else {
+ //TODO
+ qWarning() << "MetaCall type" << c << "not yet handled";
+ }
+ return id;
+}
+
+void *QServiceProxy::qt_metacast(const char* className)
+{
+ if (!className) return 0;
+ //this object should not be castable to anything but QObject
+ return QObject::qt_metacast(className);
+}
+QTM_END_NAMESPACE
diff --git a/src/serviceframework/ipc/proxyobject_dbus_p.h b/src/serviceframework/ipc/proxyobject_dbus_p.h
new file mode 100644
index 0000000000..d215a9ccd0
--- /dev/null
+++ b/src/serviceframework/ipc/proxyobject_dbus_p.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PROXY_OBJECT_H
+#define PROXY_OBJECT_H
+
+#include "qmobilityglobal.h"
+#include "objectendpoint_dbus_p.h"
+#include <QObject>
+
+QTM_BEGIN_NAMESPACE
+
+class QServiceProxyPrivate;
+class QServiceProxy : public QObject
+{
+ //Note: Do not put Q_OBJECT here
+public:
+ QServiceProxy(const QByteArray& metadata, ObjectEndPoint* endpoint, QObject* parent = 0);
+ virtual ~QServiceProxy();
+
+ //provide custom Q_OBJECT implementation
+ virtual const QMetaObject* metaObject() const;
+ int qt_metacall(QMetaObject::Call c, int id, void **a);
+ void *qt_metacast(const char* className);
+/*protected:
+ void connectNotify(const char* signal);
+ void disconnectNotify(const char* signal);*/
+
+private:
+ QServiceProxyPrivate* d;
+ QVector<bool> localSignals;
+};
+
+
+
+QTM_END_NAMESPACE
+
+#endif //PROXY_OBJECT_H
diff --git a/src/serviceframework/ipc/qremoteservicecontrol_dbus_p.cpp b/src/serviceframework/ipc/qremoteservicecontrol_dbus_p.cpp
index e6188ed642..e89f6a6661 100644
--- a/src/serviceframework/ipc/qremoteservicecontrol_dbus_p.cpp
+++ b/src/serviceframework/ipc/qremoteservicecontrol_dbus_p.cpp
@@ -41,10 +41,8 @@
#include "qremoteservicecontrol_dbus_p.h"
#include "ipcendpoint_p.h"
-#include "objectendpoint_p.h"
+#include "objectendpoint_dbus_p.h"
-#include <QLocalServer>
-#include <QLocalSocket>
#include <QDataStream>
#include <QTimer>
@@ -61,8 +59,8 @@ class DBusEndPoint : public QServiceIpcEndPoint
Q_OBJECT
public:
- DBusEndPoint(QDBusInterface* iface, int type, const QString &id, QObject* parent = 0)
- : QServiceIpcEndPoint(parent), interface(iface), endType(type), sessionID(id)
+ DBusEndPoint(QDBusInterface* iface, int type, QObject* parent = 0)
+ : QServiceIpcEndPoint(parent), interface(iface), endType(type)
{
Q_ASSERT(interface);
interface->setParent(this);
@@ -73,6 +71,10 @@ public:
{
}
+ void testThis()
+ {
+ qDebug() << "HELLO";
+ }
protected:
void flushPackage(const QServicePackage& package)
@@ -81,26 +83,32 @@ protected:
if (!connection->isConnected()) {
qWarning() << "Cannot connect to DBus";
}
-
+
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_6);
out << package;
- interface->asyncCall("writePackage", block, endType, sessionID);
+ packageId = package.d->messageId;
+ interface->asyncCall("writePackage", block, endType, packageId);
}
protected slots:
void readPackage(const QByteArray &package, int type, const QString &id) {
+
+ // Check the message id
+ QDataStream data(package);
+ QServicePackage pack;
+ data >> pack;
+
// Check that its of a client-server nature
if (endType != type) {
// Client to Server
if (type != 0) {
- sessionID = id;
readIncoming(package);
- // Server to Client
} else {
- if (id == sessionID)
+ // Server to Client
+ if (id == packageId)
readIncoming(package);
}
}
@@ -111,7 +119,7 @@ protected slots:
QDataStream data(package);
QServicePackage pack;
data >> pack;
-
+
incoming.enqueue(pack);
emit readyRead();
}
@@ -119,7 +127,7 @@ protected slots:
private:
QDBusInterface* interface;
int endType;
- QString sessionID;
+ QString packageId;
};
class DBusSession: public QObject
@@ -200,45 +208,28 @@ bool QRemoteServiceControlPrivate::createServiceEndPoint(const QString& ident)
QList<QRemoteServiceIdentifier> list = iManager->allIdents();
if (list.size() > 0) {
-
QDBusConnection *connection = new QDBusConnection(QDBusConnection::sessionBus());
if (!connection->isConnected()) {
qWarning() << "Cannot connect to DBus";
return 0;
}
- // Register all services in the InstanceManager registered by
- // QRemoteServiceRegister
- for (int i=0; i<list.size(); i++) {
- QString serviceName = "com.nokia.qtmobility.sfw." + list[i].name;
-
- // TODO: do we want to always re-register services to dbus?
- connection->unregisterService(serviceName);
-
- connection->registerService(serviceName);
- if (!connection->registerService(serviceName)) {
- qWarning() << "Cannot register service to DBus";
- return 0;
- }
-
- // Registers all services on the DBUS, to be used for complete DBUS
- // implementation
- QUuid myID;
- myID = QUuid();
- QObject* myObj = iManager->createObjectInstance(list[0], myID);
+ // MAYBE A FOR-LOOP FOR EACH SERVICENAME (ie DBUSExample, IPCExample)
- QString path = "/" + list[i].interface + "/" + list[i].version;
- path.replace(QString("."), QString("/"));
+ // TODO: do we want to always re-register services to dbus?
+ QString serviceName = "com.nokia.qtmobility.sfw." + list[0].name;
+ connection->unregisterService(serviceName);
- connection->registerObject(path, myObj, QDBusConnection::ExportAllSlots);
-
+ connection->registerService(serviceName);
+ if (!connection->registerService(serviceName)) {
+ qWarning() << "Cannot register service to DBus";
+ return 0;
}
// Register our DBusSession server/client
DBusSession *session = new DBusSession();
new DBusSessionAdaptor(session);
- QString serviceName = "com.nokia.qtmobility.sfw." + list[0].name;
QString path = "/" + list[0].interface + "/DBusSession";
path.replace(QString("."), QString("/"));
connection->registerObject(path, session);
@@ -248,8 +239,8 @@ bool QRemoteServiceControlPrivate::createServiceEndPoint(const QString& ident)
qWarning() << "Cannot connect to remote service" << serviceName << path;;
return 0;
}
-
- DBusEndPoint* ipcEndPoint = new DBusEndPoint(iface, 0, QUuid::createUuid().toString());
+
+ DBusEndPoint* ipcEndPoint = new DBusEndPoint(iface, 0);
ObjectEndPoint* endpoint = new ObjectEndPoint(ObjectEndPoint::Service, ipcEndPoint, this);
return true;
@@ -277,10 +268,12 @@ QObject* QRemoteServiceControlPrivate::proxyForService(const QRemoteServiceIdent
return 0;
}
- DBusEndPoint* ipcEndPoint = new DBusEndPoint(inface, 1, QUuid::createUuid().toString());
+ DBusEndPoint* ipcEndPoint = new DBusEndPoint(inface, 1);
ObjectEndPoint* endPoint = new ObjectEndPoint(ObjectEndPoint::Client, ipcEndPoint);
-
+
+ //QObject* proxy
QObject *proxy = endPoint->constructProxy(typeIdent);
+
QObject::connect(proxy, SIGNAL(destroyed()), endPoint, SLOT(deleteLater()));
return proxy;
}
diff --git a/src/serviceframework/ipc/qservicepackage.cpp b/src/serviceframework/ipc/qservicepackage.cpp
index fd9faea037..2534e929a8 100644
--- a/src/serviceframework/ipc/qservicepackage.cpp
+++ b/src/serviceframework/ipc/qservicepackage.cpp
@@ -77,6 +77,7 @@ QServicePackage QServicePackage::createResponse() const
response.d = new QServicePackagePrivate();
response.d->packageType = d->packageType;
response.d->messageId = d->messageId;
+ response.d->instanceId = d->instanceId;
response.d->responseType = QServicePackage::Failed;
return response;
@@ -95,6 +96,7 @@ QDataStream &operator<<(QDataStream &out, const QServicePackage& package)
out << (qint8) package.d->packageType;
out << (qint8) package.d->responseType;
out << package.d->messageId;
+ out << package.d->instanceId;
out << package.d->typeId;
out << package.d->payload;
}
@@ -130,6 +132,7 @@ QDataStream &operator>>(QDataStream &in, QServicePackage& package)
in >> data;
package.d->responseType = (QServicePackage::ResponseType) data;
in >> package.d->messageId;
+ in >> package.d->instanceId;
in >> package.d->typeId;
in >> package.d->payload;
} else {
diff --git a/src/serviceframework/ipc/qservicepackage_p.h b/src/serviceframework/ipc/qservicepackage_p.h
index a6e1d77a59..c12147ec09 100644
--- a/src/serviceframework/ipc/qservicepackage_p.h
+++ b/src/serviceframework/ipc/qservicepackage_p.h
@@ -80,7 +80,7 @@ public:
QServicePackage createResponse() const;
bool isValid() const;
-
+
QExplicitlySharedDataPointer<QServicePackagePrivate> d;
#ifndef QT_NO_DATASTREAM
@@ -104,7 +104,7 @@ public:
QServicePackagePrivate()
: packageType(QServicePackage::ObjectCreation),
typeId(QRemoteServiceIdentifier()), payload(QVariant()),
- messageId(QUuid()), responseType(QServicePackage::NotAResponse)
+ messageId(QUuid()), instanceId(QUuid()), responseType(QServicePackage::NotAResponse)
{
}
@@ -112,12 +112,14 @@ public:
QRemoteServiceIdentifier typeId;
QVariant payload;
QUuid messageId;
+ QUuid instanceId;
QServicePackage::ResponseType responseType;
virtual void clean()
{
packageType = QServicePackage::ObjectCreation;
messageId = QUuid();
+ instanceId = QUuid();
payload = QVariant();
typeId = QRemoteServiceIdentifier();
responseType = QServicePackage::NotAResponse;
diff --git a/tests/auto/qservicemanager_ipc/client/tst_qservicemanager_ipc.cpp b/tests/auto/qservicemanager_ipc/client/tst_qservicemanager_ipc.cpp
index 7e1842fc1b..ac306a28a6 100644
--- a/tests/auto/qservicemanager_ipc/client/tst_qservicemanager_ipc.cpp
+++ b/tests/auto/qservicemanager_ipc/client/tst_qservicemanager_ipc.cpp
@@ -821,8 +821,8 @@ void tst_QServiceManager_IPC::testInvokableFunctions()
#ifdef UNIQUE_TESTS
void tst_QServiceManager_IPC::testSignalling()
{
- QSignalSpy spy(serviceUnique, SIGNAL(signalWithIntParam(int)));
- QMetaObject::invokeMethod(serviceUnique, "triggerSignalWithIntParam");
+ QSignalSpy spy(serviceShared, SIGNAL(signalWithIntParam(int)));
+ QMetaObject::invokeMethod(serviceShared, "triggerSignalWithIntParam");
QTRY_VERIFY(spy.count() == 1);
QCOMPARE(spy.at(0).at(0).toInt(), 5);
@@ -938,13 +938,13 @@ void tst_QServiceManager_IPC::testSlotInvokation()
#ifdef UNIQUE_TESTS
void tst_QServiceManager_IPC::testIpcFailure()
-{
- QMetaObject::invokeMethod(serviceUnique, "testIpcFailure");
- int i = 0;
- while (!ipcfailure && i++ < 50)
- QTest::qWait(50);
-
- QVERIFY(ipcfailure);
+ {
+ QMetaObject::invokeMethod(serviceUnique, "testIpcFailure");
+ int i = 0;
+ while (!ipcfailure && i++ < 50)
+ QTest::qWait(50);
+
+ QVERIFY(ipcfailure);
// TODO restart the connection
// service = manager->loadInterface("com.nokia.qt.ipcunittest");
diff --git a/tests/auto/qservicemanager_ipc/service/main.cpp b/tests/auto/qservicemanager_ipc/service/main.cpp
index 7651c90f85..230cef72ab 100644
--- a/tests/auto/qservicemanager_ipc/service/main.cpp
+++ b/tests/auto/qservicemanager_ipc/service/main.cpp
@@ -114,6 +114,7 @@ public:
Q_INVOKABLE void setConfirmationHash(uint hash)
{
+ qDebug() << "I DID IT CUNT";
m_hash = hash;
}