|
1 // Copyright (c) 2004-2010 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 "session.h" |
|
34 #include "messagequeue.h" |
|
35 #include "remconserver.h" |
|
36 |
|
37 #ifdef __FLOG_ACTIVE |
|
38 _LIT8(KLogComponent, LOG_COMPONENT_REMCON_SERVER); |
|
39 #endif |
|
40 |
|
41 #ifdef _DEBUG |
|
42 PANICCATEGORY("session"); |
|
43 #endif |
|
44 |
|
45 |
|
46 CRemConSession::CRemConSession(CRemConServer& aServer, |
|
47 CBearerManager& aBearerManager, |
|
48 TUint aId) |
|
49 : iServer(aServer), |
|
50 iBearerManager(aBearerManager), |
|
51 iId(aId) |
|
52 { |
|
53 LOG_FUNC; |
|
54 } |
|
55 |
|
56 void CRemConSession::BaseConstructL(const TClientInfo& aClientInfo) |
|
57 { |
|
58 LOG_FUNC; |
|
59 |
|
60 iClientInfo = aClientInfo; |
|
61 |
|
62 iSendQueue = CMessageQueue::NewL(); |
|
63 |
|
64 // The send callback is used by the base class to handle queued sends. |
|
65 iSendNextCallBack = new(ELeave) CAsyncCallBack(CActive::EPriorityStandard); |
|
66 TCallBack cb(SendNextCb, this); |
|
67 iSendNextCallBack->Set(cb); |
|
68 |
|
69 } |
|
70 |
|
71 CRemConSession::~CRemConSession() |
|
72 { |
|
73 LOG(KNullDesC8); |
|
74 LOG_FUNC; |
|
75 |
|
76 delete iSendNextCallBack; |
|
77 delete iSendQueue; |
|
78 delete iInterestedAPIs; |
|
79 } |
|
80 |
|
81 void CRemConSession::ServiceL(const RMessage2& aMessage) |
|
82 { |
|
83 LOG(KNullDesC8); |
|
84 LOG_FUNC; |
|
85 LOG1(_L("\taMessage.Function() = %d"), aMessage.Function()); |
|
86 // Switch on the IPC number and call a 'message handler'. Message handlers |
|
87 // complete aMessage (either with Complete or Panic), or make a note of |
|
88 // the message for later asynchronous completion. |
|
89 // Message handlers should not leave- the server does not have an Error |
|
90 // function. |
|
91 |
|
92 switch ( aMessage.Function() ) |
|
93 { |
|
94 // Heap failure testing APIs. |
|
95 case ERemConDbgMarkHeap: |
|
96 #ifdef _DEBUG |
|
97 LOG(_L("\tmark heap")); |
|
98 __UHEAP_MARK; |
|
99 #endif // _DEBUG |
|
100 CompleteClient(aMessage, KErrNone); |
|
101 break; |
|
102 |
|
103 case ERemConDbgCheckHeap: |
|
104 #ifdef _DEBUG |
|
105 LOG1(_L("\tcheck heap (expecting %d cells)"), aMessage.Int0()); |
|
106 __UHEAP_CHECK(aMessage.Int0()); |
|
107 #endif // _DEBUG |
|
108 CompleteClient(aMessage, KErrNone); |
|
109 break; |
|
110 |
|
111 case ERemConDbgMarkEnd: |
|
112 #ifdef _DEBUG |
|
113 LOG1(_L("\tmark end (expecting %d cells)"), aMessage.Int0()); |
|
114 __UHEAP_MARKENDC(aMessage.Int0()); |
|
115 #endif // _DEBUG |
|
116 CompleteClient(aMessage, KErrNone); |
|
117 break; |
|
118 |
|
119 case ERemConDbgFailNext: |
|
120 #ifdef _DEBUG |
|
121 { |
|
122 LOG1(_L("\tfail next (simulating failure after %d allocation(s))"), aMessage.Int0()); |
|
123 if ( aMessage.Int0() == 0 ) |
|
124 { |
|
125 __UHEAP_RESET; |
|
126 } |
|
127 else |
|
128 { |
|
129 __UHEAP_FAILNEXT(aMessage.Int0()); |
|
130 } |
|
131 } |
|
132 #endif // _DEBUG |
|
133 CompleteClient(aMessage, KErrNone); |
|
134 break; |
|
135 |
|
136 case ERemConSetPlayerType: |
|
137 SetPlayerType(aMessage); |
|
138 // This is a sync API- check that the message has been completed. |
|
139 // (NB We don't check the converse for async APIs because the message |
|
140 // may have been panicked synchronously.) |
|
141 ASSERT_DEBUG(aMessage.IsNull()); |
|
142 break; |
|
143 |
|
144 case ERemConSend: |
|
145 Send(aMessage); |
|
146 break; |
|
147 |
|
148 case ERemConSendUnreliable: |
|
149 SendUnreliable(aMessage); |
|
150 break; |
|
151 |
|
152 case ERemConSendCancel: |
|
153 SendCancel(aMessage); |
|
154 ASSERT_DEBUG(aMessage.IsNull()); |
|
155 break; |
|
156 |
|
157 case ERemConReceive: |
|
158 Receive(aMessage); |
|
159 break; |
|
160 |
|
161 case ERemConReceiveCancel: |
|
162 ReceiveCancel(aMessage); |
|
163 ASSERT_DEBUG(aMessage.IsNull()); |
|
164 break; |
|
165 |
|
166 case ERemConGetConnectionCount: |
|
167 GetConnectionCount(aMessage); |
|
168 ASSERT_DEBUG(aMessage.IsNull()); |
|
169 break; |
|
170 |
|
171 case ERemConGetConnections: |
|
172 GetConnections(aMessage); |
|
173 ASSERT_DEBUG(aMessage.IsNull()); |
|
174 break; |
|
175 |
|
176 case ERemConNotifyConnectionsChange: |
|
177 NotifyConnectionsChange(aMessage); |
|
178 break; |
|
179 |
|
180 case ERemConNotifyConnectionsChangeCancel: |
|
181 NotifyConnectionsChangeCancel(aMessage); |
|
182 ASSERT_DEBUG(aMessage.IsNull()); |
|
183 break; |
|
184 |
|
185 case ERemConRegisterInterestedAPIs: |
|
186 RegisterInterestedAPIs(aMessage); |
|
187 ASSERT_DEBUG(aMessage.IsNull()); |
|
188 break; |
|
189 |
|
190 case ERemConGoConnectionOriented: |
|
191 GoConnectionOriented(aMessage); |
|
192 ASSERT_DEBUG(aMessage.IsNull()); |
|
193 break; |
|
194 |
|
195 case ERemConGoConnectionless: |
|
196 GoConnectionless(aMessage); |
|
197 ASSERT_DEBUG(aMessage.IsNull()); |
|
198 break; |
|
199 |
|
200 case ERemConConnectBearer: |
|
201 ConnectBearer(aMessage); |
|
202 break; |
|
203 |
|
204 case ERemConConnectBearerCancel: |
|
205 ConnectBearerCancel(aMessage); |
|
206 ASSERT_DEBUG(aMessage.IsNull()); |
|
207 break; |
|
208 |
|
209 case ERemConDisconnectBearer: |
|
210 DisconnectBearer(aMessage); |
|
211 break; |
|
212 |
|
213 case ERemConDisconnectBearerCancel: |
|
214 DisconnectBearerCancel(aMessage); |
|
215 ASSERT_DEBUG(aMessage.IsNull()); |
|
216 break; |
|
217 |
|
218 case ERemConSendNotify: |
|
219 SendNotify(aMessage); |
|
220 break; |
|
221 |
|
222 default: |
|
223 // Unknown message |
|
224 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicIllegalIpc); |
|
225 break; |
|
226 } |
|
227 } |
|
228 |
|
229 void CRemConSession::CompleteClient(const RMessage2& aMessage, TInt aError) |
|
230 { |
|
231 LOG1(_L("\tcompleting client message with %d"), aError); |
|
232 TBool cleanClientInfoMessage = (iClientInfo.Message().Handle() == aMessage.Handle()); |
|
233 aMessage.Complete(aError); |
|
234 if(cleanClientInfoMessage) |
|
235 { |
|
236 iClientInfo.Message() = RMessage2(); |
|
237 } |
|
238 } |
|
239 |
|
240 void CRemConSession::GetPlayerTypeAndNameL(const RMessage2& aMessage, TPlayerTypeInformation& aPlayerType, RBuf8& aPlayerName) |
|
241 { |
|
242 // check validity of descriptors |
|
243 if (aMessage.GetDesLength(1) < 0 || aMessage.GetDesLength(2) < 0) |
|
244 { |
|
245 LEAVEL(KErrBadDescriptor); |
|
246 } |
|
247 |
|
248 // Retrieve and validate the client type information |
|
249 TPckg<TPlayerTypeInformation> pckg(aPlayerType); |
|
250 aMessage.ReadL(1, pckg); |
|
251 switch (aPlayerType.iPlayerType) |
|
252 { |
|
253 case ERemConAudioPlayer: |
|
254 // Valid |
|
255 case ERemConVideoPlayer: |
|
256 // Valid |
|
257 case ERemConBroadcastingAudioPlayer: |
|
258 // Valid |
|
259 case ERemConBroadcastingVideoPlayer: |
|
260 // Valid |
|
261 break; |
|
262 default: |
|
263 // Invalid |
|
264 LEAVEL(KErrArgument); |
|
265 } |
|
266 switch (aPlayerType.iPlayerSubType) |
|
267 { |
|
268 case ERemConNoSubType: |
|
269 // Valid |
|
270 case ERemConAudioBook: |
|
271 // Valid |
|
272 case ERemConPodcast: |
|
273 // Valid |
|
274 break; |
|
275 default: |
|
276 // Invalid |
|
277 LEAVEL(KErrArgument); |
|
278 } |
|
279 |
|
280 // Retrieve the client player name inforamtion |
|
281 aPlayerName.CreateL(aMessage.GetDesLengthL(2)); |
|
282 CleanupClosePushL(aPlayerName); |
|
283 aMessage.ReadL(2, aPlayerName); |
|
284 CleanupStack::Pop(&aPlayerName); |
|
285 } |
|
286 |
|
287 void CRemConSession::Send(const RMessage2& aMessage) |
|
288 { |
|
289 LOG_FUNC; |
|
290 |
|
291 // Check we're not already sending... |
|
292 if ( iSendMsg.Handle()) |
|
293 { |
|
294 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicSendAlreadyOutstanding); |
|
295 return; |
|
296 } |
|
297 |
|
298 iSendMsg = aMessage; |
|
299 |
|
300 // Check we've had our features set... |
|
301 if (!ClientAvailable()) |
|
302 { |
|
303 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicClientFeaturesNotSet); |
|
304 return; |
|
305 } |
|
306 |
|
307 // Before we ask the server to send, we must set our ClientInfo |
|
308 // correctly so the TSP can get information about the client. |
|
309 iClientInfo.Message() = aMessage; |
|
310 |
|
311 // Prepare the message for send. If DoPrepareSendMessageL() returns |
|
312 // NULL, it panicked the client. |
|
313 CRemConMessage* msg = NULL; |
|
314 TRAPD(err, msg = DoPrepareSendMessageL(aMessage)); |
|
315 |
|
316 if ( err != KErrNone ) |
|
317 { |
|
318 CompleteClient(aMessage, err); |
|
319 } |
|
320 else if (msg) |
|
321 { |
|
322 ASSERT_DEBUG(iSendQueue); |
|
323 |
|
324 if (iSending != ENotSending || !iSendQueue->IsEmpty()) |
|
325 { |
|
326 iSendQueue->Append(*msg); |
|
327 } |
|
328 else |
|
329 { |
|
330 // we know msg cannot be null here as said above. |
|
331 SendToServer(*msg); |
|
332 } |
|
333 } |
|
334 } |
|
335 |
|
336 void CRemConSession::SendCancel(const RMessage2& aMessage) |
|
337 { |
|
338 LOG_FUNC; |
|
339 |
|
340 // Check we've had our features set... |
|
341 if (!ClientAvailable()) |
|
342 { |
|
343 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicClientFeaturesNotSet); |
|
344 return; |
|
345 } |
|
346 |
|
347 // See comments in ConnectBearerCancel. |
|
348 if ( iSendMsg.Handle() ) |
|
349 { |
|
350 DoSendCancel(); |
|
351 } |
|
352 |
|
353 if (iSendMsg.Handle()) |
|
354 { |
|
355 CRemConMessage* msg; |
|
356 TBool first = ETrue; |
|
357 ASSERT_DEBUG(iSendQueue); |
|
358 TSglQueIter<CRemConMessage>& iter = iSendQueue->SetToFirst(); |
|
359 while ((msg = iter++) != NULL) |
|
360 { |
|
361 if (msg->IsReliableSend()) |
|
362 { |
|
363 CompleteClient(iSendMsg, KErrCancel); |
|
364 iSendQueue->RemoveAndDestroy(*msg); |
|
365 if (first) |
|
366 { |
|
367 ASSERT_DEBUG(iSendNextCallBack); |
|
368 iSendNextCallBack->Cancel(); |
|
369 } |
|
370 break; |
|
371 } |
|
372 first = EFalse; |
|
373 } |
|
374 } |
|
375 |
|
376 CompleteClient(aMessage, KErrNone); |
|
377 } |
|
378 |
|
379 void CRemConSession::Receive(const RMessage2& aMessage) |
|
380 { |
|
381 LOG_FUNC; |
|
382 |
|
383 // Messages are pushed from bearers, so we |
|
384 // (a) do some sanity checking, |
|
385 // (b) check the queue of incoming messages in case there's anything |
|
386 // already waiting to be given to the client. |
|
387 |
|
388 if ( iReceiveMsg.Handle() ) |
|
389 { |
|
390 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicReceiveAlreadyOutstanding); |
|
391 return; |
|
392 } |
|
393 |
|
394 // Check we've had our features set... |
|
395 if (!ClientAvailable()) |
|
396 { |
|
397 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicClientFeaturesNotSet); |
|
398 return; |
|
399 } |
|
400 |
|
401 iReceiveMsg = aMessage; |
|
402 |
|
403 DoReceive(); |
|
404 } |
|
405 |
|
406 void CRemConSession::ReceiveCancel(const RMessage2& aMessage) |
|
407 { |
|
408 LOG_FUNC; |
|
409 |
|
410 // Check we've had our features set... |
|
411 if (!ClientAvailable()) |
|
412 { |
|
413 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicClientFeaturesNotSet); |
|
414 return; |
|
415 } |
|
416 |
|
417 // See comments in ConnectBearerCancel. |
|
418 if ( iReceiveMsg.Handle() ) |
|
419 { |
|
420 CompleteClient(iReceiveMsg, KErrCancel); |
|
421 } |
|
422 CompleteClient(aMessage, KErrNone); |
|
423 } |
|
424 |
|
425 void CRemConSession::GetConnectionCount(const RMessage2& aMessage) |
|
426 { |
|
427 LOG_FUNC; |
|
428 |
|
429 // Check we've had our features set... |
|
430 if (!ClientAvailable()) |
|
431 { |
|
432 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicClientFeaturesNotSet); |
|
433 return; |
|
434 } |
|
435 |
|
436 // Get the answer to the question- the number of connections at the |
|
437 // current point in time (i.e. the latest entry in the connection |
|
438 // history). |
|
439 const TUint connCount = iServer.Connections().Count(); |
|
440 LOG1(_L("\tconnCount = %d"), connCount); |
|
441 TPckg<TUint> count(connCount); |
|
442 TInt err = aMessage.Write(0, count); |
|
443 |
|
444 // If the client was told the answer with no error, then remember the |
|
445 // current point in the connection history, so that when the client asks |
|
446 // for the connections themselves, we give them a consistent answer. |
|
447 if ( err == KErrNone ) |
|
448 { |
|
449 iServer.SetConnectionHistoryPointer(Id()); |
|
450 iInGetConnectionsProcedure = ETrue; |
|
451 } |
|
452 CompleteClient(aMessage, err); |
|
453 } |
|
454 |
|
455 void CRemConSession::GetConnections(const RMessage2& aMessage) |
|
456 { |
|
457 LOG_FUNC; |
|
458 |
|
459 // Check we've had our features set... |
|
460 if (!ClientAvailable()) |
|
461 { |
|
462 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicClientFeaturesNotSet); |
|
463 return; |
|
464 } |
|
465 |
|
466 iInGetConnectionsProcedure = EFalse; |
|
467 |
|
468 // Get the array of connections at the point in the history we're |
|
469 // interested in and write it back to the client. NB This is not |
|
470 // necessarily the Last item in the history but the item that we were |
|
471 // pointing at when GetConnectionCount was called. |
|
472 const CConnections& conns = iServer.Connections(iId); |
|
473 const TUint count = conns.Count(); |
|
474 LOG1(_L("\tcount = %d"), count); |
|
475 RBuf8 buf; |
|
476 TInt err = buf.Create(count * sizeof(TRemConAddress)); |
|
477 if ( err == KErrNone ) |
|
478 { |
|
479 TSglQueIter<TRemConAddress>& iter = conns.SetToFirst(); |
|
480 TRemConAddress* addr; |
|
481 while ( ( addr = iter++ ) != NULL ) |
|
482 { |
|
483 buf.Append((TUint8*)addr, sizeof(TRemConAddress)); |
|
484 } |
|
485 |
|
486 // Write back to the client... |
|
487 err = aMessage.Write(0, buf); |
|
488 buf.Close(); |
|
489 if ( err != KErrNone ) |
|
490 { |
|
491 // We don't need to call SetConnectionHistoryPointer here because |
|
492 // the server will do it when it cleans up the panicked client. |
|
493 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBadDescriptor); |
|
494 return; |
|
495 } |
|
496 } |
|
497 |
|
498 // Whether or not there was an error, we're no longer interested in the |
|
499 // history item we're currently registered as being interested in, so tell |
|
500 // the server to bump up our pointer to the current (latest) one. NB This |
|
501 // may in fact be the same record, if no connection changes have occurred |
|
502 // since GetConnectionCount was called, but it's still important to give |
|
503 // the server a chance to remove obsolete history records. |
|
504 iServer.SetConnectionHistoryPointer(Id()); |
|
505 CompleteClient(aMessage, err); |
|
506 } |
|
507 |
|
508 void CRemConSession::NotifyConnectionsChange(const RMessage2& aMessage) |
|
509 { |
|
510 LOG_FUNC; |
|
511 |
|
512 // Messages are pushed to us from bearers, so we don't need anything more |
|
513 // than some sanity checking here. |
|
514 // Check we've had our features set... |
|
515 if (!ClientAvailable()) |
|
516 { |
|
517 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicClientFeaturesNotSet); |
|
518 return; |
|
519 } |
|
520 |
|
521 if ( iNotifyConnectionsChangeMsg.Handle() ) |
|
522 { |
|
523 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicConnectionsNotificationAlreadyOutstanding); |
|
524 } |
|
525 else |
|
526 { |
|
527 iNotifyConnectionsChangeMsg = aMessage; |
|
528 // Check the connection history for any more recent items than that we |
|
529 // currently know about. If our pointer into the connection history |
|
530 // isn't pointing at the 'current' item, we can complete the |
|
531 // notification immediately and move the pointer up. |
|
532 if ( !iServer.ConnectionHistoryPointerAtLatest(Id()) ) |
|
533 { |
|
534 CompleteClient(iNotifyConnectionsChangeMsg, KErrNone); |
|
535 iServer.SetConnectionHistoryPointer(Id()); |
|
536 } |
|
537 } |
|
538 } |
|
539 |
|
540 void CRemConSession::NotifyConnectionsChangeCancel(const RMessage2& aMessage) |
|
541 { |
|
542 LOG_FUNC; |
|
543 |
|
544 // Check we've had our features set... |
|
545 if (!ClientAvailable()) |
|
546 { |
|
547 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicClientFeaturesNotSet); |
|
548 return; |
|
549 } |
|
550 |
|
551 // See comments in ConnectBearerCancel. |
|
552 if ( iNotifyConnectionsChangeMsg.Handle() ) |
|
553 { |
|
554 CompleteClient(iNotifyConnectionsChangeMsg, KErrCancel); |
|
555 } |
|
556 CompleteClient(aMessage, KErrNone); |
|
557 } |
|
558 |
|
559 CRemConInterfaceDetailsArray* CRemConSession::ExtractInterestedAPIsL(const RMessage2& aMessage) |
|
560 { |
|
561 LOG_FUNC; |
|
562 |
|
563 CRemConInterfaceDetailsArray* result; |
|
564 |
|
565 RBuf8 buf; |
|
566 buf.CreateL(aMessage.GetDesLengthL(0)); |
|
567 CleanupClosePushL(buf); |
|
568 |
|
569 aMessage.ReadL(0, buf); |
|
570 RDesReadStream ipcStream(buf); |
|
571 |
|
572 result = CRemConInterfaceDetailsArray::InternalizeL(ipcStream); |
|
573 |
|
574 ipcStream.Close(); |
|
575 CleanupStack::PopAndDestroy(&buf); |
|
576 |
|
577 return result; |
|
578 } |
|
579 |
|
580 TBool CRemConSession::DoGetSendInfoLC(const RMessage2& aMessage, |
|
581 TUid& aInterfaceUid, |
|
582 TUint& aOperationId, |
|
583 TRemConMessageSubType& aMessageSubType, |
|
584 RBuf8& aSendDes) |
|
585 { |
|
586 // Get the data the client wants to send. |
|
587 aInterfaceUid = TUid::Uid(aMessage.Int0()); |
|
588 LOG1(_L("\taInterfaceUid = 0x%08x"), aInterfaceUid); |
|
589 |
|
590 if (aMessage.GetDesLengthL(1) != sizeof(TOperationInformation)) |
|
591 { |
|
592 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBadDescriptor); |
|
593 return EFalse; |
|
594 } |
|
595 |
|
596 TPckgBuf<TOperationInformation> opInfoPckg; |
|
597 |
|
598 TInt err= aMessage.Read( |
|
599 1, // location of the descriptor in the client's message (as we expect them to have set it up) |
|
600 opInfoPckg, // descriptor to write to from client memory space |
|
601 0 // offset into our descriptor to put the client's data |
|
602 ); |
|
603 |
|
604 if ( err != KErrNone ) |
|
605 { |
|
606 LOG1(_L("\taMessage.Read = %d"), err); |
|
607 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBadDescriptor); |
|
608 return EFalse; |
|
609 } |
|
610 |
|
611 aOperationId = opInfoPckg().iOperationId; |
|
612 LOG1(_L("\taOperationId = 0x%02x"), aOperationId); |
|
613 |
|
614 aMessageSubType = opInfoPckg().iMessageSubType; |
|
615 LOG1(_L("\taMessageSubType = 0x%02x"), aMessageSubType); |
|
616 |
|
617 const TUint dataLength = (TUint)aMessage.GetDesLengthL(3); |
|
618 LOG1(_L("\tdataLength = %d"), dataLength); |
|
619 |
|
620 // If the client wanted to send some operation-associated data, read it |
|
621 // from them. |
|
622 if ( dataLength != 0 ) |
|
623 { |
|
624 aSendDes.CreateL(dataLength); |
|
625 TInt err = aMessage.Read( |
|
626 3, // location of the descriptor in the client's message (as we expect them to have set it up) |
|
627 aSendDes, // descriptor to write to from client memory space |
|
628 0 // offset into our descriptor to put the client's data |
|
629 ); |
|
630 // NB We don't do LEAVEIFERRORL(aMessage.Read) because a bad client |
|
631 // descriptor is a panicking offence for them, not an 'error the |
|
632 // request' offence. |
|
633 if ( err != KErrNone ) |
|
634 { |
|
635 LOG1(_L("\taMessage.Read = %d"), err); |
|
636 aSendDes.Close(); |
|
637 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBadDescriptor); |
|
638 return EFalse; |
|
639 } |
|
640 } |
|
641 CleanupClosePushL(aSendDes); |
|
642 return ETrue; |
|
643 } |
|
644 |
|
645 void CRemConSession::GoConnectionOriented(const RMessage2& aMessage) |
|
646 { |
|
647 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBadType); |
|
648 } |
|
649 |
|
650 void CRemConSession::GoConnectionless(const RMessage2& aMessage) |
|
651 { |
|
652 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBadType); |
|
653 } |
|
654 |
|
655 void CRemConSession::ConnectBearer(const RMessage2& aMessage) |
|
656 { |
|
657 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBadType); |
|
658 } |
|
659 |
|
660 void CRemConSession::ConnectBearerCancel(const RMessage2& aMessage) |
|
661 { |
|
662 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBadType); |
|
663 } |
|
664 |
|
665 void CRemConSession::DisconnectBearer(const RMessage2& aMessage) |
|
666 { |
|
667 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBadType); |
|
668 } |
|
669 |
|
670 void CRemConSession::DisconnectBearerCancel(const RMessage2& aMessage) |
|
671 { |
|
672 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBadType); |
|
673 } |
|
674 |
|
675 void CRemConSession::SendNotify(const RMessage2& aMessage) |
|
676 { |
|
677 PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBadType); |
|
678 } |
|
679 |
|
680 void CRemConSession::ConnectionsChanged() |
|
681 { |
|
682 LOG_FUNC; |
|
683 |
|
684 LOG1(_L("\tiInGetConnectionsProcedure = %d"), iInGetConnectionsProcedure); |
|
685 // Only update the connections history pointer if we're not in the middle |
|
686 // of a 'GetConnections' procedure. |
|
687 if ( !iInGetConnectionsProcedure ) |
|
688 { |
|
689 iServer.SetConnectionHistoryPointer(Id()); |
|
690 } |
|
691 LOG1(_L("\tiNotifyConnectionsChangeMsg.Handle = %d"), iNotifyConnectionsChangeMsg.Handle()); |
|
692 if ( iNotifyConnectionsChangeMsg.Handle() ) |
|
693 { |
|
694 CompleteClient(iNotifyConnectionsChangeMsg, KErrNone); |
|
695 } |
|
696 } |
|
697 |
|
698 void CRemConSession::CompleteSend() |
|
699 { |
|
700 LOG_FUNC; |
|
701 LOG2(_L("\tiNumRemotes = %d, iSendError = %d"), iNumRemotes, iSendError); |
|
702 |
|
703 ASSERT_DEBUG(NumRemotesToTry() == 0); |
|
704 |
|
705 if (iSending == ESendingReliable) |
|
706 { |
|
707 if ( iSendError == KErrNone ) |
|
708 { |
|
709 TPckg<TUint> count(iNumRemotes); |
|
710 // 2 is the slot in the client's message for the number of remotes the |
|
711 // message got sent to. |
|
712 iSendError = iSendMsg.Write(2, count); |
|
713 } |
|
714 CompleteClient(iSendMsg, iSendError); |
|
715 } |
|
716 |
|
717 ASSERT_DEBUG(iSendQueue); |
|
718 if (!iSendQueue->IsEmpty()) |
|
719 { |
|
720 ASSERT_DEBUG(iSendNextCallBack); |
|
721 iSendNextCallBack->CallBack(); |
|
722 } |
|
723 iSending = ENotSending; |
|
724 } |
|
725 |
|
726 void CRemConSession::CompleteSendNotify() |
|
727 { |
|
728 LOG_FUNC; |
|
729 LOG1(_L("\tiSendError = %d"), iSendError); |
|
730 |
|
731 if (iSending == ESendingReliable) |
|
732 { |
|
733 CompleteClient(iSendMsg, iSendError); |
|
734 } |
|
735 |
|
736 ASSERT_DEBUG(iSendQueue); |
|
737 if (!iSendQueue->IsEmpty()) |
|
738 { |
|
739 ASSERT_DEBUG(iSendNextCallBack); |
|
740 iSendNextCallBack->CallBack(); |
|
741 } |
|
742 iSending = ENotSending; |
|
743 } |
|
744 |
|
745 void CRemConSession::PanicSend(TRemConClientPanic aCode) |
|
746 { |
|
747 LOG_FUNC; |
|
748 LOG1(_L("\taCode = %d"), aCode); |
|
749 |
|
750 PANIC_MSG(iSendMsg, KRemConClientPanicCat, aCode); |
|
751 } |
|
752 |
|
753 TInt CRemConSession::WriteMessageToClient(const CRemConMessage& aMsg) |
|
754 { |
|
755 LOG_FUNC; |
|
756 |
|
757 ASSERT_DEBUG(SupportedMessage(aMsg)); |
|
758 ASSERT_DEBUG(iReceiveMsg.Handle()); |
|
759 TRAPD(err, WriteMessageToClientL(aMsg)); |
|
760 CompleteClient(iReceiveMsg, err); |
|
761 |
|
762 LOG1(_L("\terr = %d"), err); |
|
763 return err; |
|
764 } |
|
765 |
|
766 void CRemConSession::WriteMessageToClientL(const CRemConMessage& aMsg) |
|
767 { |
|
768 LOG_FUNC; |
|
769 |
|
770 //check if our client is interested in this API |
|
771 //Only need to check commands because it is safe to assume that we are interested |
|
772 //in the response if we have sent out a command. |
|
773 if(aMsg.MsgType() == ERemConCommand && !FindInterfaceByUid(aMsg.InterfaceUid())) |
|
774 { |
|
775 //The server will clean up the resource allocated for this msg |
|
776 LEAVEL(KErrArgument); |
|
777 } |
|
778 |
|
779 // This logging code left in for maintenance. |
|
780 //LOG1(_L("\t\tOperationData = \"%S\""), &aMsg.OperationData()); |
|
781 |
|
782 TRemConClientReceivePackage receivePackage; |
|
783 receivePackage.iInterfaceUid = aMsg.InterfaceUid(); |
|
784 receivePackage.iOperationId = aMsg.OperationId(); |
|
785 receivePackage.iMessageSubType = aMsg.MsgSubType(); |
|
786 receivePackage.iRemoteAddress = aMsg.Addr(); |
|
787 |
|
788 TPckgC<TRemConClientReceivePackage> recPckg(receivePackage); |
|
789 LEAVEIFERRORL(iReceiveMsg.Write(0, recPckg)); |
|
790 |
|
791 // Note that we do not panic the client if their descriptor is not |
|
792 // big enough to hold the operation-specific data. If we did, then |
|
793 // a buggy remote could take down a client of RemCon. Just error |
|
794 // the client instead. |
|
795 LEAVEIFERRORL(iReceiveMsg.Write(1, aMsg.OperationData())); |
|
796 } |
|
797 |
|
798 TInt CRemConSession::SupportedInterfaces(RArray<TUid>& aUids) |
|
799 { |
|
800 LOG_FUNC; |
|
801 |
|
802 aUids.Reset(); |
|
803 return AppendSupportedInterfaces(aUids); |
|
804 } |
|
805 |
|
806 TInt CRemConSession::AppendSupportedInterfaces(RArray<TUid>& aUids) |
|
807 { |
|
808 LOG_FUNC; |
|
809 ASSERT_DEBUG(iInterestedAPIs); |
|
810 TInt err = KErrNone; |
|
811 |
|
812 TInt count = iInterestedAPIs->Array().Count(); |
|
813 for(TInt i=0; (i<count) && (err == KErrNone); i++) |
|
814 { |
|
815 CRemConInterfaceDetails* details = iInterestedAPIs->Array()[i]; |
|
816 ASSERT_DEBUG(details); |
|
817 err = aUids.Append(details->Uid()); |
|
818 } |
|
819 |
|
820 return err; |
|
821 } |
|
822 |
|
823 TInt CRemConSession::SupportedBulkInterfaces(RArray<TUid>& aUids) |
|
824 { |
|
825 LOG_FUNC; |
|
826 |
|
827 aUids.Reset(); |
|
828 return AppendSupportedBulkInterfaces(aUids); |
|
829 } |
|
830 |
|
831 TInt CRemConSession::AppendSupportedBulkInterfaces(RArray<TUid>& aUids) |
|
832 { |
|
833 LOG_FUNC; |
|
834 ASSERT_DEBUG(iInterestedAPIs); |
|
835 TInt err = KErrNone; |
|
836 |
|
837 TInt count = iInterestedAPIs->Array().Count(); |
|
838 for(TInt i=0; (i<count) && (err == KErrNone); i++) |
|
839 { |
|
840 CRemConInterfaceDetails* details = iInterestedAPIs->Array()[i]; |
|
841 ASSERT_DEBUG(details); |
|
842 if(details->IsBulk()) |
|
843 { |
|
844 err = aUids.Append(details->Uid()); |
|
845 } |
|
846 } |
|
847 |
|
848 return err; |
|
849 } |
|
850 |
|
851 TInt CRemConSession::SupportedOperations(TUid aInterfaceUid, RArray<TUint>& aOperations) |
|
852 { |
|
853 LOG_FUNC; |
|
854 TInt err = KErrNotSupported; |
|
855 CRemConInterfaceDetails* details = FindInterfaceByUid(aInterfaceUid); |
|
856 |
|
857 if(details) |
|
858 { |
|
859 TRAP(err, details->GetRemConInterfaceFeaturesL(aOperations)); |
|
860 } |
|
861 return err; |
|
862 } |
|
863 |
|
864 CRemConInterfaceDetails* CRemConSession::FindInterfaceByUid(TUid aUid) const |
|
865 { |
|
866 LOG_FUNC; |
|
867 ASSERT_DEBUG(iInterestedAPIs); |
|
868 TInt count = iInterestedAPIs->Array().Count(); |
|
869 for(TInt ix=0; ix<count; ++ix) |
|
870 { |
|
871 CRemConInterfaceDetails* details = iInterestedAPIs->Array()[ix]; |
|
872 ASSERT_DEBUG(details); |
|
873 if(details->Uid() == aUid) |
|
874 { |
|
875 return details; |
|
876 } |
|
877 } |
|
878 return NULL; |
|
879 } |
|
880 |
|
881 void CRemConSession::DoSendNext() |
|
882 { |
|
883 LOG_FUNC; |
|
884 |
|
885 ASSERT_DEBUG(iSendQueue); |
|
886 CRemConMessage& msg = iSendQueue->First(); |
|
887 iSendQueue->Remove(msg); |
|
888 SendToServer(msg); |
|
889 } |
|
890 |
|
891 TInt CRemConSession::SendNextCb(TAny *aThis) |
|
892 { |
|
893 LOG_STATIC_FUNC; |
|
894 |
|
895 static_cast<CRemConSession*>(aThis)->DoSendNext(); |
|
896 return KErrNone; |
|
897 } |
|
898 |