diff -r 675a964f4eb5 -r 35751d3474b7 cryptomgmtlibs/securitycommonutils/source/scsserver/scssession.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cryptomgmtlibs/securitycommonutils/source/scsserver/scssession.cpp Thu Sep 10 14:01:51 2009 +0300 @@ -0,0 +1,380 @@ +/* +* Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the License "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: +* CScsSession implementation. See class and function definitions +* for more detail. +* +*/ + + +/** + @file +*/ + + +#include +#include "scsserverconstants.h" + +EXPORT_C void CScsSession::ConstructL() +/** + The subsession [handle] container could be constructed + here, but that is deferred until the subsession is allocated to + avoid the memory overhead for sessions which may not require + subsessions. + */ + { + iServer.IncrementSessionCount(); + } + +EXPORT_C CScsSession::CScsSession(CScsServer &aServer) + : iServer(aServer) +/** + Setup the iServer member variable so it can be used during construction + */ + { + } + + +EXPORT_C CScsSession::~CScsSession() +/** + Deletes any subsessions. + + Deletes any outstanding requests. + + Decrements the server's session count so the server can be shut down + if there are no open sessions. + */ + { + iServer.CancelOutstandingRequests(this, /* aCompleteClientRequests */ EFalse); + + DeleteSubsessionContainers(); // closes any remaining subsessions + + // decrement the session count, so the server can be shut down if + // there are no more open sessions. + iServer.DecrementSessionCount(); + } + +EXPORT_C void CScsSession::CloseAllSubsessionsL() + { + DeleteSubsessionContainers(); + } + +EXPORT_C void CScsSession::ServiceL(const RMessage2& aMessage) +/** + Implement CSession2 by handling any SCS-specific messages, and + otherwise delegating to the subclass' implementation. + + @param aMessage Standard server-side message object. + */ + { + ScsImpl::TScsFunction scsFunc; + TInt implFunc; + ScsImpl::ExtractScsAndImplFunctions(aMessage, &scsFunc, &implFunc); + TBool completeMessage = ETrue; + + switch (scsFunc) + { + // sessions + case ScsImpl::ECallSessionFunc: + completeMessage = DoServiceL(implFunc, aMessage); + break; + + case ScsImpl::EPreCloseSession: + PreCloseSession(); + break; + + case ScsImpl::ECancelSessionFunc: + CancelAsyncSessionRequestL(implFunc); + break; + + case ScsImpl::EGetServerPid: + { + TPckgBuf idBuf; + RProcess proc; + idBuf() = proc.Id(); + aMessage.WriteL(0, idBuf); + break; + } + + case ScsImpl::EShutdownAsap: + iServer.ShutdownWhenIdleL(); + break; + + // subsessions + case ScsImpl::ECreateSubsession: + // if there are no open subsessions before this attempt then clean up + // the containers if it fails. This is to ensure the server heap balances + // in the event of failure. + iPreCreateSubsessionCount = iSsHandles ? iSsHandles->ActiveCount() : 0; + CreateSubsessionL(implFunc, aMessage); + break; + + case ScsImpl::ECloseSubsession: + CloseSubsessionL(aMessage); + break; + + case ScsImpl::ECallSubsessionFunc: + completeMessage = CallSubsessionFunctionL(implFunc, aMessage); + break; + + case ScsImpl::ECancelSubsessionFunc: + CancelAsyncSubsessionRequestL(implFunc, aMessage); + break; + + // server heap testing + case ScsImpl::EUHeapSetFail: +#ifdef _DEBUG + iServer.DoPreHeapMarkOrCheckL(); + __UHEAP_MARK; + __UHEAP_SETFAIL(RAllocator::EDeterministic, aMessage.Int0()); + iServer.DoPostHeapMarkOrCheckL(); +#endif + break; + + case ScsImpl::EUHeapResetFail: +#ifdef _DEBUG + iServer.DoPreHeapMarkOrCheckL(); + __UHEAP_RESET; + __UHEAP_MARKEND; + iServer.DoPostHeapMarkOrCheckL(); +#endif + break; + + // unrecognized SCS code, so fail with KErrNotSupported + default: + User::Leave(KErrNotSupported); + } + + // None of the delegate functions have left so complete with KErrNone. + if(completeMessage) + { + aMessage.Complete(KErrNone); + } + } + +EXPORT_C void CScsSession::ServiceError(const RMessage2& aMessage, TInt aError) +/** + Override CSession2 by handling any leave which occurred during the ServiceL. + + Panick the client if the leave is because of a bad descriptor or subsession + handle. Otherwise, complete the request with the error code. + + @param aMessage Message which caused leave to occur. + @param aError Leave code. This is a Symbian OS error code. + @see CSession2::ServiceError + */ + { + // if failed to create first subsession then free containers so heap + // balances after message has been completed. + + ScsImpl::TScsFunction scsFunc; + ScsImpl::ExtractScsAndImplFunctions(aMessage, &scsFunc, NULL); + + if (scsFunc == ScsImpl::ECreateSubsession && iPreCreateSubsessionCount == 0) + DeleteSubsessionContainers(); + + switch (aError) + { + case KErrBadDescriptor: + PanicClient(aMessage, ScsImpl::EScsClBadDesc); + break; + + case KErrBadHandle: + PanicClient(aMessage, ScsImpl::EScsClBadHandle); + break; + + case KErrScsAsyncAlreadyQueued: + PanicClient(aMessage, ScsImpl::EScsClAsyncAlreadyQueued); + break; + + default: + aMessage.Complete(aError); + break; + } + } + +// -------- session close -------- + +void CScsSession::PreCloseSession() +/** + This function is invoked from RScsClientBase::Close + just before the session is closed, to cancel any + outstanding requests. + */ + { + iServer.CancelOutstandingRequests(this, /* aCompleteClientRequests */ ETrue); + } + +// -------- asynchronous requests -------- + +void CScsSession::CancelAsyncSessionRequestL(TInt aFunction) +/** + This function is called when handling an ECancelSessionFunction message. + If the outstanding function cannot be found, this function does nothing. + + @param aFunction Implementation function without SCS code. + */ + { + iServer.CancelAsyncRequest(this, /* aSubsession */ 0, aFunction); + } + +// -------- subsessions -------- + +CScsSubsession* CScsSession::GetSubsessionL(const RMessage2& aMessage) +/** + Extract subsession handle from the supplied message and return + a pointer to the corresponding subsession object. + + @param aMessage Standard server-side message object. The fourth + argument is the subsession handle. + @return Pointer to corresponding subsession object. + @leave KErrBadHandle if the handle does not identify a + current subsession. + */ + { + TInt handle = aMessage.Int3(); + CObject* obj = iSsHandles->AtL(handle); // leaves with KErrBadHandle if not found + return static_cast(obj); + } + +void CScsSession::DeleteSubsessionContainers() +/** + Free the handle and object containers which this session uses + to manage subsessions. It is safe to call this function if the + containers were not set up successfully. + */ + { + delete iSsHandles; + iSsHandles = 0; + + if (iSsObjects != 0) + { + iServer.iContainerIndex->Remove(iSsObjects); + iSsObjects = 0; + } + } + +void CScsSession::CreateSubsessionL(TInt aFunction, const RMessage2& aMessage) +/** + Attempt to allocate a subsession object for this session. The actual + subsession allocation is delegated to the subclass's implementation + of DoCreateSubsessionL. If the subclass has not reimplemented this + function, then default implementation leaves with KErrNotSupported. + + @param aFunction Function identifier without SCS code. + @param aMessage Standard server-side message object. + */ + { + // if this is the first subsession then create the object container and index + if (iSsObjects == 0) + { + iSsObjects = iServer.iContainerIndex->CreateL(); + iSsHandles = CObjectIx::NewL(); + } + + CScsSubsession* ss = DoCreateSubsessionL(aFunction, aMessage); + CleanupClosePushL(*ss); + + iSsObjects->AddL(ss); + TInt handle = iSsHandles->AddL(ss); + CleanupStack::Pop(ss); + + TPckg handlePckg(handle); + TInt r = aMessage.Write(3, handlePckg); + User::LeaveIfError(r); + } + +#ifdef _BullseyeCoverage +static const char * const bull1="BullseyeCoverage save off"; +#endif +EXPORT_C CScsSubsession* CScsSession::DoCreateSubsessionL(TInt aFunction, const RMessage2& aMessage) +/** + This default implementation leaves with KErrNotSupported. The subclass + does not have to supply its own implementation unless it actually wants + to support subsessions. + + @param aFunction Function identifier without SCS code. The subclass + implementation of this function would use this to decide + what kind of subsession object to create. + @param aMessage Client message. Not used. + @leave KErrNotSupported. + */ + { + (void) aFunction; + (void) aMessage; + + User::Leave(KErrNotSupported); + /*lint -unreachable*/ // Avoid compiler warning and keep lint happy + return 0; + } +#ifdef _BullseyeCoverage +static const char * const bull2="BullseyeCoverage restore"; +#endif + +void CScsSession::CloseSubsessionL(const RMessage2& aMessage) +/** + Delete the subsession identified in the supplied message. + + If the subsession cannot be found this function leaves with KErrBadHandle, + and the client is panicked in ServiceError. + + @param aMessage Standard server-side message handle. The fourth + integer contains the subsession handle. + */ + { + TInt handle = aMessage.Int3(); + CObject* obj = iSsHandles->AtL(handle); // leaves with KErrBadHandle if not found + CScsSubsession* ss = static_cast(obj); + + iServer.CancelOutstandingRequests(this, ss, /* aCancelClientRequests */ ETrue); + + iSsHandles->Remove(handle); + + // close the container objects to ensure the heap balances when the last subsession is closed + if (iSsHandles->ActiveCount() == 0) + DeleteSubsessionContainers(); + } + +TBool CScsSession::CallSubsessionFunctionL(TInt aFunction, const RMessage2& aMessage) +/** + Pass the supplied function identifier and message to the subsession + which is identified in the message. + + If the subsession cannot be found this function leaves with KErrBadHandle, + and the client is panicked in ServiceError. + + @param aFunction Function identifier without SCS code. + @param aMessage Client message. + @return ETrue means complete client request now. + + */ + { + CScsSubsession* ss = GetSubsessionL(aMessage); + return ss->DoServiceL(aFunction, aMessage); + } + +void CScsSession::CancelAsyncSubsessionRequestL(TInt aFunction, const RMessage2& aMessage) +/** + Cancel an outstanding asynchronous request for the subsession + identified in the supplied message. + + @param aFunction Function identifier without SCS code. + @param aMessage Standard server-side message handle. The fourth + integer contains the subsession handle. + */ + { + CScsSubsession* ss = GetSubsessionL(aMessage); + iServer.CancelAsyncRequest(this, ss, aFunction); + } +