|
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 * CScsSession implementation. See class and function definitions |
|
16 * for more detail. |
|
17 * |
|
18 */ |
|
19 |
|
20 |
|
21 /** |
|
22 @file |
|
23 */ |
|
24 |
|
25 |
|
26 #include <scs/scsserver.h> |
|
27 #include "scsserverconstants.h" |
|
28 |
|
29 EXPORT_C void CScsSession::ConstructL() |
|
30 /** |
|
31 The subsession [handle] container could be constructed |
|
32 here, but that is deferred until the subsession is allocated to |
|
33 avoid the memory overhead for sessions which may not require |
|
34 subsessions. |
|
35 */ |
|
36 { |
|
37 iServer.IncrementSessionCount(); |
|
38 } |
|
39 |
|
40 EXPORT_C CScsSession::CScsSession(CScsServer &aServer) |
|
41 : iServer(aServer) |
|
42 /** |
|
43 Setup the iServer member variable so it can be used during construction |
|
44 */ |
|
45 { |
|
46 } |
|
47 |
|
48 |
|
49 EXPORT_C CScsSession::~CScsSession() |
|
50 /** |
|
51 Deletes any subsessions. |
|
52 |
|
53 Deletes any outstanding requests. |
|
54 |
|
55 Decrements the server's session count so the server can be shut down |
|
56 if there are no open sessions. |
|
57 */ |
|
58 { |
|
59 iServer.CancelOutstandingRequests(this, /* aCompleteClientRequests */ EFalse); |
|
60 |
|
61 DeleteSubsessionContainers(); // closes any remaining subsessions |
|
62 |
|
63 // decrement the session count, so the server can be shut down if |
|
64 // there are no more open sessions. |
|
65 iServer.DecrementSessionCount(); |
|
66 } |
|
67 |
|
68 EXPORT_C void CScsSession::CloseAllSubsessionsL() |
|
69 { |
|
70 DeleteSubsessionContainers(); |
|
71 } |
|
72 |
|
73 EXPORT_C void CScsSession::ServiceL(const RMessage2& aMessage) |
|
74 /** |
|
75 Implement CSession2 by handling any SCS-specific messages, and |
|
76 otherwise delegating to the subclass' implementation. |
|
77 |
|
78 @param aMessage Standard server-side message object. |
|
79 */ |
|
80 { |
|
81 ScsImpl::TScsFunction scsFunc; |
|
82 TInt implFunc; |
|
83 ScsImpl::ExtractScsAndImplFunctions(aMessage, &scsFunc, &implFunc); |
|
84 TBool completeMessage = ETrue; |
|
85 |
|
86 switch (scsFunc) |
|
87 { |
|
88 // sessions |
|
89 case ScsImpl::ECallSessionFunc: |
|
90 completeMessage = DoServiceL(implFunc, aMessage); |
|
91 break; |
|
92 |
|
93 case ScsImpl::EPreCloseSession: |
|
94 PreCloseSession(); |
|
95 break; |
|
96 |
|
97 case ScsImpl::ECancelSessionFunc: |
|
98 CancelAsyncSessionRequestL(implFunc); |
|
99 break; |
|
100 |
|
101 case ScsImpl::EGetServerPid: |
|
102 { |
|
103 TPckgBuf<TProcessId> idBuf; |
|
104 RProcess proc; |
|
105 idBuf() = proc.Id(); |
|
106 aMessage.WriteL(0, idBuf); |
|
107 break; |
|
108 } |
|
109 |
|
110 case ScsImpl::EShutdownAsap: |
|
111 iServer.ShutdownWhenIdleL(); |
|
112 break; |
|
113 |
|
114 // subsessions |
|
115 case ScsImpl::ECreateSubsession: |
|
116 // if there are no open subsessions before this attempt then clean up |
|
117 // the containers if it fails. This is to ensure the server heap balances |
|
118 // in the event of failure. |
|
119 iPreCreateSubsessionCount = iSsHandles ? iSsHandles->ActiveCount() : 0; |
|
120 CreateSubsessionL(implFunc, aMessage); |
|
121 break; |
|
122 |
|
123 case ScsImpl::ECloseSubsession: |
|
124 CloseSubsessionL(aMessage); |
|
125 break; |
|
126 |
|
127 case ScsImpl::ECallSubsessionFunc: |
|
128 completeMessage = CallSubsessionFunctionL(implFunc, aMessage); |
|
129 break; |
|
130 |
|
131 case ScsImpl::ECancelSubsessionFunc: |
|
132 CancelAsyncSubsessionRequestL(implFunc, aMessage); |
|
133 break; |
|
134 |
|
135 // server heap testing |
|
136 case ScsImpl::EUHeapSetFail: |
|
137 #ifdef _DEBUG |
|
138 iServer.DoPreHeapMarkOrCheckL(); |
|
139 __UHEAP_MARK; |
|
140 __UHEAP_SETFAIL(RAllocator::EDeterministic, aMessage.Int0()); |
|
141 iServer.DoPostHeapMarkOrCheckL(); |
|
142 #endif |
|
143 break; |
|
144 |
|
145 case ScsImpl::EUHeapResetFail: |
|
146 #ifdef _DEBUG |
|
147 iServer.DoPreHeapMarkOrCheckL(); |
|
148 __UHEAP_RESET; |
|
149 __UHEAP_MARKEND; |
|
150 iServer.DoPostHeapMarkOrCheckL(); |
|
151 #endif |
|
152 break; |
|
153 |
|
154 // unrecognized SCS code, so fail with KErrNotSupported |
|
155 default: |
|
156 User::Leave(KErrNotSupported); |
|
157 } |
|
158 |
|
159 // None of the delegate functions have left so complete with KErrNone. |
|
160 if(completeMessage) |
|
161 { |
|
162 aMessage.Complete(KErrNone); |
|
163 } |
|
164 } |
|
165 |
|
166 EXPORT_C void CScsSession::ServiceError(const RMessage2& aMessage, TInt aError) |
|
167 /** |
|
168 Override CSession2 by handling any leave which occurred during the ServiceL. |
|
169 |
|
170 Panick the client if the leave is because of a bad descriptor or subsession |
|
171 handle. Otherwise, complete the request with the error code. |
|
172 |
|
173 @param aMessage Message which caused leave to occur. |
|
174 @param aError Leave code. This is a Symbian OS error code. |
|
175 @see CSession2::ServiceError |
|
176 */ |
|
177 { |
|
178 // if failed to create first subsession then free containers so heap |
|
179 // balances after message has been completed. |
|
180 |
|
181 ScsImpl::TScsFunction scsFunc; |
|
182 ScsImpl::ExtractScsAndImplFunctions(aMessage, &scsFunc, NULL); |
|
183 |
|
184 if (scsFunc == ScsImpl::ECreateSubsession && iPreCreateSubsessionCount == 0) |
|
185 DeleteSubsessionContainers(); |
|
186 |
|
187 switch (aError) |
|
188 { |
|
189 case KErrBadDescriptor: |
|
190 PanicClient(aMessage, ScsImpl::EScsClBadDesc); |
|
191 break; |
|
192 |
|
193 case KErrBadHandle: |
|
194 PanicClient(aMessage, ScsImpl::EScsClBadHandle); |
|
195 break; |
|
196 |
|
197 case KErrScsAsyncAlreadyQueued: |
|
198 PanicClient(aMessage, ScsImpl::EScsClAsyncAlreadyQueued); |
|
199 break; |
|
200 |
|
201 default: |
|
202 aMessage.Complete(aError); |
|
203 break; |
|
204 } |
|
205 } |
|
206 |
|
207 // -------- session close -------- |
|
208 |
|
209 void CScsSession::PreCloseSession() |
|
210 /** |
|
211 This function is invoked from RScsClientBase::Close |
|
212 just before the session is closed, to cancel any |
|
213 outstanding requests. |
|
214 */ |
|
215 { |
|
216 iServer.CancelOutstandingRequests(this, /* aCompleteClientRequests */ ETrue); |
|
217 } |
|
218 |
|
219 // -------- asynchronous requests -------- |
|
220 |
|
221 void CScsSession::CancelAsyncSessionRequestL(TInt aFunction) |
|
222 /** |
|
223 This function is called when handling an ECancelSessionFunction message. |
|
224 If the outstanding function cannot be found, this function does nothing. |
|
225 |
|
226 @param aFunction Implementation function without SCS code. |
|
227 */ |
|
228 { |
|
229 iServer.CancelAsyncRequest(this, /* aSubsession */ 0, aFunction); |
|
230 } |
|
231 |
|
232 // -------- subsessions -------- |
|
233 |
|
234 CScsSubsession* CScsSession::GetSubsessionL(const RMessage2& aMessage) |
|
235 /** |
|
236 Extract subsession handle from the supplied message and return |
|
237 a pointer to the corresponding subsession object. |
|
238 |
|
239 @param aMessage Standard server-side message object. The fourth |
|
240 argument is the subsession handle. |
|
241 @return Pointer to corresponding subsession object. |
|
242 @leave KErrBadHandle if the handle does not identify a |
|
243 current subsession. |
|
244 */ |
|
245 { |
|
246 TInt handle = aMessage.Int3(); |
|
247 CObject* obj = iSsHandles->AtL(handle); // leaves with KErrBadHandle if not found |
|
248 return static_cast<CScsSubsession*>(obj); |
|
249 } |
|
250 |
|
251 void CScsSession::DeleteSubsessionContainers() |
|
252 /** |
|
253 Free the handle and object containers which this session uses |
|
254 to manage subsessions. It is safe to call this function if the |
|
255 containers were not set up successfully. |
|
256 */ |
|
257 { |
|
258 delete iSsHandles; |
|
259 iSsHandles = 0; |
|
260 |
|
261 if (iSsObjects != 0) |
|
262 { |
|
263 iServer.iContainerIndex->Remove(iSsObjects); |
|
264 iSsObjects = 0; |
|
265 } |
|
266 } |
|
267 |
|
268 void CScsSession::CreateSubsessionL(TInt aFunction, const RMessage2& aMessage) |
|
269 /** |
|
270 Attempt to allocate a subsession object for this session. The actual |
|
271 subsession allocation is delegated to the subclass's implementation |
|
272 of DoCreateSubsessionL. If the subclass has not reimplemented this |
|
273 function, then default implementation leaves with KErrNotSupported. |
|
274 |
|
275 @param aFunction Function identifier without SCS code. |
|
276 @param aMessage Standard server-side message object. |
|
277 */ |
|
278 { |
|
279 // if this is the first subsession then create the object container and index |
|
280 if (iSsObjects == 0) |
|
281 { |
|
282 iSsObjects = iServer.iContainerIndex->CreateL(); |
|
283 iSsHandles = CObjectIx::NewL(); |
|
284 } |
|
285 |
|
286 CScsSubsession* ss = DoCreateSubsessionL(aFunction, aMessage); |
|
287 CleanupClosePushL(*ss); |
|
288 |
|
289 iSsObjects->AddL(ss); |
|
290 TInt handle = iSsHandles->AddL(ss); |
|
291 CleanupStack::Pop(ss); |
|
292 |
|
293 TPckg<TInt> handlePckg(handle); |
|
294 TInt r = aMessage.Write(3, handlePckg); |
|
295 User::LeaveIfError(r); |
|
296 } |
|
297 |
|
298 #ifdef _BullseyeCoverage |
|
299 static const char * const bull1="BullseyeCoverage save off"; |
|
300 #endif |
|
301 EXPORT_C CScsSubsession* CScsSession::DoCreateSubsessionL(TInt aFunction, const RMessage2& aMessage) |
|
302 /** |
|
303 This default implementation leaves with KErrNotSupported. The subclass |
|
304 does not have to supply its own implementation unless it actually wants |
|
305 to support subsessions. |
|
306 |
|
307 @param aFunction Function identifier without SCS code. The subclass |
|
308 implementation of this function would use this to decide |
|
309 what kind of subsession object to create. |
|
310 @param aMessage Client message. Not used. |
|
311 @leave KErrNotSupported. |
|
312 */ |
|
313 { |
|
314 (void) aFunction; |
|
315 (void) aMessage; |
|
316 |
|
317 User::Leave(KErrNotSupported); |
|
318 /*lint -unreachable*/ // Avoid compiler warning and keep lint happy |
|
319 return 0; |
|
320 } |
|
321 #ifdef _BullseyeCoverage |
|
322 static const char * const bull2="BullseyeCoverage restore"; |
|
323 #endif |
|
324 |
|
325 void CScsSession::CloseSubsessionL(const RMessage2& aMessage) |
|
326 /** |
|
327 Delete the subsession identified in the supplied message. |
|
328 |
|
329 If the subsession cannot be found this function leaves with KErrBadHandle, |
|
330 and the client is panicked in ServiceError. |
|
331 |
|
332 @param aMessage Standard server-side message handle. The fourth |
|
333 integer contains the subsession handle. |
|
334 */ |
|
335 { |
|
336 TInt handle = aMessage.Int3(); |
|
337 CObject* obj = iSsHandles->AtL(handle); // leaves with KErrBadHandle if not found |
|
338 CScsSubsession* ss = static_cast<CScsSubsession*>(obj); |
|
339 |
|
340 iServer.CancelOutstandingRequests(this, ss, /* aCancelClientRequests */ ETrue); |
|
341 |
|
342 iSsHandles->Remove(handle); |
|
343 |
|
344 // close the container objects to ensure the heap balances when the last subsession is closed |
|
345 if (iSsHandles->ActiveCount() == 0) |
|
346 DeleteSubsessionContainers(); |
|
347 } |
|
348 |
|
349 TBool CScsSession::CallSubsessionFunctionL(TInt aFunction, const RMessage2& aMessage) |
|
350 /** |
|
351 Pass the supplied function identifier and message to the subsession |
|
352 which is identified in the message. |
|
353 |
|
354 If the subsession cannot be found this function leaves with KErrBadHandle, |
|
355 and the client is panicked in ServiceError. |
|
356 |
|
357 @param aFunction Function identifier without SCS code. |
|
358 @param aMessage Client message. |
|
359 @return ETrue means complete client request now. |
|
360 |
|
361 */ |
|
362 { |
|
363 CScsSubsession* ss = GetSubsessionL(aMessage); |
|
364 return ss->DoServiceL(aFunction, aMessage); |
|
365 } |
|
366 |
|
367 void CScsSession::CancelAsyncSubsessionRequestL(TInt aFunction, const RMessage2& aMessage) |
|
368 /** |
|
369 Cancel an outstanding asynchronous request for the subsession |
|
370 identified in the supplied message. |
|
371 |
|
372 @param aFunction Function identifier without SCS code. |
|
373 @param aMessage Standard server-side message handle. The fourth |
|
374 integer contains the subsession handle. |
|
375 */ |
|
376 { |
|
377 CScsSubsession* ss = GetSubsessionL(aMessage); |
|
378 iServer.CancelAsyncRequest(this, ss, aFunction); |
|
379 } |
|
380 |