cryptomgmtlibs/securitycommonutils/inc/scsserver.h
changeset 8 35751d3474b7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cryptomgmtlibs/securitycommonutils/inc/scsserver.h	Thu Sep 10 14:01:51 2009 +0300
@@ -0,0 +1,400 @@
+/*
+* 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: 
+* Server-side classes which are required to implement a session counting server.
+*
+*/
+
+
+/**
+ @file
+ @publishedPartner
+ @released
+*/
+
+#ifndef SCSSERVER_H
+#define SCSSERVER_H
+
+#include <e32base.h>
+
+#include <scs/scsclient.h>
+#include <scs/scscommon.h>
+
+#ifndef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include "scsserverconstants.h"
+#endif
+
+// -------- error handling --------
+
+
+const TInt KErrScsAsyncAlreadyQueued = -5702;	///< Tried to re-queue an outstanding request.
+
+
+
+// forward declarations
+class CScsServer;
+class CScsSession;
+class CScsSubsession;
+
+class CShutdownTimer : public CTimer
+/**
+	When an instance of this class is constructed it is given a delay period.
+	If the object runs to completion, i.e. if it is not cancelled, then it stops
+	the active scheduler, which has the effect of terminating the server.
+*/
+	{
+public:
+	static CShutdownTimer* NewL(TInt aDelayUs);
+
+	void Restart();
+
+	void ImmediateTimeoutNextRestart();
+
+private:
+	CShutdownTimer(TInt aDelayUs);
+
+	// implement CTimer
+	virtual void RunL();
+
+private:
+	TInt iDelayUs;			///< Timer delay in microseconds.
+	TBool iImmediateTimeoutNextRestart;
+	};
+
+class CAsyncRequest : public CActive
+/**
+	An outstanding request on the server side.	A subclass should
+	be created for each type of outstanding request.
+
+	This class is implemented as an active object, because it is
+	anticipated that some asynchronous requests can be implemented
+	simply by completing the client request when a TRequestStatus
+	completes.	The implementor can override this behavior by
+	re-implementing RunL, e.g. to free some resources before completing
+	the request.  If they do so, they must call CompleteAndMarkForDeletion to 
+	complete the client request and mark this object for deletion (alternatively
+	they can simply call CAsyncRequest::RunL from their RunL).
+
+	This class cannot, however, anticipate the cancellation
+	mechanism.	The implementor must implement DoCancel for that.
+	DoCancel should not delete the client request or mark this object
+	for deletion.
+
+	When the implementor has allocated an instance of this
+	class, they must add it to the session by calling CAsyncRequest::TransferToScsFrameworkL.
+	The second-phase constructor must not  leave between that and calling
+	SetActive.
+
+	These objects are cancelled and destroyed when the
+	client-side session / subsession sends a cancel command.
+
+	@see CScsSession::AddAsyncRequestL
+*/
+	{
+public:
+	IMPORT_C CAsyncRequest(CScsSession* aSession, CScsSubsession* aSubsession, const RMessage2& aMessage);
+	
+	void CancelCompleteAndMarkForDeletion();	// explicit cancel request
+	void MarkForDeletion();						// session close
+	IMPORT_C virtual void DoCleanup();	// Cancel this request
+	
+	IMPORT_C void TransferToScsFrameworkL();
+protected:
+	
+	IMPORT_C void CompleteAndMarkForDeletion(TInt aError);
+	
+	// implement CActive
+	IMPORT_C virtual void RunL();
+
+	// override CActive
+	IMPORT_C virtual TInt RunError(TInt aError);
+		
+public:
+	/** Session on which this request is queued.  NULL if completed. */
+	CScsSession* iSession;
+	/** Subsession on which this request is queued.	 NULL if session-relative. */
+	CScsSubsession* iSubsession;
+	/** Outstanding message to complete. */
+	const RMessagePtr2 iMessagePtr2;
+	/** Identifies outstanding request. */
+	TInt iFunction;
+	};
+
+class CScsSubsession : public CObject
+/**
+	If the server implementation supports subsessions, they must
+	derive from this class.
+
+	WARNING: Because this class derives from CObject you must not simply delete
+	an instance of a class derived from this class (ie. your subsession), instead you MUST
+	Close() it. 
+
+	In practise this probably means you need a ConstructL like this:-
+	CFred *self = new(ELeave) CFred(....);
+	CleanupClosePushL(*self); // Note use of CleanupClosePushL and of *self
+	self->ConstructL(...);
+	CleanupStack::Pop(self); // Note use of *self instead of self
+ */
+	{
+public:
+	/**
+		SCS routes subsession messages to this function; the session
+		object does not have to decode them	 itself.
+
+		@param	aFunction		Implementation function, i.e. the function
+								identifier with the SCS field removed.
+		@param	aMessage		Standard server message object.
+		@return ETrue means complete client request now.
+	 */
+	virtual TBool DoServiceL(TInt aFunction, const RMessage2& aMessage) = 0;
+
+protected:
+	IMPORT_C CScsSubsession(CScsSession &aSession);
+	
+public:
+	// Note this is setup by the constructor, before the derived class
+	// ConstructL is called.
+	CScsSession& iSession;			///< Owning session.
+	};
+
+class CScsSession : public CSession2
+/**
+	When this session object is destroyed (because the client-server session
+	has closed,) this notifies the server object which decrements the session
+	count.	Therefore, the server can be shut down after an inactivity
+	period during which there are no open sessions.
+
+	This object also frees any remaining subsession objects when it is closed.
+*/
+	{
+protected:
+	IMPORT_C void ConstructL();
+	IMPORT_C virtual ~CScsSession();
+	
+	// implement CSession2
+	IMPORT_C virtual void ServiceL(const RMessage2& aMessage);
+	// override CSession2
+	IMPORT_C virtual void ServiceError(const RMessage2& aMessage, TInt aError);
+	IMPORT_C void CloseAllSubsessionsL();
+	
+	// asynchronous requests
+	//IMPORT_C void CompleteAsyncRequest(CAsyncRequest* aAsyncRequest, TInt aReason);
+		
+private:
+	/**
+		This function is called from ServiceL after it has removed the
+		SCS-specific field and handled any other messages.	I.e., it is
+		called for functions which really require the session as opposed
+		to subsession commands or debugging commands such as heap failure.
+
+		@param	aFunction		Implementation function, i.e. the function
+								identifier with the SCS field removed.
+		@param	aMessage		Standard server message object.
+		@return ETrue if client message should be completed now.
+	 */
+	virtual TBool DoServiceL(TInt aFunction, const RMessage2& aMessage) = 0;
+
+	void PreCloseSession();
+
+	IMPORT_C virtual CScsSubsession* DoCreateSubsessionL(TInt aFunction, const RMessage2& aMessage);
+	
+	// subessions
+	CScsSubsession* GetSubsessionL(const RMessage2& aMessage);
+	void DeleteSubsessionContainers();
+	
+	void CreateSubsessionL(TInt aFunction, const RMessage2& aMessage);
+	void CloseSubsessionL(const RMessage2& aMessage);
+	TBool CallSubsessionFunctionL(TInt aFunction, const RMessage2& aMessage);
+	void CancelAsyncSubsessionRequestL(TInt aFunction, const RMessage2& aMessage);
+	
+	// asynchronous requests (support)
+	CAsyncRequest* FindSessionAsyncRequest(TInt aFunction);
+	void CancelAsyncSessionRequestL(TInt aFunction);
+
+private:
+	/**
+		Number of open subsessions before a new one is created.	 This is used
+		to manage cleanup if the subsession cannot be created.
+	 */
+	TInt iPreCreateSubsessionCount;
+
+	CObjectCon* iSsObjects;				///< Currently open subsessions.
+	CObjectIx* iSsHandles;				///< Maps handles to open subsessions.
+	
+public:
+	IMPORT_C CScsSession(CScsServer &aServer);
+	// This duplicates the iServer/Server() code in the base class,
+	// BUT this variable IS setup before derived class ConstructL is
+	// called and is NOT const. This trades off 4 bytes of memory
+	// against making the code cleaner and more consistent....
+	CScsServer& iServer;			///< Owning server.
+	};
+
+/**
+	Pass to CScsServer::CancelOutstandingRequests to mean all requests
+	associated with a session or its subsessions.
+ */
+CScsSubsession*const KWildSubsession = reinterpret_cast<CScsSubsession*>(~0);
+
+class CScsServer : public CPolicyServer
+/**
+	The main server object allocates sessions.	It also uses
+	a shutdown timer to stop the server when there have been no
+	open sessions for a set period.
+
+	The implementor must define a subclass which returns session
+	objects of the appropriate type.
+ */
+	{
+public:
+	IMPORT_C virtual ~CScsServer();
+
+	void IncrementSessionCount();
+	void DecrementSessionCount();
+	inline TInt SessionCount() const;
+
+	IMPORT_C void ShutdownWhenIdleL();
+
+	// asynchronous requests
+	void AddAsyncRequestL(CAsyncRequest* aAsyncRequest);
+	void CancelAsyncRequest(
+		CScsSession* aSession, CScsSubsession* aSubsession, TInt aFunction);
+	
+	void CancelOutstandingRequests(CScsSession* aSession, TBool aCompleteClientRequests);
+	void CancelOutstandingRequests(CScsSession* aSession, CScsSubsession* aSubsession, TBool aCompleteClientRequests);
+
+	/**
+		This function is called just before the SCS framework marks the heap for OOM 
+		testing and just before checking the heap.
+
+		Typically this function should compact any arrays and free objects which change size and can
+		not be compacted back to the same level.
+	*/
+	IMPORT_C virtual void DoPreHeapMarkOrCheckL();
+
+	/**
+		This function is called just after the heap has either been marked or checked (which is just 
+		after DoPreHeapMarkOrCheck).
+
+		Typically this function should re-create any objects which had to be freed by DoPreHeapMarkOrCheck.
+	*/
+	IMPORT_C virtual void DoPostHeapMarkOrCheckL();
+
+	enum TFunctionRanges
+	/**
+	   Function ranges to be used when configuring the server security via
+	   a CPolicyServer::TPolicy object.
+	   
+	   Session/sSubsession function codes will be ORed into the
+	   EBaseSession/EBaseSubSession ranges.
+	   
+	   Values from EBaseMustAllow, upwards, are used internally and must be allowed.
+	   
+	   If there are multiple subsession types (with different function
+	   code values), then codes must be be different for each subsession
+	   (this restriction only applies if using the CPolicyServer::TPolicy
+	   mechanism to configure server security).
+	   
+	   WARNNIG: These ranges MUST match the values in scscommon.h TScsFunction.
+	*/
+	{
+		EBaseSession	= 0x01000000,
+		EBaseSubSession = 0x02000000,
+		EBaseMustAllow	= 0x03000000 //< Must allow from EBaseMustAllow upwards
+	};
+	
+	static TInt StripScsFunctionMask(TInt aFunctionId) { return aFunctionId & ~ScsImpl::KScsFunctionMask;}
+
+protected:
+	IMPORT_C CScsServer(const TVersion& aVersion, CActive::TPriority aPriority = CActive::EPriorityStandard);
+	IMPORT_C CScsServer(const TVersion& aVersion, const CPolicyServer::TPolicy& aPolicy, CActive::TPriority aPriority = CActive::EPriorityStandard);
+	IMPORT_C void ConstructL(TInt aShutdownPeriodUs);
+
+	IMPORT_C void DisableShutdownTimer();
+	IMPORT_C void EnableShutdownTimerL(TInt aShutdownPeriodUs);
+
+
+	// implement CServer2
+	IMPORT_C virtual CSession2* NewSessionL(const TVersion& aVersion, const RMessage2& aMessage) const;
+
+	/**
+		NewSessionL checks that this server supports the version which is
+		requested by the client.  If that is so, then it calls this function
+		to allocate a new session object.
+
+		@param	aMessage		Connection message, as passed to NewSessionL.
+		@return					New session object.	 This is owned by the kernel,
+								which will delete it when the session is closed.
+	 */
+	virtual CScsSession* DoNewSessionL(const RMessage2& aMessage) = 0;
+
+private:
+	// asynchronous requests
+	CAsyncRequest* FindAsyncRequest(
+		CScsSession* aSession, CScsSubsession* aSubsession, TInt aFunction);
+	
+	static TInt RemoveCompletedRequests(TAny* aPtr);
+	void RemoveCompletedRequests();
+
+private:
+	/**
+		This server's version.	It is compared against client's requested version
+		when the client attempts to make a connection.
+	 */
+	const TVersion iVersion;
+
+	/** Number of open sessions.  Used to start and cancel the shutdown timer. */
+	TInt iSessionCount;
+
+	/**
+		Shutdown timer, started when there are no open sessions, cancelled when
+		the first session is created.
+	 */
+	CShutdownTimer* iShutdownTimer;
+
+	
+public:
+	/**
+		Generates instances of CObjectCon, for each session to host its subsessions.
+		Public because must be accessible to session objects.
+	 */
+	CObjectConIx* iContainerIndex;
+	
+	/** Currently outstanding requests. */
+	RPointerArray<CAsyncRequest> iAsyncRequests;
+	
+	/** Runs to remove completed requests from iAsyncRequests. */
+	CAsyncCallBack* iAsyncCleanup;
+	};
+
+inline TInt CScsServer::SessionCount() const
+	{
+	return iSessionCount;
+	}
+
+
+
+// -------- startup --------
+
+/**
+	The server executable must implement a factory function with this
+	signature and pass it to StartScsServer to allocate and start the server.
+ */	
+typedef CScsServer* (*TScsServerFactory)();
+
+IMPORT_C TInt StartScsServer(TScsServerFactory aServerFactoryLC);
+
+
+#endif	// #ifndef SCSSERVER_H
+