cryptomgmtlibs/securitycommonutils/source/scsserver/scssession.cpp
changeset 8 35751d3474b7
--- /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 <scs/scsserver.h>
+#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<TProcessId> 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<CScsSubsession*>(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<TInt> 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<CScsSubsession*>(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);
+	}
+