summaryrefslogtreecommitdiffstats
path: root/src/serviceframework/ipc/qremoteserviceregister_s60.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/serviceframework/ipc/qremoteserviceregister_s60.cpp')
-rw-r--r--src/serviceframework/ipc/qremoteserviceregister_s60.cpp874
1 files changed, 874 insertions, 0 deletions
diff --git a/src/serviceframework/ipc/qremoteserviceregister_s60.cpp b/src/serviceframework/ipc/qremoteserviceregister_s60.cpp
new file mode 100644
index 00000000..969af3a3
--- /dev/null
+++ b/src/serviceframework/ipc/qremoteserviceregister_s60.cpp
@@ -0,0 +1,874 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qremoteserviceregister_s60_p.h"
+#include "ipcendpoint_p.h"
+#include "objectendpoint_p.h"
+#include <QTimer>
+#include <QCoreApplication>
+
+#include <e32base.h>
+
+/* IPC based on Symbian Client-Server framework
+ * This module implements the Symbian specific IPC mechanisms and related control.
+ * IPC is based on Symbian Client-Server architecture.
+ */
+
+QTM_BEGIN_NAMESPACE
+
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+void printServicePackage(const QServicePackage& package)
+{
+ if(package.d) {
+ qDebug() << "QServicePackage packageType : " << package.d->packageType;
+ qDebug() << "QServicePackage QUuid : " << package.d->messageId;
+ qDebug() << "QServicePackage responseType : " << package.d->responseType;
+ qDebug() << "QServicePackage value : " << package.d->payload;
+ }
+ else {
+ qDebug() << "Invalid ServicePackage" << " LEAVING";
+ User::Leave(KErrCorrupt);
+ }
+}
+#endif
+
+
+class SymbianClientEndPoint: public QServiceIpcEndPoint
+{
+ Q_OBJECT
+public:
+ SymbianClientEndPoint(RServiceSession* session, QObject* parent = 0)
+ : QServiceIpcEndPoint(parent), session(session)
+ {
+ Q_ASSERT(session);
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug() << "Symbian IPC endpoint created. 255 buffer";
+#endif
+ connect(session, SIGNAL(Disconnected()), this, SIGNAL(disconnected()));
+ }
+
+ ~SymbianClientEndPoint()
+ {
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug() << "Symbian IPC client endpoint destroyed.";
+#endif
+ }
+
+ void PackageReceived(QServicePackage package)
+ {
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug() << "SymbianClientEndPoint::PackageReceived. Enqueueing and emiting ReadyRead()";
+ printServicePackage(package);
+#endif
+ incoming.enqueue(package);
+ emit readyRead();
+ }
+
+protected:
+ void flushPackage(const QServicePackage& package)
+ {
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug() << "SymbianClientEndPoint::flushPackage() for package: ";
+ printServicePackage(package);
+#endif
+ session->SendServicePackage(package);
+ }
+
+private:
+ RServiceSession *session;
+};
+
+class SymbianServerEndPoint: public QServiceIpcEndPoint
+{
+ Q_OBJECT
+public:
+ SymbianServerEndPoint(CServiceProviderServerSession* session, QObject* parent = 0)
+ : QServiceIpcEndPoint(parent), session(session), obj(0)
+ {
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug() << "Symbian IPC server endpoint created.";
+#endif
+ Q_ASSERT(session);
+ // CBase derived classes cannot inherit from QObject,
+ // hence manual ownershipping instead of Qt hierarchy.
+ session->SetParent(this);
+ }
+
+
+ ~SymbianServerEndPoint()
+ {
+ #ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug() << "Symbian IPC server endpoint destroyed. --- emit disconnected";
+ #endif
+
+ emit disconnected();
+ }
+
+ void packageReceived(QServicePackage package)
+ {
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug() << "SymbianServerEndPoint::packageReceived, putting to queue and emiting readyread.";
+ printServicePackage(package);
+#endif
+ incoming.enqueue(package);
+ emit readyRead();
+ }
+
+ void setObjectEndPoint(ObjectEndPoint *aObj)
+ {
+ obj = aObj;
+ }
+
+protected:
+ void flushPackage(const QServicePackage& package)
+ {
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug() << "SymbianServerEndPoint::flushPackage() for package: ";
+ printServicePackage(package);
+#endif
+ TRAPD(err, session->SendServicePackageL(package));
+ if(err != KErrNone){
+ qDebug() << "flushPackage: Failed to send request: " << err;
+ }
+ }
+
+private:
+ CServiceProviderServerSession *session;
+ ObjectEndPoint *obj;
+};
+
+QRemoteServiceRegisterSymbianPrivate::QRemoteServiceRegisterSymbianPrivate(QObject *parent)
+ : QRemoteServiceRegisterPrivate(parent), m_server(0)
+{
+}
+
+QRemoteServiceRegisterSymbianPrivate::~QRemoteServiceRegisterSymbianPrivate()
+{
+ delete m_server;
+}
+
+void QRemoteServiceRegisterSymbianPrivate::publishServices(const QString &ident)
+{
+ // Create service side of the Symbian Client-Server architecture.
+ m_server = new CServiceProviderServer(this);
+ TPtrC serviceIdent(reinterpret_cast<const TUint16*>(ident.utf16()));
+
+ if(getSecurityFilter())
+ m_server->setSecurityFilter(getSecurityFilter());
+
+ TInt err = m_server->Start(serviceIdent);
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ if (err != KErrNone) {
+ qDebug() << "publishServices: server->Start() failed: " << err;
+ } else {
+ qDebug("publishServices: service started successfully");
+ }
+#endif
+ // If we're started by the client, notify them we're running
+ RProcess::Rendezvous(KErrNone);
+}
+
+void QRemoteServiceRegisterSymbianPrivate::processIncoming(CServiceProviderServerSession* newSession)
+{
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug("processingIncoming session creation.");
+#endif
+ // Create service provider-side endpoints.
+ SymbianServerEndPoint* ipcEndPoint = new SymbianServerEndPoint(newSession, this);
+ ObjectEndPoint* endPoint = new ObjectEndPoint(ObjectEndPoint::Service, ipcEndPoint, this);
+ ipcEndPoint->setObjectEndPoint(endPoint);
+}
+
+QRemoteServiceRegister::SecurityFilter QRemoteServiceRegisterSymbianPrivate::setSecurityFilter(QRemoteServiceRegister::SecurityFilter filter)
+{
+ if(m_server)
+ m_server->setSecurityFilter(filter);
+
+ return QRemoteServiceRegisterPrivate::setSecurityFilter(filter);
+}
+
+
+QRemoteServiceRegisterPrivate* QRemoteServiceRegisterPrivate::constructPrivateObject(QObject *parent)
+{
+ return new QRemoteServiceRegisterSymbianPrivate(parent);
+}
+
+QObject* QRemoteServiceRegisterPrivate::proxyForService(const QRemoteServiceRegister::Entry &entry, const QString &location)
+{
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug() << "proxyForService for location: " << location;
+#endif
+ // Create client-side session for the IPC and connect it to the service
+ // provide. If service provider is not up, it will be started.
+ // Connecting is tried few times in a loop, because if service starting is
+ // done at device startup, everything may not be ready yet.
+ RServiceSession *session = new RServiceSession(location);
+ int err = session->Connect();
+ int i = 0;
+ while (err != KErrNone) {
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug() << "proxyForService Connecting in loop: " << i;
+#endif
+ if (i > 10) {
+ qWarning() << "QtSFW failed to connect to service provider.";
+ return NULL;
+ }
+ User::After(50);
+ err = session->Connect();
+ i++;
+ }
+
+ // Create IPC endpoint. In practice binds the communication session and abstracting
+ // class presenting the IPC endoint.
+ SymbianClientEndPoint* ipcEndPoint = new SymbianClientEndPoint(session);
+ ipcEndPoint->setParent(session);
+ // Create an active message solicitor, which listens messages from server
+ ServiceMessageListener* messageListener = new ServiceMessageListener(session, ipcEndPoint);
+ // Create object endpoint, which handles the metaobject protocol.
+ ObjectEndPoint* endPoint = new ObjectEndPoint(ObjectEndPoint::Client, ipcEndPoint);
+ endPoint->setParent(session);
+ QObject *proxy = endPoint->constructProxy(entry);
+ session->setParent(proxy);
+ QObject::connect(session, SIGNAL(errorUnrecoverableIPCFault(QService::UnrecoverableIPCError)),
+ proxy, SIGNAL(errorUnrecoverableIPCFault(QService::UnrecoverableIPCError)));
+ return proxy;
+}
+
+RServiceSession::RServiceSession(QString address)
+: iSize(0), iListener(0), iDataSizes(KIpcBufferMinimumSize),iServerStarted(EFalse)
+{
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug() << "RServiceSession() for address: " << address;
+#endif
+ qt_symbian_throwIfError(iMessageFromServer.Create(KIpcBufferMinimumSize));
+ iServerAddress = address;
+}
+
+RServiceSession::~RServiceSession()
+{
+ delete iListener;
+ Close();
+ iMessageFromServer.Close();
+}
+
+void RServiceSession::setListener(ServiceMessageListener *listener)
+{
+ iListener = listener;
+}
+
+void RServiceSession::Close()
+{
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug() << "RServiceSession close()";
+#endif
+ RSessionBase::Close();
+}
+
+TInt RServiceSession::Connect()
+{
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug() << "RServiceSession Connect()";
+#endif
+ TInt err=KErrUnknown;
+ if(!iServerStarted){
+ TInt err = StartServer();
+ if (err == KErrNone) {
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug() << "StartServer successful, Creating session.";
+#endif
+ iServerStarted = ETrue;
+ }
+ }
+ TPtrC serviceAddressPtr(reinterpret_cast<const TUint16*>(iServerAddress.utf16()));
+ err = CreateSession(serviceAddressPtr, Version());
+
+ return err;
+}
+
+TVersion RServiceSession::Version() const
+{
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug() << "RServiceSession Version()";
+#endif
+ return TVersion(KServerMajorVersionNumber, KServerMinorVersionNumber, KServerBuildVersionNumber);
+}
+
+void RServiceSession::SendServicePackage(const QServicePackage& aPackage)
+{
+ // Serialize the package into byte array, wrap it in descriptor,
+ // and send to service provider.
+ QByteArray block;
+ QDataStream out(&block, QIODevice::WriteOnly);
+ out.setVersion(QDataStream::Qt_4_6);
+ out << aPackage;
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug() << "SendServicePackage: Size of package sent from client to server: " << block.count();
+#endif
+ TPtrC8 ptr8((TUint8*)(block.constData()), block.size());
+ TIpcArgs args(&ptr8, &iError);
+ TInt err = SendReceive(EServicePackage, args);
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug() << "SendServicePackage error code received: " << err;
+#endif
+ if(err != KErrNone){
+ enum QService::UnrecoverableIPCError e = QService::ErrorUnknown;
+ switch(err){
+ case KErrServerTerminated:
+ e = QService::ErrorServiceNoLongerAvailable;
+ break;
+ case KErrNoMemory:
+ case KErrServerBusy: // if the slots are full, something is really wrong
+ e = QService::ErrorOutofMemory;
+ break;
+ }
+ emit errorUnrecoverableIPCFault(e);
+ }
+}
+
+void RServiceSession::addDataSize(TInt dataSize)
+{
+ iDataSizes.addSample(dataSize);
+}
+
+// StartServer() checks if the service is already published by someone (i.e. can be found
+// from Kernel side). If not, it will start the process that provides the service.
+TInt RServiceSession::StartServer()
+{
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug() << "RServiceSession::StartServer()";
+#endif
+ TInt ret = KErrNone;
+ TPtrC serviceAddressPtr(reinterpret_cast<const TUint16*>(iServerAddress.utf16()));
+ TFindServer findServer(serviceAddressPtr);
+ TFullName name;
+ // Looks up from Kernel-side if there are active servers with the given name.
+ // If not found, a process providing the service needs to be started.
+ if (findServer.Next(name) != KErrNone) {
+#if defined(__WINS__) && !defined(SYMBIAN_EMULATOR_SUPPORTS_PERPROCESS_WSD)
+ qWarning("WINS Support for QSFW OOP not implemented.");
+#else
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug() << "RServiceSession::StartServer() Service not found. Starting " << iServerAddress;
+#endif
+ TRequestStatus status;
+ RProcess serviceServerProcess;
+ ret = serviceServerProcess.Create(serviceAddressPtr, KNullDesC);
+ if (ret != KErrNone) {
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug() << "StartServer RProcess::Create failed: " << ret;
+#endif
+ return ret;
+ }
+ // Point of synchronization. Waits until the started process calls
+ // counterpart of this function (quits wait also if process dies / panics).
+ serviceServerProcess.Rendezvous(status);
+
+ if (status != KRequestPending) {
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug() << "StartServer Service Server Process Rendezvous() failed, killing process.";
+#endif
+ serviceServerProcess.Kill(KErrNone);
+ serviceServerProcess.Close();
+ return KErrGeneral;
+ } else {
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug() << "StartServer Service Server Process Rendezvous() successful, resuming process.";
+#endif
+ serviceServerProcess.Resume();
+ }
+ User::WaitForRequest(status);
+ if (status != KErrNone){
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug("RTR Process Resume failed.");
+#endif
+ serviceServerProcess.Close();
+ return status.Int();
+ }
+ // Free the handle to the process (RHandleBase function, does not 'close process')
+ serviceServerProcess.Close();
+#endif // __WINS__
+ } else {
+ qDebug() << "RServiceSession::StartServer() GTR Service found from Kernel, no need to start process.";
+ }
+ return ret;
+}
+
+/* Since the average size will not change in the middle of a fragmented message
+ * trasnfer actual updates to buffer size will happen only when a new message
+ * arrives */
+void RServiceSession::updateIpcBufferSize()
+{
+ TInt weightedAvg = iDataSizes.averageWeighted();
+
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug() << "updateIpcBufferSize(): current weighted average of data size is: "<<weightedAvg;
+ qDebug() << "Current IPC Buffer size is: "<<iMessageFromServer.MaxLength();
+#endif
+ TInt newSize = iMessageFromServer.MaxLength();
+ if(weightedAvg > iMessageFromServer.MaxLength()){
+ newSize = iMessageFromServer.MaxLength()*2;
+ }
+ else if(weightedAvg < iMessageFromServer.MaxLength()/2){
+
+ newSize = iMessageFromServer.MaxLength()/2;
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug() << "updateIpcBufferSize(): current weighted average of data size is:(2) "<<weightedAvg<<" max/2";
+#endif
+ }
+
+ if(newSize < KIpcBufferMinimumSize)
+ newSize = KIpcBufferMinimumSize;
+ else if(newSize > KIpcBufferMaximumSize)
+ newSize = KIpcBufferMaximumSize;
+
+
+ if(newSize != iMessageFromServer.MaxLength()) {
+
+ iMessageFromServer.SetLength(0);
+ //If realloc fails the old descriptor is left unchanged.
+ iMessageFromServer.ReAlloc(newSize);
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug() << "updateIpcBufferSize(): New Size of IPC Buffer: "<<newSize;
+#endif
+ }
+}
+
+void RServiceSession::ListenForPackages(TRequestStatus& aStatus)
+{
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug() << "GTR RServiceSession::ListenForPackages(), iSize: " << iSize();
+#endif
+ updateIpcBufferSize();
+ iArgs.Set(0, &iMessageFromServer);
+ // Total Size of returned messaage,which might differ from the amount of data in iMessageFromServer
+ iArgs.Set(1, &iSize);
+ iArgs.Set(2, &iError);
+
+ SendReceive(EPackageRequest, iArgs, aStatus);
+}
+
+void RServiceSession::CancelListenForPackages()
+{
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug("RServiceSession::CancelListenForPackages -- 2");
+#endif
+ TInt err = SendReceive(EPackageRequestCancel, TIpcArgs(NULL));
+ if(err != KErrNone){
+ enum QService::UnrecoverableIPCError e = QService::ErrorUnknown;
+ switch(err){
+ case KErrServerTerminated:
+ e = QService::ErrorServiceNoLongerAvailable;
+ break;
+ case KErrNoMemory:
+ case KErrServerBusy: // if the slots are full, something is really wrong
+ e = QService::ErrorOutofMemory;
+ break;
+ }
+ emit errorUnrecoverableIPCFault(e);
+ }
+}
+
+void RServiceSession::ipcFailure(QService::UnrecoverableIPCError err)
+{
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug("RServiceSession::ipcFailure ipc Fault reported");
+#endif
+ emit errorUnrecoverableIPCFault(err);
+}
+
+static const TUint myRangeCount = 1;
+static const TInt myRanges[myRangeCount] =
+ {
+ 0 //range is 0-Max inclusive
+ };
+static const TUint8 myElementsIndex[myRangeCount] =
+ {
+ CPolicyServer::EAlwaysPass
+ };
+static const CPolicyServer::TPolicyElement myElements[] =
+ {
+ {_INIT_SECURITY_POLICY_PASS } // Dummy entry
+ };
+static const CPolicyServer::TPolicy myPolicy =
+ {
+ CPolicyServer::ECustomCheck, //specifies all connect attempts should pass
+ myRangeCount,
+ myRanges,
+ myElementsIndex,
+ myElements,
+ };
+
+CServiceProviderServer::CServiceProviderServer(QRemoteServiceRegisterSymbianPrivate* aOwner)
+ : CPolicyServer(EPriorityNormal, myPolicy), iSessionCount(0), iOwner(aOwner), iFilter(0)
+{
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug("CServiceProviderServer constructor");
+#endif
+ Q_ASSERT(aOwner);
+}
+
+CPolicyServer::TCustomResult CServiceProviderServer::CustomSecurityCheckL(const RMessage2 &aMessage, TInt &aAction, TSecurityInfo &aMissing)
+{
+ if(iFilter){
+ if(iFilter(reinterpret_cast<const void *>(&aMessage))){
+ return CPolicyServer::EPass;
+ }
+ else {
+ return CPolicyServer::EFail;
+ }
+ }
+ return CPolicyServer::EPass;
+}
+
+CSession2* CServiceProviderServer::NewSessionL(const TVersion &aVersion, const RMessage2 &aMessage) const
+{
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug("CServiceProviderServer::NewSessionL()");
+#endif
+ if (!User::QueryVersionSupported(TVersion(KServerMajorVersionNumber,
+ KServerMinorVersionNumber, KServerBuildVersionNumber), aVersion))
+ {
+ User::Leave(KErrNotSupported);
+ }
+ CServiceProviderServerSession* session = CServiceProviderServerSession::NewL(*const_cast<CServiceProviderServer*>(this));
+ iOwner->processIncoming(session);
+ return session;
+}
+
+void CServiceProviderServer::IncreaseSessions()
+{
+ iSessionCount++;
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug() << ">>>> CServiceProviderServer incremented session count to: " << iSessionCount;
+#endif
+}
+
+void CServiceProviderServer::DecreaseSessions()
+{
+ iSessionCount--;
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug() << "<<<< CServiceProviderServer decremented session count to: " << iSessionCount;
+#endif
+ if(iSessionCount == 0){
+ Cancel();
+ if(iOwner->quitOnLastInstanceClosed())
+ QCoreApplication::exit();
+ }
+}
+
+void CServiceProviderServer::setSecurityFilter(QRemoteServiceRegister::SecurityFilter filter)
+{
+ iFilter = filter;
+}
+
+CServiceProviderServerSession *CServiceProviderServerSession::NewL(CServiceProviderServer &aServer)
+{
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug("CServiceProviderServerSession::NewL()");
+#endif
+ CServiceProviderServerSession *self = CServiceProviderServerSession::NewLC(aServer);
+ CleanupStack::Pop(self);
+ return self;
+}
+
+CServiceProviderServerSession *CServiceProviderServerSession::NewLC(CServiceProviderServer &aServer)
+{
+ CServiceProviderServerSession* self = new (ELeave) CServiceProviderServerSession(aServer);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ return self;
+}
+
+CServiceProviderServerSession::CServiceProviderServerSession(CServiceProviderServer &aServer)
+ : iServer(aServer)
+{
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug("CServiceProviderServerSession constructor");
+#endif
+ iServer.IncreaseSessions();
+}
+
+void CServiceProviderServerSession::ConstructL()
+{
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug("OTR CServiceProviderServerSession::ConstructL()");
+#endif
+ iTotalSize = 0; // No data
+ iBlockData.clear();// clear the buffer
+}
+
+CServiceProviderServerSession::~CServiceProviderServerSession()
+{
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug("CServiceProviderServerSession destructor");
+#endif
+ iServer.DecreaseSessions();
+ delete iByteArray;
+ delete iOwner;
+}
+
+void CServiceProviderServerSession::ServiceL(const RMessage2 &aMessage)
+{
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug() << "CServiceProviderServerSession::ServiceL for message: " << aMessage.Function();
+#endif
+ switch (aMessage.Function())
+ {
+ case EServicePackage:
+ HandleServicePackageL(aMessage);
+ aMessage.Complete(KErrNone);
+ break;
+ case EPackageRequest:
+ HandlePackageRequestL(aMessage);
+ break;
+ case EPackageRequestCancel:
+ HandlePackageRequestCancelL(aMessage);
+ break;
+ }
+}
+
+void CServiceProviderServerSession::HandleServicePackageL(const RMessage2& aMessage)
+{
+ // Reproduce the serialized data.
+ HBufC8* servicePackageBuf8 = HBufC8::New(aMessage.GetDesLength(0));
+ if (!servicePackageBuf8) {
+ User::Leave( KErrNoMemory );
+ }
+
+ TPtr8 ptrToBuf(servicePackageBuf8->Des());
+ TInt ret = KErrNone;
+ TRAP(ret, aMessage.ReadL(0, ptrToBuf));
+ if (ret != KErrNone) {
+ // TODO: is this error handleing correct
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug() << "HandleServicePackageL. Message read failed: " << ret;
+#endif
+ //iDb->lastError().setError(DBError::UnknownError);
+ //aMessage.Write(1, LastErrorCode());
+ delete servicePackageBuf8;
+ User::Leave( ret );
+ }
+
+ QByteArray byteArray((const char*)ptrToBuf.Ptr(), ptrToBuf.Length());
+ QDataStream in(byteArray);
+ QServicePackage results;
+ in >> results;
+
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug() << "CServiceProviderServerSession Reproduced service package: ";
+ printServicePackage(results);
+#endif
+ iOwner->packageReceived(results);
+ delete servicePackageBuf8;
+}
+
+void CServiceProviderServerSession::SetParent(SymbianServerEndPoint *aOwner)
+{
+ iOwner = aOwner;
+}
+
+void CServiceProviderServerSession::HandlePackageRequestL(const RMessage2& aMessage)
+{
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug("HandlePackageRequestL(). Setting pending true and storing message.");
+#endif
+ iMsg = aMessage;
+ iPendingPackageRequest = ETrue;
+ if(!iPendingPackageQueue.isEmpty())
+ SendServicePackageL(iPendingPackageQueue.dequeue());
+}
+
+void CServiceProviderServerSession::HandlePackageRequestCancelL(const RMessage2& aMessage)
+{
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug("HandlePackageRequestCancelL");
+#endif
+ if (iPendingPackageRequest) {
+ iMsg.Complete(KErrCancel);
+ iPendingPackageRequest = EFalse;
+ }
+ aMessage.Complete(EPackageRequestComplete);
+}
+
+void CServiceProviderServerSession::SendServicePackageL(const QServicePackage& aPackage)
+{
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug("CServiceProviderServerSession:: SendServicePackage for package: ");
+ printServicePackage(aPackage);
+#endif
+ if (iPendingPackageRequest) {
+ if(iBlockData.isEmpty()){
+ // Serialize the package
+ QDataStream out(&iBlockData, QIODevice::WriteOnly);
+ out.setVersion(QDataStream::Qt_4_6);
+ out << aPackage;
+ iTotalSize = iBlockData.size();
+ }
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug() << "Size of package sent from server to client: " << iBlockData.count();
+ qDebug() << "Size of buffer from client: " << iMsg.GetDesMaxLength(0);
+#endif
+
+ int size = iBlockData.size();
+ if(size > iMsg.GetDesMaxLength(0)){
+ size = iMsg.GetDesMaxLength(0);
+ // enequeue the package so we send the next chunk
+ // when the next request comes through
+ iPendingPackageQueue.prepend(aPackage);
+ }
+ TPtrC8 ptr8((TUint8*)(iBlockData.constData()), size);
+ iMsg.WriteL(0, ptr8);
+ iBlockData.remove(0, size);
+//#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+// if(status == KErrOverflow){
+// qDebug() << "OTR Server to client, got overflow, sending 0 bytes";
+// }
+// else if(status != KErrNone){
+// qDebug() << "OTR SendServicePackage: error code from send: " << status;
+// }
+//#endif
+ TPckgBuf<TInt> totalSize(iTotalSize);
+ iMsg.WriteL(1,totalSize);
+ iMsg.Complete(EPackageRequestComplete);
+ iPendingPackageRequest = EFalse;
+ } else {
+ iPendingPackageQueue.enqueue(aPackage);
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qWarning() << "RTR SendServicePackage: service package from server to client queued - no pending receive request.";
+#endif
+ }
+}
+
+ServiceMessageListener::ServiceMessageListener(RServiceSession* aSession, SymbianClientEndPoint* aOwner)
+ : CActive(EPriorityNormal),
+ iClientSession(aSession),
+ iOwnerEndPoint(aOwner)
+{
+ Q_ASSERT(iClientSession);
+ Q_ASSERT(iOwnerEndPoint);
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug("ServiceMessageListener constructor");
+#endif
+ aSession->setListener(this);
+ CActiveScheduler::Add(this);
+ StartListening();
+}
+
+ServiceMessageListener::~ServiceMessageListener()
+{
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug("ServiceMessageListener destructor");
+#endif
+ Cancel();
+}
+
+void ServiceMessageListener::StartListening()
+{
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug("ServiceMessageListener::StartListening");
+#endif
+ iClientSession->ListenForPackages(iStatus);
+ SetActive();
+}
+
+void ServiceMessageListener::DoCancel()
+{
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug("ServiceMessageListener::DoCancel");
+#endif
+ iClientSession->CancelListenForPackages();
+}
+
+void ServiceMessageListener::RunL()
+{
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug() << "ServiceMessageListener::RunL for iStatus.Int(should be 4): " << iStatus.Int();
+#endif
+ if (iStatus.Int() == EPackageRequestComplete) {
+ // Client side has received a service package from server. Pass it onwards and
+ // issue new pending request.
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug() << "RunL length of the package received client side is: " << iClientSession->iMessageFromServer.Length();
+#endif
+ if(iClientSession->iMessageFromServer.Length() == 0){
+ // we received 0 bytes from the other side,
+ // normally because it tried to write more bytes
+ // than were in the TDes
+ User::Leave(KErrTooBig);
+ }
+
+ if(!iByteArray.length()){
+ /* Helps client session to calculate an optimum IPC buffer size */
+ iClientSession->addDataSize(iClientSession->iSize());
+ }
+
+ iByteArray.append((const char*)iClientSession->iMessageFromServer.Ptr(),
+ iClientSession->iMessageFromServer.Length());
+ if(iByteArray.length() >= iClientSession->iSize()){
+ QDataStream in(iByteArray);
+ iByteArray.clear();
+ QServicePackage results;
+ in >> results;
+#ifdef QT_SFW_SYMBIAN_IPC_DEBUG
+ qDebug() << "ServiceMessageListener Reproduced service package: ";
+ printServicePackage(results);
+#endif
+ iOwnerEndPoint->PackageReceived(results);
+ }
+ StartListening();
+ }
+ else if(iStatus.Int() < 0){
+ TInt s = iStatus.Int();
+ switch(s){
+ case KErrServerTerminated:
+ iClientSession->ipcFailure(QService::ErrorServiceNoLongerAvailable);
+ break;
+ case KErrServerBusy:
+ case KErrNoMemory:
+ iClientSession->ipcFailure(QService::ErrorOutofMemory);
+ break;
+ }
+ }
+}
+
+#include "moc_qremoteserviceregister_s60_p.cpp"
+#include "qremoteserviceregister_s60.moc"
+QTM_END_NAMESPACE