// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of "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:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
//
// INCLUDE FILES
#include <e32base.h>
#include <lbs.h>
#include "lbslocservermessageenums.h"
#include <lbs/epos_mposmodulesobserver.h>
#include <lbs/epos_cposmoduleidlist.h>
#include <lbs/epos_cpositioner.h>
#include "EPos_PositionerConstructParams.h"
#include "lbsdevloggermacros.h"
#include "eposuid.hrh"
#ifdef _DEBUG
#include <lbs/epos_cpostrace.h>
#endif
#include "EPos_CPosSession.h"
#include "EPos_CPosSubSession.h"
#include "EPos_CPosServer.h"
#include "EPos_CPosSubsessionRegistry.h"
#include "EPos_Global.h"
#include "EPos_CPosModulesStatus.h"
#include "epos_cposmodulessettings.h"
// CONSTANTS
#ifdef _DEBUG
_LIT(KTraceFileName, "EPos_CPosSession.cpp");
#endif
const TPositionModuleId KPosDefaultModule = { KPosDefaultPsyImplUid };
const TPositionModuleId KPosStrategyModule = { KPosStrategyPsyImplUid };
const TInt KParamCriteria = 0;
const TInt KParamNumModules = 0;
const TInt KParamModuleIdOpen = 0;
const TInt KParamModuleIdGetInfo = 0;
const TInt KParamModuleIdGetStatus = 0;
const TInt KParamModuleIdGetDefault = 0;
const TInt KParamModuleInfo = 1;
const TInt KParamModuleStatusGet = 1;
const TInt KParamSubsession = 3;
// ================= MEMBER FUNCTIONS =======================
/**
* C++ constructor.
*/
CPosSession::CPosSession(CPosServer& aServer,
CPosModuleSettings& aModuleSettings,
CPosModulesStatus& aModulesStatus,
CPosLocMonitorReqHandlerHub& aLocMonitorReqHandlerHub)
: iPosServer(aServer),
iModuleSettings(aModuleSettings),
iModulesStatus(aModulesStatus),
iLocMonitorReqHandlerHub(aLocMonitorReqHandlerHub)
{
}
/**
* C++ destructor.
*/
CPosSession::~CPosSession()
{
delete iSubSessionRegistry;
// The flag iServerShutdown prevents calling the server or its members if
// it is already destroyed.
if (!iServerShutdown)
{
iModulesStatus.NotifySessionClosed(this);
iLocMonitorReqHandlerHub.NotifySessionClosed( const_cast<const CSession2*>( static_cast<CSession2*> (this) ) ); //TODO ????????????????????????????????????????????
if (iDecrementSessions)
{
iPosServer.DecrementSessions();
}
}
}
/**
* Two-phased constructor.
*
* @param aServer Pointer to the server Active Object
* @param aModules Modules settings.
* @param aModulesStatus Pointer to the ModulesStatus object.
* @param aLastPositionHandler Last Position Handler.
* @return Pointer to a new instance of CPosSession
*/
CPosSession* CPosSession::NewL(CPosServer& aServer,
CPosModuleSettings& aModuleSettings,
CPosModulesStatus& aModulesStatus,
CPosLocMonitorReqHandlerHub& aLocMonitorReqHandlerHub)
{
CPosSession* self = new (ELeave)
CPosSession(
aServer,
aModuleSettings,
aModulesStatus,
aLocMonitorReqHandlerHub);
CleanupStack::PushL(self);
self->ConstructL();
CleanupStack::Pop(self);
return self;
}
/**
* Symbian destructor.
*/
void CPosSession::ConstructL()
{
iSubSessionRegistry = CPosSubsessionRegistry::NewL();
// This call will also cancel any server shutdown in progress.
iPosServer.IncrementSessions();
iDecrementSessions = ETrue;
}
/**
* From CSession2
*
* This function services all requests from clients.
*/
void CPosSession::ServiceL(const RMessage2& aMessage)
{
LBSLOG2(ELogP1, "CPosSession::ServiceL function called with Function() = %u\n", aMessage.Function());
switch (aMessage.Function())
{
case ELbsPositionerOpenModuleId:
OpenFromModuleIdL(aMessage);
break;
case ELbsPositionerOpen:
OpenDefaultPositionerL(aMessage);
break;
case ELbsPositionerOpenCriteria:
OpenPositionerFromCriteriaL(aMessage);
break;
case ELbsPositionerClose:
ClosePositioner(aMessage);
break;
case ELbsGetDefaultModuleId:
GetDefaultModuleIdL(aMessage);
break;
case ELbsGetNumModules:
GetNumModulesL(aMessage);
break;
case ELbsGetModuleInfoByIndex:
GetModuleInfoByIndexL(aMessage);
break;
case ELbsGetModuleInfoById:
GetModuleInfoByIdL(aMessage);
break;
case ELbsGetModuleStatus:
GetModuleStatusL(aMessage);
break;
case ELbsNotifyModuleStatusEvent:
NotifyModuleStatusEventL(aMessage);
break;
case ELbsEmptyLastKnownPositionStore:
EmptyLastKnownPositionStoreL(aMessage);
break;
case ELbsServerCancelAsyncRequest:
LBS_RDEBUG("Client", "LBS", "CancelAsyncRequest");
HandleCancelAsyncRequestL(aMessage);
break;
default:
ForwardToSubSessionL(aMessage);
break;
}
}
/**
* From CSession2
*
* This function is called when ServiceL leaves.
*/
void CPosSession::ServiceError(const RMessage2& aMessage, TInt aError)
{
DEBUG_TRACE("Client's request failed with error", aError)
CSession2::ServiceError(aMessage, aError);
}
/**
* Called when a change has been detected in the location settings.
* @param aEvent Event information
*/
void CPosSession::HandleSettingsChangeL(TPosModulesEvent aEvent)
{
// For all subSessions, call HandleSettingsChangeL()
TInt nrOfSubSessions = iSubSessionRegistry->Count();
for (TInt i = 0; i < nrOfSubSessions; i++)
{
CPosSubSession* subSession =
static_cast <CPosSubSession*>
(iSubSessionRegistry->SubSessionFromIndex(i));
if (subSession)
{
subSession->HandleSettingsChangeL(aEvent);
}
}
}
/**
* Called when the server class is shutting down.
*/
void CPosSession::NotifyServerShutdown()
{
DEBUG_TRACE("NotifyServerShutdown", __LINE__)
iServerShutdown = ETrue;
TInt nrOfSubSessions = iSubSessionRegistry->Count();
iLocMonitorReqHandlerHub.NotifyServerShutDown(); //TODO ????????????????????????????????????????????
for (TInt i = 0; i < nrOfSubSessions; i++)
{
CPosSubSession* subSession =
static_cast <CPosSubSession*>
(iSubSessionRegistry->SubSessionFromIndex(i));
if (subSession)
{
subSession->NotifyServerShutdown();
}
}
}
void CPosSession::OpenFromModuleIdL(const RMessage2& aMessage)
{
DEBUG_TRACE("EPositionerOpenModuleId", __LINE__)
TPckgBuf<TPositionModuleId> moduleIdBuf;
User::LeaveIfError(Global::Read(aMessage, KParamModuleIdOpen, moduleIdBuf));
CreateSubSessionL(moduleIdBuf(), EFalse, aMessage);
RequestComplete(aMessage, KErrNone);
}
void CPosSession::OpenDefaultPositionerL(const RMessage2& aMessage)
{
DEBUG_TRACE("EPositionerOpen(Default)", __LINE__)
CreateSubSessionL(KPosDefaultModule, ETrue, aMessage);
RequestComplete(aMessage, KErrNone);
}
void CPosSession::OpenPositionerFromCriteriaL(const RMessage2& aMessage)
{
DEBUG_TRACE("EPositionerOpenCriteria", __LINE__)
// Read Criteria
TPckgBuf<TPositionCriteria> criteria;
User::LeaveIfError(Global::Read(aMessage, KParamCriteria, criteria));
CreateSubSessionL(KPosStrategyModule, ETrue, aMessage);
RequestComplete(aMessage, KErrNone);
}
void CPosSession::ClosePositioner(const RMessage2& aMessage)
{
iLocMonitorReqHandlerHub.NotifySubSessionClosed(aMessage);
TInt handle = aMessage.Int3();
iSubSessionRegistry->CloseSubSession(handle);
RequestComplete(aMessage, KErrNone);
DEBUG_TRACE("EPositionerClose", __LINE__)
}
void CPosSession::GetDefaultModuleIdL(const RMessage2& aMessage)
{
DEBUG_TRACE("EPositionServerGetDefaultModuleId", __LINE__)
CPosModuleIdList* moduleList = iModuleSettings.ModuleIdListL();
CleanupStack::PushL( moduleList );
TInt nrOfModules = moduleList->Count();
TInt res = KErrNotFound;
for (TInt i = 0; (i < nrOfModules) && (res == KErrNotFound); i++)
{
TPositionModuleInfo candidate;
iModuleSettings.GetModuleInfoL((*moduleList)[i], candidate);
if (candidate.IsAvailable())
{
TPckg<TPositionModuleId> moduleId(candidate.ModuleId());
User::LeaveIfError(Global::Write(aMessage, KParamModuleIdGetDefault, moduleId));
res = KErrNone;
}
}
CleanupStack::PopAndDestroy(moduleList);
RequestComplete(aMessage, res);
}
void CPosSession::GetNumModulesL(const RMessage2& aMessage)
{
DEBUG_TRACE("EPositionServerGetNumModules", __LINE__)
CPosModuleIdList* moduleList = iModuleSettings.ModuleIdListL();
TInt num = moduleList->Count();
delete moduleList;
TPckg<TUint> numPackage(num);
User::LeaveIfError(Global::Write(aMessage, KParamNumModules, numPackage));
RequestComplete(aMessage, KErrNone);
}
void CPosSession::GetModuleInfoByIndexL(const RMessage2& aMessage)
{
DEBUG_TRACE("EPositionServerGetModuleInfoByIndex in", __LINE__)
// module index
TInt modIndex = aMessage.Int0();
CPosModuleIdList* moduleIdList = iModuleSettings.ModuleIdListL();
CleanupStack::PushL( moduleIdList );
if (modIndex >= moduleIdList->Count() || modIndex < 0)
{
User::Leave(KErrNotFound);
}
TPositionModuleId moduleId = (*moduleIdList)[modIndex];
// module info
HBufC8* buffer = Global::CopyClientBuffer8LC(aMessage, KParamModuleInfo);
TPositionModuleInfoBase* moduleInfoBase =
reinterpret_cast<TPositionModuleInfoBase*>(
const_cast<TUint8*>(buffer->Ptr()));
Global::ValidatePositionClassBufferL(*moduleInfoBase, buffer->Des());
// TPositionModuleInfo is the only class supported by CPosModules
Global::ValidatePositionClassTypeL(*moduleInfoBase, EPositionModuleInfoClass);
DEBUG_TRACE("Buffer validation done", __LINE__)
CleanupStack::PopAndDestroy(2, moduleIdList);
// TPositionModuleInfo contains descriptor. If it is corrupt
// (malicious client) then writing to this will panic server
// Local instance of TPositionModuleInfo is created to be sure
// that module name descriptor is not corrupt
TPositionModuleInfo modInfo;
iModuleSettings.GetModuleInfoL(moduleId, modInfo);
TPckg<TPositionModuleInfo> modInfoPack(modInfo);
User::LeaveIfError(Global::Write(aMessage, KParamModuleInfo, modInfoPack));
RequestComplete(aMessage, KErrNone);
DEBUG_TRACE("EPositionServerGetModuleInfoByIndex out", __LINE__)
}
void CPosSession::GetModuleInfoByIdL(const RMessage2& aMessage)
{
DEBUG_TRACE("EPositionServerGetModuleInfoById in", __LINE__)
TPckgBuf<TPositionModuleId> moduleIdBuf;
User::LeaveIfError(Global::Read(aMessage, KParamModuleIdGetInfo, moduleIdBuf));
TPositionModuleId moduleId = moduleIdBuf();
HBufC8* buffer = Global::CopyClientBuffer8LC(aMessage, KParamModuleInfo);
TPositionModuleInfoBase* moduleInfoBase =
reinterpret_cast<TPositionModuleInfoBase*>(
const_cast<TUint8*>(buffer->Ptr()));
Global::ValidatePositionClassBufferL(*moduleInfoBase, buffer->Des());
// TPositionModuleInfo is the only class supported by CPosModules
Global::ValidatePositionClassTypeL(*moduleInfoBase, EPositionModuleInfoClass);
DEBUG_TRACE("Buffer validation done", __LINE__)
CleanupStack::PopAndDestroy(buffer);
// TPositionModuleInfo contains descriptor. If it is corrupt
// (malicious client) then writing to this will panic server
// Local instance of TPositionModuleInfo is created to be sure
// that module name descriptor is not corrupt
TPositionModuleInfo modInfo;
iModuleSettings.GetModuleInfoL(moduleId, modInfo);
TPckg<TPositionModuleInfo> modInfoPack(modInfo);
User::LeaveIfError(Global::Write(aMessage, KParamModuleInfo, modInfoPack));
RequestComplete(aMessage, KErrNone);
DEBUG_TRACE("EPositionServerGetModuleInfoById out", __LINE__)
}
void CPosSession::GetModuleStatusL(const RMessage2& aMessage)
{
DEBUG_TRACE("EPositionServerGetModuleStatus in", __LINE__)
TPckgBuf<TPositionModuleId> moduleIdBuf;
User::LeaveIfError(Global::Read(aMessage, KParamModuleIdGetStatus, moduleIdBuf));
TPositionModuleId moduleId = moduleIdBuf();
HBufC8* buffer = Global::CopyClientBuffer8LC(aMessage, KParamModuleStatusGet);
// Read module status and write back to client
TPositionModuleStatusBase* moduleStatusBase =
reinterpret_cast<TPositionModuleStatusBase*>(
const_cast<TUint8*>(buffer->Ptr()));
Global::ValidatePositionClassBufferL(*moduleStatusBase, buffer->Des());
User::LeaveIfError (
iModulesStatus.GetModuleStatus(moduleId, *moduleStatusBase) );
User::LeaveIfError(Global::Write(aMessage, KParamModuleStatusGet, *buffer));
CleanupStack::PopAndDestroy(buffer);
RequestComplete(aMessage, KErrNone);
DEBUG_TRACE("EPositionServerGetModuleStatus out", __LINE__)
}
void CPosSession::NotifyModuleStatusEventL(const RMessage2& aMessage)
{
DEBUG_TRACE("EPositionServerNotifyModuleStatusEvent", __LINE__)
iModulesStatus.NotifyModuleStatusEventL(aMessage, this);
}
void CPosSession::NotifyModuleStatusEventCancelL(const RMessage2& aMessage)
{
DEBUG_TRACE("EPositionServerNotifyModuleStatusEventCancel", __LINE__)
iModulesStatus.CancelNotifyModuleStatusEventL(this);
RequestComplete(aMessage, KErrNone);
}
void CPosSession::HandleCancelAsyncRequestL(const RMessage2& aMessage)
{
switch (aMessage.Int0())
{
case KServerNotifyModuleStatusEventSymbian:
case KServerNotifyModuleStatusEventVariant:
case ELbsNotifyModuleStatusEvent: // TODO Verify
NotifyModuleStatusEventCancelL(aMessage);
break;
case ELbsEmptyLastKnownPositionStore:
EmptyLastKnownPositionStoreCancelL(aMessage); // TODO Verify
default:
RequestComplete(aMessage, KErrNotSupported);
break;
}
}
void CPosSession::EmptyLastKnownPositionStoreL(const RMessage2& aMessage)
{
iLocMonitorReqHandlerHub.EmptyLastKnownPosStoreReqL(aMessage);
}
void CPosSession::EmptyLastKnownPositionStoreCancelL(const RMessage2& aMessage)
{
iLocMonitorReqHandlerHub.CancelEmptyLastKnownPosStoreReqL(aMessage);
}
void CPosSession::CreateSubSessionL(TPositionModuleId aId, TBool aIsProxy, const RMessage2& aMessage)
{
CPosSubSession* subSession = CPosSubSession::NewLC(
iModuleSettings,
iLocMonitorReqHandlerHub,
aId,
aIsProxy,
&iModulesStatus,
&iModulesStatus);
TInt subSessionHandle = iSubSessionRegistry->AddInstanceL(subSession);
CleanupStack::Pop(subSession); // Now owned by registry
// Set the client subsession identifier.
TPckg<TInt> handlePackage(subSessionHandle);
TInt err = Global::Write(aMessage, KParamSubsession, handlePackage);
if (err)
{
iSubSessionRegistry->CloseSubSession(subSessionHandle);
User::Leave(err);
}
DEBUG_TRACE("Subsession created successfully", __LINE__)
}
void CPosSession::ForwardToSubSessionL(const RMessage2& aMessage)
{
CPosSubSession* subSession =
iSubSessionRegistry->SubSessionFromHandleL(aMessage.Int3());
if (!subSession)
{
User::Leave(KErrNotSupported);
}
subSession->ServiceL(aMessage);
}
void CPosSession::RequestComplete(const RMessage2& aMessage, TInt aCompleteCode)
{
if (!aMessage.IsNull())
{
aMessage.Complete(aCompleteCode);
}
}
// End of File