|
1 /* |
|
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 #include <e32std.h> |
|
18 #include <ecom/ecom.h> |
|
19 #include <ecom/implementationproxy.h> |
|
20 #include <elements/nm_messages_base.h> |
|
21 #include <elements/nm_messages_child.h> |
|
22 |
|
23 #ifdef SYMBIAN_OLD_EXPORT_LOCATION |
|
24 #include "ss_subconnflow.h" |
|
25 #else |
|
26 #include <comms-infras/ss_subconnflow.h> |
|
27 #endif |
|
28 |
|
29 #include <comms-infras/ss_log.h> |
|
30 #include "flow.h" |
|
31 #include "binder.h" |
|
32 #include "provision.h" |
|
33 |
|
34 using namespace Messages; |
|
35 using namespace MeshMachine; |
|
36 using namespace ESock; |
|
37 |
|
38 _LIT8(KNif,"legacy_loopback_link_protocol"); |
|
39 |
|
40 CLegacyLoopbackSubConnectionFlowFactory* CLegacyLoopbackSubConnectionFlowFactory::NewL(TAny* aConstructionParameters) |
|
41 /** |
|
42 Constructs a Default SubConnection Flow Factory |
|
43 |
|
44 @param aConstructionParameters construction data passed by ECOM |
|
45 |
|
46 @returns pointer to a constructed factory |
|
47 */ |
|
48 { |
|
49 CLegacyLoopbackSubConnectionFlowFactory* ptr = new (ELeave) CLegacyLoopbackSubConnectionFlowFactory(TUid::Uid(KLegacyLoopbackFlowImplementationUid), *(reinterpret_cast<CSubConnectionFlowFactoryContainer*>(aConstructionParameters))); |
|
50 return ptr; |
|
51 } |
|
52 |
|
53 |
|
54 CLegacyLoopbackSubConnectionFlowFactory::CLegacyLoopbackSubConnectionFlowFactory(TUid aFactoryId, CSubConnectionFlowFactoryContainer& aParentContainer) |
|
55 : CSubConnectionFlowFactoryBase(aFactoryId, aParentContainer) |
|
56 /** |
|
57 Default SubConnection Flow Factory Constructor |
|
58 |
|
59 @param aFactoryId ECOM Implementation Id |
|
60 @param aParentContainer Object Owner |
|
61 */ |
|
62 { |
|
63 } |
|
64 |
|
65 |
|
66 CSubConnectionFlowBase* CLegacyLoopbackSubConnectionFlowFactory::DoCreateFlowL(CProtocolIntfBase* aProtocolIntf, TFactoryQueryBase& aQuery) |
|
67 { |
|
68 const TDefaultFlowFactoryQuery& query = static_cast<const TDefaultFlowFactoryQuery&>(aQuery); |
|
69 return CLegacyLoopbackSubConnectionFlow::NewL(*this, query.iSCprId, aProtocolIntf); |
|
70 } |
|
71 |
|
72 |
|
73 //======================================================================================= |
|
74 // CLegacyLoopbackSubConnectionFlow |
|
75 // |
|
76 |
|
77 CLegacyLoopbackSubConnectionFlow::CLegacyLoopbackSubConnectionFlow(CSubConnectionFlowFactoryBase& aFactory, const TNodeId& aSubConnId, CProtocolIntfBase* aProtocolIntf) |
|
78 : CSubConnectionFlowBase(aFactory, aSubConnId, aProtocolIntf) |
|
79 { |
|
80 __FLOG_OPEN(KCFNodeTag, KNif); |
|
81 LOG_NODE_CREATE(KNif, CLegacyLoopbackSubConnectionFlow); |
|
82 } |
|
83 |
|
84 CLegacyLoopbackSubConnectionFlow::~CLegacyLoopbackSubConnectionFlow() |
|
85 /** |
|
86 Destroys 'this' |
|
87 */ |
|
88 { |
|
89 ASSERT(iBinder4 == NULL); |
|
90 ASSERT(iBinder6 == NULL); |
|
91 |
|
92 LOG_NODE_DESTROY(KNif, CLegacyLoopbackSubConnectionFlow); |
|
93 __FLOG_CLOSE; |
|
94 } |
|
95 |
|
96 CLegacyLoopbackSubConnectionFlow* CLegacyLoopbackSubConnectionFlow::NewL(CSubConnectionFlowFactoryBase& aFactory, const TNodeId& aSubConnId, CProtocolIntfBase* aProtocolIntf) |
|
97 { |
|
98 CLegacyLoopbackSubConnectionFlow* flow = new (ELeave) CLegacyLoopbackSubConnectionFlow(aFactory, aSubConnId, aProtocolIntf); |
|
99 return flow; |
|
100 } |
|
101 |
|
102 // Methods called from Binders |
|
103 |
|
104 void CLegacyLoopbackSubConnectionFlow::FlowDown(TInt aError, TInt aAction /*= MNifIfNotify::EDisconnect*/) |
|
105 /** |
|
106 Binder requesting a FlowDown() message be sent to SCPR |
|
107 */ |
|
108 { |
|
109 PostFlowDownMessage(aError, aAction); |
|
110 iAgentProvision = NULL; |
|
111 } |
|
112 |
|
113 void CLegacyLoopbackSubConnectionFlow::Progress(TInt aStage, TInt aError) |
|
114 /** |
|
115 Binder requesting a Progress() message be sent to SCPR |
|
116 */ |
|
117 { |
|
118 PostProgressMessage(aStage, aError); |
|
119 } |
|
120 |
|
121 const TLegacyLoopbackIp6Provision* CLegacyLoopbackSubConnectionFlow::Ip6Provision() const |
|
122 /** |
|
123 Return a pointer to the IPv6 provisioning structure |
|
124 */ |
|
125 { |
|
126 ASSERT(iProvision); |
|
127 return &iProvision->iIp6Provision; |
|
128 } |
|
129 |
|
130 const TLegacyLoopBackAgentProvision* CLegacyLoopbackSubConnectionFlow::AgentProvision() const |
|
131 /** |
|
132 Return a pointer to the Agent provisioning structure |
|
133 */ |
|
134 { |
|
135 ASSERT(iAgentProvision); |
|
136 return iAgentProvision; |
|
137 } |
|
138 |
|
139 //-========================================================= |
|
140 // Messages::ANode methods |
|
141 //-========================================================= |
|
142 |
|
143 void CLegacyLoopbackSubConnectionFlow::ReceivedL(const TRuntimeCtxId& aSender, const TNodeId& aRecipient, TSignatureBase& aMessage) |
|
144 /** |
|
145 Method called on incoming SCPR messages |
|
146 |
|
147 @param aCFMessage message base |
|
148 */ |
|
149 { |
|
150 CSubConnectionFlowBase::ReceivedL(aSender, aRecipient, aMessage); |
|
151 if (aMessage.IsMessage<TEBase::TError>()) |
|
152 { |
|
153 SubConnectionError(static_cast<TEBase::TError&>(aMessage).iValue); |
|
154 } |
|
155 else if (TEChild::ERealmId == aMessage.MessageId().Realm()) |
|
156 { |
|
157 switch (aMessage.MessageId().MessageId()) |
|
158 { |
|
159 case TEChild::TDestroy::EId : |
|
160 Destroy(); |
|
161 break; |
|
162 default: |
|
163 //TODO - logging |
|
164 ASSERT(EFalse); |
|
165 } |
|
166 } |
|
167 else if (TCFDataClient::ERealmId == aMessage.MessageId().Realm()) |
|
168 { |
|
169 switch (aMessage.MessageId().MessageId()) |
|
170 { |
|
171 case TCFDataClient::TStart::EId : |
|
172 StartFlowL(); |
|
173 break; |
|
174 case TCFDataClient::TStop::EId : |
|
175 StopFlow(static_cast<TCFDataClient::TStop&>(aMessage).iValue); |
|
176 break; |
|
177 case TCFDataClient::TProvisionConfig::EId: |
|
178 ProvisionConfig(static_cast<TCFDataClient::TProvisionConfig&>(aMessage).iConfig); |
|
179 break; |
|
180 case TCFDataClient::TBindTo::EId: |
|
181 { |
|
182 TCFDataClient::TBindTo& bindToReq = message_cast<TCFDataClient::TBindTo>(aMessage); |
|
183 if (!bindToReq.iNodeId.IsNull()) |
|
184 { |
|
185 User::Leave(KErrNotSupported); |
|
186 } |
|
187 RClientInterface::OpenPostMessageClose(Id(), aSender, TCFDataClient::TBindToComplete().CRef()); |
|
188 } |
|
189 break; |
|
190 default: |
|
191 //TODO - logging |
|
192 ASSERT(EFalse); |
|
193 } |
|
194 } |
|
195 else // realm != TCFMessage::ERealmId |
|
196 { |
|
197 Panic(EUnexpectedMessage); |
|
198 } |
|
199 } |
|
200 |
|
201 // |
|
202 // Methods for handling received SCPR messages |
|
203 // |
|
204 |
|
205 void CLegacyLoopbackSubConnectionFlow::StartFlowL() |
|
206 { |
|
207 __FLOG(_L8("CLegacyLoopbackSubConnectionFlow:\tStartFlowL()")); |
|
208 if (iDisableStart) |
|
209 { |
|
210 User::Leave(KErrCouldNotConnect); |
|
211 } |
|
212 |
|
213 if (iFlowStarted) |
|
214 { |
|
215 //Flow can be started multiple times. |
|
216 //For example a start may fail on an upper layer in which case the upper layer will not be able |
|
217 //to stop our layer and we need to accept start again. |
|
218 PostProgressMessage(KLinkLayerOpen, KErrNone); |
|
219 PostDataClientStartedMessage(); |
|
220 return; |
|
221 } |
|
222 |
|
223 iFlowStarted = ETrue; |
|
224 |
|
225 // If the processing of the ProvisionConfig message failed earlier, send the error response |
|
226 // here to the StartFlow message as there is no response to ProvisionConfig. |
|
227 |
|
228 User::LeaveIfError(iSavedError); |
|
229 |
|
230 AgentProvisionConfigL(); // retrieve and validate the Agent provisioning information |
|
231 |
|
232 PostProgressMessage(KLinkLayerOpen, KErrNone); |
|
233 PostDataClientStartedMessage(); |
|
234 |
|
235 if (iBinder4) |
|
236 { |
|
237 iBinder4->BinderReady(); |
|
238 } |
|
239 if (iBinder6) |
|
240 { |
|
241 iBinder6->BinderReady(); |
|
242 } |
|
243 } |
|
244 |
|
245 void CLegacyLoopbackSubConnectionFlow::StopFlow(TInt aError) |
|
246 { |
|
247 __FLOG_1(_L8("CLegacyLoopbackSubConnectionFlow:\tStopFlow(%d)"), aError); |
|
248 |
|
249 PostProgressMessage(KLinkLayerClosed, aError); |
|
250 iFlowStarted = EFalse; |
|
251 PostFlowDownMessage(aError); |
|
252 iAgentProvision = NULL; |
|
253 } |
|
254 |
|
255 |
|
256 /* |
|
257 Provisioning description for Dummy CFProtocol Flow: |
|
258 |
|
259 - on receipt of the ProvisionConfig message, the pointer contained within it is stored |
|
260 in iAccessPointConfig and the information contained within the iAccessPointConfig |
|
261 array is validated: |
|
262 - CDummyProtoProvision must be present. It is added by the DummyProtoMCPr and populated from CommsDat. |
|
263 It is a 'C' class to take advantage of zero initialisation. |
|
264 Any errors are saved in iSavedError - there is no response to ProvisionConfig, so an error |
|
265 response is sent later to StartFlow message. |
|
266 |
|
267 - on receipt of TCFDataClient::TStart: |
|
268 - iSavedError is checked and, if non-zero, an Error message is sent to the SCPr |
|
269 - TLegacyLoopBackAgentProvision must be present. It is added by the DummyAgentHandler and populated via calls |
|
270 to the Agent. It is a 'T' class because it requires no zero initialisation. If missing, |
|
271 an Error message is signalled to the SCPr. |
|
272 */ |
|
273 |
|
274 void CLegacyLoopbackSubConnectionFlow::ProvisionConfig(const ESock::RMetaExtensionContainerC& aConfigData) |
|
275 /** |
|
276 Save the provisioning structure pointer passed in the TProvisionConfig message |
|
277 |
|
278 @param aData pointer to provisioning structure |
|
279 */ |
|
280 { |
|
281 __FLOG_0(_L8("CLegacyLoopbackSubConnectionFlow:\tProvisionConfig message received")); |
|
282 |
|
283 iAccessPointConfig.Close(); |
|
284 iAccessPointConfig.Open(aConfigData); |
|
285 |
|
286 const CLegacyLoopbackProvision* provision = static_cast<const CLegacyLoopbackProvision*>(AccessPointConfig().FindExtension( |
|
287 STypeId::CreateSTypeId(CLegacyLoopbackProvision::EUid, CLegacyLoopbackProvision::ETypeId))); |
|
288 if (provision == NULL) |
|
289 { |
|
290 __FLOG_0(_L8("CLegacyLoopbackSubConnectionFlow:\tProvisionConfigL() - config not found")); |
|
291 iSavedError = KErrCorrupt; |
|
292 } |
|
293 |
|
294 // Save pointer to provisioning information |
|
295 iProvision = provision; |
|
296 } |
|
297 |
|
298 |
|
299 void CLegacyLoopbackSubConnectionFlow::AgentProvisionConfigL() |
|
300 /** |
|
301 Validate and process the Agent provisioning information. |
|
302 |
|
303 This information is not valid when TProvisionConfig message is received, but only |
|
304 becomes valid at TCFDataClient::TStart. |
|
305 */ |
|
306 { |
|
307 const TLegacyLoopBackAgentProvision* agentProvision = static_cast<const TLegacyLoopBackAgentProvision*>( |
|
308 AccessPointConfig().FindExtension( |
|
309 STypeId::CreateSTypeId(TLegacyLoopBackAgentProvision::EUid, TLegacyLoopBackAgentProvision::ETypeId))); |
|
310 |
|
311 if (agentProvision == NULL) |
|
312 { |
|
313 __FLOG_0(_L8("CLegacyLoopbackSubConnectionFlow:\tProvisionConfigL() - DummyProto Agent config not found")); |
|
314 User::Leave(KErrCorrupt); |
|
315 } |
|
316 |
|
317 ASSERT(iAgentProvision == NULL); |
|
318 iAgentProvision = agentProvision; |
|
319 } |
|
320 |
|
321 void CLegacyLoopbackSubConnectionFlow::Destroy() |
|
322 /** |
|
323 Request from SCPR to destroy |
|
324 */ |
|
325 { |
|
326 // No-one should be bound to us from above if we are about to disappear. |
|
327 ASSERT(iBinder4 == NULL && iBinder6 == NULL); |
|
328 DeleteThisFlow(); |
|
329 } |
|
330 |
|
331 void CLegacyLoopbackSubConnectionFlow::SubConnectionGoingDown() |
|
332 { |
|
333 __FLOG(_L8("CLegacyLoopbackSubConnectionFlow:\tSubConnectionGoingDown")); |
|
334 } |
|
335 |
|
336 void CLegacyLoopbackSubConnectionFlow::SubConnectionError(TInt /*aError*/) |
|
337 { |
|
338 __FLOG(_L8("CLegacyLoopbackSubConnectionFlow:\tSubConnectionError")); |
|
339 } |
|
340 |
|
341 MFlowBinderControl* CLegacyLoopbackSubConnectionFlow::DoGetBinderControlL() |
|
342 /** |
|
343 Return MFlowBinderControl instance. |
|
344 |
|
345 Called by upper layer for binding |
|
346 |
|
347 @return MFlowBinderControl instance |
|
348 */ |
|
349 { |
|
350 __FLOG(_L8("CLegacyLoopbackSubConnectionFlow::DoGetBinderControlL")); |
|
351 return this; |
|
352 } |
|
353 |
|
354 //-========================================================= |
|
355 // MFlowBinderControl methods |
|
356 // |
|
357 |
|
358 MLowerControl* CLegacyLoopbackSubConnectionFlow::GetControlL(const TDesC8& aProtocol) |
|
359 /** |
|
360 Create and return an MLowerControl instance of the specified binder type. |
|
361 |
|
362 Called from upper layer during binding procedure. |
|
363 |
|
364 @param aProtocol Protocol type of the binder |
|
365 @return MLowerControl instance of the protocol type |
|
366 */ |
|
367 { |
|
368 |
|
369 MLowerControl* lowerControl = NULL; |
|
370 |
|
371 if (aProtocol.CompareF(KProtocol4()) == 0) |
|
372 { |
|
373 __FLOG(_L8("CLegacyLoopbackSubConnectionFlow:\tGetLowerControlL(KProtocol4)")); |
|
374 iBinder4 = CLegacyLoopbackBinder4::NewL(*this); |
|
375 lowerControl = iBinder4; |
|
376 } |
|
377 else |
|
378 if (aProtocol.CompareF(KProtocol6()) == 0) |
|
379 { |
|
380 __FLOG(_L8("CLegacyLoopbackSubConnectionFlow::GetLowerControlL(KProtocol6)")); |
|
381 |
|
382 iBinder6 = CLegacyLoopbackBinder6::NewL(*this); |
|
383 lowerControl = iBinder6; |
|
384 } |
|
385 |
|
386 ASSERT(lowerControl); |
|
387 return lowerControl; |
|
388 } |
|
389 |
|
390 MLowerDataSender* CLegacyLoopbackSubConnectionFlow::BindL(const TDesC8& aProtocol, MUpperDataReceiver* aReceiver, MUpperControl* aControl) |
|
391 /** |
|
392 Create and return an MLowerDataSender instance of the specified protocol type. |
|
393 This is bound to the specified upper layer objects. |
|
394 |
|
395 Called from upper layer to bind to this layer. |
|
396 |
|
397 @param aProtocol Protocol type of the binder (same as in GetControlL()) |
|
398 @param aReceiver upper layer's MUpperDataReceiver instance for this binder to associate with |
|
399 @param aControl upper layer's MUpperControl instance for this binder to associate with |
|
400 @return MLowerDataSender instance |
|
401 */ |
|
402 { |
|
403 __FLOG(_L8("CLegacyLoopbackSubConnectionFlow:\tBindL()")); |
|
404 |
|
405 MLowerDataSender* lowerDataSender = NULL; |
|
406 |
|
407 if (aProtocol.CompareF(KProtocol4()) == 0) |
|
408 { |
|
409 lowerDataSender = iBinder4->Bind(*aReceiver, *aControl); |
|
410 } |
|
411 else |
|
412 if (aProtocol.CompareF(KProtocol6()) == 0) |
|
413 { |
|
414 lowerDataSender = iBinder6->Bind(*aReceiver, *aControl); |
|
415 } |
|
416 |
|
417 iSubConnectionProvider.PostMessage(Id(), TCFControlProvider::TActive().CRef()); |
|
418 ASSERT(lowerDataSender); |
|
419 return lowerDataSender; |
|
420 } |
|
421 |
|
422 void CLegacyLoopbackSubConnectionFlow::Unbind(MUpperDataReceiver* aReceiver, MUpperControl* aControl) |
|
423 /** |
|
424 Unbind from the upper layer. |
|
425 |
|
426 Called from the upper layer during unbinding. |
|
427 |
|
428 @param aReceiver |
|
429 @param aControl |
|
430 |
|
431 */ |
|
432 { |
|
433 __FLOG(_L8("CLegacyLoopbackSubConnectionFlow:\tUnbind()")); |
|
434 |
|
435 if (iBinder4 && iBinder4->MatchesUpperControl(aControl)) |
|
436 { |
|
437 iBinder4->Unbind(*aReceiver, *aControl); |
|
438 delete iBinder4; |
|
439 iBinder4 = NULL; |
|
440 } |
|
441 else if (iBinder6 && iBinder6->MatchesUpperControl(aControl)) |
|
442 { |
|
443 iBinder6->Unbind(*aReceiver, *aControl); |
|
444 delete iBinder6; |
|
445 iBinder6 = NULL; |
|
446 } |
|
447 |
|
448 |
|
449 MaybePostDataClientIdle(); |
|
450 } |
|
451 |
|
452 ESock::CSubConnectionFlowBase* CLegacyLoopbackSubConnectionFlow::Flow() |
|
453 /** |
|
454 Return the flow object corresponding to the MFlowBinderControl |
|
455 */ |
|
456 { |
|
457 return this; |
|
458 } |
|
459 |
|
460 // |
|
461 // Utilities for posting SCPR messages |
|
462 // |
|
463 |
|
464 void CLegacyLoopbackSubConnectionFlow::PostProgressMessage(TInt aStage, TInt aError) |
|
465 { |
|
466 iSubConnectionProvider.PostMessage(Id(), TCFMessage::TStateChange(Elements::TStateChange(aStage, aError)).CRef()); |
|
467 } |
|
468 |
|
469 void CLegacyLoopbackSubConnectionFlow::PostDataClientStartedMessage() |
|
470 { |
|
471 iLastRequestOriginator.ReplyTo(Id(), TCFDataClient::TStarted().CRef()); |
|
472 } |
|
473 |
|
474 void CLegacyLoopbackSubConnectionFlow::PostFlowDownMessage(TInt aError, TInt aAction /*= MNifIfNotify::EDisconnect*/) |
|
475 { |
|
476 if (iFlowStarted) |
|
477 { |
|
478 iFlowStarted = EFalse; |
|
479 iSubConnectionProvider.PostMessage(Id(), TCFControlProvider::TDataClientGoneDown(aError, aAction).CRef()); |
|
480 } |
|
481 else |
|
482 { |
|
483 iLastRequestOriginator.ReplyTo(Id(), TCFDataClient::TStopped(aError).CRef()); |
|
484 } |
|
485 iAgentProvision = NULL; |
|
486 } |
|
487 |
|
488 void CLegacyLoopbackSubConnectionFlow::MaybePostDataClientIdle() |
|
489 { |
|
490 // Can only send DataClientIdle when the upper layer has unbound and the flow is stopped |
|
491 if (iBinder4 == NULL && iBinder6 == NULL) |
|
492 { |
|
493 iSubConnectionProvider.PostMessage(Id(), TCFControlProvider::TIdle().CRef()); |
|
494 } |
|
495 } |
|
496 |
|
497 // |
|
498 // Other utilities |
|
499 // |
|
500 |
|
501 void Panic(TLegacyLoopbackPanicNum aNum) |
|
502 { |
|
503 _LIT(KLegacyLoopbackPanicString, "legacy_loopback"); |
|
504 User::Panic(KLegacyLoopbackPanicString, aNum); |
|
505 } |
|
506 |