cryptomgmtlibs/securitycommonutils/source/scsserver/scsserver.cpp
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 * Implements CScsServer functionality.  See class and functions definitions
       
    16 * for more detail.
       
    17 *
       
    18 */
       
    19 
       
    20 
       
    21 /**
       
    22  @file
       
    23 */
       
    24 
       
    25 #include <scs/scsserver.h>
       
    26 #include "scsserverconstants.h"
       
    27 
       
    28 static const TInt defaultPolicyRangeCount = 1;
       
    29 static const TInt defaultPolicyRanges[defaultPolicyRangeCount] = 
       
    30 				{
       
    31 				0 // All requests
       
    32 				};
       
    33 
       
    34 static const TUint8 defaultPolicyElementsIndex[defaultPolicyRangeCount] = 
       
    35 				{
       
    36 				CPolicyServer::EAlwaysPass
       
    37 				};
       
    38 
       
    39 static const CPolicyServer::TPolicyElement defaultPolicyPolicyElements[1] = {};
       
    40 
       
    41 
       
    42 static const CPolicyServer::TPolicy defaultPolicy =
       
    43 				{
       
    44 				CPolicyServer::EAlwaysPass, // Allow all connects
       
    45 				defaultPolicyRangeCount,
       
    46 				defaultPolicyRanges,
       
    47 				defaultPolicyElementsIndex,
       
    48 				defaultPolicyPolicyElements,
       
    49 				};
       
    50 
       
    51 EXPORT_C CScsServer::CScsServer(const TVersion& aVersion, CActive::TPriority aPriority)
       
    52 /**
       
    53 	Record this server's version so it can be compared against the requested
       
    54 	version in NewSessionL.
       
    55 
       
    56 	@param	aVersion		This server's version.	This is compared against each
       
    57 							client's requested version when the client tries to connect.
       
    58 	@param	aPriority		This server's active object priority.
       
    59  */
       
    60 	:	CPolicyServer(aPriority, defaultPolicy, ESharableSessions)
       
    61 	,iVersion(aVersion)
       
    62 //	,iSessionCount(0)
       
    63 	{
       
    64 	// empty.
       
    65 	}
       
    66 
       
    67 EXPORT_C CScsServer::CScsServer(const TVersion& aVersion, const CPolicyServer::TPolicy& aPolicy, CActive::TPriority aPriority)
       
    68 /**
       
    69 	Record this server's version so it can be compared against the requested
       
    70 	version in NewSessionL.
       
    71 
       
    72 	@param	aVersion		This server's version.	This is compared against each
       
    73 							client's requested version when the client tries to connect.
       
    74 	@param	aPolicy			Can be used to configure security for server connect and session functions
       
    75 	@param	aPriority		This server's active object priority.
       
    76 
       
    77 	Note that aPolicy must be configured to allow all functions
       
    78 	covered by the KScsFunctionMask mask.
       
    79  */
       
    80 	:	CPolicyServer(aPriority, aPolicy, ESharableSessions)
       
    81 	,iVersion(aVersion)
       
    82 //	,iSessionCount(0)
       
    83 	{
       
    84 	// empty.
       
    85 	}
       
    86 
       
    87 EXPORT_C void CScsServer::ConstructL(TInt aShutdownPeriodUs)
       
    88 /**
       
    89 	Second-phase constructor allocates the shutdown timer for this server object.
       
    90 
       
    91 	If aShutdownPeriodUs is not 0, this function starts the shutdown
       
    92 	timer because the server starts up with no current sessions.
       
    93 
       
    94 	If aShutdownPeriodUs is 0, the timer is not started and the server
       
    95 	will not auto-exit.
       
    96 
       
    97 	nb. It must be called, even if you do not want a shutdown timer.
       
    98 
       
    99 	This function does not start the server, i.e. it does not call StartL.	The
       
   100 	calling function must do this after this function returns.
       
   101 
       
   102 	@param	aShutdownPeriodUs Shutdown period in microseconds.
       
   103  */
       
   104 	{	
       
   105 	if(aShutdownPeriodUs > 0)
       
   106 		{
       
   107 		iShutdownTimer = CShutdownTimer::NewL(aShutdownPeriodUs);
       
   108 		iShutdownTimer->Restart();
       
   109 		}
       
   110 	
       
   111 	iContainerIndex = CObjectConIx::NewL();
       
   112 	
       
   113 	TCallBack cb(RemoveCompletedRequests, this);
       
   114 	// EPriorityHigh to encourage the active scheduler to action the
       
   115 	// delete ASAP, in particular ahead of pending or new requests.
       
   116 	iAsyncCleanup = new(ELeave) CAsyncCallBack(cb, CActive::EPriorityHigh);
       
   117 	}
       
   118 
       
   119 
       
   120 EXPORT_C void CScsServer::DisableShutdownTimer()
       
   121 /**
       
   122 	The server will no longer shutdown after the last client session closes.
       
   123 	Client calls to RScsClientBase::ShutdownServer will fail with KErrNotSupported.
       
   124 */
       
   125 	{
       
   126 	if(iShutdownTimer)
       
   127 		{
       
   128 		iShutdownTimer->Cancel();
       
   129 		}
       
   130 	delete iShutdownTimer;
       
   131 	iShutdownTimer = 0;
       
   132 	}
       
   133 
       
   134 EXPORT_C void CScsServer::EnableShutdownTimerL(TInt aShutdownPeriodUs)
       
   135 /**
       
   136 	Enable shutdown timer support in the server.
       
   137 	If there are currently no client sessions the timer will be immediately started, otherwise
       
   138 	it will be started when the last client session closes.
       
   139 	If the timer expires, before another client creates a session, the server will shutdown.
       
   140 	The RScsClientBase::ShutdownServer api will now be supported, if called the server timeout
       
   141 	will effectively be reduced to 0.
       
   142 */
       
   143 	{
       
   144 	if(aShutdownPeriodUs <= 0)
       
   145 		{
       
   146 		return;
       
   147 		}
       
   148 	DisableShutdownTimer();
       
   149 	iShutdownTimer = CShutdownTimer::NewL(aShutdownPeriodUs);
       
   150 	if(iSessionCount == 0)
       
   151 		{
       
   152 		iShutdownTimer->Restart();
       
   153 		}
       
   154 	}
       
   155 
       
   156 
       
   157 EXPORT_C CScsServer::~CScsServer()
       
   158 /**
       
   159 	Frees resources used at this level.	 Specifically, frees the
       
   160 	container index, which is used to generate subsession containers,
       
   161 	the shutdown timer, and the async request cleanup object.
       
   162  */
       
   163 	{
       
   164 	__ASSERT_DEBUG(iSessionCount == 0, PanicServer(ESvrRemSessions));
       
   165 	__ASSERT_DEBUG(iAsyncCleanup == 0 || !iAsyncCleanup->IsActive(), PanicServer(ESvrRemCleanup));
       
   166 	__ASSERT_DEBUG(iAsyncRequests.Count() == 0, PanicServer(ESvrRemRequests));
       
   167 
       
   168 	delete iContainerIndex;
       
   169 	delete iShutdownTimer;
       
   170 	
       
   171 	delete iAsyncCleanup;
       
   172 	iAsyncRequests.Reset();
       
   173 	}
       
   174 
       
   175 // -------- sessions --------
       
   176 
       
   177 EXPORT_C CSession2* CScsServer::NewSessionL(const TVersion& aVersion, const RMessage2& aMessage) const
       
   178 /**
       
   179 	Implement CServer2 by allocating a new session object.	This function
       
   180 	delegates the actual allocation to the subclass.  Before creating the
       
   181 	session object, it compares the requested version with its own version.
       
   182 	After creating the session object, it increments the session count, which
       
   183 	reset the shutdown timer if it is the only	session.
       
   184 
       
   185 	@param	aVersion		Version of server which client requires.
       
   186 	@param	aMessage		Connect message.
       
   187 	@return					New initialized instance of CSession2 subclass.
       
   188  */
       
   189 	{
       
   190 	TBool versionOk = User::QueryVersionSupported(/* aCurrent */ iVersion, /* aRequested */ aVersion);
       
   191 	if (! versionOk)
       
   192 		User::Leave(KErrNotSupported);
       
   193 	
       
   194 	CScsSession* s = const_cast<CScsServer*>(this)->DoNewSessionL(aMessage);
       
   195 	
       
   196 	return s;
       
   197 	}
       
   198 
       
   199 EXPORT_C void CScsServer::DoPreHeapMarkOrCheckL()
       
   200 	{
       
   201 	}
       
   202 
       
   203 EXPORT_C void CScsServer::DoPostHeapMarkOrCheckL()
       
   204 	{
       
   205 	}
       
   206 
       
   207 void CScsServer::IncrementSessionCount()
       
   208 /**
       
   209 	Record the fact that another session has been created.	If this new
       
   210 	session is the only session then cancel the shutdown timer.
       
   211  */
       
   212 	{
       
   213 	++iSessionCount;
       
   214 	if (iSessionCount == 1)
       
   215 		{
       
   216 		if(iShutdownTimer)
       
   217 			{
       
   218 			iShutdownTimer->Cancel();
       
   219 			}
       
   220 		}
       
   221 	}
       
   222 
       
   223 void CScsServer::DecrementSessionCount()
       
   224 /**
       
   225 	Record the fact that a session has been deleted.  If this was the
       
   226 	only remaining session then start the shutdown timer.
       
   227 
       
   228 	Note the shutdown timer may be deferred if a request cleanup is
       
   229 	pending.
       
   230  */
       
   231 	{
       
   232 	--iSessionCount;
       
   233 	if (iShutdownTimer && (iSessionCount == 0) && (! iAsyncCleanup->IsActive()))
       
   234 		{
       
   235 		iShutdownTimer->Restart();
       
   236 		}
       
   237 	}
       
   238 
       
   239 EXPORT_C void CScsServer::ShutdownWhenIdleL()
       
   240 	/**
       
   241 	   Shutdown immediately when server is next idle.  If the server
       
   242 	   is not transient (ie. has no shutdown timer), this call is
       
   243 	   prohibited and will leave with KErrNotSupported.
       
   244 	 */
       
   245 	{
       
   246 	if(! iShutdownTimer)
       
   247 		{
       
   248 		// We do not allow shutdown of non-transient servers.
       
   249 		User::Leave(KErrNotSupported);
       
   250 		}
       
   251 	
       
   252 	// Next time we are idle, shutdown immediately.
       
   253 	iShutdownTimer->ImmediateTimeoutNextRestart();
       
   254 	}
       
   255 
       
   256 
       
   257 
       
   258 // -------- asynchronous requests --------
       
   259 
       
   260 CAsyncRequest* CScsServer::FindAsyncRequest(
       
   261 	CScsSession* aSession, CScsSubsession* aSubsession, TInt aFunction)
       
   262 /**
       
   263 	Find the outstanding request which matches the supplied criteria.
       
   264 
       
   265 	@param	aSession		Session which hosts the request.
       
   266 	@param	aSubsession		Subsession which hosts the request, NULL if
       
   267 							the request is relative to a session.
       
   268 	@param	aFunction		The function identifier, without any SCS code.
       
   269 	@return					The matching asynchronous request, NULL if not
       
   270 							found.
       
   271  */
       
   272 	{
       
   273 	TInt reqCount = iAsyncRequests.Count();
       
   274 	for (TInt i = reqCount - 1; i >= 0; --i)
       
   275 		{
       
   276 		CAsyncRequest* req = iAsyncRequests[i];
       
   277 		
       
   278 		if (req->iSession != aSession)
       
   279 			continue;
       
   280 		
       
   281 		if (req->iSubsession != aSubsession)
       
   282 			continue;
       
   283 		
       
   284 		if (req->iFunction != aFunction)
       
   285 			continue;
       
   286 		
       
   287 		return req;
       
   288 		}
       
   289 	
       
   290 	return 0;				// request not found
       
   291 	}
       
   292 
       
   293 void CScsServer::AddAsyncRequestL(CAsyncRequest* aAsyncRequest)
       
   294 /**
       
   295 	Add the supplied request to the server's collection.
       
   296 
       
   297 	@param	aAsyncRequest	Request to add.	 If this function succeeds
       
   298 							then ownership has been transferred to the
       
   299 							collection.
       
   300  */
       
   301 	{
       
   302 	// ensure this session does not already have an outstanding request
       
   303 	// for the same function
       
   304 	CAsyncRequest* existReq = FindAsyncRequest(
       
   305 		aAsyncRequest->iSession, aAsyncRequest->iSubsession,
       
   306 		aAsyncRequest->iFunction);
       
   307 	
       
   308 	if (existReq != 0)
       
   309 		User::Leave(KErrScsAsyncAlreadyQueued);
       
   310 
       
   311 	iAsyncRequests.AppendL(aAsyncRequest);
       
   312 	}
       
   313 
       
   314 void CScsServer::CancelAsyncRequest(
       
   315 	CScsSession* aSession, CScsSubsession* aSubsession, TInt aFunction)
       
   316 /**
       
   317 	Cancels a specific (sub)session request in response to a client
       
   318 	command.  Also completes the client request.
       
   319 	
       
   320 	CancelOutstandingRequest should be called when a (sub)session is closed.
       
   321 
       
   322 	@param	aSession		Session which hosts the request.
       
   323 	@param	aSubsession		Subsession which hosts the request, NULL if
       
   324 							the request is relative to a session.
       
   325 	@param	aFunction		The function identifier, without any SCS code.
       
   326  */
       
   327 	{
       
   328 	CAsyncRequest* req = FindAsyncRequest(aSession, aSubsession, aFunction);
       
   329 	
       
   330 	// not an error if the request is not queued; could have been
       
   331 	// completed before the cancel function was processed.
       
   332 	if (req != 0)
       
   333 		req->CancelCompleteAndMarkForDeletion();
       
   334 	}
       
   335 
       
   336 void CScsServer::CancelOutstandingRequests(CScsSession* aSession, TBool aCompleteClientRequests)
       
   337 /**
       
   338 	Cancels and deletes all outstanding asynchronous requests associated
       
   339 	with the supplied session or any of its subsessions.  Does not complete
       
   340 	the associated client requests.
       
   341 	
       
   342 	This function should be called when a session is closed.
       
   343 	CancelAsyncRequest should be called when a specific request is cancelled.
       
   344 	
       
   345 	@param	aSession		Session which is being closed.
       
   346 	@param	aCompleteClientRequests Whether to complete the client-side requests
       
   347 							with KErrCancel.
       
   348  */
       
   349 	{
       
   350 	CancelOutstandingRequests(aSession, KWildSubsession, aCompleteClientRequests);
       
   351 	}
       
   352 
       
   353 void CScsServer::CancelOutstandingRequests(CScsSession* aSession, CScsSubsession* aSubsession, TBool aCompleteClientRequests)
       
   354 /**
       
   355 	Cancels and deletes all outstanding asynchronous requests associated
       
   356 	with the supplied session and subsession.  This should be called when
       
   357 	a session or subsession is closed.
       
   358 	
       
   359 	As an exception, the user-side request is completed when a subsession is
       
   360 	closed, else the request would not be completed	until the session itself
       
   361 	was destroyed.
       
   362 	
       
   363 	CancelAsyncRequest should be called when a specific request is cancelled.
       
   364 	
       
   365 	@param	aSession		Session which is being closed.
       
   366 	@param	aSubsession		Subsession which is being closed.  If this is
       
   367 							KWildSubsession then a session is being closed so all of
       
   368 							its subsession requests should be destroyed as well.
       
   369 	@param	aCompleteClientRequests Whether to complete the client-side requests
       
   370 							with KErrCancel.
       
   371  */
       
   372 	{
       
   373 	TBool wildSubsession = (aSubsession == KWildSubsession);
       
   374 	
       
   375 	TInt reqCount = iAsyncRequests.Count();
       
   376 	for (TInt i = reqCount - 1; i >= 0; --i)
       
   377 		{
       
   378 		CAsyncRequest* req = iAsyncRequests[i];
       
   379 
       
   380 		TBool sessionMatch = (req->iSession == aSession);
       
   381 		if (! sessionMatch)
       
   382 			continue;
       
   383 		
       
   384 		TBool subsessionMatch = wildSubsession || (req->iSubsession == aSubsession);
       
   385 		if (! subsessionMatch)
       
   386 			continue;
       
   387 
       
   388 		if (aCompleteClientRequests)
       
   389 			req->CancelCompleteAndMarkForDeletion();
       
   390 		else
       
   391 			{
       
   392 			req->DoCleanup();
       
   393 			req->MarkForDeletion();
       
   394 			}
       
   395 		}
       
   396 	}
       
   397 
       
   398 TInt CScsServer::RemoveCompletedRequests(TAny* aPtr)
       
   399 /**
       
   400 	This static function is called when iAsyncCleanup
       
   401 	runs.  It interprets its argument as a pointer to
       
   402 	an instance of CScsServer and removes any asynchronous
       
   403 	requests which have been completed.
       
   404 	
       
   405 	@param	aPtr			Required callback argument.	 Interpreted
       
   406 							as a pointer to an instance of CScsServer.
       
   407 	@return					KErrNone.  Required to satisfy the TCallBack
       
   408 							function signature.
       
   409 	@see RemoveCompletedRequests()
       
   410  */
       
   411 	{
       
   412 	CScsServer* svr = static_cast<CScsServer*>(aPtr);
       
   413 	svr->RemoveCompletedRequests();
       
   414 	return KErrNone;
       
   415 	}
       
   416 
       
   417 void CScsServer::RemoveCompletedRequests()
       
   418 /**
       
   419 	Delete any asynchronous requests which are marked for deletion.
       
   420  */
       
   421 	{
       
   422 	// The requests have already been completed; they just need to be removed.
       
   423 	TInt reqCount = iAsyncRequests.Count();
       
   424 	for (TInt i = reqCount - 1; i >= 0; --i)
       
   425 		{
       
   426 		CAsyncRequest* req = iAsyncRequests[i];
       
   427 		if (req->iSession != 0)		// still outstanding if iSession != 0
       
   428 			continue;
       
   429 		
       
   430 		delete req;
       
   431 		iAsyncRequests.Remove(i);
       
   432 		}
       
   433 	
       
   434 	// if no more outstanding requests then reset array so heap balances
       
   435 	if (iAsyncRequests.Count() == 0)
       
   436 		iAsyncRequests.Compress();
       
   437 	
       
   438 	// if the shutdown timer was deferred because of an impending
       
   439 	// cleanup then launch it now.
       
   440 	if (iShutdownTimer && (iSessionCount == 0))
       
   441 		{
       
   442 		iShutdownTimer->Restart();
       
   443 		}
       
   444 	}
       
   445 // End of file
       
   446