|
1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "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 // Implements the CRawIPFlow class, which provides a central point for the NIF |
|
15 // to communicate with NifMan and the BCA controllers. This class creates an interface |
|
16 // to the IPv4 protocol when it is required. |
|
17 // |
|
18 // |
|
19 |
|
20 /** |
|
21 @file |
|
22 */ |
|
23 |
|
24 #include <f32file.h> |
|
25 #include <nifman.h> |
|
26 #include <nifmbuf.h> |
|
27 #include <in_iface.h> |
|
28 #include <nifvar.h> |
|
29 #include "IPv4Binder.h" |
|
30 #include "IPv6Binder.h" |
|
31 #include "RawIP2Flow.h" |
|
32 #include "BcaController.h" |
|
33 #include <comms-infras/linkprovision.h> |
|
34 #include <comms-infras/linkmessages.h> |
|
35 #include <comms-infras/ss_metaconnprov.h> // for SAccessPointConfig |
|
36 #include <elements/nm_messages_base.h> |
|
37 #include <elements/nm_messages_child.h> |
|
38 #include <comms-infras/ss_nodemessages_flow.h> |
|
39 |
|
40 using namespace Messages; |
|
41 using namespace MeshMachine; |
|
42 |
|
43 #ifdef __FLOG_ACTIVE |
|
44 //These variables are used only if flog is active. |
|
45 _LIT8(KTcpDumpFirstTag,"TcpDump"); |
|
46 static const TUint16 KTcpDumpLinkType = 12; |
|
47 #endif |
|
48 |
|
49 CRawIP2Flow::CRawIP2Flow(ESock::CSubConnectionFlowFactoryBase& aFactory, const Messages::TNodeId& aSubConnId, ESock::CProtocolIntfBase* aProtocolIntf, CBttLogger* aTheLogger) |
|
50 /** |
|
51 * Constructor. |
|
52 * |
|
53 * @param aFactory Reference to the factory which created this object. |
|
54 * @param aSubConnId Reference to the node id for sub connection. |
|
55 * @param aProtocolIntf pointer to the CProtocolIntfBase |
|
56 * @param aTheLogger The logging object, ownership is passed to this object |
|
57 */ |
|
58 : CSubConnectionFlowBase(aFactory, aSubConnId, aProtocolIntf), |
|
59 iTheLogger(aTheLogger), |
|
60 iInitError(KErrNone), |
|
61 iStarted(EFalse), |
|
62 iStopping(EFalse) |
|
63 { |
|
64 LOG_NODE_CREATE(KNifSubDir, CRawIP2Flow); |
|
65 } |
|
66 |
|
67 void CRawIP2Flow::ConstructL() |
|
68 /** |
|
69 * Second-phase constructor. Creates the Etel |
|
70 * control engine |
|
71 * |
|
72 * @param aName The name of the NIF (unused) |
|
73 */ |
|
74 { |
|
75 _LOG_L1C2(_L8("CRawIP2Flow %08x:\tConstructL()"), this); |
|
76 |
|
77 iBinderControl = new (ELeave) TBinderControlProxy(*this); |
|
78 iBcaController = CBcaController::NewL(*this, iTheLogger); |
|
79 } |
|
80 |
|
81 CRawIP2Flow::~CRawIP2Flow() |
|
82 /** |
|
83 * Destructor. Cancels and deletes all owned active objects. |
|
84 */ |
|
85 { |
|
86 // Note that we don't delete iBinder because it's not owned by us. |
|
87 delete iBcaController; |
|
88 // This class also deletes the logging object |
|
89 delete iTheLogger; |
|
90 |
|
91 ASSERT(iBinder == NULL); |
|
92 |
|
93 delete iBinderControl; |
|
94 LOG_NODE_DESTROY(KNifSubDir, CRawIP2Flow); |
|
95 // Cleanup when stop was not called - harmless as it null's the pointer |
|
96 __PACKETLOG_DELETE; |
|
97 } |
|
98 |
|
99 void CRawIP2Flow::StartFlowL() |
|
100 /** |
|
101 * Starts the Flow up. This process involves connecting to the BCA. |
|
102 * |
|
103 * Called in response to corresponding SCPR message. |
|
104 * |
|
105 * @return Allways KErrNone |
|
106 */ |
|
107 { |
|
108 ASSERT(iStarting==EFalse); |
|
109 iStarting = ETrue; |
|
110 _LOG_L1C2(_L8("CRawIP2Flow %08x:\tStartFlowL()"), this); |
|
111 |
|
112 // If there were any errors during earlier processing of the ProvisionConfig message |
|
113 // then send an Error message in response to the StartFlow (because ProvisionConfig |
|
114 // does not have a response code). |
|
115 if (iProvisionError != KErrNone) |
|
116 { |
|
117 User::Leave(iProvisionError); |
|
118 } |
|
119 |
|
120 // Retrieve Agent provisioned information only available at StartFlow time |
|
121 DynamicProvisionConfigL(); |
|
122 InitialiseL(); |
|
123 |
|
124 // associate the binder object with the lowersender |
|
125 iBinder->SetSender(&(iBcaController->Bca()->GetSender())); |
|
126 //the name calculation should be done only if logging is enabled |
|
127 #ifdef __FLOG_ACTIVE |
|
128 const TUint KModemNameLen = KCommsDbSvrMaxColumnNameLength + 10; // need enough for ppp-XXX.txt - e.g. ppp-comm-1.txt, ppp-btcomm-10.txt etc |
|
129 TBuf8<KModemNameLen> modemName; |
|
130 |
|
131 _LIT8(KDoubleColon, "::"); |
|
132 |
|
133 modemName.Copy(iBCAProvisionConfig->GetPortName()); |
|
134 const TInt pos = modemName.FindC((const TDesC8&)KDoubleColon); |
|
135 if(pos != KErrNotFound) |
|
136 { |
|
137 modemName.Delete(pos, 2); |
|
138 } |
|
139 |
|
140 //append time stamp |
|
141 const TUint KTimeStampLen = 8; |
|
142 TBuf8<KTimeStampLen> logFileName; |
|
143 |
|
144 _LIT8(KTimeFormat, "%08X"); |
|
145 TUint32 counter = User::FastCounter(); |
|
146 logFileName.Format(KTimeFormat, counter); |
|
147 |
|
148 TRAPD(err,__PACKETLOG_NEWL(KTcpDumpFirstTag, logFileName, CPacketLogger::ETcpDump, KTcpDumpLinkType)); |
|
149 if (err) |
|
150 { |
|
151 _LOG_L1C1(_L8("Trapped leave from __PACKETLOG_NEWL")); |
|
152 } |
|
153 |
|
154 const TUint KLogTextLen = KModemNameLen+KTimeStampLen+30; |
|
155 TBuf8<KLogTextLen> logText; |
|
156 _LIT8(KLogTimeText, "TcpDump log file time stamp:"); |
|
157 _LIT8(KLogModemText, " for modem:"); |
|
158 logText.Append(KLogTimeText); |
|
159 logText.Append(logFileName); |
|
160 logText.Append(KLogModemText); |
|
161 logText.Append(modemName); |
|
162 _LOG_L1C1(logText); |
|
163 #endif |
|
164 } |
|
165 |
|
166 |
|
167 void CRawIP2Flow::LinkLayerUp() |
|
168 /** |
|
169 * This function is called when initialisation is complete and the Flow is |
|
170 * ready to send/receive data. It notifies NifMan and the IP interface that it's |
|
171 * ready to go. |
|
172 */ |
|
173 { |
|
174 _LOG_L1C2(_L8("CRawIP2Flow %08x:\tLinkLayerUp()"), this); |
|
175 |
|
176 iLastRequestOriginator.ReplyTo(Id(), ESock::TCFDataClient::TStarted().CRef()); |
|
177 |
|
178 iStarted = ETrue; |
|
179 iStarting = EFalse; |
|
180 } |
|
181 |
|
182 void CRawIP2Flow::LinkLayerDown(TInt aError) |
|
183 /** |
|
184 * This function is called when the context has been deactivated and the NIF |
|
185 * is ready to be deleted, or if there is an error on startup. Its job is to |
|
186 * notify NifMan that the link has gone down, so it can delete the NIF. |
|
187 * |
|
188 * @param aError An error code to propagate to NifMan |
|
189 */ |
|
190 { |
|
191 _LOG_L1C3(_L8("CRawIP2Flow %08x:\tLinkLayerDown(aError %d)"), this, aError); |
|
192 __PACKETLOG_DELETE; |
|
193 |
|
194 if (iStopping) |
|
195 { |
|
196 iLastRequestOriginator.ReplyTo(Id(), ESock::TCFDataClient::TStopped(aError).CRef()); |
|
197 } |
|
198 else if (iStarting) |
|
199 { |
|
200 iSubConnectionProvider.PostMessage(Id(), TEBase::TError(ESock::TCFServiceProvider::TStart::Id(), aError).CRef()); |
|
201 } |
|
202 else |
|
203 { |
|
204 iSubConnectionProvider.PostMessage(Id(), ESock::TCFControlProvider::TDataClientGoneDown(aError, MNifIfNotify::EDisconnect).CRef()); |
|
205 } |
|
206 |
|
207 iStarted = EFalse; |
|
208 iStarting = EFalse; |
|
209 iStopping = EFalse; |
|
210 } |
|
211 |
|
212 void CRawIP2Flow::StopFlow(TInt aError) |
|
213 /** |
|
214 * This function is called by NifMan to bring down the link. It starts |
|
215 * the asynchronous context deactivation process; LinkLayerDown() will be |
|
216 * called when the context has been deactivated. |
|
217 * |
|
218 * @param aError A code specifying why the link is to be brought down |
|
219 * @param aAction The action to take: disconnect or reconnect |
|
220 */ |
|
221 { |
|
222 _LOG_L1C3(_L8("CRawIP2Flow %08x:\tStopFlow(aError %d)"), this, aError); |
|
223 __PACKETLOG_DELETE; |
|
224 iStopping = ETrue; |
|
225 ShutDown(aError); |
|
226 } |
|
227 |
|
228 |
|
229 void CRawIP2Flow::InitialiseL() |
|
230 /** |
|
231 * This method controls the initialisation sequence of the different modules |
|
232 * in the Flow. When a module completes all the initialisation tasks it will |
|
233 * call again this method with the new state. If an error occurs then the |
|
234 * ShutDown() method will be called. |
|
235 * |
|
236 * @param aState The current initialisation step |
|
237 * @param aError A possible error |
|
238 */ |
|
239 { |
|
240 _LOG_L1C2(_L8("CRawIPFlow %08x:\tInitialiseL"),this); |
|
241 |
|
242 // Update local state from TSY information originally from Agent. |
|
243 GetBinder()->UpdateContextConfigL(*iAgentProvision->iGprsConfig); |
|
244 GetBinder()->UpdateConnectionSpeed(iAgentProvision->iConnectionSpeed); |
|
245 |
|
246 UpdateContextState(RPacketContext::EStatusActive, KErrNone); |
|
247 |
|
248 iBcaController->StartLoadL(iBCAProvisionConfig,iBinder,iBinder); |
|
249 } |
|
250 |
|
251 void CRawIP2Flow::ShutDown(TInt aError) |
|
252 /** |
|
253 * This method controls the shutdown sequence of the different modules |
|
254 * in the Flow. When a module completes all the shutdown tasks it will |
|
255 * call again this method with the new state. |
|
256 * |
|
257 * @param aState The current state |
|
258 * @param aError A possible error (only during initialisation) |
|
259 */ |
|
260 { |
|
261 _LOG_L1C3(_L8("CRawIPFlow %08x:\tShutDown(aError %d)"),this, aError); |
|
262 |
|
263 if (aError != KErrNone) |
|
264 { |
|
265 // Flow is shutting down due to an error. |
|
266 // The error code must be stored in order to call linklayer down |
|
267 // passing that value |
|
268 iInitError = aError; |
|
269 } |
|
270 |
|
271 iBcaController->Stop(aError); |
|
272 LinkLayerDown(iInitError); |
|
273 } |
|
274 |
|
275 CBinderBase* CRawIP2Flow::GetBinder() |
|
276 /** |
|
277 * Returns a pointer to the Binder class |
|
278 * |
|
279 * @return a pointer to a CBinderBase derived class |
|
280 */ |
|
281 { |
|
282 return iBinder; |
|
283 } |
|
284 |
|
285 CBcaController* CRawIP2Flow::GetBcaController() |
|
286 /** |
|
287 * Returns a pointer to the CBcaIoController class |
|
288 * |
|
289 * @return a pointer to CBcaIoController |
|
290 */ |
|
291 { |
|
292 return iBcaController; |
|
293 } |
|
294 |
|
295 void CRawIP2Flow::UpdateContextState( |
|
296 RPacketContext::TContextStatus aState, TInt /*aError*/) |
|
297 /** |
|
298 * Updates the state of the iContextState variable |
|
299 * |
|
300 * @param aState The new state |
|
301 * @param aError A possible error |
|
302 */ |
|
303 { |
|
304 _LOG_L1C3(_L8("CRawIP2Flow %08x:\tUpdateContextState(aState %d)"), this, aState); |
|
305 |
|
306 // Note that we do not need to close the Flow down if there's been an |
|
307 // error, as the context state machine will do this for us. |
|
308 |
|
309 iContextStatus = aState; |
|
310 } |
|
311 |
|
312 // ===================================================================================== |
|
313 // |
|
314 // CSubConnectionFlowBase |
|
315 // |
|
316 |
|
317 ESock::MFlowBinderControl* CRawIP2Flow::DoGetBinderControlL() |
|
318 { |
|
319 return iBinderControl; |
|
320 } |
|
321 |
|
322 // ===================================================================================== |
|
323 // |
|
324 // MFlowBinderControl methods |
|
325 // |
|
326 |
|
327 ESock::MLowerControl* CRawIP2Flow::GetControlL(const TDesC8& aProtocol) |
|
328 { |
|
329 #ifdef __BTT_LOGGING__ |
|
330 //TBuf8<256> debugBuffer; |
|
331 //debugBuffer.Copy(aProtocol); |
|
332 _LOG_L1C3(_L8("CRawIP2Flow %08x:\tGetControlL(aProtocol %S)"), this, &aProtocol); |
|
333 #endif |
|
334 |
|
335 // IPv4 and ICMP Protocols |
|
336 if (aProtocol.CompareF(KDescIp()) == 0 || aProtocol.CompareF(KDescIcmp()) == 0) |
|
337 { |
|
338 if (!iBinder) |
|
339 { |
|
340 iBinder = new (ELeave) CIPv4Binder(*this, iTheLogger); |
|
341 #ifdef RAWIP_HEADER_APPENDED_TO_PACKETS |
|
342 iBinder->SetType(KIp4FrameType); |
|
343 #endif // RAWIP_HEADER_APPENDED_TO_PACKETS |
|
344 } |
|
345 else |
|
346 { |
|
347 _LOG_L1C2(_L8("CRawIP2Flow %08x:\tGetControlL(): IPv4 binder already exists"), this); |
|
348 } |
|
349 } |
|
350 // IPv6 Protocol |
|
351 else if (aProtocol.CompareF(KDescIp6()) == 0) |
|
352 { |
|
353 if (!iBinder) |
|
354 { |
|
355 iBinder = new (ELeave) CIPv6Binder(*this, iTheLogger); |
|
356 #ifdef RAWIP_HEADER_APPENDED_TO_PACKETS |
|
357 iBinder->SetType(KIp6FrameType); |
|
358 #endif // RAWIP_HEADER_APPENDED_TO_PACKETS |
|
359 } |
|
360 else |
|
361 { |
|
362 _LOG_L1C2(_L8("CRawIP2Flow %08x:\tGetControlL(): IPv6 binder already exists"), this); |
|
363 } |
|
364 } |
|
365 else |
|
366 { |
|
367 User::Leave(KErrNotSupported); |
|
368 } |
|
369 |
|
370 return iBinder; |
|
371 } |
|
372 |
|
373 ESock::MLowerDataSender* CRawIP2Flow::BindL(const TDesC8& aProtocol, ESock::MUpperDataReceiver* aReceiver, ESock::MUpperControl* aControl) |
|
374 /** |
|
375 * Binds upper CFProtocol to this CFProtocol |
|
376 * |
|
377 * @param aUpperReceiver A pointer to Upper layer Receive class |
|
378 * @param aUpperControl A pointer to Upper layer control class |
|
379 */ |
|
380 { |
|
381 #ifndef _DEBUG |
|
382 (void) aProtocol; |
|
383 #endif |
|
384 |
|
385 ASSERT (aProtocol.CompareF(KDescIp()) == 0 || aProtocol.CompareF(KDescIcmp()) == 0 |
|
386 || aProtocol.CompareF(KDescIp6()) == 0); |
|
387 ASSERT(iBinder); |
|
388 |
|
389 iSubConnectionProvider.PostMessage(Id(), ESock::TCFControlProvider::TActive().CRef()); |
|
390 return iBinder->Bind(aReceiver, aControl); |
|
391 } |
|
392 |
|
393 void CRawIP2Flow::Unbind(ESock::MUpperDataReceiver* aUpperReceiver, ESock::MUpperControl* aUpperControl) |
|
394 { |
|
395 _LOG_L1C2(_L8("CRawIP2Flow %08x:\tUnbind()"), this); |
|
396 |
|
397 ASSERT(iBinder); |
|
398 iBinder->Unbind(aUpperReceiver, aUpperControl); |
|
399 |
|
400 delete iBinder; |
|
401 iBinder = NULL; |
|
402 |
|
403 SendDataClientIdleIfNoClients(); |
|
404 } |
|
405 |
|
406 |
|
407 void CRawIP2Flow::SendDataClientIdleIfNoClients() |
|
408 { |
|
409 if (iBinder == NULL) |
|
410 { |
|
411 iSubConnectionProvider.PostMessage(Id(), ESock::TCFControlProvider::TIdle().CRef()); |
|
412 } |
|
413 } |
|
414 |
|
415 ESock::CSubConnectionFlowBase* CRawIP2Flow::Flow() |
|
416 /** |
|
417 Return the Flow corresponding to the MFlowBinderControl |
|
418 */ |
|
419 { |
|
420 return this; |
|
421 } |
|
422 |
|
423 // ===================================================================================== |
|
424 // |
|
425 // MCFNode |
|
426 // |
|
427 |
|
428 void CRawIP2Flow::ReceivedL(const TRuntimeCtxId& aSender, const TNodeId& aRecipient, TSignatureBase& aMessage) |
|
429 { |
|
430 CSubConnectionFlowBase::ReceivedL(aSender, aRecipient, aMessage); |
|
431 |
|
432 if (aMessage.IsMessage<TEBase::TError>()) |
|
433 { |
|
434 SubConnectionError(static_cast<TEBase::TError&>(aMessage).iValue); |
|
435 } |
|
436 else if (TEChild::ERealmId == aMessage.MessageId().Realm()) |
|
437 { |
|
438 switch (aMessage.MessageId().MessageId()) |
|
439 { |
|
440 case TEChild::TDestroy::EId : |
|
441 Destroy(); |
|
442 break; |
|
443 default: |
|
444 //TODO - logging |
|
445 ASSERT(EFalse); |
|
446 } |
|
447 } |
|
448 else if (ESock::TCFDataClient::ERealmId == aMessage.MessageId().Realm()) |
|
449 { |
|
450 switch (aMessage.MessageId().MessageId()) |
|
451 { |
|
452 case ESock::TCFDataClient::TStart::EId : |
|
453 StartFlowL(); |
|
454 break; |
|
455 case ESock::TCFDataClient::TStop::EId : |
|
456 StopFlow(static_cast<ESock::TCFDataClient::TStop&>(aMessage).iValue); |
|
457 break; |
|
458 case ESock::TCFDataClient::TProvisionConfig::EId: |
|
459 ProvisionConfig(static_cast<ESock::TCFDataClient::TProvisionConfig&>(aMessage).iConfig); |
|
460 break; |
|
461 case ESock::TCFDataClient::TBindTo::EId: |
|
462 { |
|
463 ESock::TCFDataClient::TBindTo& bindToReq = message_cast<ESock::TCFDataClient::TBindTo>(aMessage); |
|
464 if (!bindToReq.iNodeId.IsNull()) |
|
465 { |
|
466 User::Leave(KErrNotSupported); |
|
467 } |
|
468 RClientInterface::OpenPostMessageClose(Id(), aSender, ESock::TCFDataClient::TBindToComplete().CRef()); |
|
469 } |
|
470 break; |
|
471 default: |
|
472 //TODO - logging |
|
473 ASSERT(EFalse); |
|
474 } |
|
475 } |
|
476 else if (ESock::TCFFlow::ERealmId == aMessage.MessageId().Realm()) |
|
477 { |
|
478 switch (aMessage.MessageId().MessageId()) |
|
479 { |
|
480 case ESock::TCFFlow::TBlock::EId : |
|
481 iBlocked = ETrue; |
|
482 break; |
|
483 case ESock::TCFFlow::TUnBlock::EId : |
|
484 iBlocked = EFalse; |
|
485 if (iBinder) |
|
486 { |
|
487 iBinder->StartSending(); |
|
488 } |
|
489 break; |
|
490 case ESock::TCFFlow::TRejoin::EId: |
|
491 { |
|
492 ESock::TCFFlow::TRejoin& rejoinMsg = message_cast<ESock::TCFFlow::TRejoin>(aMessage); |
|
493 ESock::TDefaultFlowFactoryQuery query(rejoinMsg.iNodeId); |
|
494 CRawIP2Flow* otherFlow = static_cast<CRawIP2Flow*>(Factory().Find(query)); |
|
495 ASSERT(otherFlow); |
|
496 |
|
497 //This rather ugly looking snipped of code implements |
|
498 //the scenario whereat the network tears down the default |
|
499 //scpr and the default scpr selects a new default amongst |
|
500 //the non-default and subsequently performs a transparant |
|
501 //swap - i.e.: the upper layer perceives this as a |
|
502 //non-default going down. Since the datapath is pre-bound |
|
503 //to the flow representing the default, the datapath needs |
|
504 //to perform a transparent swap too, so that the upper layer |
|
505 //doesn't notice anything. It does that by swapping the |
|
506 //flows below the binders. |
|
507 CBinderBase* localBinder = iBinder; |
|
508 CBttLogger* logger = localBinder->iTheLogger; |
|
509 |
|
510 TBinderControlProxy* localBinderControl = iBinderControl; |
|
511 iBinder = otherFlow->iBinder; |
|
512 otherFlow->iBinder->ChangeFlow(*this); |
|
513 localBinder->ChangeFlow(*otherFlow); |
|
514 otherFlow->iBinder = localBinder; |
|
515 iBinderControl = otherFlow->iBinderControl; |
|
516 otherFlow->iBinderControl = localBinderControl; |
|
517 otherFlow->iBinderControl->iFlow = otherFlow; |
|
518 iBinderControl->iFlow = this; |
|
519 |
|
520 iBinder->iTheLogger = logger; |
|
521 |
|
522 iSubConnectionProvider.Close(); |
|
523 iSubConnectionProvider.Open(address_cast<TNodeId>(rejoinMsg.iNodeId)); |
|
524 } |
|
525 break; |
|
526 default: |
|
527 //TODO - logging |
|
528 ASSERT(EFalse); |
|
529 } |
|
530 } |
|
531 else // not a recognised realm or message |
|
532 { |
|
533 ASSERT(EFalse); |
|
534 } |
|
535 } |
|
536 |
|
537 |
|
538 // ===================================================================================== |
|
539 // |
|
540 // Methods for handling incoming SCPR messages |
|
541 // |
|
542 |
|
543 void CRawIP2Flow::SubConnectionGoingDown() |
|
544 { |
|
545 } |
|
546 |
|
547 void CRawIP2Flow::SubConnectionError(TInt /*aError*/) |
|
548 { |
|
549 } |
|
550 |
|
551 /* |
|
552 Provisioning description for RawIp CFProtocol Flow: |
|
553 |
|
554 - on receipt of the ProvisionConfig message, the pointer contained within is stored |
|
555 in iAccessPointConfig and the provisioning information contained within it is validated: |
|
556 - CBCAProvision must be present. It is added by the RawIpMCPr and populated from CommsDat. A pointer to it |
|
557 is stored in iProvision. |
|
558 if any are missing, an error is stored in iProvisionError and sent in response to the StartFlow |
|
559 message later on (ProvisionConfig has no response). |
|
560 |
|
561 - on receipt of the StartFlow message, further provisioning information is retrieved: |
|
562 - CIPConfig must be present. It is added by the RawIpMCPr and populated from CommsDat. The binder retrieves |
|
563 individual fields from it. |
|
564 - CRawIpAgentConfig must be present. It is added by the RawIpAgentHandler and populated via calls |
|
565 to the Agent. A pointer to it is stored in iAgentProvision. Note that the iGprsConfig field |
|
566 is a pointer to a (large) structure in the Agent (see CRawIpAgentHandler). |
|
567 if any of the above are missing, an Error message is signalled back to the SCPr in response |
|
568 to the StartFlow. |
|
569 */ |
|
570 |
|
571 void CRawIP2Flow::ProvisionConfig(const ESock::RMetaExtensionContainerC& aConfigData) |
|
572 /** |
|
573 Handle ProvisionConfig message from SCPR. |
|
574 |
|
575 Just save the pointer for now - validate it later on StartFlow. |
|
576 |
|
577 @param aData provisioning pointer from message |
|
578 */ |
|
579 { |
|
580 _LOG_L1C2(_L8("CRawIP2Flow %08x:\tProvisionConfig()"), this); |
|
581 iProvisionError = KErrNone; |
|
582 |
|
583 AccessPointConfig().Close(); |
|
584 AccessPointConfig().Open(aConfigData); |
|
585 |
|
586 ASSERT(iBCAProvisionConfig == NULL); |
|
587 iBCAProvisionConfig = static_cast<const CBCAProvision*>(AccessPointConfig().FindExtension(STypeId::CreateSTypeId(CBCAProvision::EUid, CBCAProvision::ETypeId))); |
|
588 |
|
589 if (iBCAProvisionConfig == NULL) |
|
590 { |
|
591 _LOG_L1C1(_L8("CRawIP2Flow:\tProvisionConfigL() - CBCAProvision config incomplete")); |
|
592 iProvisionError = KErrCorrupt; |
|
593 return; |
|
594 } |
|
595 } |
|
596 |
|
597 void CRawIP2Flow::DynamicProvisionConfigL() |
|
598 /** |
|
599 Retrieve provisioning information available only at StartFlow time. |
|
600 */ |
|
601 { |
|
602 ASSERT(iAgentProvision == NULL); |
|
603 iAgentProvision = static_cast<const CRawIpAgentConfig*>(AccessPointConfig().FindExtension(STypeId::CreateSTypeId(CRawIpAgentConfig::EUid, CRawIpAgentConfig::ETypeId))); |
|
604 |
|
605 if (iAgentProvision == NULL) |
|
606 { |
|
607 User::Leave(KErrCorrupt); |
|
608 } |
|
609 |
|
610 const CIPConfig* wcdmaIpProvision = static_cast<const CIPConfig*>(AccessPointConfig().FindExtension(STypeId::CreateSTypeId(CIPConfig::EUid, CIPConfig::ETypeId))); |
|
611 if (wcdmaIpProvision == NULL) |
|
612 { |
|
613 _LOG_L1C2(_L8("CRawIP2Flow %08x:\tDynamicProvisionConfigL() - WCDMA config incomplete"), this); |
|
614 iProvisionError = KErrCorrupt; |
|
615 return; |
|
616 } |
|
617 // Pass pointer to binder specific provisioning information to binder |
|
618 if (iBinder) |
|
619 { |
|
620 iBinder->SetProvision(*wcdmaIpProvision); |
|
621 } |
|
622 } |
|
623 |
|
624 |
|
625 void CRawIP2Flow::Destroy() |
|
626 /** |
|
627 Handle Destroy message from SCPR. |
|
628 */ |
|
629 { |
|
630 DeleteThisFlow(); |
|
631 } |
|
632 |
|
633 ESock::MLowerControl* CRawIP2Flow::TBinderControlProxy::GetControlL(const TDesC8& aProtocol) |
|
634 { |
|
635 return RawIP2Flow().GetControlL(aProtocol); |
|
636 } |
|
637 |
|
638 ESock::MLowerDataSender* CRawIP2Flow::TBinderControlProxy::BindL(const TDesC8& aProtocol, ESock::MUpperDataReceiver* aReceiver, ESock::MUpperControl* aControl) |
|
639 { |
|
640 return RawIP2Flow().BindL(aProtocol, aReceiver, aControl); |
|
641 } |
|
642 |
|
643 void CRawIP2Flow::TBinderControlProxy::Unbind(ESock::MUpperDataReceiver* aReceiver, ESock::MUpperControl* aControl) |
|
644 { |
|
645 return RawIP2Flow().Unbind(aReceiver, aControl); |
|
646 } |
|
647 |
|
648 ESock::CSubConnectionFlowBase* CRawIP2Flow::TBinderControlProxy::Flow() |
|
649 { |
|
650 return iFlow; |
|
651 } |
|
652 |
|
653 // ===================================================================================== |
|
654 // |
|
655 // Utility functions |
|
656 // |
|
657 |
|
658 void CRawIP2Flow::PostProgressMessage(TInt aStage, TInt aError) |
|
659 { |
|
660 iSubConnectionProvider.PostMessage(Id(), ESock::TCFMessage::TStateChange(Elements::TStateChange( aStage, aError)).CRef()); |
|
661 } |
|
662 |
|
663 // |
|
664 // NOTE: |
|
665 // Attribute table should be in the control side module that instantiates CRawIpProvision. |
|
666 // RawIP CFProtocol does not instantiate the CRawIpProvision object, so does not need to |
|
667 // define the attribute tables. The attribute table can therefore be placed directly into |
|
668 // the control side module. |
|
669 // |
|
670 // The reason for this is to save splitting RawIP CFProtocol into two DLL's - ECOM and Main - |
|
671 // just for control side module to link against Main DLL to retrieve the attribute table. |
|
672 // In fact, it can be placed into control side module as "START_ATTRIBUTE_TABLE" rather |
|
673 // than "EXPORT_START_ATTRIBUTE_TABLE". In fact, do we just need "TYPEID_TABLE" ? |
|
674 // |
|
675 // EXPORT_START_ATTRIBUTE_TABLE(CRawIpProvision, KRawIpConfigUid, KRawIpConfigType) |
|
676 // END_ATTRIBUTE_TABLE() |