Update contrib.
2 * Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
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".
9 * Initial Contributors:
10 * Nokia Corporation - initial contribution.
15 * Implements CScsServer functionality. See class and functions definitions
25 #include <scs/scsserver.h>
26 #include "scsserverconstants.h"
28 static const TInt defaultPolicyRangeCount = 1;
29 static const TInt defaultPolicyRanges[defaultPolicyRangeCount] =
34 static const TUint8 defaultPolicyElementsIndex[defaultPolicyRangeCount] =
36 CPolicyServer::EAlwaysPass
39 static const CPolicyServer::TPolicyElement defaultPolicyPolicyElements[1] = {};
42 static const CPolicyServer::TPolicy defaultPolicy =
44 CPolicyServer::EAlwaysPass, // Allow all connects
45 defaultPolicyRangeCount,
47 defaultPolicyElementsIndex,
48 defaultPolicyPolicyElements,
51 EXPORT_C CScsServer::CScsServer(const TVersion& aVersion, CActive::TPriority aPriority)
53 Record this server's version so it can be compared against the requested
54 version in NewSessionL.
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.
60 : CPolicyServer(aPriority, defaultPolicy, ESharableSessions)
67 EXPORT_C CScsServer::CScsServer(const TVersion& aVersion, const CPolicyServer::TPolicy& aPolicy, CActive::TPriority aPriority)
69 Record this server's version so it can be compared against the requested
70 version in NewSessionL.
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.
77 Note that aPolicy must be configured to allow all functions
78 covered by the KScsFunctionMask mask.
80 : CPolicyServer(aPriority, aPolicy, ESharableSessions)
87 EXPORT_C void CScsServer::ConstructL(TInt aShutdownPeriodUs)
89 Second-phase constructor allocates the shutdown timer for this server object.
91 If aShutdownPeriodUs is not 0, this function starts the shutdown
92 timer because the server starts up with no current sessions.
94 If aShutdownPeriodUs is 0, the timer is not started and the server
97 nb. It must be called, even if you do not want a shutdown timer.
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.
102 @param aShutdownPeriodUs Shutdown period in microseconds.
105 if(aShutdownPeriodUs > 0)
107 iShutdownTimer = CShutdownTimer::NewL(aShutdownPeriodUs);
108 iShutdownTimer->Restart();
111 iContainerIndex = CObjectConIx::NewL();
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);
120 EXPORT_C void CScsServer::DisableShutdownTimer()
122 The server will no longer shutdown after the last client session closes.
123 Client calls to RScsClientBase::ShutdownServer will fail with KErrNotSupported.
128 iShutdownTimer->Cancel();
130 delete iShutdownTimer;
134 EXPORT_C void CScsServer::EnableShutdownTimerL(TInt aShutdownPeriodUs)
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.
144 if(aShutdownPeriodUs <= 0)
148 DisableShutdownTimer();
149 iShutdownTimer = CShutdownTimer::NewL(aShutdownPeriodUs);
150 if(iSessionCount == 0)
152 iShutdownTimer->Restart();
157 EXPORT_C CScsServer::~CScsServer()
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.
164 __ASSERT_DEBUG(iSessionCount == 0, PanicServer(ESvrRemSessions));
165 __ASSERT_DEBUG(iAsyncCleanup == 0 || !iAsyncCleanup->IsActive(), PanicServer(ESvrRemCleanup));
166 __ASSERT_DEBUG(iAsyncRequests.Count() == 0, PanicServer(ESvrRemRequests));
168 delete iContainerIndex;
169 delete iShutdownTimer;
171 delete iAsyncCleanup;
172 iAsyncRequests.Reset();
175 // -------- sessions --------
177 EXPORT_C CSession2* CScsServer::NewSessionL(const TVersion& aVersion, const RMessage2& aMessage) const
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.
185 @param aVersion Version of server which client requires.
186 @param aMessage Connect message.
187 @return New initialized instance of CSession2 subclass.
190 TBool versionOk = User::QueryVersionSupported(/* aCurrent */ iVersion, /* aRequested */ aVersion);
192 User::Leave(KErrNotSupported);
194 CScsSession* s = const_cast<CScsServer*>(this)->DoNewSessionL(aMessage);
199 EXPORT_C void CScsServer::DoPreHeapMarkOrCheckL()
203 EXPORT_C void CScsServer::DoPostHeapMarkOrCheckL()
207 void CScsServer::IncrementSessionCount()
209 Record the fact that another session has been created. If this new
210 session is the only session then cancel the shutdown timer.
214 if (iSessionCount == 1)
218 iShutdownTimer->Cancel();
223 void CScsServer::DecrementSessionCount()
225 Record the fact that a session has been deleted. If this was the
226 only remaining session then start the shutdown timer.
228 Note the shutdown timer may be deferred if a request cleanup is
233 if (iShutdownTimer && (iSessionCount == 0) && (! iAsyncCleanup->IsActive()))
235 iShutdownTimer->Restart();
239 EXPORT_C void CScsServer::ShutdownWhenIdleL()
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.
248 // We do not allow shutdown of non-transient servers.
249 User::Leave(KErrNotSupported);
252 // Next time we are idle, shutdown immediately.
253 iShutdownTimer->ImmediateTimeoutNextRestart();
258 // -------- asynchronous requests --------
260 CAsyncRequest* CScsServer::FindAsyncRequest(
261 CScsSession* aSession, CScsSubsession* aSubsession, TInt aFunction)
263 Find the outstanding request which matches the supplied criteria.
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
273 TInt reqCount = iAsyncRequests.Count();
274 for (TInt i = reqCount - 1; i >= 0; --i)
276 CAsyncRequest* req = iAsyncRequests[i];
278 if (req->iSession != aSession)
281 if (req->iSubsession != aSubsession)
284 if (req->iFunction != aFunction)
290 return 0; // request not found
293 void CScsServer::AddAsyncRequestL(CAsyncRequest* aAsyncRequest)
295 Add the supplied request to the server's collection.
297 @param aAsyncRequest Request to add. If this function succeeds
298 then ownership has been transferred to the
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);
309 User::Leave(KErrScsAsyncAlreadyQueued);
311 iAsyncRequests.AppendL(aAsyncRequest);
314 void CScsServer::CancelAsyncRequest(
315 CScsSession* aSession, CScsSubsession* aSubsession, TInt aFunction)
317 Cancels a specific (sub)session request in response to a client
318 command. Also completes the client request.
320 CancelOutstandingRequest should be called when a (sub)session is closed.
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.
328 CAsyncRequest* req = FindAsyncRequest(aSession, aSubsession, aFunction);
330 // not an error if the request is not queued; could have been
331 // completed before the cancel function was processed.
333 req->CancelCompleteAndMarkForDeletion();
336 void CScsServer::CancelOutstandingRequests(CScsSession* aSession, TBool aCompleteClientRequests)
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.
342 This function should be called when a session is closed.
343 CancelAsyncRequest should be called when a specific request is cancelled.
345 @param aSession Session which is being closed.
346 @param aCompleteClientRequests Whether to complete the client-side requests
350 CancelOutstandingRequests(aSession, KWildSubsession, aCompleteClientRequests);
353 void CScsServer::CancelOutstandingRequests(CScsSession* aSession, CScsSubsession* aSubsession, TBool aCompleteClientRequests)
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.
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
363 CancelAsyncRequest should be called when a specific request is cancelled.
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
373 TBool wildSubsession = (aSubsession == KWildSubsession);
375 TInt reqCount = iAsyncRequests.Count();
376 for (TInt i = reqCount - 1; i >= 0; --i)
378 CAsyncRequest* req = iAsyncRequests[i];
380 TBool sessionMatch = (req->iSession == aSession);
384 TBool subsessionMatch = wildSubsession || (req->iSubsession == aSubsession);
385 if (! subsessionMatch)
388 if (aCompleteClientRequests)
389 req->CancelCompleteAndMarkForDeletion();
393 req->MarkForDeletion();
398 TInt CScsServer::RemoveCompletedRequests(TAny* aPtr)
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.
405 @param aPtr Required callback argument. Interpreted
406 as a pointer to an instance of CScsServer.
407 @return KErrNone. Required to satisfy the TCallBack
409 @see RemoveCompletedRequests()
412 CScsServer* svr = static_cast<CScsServer*>(aPtr);
413 svr->RemoveCompletedRequests();
417 void CScsServer::RemoveCompletedRequests()
419 Delete any asynchronous requests which are marked for deletion.
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)
426 CAsyncRequest* req = iAsyncRequests[i];
427 if (req->iSession != 0) // still outstanding if iSession != 0
431 iAsyncRequests.Remove(i);
434 // if no more outstanding requests then reset array so heap balances
435 if (iAsyncRequests.Count() == 0)
436 iAsyncRequests.Compress();
438 // if the shutdown timer was deferred because of an impending
439 // cleanup then launch it now.
440 if (iShutdownTimer && (iSessionCount == 0))
442 iShutdownTimer->Restart();