diff -r 675a964f4eb5 -r 35751d3474b7 cryptomgmtlibs/securitycommonutils/source/scsserver/scsserver.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cryptomgmtlibs/securitycommonutils/source/scsserver/scsserver.cpp Thu Sep 10 14:01:51 2009 +0300 @@ -0,0 +1,446 @@ +/* +* Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the License "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* Implements CScsServer functionality. See class and functions definitions +* for more detail. +* +*/ + + +/** + @file +*/ + +#include +#include "scsserverconstants.h" + +static const TInt defaultPolicyRangeCount = 1; +static const TInt defaultPolicyRanges[defaultPolicyRangeCount] = + { + 0 // All requests + }; + +static const TUint8 defaultPolicyElementsIndex[defaultPolicyRangeCount] = + { + CPolicyServer::EAlwaysPass + }; + +static const CPolicyServer::TPolicyElement defaultPolicyPolicyElements[1] = {}; + + +static const CPolicyServer::TPolicy defaultPolicy = + { + CPolicyServer::EAlwaysPass, // Allow all connects + defaultPolicyRangeCount, + defaultPolicyRanges, + defaultPolicyElementsIndex, + defaultPolicyPolicyElements, + }; + +EXPORT_C CScsServer::CScsServer(const TVersion& aVersion, CActive::TPriority aPriority) +/** + Record this server's version so it can be compared against the requested + version in NewSessionL. + + @param aVersion This server's version. This is compared against each + client's requested version when the client tries to connect. + @param aPriority This server's active object priority. + */ + : CPolicyServer(aPriority, defaultPolicy, ESharableSessions) + ,iVersion(aVersion) +// ,iSessionCount(0) + { + // empty. + } + +EXPORT_C CScsServer::CScsServer(const TVersion& aVersion, const CPolicyServer::TPolicy& aPolicy, CActive::TPriority aPriority) +/** + Record this server's version so it can be compared against the requested + version in NewSessionL. + + @param aVersion This server's version. This is compared against each + client's requested version when the client tries to connect. + @param aPolicy Can be used to configure security for server connect and session functions + @param aPriority This server's active object priority. + + Note that aPolicy must be configured to allow all functions + covered by the KScsFunctionMask mask. + */ + : CPolicyServer(aPriority, aPolicy, ESharableSessions) + ,iVersion(aVersion) +// ,iSessionCount(0) + { + // empty. + } + +EXPORT_C void CScsServer::ConstructL(TInt aShutdownPeriodUs) +/** + Second-phase constructor allocates the shutdown timer for this server object. + + If aShutdownPeriodUs is not 0, this function starts the shutdown + timer because the server starts up with no current sessions. + + If aShutdownPeriodUs is 0, the timer is not started and the server + will not auto-exit. + + nb. It must be called, even if you do not want a shutdown timer. + + This function does not start the server, i.e. it does not call StartL. The + calling function must do this after this function returns. + + @param aShutdownPeriodUs Shutdown period in microseconds. + */ + { + if(aShutdownPeriodUs > 0) + { + iShutdownTimer = CShutdownTimer::NewL(aShutdownPeriodUs); + iShutdownTimer->Restart(); + } + + iContainerIndex = CObjectConIx::NewL(); + + TCallBack cb(RemoveCompletedRequests, this); + // EPriorityHigh to encourage the active scheduler to action the + // delete ASAP, in particular ahead of pending or new requests. + iAsyncCleanup = new(ELeave) CAsyncCallBack(cb, CActive::EPriorityHigh); + } + + +EXPORT_C void CScsServer::DisableShutdownTimer() +/** + The server will no longer shutdown after the last client session closes. + Client calls to RScsClientBase::ShutdownServer will fail with KErrNotSupported. +*/ + { + if(iShutdownTimer) + { + iShutdownTimer->Cancel(); + } + delete iShutdownTimer; + iShutdownTimer = 0; + } + +EXPORT_C void CScsServer::EnableShutdownTimerL(TInt aShutdownPeriodUs) +/** + Enable shutdown timer support in the server. + If there are currently no client sessions the timer will be immediately started, otherwise + it will be started when the last client session closes. + If the timer expires, before another client creates a session, the server will shutdown. + The RScsClientBase::ShutdownServer api will now be supported, if called the server timeout + will effectively be reduced to 0. +*/ + { + if(aShutdownPeriodUs <= 0) + { + return; + } + DisableShutdownTimer(); + iShutdownTimer = CShutdownTimer::NewL(aShutdownPeriodUs); + if(iSessionCount == 0) + { + iShutdownTimer->Restart(); + } + } + + +EXPORT_C CScsServer::~CScsServer() +/** + Frees resources used at this level. Specifically, frees the + container index, which is used to generate subsession containers, + the shutdown timer, and the async request cleanup object. + */ + { + __ASSERT_DEBUG(iSessionCount == 0, PanicServer(ESvrRemSessions)); + __ASSERT_DEBUG(iAsyncCleanup == 0 || !iAsyncCleanup->IsActive(), PanicServer(ESvrRemCleanup)); + __ASSERT_DEBUG(iAsyncRequests.Count() == 0, PanicServer(ESvrRemRequests)); + + delete iContainerIndex; + delete iShutdownTimer; + + delete iAsyncCleanup; + iAsyncRequests.Reset(); + } + +// -------- sessions -------- + +EXPORT_C CSession2* CScsServer::NewSessionL(const TVersion& aVersion, const RMessage2& aMessage) const +/** + Implement CServer2 by allocating a new session object. This function + delegates the actual allocation to the subclass. Before creating the + session object, it compares the requested version with its own version. + After creating the session object, it increments the session count, which + reset the shutdown timer if it is the only session. + + @param aVersion Version of server which client requires. + @param aMessage Connect message. + @return New initialized instance of CSession2 subclass. + */ + { + TBool versionOk = User::QueryVersionSupported(/* aCurrent */ iVersion, /* aRequested */ aVersion); + if (! versionOk) + User::Leave(KErrNotSupported); + + CScsSession* s = const_cast(this)->DoNewSessionL(aMessage); + + return s; + } + +EXPORT_C void CScsServer::DoPreHeapMarkOrCheckL() + { + } + +EXPORT_C void CScsServer::DoPostHeapMarkOrCheckL() + { + } + +void CScsServer::IncrementSessionCount() +/** + Record the fact that another session has been created. If this new + session is the only session then cancel the shutdown timer. + */ + { + ++iSessionCount; + if (iSessionCount == 1) + { + if(iShutdownTimer) + { + iShutdownTimer->Cancel(); + } + } + } + +void CScsServer::DecrementSessionCount() +/** + Record the fact that a session has been deleted. If this was the + only remaining session then start the shutdown timer. + + Note the shutdown timer may be deferred if a request cleanup is + pending. + */ + { + --iSessionCount; + if (iShutdownTimer && (iSessionCount == 0) && (! iAsyncCleanup->IsActive())) + { + iShutdownTimer->Restart(); + } + } + +EXPORT_C void CScsServer::ShutdownWhenIdleL() + /** + Shutdown immediately when server is next idle. If the server + is not transient (ie. has no shutdown timer), this call is + prohibited and will leave with KErrNotSupported. + */ + { + if(! iShutdownTimer) + { + // We do not allow shutdown of non-transient servers. + User::Leave(KErrNotSupported); + } + + // Next time we are idle, shutdown immediately. + iShutdownTimer->ImmediateTimeoutNextRestart(); + } + + + +// -------- asynchronous requests -------- + +CAsyncRequest* CScsServer::FindAsyncRequest( + CScsSession* aSession, CScsSubsession* aSubsession, TInt aFunction) +/** + Find the outstanding request which matches the supplied criteria. + + @param aSession Session which hosts the request. + @param aSubsession Subsession which hosts the request, NULL if + the request is relative to a session. + @param aFunction The function identifier, without any SCS code. + @return The matching asynchronous request, NULL if not + found. + */ + { + TInt reqCount = iAsyncRequests.Count(); + for (TInt i = reqCount - 1; i >= 0; --i) + { + CAsyncRequest* req = iAsyncRequests[i]; + + if (req->iSession != aSession) + continue; + + if (req->iSubsession != aSubsession) + continue; + + if (req->iFunction != aFunction) + continue; + + return req; + } + + return 0; // request not found + } + +void CScsServer::AddAsyncRequestL(CAsyncRequest* aAsyncRequest) +/** + Add the supplied request to the server's collection. + + @param aAsyncRequest Request to add. If this function succeeds + then ownership has been transferred to the + collection. + */ + { + // ensure this session does not already have an outstanding request + // for the same function + CAsyncRequest* existReq = FindAsyncRequest( + aAsyncRequest->iSession, aAsyncRequest->iSubsession, + aAsyncRequest->iFunction); + + if (existReq != 0) + User::Leave(KErrScsAsyncAlreadyQueued); + + iAsyncRequests.AppendL(aAsyncRequest); + } + +void CScsServer::CancelAsyncRequest( + CScsSession* aSession, CScsSubsession* aSubsession, TInt aFunction) +/** + Cancels a specific (sub)session request in response to a client + command. Also completes the client request. + + CancelOutstandingRequest should be called when a (sub)session is closed. + + @param aSession Session which hosts the request. + @param aSubsession Subsession which hosts the request, NULL if + the request is relative to a session. + @param aFunction The function identifier, without any SCS code. + */ + { + CAsyncRequest* req = FindAsyncRequest(aSession, aSubsession, aFunction); + + // not an error if the request is not queued; could have been + // completed before the cancel function was processed. + if (req != 0) + req->CancelCompleteAndMarkForDeletion(); + } + +void CScsServer::CancelOutstandingRequests(CScsSession* aSession, TBool aCompleteClientRequests) +/** + Cancels and deletes all outstanding asynchronous requests associated + with the supplied session or any of its subsessions. Does not complete + the associated client requests. + + This function should be called when a session is closed. + CancelAsyncRequest should be called when a specific request is cancelled. + + @param aSession Session which is being closed. + @param aCompleteClientRequests Whether to complete the client-side requests + with KErrCancel. + */ + { + CancelOutstandingRequests(aSession, KWildSubsession, aCompleteClientRequests); + } + +void CScsServer::CancelOutstandingRequests(CScsSession* aSession, CScsSubsession* aSubsession, TBool aCompleteClientRequests) +/** + Cancels and deletes all outstanding asynchronous requests associated + with the supplied session and subsession. This should be called when + a session or subsession is closed. + + As an exception, the user-side request is completed when a subsession is + closed, else the request would not be completed until the session itself + was destroyed. + + CancelAsyncRequest should be called when a specific request is cancelled. + + @param aSession Session which is being closed. + @param aSubsession Subsession which is being closed. If this is + KWildSubsession then a session is being closed so all of + its subsession requests should be destroyed as well. + @param aCompleteClientRequests Whether to complete the client-side requests + with KErrCancel. + */ + { + TBool wildSubsession = (aSubsession == KWildSubsession); + + TInt reqCount = iAsyncRequests.Count(); + for (TInt i = reqCount - 1; i >= 0; --i) + { + CAsyncRequest* req = iAsyncRequests[i]; + + TBool sessionMatch = (req->iSession == aSession); + if (! sessionMatch) + continue; + + TBool subsessionMatch = wildSubsession || (req->iSubsession == aSubsession); + if (! subsessionMatch) + continue; + + if (aCompleteClientRequests) + req->CancelCompleteAndMarkForDeletion(); + else + { + req->DoCleanup(); + req->MarkForDeletion(); + } + } + } + +TInt CScsServer::RemoveCompletedRequests(TAny* aPtr) +/** + This static function is called when iAsyncCleanup + runs. It interprets its argument as a pointer to + an instance of CScsServer and removes any asynchronous + requests which have been completed. + + @param aPtr Required callback argument. Interpreted + as a pointer to an instance of CScsServer. + @return KErrNone. Required to satisfy the TCallBack + function signature. + @see RemoveCompletedRequests() + */ + { + CScsServer* svr = static_cast(aPtr); + svr->RemoveCompletedRequests(); + return KErrNone; + } + +void CScsServer::RemoveCompletedRequests() +/** + Delete any asynchronous requests which are marked for deletion. + */ + { + // The requests have already been completed; they just need to be removed. + TInt reqCount = iAsyncRequests.Count(); + for (TInt i = reqCount - 1; i >= 0; --i) + { + CAsyncRequest* req = iAsyncRequests[i]; + if (req->iSession != 0) // still outstanding if iSession != 0 + continue; + + delete req; + iAsyncRequests.Remove(i); + } + + // if no more outstanding requests then reset array so heap balances + if (iAsyncRequests.Count() == 0) + iAsyncRequests.Compress(); + + // if the shutdown timer was deferred because of an impending + // cleanup then launch it now. + if (iShutdownTimer && (iSessionCount == 0)) + { + iShutdownTimer->Restart(); + } + } +// End of file +