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