|
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 // |
|
15 |
|
16 /** |
|
17 @file |
|
18 @internalComponent |
|
19 */ |
|
20 |
|
21 #include <bluetooth/logger.h> |
|
22 #include <comms-infras/eintsock.h> |
|
23 #include "CBnepBridge.h" |
|
24 #include "CBnepChannelController.h" |
|
25 #include "CBnepLink.h" |
|
26 #include "RBnepSetupConnectionRequestControl.h" |
|
27 #include "RBnepSetupConnectionResponseControl.h" |
|
28 #include "bneputils.h" |
|
29 #include "RBnepFilterNetTypeSetRequestControl.h" |
|
30 #include "RBnepFilterNetTypeResponseControl.h" |
|
31 #include "RBnepFilterMultiAddrSetRequestControl.h" |
|
32 #include "RBnepFilterMultiAddrResponseControl.h" |
|
33 |
|
34 #ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY |
|
35 #include "panmessages.h" |
|
36 |
|
37 using namespace ESock; |
|
38 using namespace Messages; |
|
39 |
|
40 #ifdef ESOCK_EXTLOG_ACTIVE |
|
41 _LIT8(KBnepSubTag, "bnep"); |
|
42 #endif |
|
43 |
|
44 #endif |
|
45 // SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY |
|
46 |
|
47 #ifdef __FLOG_ACTIVE |
|
48 _LIT8(KLogComponent, LOG_COMPONENT_PAN_BNEP); |
|
49 #endif |
|
50 |
|
51 /** |
|
52 Implement cleanup for an RBnepControl object allocated on the heap. |
|
53 */ |
|
54 void CleanupControl(TAny* aControl) |
|
55 { |
|
56 LOG_STATIC_FUNC |
|
57 RBnepControl* control = static_cast<RBnepControl*>(aControl); |
|
58 control->Free(); |
|
59 delete control; |
|
60 } |
|
61 |
|
62 #ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY |
|
63 CBnepChannelController::CBnepChannelController (const TNodeId& aNotify, CPacketDriverOwner& aPktDrvOwner) |
|
64 : iPanConnectionNotify(aNotify), iPktDrvOwner(aPktDrvOwner) |
|
65 { |
|
66 NM_LOG_NODE_CREATE(KBnepSubTag, CBnepChannelController); |
|
67 CONNECT_LOGGER |
|
68 LOG_FUNC |
|
69 iPktDrvOwner.Open(); |
|
70 } |
|
71 |
|
72 #else |
|
73 // !SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY |
|
74 CBnepChannelController::CBnepChannelController (MPanConnectionNotify& aNotify) |
|
75 :iNotify(aNotify) |
|
76 { |
|
77 LOG_FUNC |
|
78 } |
|
79 #endif |
|
80 // SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY |
|
81 |
|
82 CBnepChannelController::~CBnepChannelController() |
|
83 { |
|
84 /** |
|
85 Close all objects that we're reponsible for - including the socket. |
|
86 @internalComponent |
|
87 */ |
|
88 LOG_FUNC |
|
89 if(iLink) |
|
90 { |
|
91 delete iLink; |
|
92 // iLink must be reset to zero after deletion to prevent a later panic. |
|
93 iLink = NULL; |
|
94 } |
|
95 |
|
96 |
|
97 iProceedCallBack->Cancel(); |
|
98 delete iProceedCallBack; |
|
99 |
|
100 #ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY |
|
101 NM_LOG_NODE_DESTROY(KBnepSubTag, CBnepChannelController); |
|
102 CLOSE_LOGGER |
|
103 iPktDrvOwner.Close(); |
|
104 #endif |
|
105 } |
|
106 |
|
107 void CBnepChannelController::BnepRoleRequestFromLocalDevice (TBluetoothPanRole aRequestedLocalRole, TBluetoothPanRole aRequestedRemoteRole) |
|
108 { |
|
109 /** |
|
110 Call from the agent to request that we set a certain role. |
|
111 @internalComponent |
|
112 */ |
|
113 LOG_FUNC |
|
114 iLink->SuspendDataTransfer(); |
|
115 |
|
116 TRAPD(err, CreateAndQueueConnectionSetupRequestL(aRequestedLocalRole, aRequestedRemoteRole)); |
|
117 if(!err) |
|
118 { |
|
119 iLink->Proceed(); |
|
120 } |
|
121 else |
|
122 { |
|
123 iLink->ResumeDataTransfer(); |
|
124 } |
|
125 } |
|
126 |
|
127 void CBnepChannelController::SetUplinkAccessAllowedForBnepLink(TBool aAllowed) |
|
128 { |
|
129 iLink->SetUplinkAccessAllowedForBnepLink(aAllowed); |
|
130 } |
|
131 |
|
132 |
|
133 /** |
|
134 Response to a remote request for a given set of roles -- generate control |
|
135 packet and pass it back to the remote device. |
|
136 @internalComponent |
|
137 */ |
|
138 void CBnepChannelController::BnepRoleResponseFromLocalDevice (TBnepSetupConnectionResponseMessage aRoleResponseCode) |
|
139 { |
|
140 // This may fail if it cannot allocate the response. However, |
|
141 // we will just continue and do the same as if it had succeeded |
|
142 // as we won't get another prompt to continue. The remote may |
|
143 // resend its ConnectionSetupRequest when we don't respond, or |
|
144 // may disconnect the link. |
|
145 TRAP_IGNORE(CreateAndQueueConnectionSetupResponseL(aRoleResponseCode)); |
|
146 |
|
147 // All control processing has been suspended while awaiting this event, |
|
148 // so we can now free things up again. |
|
149 SetAwaitingResponse(EFalse); |
|
150 iLink->ResumeDataTransfer(); // enable the link for data transfer |
|
151 |
|
152 if(EOperationSuccessful == aRoleResponseCode) |
|
153 { |
|
154 //In case this is the first negotiation, we only want to trigger LinkLayerUp if the |
|
155 //negotiation is successful |
|
156 iLink->RemoteDeviceReady(); |
|
157 } |
|
158 |
|
159 //If iProceedCallBack is already active then BNEP must be processing the next command inside |
|
160 //the same frame. We don't have to don't anything here. The callback will complete when all the |
|
161 //commands are processed. |
|
162 if(!iProceedCallBack->IsActive()) |
|
163 { |
|
164 __ASSERT_DEBUG(!iProceedCallBack->IsAdded(), BnepUtils::Panic(Bnep::ECallBackAlreadyAdded)); |
|
165 CActiveScheduler::Add(iProceedCallBack); |
|
166 iProceedCallBack->CallBack(); |
|
167 } |
|
168 } |
|
169 |
|
170 TInt CBnepChannelController::ProceedCb(TAny* aPtr) |
|
171 { |
|
172 static_cast<CBnepChannelController*>(aPtr)->Proceed(); |
|
173 |
|
174 return KErrNone; |
|
175 } |
|
176 |
|
177 void CBnepChannelController::Proceed() |
|
178 { |
|
179 iProceedCallBack->Deque(); |
|
180 // Carry on processing any outstanding controls and data transfers. |
|
181 iLink->Proceed(); |
|
182 } |
|
183 |
|
184 /** |
|
185 Close this channel. This has the effect of deleting the coupled CBnepLink. |
|
186 @internalComponent |
|
187 */ |
|
188 void CBnepChannelController::Close () |
|
189 { |
|
190 LOG_FUNC |
|
191 delete this; |
|
192 } |
|
193 |
|
194 /** |
|
195 Create the channel controller and the link object. |
|
196 Ownership of all these objects is a little strange -- the channel controller |
|
197 owns the underlying link, and the channel controller itself is owned by the |
|
198 agent (in another dll...). Destruction paths can therefore look a little |
|
199 confusing. |
|
200 @internalComponent |
|
201 */ |
|
202 void CBnepChannelController::ConstructL (CBnepBridge& aBridge, RInternalSocket& aConnectedSocket) |
|
203 { |
|
204 LOG_FUNC |
|
205 iLink = CBnepLink::NewL(aBridge, aConnectedSocket, *this); |
|
206 |
|
207 iProceedCallBack = new (ELeave) CAsyncCallBack(KBnepProceedCallBackPriority); |
|
208 TCallBack proceedCb(ProceedCb, this); |
|
209 iProceedCallBack->Set(proceedCb); |
|
210 //Remove the callback from active scheduler whenever it is not used because it is |
|
211 //used only in role request and has a high priority. |
|
212 iProceedCallBack->Deque(); |
|
213 } |
|
214 |
|
215 /** |
|
216 Having received a SetupConnectionRequest from a remote device, the controller |
|
217 must hand off the request to the agent. This may be asynchronous, in which case |
|
218 the method returns immediately, having suspended further control processing |
|
219 until the agent responds. However, the agent may call back into the controller |
|
220 synchronously. This has implications for how controls are processed by the link. |
|
221 @internalComponent |
|
222 */ |
|
223 void CBnepChannelController::Handle (RBnepSetupConnectionRequestControl* aSetupRequest) |
|
224 { |
|
225 LOG_FUNC |
|
226 __ASSERT_DEBUG(aSetupRequest,BnepUtils::Panic(Bnep::ENullPointer)); |
|
227 if(aSetupRequest) |
|
228 { |
|
229 TUUID localRole; |
|
230 TUUID remoteRole; |
|
231 TInt err1 = aSetupRequest->LocalRole(localRole); |
|
232 TInt err2 = aSetupRequest->RemoteRole(remoteRole); |
|
233 // The control object must be freed and deleted now, before the request is |
|
234 // passed out, to ensure that the controller is re-entrant and doesn't leak memory. |
|
235 aSetupRequest->Free(); |
|
236 delete aSetupRequest; |
|
237 if(!err1 && !err2) |
|
238 { |
|
239 // Suspend further link processing for the time being. |
|
240 SetAwaitingResponse(ETrue); |
|
241 |
|
242 #ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY |
|
243 TPanMessage::TRoleRequestFromRemoteDevice msg(localRole, remoteRole); |
|
244 RClientInterface::OpenPostMessageClose(Id(),iPanConnectionNotify,msg); |
|
245 #else |
|
246 iNotify.BnepRoleRequestFromRemoteDevice(localRole, remoteRole); |
|
247 #endif |
|
248 } |
|
249 else |
|
250 { |
|
251 // The UUIDSize is not within spec, so we need to tell the remote end. |
|
252 // This may leave if we fail to allocate the new response. Unfortunately |
|
253 // there's not a lot we can do in that circumstance. Just drop our response |
|
254 // and wait for the remote to timeout. |
|
255 TRAP_IGNORE(CreateAndQueueConnectionSetupResponseL(EInvalidServiceUuidSize)); |
|
256 } |
|
257 } |
|
258 } |
|
259 |
|
260 /** |
|
261 The remote device has sent a response to our Setup request. If it has |
|
262 been successful we can resume data transfer operations on the link. |
|
263 The agent is notified of the response. |
|
264 @param aSetupResponse A control containing the remote end's response to our |
|
265 request to set up a connection. |
|
266 @internalComponent |
|
267 */ |
|
268 void CBnepChannelController::Handle (RBnepSetupConnectionResponseControl* aSetupResponse) |
|
269 { |
|
270 LOG_FUNC |
|
271 __ASSERT_DEBUG(aSetupResponse,BnepUtils::Panic(Bnep::ENullPointer)); |
|
272 if(aSetupResponse) |
|
273 { |
|
274 TBnepSetupConnectionResponseMessage responseCode = EOperationSuccessful; |
|
275 TRAPD(err,aSetupResponse->ConnectionSetupResponseL(responseCode)); |
|
276 |
|
277 if(!err) |
|
278 { |
|
279 iLink->ResumeDataTransfer(); |
|
280 if(EOperationSuccessful == responseCode) |
|
281 { |
|
282 //In case this is the first negotiation, we only want to trigger LinkLayerUp if the |
|
283 //negotiation is successful |
|
284 iLink->RemoteDeviceReady(); |
|
285 } |
|
286 // The control object must be freed and deleted now, before the request is |
|
287 // passed out, to ensure that the controller is re-entrant and doesn't leak memory. |
|
288 aSetupResponse->Free(); |
|
289 delete aSetupResponse; |
|
290 |
|
291 #ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY |
|
292 TPanMessage::TRoleResponseFromRemoteDevice msg(responseCode); |
|
293 RClientInterface::OpenPostMessageClose(Id(),iPanConnectionNotify,msg); |
|
294 #else |
|
295 iNotify.BnepRoleResponseFromRemoteDevice(responseCode); |
|
296 #endif |
|
297 } |
|
298 else |
|
299 { |
|
300 // They sent us bobbins, just drop it. |
|
301 aSetupResponse->Free(); |
|
302 delete aSetupResponse; |
|
303 } |
|
304 } |
|
305 } |
|
306 |
|
307 /** |
|
308 Handle an attempt, by a remote device, to set network packet type filters. |
|
309 @param aFilterNetTypeSetRequest A control containing a network packet type |
|
310 filter set message. |
|
311 @internalComponent |
|
312 */ |
|
313 void CBnepChannelController::Handle (RBnepFilterNetTypeSetRequestControl* aFilterNetTypeSetRequest) |
|
314 { |
|
315 LOG_FUNC |
|
316 __ASSERT_DEBUG(aFilterNetTypeSetRequest,BnepUtils::Panic(Bnep::ENullPointer)); |
|
317 |
|
318 if(aFilterNetTypeSetRequest) |
|
319 { |
|
320 TFilterNetTypeResponse response; |
|
321 // Specification requires that we check the validity of the filter request |
|
322 // before it is implementeted in BNEP. |
|
323 TUint16 typeListSize ; |
|
324 TInt err1 = aFilterNetTypeSetRequest->NetworkProtocolTypeListLength(typeListSize); |
|
325 if(!err1) |
|
326 { |
|
327 LOG1(_L8("NetworkProtocolTypeListLength = %d"),typeListSize); |
|
328 if((2*KMaxNetTypeFilters*KSizeOfNetType) < typeListSize) |
|
329 { |
|
330 response = EFilterNetTypeTooManyFilters; |
|
331 } |
|
332 else |
|
333 { |
|
334 CNetTypeFilterTable* netTypeFilterTable = new CNetTypeFilterTable; |
|
335 |
|
336 if(netTypeFilterTable) |
|
337 { |
|
338 TUint index = 0; |
|
339 do |
|
340 { |
|
341 TUint16 startValue; |
|
342 TUint16 endValue; |
|
343 err1 = aFilterNetTypeSetRequest->NetworkProtocolTypeRange(startValue, endValue, index); |
|
344 index++; |
|
345 LOG2(_L8("Net type filter request: startValue: %d , endValue: %d"),startValue, endValue); |
|
346 if( KErrGeneral == err1 ) |
|
347 { |
|
348 // This one is because the advertised length doesn't match what's |
|
349 // actually in the packet. |
|
350 response = EFilterNetTypeUnsupportedRequest; |
|
351 break; |
|
352 } |
|
353 if( KErrArgument == err1 ) |
|
354 { |
|
355 // This one means they've somehow got their start and end |
|
356 // addresses in the wrong order. |
|
357 response = EFilterNetTypeInvalidNetworkingProtocolTypeRange; |
|
358 break; |
|
359 } |
|
360 if(KErrNotFound != err1) |
|
361 { |
|
362 TInt err2 = netTypeFilterTable->Insert(startValue, endValue); |
|
363 if( KErrArgument == err2 ) |
|
364 { |
|
365 // This one means they've somehow got their start and end |
|
366 // addresses in the wrong order, and we didn't catch it earlier. |
|
367 response = EFilterNetTypeInvalidNetworkingProtocolTypeRange; |
|
368 break; |
|
369 } |
|
370 if( KErrTooBig == err2 ) |
|
371 { |
|
372 // This one means that they've asked for more filters than |
|
373 // we currently support. |
|
374 response = EFilterNetTypeTooManyFilters; |
|
375 break; |
|
376 } |
|
377 response = EFilterNetTypeOperationSuccessful; |
|
378 } |
|
379 else |
|
380 { |
|
381 netTypeFilterTable->Reset(); // This is going to be an empty table |
|
382 response = EFilterNetTypeOperationSuccessful; // This is supported |
|
383 err1 = KErrEof; // Nothing more to be done |
|
384 } |
|
385 }while( KErrEof != err1 ); |
|
386 if(EFilterNetTypeOperationSuccessful == response) |
|
387 { |
|
388 // We can now adopt the new filter table. |
|
389 // The link will own it and be responsible for it's deletion. |
|
390 iLink->Install(netTypeFilterTable); |
|
391 } |
|
392 else |
|
393 { |
|
394 // That request failed for some reason, so drop the new table. |
|
395 delete netTypeFilterTable; |
|
396 } |
|
397 } |
|
398 else |
|
399 { |
|
400 // If we get here, then we have failed to construct a CNetTypeFilterTable. |
|
401 // There is nothing in the protocol that allows us to pass back a generic |
|
402 // "Request Unsuccessful" message, so the nearest we could come up with was |
|
403 // "Too Many Filters", which is a bit more truthful that "Unsupported Request". |
|
404 response = EFilterNetTypeTooManyFilters; |
|
405 } |
|
406 } |
|
407 } |
|
408 else |
|
409 { |
|
410 response = EFilterNetTypeUnsupportedRequest; |
|
411 } |
|
412 // The control object must be freed and deleted now, before the response is |
|
413 // generated, to ensure that the controller is re-entrant and doesn't leak memory. |
|
414 aFilterNetTypeSetRequest->Free(); |
|
415 delete aFilterNetTypeSetRequest; |
|
416 |
|
417 // This may leave if we fail to allocate the new response. Unfortunately |
|
418 // there's not a lot we can do in that circumstance. Just drop our response |
|
419 // and wait for the remote to timeout. |
|
420 TRAP_IGNORE(CreateAndQueueFilterNetTypeResponseL(response)); |
|
421 } |
|
422 } |
|
423 |
|
424 /** |
|
425 This overloaded method is a placeholder for the code that will handle |
|
426 responses from the remote end after BNEP hass emitted a Filter Net Type |
|
427 Request.This version of BNEP does not emit these requests. |
|
428 @internalComponent |
|
429 */ |
|
430 void CBnepChannelController::Handle (RBnepFilterNetTypeResponseControl* aFilterNetTypeResponse) |
|
431 { |
|
432 LOG_FUNC |
|
433 __ASSERT_DEBUG(aFilterNetTypeResponse,BnepUtils::Panic(Bnep::ENullPointer)); |
|
434 // We don't do anything with this yet |
|
435 if(aFilterNetTypeResponse) |
|
436 { |
|
437 aFilterNetTypeResponse->Free(); |
|
438 delete aFilterNetTypeResponse; |
|
439 } |
|
440 } |
|
441 |
|
442 /** |
|
443 Handle an attempt by a remote device to set multicast adddress filters |
|
444 @internalComponent |
|
445 */ |
|
446 void CBnepChannelController::Handle (RBnepFilterMultiAddrSetRequestControl* aFilterMultiAddrSetRequest) |
|
447 { |
|
448 LOG_FUNC |
|
449 __ASSERT_DEBUG(aFilterMultiAddrSetRequest,BnepUtils::Panic(Bnep::ENullPointer)); |
|
450 |
|
451 if(aFilterMultiAddrSetRequest) |
|
452 { |
|
453 TInt err1; |
|
454 TBnepBTDevAddr startAddr; |
|
455 TBnepBTDevAddr endAddr; |
|
456 TFilterMultiAddrResponse response; |
|
457 // Specification requires that we check the validity of the filter request |
|
458 // before it is implementeted in BNEP. |
|
459 TUint16 typeListSize = aFilterMultiAddrSetRequest->MulticastAddressListLength(); |
|
460 LOG1(_L8("MulticastAddressListLength = %d"),typeListSize); |
|
461 if((2*KMaxMultiAddrFilters*KSizeOfMultiAddr) < typeListSize) |
|
462 { |
|
463 LOG(_L8("Too many filters")); |
|
464 response = EFilterMultiAddrTooManyFilters; |
|
465 } |
|
466 else |
|
467 { |
|
468 CMultiAddrFilterTable* multiAddrFilterTable = new CMultiAddrFilterTable; |
|
469 |
|
470 if(multiAddrFilterTable) |
|
471 { |
|
472 TUint index = 0; |
|
473 do |
|
474 { |
|
475 err1 = aFilterMultiAddrSetRequest->MultiAddrRange(startAddr, endAddr, index); |
|
476 if(KErrArgument == err1) |
|
477 { |
|
478 response = EFilterMultiAddrUnsupportedRequest; |
|
479 break; // Stop processing this request |
|
480 } |
|
481 if(KErrNotFound != err1) |
|
482 { |
|
483 TInt err2 = multiAddrFilterTable->Insert(startAddr, endAddr); |
|
484 if( KErrArgument == err2 ) |
|
485 { |
|
486 response = EFilterMultiAddrUnsupportedRequest; |
|
487 break; // Stop processing this request |
|
488 } |
|
489 if( KErrTooBig == err2 ) |
|
490 { |
|
491 response = EFilterMultiAddrTooManyFilters; |
|
492 break; // Stop processing this request |
|
493 } |
|
494 response = EFilterMultiAddrOperationSuccessful; // Must be good if we got here. |
|
495 ++index; |
|
496 } |
|
497 else |
|
498 { |
|
499 multiAddrFilterTable->Reset(); // This is going to be an empty table |
|
500 response = EFilterMultiAddrOperationSuccessful; // This is supported |
|
501 err1 = KErrEof; // Nothing more to be done |
|
502 } |
|
503 } while( KErrEof != err1 ); |
|
504 if(EFilterMultiAddrOperationSuccessful == response) |
|
505 { |
|
506 // We can adopt the new filter table. |
|
507 // The link will own it and be responsible for it's deletion. |
|
508 iLink->Install(multiAddrFilterTable); |
|
509 } |
|
510 else |
|
511 { |
|
512 // That request failed for some reason, so drop the new table unused. |
|
513 delete multiAddrFilterTable; |
|
514 } |
|
515 } |
|
516 else |
|
517 { |
|
518 // If we get here, then we have failed to construct a CMultiAddrFilterTable. |
|
519 // There is nothing in the protocol that allows us to pass back a generic |
|
520 // "Request Unsuccessful" message, so the nearest we could come up with was |
|
521 // "Too Many Filters", which is a bit more truthful that "Unsupported Request". |
|
522 response = EFilterMultiAddrTooManyFilters; |
|
523 } |
|
524 } |
|
525 // The control object must be freed and deleted now, before the request is |
|
526 // honoured, to ensure that the controller is re-entrant and doesn't leak memory. |
|
527 aFilterMultiAddrSetRequest->Free(); |
|
528 delete aFilterMultiAddrSetRequest; |
|
529 |
|
530 // This may leave if we fail to allocate the new response. Unfortunately |
|
531 // there's not a lot we can do in that circumstance. Just drop our response |
|
532 // and wait for the remote to timeout. |
|
533 TRAP_IGNORE(CreateAndQueueFilterMultiAddrResponseL(response)); |
|
534 } |
|
535 } |
|
536 |
|
537 /** |
|
538 This overloaded method is a placeholder for the code that will handle |
|
539 responses from the remote end after BNEP hass emitted a Multicast Address Filter |
|
540 Request.This version of BNEP does not emit these requests. |
|
541 @internalComponent |
|
542 */ |
|
543 void CBnepChannelController::Handle (RBnepFilterMultiAddrResponseControl* aFilterMultiAddrResponse) |
|
544 { |
|
545 LOG_FUNC |
|
546 __ASSERT_DEBUG(aFilterMultiAddrResponse,BnepUtils::Panic(Bnep::ENullPointer)); |
|
547 // We don't do anything with this yet. |
|
548 if(aFilterMultiAddrResponse) |
|
549 { |
|
550 aFilterMultiAddrResponse->Free(); |
|
551 delete aFilterMultiAddrResponse; |
|
552 } |
|
553 } |
|
554 |
|
555 /** |
|
556 Handle a control that we don't understand. |
|
557 @internalComponent |
|
558 */ |
|
559 void CBnepChannelController::HandleUnknownCommandPacket (RBnepControl* aControl) |
|
560 { |
|
561 LOG_FUNC |
|
562 __ASSERT_DEBUG(aControl,BnepUtils::Panic(Bnep::ENullPointer)); |
|
563 |
|
564 if(aControl) |
|
565 { |
|
566 TUint8 controlType = static_cast<TUint8>(aControl->ControlType()); |
|
567 // The control object must be freed and deleted now, before the response is |
|
568 // generated, to ensure that the controller is re-entrant and doesn't leak memory. |
|
569 aControl->Free(); |
|
570 delete aControl; |
|
571 |
|
572 // This may leave if we fail to allocate the new response. Unfortunately |
|
573 // there's not a lot we can do in that circumstance. Just drop our response |
|
574 // and wait for the remote to timeout. |
|
575 TRAP_IGNORE(CreateAndQueueNotUnderstoodResponseL(controlType)); |
|
576 } |
|
577 } |
|
578 |
|
579 void CBnepChannelController::CreateAndQueueConnectionSetupRequestL(TBluetoothPanRole aRequestedLocalRole, TBluetoothPanRole aRequestedRemoteRole) |
|
580 { |
|
581 LOG_FUNC |
|
582 |
|
583 RBnepSetupConnectionRequestControl* controlSetup = new(ELeave)RBnepSetupConnectionRequestControl(); |
|
584 CleanupStack::PushL(TCleanupItem(CleanupControl, controlSetup)); |
|
585 |
|
586 controlSetup->InitL(); |
|
587 |
|
588 TUUID localRole(aRequestedLocalRole); |
|
589 TUUID remoteRole(aRequestedRemoteRole); |
|
590 controlSetup->SetRolesL(localRole, remoteRole); |
|
591 |
|
592 CleanupStack::Pop(controlSetup); |
|
593 iLink->QueueOnOutput(controlSetup); |
|
594 } |
|
595 |
|
596 void CBnepChannelController::CreateAndQueueConnectionSetupResponseL(TBnepSetupConnectionResponseMessage aRoleResponseCode) |
|
597 { |
|
598 LOG_FUNC |
|
599 |
|
600 RBnepSetupConnectionResponseControl* responseControl = new(ELeave)RBnepSetupConnectionResponseControl(); |
|
601 CleanupStack::PushL(TCleanupItem(CleanupControl, responseControl)); |
|
602 |
|
603 responseControl->InitL(); |
|
604 responseControl->SetConnectionSetupResponseL(aRoleResponseCode); |
|
605 |
|
606 CleanupStack::Pop(responseControl); |
|
607 iLink->QueueOnOutput(responseControl); |
|
608 } |
|
609 |
|
610 void CBnepChannelController::CreateAndQueueNotUnderstoodResponseL(TUint8 aControlType) |
|
611 { |
|
612 LOG_FUNC |
|
613 |
|
614 RBnepNotUnderstoodResponseControl* responseControl = new(ELeave)RBnepNotUnderstoodResponseControl(); |
|
615 CleanupStack::PushL(TCleanupItem(CleanupControl, responseControl)); |
|
616 |
|
617 responseControl->InitL(); |
|
618 responseControl->SetUnknownControlType(aControlType); |
|
619 |
|
620 CleanupStack::Pop(responseControl); |
|
621 iLink->QueueOnOutput(responseControl); |
|
622 } |
|
623 |
|
624 void CBnepChannelController::CreateAndQueueFilterNetTypeResponseL(TFilterNetTypeResponse aResponse) |
|
625 { |
|
626 LOG_FUNC |
|
627 |
|
628 RBnepFilterNetTypeResponseControl* responseControl = new(ELeave)RBnepFilterNetTypeResponseControl(); |
|
629 CleanupStack::PushL(TCleanupItem(CleanupControl, responseControl)); |
|
630 |
|
631 responseControl->InitL(); |
|
632 responseControl->SetNetTypeResponseL(aResponse); |
|
633 |
|
634 CleanupStack::Pop(responseControl); |
|
635 iLink->QueueOnOutput(responseControl); |
|
636 } |
|
637 |
|
638 void CBnepChannelController::CreateAndQueueFilterMultiAddrResponseL(TFilterMultiAddrResponse aResponse) |
|
639 { |
|
640 LOG_FUNC |
|
641 |
|
642 RBnepFilterMultiAddrResponseControl* responseControl = new(ELeave)RBnepFilterMultiAddrResponseControl(); |
|
643 CleanupStack::PushL(TCleanupItem(CleanupControl, responseControl)); |
|
644 |
|
645 responseControl->InitL(); |
|
646 responseControl->SetMultiAddrResponseL(aResponse); |
|
647 |
|
648 CleanupStack::Pop(responseControl); |
|
649 iLink->QueueOnOutput(responseControl); |
|
650 } |
|
651 |
|
652 /** |
|
653 Create a command parser/channel controller for a specific BNEP link. |
|
654 The controller is owned by the agent objects. |
|
655 @param aBridge The packet router |
|
656 @param aConnectedSocket The socket to run the link over (already connected to the remote device) |
|
657 @internalComponent |
|
658 */ |
|
659 #ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY |
|
660 CBnepChannelController* CBnepChannelController::NewL (CBnepBridge& aBridge, RInternalSocket& aConnectedSocket, const TNodeId& aNotify, CPacketDriverOwner& aPktDrvOwner) |
|
661 { |
|
662 LOG_STATIC_FUNC |
|
663 CBnepChannelController* self = new(ELeave) CBnepChannelController(aNotify, aPktDrvOwner); |
|
664 CleanupStack::PushL(self); |
|
665 self->ConstructL(aBridge, aConnectedSocket); |
|
666 CleanupStack::Pop(self); |
|
667 return(self); |
|
668 } |
|
669 |
|
670 #else |
|
671 // !SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY |
|
672 CBnepChannelController* CBnepChannelController::NewL (CBnepBridge& aBridge, RInternalSocket& aConnectedSocket, MPanConnectionNotify& aNotify) |
|
673 { |
|
674 LOG_FUNC |
|
675 CBnepChannelController* self = new(ELeave) CBnepChannelController(aNotify); |
|
676 CleanupStack::PushL(self); |
|
677 self->ConstructL(aBridge, aConnectedSocket); |
|
678 CleanupStack::Pop(self); |
|
679 return(self); |
|
680 } |
|
681 #endif |
|
682 // SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY |
|
683 |
|
684 /** |
|
685 Process incoming BNEP control commands. |
|
686 This upcall is called repeatedly by the packet parsing code if multiple |
|
687 commands are present in the packet. |
|
688 @internalComponent |
|
689 */ |
|
690 void CBnepChannelController::Execute (RBnepControl* aControl) |
|
691 { |
|
692 LOG_FUNC |
|
693 __ASSERT_DEBUG(aControl,BnepUtils::Panic(Bnep::ENullPointer)); |
|
694 |
|
695 if(aControl) |
|
696 { |
|
697 switch (aControl->ControlType()) |
|
698 { |
|
699 case EBnepSetupConnectionRequestMessage: |
|
700 LOG1(_L8("CBnepChannelController[%x]: EBnepSetupConnectionRequestMessage"), this); |
|
701 Handle(static_cast<RBnepSetupConnectionRequestControl*>(aControl)); |
|
702 break; |
|
703 |
|
704 case EBnepSetupConnectionResponseMessage: |
|
705 LOG1(_L8("CBnepChannelController[%x]: EBnepSetupConnectionResponseMessage"), this); |
|
706 Handle(static_cast<RBnepSetupConnectionResponseControl*>(aControl)); |
|
707 break; |
|
708 |
|
709 case EBnepFilterNetTypeSetMsg: |
|
710 LOG1(_L8("CBnepChannelController[%x]: EBnepFilterNetTypeSetMsg"), this); |
|
711 Handle(static_cast<RBnepFilterNetTypeSetRequestControl*>(aControl)); |
|
712 break; |
|
713 |
|
714 case EBnepFilterNetTypeResponse: |
|
715 LOG1(_L8("CBnepChannelController[%x]: EBnepFilterNetTypeResponse"), this); |
|
716 Handle(static_cast<RBnepFilterNetTypeResponseControl*>(aControl)); |
|
717 break; |
|
718 |
|
719 case EBnepFilterMultiAddrSetMsg: |
|
720 LOG1(_L8("CBnepChannelController[%x]: EBnepFilterMultiAddrSetMsg"), this); |
|
721 Handle(static_cast<RBnepFilterMultiAddrSetRequestControl*>(aControl)); |
|
722 break; |
|
723 |
|
724 case EBnepFilterMultiAddrResponseMsg: |
|
725 LOG1(_L8("CBnepChannelController[%x]: EBnepFilterMultiAddrResponseMsg"), this); |
|
726 Handle(static_cast<RBnepFilterMultiAddrResponseControl*>(aControl)); |
|
727 break; |
|
728 |
|
729 case EBnepControlCommandNotUnderstood: |
|
730 LOG1(_L8("CBnepChannelController[%x]: EBnepControlCommandNotUnderstood"), this); |
|
731 aControl->Free(); |
|
732 delete aControl; |
|
733 break; |
|
734 |
|
735 default: |
|
736 LOG1(_L8("CBnepChannelController[%x]: default"), this); |
|
737 HandleUnknownCommandPacket(aControl); |
|
738 } |
|
739 } |
|
740 } |
|
741 |
|
742 /** |
|
743 Remote device has terminated the connection. |
|
744 We have to dismantle the link and notify the agent. |
|
745 @internalComponent |
|
746 */ |
|
747 void CBnepChannelController::RemoteDeviceDisconnect (TInt aError) |
|
748 { |
|
749 LOG_FUNC |
|
750 |
|
751 // This call can result in the CBnepChannelController being deleted. |
|
752 // No code should be placed after this call. |
|
753 |
|
754 #ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY |
|
755 TPanMessage::TRemoteDeviceDisconnect msg(aError); |
|
756 RClientInterface::OpenPostMessageClose(Id(),iPanConnectionNotify,msg); |
|
757 #else |
|
758 iNotify.RemoteDeviceDisconnect(aError); |
|
759 #endif |
|
760 } |
|
761 |
|
762 |
|
763 #ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY |
|
764 |
|
765 void CBnepChannelController::ReceivedL(const Messages::TRuntimeCtxId& /* aSender */, const Messages::TNodeId& /* aRecipient */, Messages::TSignatureBase& aCFMessage) |
|
766 { |
|
767 // IMPORTANT NOTE: |
|
768 // We register/deregister the pan messages for this thread with the |
|
769 // Comms Transport in CBnepBridge and therefore the lifetime of the |
|
770 // registration is the same as CBnepBridge. Instances of |
|
771 // CBnepChannelController can live past the deletion ofthe CBnepBridge. |
|
772 // After CBnepBridge has gone no custom message signatures can be |
|
773 // received, but this is ok since the only message we expect to receive |
|
774 // is TCloseChannelController which uses the SigVoid signature from |
|
775 // ESock. If this expectation changes an additional registration/deregistration |
|
776 // will need to be added to CBnepChannelController's c'tor/d'tor. |
|
777 |
|
778 if (aCFMessage.MessageId().Realm() == TPanMessage::ERealmId) |
|
779 { |
|
780 switch (aCFMessage.MessageId().MessageId()) |
|
781 { |
|
782 case TPanMessage::TRoleRequestFromLocalDevice::EId: |
|
783 { |
|
784 TPanMessage::TRoleRequestFromLocalDevice& msg = message_cast<TPanMessage::TRoleRequestFromLocalDevice>(aCFMessage); |
|
785 BnepRoleRequestFromLocalDevice(msg.iRequestedLocalRole, msg.iRequestedRemoteRole); |
|
786 } |
|
787 break; |
|
788 |
|
789 case TPanMessage::TRoleResponseFromLocalDevice::EId: |
|
790 { |
|
791 TPanMessage::TRoleResponseFromLocalDevice& msg = message_cast<TPanMessage::TRoleResponseFromLocalDevice>(aCFMessage); |
|
792 BnepRoleResponseFromLocalDevice(msg.iSetupResponse); |
|
793 } |
|
794 break; |
|
795 |
|
796 case TPanMessage::TCloseChannelController::EId: |
|
797 { |
|
798 // Don't put anything accessing "this" after the call to Close() - it wont be there |
|
799 Close(); |
|
800 } |
|
801 break; |
|
802 |
|
803 case TPanMessage::TSetUplinkAccessAllowedForBnepLink::EId: |
|
804 { |
|
805 TPanMessage::TSetUplinkAccessAllowedForBnepLink& msg = message_cast<TPanMessage::TSetUplinkAccessAllowedForBnepLink>(aCFMessage); |
|
806 SetUplinkAccessAllowedForBnepLink(msg.iValue); |
|
807 } |
|
808 break; |
|
809 |
|
810 default: |
|
811 __ASSERT_DEBUG(EFalse, BnepUtils::Panic(Bnep::EUnexpectedMessage)); |
|
812 } |
|
813 } |
|
814 else |
|
815 { |
|
816 __ASSERT_DEBUG(EFalse, BnepUtils::Panic(Bnep::EUnexpectedMessage)); |
|
817 } |
|
818 |
|
819 // Absorb messages |
|
820 aCFMessage.ClearMessageId(); |
|
821 } |
|
822 #endif |
|
823 |