diff -r 000000000000 -r 094583676ce7 PECengine/StorageManager2/ServerSrc/CPEngStorageServer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PECengine/StorageManager2/ServerSrc/CPEngStorageServer.cpp Thu Dec 17 08:41:52 2009 +0200 @@ -0,0 +1,1256 @@ +/* +* Copyright (c) 2002 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: Implementation of class CPEngStorageServer +* +*/ + + +// Include Files +#include +#include +#include + + +#include "CPEngStorageServer.h" +#include "CPEngStorageSession.h" +#include "CPEngStorageFolder.h" +#include "PEngStorageServerCommon.h" +#include "TPEngServerParams.h" +#include "CPEngHandlerListenEvents.h" +#include "PEngInternalGlobalConsts.h" +#include "CPEngTimer.h" +#include "CPEngActiveScheduler.h" + +// Session Slot utility +#include "CPEngSessionSlotId.h" +#include "CPEngSessionSlotState.h" +#include "CPEngSessionSlotEvent.h" +#include "RObjectArray.h" + +// Hash Tool +#include "PEngHashTool.h" + +// Debug Prints +#include "PresenceDebugPrint.h" + + +// CONSTANTS + +// Init size of the buffer for client server communications +static const TInt KBufferInitSize = 100; + +// Static data for Capability check configuration +static const TInt KPEngStoreServRangeCount = 2; + +/** + * Ranges for the Request values + * All requests will fall in one range + */ +static const TInt PEngStoreServRanges[ KPEngStoreServRangeCount ] = + { + // Range from EMainSessShutdownServer to EFolderSubSessNotifyChangedSIDs + 0, + + // range is from EHighestStoreServerRequest request to KMaxInt + EHighestStoreServerRequest + }; + +/** + * Element indexes for the defined ranges + * we have only one range and for it is defined only one Element + */ +static const TUint8 KPEngStoreServElementsIndex[ KPEngStoreServRangeCount ] = + { + // First element in the element array will be applied for this range + 0, + // Not supported will be applied for this range + CPolicyServer::ENotSupported + }; + +// Policy elements +static const CPolicyServer::TPolicyElement KPEngStoreServElements[] = + { + { + _INIT_SECURITY_POLICY_C2( ECapabilityReadUserData, + ECapabilityWriteUserData ), + CPolicyServer::EFailClient + } + }; + +static const CPolicyServer::TPolicy KPEngServerPolicy = + { + // The index into Elements,that is used to check a connection attempt + + 0, + + // Number of ranges in the iRanges array + KPEngStoreServRangeCount, + + // A pointer to an array of ordered ranges of request numbers + PEngStoreServRanges, + + // A pointer to an array of TUint8 values specifying + // the appropriate action to take for each range in iRanges + KPEngStoreServElementsIndex, + + // A pointer to an array of distinct policy elements + KPEngStoreServElements + }; + +// MACROS +#define RETURN_IF_ERROR( aError )\ + if( aError != KErrNone )\ + {\ + return aError;\ + } + + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::CPEngStorageServer +// C++ default constructor can NOT contain any code, that might leave. +// ----------------------------------------------------------------------------- +// +CPEngStorageServer::CPEngStorageServer( TInt aPriority ) + : CPolicyServer( aPriority, KPEngServerPolicy ), + iRunning( EFalse ) + { + } + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CPEngStorageServer::ConstructL() + { + StartL( KStorageServerName ); + iBuff16.CreateL( KBufferInitSize ); + iBuff8.CreateL( KBufferInitSize ); + // create container collection + iContainerIx = CObjectConIx::NewL(); + iSubSessionCnt = iContainerIx->CreateL(); + iFoldersCnt = iContainerIx->CreateL(); + iObserversCnt = iContainerIx->CreateL(); + + // set up file system enviroment + User::LeaveIfError( iFs.Connect() );// connect to file server + // set session to the private folder + TInt err( iFs.CreatePrivatePath( EDriveC ) ); + if ( err != KErrAlreadyExists ) + { + User::LeaveIfError( err ); + } + User::LeaveIfError( iFs.SetSessionToPrivate( EDriveC ) ); + TFileName name; + iFs.SessionPath( name ); + name.Append( KPEngStorageTempFolder ); + iTempFolder = name.AllocL(); + + // make sure we have Storage folder, flush it first and then created + CFileMan* fileMan = CFileMan::NewL( iFs ); + CleanupStack::PushL( fileMan ); + fileMan->RmDir( *iTempFolder ); + // ignore errors + iFs.Delete( *iTempFolder ); + CleanupStack::PopAndDestroy(); // fileMan + // try to create temp folder + TInt er ( iFs.MkDirAll( *iTempFolder ) ); + if ( er != KErrAlreadyExists ) + { + User::LeaveIfError( er ); + } + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::NewLC +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CPEngStorageServer* CPEngStorageServer::NewL( TInt aPriority ) + { + CPEngStorageServer* self = CPEngStorageServer::NewLC( aPriority ); + CleanupStack::Pop(); + + return self; + } + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::NewLC +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CPEngStorageServer* CPEngStorageServer::NewLC( TInt aPriority ) + { + CPEngStorageServer* self = new( ELeave ) CPEngStorageServer( aPriority ); + CleanupStack::PushL( self ); + self->ConstructL(); + return self; + } + +// Destructor (virtual by CBase) +CPEngStorageServer::~CPEngStorageServer() + { + // clean all containers from the objects in it + // close all elements of the array + if ( iFoldersCnt ) + { + for ( TInt x( iFoldersCnt->Count() - 1 ) ; x >= 0 ; --x ) + { + ( *iFoldersCnt )[ x ]->Close(); + } + } + + + // close all elements of the array + if ( iObserversCnt ) + { + for ( TInt y( iObserversCnt->Count() - 1 ) ; y >= 0 ; --y ) + { + ( *iObserversCnt )[ y ]->Close(); + } + } + + // all containers are deleted with the collection + delete iContainerIx; + // clean file enviroment + iFs.Close(); + delete iTempFolder; + // shut down plugin server + delete iTimeOut; + iBuff16.Close(); + iBuff8.Close(); + } + + +// ============================================================================= +// =============== Functions from base class =================================== +// ============================================================================= + + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::ExecuteServerL() +// ----------------------------------------------------------------------------- +// +TInt CPEngStorageServer::ExecuteServerL( TPEngServerParams& aParams ) + { + //Renaming must be done as early as possible + aParams.RenameMainThread( KStorageServerName ); + + TInt res( KErrNone ); + + // start scheduler and server + CPEngActiveScheduler* pA = new( ELeave )CPEngActiveScheduler; + CleanupStack::PushL( pA ); + CPEngActiveScheduler::Install( pA ); + + //If exe server, call RunServerL directly. + TRAP( res, RunServerL( aParams ) ); + + CPEngActiveScheduler::Install( NULL ); + CleanupStack::PopAndDestroy();//pA + return res; + } + + + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::StopServer() +// ----------------------------------------------------------------------------- +// +void CPEngStorageServer::StopServer() + { + if ( iRunning ) + { + CPEngActiveScheduler::Stop(); + } + iRunning = EFalse; + } + + + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::RunServerL() +// ----------------------------------------------------------------------------- +// +void CPEngStorageServer::RunServerL( TPEngServerParams& aParams ) + { + PENG_DP( D_PENG_LIT( "CPEngStorageServer::RunServerL()" ) ); + + //One instance of server must be allocated here. + CPEngStorageServer* server = CPEngStorageServer::NewLC( KServerPriority ); + + //must die if can't signal client + aParams.Signal(); + // start fielding requests from clients + //Thread is ended when CPEngActiveScheduler::Stop is called. + server->StartServer(); + + + CleanupStack::PopAndDestroy();//server + // finished + } + + +// ============================================================================= +// =============== Functions from the MPEngStorageServer class ================= +// ============================================================================= + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::AddSubSessionL() +// ----------------------------------------------------------------------------- +// +void CPEngStorageServer::AddSubSessionL( + CObject& aSubSession ) + { + iSubSessionCnt->AddL( &aSubSession ); + } + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::RemoveSubSessionL() +// ----------------------------------------------------------------------------- +// +void CPEngStorageServer::RemoveSubSessionL( + CObject& aSubSession ) + { + iSubSessionCnt->Remove( & aSubSession ); + } + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::RegisterGlobEventListenerL() +// ----------------------------------------------------------------------------- +// +void CPEngStorageServer::RegisterGlobEventListenerL( + const RPEngMessage& /* aMessage */, + TUint32 aSessionId ) + { + CPEngHandlerListenEvents* reqHandler = FindRequestHandler( aSessionId , + EMainSessListenGlobalEvents ); + if ( reqHandler ) + { + // this handler already exists, not allowed by multiple + User::Leave( KErrAlreadyExists ); + } + // create new handler + reqHandler = CPEngHandlerListenEvents::NewLC( aSessionId ); + iObserversCnt->AddL( reqHandler ); + CleanupStack::Pop(); // newHandler + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::CancelRequestL() +// ----------------------------------------------------------------------------- +// +void CPEngStorageServer::CancelRequestL( + const RPEngMessage& aMessage, + TUint32 aSessionId ) + { + CPEngRequestHandler* reqHandler = FindRequestHandler( aSessionId, + static_cast ( aMessage.Int0() ) ); + // ignore if such a request does not exists + if ( reqHandler ) + { + reqHandler->CancelRequestD(); + } + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::CancelRequestL() +// ----------------------------------------------------------------------------- +// +void CPEngStorageServer::CancelAllSessionRequests( + TUint32 aSessionId ) + { + for ( TInt x( iObserversCnt->Count() - 1 ) ; x >= 0 ; --x ) + { + CPEngRequestHandler* handler = static_cast( ( *iObserversCnt )[ x ] ); + if ( handler->SessionId() == aSessionId ) + { + handler->CancelRequestD(); + } + } + } + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::ReloadAsynchronousScoutL() +// Reload Asynchronous scout of the async observer +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CPEngStorageServer::ReloadAsynchronousScoutL( + const RPEngMessage& aMessage, + TUint32 aSessionId ) + { + CPEngRequestHandler* reqHandler = FindRequestHandler( aSessionId, + static_cast ( aMessage.Int0() ) ); + if ( !reqHandler ) + { + // there is not such a request to be reloaded + User::Leave( KErrArgument ); + } + reqHandler->ReloadScoutWithNewMessageL( aMessage ); + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::CreateSessionFolderL() +// ----------------------------------------------------------------------------- +// +void CPEngStorageServer::CreateSessionFolderL( + const RPEngMessage& aMessage ) + { + CPEngSessionSlotId* sessId = TranslateSessionIdLC( aMessage ); + CPEngSessionSlotState* state = NULL; + CPEngStorageFolder* folder = NULL; + HBufC* stateFile = NULL; + // load state + TInt cleanUp ( LoadSessionStateLCX( *sessId, ETrue, + state, folder, stateFile ) ); + + // update state with the new application ID + aMessage.ReadOneDescriptorL( KMessageSlot1, iBuff16 ); + + // also create session slot global event for notification + CPEngSessionSlotEvent* globEvent = PackGlobEventLC( *state, + EPEngEventNWSessionSlotCreated, + iBuff16 ); + + TPtr stateFileName( stateFile->Des() ); + UpdateSessionSltStateL( folder, *state, *globEvent, stateFileName ); + + // notify about event + globEvent->PackEventL( iBuff8 ); + NotifyGlobalEvent( iBuff8 ); + + // clean globEvent, (state), stateFile, sessId + CleanupStack::PopAndDestroy( 2 + cleanUp ); + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::RemoveSessionFolderL() +// ----------------------------------------------------------------------------- +// +void CPEngStorageServer::RemoveSessionFolderL( + const RPEngMessage& aMessage ) + { + CPEngSessionSlotId* sessId = TranslateSessionIdLC( aMessage ); + CPEngSessionSlotState* state = NULL; + CPEngStorageFolder* folder = NULL; + HBufC* stateFile = NULL; + // load state + TInt cleanUp ( LoadSessionStateLCX( *sessId, + EFalse, + state, + folder, + stateFile ) ); + + if ( folder ) + { + // folder is active, refuse any deletion + User::Leave( KErrInUse ); + } + // remove registered ID from the session + aMessage.ReadOneDescriptorL( KMessageSlot1, iBuff16 ); + + // also create session slot global event for notification + CPEngSessionSlotEvent* globEvent = PackGlobEventLC( + *state, + EPEngEventNWSessionSlotRemoved, + iBuff16 ); + + TPtr stateFileName( stateFile->Des() ); + UpdateSessionSltStateL( folder, *state, *globEvent, stateFileName ); + + // notify about event + globEvent->PackEventL( iBuff8 ); + NotifyGlobalEvent( iBuff8 ); + + // clean globEvent, (state), stateFile, sessId + CleanupStack::PopAndDestroy( 2 + cleanUp ); + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::SessionStateL() +// ----------------------------------------------------------------------------- +// +void CPEngStorageServer::SessionStateL( + const RPEngMessage& aMessage ) + { + CPEngSessionSlotId* sessId = TranslateSessionIdLC( aMessage ); + CPEngStorageFolder* folder = FindStorageFolder( *sessId ); + CPEngSessionSlotState* state = NULL; + if ( folder ) + { + state = &( folder->SessionSlotState() ); + } + else + { + HBufC* stateFile = NULL; + state = ReadSessionStatePermanentLC( *sessId, stateFile ); + } + + state->PackDataL( EPureState, iBuff8 ); + + TInt err( aMessage.WriteOneDescriptor( KMessageSlot1, iBuff8 ) ); + if ( err == KErrOverflow ) + { + User::Leave( iBuff8.Length() ); + } + User::LeaveIfError( err ); + + if ( !folder ) + { + CleanupStack::PopAndDestroy( 2 ); // state, stateFile + } + CleanupStack::PopAndDestroy(); // sessId + } + + + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::AllSessionStatesL() +// ----------------------------------------------------------------------------- +// +void CPEngStorageServer::AllSessionStatesL( + const RPEngMessage& aMessage ) + { + // pack all states to one big buffer + // this takes all active folders and adds sessions not active + CDir* dirList = NULL; + TFileName dir; + User::LeaveIfError( iFs.PrivatePath( dir ) ); + // insert drive leter on the beginning + dir.Insert( 0, KPEngStorageDrive ); + + User::LeaveIfError( iFs.GetDir( dir, + KEntryAttNormal, + ESortByName, + dirList ) ); + CleanupStack::PushL( dirList ); + TInt count( dirList->Count() ); + RObjectArray states; + CleanupClosePushL( states ); + // 4 for the count of the states + TInt size( 4 ); + for ( TInt x( 0 ) ; x < count ; x++ ) + { + const TEntry& entry = ( *dirList )[ x ]; + if ( ! entry.IsDir() ) + { + CPEngSessionSlotState* state = CPEngSessionSlotState::NewLC(); + ReadFileL( entry.iName, iBuff8 ); + state->UnpackDataL( iBuff8, EPermanentData ); + states.AppendL( state ); + size += state->Size( EPermanentData ); + CleanupStack::Pop(); // state + } + } + // now go through all session and if they are loaded as folders + // and pack them to the buffer + // get buffer for transfer + CBufFlat* buf = CBufFlat::NewL( size ); + CleanupStack::PushL( buf ); + RBufWriteStream ws; + CleanupClosePushL( ws ); + ws.Open( *buf ); // CSI: 65 # + + // write count of all sessions + count = states.Count(); + ws.WriteInt32L( count ); + + for ( TInt i( 0 ) ; i < count ; i++ ) + { + CPEngStorageFolder* folder = FindStorageFolder( + states[ i ]->SessionSlotId() ); + if ( folder ) + { + // there is loaded folder, take state from there + folder->SessionSlotState().ExternalizeL( ws, EWholeState ); + } + else + { + states[ i ]->ExternalizeL( ws, EWholeState ); + } + } + // write data to the client side + TInt err( aMessage.WriteOneDescriptor( KMessageSlot0, buf->Ptr( 0 ) ) ); + if ( err == KErrOverflow ) + { + User::Leave( buf->Ptr( 0 ).Length() ); + } + User::LeaveIfError( err ); + CleanupStack::PopAndDestroy( 4 ); // ws, buf, states, dirList, + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::StorageFolderL() +// ----------------------------------------------------------------------------- +// +CPEngStorageFolder* CPEngStorageServer::StorageFolderL( + const RPEngMessage& aMessage ) + { + CPEngSessionSlotId* sessId = TranslateSessionIdLC( aMessage ); + CPEngStorageFolder* folder = LoadStorageFolderL( *sessId ); + CleanupStack::PopAndDestroy(); // sessId + return folder; + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::NotifyGlobalEvent() +// ----------------------------------------------------------------------------- +// +void CPEngStorageServer::NotifyGlobalEvent( + const TDesC8& aGlobalEvent ) + { + // better to go through array from end + for ( TInt x( iObserversCnt->Count() - 1 ) ; x >= 0 ; x-- ) + { + CPEngHandlerListenEvents* handler = + static_cast( ( *iObserversCnt )[ x ] ); + handler->NotifyEvent( aGlobalEvent ); + } + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::NotifyError() +// ----------------------------------------------------------------------------- +// +void CPEngStorageServer::NotifyError( + TInt aError ) + { + // better to go through array from end + for ( TInt x( iObserversCnt->Count() - 1 ) ; x >= 0 ; x-- ) + { + CPEngHandlerListenEvents* handler = + static_cast( ( *iObserversCnt )[ x ] ); + handler->NotifyError( aError ); + } + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::IsAppIdRegisteredL() +// ----------------------------------------------------------------------------- +// +void CPEngStorageServer::IsAppIdRegisteredL( + const RPEngMessage& aMessage ) + { + CPEngSessionSlotId* sessId = TranslateSessionIdLC( aMessage ); + aMessage.ReadOneDescriptorL( KMessageSlot1, iBuff16 ); + + CPEngSessionSlotState* state = NULL; + CPEngStorageFolder* folder = NULL; + HBufC* stateFile = NULL; + // load state + TInt cleanUp ( LoadSessionStateLCX( *sessId, ETrue, + state, folder, stateFile ) ); + // check if appId is registered + state->ApplicationRegisteredL( iBuff16 ); + // clean (state),stateFile,appId,sessId + CleanupStack::PopAndDestroy( cleanUp + 2 ); + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::BackUpActive() +// ----------------------------------------------------------------------------- +// +TBool CPEngStorageServer::BackUpActive() + { + return iBackUpActive; + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::WipeSessionSlotFolderL() +// ----------------------------------------------------------------------------- +// +void CPEngStorageServer::WipeSessionSlotFolderL( + const RPEngMessage& aMessage ) + { + CPEngSessionSlotId* sessId = TranslateSessionIdLC( aMessage ); + CPEngSessionSlotState* state = NULL; + CPEngStorageFolder* folder = NULL; + HBufC* stateFile = NULL; + // load state + TInt cleanUp ( LoadSessionStateLCX( *sessId, + EFalse, + state, + folder, + stateFile ) ); + + if ( folder ) + { + // folder is active, refuse any deletion + User::Leave( KErrInUse ); + } + + TPtr stateFileName( stateFile->Des() ); + User::LeaveIfError( CleanStorageFromSessionL( stateFileName ) ); + + // clean globEvent, (state), stateFile, sessId + CleanupStack::PopAndDestroy( 1 + cleanUp ); + } + + +// ============================================================================= +// ======== New function of the CPEngStorageServer ===================== +// ============================================================================= + + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::SessionCreated() +// Session has been created +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CPEngStorageServer::SessionCreated() + { + iSessCount++; + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::SessionDied() +// ----------------------------------------------------------------------------- +// +void CPEngStorageServer::SessionDied() + { + iSessCount--; + if ( iSessCount == 0 ) + { + // Start timer + delete iTimeOut; + iTimeOut = NULL; + + TRAP_IGNORE( + { + iTimeOut = CPEngTimer::NewL( *this ); + iTimeOut->After( KServerCloseTimeOut ); + } ); + } + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::TimeExpired() +// ----------------------------------------------------------------------------- +// +void CPEngStorageServer::TimeExpired() + { + if ( iSessCount == 0 ) + { + // stop server + StopServer(); + } + } + + +// ============================================================================= +// =============== Functions from the MBackupOperationObserver class =========== +// ============================================================================= + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::HandleBackupOperationEventL() +// Called when a backup or restore operation either starts or ends. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// Restore is not implemented before new API won't be delivered +/* +void CPEngStorageServer::HandleBackupOperationEventL( + const TBackupOperationAttributes& aBackupOperationAttributes) + { + } +*/ +// ============================================================================= +// =============== Functions from the CServer2 class =========================== +// ============================================================================= + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::NewSessionL() +// ----------------------------------------------------------------------------- +// +CSession2* CPEngStorageServer::NewSessionL( + const TVersion &aVersion, + const RMessage2& /*aMessage*/ ) const + { + if ( !User::QueryVersionSupported( aVersion, TVersion( + KRequiredVersionMajor, + KRequiredVersionMinor, + KRequiredVersionBuild ) ) ) + { + User::Leave( KErrNotSupported ); + } + + return CPEngStorageSession::NewL( const_cast( *this ) ); + } + + +// ============================================================================= +// =============== New Private methods from class ============================== +// ============================================================================= + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::StartServer() +// Start Server +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CPEngStorageServer::StartServer() + { + iRunning = ETrue; + PENG_DP( D_PENG_LIT( "PECStorageServer::Started" ) ); + CPEngActiveScheduler::Start(); + PENG_DP( D_PENG_LIT( "PECStorageServer::Stopped" ) ); + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::TranslateSessionIdLC() +// Read Session ID from the client's message +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +CPEngSessionSlotId* CPEngStorageServer::TranslateSessionIdLC( + const RPEngMessage& aMessage ) + { + // 0 slot of the message has always session identification if required + CPEngSessionSlotId* sessId = CPEngSessionSlotId::NewLC(); + + aMessage.ReadOneDescriptorL( KMessageSlot0, iBuff8 ); + sessId->UnPackL( iBuff8 ); + return sessId; + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::FindStorageFolder() +// Try to find session Folder if it is active +// if folder is not active, it returns NULL pointer +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +CPEngStorageFolder* CPEngStorageServer::FindStorageFolder( + const CPEngSessionSlotId& aSessionId ) + { + // look for the session + TInt count( iFoldersCnt->Count() ); + for ( TInt x( 0 ) ; x < count ; x++ ) + { + CPEngStorageFolder* folder = + static_cast ( ( *iFoldersCnt )[ x ] ); + if ( KErrNone == folder->SessionSlotState().SessionSlotId().Match( aSessionId ) ) + { + return folder; + } + } + return NULL; + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::LoadStorageFolderL() +// Load storage folder, +// there is open handle to the returner pointer +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +CPEngStorageFolder* CPEngStorageServer::LoadStorageFolderL( + const CPEngSessionSlotId& aSessionId ) + { + CPEngStorageFolder* folder = FindStorageFolder( aSessionId ); + if ( folder ) + { + TInt val = folder->Open(); // CSI: 65 # + return folder; + } + + // read session state from permanent store + HBufC* stateFile = NULL; + CPEngSessionSlotState* state = ReadSessionStatePermanentLC( aSessionId, + stateFile ); + + // it makes directory if does not exists + TPtr fileName = stateFile->Des(); + UpdateFileToFolderName( fileName ); + + // create folder class, pass state + CPEngStorageFolder* newFolder = CPEngStorageFolder::NewL( iFs, + *iTempFolder, + iBuff16 ); + CleanupClosePushL( *newFolder ); + + // update Folder path to include, session part + TFileName sessPath; + User::LeaveIfError( iFs.SessionPath( sessPath ) ); + stateFile = stateFile->ReAllocL( stateFile->Length() + + sessPath.Length() ); + stateFile->Des().Insert( 0, sessPath ); + + CleanupStack::Pop(); //newFolder + CleanupStack::Pop( 2 ); // state, stateFile + + // following functions are transfering ownership + newFolder->SetSessionSlotState( *state ); + newFolder->SetSessionFolder( * stateFile ); + + // add folder to the folders container + CleanupClosePushL( * newFolder ); + iFoldersCnt->AddL( newFolder ); + CleanupStack::Pop(); // newFolder + return newFolder; + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::LoadSessionStateLCX() +// Load session slot state +// If there is Storage folder for this session +// then state is taken from it, while nothing is put on clean up stack +// if not, then state is loaded from state file, +// if file does not exist, depends on the aCreate flag, can be +// created or it leave with KErrNotFound +// order items on clan up stack is: aStateFileName, +// or aStateFileName, aSessState +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TInt CPEngStorageServer::LoadSessionStateLCX( + CPEngSessionSlotId& aSessId, + TBool aCreate, + CPEngSessionSlotState*& aSessState, + CPEngStorageFolder*& aStorageFolder, + HBufC*& aStateFileName ) + { + aStorageFolder = FindStorageFolder( aSessId ); + // was state folder found or not + if ( aStorageFolder ) + { + aSessState = &( aStorageFolder->SessionSlotState() ); + aStateFileName = PEngHashTool::HashStateNameL( // CSI: 42 # + aSessState->SessionSlotId().ServiceAddress(), + aSessState->SessionSlotId().UserId() ); + CleanupStack::PushL( aStateFileName ); // CSI: 42 # + return 1; + } + if ( !aCreate ) + { + aSessState = ReadSessionStatePermanentLC( aSessId, aStateFileName ); // CSI: 42 # + return 2; + } + + // if it won't exist create it, so we need to trap leave + TRAPD( e, + { + aSessState = ReadSessionStatePermanentLC( aSessId, + aStateFileName ); + // we need to fool TRAP CleanUp level check + CleanupStack::Pop( 2 ); + } ); + + // put those elements back to CleanUpStack + if ( e == KErrNone ) + { + CleanupStack::PushL( aStateFileName ); // CSI: 42 # + CleanupStack::PushL( aSessState ); // CSI: 42 # + } + + // does even the file exist? + else if ( e == KErrNotFound ) + { + // file does not exists, create state file and folder + aStateFileName = PEngHashTool::HashStateNameL( aSessId.ServiceAddress(), // CSI: 42 # + aSessId.UserId() ); + CleanupStack::PushL( aStateFileName ); // CSI: 42 # + aSessState = CPEngSessionSlotState::NewLC(); // CSI: 42 # + aSessState->SetSessionSlotId( aSessId, EFalse ); + TPtr fileName = aStateFileName->Des(); + CreateSessionDirectoryL( fileName ); // CSI: 42 # + } + else + { + // was there some other error? + User::LeaveIfError( e ); // CSI: 42 # + } + return 2; + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::ReadSessionStatePermanentLC() +// Read State file from permanent store if it does exists +// Function returns Session Slot state and des buffer with +// session slot state file name ownership of both is transfered +// to the calling client +// both items are left on clean up stack, while state is topest one +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +CPEngSessionSlotState* CPEngStorageServer::ReadSessionStatePermanentLC( + const CPEngSessionSlotId& aSessionId, + HBufC*& aFileName ) + { + // Folder is not activated yet, check if folder does exist in the store + // get folder name of the session + aFileName = PEngHashTool::HashStateNameL( + aSessionId.ServiceAddress(), + aSessionId.UserId() ); + CleanupStack::PushL( aFileName ); + + // try to get state of the session if it exists + CPEngSessionSlotState* state = CPEngSessionSlotState::NewLC(); + ReadFileL( *aFileName, iBuff8 ); + state->UnpackDataL( iBuff8, EPermanentData ); + return state; + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::UpdateFileToFolderName() +// Modify State file name to folder name +// Functions remove state suffix from file name and replaces is with +// folder delimiter characters +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CPEngStorageServer::UpdateFileToFolderName( + TDes& aFileName ) + { + aFileName.SetLength( aFileName.Length() - + KPEngStorageStateSuffix().Length() ); + aFileName.Append( KDirDelim ); + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::CreateSessionDirectoryL() +// Create session directory in the file system +// Passed buffer is used, modified to sued session folder +// and then back to the state as it was before +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CPEngStorageServer::CreateSessionDirectoryL( + TDes& aFileName ) + { + // make directory if does not exists + UpdateFileToFolderName( aFileName ); + TFileName folderName; + iFs.SessionPath( folderName ); + folderName.Append( aFileName ); + TInt err( iFs.MkDirAll( folderName ) ); + // ignore KErrAlreadyExist + err = ( err == KErrAlreadyExists ? KErrNone : err ); + User::LeaveIfError( err ); + // modify folder name back to the state file name + aFileName.SetLength( aFileName.Length() - KDirDelimLength ); + aFileName.Append( KPEngStorageStateSuffix ); + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::StoreFile() +// Store data to the file +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TInt CPEngStorageServer::StoreFile( + const TDesC& aFileName, + const TDesC8& aData ) + { + // open temp file, write date into it and rename it to the correct file + RFile temp; + TFileName fName; + TInt err( temp.Temp( iFs, *iTempFolder, fName, EFileShareExclusive ) ); + RETURN_IF_ERROR( err ); + err = temp.Write( aData ); + if ( ( err != KErrNone ) ) + { + temp.Close(); + return err; + } + err = temp.Flush(); + temp.Close(); + RETURN_IF_ERROR( err ); + + err = iFs.Delete( aFileName ); + if ( ( err != KErrNone ) && ( err != KErrNotFound ) ) + { + return err; + } + return iFs.Rename( fName, aFileName ); + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::ReadFileL() +// Read data from the file +// if file does not exists function will leave +// returned buffer is left on the clean up stack +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CPEngStorageServer::ReadFileL( + const TDesC& aFileName, + RBuf8& aBuff ) + { + RFile f; + User::LeaveIfError( f.Open( iFs, aFileName, EFileRead ) ); + CleanupClosePushL( f ); + TInt size( 0 ); + User::LeaveIfError( f.Size( size ) ); + if ( size > aBuff.MaxSize() ) + { + aBuff.ReAllocL( size ); + } + aBuff.Zero(); + User::LeaveIfError( f.Read( aBuff ) ); + CleanupStack::PopAndDestroy(); // f + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::CleanStorageFromSessionL() +// Clean storage from session +// Function deletes session folder and session state +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TInt CPEngStorageServer::CleanStorageFromSessionL( TDes& aFileName ) + { + // delete directory + UpdateFileToFolderName( aFileName ); + TFileName sessionFolder; + iFs.SessionPath( sessionFolder ); + sessionFolder.Append( aFileName ); + + CFileMan* fileMan = CFileMan::NewL( iFs ); + CleanupStack::PushL( fileMan ); + TInt err( fileMan->RmDir( sessionFolder ) ); + CleanupStack::PopAndDestroy(); // fileMan + RETURN_IF_ERROR( err ); + + // modify folder name back to the state file name + aFileName.SetLength( aFileName.Length() - KDirDelimLength ); + aFileName.Append( KPEngStorageStateSuffix ); + + // try to delete file + return iFs.Delete( aFileName ); + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::PackGlobEventLC() +// Create Buffer with global event from the passed +// state and event enumeration, and application Id +// Function deletes session folder and session state +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +CPEngSessionSlotEvent* CPEngStorageServer::PackGlobEventLC( + CPEngSessionSlotState& aState, + TPEngNWSessionSlotEvent aEvent, + const TDesC& aAppId ) + { + CPEngSessionSlotEvent* newEvent = CPEngSessionSlotEvent::NewLC(); + newEvent->SetSessionSlotId( &( aState.SessionSlotId() ), EFalse ); + newEvent->SetAppIdL( aAppId ); + newEvent->SetSessSltEvent( aEvent ); + newEvent->SetAppSessSltState( aState.AppState( aAppId ) ); + newEvent->SetGlobSessSltState( aState.SessionSlotState() ); + return newEvent; + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::UpdateSessionSltStateL() +// Update Session Slot state +// Passed session slot folder pointer can be NULL, then +// session slot state reference is used instead +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CPEngStorageServer::UpdateSessionSltStateL( + CPEngStorageFolder* aFolder, + CPEngSessionSlotState& aState, + CPEngSessionSlotEvent& aEvent, + TDes& aFileName ) + { + // do we need to do permanent store update? + if ( aState.UpdateStateL( aEvent ) ) + { + // store changes + aState.PackDataL( EPermanentData, iBuff8 ); + + // open file and store there data + TInt e ( StoreFile( aFileName, iBuff8 ) ); + if ( e != KErrNone ) + { + // remove the ID from the sate, this is for case folder is active + aState.RollBackLastUpdate(); + User::Leave( e ); + } + } + aState.CommitLastUpdate(); + if ( aFolder ) + { + aFolder->CommiteStateUpdate(); + } + + // shall we clean storage? + if ( aState.RegisteredApplications().MdcaCount() == KErrNone ) + { + CleanStorageFromSessionL( aFileName ); + } + } + + + +// ============================================================================= +// ============= New notification engine functions ============================= +// ============================================================================= + +// ----------------------------------------------------------------------------- +// CPEngStorageServer::FindRequestHandler() +// Find Request Handler +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +CPEngHandlerListenEvents* CPEngStorageServer::FindRequestHandler( + TUint32 aSessionId, + TPEngStorageServerMessages aFunction ) + { + TInt count( iObserversCnt->Count() ); + for ( TInt x( 0 ) ; x < count ; x++ ) + { + CPEngHandlerListenEvents* reqHandler = static_cast( ( *iObserversCnt )[ x ] ); + if ( ( reqHandler->SessionId() == aSessionId ) + && ( reqHandler->RequestFunction() == aFunction ) ) + { + return reqHandler; + } + } + return NULL; + } + +// End of File