1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/security/cryptomgmtlibs/securitycommonutils/source/scsserver/scsserver.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,446 @@
1.4 +/*
1.5 +* Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
1.6 +* All rights reserved.
1.7 +* This component and the accompanying materials are made available
1.8 +* under the terms of the License "Eclipse Public License v1.0"
1.9 +* which accompanies this distribution, and is available
1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.11 +*
1.12 +* Initial Contributors:
1.13 +* Nokia Corporation - initial contribution.
1.14 +*
1.15 +* Contributors:
1.16 +*
1.17 +* Description:
1.18 +* Implements CScsServer functionality. See class and functions definitions
1.19 +* for more detail.
1.20 +*
1.21 +*/
1.22 +
1.23 +
1.24 +/**
1.25 + @file
1.26 +*/
1.27 +
1.28 +#include <scs/scsserver.h>
1.29 +#include "scsserverconstants.h"
1.30 +
1.31 +static const TInt defaultPolicyRangeCount = 1;
1.32 +static const TInt defaultPolicyRanges[defaultPolicyRangeCount] =
1.33 + {
1.34 + 0 // All requests
1.35 + };
1.36 +
1.37 +static const TUint8 defaultPolicyElementsIndex[defaultPolicyRangeCount] =
1.38 + {
1.39 + CPolicyServer::EAlwaysPass
1.40 + };
1.41 +
1.42 +static const CPolicyServer::TPolicyElement defaultPolicyPolicyElements[1] = {};
1.43 +
1.44 +
1.45 +static const CPolicyServer::TPolicy defaultPolicy =
1.46 + {
1.47 + CPolicyServer::EAlwaysPass, // Allow all connects
1.48 + defaultPolicyRangeCount,
1.49 + defaultPolicyRanges,
1.50 + defaultPolicyElementsIndex,
1.51 + defaultPolicyPolicyElements,
1.52 + };
1.53 +
1.54 +EXPORT_C CScsServer::CScsServer(const TVersion& aVersion, CActive::TPriority aPriority)
1.55 +/**
1.56 + Record this server's version so it can be compared against the requested
1.57 + version in NewSessionL.
1.58 +
1.59 + @param aVersion This server's version. This is compared against each
1.60 + client's requested version when the client tries to connect.
1.61 + @param aPriority This server's active object priority.
1.62 + */
1.63 + : CPolicyServer(aPriority, defaultPolicy, ESharableSessions)
1.64 + ,iVersion(aVersion)
1.65 +// ,iSessionCount(0)
1.66 + {
1.67 + // empty.
1.68 + }
1.69 +
1.70 +EXPORT_C CScsServer::CScsServer(const TVersion& aVersion, const CPolicyServer::TPolicy& aPolicy, CActive::TPriority aPriority)
1.71 +/**
1.72 + Record this server's version so it can be compared against the requested
1.73 + version in NewSessionL.
1.74 +
1.75 + @param aVersion This server's version. This is compared against each
1.76 + client's requested version when the client tries to connect.
1.77 + @param aPolicy Can be used to configure security for server connect and session functions
1.78 + @param aPriority This server's active object priority.
1.79 +
1.80 + Note that aPolicy must be configured to allow all functions
1.81 + covered by the KScsFunctionMask mask.
1.82 + */
1.83 + : CPolicyServer(aPriority, aPolicy, ESharableSessions)
1.84 + ,iVersion(aVersion)
1.85 +// ,iSessionCount(0)
1.86 + {
1.87 + // empty.
1.88 + }
1.89 +
1.90 +EXPORT_C void CScsServer::ConstructL(TInt aShutdownPeriodUs)
1.91 +/**
1.92 + Second-phase constructor allocates the shutdown timer for this server object.
1.93 +
1.94 + If aShutdownPeriodUs is not 0, this function starts the shutdown
1.95 + timer because the server starts up with no current sessions.
1.96 +
1.97 + If aShutdownPeriodUs is 0, the timer is not started and the server
1.98 + will not auto-exit.
1.99 +
1.100 + nb. It must be called, even if you do not want a shutdown timer.
1.101 +
1.102 + This function does not start the server, i.e. it does not call StartL. The
1.103 + calling function must do this after this function returns.
1.104 +
1.105 + @param aShutdownPeriodUs Shutdown period in microseconds.
1.106 + */
1.107 + {
1.108 + if(aShutdownPeriodUs > 0)
1.109 + {
1.110 + iShutdownTimer = CShutdownTimer::NewL(aShutdownPeriodUs);
1.111 + iShutdownTimer->Restart();
1.112 + }
1.113 +
1.114 + iContainerIndex = CObjectConIx::NewL();
1.115 +
1.116 + TCallBack cb(RemoveCompletedRequests, this);
1.117 + // EPriorityHigh to encourage the active scheduler to action the
1.118 + // delete ASAP, in particular ahead of pending or new requests.
1.119 + iAsyncCleanup = new(ELeave) CAsyncCallBack(cb, CActive::EPriorityHigh);
1.120 + }
1.121 +
1.122 +
1.123 +EXPORT_C void CScsServer::DisableShutdownTimer()
1.124 +/**
1.125 + The server will no longer shutdown after the last client session closes.
1.126 + Client calls to RScsClientBase::ShutdownServer will fail with KErrNotSupported.
1.127 +*/
1.128 + {
1.129 + if(iShutdownTimer)
1.130 + {
1.131 + iShutdownTimer->Cancel();
1.132 + }
1.133 + delete iShutdownTimer;
1.134 + iShutdownTimer = 0;
1.135 + }
1.136 +
1.137 +EXPORT_C void CScsServer::EnableShutdownTimerL(TInt aShutdownPeriodUs)
1.138 +/**
1.139 + Enable shutdown timer support in the server.
1.140 + If there are currently no client sessions the timer will be immediately started, otherwise
1.141 + it will be started when the last client session closes.
1.142 + If the timer expires, before another client creates a session, the server will shutdown.
1.143 + The RScsClientBase::ShutdownServer api will now be supported, if called the server timeout
1.144 + will effectively be reduced to 0.
1.145 +*/
1.146 + {
1.147 + if(aShutdownPeriodUs <= 0)
1.148 + {
1.149 + return;
1.150 + }
1.151 + DisableShutdownTimer();
1.152 + iShutdownTimer = CShutdownTimer::NewL(aShutdownPeriodUs);
1.153 + if(iSessionCount == 0)
1.154 + {
1.155 + iShutdownTimer->Restart();
1.156 + }
1.157 + }
1.158 +
1.159 +
1.160 +EXPORT_C CScsServer::~CScsServer()
1.161 +/**
1.162 + Frees resources used at this level. Specifically, frees the
1.163 + container index, which is used to generate subsession containers,
1.164 + the shutdown timer, and the async request cleanup object.
1.165 + */
1.166 + {
1.167 + __ASSERT_DEBUG(iSessionCount == 0, PanicServer(ESvrRemSessions));
1.168 + __ASSERT_DEBUG(iAsyncCleanup == 0 || !iAsyncCleanup->IsActive(), PanicServer(ESvrRemCleanup));
1.169 + __ASSERT_DEBUG(iAsyncRequests.Count() == 0, PanicServer(ESvrRemRequests));
1.170 +
1.171 + delete iContainerIndex;
1.172 + delete iShutdownTimer;
1.173 +
1.174 + delete iAsyncCleanup;
1.175 + iAsyncRequests.Reset();
1.176 + }
1.177 +
1.178 +// -------- sessions --------
1.179 +
1.180 +EXPORT_C CSession2* CScsServer::NewSessionL(const TVersion& aVersion, const RMessage2& aMessage) const
1.181 +/**
1.182 + Implement CServer2 by allocating a new session object. This function
1.183 + delegates the actual allocation to the subclass. Before creating the
1.184 + session object, it compares the requested version with its own version.
1.185 + After creating the session object, it increments the session count, which
1.186 + reset the shutdown timer if it is the only session.
1.187 +
1.188 + @param aVersion Version of server which client requires.
1.189 + @param aMessage Connect message.
1.190 + @return New initialized instance of CSession2 subclass.
1.191 + */
1.192 + {
1.193 + TBool versionOk = User::QueryVersionSupported(/* aCurrent */ iVersion, /* aRequested */ aVersion);
1.194 + if (! versionOk)
1.195 + User::Leave(KErrNotSupported);
1.196 +
1.197 + CScsSession* s = const_cast<CScsServer*>(this)->DoNewSessionL(aMessage);
1.198 +
1.199 + return s;
1.200 + }
1.201 +
1.202 +EXPORT_C void CScsServer::DoPreHeapMarkOrCheckL()
1.203 + {
1.204 + }
1.205 +
1.206 +EXPORT_C void CScsServer::DoPostHeapMarkOrCheckL()
1.207 + {
1.208 + }
1.209 +
1.210 +void CScsServer::IncrementSessionCount()
1.211 +/**
1.212 + Record the fact that another session has been created. If this new
1.213 + session is the only session then cancel the shutdown timer.
1.214 + */
1.215 + {
1.216 + ++iSessionCount;
1.217 + if (iSessionCount == 1)
1.218 + {
1.219 + if(iShutdownTimer)
1.220 + {
1.221 + iShutdownTimer->Cancel();
1.222 + }
1.223 + }
1.224 + }
1.225 +
1.226 +void CScsServer::DecrementSessionCount()
1.227 +/**
1.228 + Record the fact that a session has been deleted. If this was the
1.229 + only remaining session then start the shutdown timer.
1.230 +
1.231 + Note the shutdown timer may be deferred if a request cleanup is
1.232 + pending.
1.233 + */
1.234 + {
1.235 + --iSessionCount;
1.236 + if (iShutdownTimer && (iSessionCount == 0) && (! iAsyncCleanup->IsActive()))
1.237 + {
1.238 + iShutdownTimer->Restart();
1.239 + }
1.240 + }
1.241 +
1.242 +EXPORT_C void CScsServer::ShutdownWhenIdleL()
1.243 + /**
1.244 + Shutdown immediately when server is next idle. If the server
1.245 + is not transient (ie. has no shutdown timer), this call is
1.246 + prohibited and will leave with KErrNotSupported.
1.247 + */
1.248 + {
1.249 + if(! iShutdownTimer)
1.250 + {
1.251 + // We do not allow shutdown of non-transient servers.
1.252 + User::Leave(KErrNotSupported);
1.253 + }
1.254 +
1.255 + // Next time we are idle, shutdown immediately.
1.256 + iShutdownTimer->ImmediateTimeoutNextRestart();
1.257 + }
1.258 +
1.259 +
1.260 +
1.261 +// -------- asynchronous requests --------
1.262 +
1.263 +CAsyncRequest* CScsServer::FindAsyncRequest(
1.264 + CScsSession* aSession, CScsSubsession* aSubsession, TInt aFunction)
1.265 +/**
1.266 + Find the outstanding request which matches the supplied criteria.
1.267 +
1.268 + @param aSession Session which hosts the request.
1.269 + @param aSubsession Subsession which hosts the request, NULL if
1.270 + the request is relative to a session.
1.271 + @param aFunction The function identifier, without any SCS code.
1.272 + @return The matching asynchronous request, NULL if not
1.273 + found.
1.274 + */
1.275 + {
1.276 + TInt reqCount = iAsyncRequests.Count();
1.277 + for (TInt i = reqCount - 1; i >= 0; --i)
1.278 + {
1.279 + CAsyncRequest* req = iAsyncRequests[i];
1.280 +
1.281 + if (req->iSession != aSession)
1.282 + continue;
1.283 +
1.284 + if (req->iSubsession != aSubsession)
1.285 + continue;
1.286 +
1.287 + if (req->iFunction != aFunction)
1.288 + continue;
1.289 +
1.290 + return req;
1.291 + }
1.292 +
1.293 + return 0; // request not found
1.294 + }
1.295 +
1.296 +void CScsServer::AddAsyncRequestL(CAsyncRequest* aAsyncRequest)
1.297 +/**
1.298 + Add the supplied request to the server's collection.
1.299 +
1.300 + @param aAsyncRequest Request to add. If this function succeeds
1.301 + then ownership has been transferred to the
1.302 + collection.
1.303 + */
1.304 + {
1.305 + // ensure this session does not already have an outstanding request
1.306 + // for the same function
1.307 + CAsyncRequest* existReq = FindAsyncRequest(
1.308 + aAsyncRequest->iSession, aAsyncRequest->iSubsession,
1.309 + aAsyncRequest->iFunction);
1.310 +
1.311 + if (existReq != 0)
1.312 + User::Leave(KErrScsAsyncAlreadyQueued);
1.313 +
1.314 + iAsyncRequests.AppendL(aAsyncRequest);
1.315 + }
1.316 +
1.317 +void CScsServer::CancelAsyncRequest(
1.318 + CScsSession* aSession, CScsSubsession* aSubsession, TInt aFunction)
1.319 +/**
1.320 + Cancels a specific (sub)session request in response to a client
1.321 + command. Also completes the client request.
1.322 +
1.323 + CancelOutstandingRequest should be called when a (sub)session is closed.
1.324 +
1.325 + @param aSession Session which hosts the request.
1.326 + @param aSubsession Subsession which hosts the request, NULL if
1.327 + the request is relative to a session.
1.328 + @param aFunction The function identifier, without any SCS code.
1.329 + */
1.330 + {
1.331 + CAsyncRequest* req = FindAsyncRequest(aSession, aSubsession, aFunction);
1.332 +
1.333 + // not an error if the request is not queued; could have been
1.334 + // completed before the cancel function was processed.
1.335 + if (req != 0)
1.336 + req->CancelCompleteAndMarkForDeletion();
1.337 + }
1.338 +
1.339 +void CScsServer::CancelOutstandingRequests(CScsSession* aSession, TBool aCompleteClientRequests)
1.340 +/**
1.341 + Cancels and deletes all outstanding asynchronous requests associated
1.342 + with the supplied session or any of its subsessions. Does not complete
1.343 + the associated client requests.
1.344 +
1.345 + This function should be called when a session is closed.
1.346 + CancelAsyncRequest should be called when a specific request is cancelled.
1.347 +
1.348 + @param aSession Session which is being closed.
1.349 + @param aCompleteClientRequests Whether to complete the client-side requests
1.350 + with KErrCancel.
1.351 + */
1.352 + {
1.353 + CancelOutstandingRequests(aSession, KWildSubsession, aCompleteClientRequests);
1.354 + }
1.355 +
1.356 +void CScsServer::CancelOutstandingRequests(CScsSession* aSession, CScsSubsession* aSubsession, TBool aCompleteClientRequests)
1.357 +/**
1.358 + Cancels and deletes all outstanding asynchronous requests associated
1.359 + with the supplied session and subsession. This should be called when
1.360 + a session or subsession is closed.
1.361 +
1.362 + As an exception, the user-side request is completed when a subsession is
1.363 + closed, else the request would not be completed until the session itself
1.364 + was destroyed.
1.365 +
1.366 + CancelAsyncRequest should be called when a specific request is cancelled.
1.367 +
1.368 + @param aSession Session which is being closed.
1.369 + @param aSubsession Subsession which is being closed. If this is
1.370 + KWildSubsession then a session is being closed so all of
1.371 + its subsession requests should be destroyed as well.
1.372 + @param aCompleteClientRequests Whether to complete the client-side requests
1.373 + with KErrCancel.
1.374 + */
1.375 + {
1.376 + TBool wildSubsession = (aSubsession == KWildSubsession);
1.377 +
1.378 + TInt reqCount = iAsyncRequests.Count();
1.379 + for (TInt i = reqCount - 1; i >= 0; --i)
1.380 + {
1.381 + CAsyncRequest* req = iAsyncRequests[i];
1.382 +
1.383 + TBool sessionMatch = (req->iSession == aSession);
1.384 + if (! sessionMatch)
1.385 + continue;
1.386 +
1.387 + TBool subsessionMatch = wildSubsession || (req->iSubsession == aSubsession);
1.388 + if (! subsessionMatch)
1.389 + continue;
1.390 +
1.391 + if (aCompleteClientRequests)
1.392 + req->CancelCompleteAndMarkForDeletion();
1.393 + else
1.394 + {
1.395 + req->DoCleanup();
1.396 + req->MarkForDeletion();
1.397 + }
1.398 + }
1.399 + }
1.400 +
1.401 +TInt CScsServer::RemoveCompletedRequests(TAny* aPtr)
1.402 +/**
1.403 + This static function is called when iAsyncCleanup
1.404 + runs. It interprets its argument as a pointer to
1.405 + an instance of CScsServer and removes any asynchronous
1.406 + requests which have been completed.
1.407 +
1.408 + @param aPtr Required callback argument. Interpreted
1.409 + as a pointer to an instance of CScsServer.
1.410 + @return KErrNone. Required to satisfy the TCallBack
1.411 + function signature.
1.412 + @see RemoveCompletedRequests()
1.413 + */
1.414 + {
1.415 + CScsServer* svr = static_cast<CScsServer*>(aPtr);
1.416 + svr->RemoveCompletedRequests();
1.417 + return KErrNone;
1.418 + }
1.419 +
1.420 +void CScsServer::RemoveCompletedRequests()
1.421 +/**
1.422 + Delete any asynchronous requests which are marked for deletion.
1.423 + */
1.424 + {
1.425 + // The requests have already been completed; they just need to be removed.
1.426 + TInt reqCount = iAsyncRequests.Count();
1.427 + for (TInt i = reqCount - 1; i >= 0; --i)
1.428 + {
1.429 + CAsyncRequest* req = iAsyncRequests[i];
1.430 + if (req->iSession != 0) // still outstanding if iSession != 0
1.431 + continue;
1.432 +
1.433 + delete req;
1.434 + iAsyncRequests.Remove(i);
1.435 + }
1.436 +
1.437 + // if no more outstanding requests then reset array so heap balances
1.438 + if (iAsyncRequests.Count() == 0)
1.439 + iAsyncRequests.Compress();
1.440 +
1.441 + // if the shutdown timer was deferred because of an impending
1.442 + // cleanup then launch it now.
1.443 + if (iShutdownTimer && (iSessionCount == 0))
1.444 + {
1.445 + iShutdownTimer->Restart();
1.446 + }
1.447 + }
1.448 +// End of file
1.449 +