|
1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of the License "Symbian Foundation License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include <e32debug.h> |
|
17 #include "csecuresessionsubsessionbase.h" |
|
18 #include "csubsessionbase.h" |
|
19 #include "lbsmessageenums.h" |
|
20 #include "messageutils.h" |
|
21 #include "lbsdevloggermacros.h" |
|
22 |
|
23 /** |
|
24 constructor, call the CSecureSessionBase base class constructor |
|
25 |
|
26 @internalTechnology |
|
27 @released |
|
28 */ |
|
29 CSecureSessionSubSessionBase::CSecureSessionSubSessionBase() : CSecureSessionBase() |
|
30 { |
|
31 LBSLOG(ELogP3, "CSecureSessionSubSessionBase::CSecureSessionSubSessionBase()"); |
|
32 } |
|
33 |
|
34 /** |
|
35 destructor, release the subsession handler container |
|
36 |
|
37 @internalTechnology |
|
38 @released |
|
39 */ |
|
40 CSecureSessionSubSessionBase::~CSecureSessionSubSessionBase() |
|
41 { |
|
42 LBSLOG(ELogP3, "->CSecureSessionSubSessionBase::~CSecureSessionSubSessionBase()"); |
|
43 |
|
44 if (iObjectIx) |
|
45 { |
|
46 TInt count = iObjectIx->Count(); |
|
47 for(TInt i=0; i<count; i++) |
|
48 { |
|
49 CObject* theObj = (*iObjectIx)[i]; |
|
50 if (theObj) |
|
51 { |
|
52 TInt handle = iObjectIx->At(theObj); |
|
53 // if we reach here somethingbad has happened. The server class |
|
54 // (i.e. the session object) is being closed by the client, BEFORE |
|
55 // the client has closes all of the open subsessions. |
|
56 // So the only reasonable thingto do here is: |
|
57 // delete the subsession - without closing it first. 'Cos this is |
|
58 // _exactly_ what the client side has asked for (for some reason). |
|
59 // The may or may not be legal, or even a good idea depending on the type of server |
|
60 // that is being developeds. But the server framework should NOT |
|
61 // prevent this from happening. Generating a panic is a |
|
62 // server developers choice, not a framework developers choice. |
|
63 // We delete by calling CObjectIdx::Remove(). This will call CObject::Close. |
|
64 // This in turn calls MSubSessionImpl::MRelease::VirtualRelease |
|
65 // which will destroy the sub session for us. |
|
66 // CloseSubSession should not be called directly. |
|
67 iObjectIx->Remove(handle); |
|
68 |
|
69 // |
|
70 // If the array length has changed, then update count and move back one space, |
|
71 // so that the same cell will be re-inspected during the next iteration of the |
|
72 // loop This is because we have removed the current cell and therefore the |
|
73 // next cell is actually in iObjectIx[i] (i.e. the current one). |
|
74 TInt newCount = iObjectIx->Count(); |
|
75 |
|
76 if (newCount != count) |
|
77 { |
|
78 count = newCount; |
|
79 i--; |
|
80 } |
|
81 |
|
82 } |
|
83 } |
|
84 delete iObjectIx; |
|
85 } |
|
86 if (iContainerIx) |
|
87 { |
|
88 iContainerIx->Remove(iObjectCon); |
|
89 delete iContainerIx; |
|
90 } |
|
91 // session decrementing handled in the parent class |
|
92 LBSLOG(ELogP3, "<-CSecureSessionSubSessionBase::~CSecureSessionSubSessionBase()"); |
|
93 } |
|
94 |
|
95 /** |
|
96 called as part of the CSession2 construction. |
|
97 Create subsession handler container and call the session CreateL function to increase the session count |
|
98 |
|
99 @internalTechnology |
|
100 @released |
|
101 */ |
|
102 void CSecureSessionSubSessionBase::CreateL() |
|
103 { |
|
104 LBSLOG(ELogP3, "->CSecureSessionSubSessionBase::CreateL"); |
|
105 iObjectIx = CObjectIx::NewL(); |
|
106 iContainerIx = CObjectConIx::NewL(); |
|
107 iObjectCon = iContainerIx->CreateL(); |
|
108 CSecureSessionBase::CreateL(); // call the parent class to inc the session count |
|
109 iBaseCreateCalled = ETrue; |
|
110 LBSLOG(ELogP3, "<-CSecureSessionSubSessionBase::CreateL"); |
|
111 } |
|
112 |
|
113 /** |
|
114 Do the real thing for subsession construction. |
|
115 Check whether the session constructL function is called or not first. If not, panic the server, |
|
116 Create a subsession and push it to stack, get the implementation of subsession and invoke the |
|
117 real subsession creation implementation. |
|
118 |
|
119 Add the subsession handler to container and write the handler to client address space through message object |
|
120 Complete the creating message. |
|
121 |
|
122 @param aMessage A RMessage2 reference. |
|
123 @internalTechnology |
|
124 @released |
|
125 */ |
|
126 void CSecureSessionSubSessionBase::CreateSubSessionL(const RMessage2& aMessage) |
|
127 { |
|
128 __ASSERT_ALWAYS(iBaseCreateCalled, Server()->PanicServer(CSecureServerBase::EBaseCreateNotCalled)); |
|
129 CSubSessionBase* subSession = new (ELeave) CSubSessionBase(); |
|
130 // Note: Use the CObject::Close() function instead of usual destructor |
|
131 // because it is needed to correctly decrement the reference count. |
|
132 // Close() will destruct subSession anyway if the ref count == 0. |
|
133 CleanupClosePushL(*subSession); |
|
134 |
|
135 MSubSessionImpl* impl = subSession->GetImplL(aMessage); |
|
136 CleanupVirtualReleasePushL(*impl); // call Release() on destruction |
|
137 //CleanupVirtualRelease::PushL(*impl); |
|
138 subSession->SetImpl(impl); // will take ownership(!) |
|
139 CleanupStack::Pop(impl); |
|
140 |
|
141 // We need to pass a handle to the controllign server down to the subsession object. |
|
142 // Since the subsession impl object is a CBase object (NOT a CSession2 object) |
|
143 // we haev to do this outherwise the subsession will not be able to referene the |
|
144 // server - which seems like a useful thing to do. |
|
145 const CSecureServerBase* server = reinterpret_cast<const CSecureServerBase*>(Server()); |
|
146 impl->CreateSubSessionL(aMessage, server); |
|
147 |
|
148 iObjectCon->AddL(subSession); |
|
149 TInt handle = iObjectIx->AddL(subSession); |
|
150 TPckgC<TInt> pH(handle); |
|
151 MessageUtils::Write(aMessage, 3, pH); |
|
152 aMessage.Complete(KErrNone); |
|
153 CleanupStack::Pop(subSession); |
|
154 } |
|
155 |
|
156 /** |
|
157 Do the real thing for subsession destruction. |
|
158 Check whether the session constructL function is called or not first. If not, panic the server, |
|
159 get a subsession handler from container and complete the message if subsession is already close, |
|
160 if not, close subsession and remove it from container then complete the message. |
|
161 |
|
162 @param aMessage A RMessage2 reference. |
|
163 @internalTechnology |
|
164 @released |
|
165 */ |
|
166 void CSecureSessionSubSessionBase::DestroySubSession(const RMessage2& aMessage) |
|
167 { |
|
168 __ASSERT_ALWAYS(iBaseCreateCalled, Server()->PanicServer(CSecureServerBase::EBaseCreateNotCalled)); |
|
169 CSubSessionBase* subSession = reinterpret_cast<CSubSessionBase*>(iObjectIx->At(aMessage.Int3())); |
|
170 |
|
171 if (subSession == NULL) |
|
172 { |
|
173 aMessage.Complete(KErrBadHandle); |
|
174 } |
|
175 else |
|
176 { |
|
177 // we have been asked to close a subsession by the client side so |
|
178 // do just that :). c.f. CSecureSessionSubSessionBase::~CSecureSessionSubSessionBase() above. |
|
179 // In this case we do need to call CloseSubSession before deleting |
|
180 // the subsession object. |
|
181 // We delete by calling CObjectIdx::Remove().This will call CObject::Close. |
|
182 // This in turn calls MSubSessionImpl::MRelease::VirtualRelease |
|
183 // which willdestroy the sub session for us. |
|
184 CSubSessionBase* subSession = static_cast<CSubSessionBase*>(iObjectIx->At(aMessage.Int3())); |
|
185 iObjectIx->Remove(aMessage.Int3()); |
|
186 aMessage.Complete(KErrNone); |
|
187 } |
|
188 } |
|
189 |
|
190 /** |
|
191 Check whether the session constructL function is called or not first. If not, panic the server, |
|
192 |
|
193 Dispatch the message at session level, only two types of message are handled here: |
|
194 SubSession Open and Close. |
|
195 The other messages are fwd to subsession via DispatchMessage. |
|
196 |
|
197 @param aMessage A RMessage2 reference. |
|
198 @internalTechnology |
|
199 @released |
|
200 */ |
|
201 void CSecureSessionSubSessionBase::DispatchL(const RMessage2& aMessage) |
|
202 { |
|
203 __ASSERT_ALWAYS(iBaseCreateCalled, Server()->PanicServer(CSecureServerBase::EBaseCreateNotCalled)); |
|
204 switch(aMessage.Function()) |
|
205 { |
|
206 case ESecureSubSessionBaseOpen: |
|
207 CreateSubSessionL(aMessage); |
|
208 break; |
|
209 case ESecureSubSessionBaseClose: |
|
210 DestroySubSession(aMessage); |
|
211 break; |
|
212 default: |
|
213 // the message could be EITHER a session operation - which we have to handle here, or an operation |
|
214 // handled by the subsession which we have to forward |
|
215 DispatchMessageL(aMessage); |
|
216 break; |
|
217 } |
|
218 |
|
219 } |
|
220 |
|
221 /** |
|
222 Check whether the session constructL function is called or not first. If not, panic the server, |
|
223 |
|
224 Check whether the message are for session or subsession |
|
225 Dispatch the message at subsession level |
|
226 get the subsession handler from container and dispatch the message to subsession implementation! |
|
227 |
|
228 @param aMessage A RMessage2 reference. |
|
229 @internalTechnology |
|
230 @released |
|
231 */ |
|
232 void CSecureSessionSubSessionBase::DispatchMessageL(const RMessage2& aMessage) |
|
233 { |
|
234 __ASSERT_ALWAYS(iBaseCreateCalled, Server()->PanicServer(CSecureServerBase::EBaseCreateNotCalled)); |
|
235 // NB the test is intened to ignore a function enum of ELastSessionMessageId - this is not a valid command |
|
236 if(aMessage.Function()<ELastSessionMessageId) |
|
237 { |
|
238 // the message is for the session |
|
239 ServiceMessageL(aMessage); // implmented in the DERIVED CSessionBase class. |
|
240 } |
|
241 else if(aMessage.Function()>ELastSessionMessageId) |
|
242 { |
|
243 // MUST be a message for the subsystem object - delegate |
|
244 CSubSessionBase* subSession = static_cast<CSubSessionBase*>(iObjectIx->At(aMessage.Int3())); |
|
245 subSession->Impl()->DispatchL(aMessage); |
|
246 } |
|
247 } |
|
248 |
|
249 /** |
|
250 Return the server |
|
251 |
|
252 @return Pointer to server base |
|
253 @internalTechnology |
|
254 @released |
|
255 */ |
|
256 const CSecureServerBase* CSecureSessionSubSessionBase::Server() const |
|
257 { |
|
258 return reinterpret_cast<const CSecureServerBase*>(CSession2::Server()); |
|
259 } |
|
260 |
|
261 /** |
|
262 Check whether the session constructL function is called or not first. If not, panic the server, |
|
263 |
|
264 Dispatch the message at session level, only two types of message are handled here: |
|
265 SubSession Open and Close. |
|
266 If error happened when open subsession, destroy the subsession. |
|
267 |
|
268 otherwise, pop the error messages to session or fwd to subsession via DispatchError. |
|
269 |
|
270 @param aMessage A RMessage2 reference. |
|
271 @param aError Error code. |
|
272 @internalTechnology |
|
273 @released |
|
274 */ |
|
275 void CSecureSessionSubSessionBase::DispatchError(const RMessage2& aMessage, TInt aError) |
|
276 { |
|
277 __ASSERT_ALWAYS(iBaseCreateCalled, Server()->PanicServer(CSecureServerBase::EBaseCreateNotCalled)); |
|
278 CSubSessionBase* subSession = NULL; |
|
279 switch(aMessage.Function()) |
|
280 { |
|
281 case ESecureSubSessionBaseOpen: |
|
282 if(aError == KErrArgument) |
|
283 { |
|
284 // panic the client we have NO idea what sort |
|
285 // of sub session class the user was tryign to create. |
|
286 // This is a client side failure!, so shoot the client |
|
287 MessageUtils::PanicClient(aMessage, KServerFrameworkPanic, ESecureSubSessionBaseUnknownSubSessionType); |
|
288 // NB there is NOTHING to clean up here, everything is deleted via |
|
289 // the cleanup stack, and the subsession object was never added to the |
|
290 // obejct containers.... See CreateSubSessionL above |
|
291 } |
|
292 else |
|
293 { |
|
294 // CreateSubSessionL() has caused a Leave, so there is |
|
295 // no sub session object to clear up - just complete the |
|
296 // message with an error |
|
297 aMessage.Complete(aError); |
|
298 } |
|
299 break; |
|
300 case ESecureSubSessionBaseClose: |
|
301 // Panic? Non-leaving function that just left? |
|
302 break; |
|
303 default: |
|
304 // DisplatchMessageL above has left - this could be becuase ServiceMessageL left or the subsession DisplatchL |
|
305 // NB the test is intened to ignore a function enum of ELastSessionMessageId - this is not a valid command |
|
306 if(aMessage.Function()<ELastSessionMessageId) |
|
307 { |
|
308 // the message is for the session |
|
309 ServiceMessageError(aMessage, aError); // implmented in the DERIVED CSessionBase class. |
|
310 } |
|
311 else if(aMessage.Function()>ELastSessionMessageId) |
|
312 { |
|
313 // MUST be a message for the subsystem object - delegate |
|
314 subSession = static_cast<CSubSessionBase*>(iObjectIx->At(aMessage.Int3())); |
|
315 subSession->Impl()->DispatchError(aMessage, aError); |
|
316 } |
|
317 break; |
|
318 } |
|
319 } |