os/security/cryptomgmtlibs/securitycommonutils/source/scsserver/scsserver.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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