/**
* Copyright (c) 2010 Sasken Communication Technologies Ltd.
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html"
*
* Initial Contributors:
* Chandradeep Gandhi, Sasken Communication Technologies Ltd - Initial contribution
*
* Contributors:
* Manasij Roy, Nalina Hariharan
*
* Description:
* SMF Server private implementation for Symbian
*
*/
#include <QDataStream>
#include <QDebug>
#include <smfrelationmgr.h>
#include "smfserversymbian_p.h"
SmfServerSymbian* SmfServerSymbian::NewL(CActive::TPriority aActiveObjectPriority,SmfServer* aWrapper)
{
SmfServerSymbian* self = new(ELeave) SmfServerSymbian(aActiveObjectPriority,aWrapper);
CleanupStack::PushL(self);
self->ConstructL();
CleanupStack::Pop();
return self;
}
void SmfServerSymbian::ConstructL()
{
}
SmfServerSymbian::SmfServerSymbian( CActive::TPriority aActiveObjectPriority,SmfServer* aWrapper )
: CPolicyServer(0,myPolicy, ESharableSessions), iWrapper(aWrapper)
{
Q_UNUSED(aActiveObjectPriority)
}
SmfServerSymbian::~SmfServerSymbian()
{
}
TInt SmfServerSymbian::addToSessionMap(SmfServerSymbianSession* aSession,const RMessage2& aMsg)
{
qDebug()<<"Inside SmfServerSymbian::addToSessionMap()";
if(iSessionCount)
{
//The key generation
TInt key = qrand();
//in case qrand generates any duplicate key
while(iMap.Find(key))
{
key = qrand();
}
CSessionStruct session;
session.iMsg = aMsg;
session.iSession = aSession;
iMap.Insert(key,session);
return key;
}
return (-1);
}
TInt SmfServerSymbian::removeFromSessionMap(SmfServerSymbianSession* aSession,RMessage2& aMsg)
{
//To be implemented
Q_UNUSED(aSession)
Q_UNUSED(aMsg)
return 0;
}
SmfServer* SmfServerSymbian::wrapper()
{
return iWrapper;
}
CSession2* SmfServerSymbian::NewSessionL(const TVersion& aVersion, const RMessage2& /*aMessage*/) const
{
qDebug()<<"Inside SmfServerSymbian::NewSessionL()";
Q_UNUSED(aVersion)
// Check that the version is OK
// TVersion v( 0, 1, 0 );
// if (!User::QueryVersionSupported( v, aVersion ))
// User::Leave( KErrNotSupported );
// Create the session.
qDebug()<<"New session created";
return new (ELeave) SmfServerSymbianSession( const_cast<SmfServerSymbian*>(this) );
}
SmfServerSymbianSession* SmfServerSymbian::findSession(TInt id)
{
qDebug()<<"Inside SmfServerSymbian::findSession()";
CSessionStruct* sessionStruct = iMap.Find(id);
if(sessionStruct)
{
qDebug()<<"Session id found";
return sessionStruct->iSession;
}
else
{
qDebug()<<"Session id not found";
return NULL;
}
}
TInt SmfServerSymbian::findAndServiceclient(TInt requestID,QByteArray* parsedData,SmfError error)
{
qDebug()<<"Inside SmfServerSymbian::findAndServiceclient()";
SmfServerSymbianSession* sessionToservice = findSession(requestID);
if(sessionToservice)
{
sessionToservice->resultsAvailable(parsedData,error);
}
return 0;
}
SmfServerSymbianSession::SmfServerSymbianSession(SmfServerSymbian* aServer):
iServer(aServer),iPtrToBuf(NULL,0) ,
iIntfNameSymbian8(NULL,0), iProviderSymbian8(NULL,0),
iIntfNameSymbian(NULL,0) ,iXtraDataPtr8(NULL,0),
iPtrToDataForClient(NULL,0) ,iPtr8DataForDSM(NULL,0),iPtr8DataFromDSM(NULL,0)
{
qDebug()<<"Inside SmfServerSymbianSession::SmfServerSymbianSession()";
iServer->iSessionCount++;
}
SmfServerSymbianSession::~SmfServerSymbianSession()
{
qDebug()<<"Inside SmfServerSymbianSession::~SmfServerSymbianSession()";
//cleanup of client resources
iServer->iSessionCount--;
}
void SmfServerSymbianSession::clientAuthorizationFinished(bool success)
{
qDebug()<<"Inside SmfServerSymbianSession::clientAuthorizationFinished() = "<<success;
//Client authorization failed
if(!success)
{
//TODO:- Should use smf wide error instead
iMessage.Complete(KErrPermissionDenied);
}
else
{
HandleClientMessageL(iMessage);
}
}
void SmfServerSymbianSession::resultsAvailable(QByteArray* parsedData,SmfError error)
{
qDebug()<<"Inside SmfServerSymbianSession::resultsAvailable()";
//Note:- The order of serialization of parsedData - Error value followed by the data
//parsedData is already serialized by PM
//We should remove the request from the map as soon its no longer outstanding
iServer->removeFromSessionMap(this,iMessage);
//Note:- Session must take the ownership of the data being passed to the client session
if(iDataForClient)
{
delete iDataForClient;
iDataForClient = NULL;
}
iDataForClient = HBufC8::NewL(parsedData->size());
iPtrToDataForClient.Set(iDataForClient->Des());
iPtrToDataForClient.Copy(reinterpret_cast<const TText8*>(parsedData->constData()),parsedData->length());
TInt writeErr = iMessage.Write(2,iPtrToDataForClient);
qDebug()<<"iMessage.Write() = "<<writeErr;
//signal completion for the last request
iMessage.Complete(error);
}
void SmfServerSymbianSession::ServiceL(const RMessage2& aMessage)
{
qDebug()<<"Inside SmfServerSymbianSession::ServiceL() = "<<iMessage.Function();
iMessage = aMessage;
//construct the client auth id
SmfClientAuthID clientAuthID;
clientAuthID.pid = aMessage.SecureId();
clientAuthID.session = this;
//TODO:- No client pid checking?No capability? So why symbian client-server?
HandleClientMessageL(iMessage);
}
void SmfServerSymbianSession::HandleClientMessageL(const RMessage2& aMessage)
{
qDebug()<<"Inside SmfServerSymbianSession::HandleClientMessageL() = "<<aMessage.Function();
iLastRequest = aMessage.Function();
/**Note:- Only ESmfGetService needs to be taken care separately as it doesn't involve createrequest for PM
*See SmfRequestTypeID for list of opcodes
*
*Two cases,-
*1.for ESmfGetServices we donno the provider info
*2. for rest of the cases, we know the provider info
*so it seems PM needs to provide two overloaded getPlugins API But for every client intf instanciation
*we would execute the same things twice.
*TODO:- to be changed after GetServices returns SmfProvider+pluginID
*
*/
if( (SmfGetService == iLastRequest) ||
(SmfPostGetMaxCharsInPost == iLastRequest) ||
(SmfPostGetMaxItems == iLastRequest) ||
(SmfPostGetSupportedFormats == iLastRequest)||
(SmfPostGetAppearanceSupport == iLastRequest) )
{
HandleSyncServiceL(aMessage);
}
else if(iLastRequest == SmfRelationCreate ||
iLastRequest == SmfRelationAssociate ||
iLastRequest == SmfRelationSearchById ||
iLastRequest == SmfRelationSearchByContact ||
iLastRequest == SmfRelationCount ||
iLastRequest == SmfRelationGet ||
iLastRequest == SmfRelationGetAll ||
iLastRequest == SmfRelationGetAllRelations ||
iLastRequest == SmfRelationDeleteRelation
)
{
HandleDSMServiceL(aMessage);
}
else
{
HandleCommonServiceL(aMessage);
}
}
void SmfServerSymbianSession::HandleDSMServiceL(const RMessage2 & aMessage)
{
qDebug()<<"Inside SmfServerSymbianSession::HandleDSMServiceL()";
//TODO:-If DSM takes care of deserialization and formation of User and social
//profile from the params then switch case can be removed
if(iData8ForDSM)
{
delete iData8ForDSM;
iData8ForDSM = NULL;
}
switch(iLastRequest)
{
case SmfRelationCreate:
{
iData8ForDSM = HBufC8::New(maxSmfRelationIdSize);
iPtr8DataForDSM.Set(iData8ForDSM->Des());
TInt readerr0 = aMessage.Read(0,iPtr8DataForDSM);
}
break;
case SmfRelationAssociate:
{
int maxAlloc = 100;
iData8ForDSM = HBufC8::New(maxAlloc);
iPtr8DataForDSM.Set(iData8ForDSM->Des());
TInt readerr0 = aMessage.Read(0,iPtr8DataForDSM);
}
break;
case SmfRelationRemove:
{
iData8ForDSM = HBufC8::New(100);
iPtr8DataForDSM.Set(iData8ForDSM->Des());
TInt readerr0 = aMessage.Read(0,iPtr8DataForDSM);
break;
}
case SmfRelationSearchById:
{
int maxAlloc = MaxSmfContactSize;
iData8ForDSM = HBufC8::New(maxAlloc);
iPtr8DataForDSM.Set(iData8ForDSM->Des());
TInt readerr0 = aMessage.Read(0,iPtr8DataForDSM);
}
break;
case SmfRelationSearchByContact:
{
int maxAlloc = 500; // hard coded in relation manager
iData8ForDSM = HBufC8::New(maxAlloc);
iPtr8DataForDSM.Set(iData8ForDSM->Des());
TInt readerr0 = aMessage.Read(0,iPtr8DataForDSM);
}
break;
case SmfRelationCount:
{
int maxAlloc = 100;
iData8ForDSM = HBufC8::New(maxAlloc);
iPtr8DataForDSM.Set(iData8ForDSM->Des());
TInt readerr0 = aMessage.Read(0,iPtr8DataForDSM);
}
break;
case SmfRelationGet:
{
int maxAlloc = maxSmfRelationItemSize*maxRelationItems;
iData8ForDSM = HBufC8::New(maxAlloc);
iPtr8DataForDSM.Set(iData8ForDSM->Des());
TInt readerr0 = aMessage.Read(0,iPtr8DataForDSM);
}
break;
case SmfRelationGetAll:
{
int maxAlloc = maxSmfRelationItemSize*maxRelationItems;
iData8ForDSM = HBufC8::New(maxAlloc);
iPtr8DataForDSM.Set(iData8ForDSM->Des());
TInt readerr0 = aMessage.Read(0,iPtr8DataForDSM);
}
break;
case SmfRelationGetAllRelations:
{
int maxAlloc = maxSmfRelationItemSize*maxRelationItems;
iData8ForDSM = HBufC8::New(maxAlloc);
iPtr8DataForDSM.Set(iData8ForDSM->Des());
TInt readerr0 = aMessage.Read(0,iPtr8DataForDSM);
break;
}
case SmfRelationDeleteRelation:
{
int maxAlloc = 100;
iData8ForDSM = HBufC8::New(maxAlloc);
iPtr8DataForDSM.Set(iData8ForDSM->Des());
TInt readerr0 = aMessage.Read(0,iPtr8DataForDSM);
break;
}
default:
break;
}
//Convert into QByteArray
QByteArray qtdataForDSM(reinterpret_cast<const char*>(iPtr8DataForDSM.Ptr()),iPtr8DataForDSM.Length()) ;
QByteArray qtdataFromDSM;
SmfRequestTypeID opcode = (SmfRequestTypeID)iLastRequest;
SmfError dsmErr = iServer->wrapper()->sendToDSM(qtdataForDSM,opcode,qtdataFromDSM);
if(dsmErr == SmfNoError)
{
if(qtdataFromDSM.size())
{
if(iData8FromDSM)
{
delete iData8FromDSM;
iData8FromDSM = NULL;
}
iData8FromDSM = HBufC8::NewL(qtdataFromDSM.size());
iPtr8DataFromDSM.Set(iData8FromDSM->Des());
iPtr8DataFromDSM.Copy(reinterpret_cast<const TText8*>(qtdataFromDSM.constData()),qtdataFromDSM.length());
TInt writeErr = aMessage.Write(1,iPtr8DataFromDSM);
}
}
else
{
iDSMErr.Zero();
TInt errInt = dsmErr;
iDSMErr.AppendNum(errInt);
TInt writeErr = aMessage.Write(2,iDSMErr);
}
}
void SmfServerSymbianSession::HandleSyncServiceL(const RMessage2 & aMessage)
{
qDebug()<<"Inside SmfServerSymbianSession::HandleSyncServiceL()";
// Following is the data format sent by client
// 1. SmfProvider +PageInfo flag+ aPageNum + aPerPage (if pageinfoflag is set) + XtraInfo flag(size of xtra data) Serialized
// 2. Interface name as string ("org.symbian.smf.client.gallery")
// 3. Data pointer to be filled by serialized data(eg: QList<smfProvider>)
// 4. Input Data if xtra flag is set
TInt intfNameSize = aMessage.GetDesLength(1);
if(iIntfNameBuf8)
{
delete iIntfNameBuf8;
iIntfNameBuf8 = NULL;
}
iIntfNameBuf8 = HBufC8::NewL(intfNameSize);
iIntfNameSymbian8.Set(iIntfNameBuf8->Des());
//read it into iIntfNameSymbian8
aMessage.ReadL(1,iIntfNameSymbian8);
QByteArray intfName(reinterpret_cast<const char*>(iIntfNameSymbian8.Ptr()),iIntfNameSymbian8.Length()) ;
QDataStream readIntfNameStream(&intfName,QIODevice::ReadOnly);
iInterfaceID.clear();
readIntfNameStream>>iInterfaceID;
qDebug()<<"After de-serializing into iInterfaceID = "<<iInterfaceID;
//Interface names are diff in client and plugin, replacing *.client.* with *.plugin.*
iInterfaceID.replace(QString(".client"),QString(".plugin"));
// for get services
if(SmfGetService == aMessage.Function())
HandleGetService(aMessage, iInterfaceID);
// for other services
else
{
// read provider info
TInt providerSize = aMessage.GetDesLength(0);
if(iProviderBuf8)
{
delete iProviderBuf8;
iProviderBuf8 = NULL;
}
iProviderBuf8 = HBufC8::NewL(providerSize);
iProviderSymbian8.Set(iProviderBuf8->Des());
//read it into iProviderSymbian8
aMessage.ReadL(0,iProviderSymbian8);
//convert SmfProvider info from Symbian into bytearray
QByteArray providerBufQt(reinterpret_cast<const char*>(iProviderSymbian8.Ptr()),iProviderSymbian8.Length());
qDebug()<<"providerBufQt.size = "<<providerBufQt.size();
//now de-serialize it
QDataStream readProviderStream(&providerBufQt,QIODevice::ReadOnly);
SmfProvider provider;
readProviderStream>>provider;
QByteArray XtraBufQt;
readProviderStream>>XtraBufQt;
//Get the plugin ID who matches provider info for a given intf name
SmfPluginID pluginID = iServer->wrapper()->getPlugin(iInterfaceID,provider);
qDebug()<<"pluginID from PM = "<<pluginID;
//we need to check only this pluginID is authorized
iPluginIDList.clear();
iPluginIDList<<pluginID;
//iAuthList will contain pluginID for a successfull case
iAuthList.clear();
iServer->wrapper()->getAuthorizedPlugins(iPluginIDList,iAuthList);
if(iAuthList.contains(pluginID))
{
//Plugin ID is authorised, service the request
//Generate request id only if the plugin ID is authorised
//request PM to get the data
SmfRequestTypeID opcode = (SmfRequestTypeID)aMessage.Function();
resultData.clear();
SmfError err = iServer->wrapper()->sendToPluginManager(pluginID,iInterfaceID,opcode,XtraBufQt, resultData);
if(resultData.size())
{
TPtrC8 resultPtr8(reinterpret_cast<const TText8*>(resultData.constData()),resultData.length());
TInt writeErr = aMessage.Write(2,resultPtr8);
qDebug()<<"aMessage.Write(2) = "<<writeErr;
}
else
{
iErrBuf.Zero();
iErrBuf.AppendNum(err);
iMessage.Write(2,iErrBuf);
}
//signal completion
aMessage.Complete(iLastRequest);
}
else
{
SmfError err = SmfNoAuthorizedPlugin;
iErrBuf.Zero();
iErrBuf.AppendNum(err);
iMessage.Write(2,iErrBuf);
aMessage.Complete(iLastRequest);
}
}
}
void SmfServerSymbianSession::HandleGetService(const RMessage2 & aMessage, const SmfInterfaceID& aInterfaceID)
{
qDebug()<<"Inside SmfServerSymbianSession::HandleGetService()";
iServer->wrapper()->getPlugins(aInterfaceID,iPluginIDMap);
//form the plugin id list from the map
iPluginIDList.clear();
iPluginIDList = iPluginIDMap.uniqueKeys();
//iAuthList will be filled by credential manager
iServer->wrapper()->getAuthorizedPlugins(iPluginIDList,iAuthList);
// iPluginIDMap now contains SmfProvider info to return to the client
// No need to add this to session map, as we are not requesting PM for this
QMap<SmfPluginID, SmfProvider> tempMap;
QMapIterator<SmfPluginID, SmfProvider> i(iPluginIDMap);
while(i.hasNext())
{
i.next();
if(iAuthList.contains(i.key()))
{
tempMap.insert(i.key(),i.value());
}
}
//now tempMap contains the info to be passed to the client
iPluginIDMap.clear();
iPluginIDMap = tempMap;
//form list of smfprovider from this map,-
QList<SmfProvider> providerList = iPluginIDMap.values();
//now serialize this list into bytearray
resultData.clear();
QDataStream stream(&resultData,QIODevice::WriteOnly);
stream<<providerList;
qDebug()<<"providerList.count() = "<<providerList.count();
qDebug()<<"Before providerListSymbian";
//now convert it into TPtr8
TPtrC8 providerListSymbian(reinterpret_cast<const TText8*>(resultData.constData()),resultData.length());
qDebug()<<"After providerListSymbian";
TInt writeErr = aMessage.Write(2,providerListSymbian);
qDebug()<<"aMessage.Write(2) = "<<writeErr;
//signal completion
TInt completion = SmfGetService;
aMessage.Complete(completion);
}
void SmfServerSymbianSession::HandleCommonServiceL(const RMessage2& aMessage)
{
qDebug()<<"Inside SmfServerSymbianSession::HandleCommonServiceL() = "<<aMessage.Function();
/**
* Note:- client sends message in the following format,-
* Slot 0:- SmfProvider* serialized+Page info flag+page number+per page (if page info flag)+xtra info flag
* Slot 1:- Interface Name buffer
* Slot 2:- Ptr to data block to be filled
* Slot 3 :- Xtra Data if xtra data flag
*/
//TODO:- Use macro instead, shared betn client-server
TInt providerSize = aMessage.GetDesLength(0);
if(iProviderBuf8)
{
delete iProviderBuf8;
iProviderBuf8 = NULL;
}
iProviderBuf8 = HBufC8::NewL(providerSize);
iProviderSymbian8.Set(iProviderBuf8->Des());
//read it into iProviderSymbian8
aMessage.ReadL(0,iProviderSymbian8);
//convert SmfProvider info from Symbian into bytearray
QByteArray providerBufQt(reinterpret_cast<const char*>(iProviderSymbian8.Ptr()),iProviderSymbian8.Length());
qDebug()<<"providerBufQt.size = "<<providerBufQt.size();
//now de-serialize it
QDataStream stream(&providerBufQt,QIODevice::ReadOnly);
SmfProvider provider;
stream>>provider;
QByteArray XtraBufQt;
stream>>XtraBufQt;
qDebug()<<"XtraBufQt size = "<<XtraBufQt.size();
TInt intfNameSize = aMessage.GetDesLength(1);
if(iIntfNameBuf8)
{
delete iIntfNameBuf8;
iIntfNameBuf8 = NULL;
}
iIntfNameBuf8 = HBufC8::NewL(intfNameSize);
iIntfNameSymbian8.Set(iIntfNameBuf8->Des());
//read it into iIntfNameSymbian8
aMessage.ReadL(1,iIntfNameSymbian8);
qDebug()<<"iIntfNameSymbian8.Size = "<<iIntfNameSymbian8.Size();
QByteArray bytearray(reinterpret_cast<const char*>(iIntfNameSymbian8.Ptr()),iIntfNameSymbian8.Length()) ;
QDataStream intfNameStream(&bytearray,QIODevice::ReadOnly);
iInterfaceID.clear();
intfNameStream>>iInterfaceID;
qDebug()<<"Interface Name = "<<iInterfaceID;
//Interface names are diff in client and plugin, replacing *.client.* with *.plugin.*
iInterfaceID.replace(QString(".client"),QString(".plugin"));
//Get the plugin ID who matches provider info for a given intf name
SmfPluginID pluginID = iServer->wrapper()->getPlugin(iInterfaceID,provider);
qDebug()<<"pluginID from PM = "<<pluginID;
//we need to check only this pluginID is authorized?
iPluginIDList.clear();
iPluginIDList<<pluginID;
//iAuthList will contain pluginID for a successfull case
iAuthList.clear();
iServer->wrapper()->getAuthorizedPlugins(iPluginIDList,iAuthList);
if(iAuthList.contains(pluginID))
{
//Plugin ID is authorised, service the request
//Gnerate request id only if the plugin ID is authorised
TInt id = iServer->addToSessionMap(this,aMessage);
//request PM to get the data
SmfRequestTypeID opcode = (SmfRequestTypeID)iLastRequest;
iServer->wrapper()->sendToPluginManager(id,pluginID,iInterfaceID,opcode,XtraBufQt);
}
else
{
SmfError err = SmfNoAuthorizedPlugin;
iErrBuf.Zero();
iErrBuf.AppendNum(err);
iMessage.Write(2,iErrBuf);
}
}