|
1 // Copyright (c) 2004-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 "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // Remote Control session implementation. |
|
15 // |
|
16 // |
|
17 |
|
18 /** |
|
19 @file |
|
20 @internalComponent |
|
21 */ |
|
22 #include "e32base.h" |
|
23 |
|
24 #include <bluetooth/logger.h> |
|
25 #include <remcon/remconbearerinterface.h> |
|
26 #include <remcon/remconifdetails.h> |
|
27 #include <s32mem.h> |
|
28 #include "utils.h" |
|
29 #include "server.h" |
|
30 #include "bearermanager.h" |
|
31 #include "remconmessage.h" |
|
32 #include "connections.h" |
|
33 #include "activehelper.h" |
|
34 #include "session.h" |
|
35 #include "messagequeue.h" |
|
36 #include "remconserver.h" |
|
37 |
|
38 #ifdef __FLOG_ACTIVE |
|
39 _LIT8(KLogComponent, LOG_COMPONENT_REMCON_SERVER); |
|
40 #endif |
|
41 |
|
42 #ifdef _DEBUG |
|
43 PANICCATEGORY("session"); |
|
44 #endif |
|
45 |
|
46 CRemConSession* CRemConSession::NewL(CRemConServer& aServer, |
|
47 CBearerManager& aBearerManager, |
|
48 const RMessage2& aMessage, |
|
49 TUint aId) |
|
50 { |
|
51 LOG_STATIC_FUNC |
|
52 CRemConSession* self = new(ELeave) CRemConSession(aServer, aBearerManager, aId); |
|
53 CleanupStack::PushL(self); |
|
54 self->ConstructL(aMessage); |
|
55 CLEANUPSTACK_POP1(self); |
|
56 return self; |
|
57 } |
|
58 |
|
59 CRemConSession::CRemConSession(CRemConServer& aServer, |
|
60 CBearerManager& aBearerManager, |
|
61 TUint aId) |
|
62 : iServer(aServer), |
|
63 iBearerManager(aBearerManager), |
|
64 iId(aId) |
|
65 { |
|
66 LOG_FUNC |
|
67 } |
|
68 |
|
69 void CRemConSession::ConstructL(const RMessage2& aMessage) |
|
70 { |
|
71 LOG_FUNC; |
|
72 |
|
73 // Get the client's process ID. |
|
74 RThread thread; |
|
75 LEAVEIFERRORL(aMessage.Client(thread)); |
|
76 CleanupClosePushL(thread); |
|
77 RProcess process; |
|
78 LEAVEIFERRORL(thread.Process(process)); |
|
79 iClientInfo.ProcessId() = process.Id(); |
|
80 process.Close(); |
|
81 iClientInfo.SecureId() = thread.SecureId(); |
|
82 CleanupStack::PopAndDestroy(&thread); |
|
83 |
|
84 iSendQueue = CMessageQueue::NewL(); |
|
85 |
|
86 TCallBack cb(SendNextCb, this); |
|
87 |
|
88 iSendNextCallBack = new(ELeave) CAsyncCallBack(cb, CActive::EPriorityStandard); |
|
89 |
|
90 // Tell the server about us. |
|
91 LEAVEIFERRORL(iServer.ClientOpened(*this)); |
|
92 |
|
93 // Set our pointer into the connection history at the current/'Last' item. |
|
94 iServer.SetConnectionHistoryPointer(Id()); |
|
95 |
|
96 iPendingMsgProcessor = new (ELeave) CActiveHelper(*this); |
|
97 } |
|
98 |
|
99 CRemConSession::~CRemConSession() |
|
100 { |
|
101 LOG(KNullDesC8); |
|
102 LOG_FUNC; |
|
103 |
|
104 delete iPendingMsgProcessor; |
|
105 delete iSendNextCallBack; |
|
106 delete iSendQueue; |
|
107 // we will need to tell the server which bearer this used to be connected to |
|
108 // this enables the server to not inform a bearer that is already connected |
|
109 // that its been connected |
|
110 // Tell the server we've gone away- it may start its shutdown timer. |
|
111 iServer.ClientClosed(*this, iRemoteAddress.BearerUid()); |
|
112 delete iInterestedAPIs; |
|
113 iPlayerName.Close(); |
|
114 } |
|
115 |
|
116 void CRemConSession::ServiceL(const RMessage2& aMessage) |
|
117 { |
|
118 LOG(KNullDesC8); |
|
119 LOG_FUNC; |
|
120 LOG1(_L("\taMessage.Function() = %d"), aMessage.Function()); |
|
121 |
|
122 // Switch on the IPC number and call a 'message handler'. Message handlers |
|
123 // complete aMessage (either with Complete or Panic), or make a note of |
|
124 // the message for later asynchronous completion. |
|
125 // Message handlers should not leave- the server does not have an Error |
|
126 // function. |
|
127 |
|
128 switch ( aMessage.Function() ) |
|
129 { |
|
130 // Heap failure testing APIs. |
|
131 case ERemConDbgMarkHeap: |
|
132 #ifdef _DEBUG |
|
133 LOG(_L("\tmark heap")); |
|
134 __UHEAP_MARK; |
|
135 #endif // _DEBUG |
|
136 CompleteClient(aMessage, KErrNone); |
|
137 break; |
|
138 |
|
139 case ERemConDbgCheckHeap: |
|
140 #ifdef _DEBUG |
|
141 LOG1(_L("\tcheck heap (expecting %d cells)"), aMessage.Int0()); |
|
142 __UHEAP_CHECK(aMessage.Int0()); |
|
143 #endif // _DEBUG |
|
144 CompleteClient(aMessage, KErrNone); |
|
145 break; |
|
146 |
|
147 case ERemConDbgMarkEnd: |
|
148 #ifdef _DEBUG |
|
149 LOG1(_L("\tmark end (expecting %d cells)"), aMessage.Int0()); |
|
150 __UHEAP_MARKENDC(aMessage.Int0()); |
|
151 #endif // _DEBUG |
|
152 CompleteClient(aMessage, KErrNone); |
|
153 break; |
|
154 |
|
155 case ERemConDbgFailNext: |
|
156 #ifdef _DEBUG |
|
157 { |
|
158 LOG1(_L("\tfail next (simulating failure after %d allocation(s))"), aMessage.Int0()); |
|
159 if ( aMessage.Int0() == 0 ) |
|
160 { |
|
161 __UHEAP_RESET; |
|
162 } |
|
163 else |
|
164 { |
|
165 __UHEAP_FAILNEXT(aMessage.Int0()); |
|
166 } |
|
167 } |
|
168 #endif // _DEBUG |
|
169 CompleteClient(aMessage, KErrNone); |
|
170 break; |
|
171 |
|
172 case ERemConSetClientType: |
|
173 SetClientType(aMessage); |
|
174 // This is a sync API- check that the message has been completed. |
|
175 // (NB We don't check the converse for async APIs because the message |
|
176 // may have been panicked synchronously.) |
|
177 ASSERT_DEBUG(aMessage.IsNull()); |
|
178 break; |
|
179 |
|
180 case ERemConGoConnectionOriented: |
|
181 GoConnectionOriented(aMessage); |
|
182 ASSERT_DEBUG(aMessage.IsNull()); |
|
183 break; |
|
184 |
|
185 case ERemConGoConnectionless: |
|
186 GoConnectionless(aMessage); |
|
187 ASSERT_DEBUG(aMessage.IsNull()); |
|
188 break; |
|
189 |
|
190 case ERemConConnectBearer: |
|
191 ConnectBearer(aMessage); |
|
192 break; |
|
193 |
|
194 case ERemConConnectBearerCancel: |
|
195 ConnectBearerCancel(aMessage); |
|
196 ASSERT_DEBUG(aMessage.IsNull()); |
|
197 break; |
|
198 |
|
199 case ERemConDisconnectBearer: |
|
200 DisconnectBearer(aMessage); |
|
201 break; |
|
202 |
|
203 case ERemConDisconnectBearerCancel: |
|
204 DisconnectBearerCancel(aMessage); |
|
205 ASSERT_DEBUG(aMessage.IsNull()); |
|
206 break; |
|
207 |
|
208 case ERemConSend: |
|
209 Send(aMessage); |
|
210 break; |
|
211 |
|
212 case ERemConSendNotify: |
|
213 SendNotify(aMessage); |
|
214 break; |
|
215 |
|
216 case ERemConSendUnreliable: |
|
217 SendUnreliable(aMessage); |
|
218 break; |
|
219 |
|
220 case ERemConSendCancel: |
|
221 SendCancel(aMessage); |
|
222 ASSERT_DEBUG(aMessage.IsNull()); |
|
223 break; |
|
224 |
|
225 case ERemConReceive: |
|
226 Receive(aMessage); |
|
227 break; |
|
228 |
|
229 case ERemConReceiveCancel: |
|
230 ReceiveCancel(aMessage); |
|
231 ASSERT_DEBUG(aMessage.IsNull()); |
|
232 break; |
|
233 |
|
234 case ERemConGetConnectionCount: |
|
235 GetConnectionCount(aMessage); |
|
236 ASSERT_DEBUG(aMessage.IsNull()); |
|
237 break; |
|
238 |
|
239 case ERemConGetConnections: |
|
240 GetConnections(aMessage); |
|
241 ASSERT_DEBUG(aMessage.IsNull()); |
|
242 break; |
|
243 |
|
244 case ERemConNotifyConnectionsChange: |
|
245 NotifyConnectionsChange(aMessage); |
|
246 break; |
|
247 |
|
248 case ERemConNotifyConnectionsChangeCancel: |
|
249 NotifyConnectionsChangeCancel(aMessage); |
|
250 ASSERT_DEBUG(aMessage.IsNull()); |
|
251 break; |
|
252 |
|
253 case ERemConRegisterInterestedAPIs: |
|
254 RegisterInterestedAPIs(aMessage); |
|
255 ASSERT_DEBUG(aMessage.IsNull()); |
|
256 break; |
|
257 |
|
258 default: |
|
259 // Unknown message |
|
260 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicIllegalIpc); |
|
261 break; |
|
262 } |
|
263 } |
|
264 |
|
265 void CRemConSession::CompleteClient(const RMessage2& aMessage, TInt aError) |
|
266 { |
|
267 LOG1(_L("\tcompleting client message with %d"), aError); |
|
268 TBool cleanClientInfoMessage = (iClientInfo.Message().Handle() == aMessage.Handle()); |
|
269 aMessage.Complete(aError); |
|
270 if(cleanClientInfoMessage) |
|
271 { |
|
272 iClientInfo.Message() = RMessage2(); |
|
273 } |
|
274 } |
|
275 |
|
276 void CRemConSession::SetClientType(const RMessage2& aMessage) |
|
277 { |
|
278 LOG_FUNC; |
|
279 |
|
280 if ( iType != ERemConClientTypeUndefined ) |
|
281 { |
|
282 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicClientTypeAlreadySet); |
|
283 return; |
|
284 } |
|
285 |
|
286 const TRemConClientType type = static_cast<TRemConClientType>(aMessage.Int0()); |
|
287 LOG1(_L("\trequested (TRemConClientType) type = %d"), type); |
|
288 |
|
289 TInt err = aMessage.GetDesLength(1); |
|
290 if(err >= 0) |
|
291 { |
|
292 TRAP(err, DoSetClientTypeL(aMessage)); |
|
293 if(err == KErrBadDescriptor) |
|
294 { |
|
295 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBadDescriptor); |
|
296 return; |
|
297 } |
|
298 } |
|
299 else if(err == KErrBadDescriptor) |
|
300 { |
|
301 // The additional parameters are optional (i.e. old or controller clients won't provide them). |
|
302 err = KErrNone; |
|
303 } |
|
304 |
|
305 if(err != KErrNone) |
|
306 { |
|
307 CompleteClient(aMessage, err); |
|
308 } |
|
309 else |
|
310 { |
|
311 switch ( type ) |
|
312 { |
|
313 case ERemConClientTypeController: |
|
314 iType = type; |
|
315 CompleteClient(aMessage, KErrNone); |
|
316 break; |
|
317 |
|
318 case ERemConClientTypeTarget: |
|
319 // Check that there aren't already any target clients with the |
|
320 // same process ID. |
|
321 if ( !iServer.TargetClientWithSameProcessId(iClientInfo.ProcessId()) ) |
|
322 { |
|
323 iType = type; |
|
324 CompleteClient(aMessage, KErrNone); |
|
325 } |
|
326 else |
|
327 { |
|
328 CompleteClient(aMessage, KErrInUse); |
|
329 } |
|
330 break; |
|
331 |
|
332 default: |
|
333 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBadType); |
|
334 break; |
|
335 } |
|
336 } |
|
337 |
|
338 if ( iType != ERemConClientTypeUndefined ) |
|
339 { |
|
340 // The type got set, so tell the server, so it can tell the bearers if |
|
341 // necessary. |
|
342 iServer.ClientTypeSet(*this); |
|
343 } |
|
344 } |
|
345 |
|
346 void CRemConSession::DoSetClientTypeL(const RMessage2& aMessage) |
|
347 { |
|
348 // Retrieve the client type information |
|
349 RBuf8 typeBuf; |
|
350 typeBuf.CreateL(sizeof(TPlayerTypeInformation)); |
|
351 CleanupClosePushL(typeBuf); |
|
352 aMessage.ReadL(1, typeBuf); |
|
353 |
|
354 const TPlayerTypeInformation* Ptr = reinterpret_cast<const TPlayerTypeInformation*> (typeBuf.Ptr()); |
|
355 iPlayerType.iPlayerType = (*Ptr).iPlayerType; |
|
356 iPlayerType.iPlayerSubType = (*Ptr).iPlayerSubType; |
|
357 // Retrieve the client player name inforamtion |
|
358 iPlayerName.CreateL(aMessage.Int2()); |
|
359 CleanupClosePushL(iPlayerName); |
|
360 aMessage.ReadL(3, iPlayerName); |
|
361 CleanupStack::Pop(&iPlayerName); |
|
362 |
|
363 CleanupStack::PopAndDestroy(&typeBuf); |
|
364 } |
|
365 void CRemConSession::GoConnectionOriented(const RMessage2& aMessage) |
|
366 { |
|
367 LOG_FUNC; |
|
368 |
|
369 // Check we've had our type set... |
|
370 if ( iType != ERemConClientTypeController ) |
|
371 { |
|
372 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBadType); |
|
373 return; |
|
374 } |
|
375 |
|
376 if ( !iRemoteAddress.IsNull() ) |
|
377 { |
|
378 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicAlreadyConnectionOriented); |
|
379 return; |
|
380 } |
|
381 |
|
382 if ( iConnectBearerMsg.Handle() || iDisconnectBearerMsg.Handle() || iSendMsg.Handle()) |
|
383 { |
|
384 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBearerControlOutstanding); |
|
385 return; |
|
386 } |
|
387 if (iSending != ENotSending) |
|
388 { |
|
389 DoSendCancel(); |
|
390 } |
|
391 EmptySendQueue(); |
|
392 |
|
393 // Get the desired address from the message and check it. |
|
394 const TUid uid = TUid::Uid(aMessage.Int0()); |
|
395 LOG1(_L("\tuid = 0x%08x"), uid); |
|
396 // Check the requested bearer exists. |
|
397 TBool bearerExists = iBearerManager.BearerExists(uid); |
|
398 if ( !bearerExists) |
|
399 { |
|
400 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBearerPluginIncorrectInterface); |
|
401 return; |
|
402 } |
|
403 // Check the bearer-specific part of the address. |
|
404 TBuf8<TRemConAddress::KMaxAddrSize> buf; |
|
405 TInt err = aMessage.Read(1, buf); |
|
406 if ( err != KErrNone ) |
|
407 { |
|
408 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBadDescriptor); |
|
409 return; |
|
410 } |
|
411 |
|
412 // Do security check- if this client won't be allowed to use the bearer |
|
413 // then fail the request. |
|
414 // NB This security check (repeated in debug at ConnectBearer and |
|
415 // DisconnectBearer time) is all that stands between a connection-oriented |
|
416 // client and the bearer, and is all the caps checking that RemCon does! |
|
417 err = KErrPermissionDenied; |
|
418 if ( iBearerManager.CheckPolicy(uid, aMessage) ) |
|
419 { |
|
420 err = KErrNone; |
|
421 } |
|
422 |
|
423 |
|
424 // if alls well and we're connection oriented then set up as such |
|
425 if (KErrNone == err) |
|
426 { |
|
427 // The client has passed all our checks- set our data member. |
|
428 iRemoteAddress.BearerUid() = uid; |
|
429 iRemoteAddress.Addr() = buf; |
|
430 // tell the server |
|
431 iServer.ClientGoConnectionOriented(*this,uid); |
|
432 } |
|
433 |
|
434 CompleteClient(aMessage, err); |
|
435 } |
|
436 |
|
437 void CRemConSession::GoConnectionless(const RMessage2& aMessage) |
|
438 { |
|
439 LOG_FUNC; |
|
440 |
|
441 // Check we've had our type set... |
|
442 if ( iType != ERemConClientTypeController ) |
|
443 { |
|
444 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBadType); |
|
445 return; |
|
446 } |
|
447 |
|
448 if ( iRemoteAddress.IsNull() ) |
|
449 { |
|
450 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicNotConnectionOriented); |
|
451 return; |
|
452 } |
|
453 |
|
454 if ( iConnectBearerMsg.Handle() || iDisconnectBearerMsg.Handle() || iSendMsg.Handle()) |
|
455 { |
|
456 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBearerControlOutstanding); |
|
457 return; |
|
458 } |
|
459 |
|
460 if (iSending != ENotSending) |
|
461 { |
|
462 DoSendCancel(); |
|
463 } |
|
464 EmptySendQueue(); |
|
465 |
|
466 // we will need to tell the server which bearer this used to be connected to |
|
467 // this enables the server to not inform a bearer that is already connected |
|
468 // that its been connected |
|
469 TUid oldUid = iRemoteAddress.BearerUid(); |
|
470 |
|
471 iRemoteAddress.BearerUid() = KNullUid; |
|
472 |
|
473 // tell the server |
|
474 iServer.ClientGoConnectionless(*this, oldUid); |
|
475 |
|
476 CompleteClient(aMessage, KErrNone); |
|
477 } |
|
478 |
|
479 void CRemConSession::ConnectBearer(const RMessage2& aMessage) |
|
480 { |
|
481 LOG_FUNC; |
|
482 |
|
483 if ( iType != ERemConClientTypeController ) |
|
484 { |
|
485 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBadType); |
|
486 return; |
|
487 } |
|
488 |
|
489 if ( iConnectBearerMsg.Handle() || iDisconnectBearerMsg.Handle() ) |
|
490 { |
|
491 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBearerControlOutstanding); |
|
492 return; |
|
493 } |
|
494 |
|
495 if ( iRemoteAddress.IsNull() ) |
|
496 { |
|
497 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicNotConnectionOriented); |
|
498 return; |
|
499 } |
|
500 |
|
501 // Check the requested bearer exists. |
|
502 TBool bearerExists = iBearerManager.BearerExists(iRemoteAddress.BearerUid()); |
|
503 // This check was done at GoConnectionOriented time. |
|
504 ASSERT_DEBUG(bearerExists); |
|
505 // So was this one. |
|
506 ASSERT_DEBUG(iBearerManager.CheckPolicy(iRemoteAddress.BearerUid(), aMessage)); |
|
507 |
|
508 // Check the state of our given connection at the bearer level. If it is: |
|
509 // -) disconnected request the connection to come up, |
|
510 // -) connecting or disconnecting, add message to the queue of pending |
|
511 // messages, and process it once connecting/disconnecting has been completed |
|
512 // -) connected, complete the client's message, |
|
513 |
|
514 TConnectionState conState; |
|
515 conState = iServer.ConnectionState(iRemoteAddress); |
|
516 |
|
517 if ( conState == EDisconnected ) |
|
518 { |
|
519 // The bearer may indicate connection synchronously, so set this |
|
520 // message _before_ we ask them |
|
521 iConnectBearerMsg = aMessage; |
|
522 TInt err = iBearerManager.Connect(iRemoteAddress); |
|
523 if ( err != KErrNone ) |
|
524 { |
|
525 CompleteClient(iConnectBearerMsg, err); |
|
526 } |
|
527 } |
|
528 else if ( conState == EDisconnecting || conState == EConnecting ) |
|
529 { |
|
530 if ( iPendingMsg.Handle() ) |
|
531 { |
|
532 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBearerControlOutstanding); |
|
533 return; |
|
534 } |
|
535 // Store the message, it will get processed later. |
|
536 iPendingMsg = aMessage; |
|
537 } |
|
538 else // EConnected |
|
539 { |
|
540 CompleteClient(aMessage, KErrNone); |
|
541 } |
|
542 |
|
543 } |
|
544 |
|
545 void CRemConSession::ConnectBearerCancel(const RMessage2& aMessage) |
|
546 { |
|
547 LOG_FUNC; |
|
548 |
|
549 // Check we've had our type set... |
|
550 if ( iType != ERemConClientTypeController ) |
|
551 { |
|
552 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBadType); |
|
553 return; |
|
554 } |
|
555 |
|
556 if ( iConnectBearerMsg.Handle() ) |
|
557 { |
|
558 CompleteClient(iConnectBearerMsg, KErrCancel); |
|
559 } |
|
560 else if ( iPendingMsg.Handle() && ( iPendingMsg.Function() == ERemConConnectBearer )) |
|
561 { |
|
562 CompleteClient(iPendingMsg, KErrCancel); |
|
563 } |
|
564 |
|
565 CompleteClient(aMessage, KErrNone); |
|
566 // At no point do we make any change to the processes going on underneath |
|
567 // us- 'Cancel' APIs are just for cancelling interest in an async |
|
568 // operation. |
|
569 } |
|
570 |
|
571 void CRemConSession::DisconnectBearer(const RMessage2& aMessage) |
|
572 { |
|
573 LOG_FUNC; |
|
574 |
|
575 if ( iType != ERemConClientTypeController ) |
|
576 { |
|
577 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBadType); |
|
578 return; |
|
579 } |
|
580 |
|
581 if ( iDisconnectBearerMsg.Handle() || iConnectBearerMsg.Handle() || iSendMsg.Handle()) |
|
582 { |
|
583 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBearerControlOutstanding); |
|
584 return; |
|
585 } |
|
586 |
|
587 if ( iRemoteAddress.IsNull() ) |
|
588 { |
|
589 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicNotConnectionOriented); |
|
590 return; |
|
591 } |
|
592 |
|
593 if (iSending != ENotSending) |
|
594 { |
|
595 DoSendCancel(); |
|
596 } |
|
597 EmptySendQueue(); |
|
598 |
|
599 // Check the requested bearer exists. |
|
600 TBool bearerExists = iBearerManager.BearerExists(iRemoteAddress.BearerUid()); |
|
601 // This check was done at GoConnectionOriented time. |
|
602 ASSERT_DEBUG(bearerExists); |
|
603 // So was this one. |
|
604 ASSERT_DEBUG(iBearerManager.CheckPolicy(iRemoteAddress.BearerUid(), aMessage)); |
|
605 |
|
606 // Check the state of the given connection. If it is: |
|
607 // -) connected, request connection to go away, |
|
608 // -) disconnected, compete the client's message, |
|
609 // -) connecting or disconnecting, add message to the queue of pending |
|
610 // messages, and process it once connecting/disconnecting has been completed |
|
611 |
|
612 TInt err; |
|
613 TConnectionState conState; |
|
614 conState = iServer.ConnectionState(iRemoteAddress); |
|
615 |
|
616 if ( conState == EConnected ) |
|
617 { |
|
618 // The bearer may indicate disconnection synchronously, so set this |
|
619 // message _before_ we ask them |
|
620 iDisconnectBearerMsg = aMessage; |
|
621 err = iBearerManager.Disconnect(iRemoteAddress); |
|
622 if ( err != KErrNone ) |
|
623 { |
|
624 CompleteClient(iDisconnectBearerMsg, err); |
|
625 } |
|
626 } |
|
627 else if ( conState == EDisconnecting || conState == EConnecting ) |
|
628 { |
|
629 if ( iPendingMsg.Handle() ) |
|
630 { |
|
631 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBearerControlOutstanding); |
|
632 return; |
|
633 } |
|
634 // Store the message, it will get processed later. |
|
635 iPendingMsg = aMessage; |
|
636 } |
|
637 else //disconnected |
|
638 { |
|
639 CompleteClient(aMessage, KErrNone); |
|
640 } |
|
641 } |
|
642 |
|
643 void CRemConSession::DisconnectBearerCancel(const RMessage2& aMessage) |
|
644 { |
|
645 LOG_FUNC; |
|
646 |
|
647 // Check we've had our type set... |
|
648 if ( iType != ERemConClientTypeController ) |
|
649 { |
|
650 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBadType); |
|
651 return; |
|
652 } |
|
653 |
|
654 if ( iDisconnectBearerMsg.Handle() ) |
|
655 { |
|
656 CompleteClient(iDisconnectBearerMsg, KErrCancel); |
|
657 } |
|
658 else if ( iPendingMsg.Handle() && (iPendingMsg.Function() == ERemConDisconnectBearer )) |
|
659 { |
|
660 CompleteClient(iPendingMsg, KErrCancel); |
|
661 } |
|
662 |
|
663 CompleteClient(aMessage, KErrNone); |
|
664 } |
|
665 |
|
666 void CRemConSession::Send(const RMessage2& aMessage) |
|
667 { |
|
668 LOG_FUNC; |
|
669 |
|
670 // Check we're not already sending... |
|
671 if ( iSendMsg.Handle()) |
|
672 { |
|
673 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicSendAlreadyOutstanding); |
|
674 return; |
|
675 } |
|
676 |
|
677 iSendMsg = aMessage; |
|
678 |
|
679 // Check we've had our type set... |
|
680 if ( Type() != ERemConClientTypeController |
|
681 && Type() != ERemConClientTypeTarget |
|
682 ) |
|
683 { |
|
684 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicClientTypeNotSet); |
|
685 return; |
|
686 } |
|
687 |
|
688 // Check we don't have a disconnect outstanding- this makes no sense from |
|
689 // a client viewpoint (they should cancel the disconnect first). |
|
690 // [The client is allowed to have a connect request outstanding- the |
|
691 // bearer manager makes sure a bearer-level connect is not posted on the |
|
692 // same address twice.] |
|
693 if ( iDisconnectBearerMsg.Handle() ) |
|
694 { |
|
695 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBearerControlOutstanding); |
|
696 return; |
|
697 } |
|
698 |
|
699 TRAPD(err, DoSendL(aMessage)); |
|
700 if ( err != KErrNone ) |
|
701 { |
|
702 CompleteClient(aMessage, err); |
|
703 } |
|
704 } |
|
705 |
|
706 /** |
|
707 Sends a notify message to the remote device. |
|
708 |
|
709 This function is intended for the RemCon controller client to send a notify |
|
710 command to the remote device. |
|
711 */ |
|
712 void CRemConSession::SendNotify(const RMessage2& aMessage) |
|
713 { |
|
714 LOG_FUNC; |
|
715 |
|
716 // Check we're not already sending... |
|
717 if ( iSendMsg.Handle()) |
|
718 { |
|
719 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicSendAlreadyOutstanding); |
|
720 return; |
|
721 } |
|
722 |
|
723 iSendMsg = aMessage; |
|
724 |
|
725 // Check we've had our type set... |
|
726 if (Type() != ERemConClientTypeController) |
|
727 { |
|
728 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicClientTypeNotSet); |
|
729 return; |
|
730 } |
|
731 |
|
732 // Check we don't have a disconnect outstanding- this makes no sense from |
|
733 // a client viewpoint (they should cancel the disconnect first). |
|
734 // [The client is allowed to have a connect request outstanding- the |
|
735 // bearer manager makes sure a bearer-level connect is not posted on the |
|
736 // same address twice.] |
|
737 if ( iDisconnectBearerMsg.Handle() ) |
|
738 { |
|
739 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBearerControlOutstanding); |
|
740 return; |
|
741 } |
|
742 |
|
743 TRAPD(err, DoSendNotifyL(aMessage)); |
|
744 if ( err != KErrNone ) |
|
745 { |
|
746 CompleteClient(aMessage, err); |
|
747 } |
|
748 } |
|
749 |
|
750 void CRemConSession::DoSendL(const RMessage2& aMessage) |
|
751 { |
|
752 LOG_FUNC; |
|
753 |
|
754 // Get the data the client wants to send. |
|
755 const TUid interfaceUid = TUid::Uid(aMessage.Int0()); |
|
756 LOG1(_L("\tinterfaceUid = 0x%08x"), interfaceUid); |
|
757 |
|
758 if (aMessage.GetDesLengthL(1) != sizeof(TOperationInformation)) |
|
759 { |
|
760 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBadDescriptor); |
|
761 return; |
|
762 } |
|
763 |
|
764 TPckgBuf<TOperationInformation> opInfoPckg; |
|
765 |
|
766 TInt err= aMessage.Read( |
|
767 1, // location of the descriptor in the client's message (as we expect them to have set it up) |
|
768 opInfoPckg, // descriptor to write to from client memory space |
|
769 0 // offset into our descriptor to put the client's data |
|
770 ); |
|
771 |
|
772 if ( err != KErrNone ) |
|
773 { |
|
774 LOG1(_L("\taMessage.Read = %d"), err); |
|
775 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBadDescriptor); |
|
776 return; |
|
777 } |
|
778 |
|
779 const TUint operationId = opInfoPckg().iOperationId; |
|
780 LOG1(_L("\toperationId = 0x%02x"), operationId); |
|
781 |
|
782 const TRemConMessageSubType messageSubType = opInfoPckg().iMessageSubType; |
|
783 LOG1(_L("\tmessageSubType = 0x%02x"), messageSubType); |
|
784 |
|
785 |
|
786 const TUint dataLength = (TUint)aMessage.GetDesLengthL(3); |
|
787 LOG1(_L("\tdataLength = %d"), dataLength); |
|
788 |
|
789 // If the client wanted to send some operation-associated data, read it |
|
790 // from them. |
|
791 RBuf8 sendDes; |
|
792 if ( dataLength != 0 ) |
|
793 { |
|
794 sendDes.CreateL(dataLength); |
|
795 TInt err = aMessage.Read( |
|
796 3, // location of the descriptor in the client's message (as we expect them to have set it up) |
|
797 sendDes, // descriptor to write to from client memory space |
|
798 0 // offset into our descriptor to put the client's data |
|
799 ); |
|
800 // NB We don't do LEAVEIFERRORL(aMessage.Read) because a bad client |
|
801 // descriptor is a panicking offence for them, not an 'error the |
|
802 // request' offence. |
|
803 if ( err != KErrNone ) |
|
804 { |
|
805 LOG1(_L("\taMessage.Read = %d"), err); |
|
806 sendDes.Close(); |
|
807 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBadDescriptor); |
|
808 return; |
|
809 } |
|
810 } |
|
811 CleanupClosePushL(sendDes); |
|
812 |
|
813 // Before we ask the server to send, we must set our ClientInfo |
|
814 // correctly so the TSP can get information about the client. |
|
815 iClientInfo.Message() = aMessage; |
|
816 |
|
817 CRemConMessage* msg = NULL; |
|
818 |
|
819 // Examine the session type. |
|
820 switch ( iType ) |
|
821 { |
|
822 case ERemConClientTypeTarget: |
|
823 { |
|
824 LOG(_L("\tTARGET send")); |
|
825 |
|
826 msg = CRemConMessage::NewL( |
|
827 TRemConAddress(), // we don't know which remotes it's going to yet |
|
828 ERemConResponse, // targets can only send responses |
|
829 messageSubType, |
|
830 interfaceUid, |
|
831 operationId, |
|
832 sendDes, // msg takes ownership |
|
833 Id(), // session id to match this response against the originating command |
|
834 0, // transaction id not yet known |
|
835 ETrue); |
|
836 CLEANUPSTACK_POP1(&sendDes); // now owned by msg |
|
837 |
|
838 } |
|
839 break; |
|
840 |
|
841 case ERemConClientTypeController: |
|
842 { |
|
843 LOG(_L("\tCONTROLLER send")); |
|
844 if ( (messageSubType == ERemConNotifyCommandAwaitingInterim) |
|
845 || (messageSubType == ERemConNotifyCommandAwaitingChanged) |
|
846 ) |
|
847 { |
|
848 LOG(_L("\terror, not allowed to use Send() to send notify command")); |
|
849 CleanupStack::PopAndDestroy(&sendDes); |
|
850 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicIllegalIpc); |
|
851 return; |
|
852 } |
|
853 else |
|
854 { |
|
855 msg = CRemConMessage::NewL( |
|
856 iRemoteAddress, // either specified (if we're connection-oriented) or null (we're connectionless- this field will be filled in by the TSP) |
|
857 ERemConCommand, |
|
858 messageSubType, |
|
859 interfaceUid, |
|
860 operationId, |
|
861 sendDes, // msg takes ownership |
|
862 Id(), // session id for when the response comes back |
|
863 0, // we let the bearer manager invent a new transaction id when the message gets to it |
|
864 ETrue); |
|
865 } |
|
866 CLEANUPSTACK_POP1(&sendDes); // now owned by msg |
|
867 |
|
868 } |
|
869 break; |
|
870 |
|
871 default: |
|
872 DEBUG_PANIC_LINENUM; |
|
873 break; |
|
874 } |
|
875 |
|
876 ASSERT_DEBUG(iSendQueue); |
|
877 // We know msg is valid at this stage as the code would leave or panic earlier if msg was |
|
878 // not set. |
|
879 ASSERT_DEBUG(msg); |
|
880 |
|
881 if (iSending != ENotSending || !iSendQueue->IsEmpty()) |
|
882 { |
|
883 iSendQueue->Append(*msg); |
|
884 } |
|
885 else |
|
886 { |
|
887 // we know msg cannot be null here as said above. |
|
888 SendToServer(*msg); |
|
889 } |
|
890 } |
|
891 |
|
892 /** |
|
893 @see CRemConSession::SendNotify |
|
894 */ |
|
895 void CRemConSession::DoSendNotifyL(const RMessage2& aMessage) |
|
896 { |
|
897 LOG_FUNC; |
|
898 |
|
899 // Get the data the client wants to send. |
|
900 const TUid interfaceUid = TUid::Uid(aMessage.Int0()); |
|
901 LOG1(_L("\tinterfaceUid = 0x%08x"), interfaceUid); |
|
902 |
|
903 if (aMessage.GetDesLengthL(1) != sizeof(TOperationInformation)) |
|
904 { |
|
905 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBadDescriptor); |
|
906 return; |
|
907 } |
|
908 |
|
909 TPckgBuf<TOperationInformation> opInfoPckg; |
|
910 TInt err= aMessage.Read( |
|
911 1, // location of the descriptor in the client's message (as we expect them to have set it up) |
|
912 opInfoPckg, // descriptor to write to from client memory space |
|
913 0 // offset into our descriptor to put the client's data |
|
914 ); |
|
915 |
|
916 if ( err != KErrNone ) |
|
917 { |
|
918 LOG1(_L("\taMessage.Read = %d"), err); |
|
919 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBadDescriptor); |
|
920 return; |
|
921 } |
|
922 |
|
923 const TUint operationId = opInfoPckg().iOperationId; |
|
924 LOG1(_L("\toperationId = 0x%02x"), operationId); |
|
925 |
|
926 const TRemConMessageSubType messageSubType = opInfoPckg().iMessageSubType; |
|
927 LOG1(_L("\tmessageSubType = 0x%02x"), messageSubType); |
|
928 |
|
929 const TUint dataLength = (TUint)aMessage.GetDesLengthL(2); |
|
930 LOG1(_L("\tdataLength = %d"), dataLength); |
|
931 |
|
932 // If the client wanted to send some operation-associated data, read it |
|
933 // from them. |
|
934 RBuf8 sendDes; |
|
935 if ( dataLength != 0 ) |
|
936 { |
|
937 sendDes.CreateL(dataLength); |
|
938 TInt err = aMessage.Read( |
|
939 2, // location of the descriptor in the client's message (as we expect them to have set it up) |
|
940 sendDes, // descriptor to write to from client memory space |
|
941 0 // offset into our descriptor to put the client's data |
|
942 ); |
|
943 // NB We don't do LEAVEIFERRORL(aMessage.Read) because a bad client |
|
944 // descriptor is a panicking offence for them, not an 'error the |
|
945 // request' offence. |
|
946 if ( err != KErrNone ) |
|
947 { |
|
948 LOG1(_L("\taMessage.Read = %d"), err); |
|
949 sendDes.Close(); |
|
950 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBadDescriptor); |
|
951 return; |
|
952 } |
|
953 } |
|
954 |
|
955 // Before we ask the server to send, we must set our ClientInfo |
|
956 // correctly so the TSP can get information about the client. |
|
957 iClientInfo.Message() = aMessage; |
|
958 |
|
959 CRemConMessage* msg = NULL; |
|
960 |
|
961 if (messageSubType != ERemConNotifyCommandAwaitingInterim) |
|
962 { |
|
963 sendDes.Close(); |
|
964 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicIllegalIpc); |
|
965 return; |
|
966 } |
|
967 |
|
968 CleanupClosePushL(sendDes); |
|
969 msg = CRemConMessage::NewL( |
|
970 iRemoteAddress, // either specified (if we're connection-oriented) or null (we're connectionless- this field will be filled in by the TSP) |
|
971 ERemConNotifyCommand, |
|
972 messageSubType, |
|
973 interfaceUid, |
|
974 operationId, |
|
975 sendDes, // msg takes ownership |
|
976 Id(), // session id for when the response comes back |
|
977 0, // we let the bearer manager invent a new transaction id when the message gets to it |
|
978 ETrue); |
|
979 CLEANUPSTACK_POP1(&sendDes); // now owned by msg |
|
980 |
|
981 LOG(_L("\tCONTROLLER send")); |
|
982 ASSERT_DEBUG(iSendQueue); |
|
983 if (iSending != ENotSending || !iSendQueue->IsEmpty()) |
|
984 { |
|
985 iSendQueue->Append(*msg); |
|
986 } |
|
987 else |
|
988 { |
|
989 SendToServer(*msg); |
|
990 } |
|
991 } |
|
992 |
|
993 void CRemConSession::SendUnreliable(const RMessage2& aMessage) |
|
994 { |
|
995 LOG_FUNC; |
|
996 |
|
997 // Check we've had our type set... |
|
998 if ( Type() != ERemConClientTypeController |
|
999 && Type() != ERemConClientTypeTarget |
|
1000 ) |
|
1001 { |
|
1002 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicClientTypeNotSet); |
|
1003 return; |
|
1004 } |
|
1005 |
|
1006 // Check we don't have a disconnect outstanding- this makes no sense from |
|
1007 // a client viewpoint (they should cancel the disconnect first). |
|
1008 // [The client is allowed to have a connect request outstanding- the |
|
1009 // bearer manager makes sure a bearer-level connect is not posted on the |
|
1010 // same address twice.] |
|
1011 if ( iDisconnectBearerMsg.Handle() ) |
|
1012 { |
|
1013 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBearerControlOutstanding); |
|
1014 return; |
|
1015 } |
|
1016 |
|
1017 CRemConMessage* msg = NULL; |
|
1018 TRAPD(err, msg = DoCreateUnreliableMessageL(aMessage)); |
|
1019 CompleteClient(aMessage, err); |
|
1020 if (err == KErrNone) |
|
1021 { |
|
1022 ASSERT_DEBUG(iSendQueue); |
|
1023 if (iSending || !iSendQueue->IsEmpty()) |
|
1024 { |
|
1025 iSendQueue->Append(*msg); |
|
1026 } |
|
1027 else |
|
1028 { |
|
1029 SendToServer(*msg); |
|
1030 } |
|
1031 } |
|
1032 } |
|
1033 |
|
1034 CRemConMessage* CRemConSession::DoCreateUnreliableMessageL(const RMessage2& aMessage) |
|
1035 { |
|
1036 LOG_FUNC; |
|
1037 |
|
1038 // Get the data the client wants to send. |
|
1039 const TUid interfaceUid = TUid::Uid(aMessage.Int0()); |
|
1040 LOG1(_L("\tinterfaceUid = 0x%08x"), interfaceUid); |
|
1041 |
|
1042 if (aMessage.GetDesLengthL(1) != sizeof(TOperationInformation)) |
|
1043 { |
|
1044 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBadDescriptor); |
|
1045 LEAVEL(KErrBadDescriptor); |
|
1046 } |
|
1047 |
|
1048 TPckgBuf<TOperationInformation> opInfoPckg; |
|
1049 |
|
1050 TInt err= aMessage.Read( |
|
1051 1, // location of the descriptor in the client's message (as we expect them to have set it up) |
|
1052 opInfoPckg, // descriptor to write to from client memory space |
|
1053 0 // offset into our descriptor to put the client's data |
|
1054 ); |
|
1055 |
|
1056 if ( err != KErrNone ) |
|
1057 { |
|
1058 LOG1(_L("\taMessage.Read = %d"), err); |
|
1059 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBadDescriptor); |
|
1060 LEAVEL(KErrBadDescriptor); |
|
1061 } |
|
1062 |
|
1063 const TUint operationId = opInfoPckg().iOperationId; |
|
1064 LOG1(_L("\toperationId = 0x%02x"), operationId); |
|
1065 |
|
1066 const TRemConMessageSubType messageSubType = opInfoPckg().iMessageSubType; |
|
1067 LOG1(_L("\tmessageSubType = 0x%02x"), messageSubType); |
|
1068 |
|
1069 |
|
1070 const TUint dataLength = (TUint)aMessage.GetDesLengthL(2); |
|
1071 LOG1(_L("\tdataLength = %d"), dataLength); |
|
1072 |
|
1073 // If the client wanted to send some operation-associated data, read it |
|
1074 // from them. |
|
1075 RBuf8 sendDes; |
|
1076 if ( dataLength != 0 ) |
|
1077 { |
|
1078 sendDes.CreateL(dataLength); |
|
1079 TInt err = aMessage.Read( |
|
1080 2, // location of the descriptor in the client's message (as we expect them to have set it up) |
|
1081 sendDes, // descriptor to write to from client memory space |
|
1082 0 // offset into our descriptor to put the client's data |
|
1083 ); |
|
1084 // NB We don't do LEAVEIFERRORL(aMessage.Read) because a bad client |
|
1085 // descriptor is a panicking offence for them, not an 'error the |
|
1086 // request' offence. |
|
1087 if ( err != KErrNone ) |
|
1088 { |
|
1089 LOG1(_L("\taMessage.Read = %d"), err); |
|
1090 sendDes.Close(); |
|
1091 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBadDescriptor); |
|
1092 LEAVEL(KErrBadDescriptor); |
|
1093 } |
|
1094 } |
|
1095 CleanupClosePushL(sendDes); |
|
1096 |
|
1097 // Before we ask the server to send, we must set our ClientInfo |
|
1098 // correctly so the TSP can get information about the client. |
|
1099 iClientInfo.Message() = aMessage; |
|
1100 |
|
1101 CRemConMessage* msg = NULL; |
|
1102 |
|
1103 // Examine the session type. |
|
1104 switch ( iType ) |
|
1105 { |
|
1106 case ERemConClientTypeTarget: |
|
1107 { |
|
1108 LOG(_L("\tTARGET send")); |
|
1109 |
|
1110 msg = CRemConMessage::NewL( |
|
1111 TRemConAddress(), // we don't know which remotes it's going to yet |
|
1112 ERemConResponse, // targets can only send responses |
|
1113 messageSubType, |
|
1114 interfaceUid, |
|
1115 operationId, |
|
1116 sendDes, // msg takes ownership |
|
1117 Id(), // session id to match this response against the originating command |
|
1118 0, // transaction id not yet known |
|
1119 EFalse); |
|
1120 CLEANUPSTACK_POP1(&sendDes); // now owned by msg |
|
1121 break; |
|
1122 } |
|
1123 |
|
1124 case ERemConClientTypeController: |
|
1125 { |
|
1126 LOG(_L("\tCONTROLLER send")); |
|
1127 |
|
1128 // A client is not allowed to send an unreliable notify command. |
|
1129 if ( (messageSubType == ERemConNotifyCommandAwaitingInterim) |
|
1130 || (messageSubType == ERemConNotifyCommandAwaitingChanged) |
|
1131 ) |
|
1132 { |
|
1133 LOG(_L8("\tNot allowed to send unreliable notify command")); |
|
1134 CleanupStack::PopAndDestroy(&sendDes); |
|
1135 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicIllegalIpc); |
|
1136 LEAVEL(KErrBadDescriptor); |
|
1137 } |
|
1138 |
|
1139 msg = CRemConMessage::NewL( |
|
1140 iRemoteAddress, // either specified (if we're connection-oriented) or null (we're connectionless- this field will be filled in by the TSP) |
|
1141 ERemConCommand, // controllers can only send commands |
|
1142 messageSubType, |
|
1143 interfaceUid, |
|
1144 operationId, |
|
1145 sendDes, // msg takes ownership |
|
1146 Id(), // session id for when the response comes back |
|
1147 0, // we let the bearer manager invent a new transaction id when the message gets to it |
|
1148 EFalse); |
|
1149 CLEANUPSTACK_POP1(&sendDes); // now owned by msg |
|
1150 |
|
1151 } |
|
1152 break; |
|
1153 |
|
1154 default: |
|
1155 DEBUG_PANIC_LINENUM; |
|
1156 break; |
|
1157 } |
|
1158 |
|
1159 return msg; |
|
1160 } |
|
1161 |
|
1162 void CRemConSession::SendToServer(CRemConMessage& aMsg) |
|
1163 { |
|
1164 LOG_FUNC; |
|
1165 |
|
1166 // Set our completion members. |
|
1167 NumRemotes() = 0; |
|
1168 NumRemotesToTry() = 0; |
|
1169 SendError() = KErrNone; |
|
1170 |
|
1171 |
|
1172 iSending = (aMsg.IsReliableSend()) ? ESendingReliable: ESendingUnreliable; |
|
1173 switch ( iType ) |
|
1174 { |
|
1175 case ERemConClientTypeTarget: |
|
1176 { |
|
1177 iServer.SendResponse(aMsg, *this); |
|
1178 break; |
|
1179 } |
|
1180 case ERemConClientTypeController: |
|
1181 { |
|
1182 iServer.SendCommand(aMsg); |
|
1183 break; |
|
1184 } |
|
1185 default: |
|
1186 DEBUG_PANIC_LINENUM; |
|
1187 break; |
|
1188 } |
|
1189 } |
|
1190 |
|
1191 |
|
1192 void CRemConSession::SendCancel(const RMessage2& aMessage) |
|
1193 { |
|
1194 LOG_FUNC; |
|
1195 |
|
1196 // Check we've had our type set... |
|
1197 if ( Type() != ERemConClientTypeController |
|
1198 && Type() != ERemConClientTypeTarget |
|
1199 ) |
|
1200 { |
|
1201 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicClientTypeNotSet); |
|
1202 return; |
|
1203 } |
|
1204 |
|
1205 // See comments in ConnectBearerCancel. |
|
1206 if ( iSendMsg.Handle() ) |
|
1207 { |
|
1208 DoSendCancel(); |
|
1209 } |
|
1210 |
|
1211 if (iSendMsg.Handle()) |
|
1212 { |
|
1213 CRemConMessage* msg; |
|
1214 TBool first = ETrue; |
|
1215 ASSERT_DEBUG(iSendQueue); |
|
1216 TSglQueIter<CRemConMessage>& iter = iSendQueue->SetToFirst(); |
|
1217 while ((msg = iter++) != NULL) |
|
1218 { |
|
1219 if (msg->IsReliableSend()) |
|
1220 { |
|
1221 CompleteClient(iSendMsg, KErrCancel); |
|
1222 iSendQueue->RemoveAndDestroy(*msg); |
|
1223 if (first) |
|
1224 { |
|
1225 ASSERT_DEBUG(iSendNextCallBack); |
|
1226 iSendNextCallBack->Cancel(); |
|
1227 } |
|
1228 break; |
|
1229 } |
|
1230 first = EFalse; |
|
1231 } |
|
1232 } |
|
1233 |
|
1234 CompleteClient(aMessage, KErrNone); |
|
1235 } |
|
1236 |
|
1237 void CRemConSession::DoSendCancel() |
|
1238 { |
|
1239 LOG_FUNC; |
|
1240 // We must tell the server, and pull the CRemConMessage from the |
|
1241 // 'outgoing pending TSP' queue if it's on it. If the TSP is currently |
|
1242 // processing the CRemConMessage, we must tell it to stop before we |
|
1243 // can complete the RMessage2 iSendMsg- the TSP might still be |
|
1244 // dereferencing bits of it. (The TSP is given iSendMsg so it can |
|
1245 // access the client's secure ID and do a capability check.) |
|
1246 // NB This only matters for commands- responses don't go through the |
|
1247 // TSP. |
|
1248 // Not also that this processing *stops* this |
|
1249 // CRemConSession::SendCancel method from being the very simple 'I'm |
|
1250 // no longer interested in the completion of the asynchronous request' |
|
1251 // type of API it (and all cancels) should be. It actually does work |
|
1252 // as well. As long as this work is implemented _synchronously_, we |
|
1253 // should be OK. |
|
1254 iServer.SendCancel(*this); |
|
1255 |
|
1256 NumRemotesToTry() = 0; |
|
1257 iSendError = KErrCancel; |
|
1258 CompleteSend(); |
|
1259 |
|
1260 } |
|
1261 |
|
1262 void CRemConSession::EmptySendQueue() |
|
1263 { |
|
1264 ASSERT_DEBUG(!iSendMsg.Handle()) |
|
1265 ASSERT_DEBUG(iSendNextCallBack); |
|
1266 iSendNextCallBack->Cancel(); |
|
1267 CRemConMessage* msg; |
|
1268 ASSERT_DEBUG(iSendQueue); |
|
1269 TSglQueIter<CRemConMessage>& iter = iSendQueue->SetToFirst(); |
|
1270 while ((msg = iter++) != NULL) |
|
1271 { |
|
1272 iSendQueue->RemoveAndDestroy(*msg); |
|
1273 } |
|
1274 } |
|
1275 |
|
1276 void CRemConSession::Receive(const RMessage2& aMessage) |
|
1277 { |
|
1278 LOG_FUNC; |
|
1279 |
|
1280 // Messages are pushed from bearers, so we |
|
1281 // (a) do some sanity checking, |
|
1282 // (b) check the queue of incoming messages in case there's anything |
|
1283 // already waiting to be given to the client. |
|
1284 |
|
1285 if ( iReceiveMsg.Handle() ) |
|
1286 { |
|
1287 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicReceiveAlreadyOutstanding); |
|
1288 return; |
|
1289 } |
|
1290 |
|
1291 // Check we've had our type set... |
|
1292 if ( Type() != ERemConClientTypeController |
|
1293 && Type() != ERemConClientTypeTarget |
|
1294 ) |
|
1295 { |
|
1296 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicClientTypeNotSet); |
|
1297 return; |
|
1298 } |
|
1299 |
|
1300 iReceiveMsg = aMessage; |
|
1301 // If there's anything waiting to be given to us, ReceiveRequest will call |
|
1302 // back to us with it. |
|
1303 iServer.ReceiveRequest(*this); |
|
1304 } |
|
1305 |
|
1306 void CRemConSession::ReceiveCancel(const RMessage2& aMessage) |
|
1307 { |
|
1308 LOG_FUNC; |
|
1309 |
|
1310 // Check we've had our type set... |
|
1311 if ( Type() != ERemConClientTypeController |
|
1312 && Type() != ERemConClientTypeTarget |
|
1313 ) |
|
1314 { |
|
1315 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicClientTypeNotSet); |
|
1316 return; |
|
1317 } |
|
1318 |
|
1319 // See comments in ConnectBearerCancel. |
|
1320 if ( iReceiveMsg.Handle() ) |
|
1321 { |
|
1322 CompleteClient(iReceiveMsg, KErrCancel); |
|
1323 } |
|
1324 CompleteClient(aMessage, KErrNone); |
|
1325 } |
|
1326 |
|
1327 void CRemConSession::GetConnectionCount(const RMessage2& aMessage) |
|
1328 { |
|
1329 LOG_FUNC; |
|
1330 |
|
1331 // Check we've had our type set... |
|
1332 if ( Type() != ERemConClientTypeController |
|
1333 && Type() != ERemConClientTypeTarget |
|
1334 ) |
|
1335 { |
|
1336 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicClientTypeNotSet); |
|
1337 return; |
|
1338 } |
|
1339 |
|
1340 // Get the answer to the question- the number of connections at the |
|
1341 // current point in time (i.e. the latest entry in the connection |
|
1342 // history). |
|
1343 const TUint connCount = iServer.Connections().Count(); |
|
1344 LOG1(_L("\tconnCount = %d"), connCount); |
|
1345 TPckg<TUint> count(connCount); |
|
1346 TInt err = aMessage.Write(0, count); |
|
1347 |
|
1348 // If the client was told the answer with no error, then remember the |
|
1349 // current point in the connection history, so that when the client asks |
|
1350 // for the connections themselves, we give them a consistent answer. |
|
1351 if ( err == KErrNone ) |
|
1352 { |
|
1353 iServer.SetConnectionHistoryPointer(Id()); |
|
1354 } |
|
1355 CompleteClient(aMessage, err); |
|
1356 } |
|
1357 |
|
1358 void CRemConSession::GetConnections(const RMessage2& aMessage) |
|
1359 { |
|
1360 LOG_FUNC; |
|
1361 |
|
1362 // Check we've had our type set... |
|
1363 if ( Type() != ERemConClientTypeController |
|
1364 && Type() != ERemConClientTypeTarget |
|
1365 ) |
|
1366 { |
|
1367 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicClientTypeNotSet); |
|
1368 return; |
|
1369 } |
|
1370 |
|
1371 // Get the array of connections at the point in the history we're |
|
1372 // interested in and write it back to the client. NB This is not |
|
1373 // necessarily the Last item in the history but the item that we were |
|
1374 // pointing at when GetConnectionCount was called. |
|
1375 const CConnections& conns = iServer.Connections(iId); |
|
1376 const TUint count = conns.Count(); |
|
1377 LOG1(_L("\tcount = %d"), count); |
|
1378 RBuf8 buf; |
|
1379 TInt err = buf.Create(count * sizeof(TRemConAddress)); |
|
1380 if ( err == KErrNone ) |
|
1381 { |
|
1382 TSglQueIter<TRemConAddress>& iter = conns.SetToFirst(); |
|
1383 TRemConAddress* addr; |
|
1384 while ( ( addr = iter++ ) != NULL ) |
|
1385 { |
|
1386 buf.Append((TUint8*)addr, sizeof(TRemConAddress)); |
|
1387 } |
|
1388 |
|
1389 // Write back to the client... |
|
1390 err = aMessage.Write(0, buf); |
|
1391 buf.Close(); |
|
1392 if ( err != KErrNone ) |
|
1393 { |
|
1394 // We don't need to call SetConnectionHistoryPointer here because |
|
1395 // the server will do it when it cleans up the panicked client. |
|
1396 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBadDescriptor); |
|
1397 return; |
|
1398 } |
|
1399 } |
|
1400 |
|
1401 // Whether or not there was an error, we're no longer interested in the |
|
1402 // history item we're currently registered as being interested in, so tell |
|
1403 // the server to bump up our pointer to the current (latest) one. NB This |
|
1404 // may in fact be the same record, if no connection changes have occurred |
|
1405 // since GetConnectionCount was called, but it's still important to give |
|
1406 // the server a chance to remove obsolete history records. |
|
1407 iServer.SetConnectionHistoryPointer(Id()); |
|
1408 CompleteClient(aMessage, err); |
|
1409 } |
|
1410 |
|
1411 void CRemConSession::NotifyConnectionsChange(const RMessage2& aMessage) |
|
1412 { |
|
1413 LOG_FUNC; |
|
1414 |
|
1415 // Messages are pushed to us from bearers, so we don't need anything more |
|
1416 // than some sanity checking here. |
|
1417 // Check we've had our type set... |
|
1418 if ( Type() != ERemConClientTypeController |
|
1419 && Type() != ERemConClientTypeTarget |
|
1420 ) |
|
1421 { |
|
1422 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicClientTypeNotSet); |
|
1423 return; |
|
1424 } |
|
1425 |
|
1426 if ( iNotifyConnectionsChangeMsg.Handle() ) |
|
1427 { |
|
1428 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicConnectionsNotificationAlreadyOutstanding); |
|
1429 } |
|
1430 else |
|
1431 { |
|
1432 iNotifyConnectionsChangeMsg = aMessage; |
|
1433 // Check the connection history for any more recent items than that we |
|
1434 // currently know about. If our pointer into the connection history |
|
1435 // isn't pointing at the 'current' item, we can complete the |
|
1436 // notification immediately and move the pointer up. |
|
1437 if ( !iServer.ConnectionHistoryPointerAtLatest(Id()) ) |
|
1438 { |
|
1439 CompleteClient(iNotifyConnectionsChangeMsg, KErrNone); |
|
1440 iServer.SetConnectionHistoryPointer(Id()); |
|
1441 } |
|
1442 } |
|
1443 } |
|
1444 |
|
1445 void CRemConSession::NotifyConnectionsChangeCancel(const RMessage2& aMessage) |
|
1446 { |
|
1447 LOG_FUNC; |
|
1448 |
|
1449 // Check we've had our type set... |
|
1450 if ( Type() != ERemConClientTypeController |
|
1451 && Type() != ERemConClientTypeTarget |
|
1452 ) |
|
1453 { |
|
1454 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicClientTypeNotSet); |
|
1455 return; |
|
1456 } |
|
1457 |
|
1458 // See comments in ConnectBearerCancel. |
|
1459 if ( iNotifyConnectionsChangeMsg.Handle() ) |
|
1460 { |
|
1461 CompleteClient(iNotifyConnectionsChangeMsg, KErrCancel); |
|
1462 } |
|
1463 CompleteClient(aMessage, KErrNone); |
|
1464 } |
|
1465 |
|
1466 void CRemConSession::RegisterInterestedAPIs(const RMessage2& aMessage) |
|
1467 { |
|
1468 LOG_FUNC; |
|
1469 |
|
1470 if(iType == ERemConClientTypeUndefined) |
|
1471 { |
|
1472 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicRegisterInterestedAPIsInNonTargetSession); |
|
1473 } |
|
1474 |
|
1475 TRAPD(err, DoRegisterInterestedAPIsL(aMessage)); |
|
1476 |
|
1477 if(iType == ERemConClientTypeController) |
|
1478 { |
|
1479 iServer.ControllerClientAvailable(); |
|
1480 } |
|
1481 else if(err == KErrNone) // must be target |
|
1482 { |
|
1483 iServer.TargetClientAvailable(*this); |
|
1484 |
|
1485 TInt count = iInterestedAPIs->Array().Count(); |
|
1486 for(TInt ix=0; ix<count; ++ix) |
|
1487 { |
|
1488 CRemConInterfaceDetails* details = iInterestedAPIs->Array()[ix]; |
|
1489 ASSERT_DEBUG(details); |
|
1490 if(details->IsBulk()) |
|
1491 { |
|
1492 iServer.BulkServerRequired(); |
|
1493 break; |
|
1494 } |
|
1495 } |
|
1496 } |
|
1497 |
|
1498 CompleteClient(aMessage, err); |
|
1499 } |
|
1500 |
|
1501 void CRemConSession::DoRegisterInterestedAPIsL(const RMessage2& aMessage) |
|
1502 { |
|
1503 LOG_FUNC; |
|
1504 |
|
1505 RBuf8 buf; |
|
1506 buf.CreateL(aMessage.GetDesLengthL(0)); |
|
1507 CleanupClosePushL(buf); |
|
1508 |
|
1509 aMessage.ReadL(0, buf); |
|
1510 RDesReadStream ipcStream(buf); |
|
1511 |
|
1512 iInterestedAPIs = CRemConInterfaceDetailsArray::InternalizeL(ipcStream); |
|
1513 |
|
1514 ipcStream.Close(); |
|
1515 CleanupStack::PopAndDestroy(&buf); |
|
1516 } |
|
1517 |
|
1518 void CRemConSession::CompleteConnect(const TRemConAddress& aAddr, TInt aError) |
|
1519 { |
|
1520 LOG_FUNC; |
|
1521 LOG2(_L("\taError = %d, aAddr.BearerUid = 0x%08x"), aError, aAddr.BearerUid()); |
|
1522 |
|
1523 LOG1(_L("\tiRemoteAddress.BearerUid = 0x%08x"), iRemoteAddress.BearerUid()); |
|
1524 LOG1(_L("\tiConnectBearerMsg.Handle = %d"), iConnectBearerMsg.Handle()); |
|
1525 |
|
1526 if ( iRemoteAddress == aAddr ) |
|
1527 { |
|
1528 if ( iConnectBearerMsg.Handle() ) |
|
1529 { |
|
1530 // We are a session that has an outstanding request on this specific |
|
1531 // connection address. |
|
1532 CompleteClient(iConnectBearerMsg, aError); |
|
1533 } |
|
1534 else |
|
1535 { |
|
1536 // Connect bearer message is not valid. |
|
1537 // Check for pending messages. |
|
1538 CheckForPendingMsg(); |
|
1539 } |
|
1540 } |
|
1541 } |
|
1542 |
|
1543 void CRemConSession::CompleteDisconnect(const TRemConAddress& aAddr, TInt aError) |
|
1544 { |
|
1545 LOG_FUNC; |
|
1546 LOG2(_L("\taError = %d, aAddr.BearerUid = 0x%08x"), aError, aAddr.BearerUid()); |
|
1547 |
|
1548 LOG1(_L("\tiRemoteAddress.BearerUid = 0x%08x"), iRemoteAddress.BearerUid()); |
|
1549 LOG1(_L("\tiDisconnectBearerMsg.Handle = %d"), iDisconnectBearerMsg.Handle()); |
|
1550 |
|
1551 if ( iRemoteAddress == aAddr ) |
|
1552 { |
|
1553 if ( iDisconnectBearerMsg.Handle() ) |
|
1554 { |
|
1555 // We are a session that has an outstanding request on this specific |
|
1556 // connection address. |
|
1557 CompleteClient(iDisconnectBearerMsg, aError); |
|
1558 } |
|
1559 else |
|
1560 { |
|
1561 // Diconnect bearer message is not valid. |
|
1562 // Check for pending messages. |
|
1563 CheckForPendingMsg(); |
|
1564 } |
|
1565 |
|
1566 } |
|
1567 } |
|
1568 |
|
1569 void CRemConSession::ConnectionsChanged() |
|
1570 { |
|
1571 LOG_FUNC; |
|
1572 |
|
1573 LOG1(_L("\tiNotifyConnectionsChangeMsg.Handle = %d"), iNotifyConnectionsChangeMsg.Handle()); |
|
1574 if ( iNotifyConnectionsChangeMsg.Handle() ) |
|
1575 { |
|
1576 // Set the connection history pointer to point to the latest item and then complete the |
|
1577 // NotifyConnectionChange request of the client. |
|
1578 iServer.SetConnectionHistoryPointer(Id()); |
|
1579 CompleteClient(iNotifyConnectionsChangeMsg, KErrNone); |
|
1580 } |
|
1581 } |
|
1582 |
|
1583 void CRemConSession::CompleteSend() |
|
1584 { |
|
1585 LOG_FUNC; |
|
1586 LOG2(_L("\tiNumRemotes = %d, iSendError = %d"), iNumRemotes, iSendError); |
|
1587 |
|
1588 ASSERT_DEBUG(NumRemotesToTry() == 0); |
|
1589 NumRemotesToTry() = -1; |
|
1590 |
|
1591 |
|
1592 if (iSending == ESendingReliable) |
|
1593 { |
|
1594 if ( iSendError == KErrNone ) |
|
1595 { |
|
1596 TPckg<TUint> count(iNumRemotes); |
|
1597 // 2 is the slot in the client's message for the number of remotes the |
|
1598 // message got sent to. |
|
1599 iSendError = iSendMsg.Write(2, count); |
|
1600 } |
|
1601 CompleteClient(iSendMsg, iSendError); |
|
1602 } |
|
1603 |
|
1604 ASSERT_DEBUG(iSendQueue); |
|
1605 if (!iSendQueue->IsEmpty()) |
|
1606 { |
|
1607 ASSERT_DEBUG(iSendNextCallBack); |
|
1608 iSendNextCallBack->CallBack(); |
|
1609 } |
|
1610 iSending = ENotSending; |
|
1611 } |
|
1612 |
|
1613 void CRemConSession::CompleteSendNotify() |
|
1614 { |
|
1615 LOG_FUNC; |
|
1616 LOG1(_L("\tiSendError = %d"), iSendError); |
|
1617 |
|
1618 if (iSending == ESendingReliable) |
|
1619 { |
|
1620 CompleteClient(iSendMsg, iSendError); |
|
1621 } |
|
1622 |
|
1623 ASSERT_DEBUG(iSendQueue); |
|
1624 if (!iSendQueue->IsEmpty()) |
|
1625 { |
|
1626 ASSERT_DEBUG(iSendNextCallBack); |
|
1627 iSendNextCallBack->CallBack(); |
|
1628 } |
|
1629 iSending = ENotSending; |
|
1630 } |
|
1631 |
|
1632 TInt CRemConSession::SendNextCb(TAny* aThis) |
|
1633 { |
|
1634 static_cast<CRemConSession*>(aThis)->DoSendNext(); |
|
1635 return KErrNone; |
|
1636 } |
|
1637 |
|
1638 void CRemConSession::DoSendNext() |
|
1639 { |
|
1640 ASSERT_DEBUG(iSendQueue); |
|
1641 CRemConMessage& msg = iSendQueue->First(); |
|
1642 iSendQueue->Remove(msg); |
|
1643 SendToServer(msg); |
|
1644 } |
|
1645 |
|
1646 void CRemConSession::PanicSend(TRemConClientPanic aCode) |
|
1647 { |
|
1648 LOG_FUNC; |
|
1649 LOG1(_L("\taCode = %d"), aCode); |
|
1650 |
|
1651 PANIC_MSG(iSendMsg, KRemConClientPanicCat, aCode); |
|
1652 } |
|
1653 |
|
1654 TBool CRemConSession::SupportedMessage(const CRemConMessage& aMsg) |
|
1655 { |
|
1656 // Return true unless this is a command for an unsupported interface |
|
1657 return !(aMsg.MsgType() == ERemConCommand && !FindInterfaceByUid(aMsg.InterfaceUid())); |
|
1658 } |
|
1659 |
|
1660 TInt CRemConSession::WriteMessageToClient(const CRemConMessage& aMsg) |
|
1661 { |
|
1662 LOG_FUNC; |
|
1663 |
|
1664 ASSERT_DEBUG(SupportedMessage(aMsg)); |
|
1665 ASSERT_DEBUG(iReceiveMsg.Handle()); |
|
1666 TRAPD(err, WriteMessageToClientL(aMsg)); |
|
1667 CompleteClient(iReceiveMsg, err); |
|
1668 |
|
1669 LOG1(_L("\terr = %d"), err); |
|
1670 return err; |
|
1671 } |
|
1672 |
|
1673 void CRemConSession::WriteMessageToClientL(const CRemConMessage& aMsg) |
|
1674 { |
|
1675 LOG_FUNC; |
|
1676 |
|
1677 //check if our client is interested in this API |
|
1678 //Only need to check commands because it is safe to assume that we are interested |
|
1679 //in the response if we have sent out a command. |
|
1680 if(aMsg.MsgType() == ERemConCommand && !FindInterfaceByUid(aMsg.InterfaceUid())) |
|
1681 { |
|
1682 //The server will clean up the resource allocated for this msg |
|
1683 LEAVEL(KErrArgument); |
|
1684 } |
|
1685 |
|
1686 // This logging code left in for maintenance. |
|
1687 //LOG1(_L("\t\tOperationData = \"%S\""), &aMsg.OperationData()); |
|
1688 |
|
1689 TRemConClientReceivePackage receivePackage; |
|
1690 receivePackage.iInterfaceUid = aMsg.InterfaceUid(); |
|
1691 receivePackage.iOperationId = aMsg.OperationId(); |
|
1692 receivePackage.iMessageSubType = aMsg.MsgSubType(); |
|
1693 receivePackage.iRemoteAddress = aMsg.Addr(); |
|
1694 |
|
1695 TPckgC<TRemConClientReceivePackage> recPckg(receivePackage); |
|
1696 LEAVEIFERRORL(iReceiveMsg.Write(0, recPckg)); |
|
1697 |
|
1698 // Note that we do not panic the client if their descriptor is not |
|
1699 // big enough to hold the operation-specific data. If we did, then |
|
1700 // a buggy remote could take down a client of RemCon. Just error |
|
1701 // the client instead. |
|
1702 LEAVEIFERRORL(iReceiveMsg.Write(1, aMsg.OperationData())); |
|
1703 } |
|
1704 |
|
1705 void CRemConSession::CheckForPendingMsg() const |
|
1706 { |
|
1707 LOG_FUNC; |
|
1708 if (iPendingMsg.Handle()) |
|
1709 { |
|
1710 ASSERT_DEBUG(iPendingMsgProcessor); |
|
1711 iPendingMsgProcessor->Complete(); |
|
1712 } |
|
1713 } |
|
1714 |
|
1715 void CRemConSession::ProcessPendingMsgL() |
|
1716 { |
|
1717 LOG_FUNC; |
|
1718 if (!iPendingMsg.Handle()) |
|
1719 { |
|
1720 // This means that the pending connect or disconnect message, |
|
1721 // has been cancelled by the time we got here. |
|
1722 // (It was cancelled between two following calls: |
|
1723 // iPendingMsgProcessor::Complete and iPendingMsgProcessor::RunL |
|
1724 return; |
|
1725 } |
|
1726 |
|
1727 ServiceL(iPendingMsg); |
|
1728 if (iPendingMsg.Handle()) |
|
1729 { |
|
1730 // This means that the pending msg has not been completed in ServiceL call. |
|
1731 // It was stored either in iConnectBearerMsg or iDisconnectBearerMsg member. |
|
1732 // This also means that this message is not "pending" any more |
|
1733 // (as processing of its copy has been started). |
|
1734 // However because the copy will get completed we need to |
|
1735 // clean iPendingMsg.iHandle here |
|
1736 // To supress coverity error for uninitialized use of 'emptyMsg' coverity annotations |
|
1737 // are used as the in-line default constructor of RMessage2 doesn't initialize all member variables. |
|
1738 // coverity[var_decl] |
|
1739 RMessage2 emptyMsg; |
|
1740 iPendingMsg = emptyMsg; |
|
1741 } |
|
1742 } |
|
1743 |
|
1744 |
|
1745 TInt CRemConSession::SupportedInterfaces(RArray<TUid>& aUids) |
|
1746 { |
|
1747 LOG_FUNC |
|
1748 ASSERT_DEBUG(iInterestedAPIs); |
|
1749 TInt err = KErrNone; |
|
1750 |
|
1751 aUids.Reset(); |
|
1752 TInt count = iInterestedAPIs->Array().Count(); |
|
1753 for(TInt i=0; (i<count) && (err == KErrNone); i++) |
|
1754 { |
|
1755 CRemConInterfaceDetails* details = iInterestedAPIs->Array()[i]; |
|
1756 ASSERT_DEBUG(details); |
|
1757 err = aUids.Append(details->Uid()); |
|
1758 } |
|
1759 |
|
1760 return err; |
|
1761 } |
|
1762 |
|
1763 TInt CRemConSession::SupportedBulkInterfaces(RArray<TUid>& aUids) |
|
1764 { |
|
1765 LOG_FUNC |
|
1766 ASSERT_DEBUG(iInterestedAPIs); |
|
1767 TInt err = KErrNone; |
|
1768 |
|
1769 aUids.Reset(); |
|
1770 TInt count = iInterestedAPIs->Array().Count(); |
|
1771 for(TInt i=0; (i<count) && (err == KErrNone); i++) |
|
1772 { |
|
1773 CRemConInterfaceDetails* details = iInterestedAPIs->Array()[i]; |
|
1774 ASSERT_DEBUG(details); |
|
1775 if(details->IsBulk()) |
|
1776 { |
|
1777 err = aUids.Append(details->Uid()); |
|
1778 } |
|
1779 } |
|
1780 |
|
1781 return err; |
|
1782 } |
|
1783 |
|
1784 TInt CRemConSession::SupportedOperations(TUid aInterfaceUid, RArray<TUint>& aOperations) |
|
1785 { |
|
1786 LOG_FUNC |
|
1787 TInt err = KErrNotSupported; |
|
1788 CRemConInterfaceDetails* details = FindInterfaceByUid(aInterfaceUid); |
|
1789 |
|
1790 if(details) |
|
1791 { |
|
1792 TRAP(err, details->GetRemConInterfaceFeaturesL(aOperations)); |
|
1793 } |
|
1794 return err; |
|
1795 } |
|
1796 |
|
1797 CRemConInterfaceDetails* CRemConSession::FindInterfaceByUid(TUid aUid) const |
|
1798 { |
|
1799 LOG_FUNC |
|
1800 ASSERT_DEBUG(iInterestedAPIs); |
|
1801 TInt count = iInterestedAPIs->Array().Count(); |
|
1802 for(TInt ix=0; ix<count; ++ix) |
|
1803 { |
|
1804 CRemConInterfaceDetails* details = iInterestedAPIs->Array()[ix]; |
|
1805 ASSERT_DEBUG(details); |
|
1806 if(details->Uid() == aUid) |
|
1807 { |
|
1808 return details; |
|
1809 } |
|
1810 } |
|
1811 return NULL; |
|
1812 } |
|
1813 |
|
1814 |