cryptomgmtlibs/securitycommonutils/inc/scsserver.h
changeset 8 35751d3474b7
equal deleted inserted replaced
2:675a964f4eb5 8:35751d3474b7
       
     1 /*
       
     2 * Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 * Server-side classes which are required to implement a session counting server.
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 /**
       
    21  @file
       
    22  @publishedPartner
       
    23  @released
       
    24 */
       
    25 
       
    26 #ifndef SCSSERVER_H
       
    27 #define SCSSERVER_H
       
    28 
       
    29 #include <e32base.h>
       
    30 
       
    31 #include <scs/scsclient.h>
       
    32 #include <scs/scscommon.h>
       
    33 
       
    34 #ifndef SYMBIAN_ENABLE_SPLIT_HEADERS
       
    35 #include "scsserverconstants.h"
       
    36 #endif
       
    37 
       
    38 // -------- error handling --------
       
    39 
       
    40 
       
    41 const TInt KErrScsAsyncAlreadyQueued = -5702;	///< Tried to re-queue an outstanding request.
       
    42 
       
    43 
       
    44 
       
    45 // forward declarations
       
    46 class CScsServer;
       
    47 class CScsSession;
       
    48 class CScsSubsession;
       
    49 
       
    50 class CShutdownTimer : public CTimer
       
    51 /**
       
    52 	When an instance of this class is constructed it is given a delay period.
       
    53 	If the object runs to completion, i.e. if it is not cancelled, then it stops
       
    54 	the active scheduler, which has the effect of terminating the server.
       
    55 */
       
    56 	{
       
    57 public:
       
    58 	static CShutdownTimer* NewL(TInt aDelayUs);
       
    59 
       
    60 	void Restart();
       
    61 
       
    62 	void ImmediateTimeoutNextRestart();
       
    63 
       
    64 private:
       
    65 	CShutdownTimer(TInt aDelayUs);
       
    66 
       
    67 	// implement CTimer
       
    68 	virtual void RunL();
       
    69 
       
    70 private:
       
    71 	TInt iDelayUs;			///< Timer delay in microseconds.
       
    72 	TBool iImmediateTimeoutNextRestart;
       
    73 	};
       
    74 
       
    75 class CAsyncRequest : public CActive
       
    76 /**
       
    77 	An outstanding request on the server side.	A subclass should
       
    78 	be created for each type of outstanding request.
       
    79 
       
    80 	This class is implemented as an active object, because it is
       
    81 	anticipated that some asynchronous requests can be implemented
       
    82 	simply by completing the client request when a TRequestStatus
       
    83 	completes.	The implementor can override this behavior by
       
    84 	re-implementing RunL, e.g. to free some resources before completing
       
    85 	the request.  If they do so, they must call CompleteAndMarkForDeletion to 
       
    86 	complete the client request and mark this object for deletion (alternatively
       
    87 	they can simply call CAsyncRequest::RunL from their RunL).
       
    88 
       
    89 	This class cannot, however, anticipate the cancellation
       
    90 	mechanism.	The implementor must implement DoCancel for that.
       
    91 	DoCancel should not delete the client request or mark this object
       
    92 	for deletion.
       
    93 
       
    94 	When the implementor has allocated an instance of this
       
    95 	class, they must add it to the session by calling CAsyncRequest::TransferToScsFrameworkL.
       
    96 	The second-phase constructor must not  leave between that and calling
       
    97 	SetActive.
       
    98 
       
    99 	These objects are cancelled and destroyed when the
       
   100 	client-side session / subsession sends a cancel command.
       
   101 
       
   102 	@see CScsSession::AddAsyncRequestL
       
   103 */
       
   104 	{
       
   105 public:
       
   106 	IMPORT_C CAsyncRequest(CScsSession* aSession, CScsSubsession* aSubsession, const RMessage2& aMessage);
       
   107 	
       
   108 	void CancelCompleteAndMarkForDeletion();	// explicit cancel request
       
   109 	void MarkForDeletion();						// session close
       
   110 	IMPORT_C virtual void DoCleanup();	// Cancel this request
       
   111 	
       
   112 	IMPORT_C void TransferToScsFrameworkL();
       
   113 protected:
       
   114 	
       
   115 	IMPORT_C void CompleteAndMarkForDeletion(TInt aError);
       
   116 	
       
   117 	// implement CActive
       
   118 	IMPORT_C virtual void RunL();
       
   119 
       
   120 	// override CActive
       
   121 	IMPORT_C virtual TInt RunError(TInt aError);
       
   122 		
       
   123 public:
       
   124 	/** Session on which this request is queued.  NULL if completed. */
       
   125 	CScsSession* iSession;
       
   126 	/** Subsession on which this request is queued.	 NULL if session-relative. */
       
   127 	CScsSubsession* iSubsession;
       
   128 	/** Outstanding message to complete. */
       
   129 	const RMessagePtr2 iMessagePtr2;
       
   130 	/** Identifies outstanding request. */
       
   131 	TInt iFunction;
       
   132 	};
       
   133 
       
   134 class CScsSubsession : public CObject
       
   135 /**
       
   136 	If the server implementation supports subsessions, they must
       
   137 	derive from this class.
       
   138 
       
   139 	WARNING: Because this class derives from CObject you must not simply delete
       
   140 	an instance of a class derived from this class (ie. your subsession), instead you MUST
       
   141 	Close() it. 
       
   142 
       
   143 	In practise this probably means you need a ConstructL like this:-
       
   144 	CFred *self = new(ELeave) CFred(....);
       
   145 	CleanupClosePushL(*self); // Note use of CleanupClosePushL and of *self
       
   146 	self->ConstructL(...);
       
   147 	CleanupStack::Pop(self); // Note use of *self instead of self
       
   148  */
       
   149 	{
       
   150 public:
       
   151 	/**
       
   152 		SCS routes subsession messages to this function; the session
       
   153 		object does not have to decode them	 itself.
       
   154 
       
   155 		@param	aFunction		Implementation function, i.e. the function
       
   156 								identifier with the SCS field removed.
       
   157 		@param	aMessage		Standard server message object.
       
   158 		@return ETrue means complete client request now.
       
   159 	 */
       
   160 	virtual TBool DoServiceL(TInt aFunction, const RMessage2& aMessage) = 0;
       
   161 
       
   162 protected:
       
   163 	IMPORT_C CScsSubsession(CScsSession &aSession);
       
   164 	
       
   165 public:
       
   166 	// Note this is setup by the constructor, before the derived class
       
   167 	// ConstructL is called.
       
   168 	CScsSession& iSession;			///< Owning session.
       
   169 	};
       
   170 
       
   171 class CScsSession : public CSession2
       
   172 /**
       
   173 	When this session object is destroyed (because the client-server session
       
   174 	has closed,) this notifies the server object which decrements the session
       
   175 	count.	Therefore, the server can be shut down after an inactivity
       
   176 	period during which there are no open sessions.
       
   177 
       
   178 	This object also frees any remaining subsession objects when it is closed.
       
   179 */
       
   180 	{
       
   181 protected:
       
   182 	IMPORT_C void ConstructL();
       
   183 	IMPORT_C virtual ~CScsSession();
       
   184 	
       
   185 	// implement CSession2
       
   186 	IMPORT_C virtual void ServiceL(const RMessage2& aMessage);
       
   187 	// override CSession2
       
   188 	IMPORT_C virtual void ServiceError(const RMessage2& aMessage, TInt aError);
       
   189 	IMPORT_C void CloseAllSubsessionsL();
       
   190 	
       
   191 	// asynchronous requests
       
   192 	//IMPORT_C void CompleteAsyncRequest(CAsyncRequest* aAsyncRequest, TInt aReason);
       
   193 		
       
   194 private:
       
   195 	/**
       
   196 		This function is called from ServiceL after it has removed the
       
   197 		SCS-specific field and handled any other messages.	I.e., it is
       
   198 		called for functions which really require the session as opposed
       
   199 		to subsession commands or debugging commands such as heap failure.
       
   200 
       
   201 		@param	aFunction		Implementation function, i.e. the function
       
   202 								identifier with the SCS field removed.
       
   203 		@param	aMessage		Standard server message object.
       
   204 		@return ETrue if client message should be completed now.
       
   205 	 */
       
   206 	virtual TBool DoServiceL(TInt aFunction, const RMessage2& aMessage) = 0;
       
   207 
       
   208 	void PreCloseSession();
       
   209 
       
   210 	IMPORT_C virtual CScsSubsession* DoCreateSubsessionL(TInt aFunction, const RMessage2& aMessage);
       
   211 	
       
   212 	// subessions
       
   213 	CScsSubsession* GetSubsessionL(const RMessage2& aMessage);
       
   214 	void DeleteSubsessionContainers();
       
   215 	
       
   216 	void CreateSubsessionL(TInt aFunction, const RMessage2& aMessage);
       
   217 	void CloseSubsessionL(const RMessage2& aMessage);
       
   218 	TBool CallSubsessionFunctionL(TInt aFunction, const RMessage2& aMessage);
       
   219 	void CancelAsyncSubsessionRequestL(TInt aFunction, const RMessage2& aMessage);
       
   220 	
       
   221 	// asynchronous requests (support)
       
   222 	CAsyncRequest* FindSessionAsyncRequest(TInt aFunction);
       
   223 	void CancelAsyncSessionRequestL(TInt aFunction);
       
   224 
       
   225 private:
       
   226 	/**
       
   227 		Number of open subsessions before a new one is created.	 This is used
       
   228 		to manage cleanup if the subsession cannot be created.
       
   229 	 */
       
   230 	TInt iPreCreateSubsessionCount;
       
   231 
       
   232 	CObjectCon* iSsObjects;				///< Currently open subsessions.
       
   233 	CObjectIx* iSsHandles;				///< Maps handles to open subsessions.
       
   234 	
       
   235 public:
       
   236 	IMPORT_C CScsSession(CScsServer &aServer);
       
   237 	// This duplicates the iServer/Server() code in the base class,
       
   238 	// BUT this variable IS setup before derived class ConstructL is
       
   239 	// called and is NOT const. This trades off 4 bytes of memory
       
   240 	// against making the code cleaner and more consistent....
       
   241 	CScsServer& iServer;			///< Owning server.
       
   242 	};
       
   243 
       
   244 /**
       
   245 	Pass to CScsServer::CancelOutstandingRequests to mean all requests
       
   246 	associated with a session or its subsessions.
       
   247  */
       
   248 CScsSubsession*const KWildSubsession = reinterpret_cast<CScsSubsession*>(~0);
       
   249 
       
   250 class CScsServer : public CPolicyServer
       
   251 /**
       
   252 	The main server object allocates sessions.	It also uses
       
   253 	a shutdown timer to stop the server when there have been no
       
   254 	open sessions for a set period.
       
   255 
       
   256 	The implementor must define a subclass which returns session
       
   257 	objects of the appropriate type.
       
   258  */
       
   259 	{
       
   260 public:
       
   261 	IMPORT_C virtual ~CScsServer();
       
   262 
       
   263 	void IncrementSessionCount();
       
   264 	void DecrementSessionCount();
       
   265 	inline TInt SessionCount() const;
       
   266 
       
   267 	IMPORT_C void ShutdownWhenIdleL();
       
   268 
       
   269 	// asynchronous requests
       
   270 	void AddAsyncRequestL(CAsyncRequest* aAsyncRequest);
       
   271 	void CancelAsyncRequest(
       
   272 		CScsSession* aSession, CScsSubsession* aSubsession, TInt aFunction);
       
   273 	
       
   274 	void CancelOutstandingRequests(CScsSession* aSession, TBool aCompleteClientRequests);
       
   275 	void CancelOutstandingRequests(CScsSession* aSession, CScsSubsession* aSubsession, TBool aCompleteClientRequests);
       
   276 
       
   277 	/**
       
   278 		This function is called just before the SCS framework marks the heap for OOM 
       
   279 		testing and just before checking the heap.
       
   280 
       
   281 		Typically this function should compact any arrays and free objects which change size and can
       
   282 		not be compacted back to the same level.
       
   283 	*/
       
   284 	IMPORT_C virtual void DoPreHeapMarkOrCheckL();
       
   285 
       
   286 	/**
       
   287 		This function is called just after the heap has either been marked or checked (which is just 
       
   288 		after DoPreHeapMarkOrCheck).
       
   289 
       
   290 		Typically this function should re-create any objects which had to be freed by DoPreHeapMarkOrCheck.
       
   291 	*/
       
   292 	IMPORT_C virtual void DoPostHeapMarkOrCheckL();
       
   293 
       
   294 	enum TFunctionRanges
       
   295 	/**
       
   296 	   Function ranges to be used when configuring the server security via
       
   297 	   a CPolicyServer::TPolicy object.
       
   298 	   
       
   299 	   Session/sSubsession function codes will be ORed into the
       
   300 	   EBaseSession/EBaseSubSession ranges.
       
   301 	   
       
   302 	   Values from EBaseMustAllow, upwards, are used internally and must be allowed.
       
   303 	   
       
   304 	   If there are multiple subsession types (with different function
       
   305 	   code values), then codes must be be different for each subsession
       
   306 	   (this restriction only applies if using the CPolicyServer::TPolicy
       
   307 	   mechanism to configure server security).
       
   308 	   
       
   309 	   WARNNIG: These ranges MUST match the values in scscommon.h TScsFunction.
       
   310 	*/
       
   311 	{
       
   312 		EBaseSession	= 0x01000000,
       
   313 		EBaseSubSession = 0x02000000,
       
   314 		EBaseMustAllow	= 0x03000000 //< Must allow from EBaseMustAllow upwards
       
   315 	};
       
   316 	
       
   317 	static TInt StripScsFunctionMask(TInt aFunctionId) { return aFunctionId & ~ScsImpl::KScsFunctionMask;}
       
   318 
       
   319 protected:
       
   320 	IMPORT_C CScsServer(const TVersion& aVersion, CActive::TPriority aPriority = CActive::EPriorityStandard);
       
   321 	IMPORT_C CScsServer(const TVersion& aVersion, const CPolicyServer::TPolicy& aPolicy, CActive::TPriority aPriority = CActive::EPriorityStandard);
       
   322 	IMPORT_C void ConstructL(TInt aShutdownPeriodUs);
       
   323 
       
   324 	IMPORT_C void DisableShutdownTimer();
       
   325 	IMPORT_C void EnableShutdownTimerL(TInt aShutdownPeriodUs);
       
   326 
       
   327 
       
   328 	// implement CServer2
       
   329 	IMPORT_C virtual CSession2* NewSessionL(const TVersion& aVersion, const RMessage2& aMessage) const;
       
   330 
       
   331 	/**
       
   332 		NewSessionL checks that this server supports the version which is
       
   333 		requested by the client.  If that is so, then it calls this function
       
   334 		to allocate a new session object.
       
   335 
       
   336 		@param	aMessage		Connection message, as passed to NewSessionL.
       
   337 		@return					New session object.	 This is owned by the kernel,
       
   338 								which will delete it when the session is closed.
       
   339 	 */
       
   340 	virtual CScsSession* DoNewSessionL(const RMessage2& aMessage) = 0;
       
   341 
       
   342 private:
       
   343 	// asynchronous requests
       
   344 	CAsyncRequest* FindAsyncRequest(
       
   345 		CScsSession* aSession, CScsSubsession* aSubsession, TInt aFunction);
       
   346 	
       
   347 	static TInt RemoveCompletedRequests(TAny* aPtr);
       
   348 	void RemoveCompletedRequests();
       
   349 
       
   350 private:
       
   351 	/**
       
   352 		This server's version.	It is compared against client's requested version
       
   353 		when the client attempts to make a connection.
       
   354 	 */
       
   355 	const TVersion iVersion;
       
   356 
       
   357 	/** Number of open sessions.  Used to start and cancel the shutdown timer. */
       
   358 	TInt iSessionCount;
       
   359 
       
   360 	/**
       
   361 		Shutdown timer, started when there are no open sessions, cancelled when
       
   362 		the first session is created.
       
   363 	 */
       
   364 	CShutdownTimer* iShutdownTimer;
       
   365 
       
   366 	
       
   367 public:
       
   368 	/**
       
   369 		Generates instances of CObjectCon, for each session to host its subsessions.
       
   370 		Public because must be accessible to session objects.
       
   371 	 */
       
   372 	CObjectConIx* iContainerIndex;
       
   373 	
       
   374 	/** Currently outstanding requests. */
       
   375 	RPointerArray<CAsyncRequest> iAsyncRequests;
       
   376 	
       
   377 	/** Runs to remove completed requests from iAsyncRequests. */
       
   378 	CAsyncCallBack* iAsyncCleanup;
       
   379 	};
       
   380 
       
   381 inline TInt CScsServer::SessionCount() const
       
   382 	{
       
   383 	return iSessionCount;
       
   384 	}
       
   385 
       
   386 
       
   387 
       
   388 // -------- startup --------
       
   389 
       
   390 /**
       
   391 	The server executable must implement a factory function with this
       
   392 	signature and pass it to StartScsServer to allocate and start the server.
       
   393  */	
       
   394 typedef CScsServer* (*TScsServerFactory)();
       
   395 
       
   396 IMPORT_C TInt StartScsServer(TScsServerFactory aServerFactoryLC);
       
   397 
       
   398 
       
   399 #endif	// #ifndef SCSSERVER_H
       
   400