|
1 // Copyright (c) 2008-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 // Dummy implementation file for network tier flow |
|
15 // |
|
16 // |
|
17 |
|
18 /** |
|
19 @file |
|
20 @internalComponent |
|
21 */ |
|
22 |
|
23 |
|
24 #include <ss_std.h> |
|
25 #include <comms-infras/ss_log.h> |
|
26 #include <ss_pman.h> |
|
27 #include <comms-infras/ss_nodemessages_internal_esock.h> |
|
28 #include <comms-infras/ss_protocolparameterset.h> |
|
29 #include "dummypr_flow.h" |
|
30 |
|
31 |
|
32 #ifdef _DEBUG |
|
33 // Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module |
|
34 // (if it could happen through user error then you should give it an explicit, documented, category + code) |
|
35 _LIT(KSpecAssert_ESockTestdmyprnt, "ESockTestdmyprnt"); |
|
36 #endif |
|
37 |
|
38 using namespace ESock; |
|
39 using namespace Messages; |
|
40 |
|
41 |
|
42 |
|
43 |
|
44 // Construction |
|
45 //------------- |
|
46 CDummyFlow* CDummyFlow::NewL(CSubConnectionFlowFactoryBase& aFactory, const Messages::TNodeId& aSubConn, CProtocolIntfBase* aProtocolIntf) |
|
47 { |
|
48 CDummyFlow* self = new (ELeave) CDummyFlow(aFactory, aSubConn, aProtocolIntf); |
|
49 return self; |
|
50 } |
|
51 |
|
52 CDummyFlow::CDummyFlow(CSubConnectionFlowFactoryBase& aFactory, const Messages::TNodeId& aSubConn, CProtocolIntfBase* aProtocolIntf) |
|
53 : CSubConnectionFlowBase(aFactory, aSubConn, aProtocolIntf) |
|
54 { |
|
55 LOG_NODE_CREATE(KESockFlowTag, CDummyFlow) |
|
56 } |
|
57 |
|
58 CDummyFlow::~CDummyFlow() |
|
59 { |
|
60 LOG_NODE_DESTROY(KESockFlowTag, CDummyFlow) |
|
61 } |
|
62 |
|
63 MSessionControl* CDummyFlow::GetControlL( |
|
64 TInt /*aSessionType*/, |
|
65 MSessionControlNotify& aSessionControlNotify) |
|
66 { |
|
67 // Apply binding locally |
|
68 __ASSERT_DEBUG(iSessionControlNotify == NULL, User::Panic(KSpecAssert_ESockTestdmyprnt, 1)); |
|
69 iSessionControlNotify = &aSessionControlNotify; |
|
70 |
|
71 return this; |
|
72 } |
|
73 |
|
74 MSessionData* CDummyFlow::BindL(MSessionDataNotify& aNotify) |
|
75 { |
|
76 LOG( ESockLog::Printf(_L8("CDummyFlow %08x:\tBindL(aNotify 0x%08x)"), this, &aNotify) ); |
|
77 |
|
78 // Apply binding locally |
|
79 __ASSERT_DEBUG(iSessionDataNotify == NULL, User::Panic(KSpecAssert_ESockTestdmyprnt, 3)); |
|
80 iSessionDataNotify = &aNotify; |
|
81 iSubConnectionProvider.RNodeInterface::PostMessage( |
|
82 Id(), |
|
83 TCFControlProvider::TActive().CRef()); |
|
84 return this; |
|
85 } |
|
86 |
|
87 void CDummyFlow::Unbind() |
|
88 { |
|
89 LOG( ESockLog::Printf(_L8("CDummyFlow %08x:\tUnbind()"), this) ); |
|
90 ASSERT(iSessionDataNotify); //who else is it calling then? |
|
91 |
|
92 iSessionControlNotify = NULL; |
|
93 iSessionDataNotify = NULL; |
|
94 |
|
95 ASSERT(iSubConnectionProvider.IsOpen()); |
|
96 iSubConnectionProvider.RNodeInterface::PostMessage( |
|
97 Id(), |
|
98 TCFControlProvider::TIdle().CRef() |
|
99 ); |
|
100 } |
|
101 |
|
102 ESock::CSubConnectionFlowBase& CDummyFlow::CloneFlowL() |
|
103 { |
|
104 TDefaultFlowFactoryQuery query (iProtocolIntf->ControlProviderId(), iSubConnectionProvider.RecipientId()); |
|
105 |
|
106 ESock::CSubConnectionFlowBase& flow = static_cast<ESock::CSubConnectionFlowBase&>(*(Factory().CreateObjectL(query))); |
|
107 |
|
108 // Have the new flow become a data client of our subconnection too |
|
109 __ASSERT_DEBUG(iSubConnectionProvider.IsOpen(), User::Panic(KSpecAssert_ESockTestdmyprnt, 6)); |
|
110 TCFPeer::TJoinRequest msg( |
|
111 flow.Id(), |
|
112 TCFClientType(TCFClientType::EData, TCFClientType::EActive) |
|
113 ); |
|
114 |
|
115 iSubConnectionProvider.PostMessage(Id(), msg); |
|
116 |
|
117 return flow; |
|
118 } |
|
119 |
|
120 CSubConnectionFlowBase* CDummyFlow::Flow() |
|
121 { |
|
122 return this; |
|
123 } |
|
124 |
|
125 |
|
126 // MSessionControl |
|
127 //---------------- |
|
128 void CDummyFlow::Start() |
|
129 {/*__ASSERT_DEBUG(iLowerFlowControl, User::Panic(KSpecAssert_ESockTestdmyprnt, 7)); return iLowerFlowControl->Start()*/;} |
|
130 |
|
131 void CDummyFlow::LocalName(TSockAddr& anAddr) const |
|
132 {__ASSERT_DEBUG(iLowerFlowControl, User::Panic(KSpecAssert_ESockTestdmyprnt, 8)); return iLowerFlowControl->LocalName(anAddr);} |
|
133 |
|
134 void CDummyFlow::SetLocalName(TSockAddr& /*anAddr*/) |
|
135 { |
|
136 // Fetch the current flow parameters (those that were sent to us) and create a new set for the flow we want |
|
137 TFlowParams flowParams; |
|
138 flowParams.iProtocol = CDummyFlow::EProtocolId; |
|
139 flowParams.iSocketType = KSockDatagram; |
|
140 |
|
141 // Create and load a parameter set with the flow parameters that form our binder request |
|
142 CFlowRequestParameters* paramSet = CFlowRequestParameters::NewL(); |
|
143 CleanupStack::PushL(paramSet); |
|
144 paramSet->SetFlowParams(flowParams); |
|
145 RCFParameterFamilyBundle flowParamsBundle; |
|
146 flowParamsBundle.CreateL(); |
|
147 RParameterFamily family = flowParamsBundle.CreateFamilyL(KFlowParametersFamily); |
|
148 family.AddParameterSetL(paramSet, RParameterFamily::ERequested); |
|
149 |
|
150 iParamBundle.Open(flowParamsBundle); |
|
151 // Construct and send the message |
|
152 iSubConnectionProvider.RNodeInterface::PostMessage( |
|
153 Id(), |
|
154 TCFControlProvider::TNoBearer(iParamBundle).CRef() |
|
155 ); |
|
156 |
|
157 CleanupStack::Pop(paramSet); |
|
158 } |
|
159 |
|
160 void CDummyFlow::RemName(TSockAddr& anAddr) const |
|
161 {__ASSERT_DEBUG(iLowerFlowControl, User::Panic(KSpecAssert_ESockTestdmyprnt, 10)); iLowerFlowControl->RemName(anAddr);} |
|
162 |
|
163 TInt CDummyFlow::SetRemName(TSockAddr& anAddr) |
|
164 {__ASSERT_DEBUG(iLowerFlowControl, User::Panic(KSpecAssert_ESockTestdmyprnt, 11)); return iLowerFlowControl->SetRemName(anAddr);} |
|
165 |
|
166 const TInt KDummyNetworkFlowOptionLevel = CDummyFlowFactory::iUid; |
|
167 const TInt KFlowProtocolName = 1; |
|
168 |
|
169 TInt CDummyFlow::GetOption(TUint aLevel, TUint aName, TDes8& anOption) const |
|
170 { |
|
171 __ASSERT_DEBUG(iLowerFlowControl, User::Panic(KSpecAssert_ESockTestdmyprnt, 12)); |
|
172 |
|
173 if(aLevel == KDummyNetworkFlowOptionLevel && aName == KFlowProtocolName) |
|
174 { |
|
175 anOption.Copy(KDummyProtocolName); |
|
176 return KErrNone; |
|
177 } |
|
178 else |
|
179 { |
|
180 return iLowerFlowControl->GetOption(aLevel, aName, anOption); |
|
181 } |
|
182 } |
|
183 |
|
184 void CDummyFlow::Ioctl(TUint aLevel, TUint aName, TDes8* anOption) |
|
185 {__ASSERT_DEBUG(iLowerFlowControl, User::Panic(KSpecAssert_ESockTestdmyprnt, 13)); iLowerFlowControl->Ioctl(aLevel, aName, anOption);} |
|
186 |
|
187 void CDummyFlow::CancelIoctl(TUint aLevel, TUint aName) |
|
188 {__ASSERT_DEBUG(iLowerFlowControl, User::Panic(KSpecAssert_ESockTestdmyprnt, 14)); iLowerFlowControl->CancelIoctl(aLevel, aName);} |
|
189 |
|
190 TInt CDummyFlow::SetOption(TUint /*aLevel*/, TUint /*aName*/, const TDesC8 &/*anOption*/) |
|
191 { return KErrNone; } |
|
192 |
|
193 void CDummyFlow::ActiveOpen() |
|
194 {__ASSERT_DEBUG(iLowerFlowControl, User::Panic(KSpecAssert_ESockTestdmyprnt, 16)); iLowerFlowControl->ActiveOpen();} |
|
195 |
|
196 void CDummyFlow::ActiveOpen(const TDesC8& aConnectionData) |
|
197 {__ASSERT_DEBUG(iLowerFlowControl, User::Panic(KSpecAssert_ESockTestdmyprnt, 17)); iLowerFlowControl->ActiveOpen(aConnectionData);} |
|
198 |
|
199 TInt CDummyFlow::PassiveOpen(TUint aQueueSize) |
|
200 {__ASSERT_DEBUG(iLowerFlowControl, User::Panic(KSpecAssert_ESockTestdmyprnt, 18)); return iLowerFlowControl->PassiveOpen(aQueueSize);} |
|
201 |
|
202 TInt CDummyFlow::PassiveOpen(TUint aQueueSize, const TDesC8& aConnectionData) |
|
203 {__ASSERT_DEBUG(iLowerFlowControl, User::Panic(KSpecAssert_ESockTestdmyprnt, 19)); return iLowerFlowControl->PassiveOpen(aQueueSize, aConnectionData);} |
|
204 |
|
205 void CDummyFlow::Shutdown(MSessionControl::TCloseType aOption) |
|
206 { |
|
207 if (iLowerFlowControl) |
|
208 { |
|
209 iLowerFlowControl->Shutdown(aOption); |
|
210 } |
|
211 else |
|
212 { |
|
213 iSessionControlNotify->CanClose(MSessionControlNotify::EDelete); |
|
214 } |
|
215 } |
|
216 |
|
217 void CDummyFlow::Shutdown(MSessionControl::TCloseType aOption, const TDesC8& aDisconnectionData) |
|
218 {__ASSERT_DEBUG(iLowerFlowControl, User::Panic(KSpecAssert_ESockTestdmyprnt, 21)); iLowerFlowControl->Shutdown(aOption, aDisconnectionData);} |
|
219 |
|
220 void CDummyFlow::AutoBind() |
|
221 {__ASSERT_DEBUG(iLowerFlowControl, User::Panic(KSpecAssert_ESockTestdmyprnt, 22)); iLowerFlowControl->AutoBind();} |
|
222 |
|
223 TInt CDummyFlow::SecurityCheck(MProvdSecurityChecker* /*aChecker*/) |
|
224 { return KErrNone;} |
|
225 |
|
226 |
|
227 // MSessionData |
|
228 //------------- |
|
229 TUint CDummyFlow::Write(const TDesC8& aDesc, TUint aOptions, TSockAddr* anAddr) |
|
230 {__ASSERT_DEBUG(iLowerFlowData, User::Panic(KSpecAssert_ESockTestdmyprnt, 24)); return iLowerFlowData->Write(aDesc, aOptions, anAddr);} |
|
231 |
|
232 TInt CDummyFlow::Write(RMBufChain& aData, TUint aOptions, TSockAddr* anAddr) |
|
233 {__ASSERT_DEBUG(iLowerFlowData, User::Panic(KSpecAssert_ESockTestdmyprnt, 25)); return iLowerFlowData->Write(aData, aOptions, anAddr);} |
|
234 |
|
235 void CDummyFlow::GetData(TDes8& aDesc, TUint aOptions, TSockAddr* anAddr) |
|
236 {__ASSERT_DEBUG(iLowerFlowData, User::Panic(KSpecAssert_ESockTestdmyprnt, 26)); iLowerFlowData->GetData(aDesc, aOptions, anAddr);} |
|
237 |
|
238 TInt CDummyFlow::GetData(RMBufChain& aData, TUint aLength, TUint aOptions, TSockAddr* anAddr) |
|
239 {__ASSERT_DEBUG(iLowerFlowData, User::Panic(KSpecAssert_ESockTestdmyprnt, 27)); return iLowerFlowData->GetData(aData, aLength, aOptions, anAddr);} |
|
240 |
|
241 |
|
242 // MSessionControlNotify |
|
243 //---------------------- |
|
244 void CDummyFlow::ConnectComplete() |
|
245 {__ASSERT_DEBUG(iSessionControlNotify, User::Panic(KSpecAssert_ESockTestdmyprnt, 28)); iSessionControlNotify->ConnectComplete();} |
|
246 |
|
247 void CDummyFlow::ConnectComplete(const TDesC8& aConnectData) |
|
248 {__ASSERT_DEBUG(iSessionControlNotify, User::Panic(KSpecAssert_ESockTestdmyprnt, 29)); iSessionControlNotify->ConnectComplete(aConnectData);} |
|
249 |
|
250 void CDummyFlow::ConnectComplete(CSubConnectionFlowBase& anSSP) |
|
251 {__ASSERT_DEBUG(iSessionControlNotify, User::Panic(KSpecAssert_ESockTestdmyprnt, 30)); iSessionControlNotify->ConnectComplete(anSSP);} |
|
252 |
|
253 void CDummyFlow::ConnectComplete(CSubConnectionFlowBase& anSSP,const TDesC8& aConnectData) |
|
254 {__ASSERT_DEBUG(iSessionControlNotify, User::Panic(KSpecAssert_ESockTestdmyprnt, 31)); iSessionControlNotify->ConnectComplete(anSSP, aConnectData);} |
|
255 |
|
256 void CDummyFlow::CanClose(MSessionControlNotify::TDelete aDelete) |
|
257 {__ASSERT_DEBUG(iSessionControlNotify, User::Panic(KSpecAssert_ESockTestdmyprnt, 32)); iSessionControlNotify->CanClose(aDelete);} |
|
258 |
|
259 void CDummyFlow::CanClose( |
|
260 const TDesC8& aDisconnectData, |
|
261 MSessionControlNotify::TDelete aDelete) |
|
262 {__ASSERT_DEBUG(iSessionControlNotify, User::Panic(KSpecAssert_ESockTestdmyprnt, 33)); iSessionControlNotify->CanClose(aDisconnectData, aDelete);} |
|
263 |
|
264 TInt CDummyFlow::Error(TInt anError,TUint anOperationMask) |
|
265 {__ASSERT_DEBUG(iSessionControlNotify, User::Panic(KSpecAssert_ESockTestdmyprnt, 34)); return iSessionControlNotify->Error(anError, anOperationMask);} |
|
266 |
|
267 void CDummyFlow::Disconnect() |
|
268 {__ASSERT_DEBUG(iSessionControlNotify, User::Panic(KSpecAssert_ESockTestdmyprnt, 35)); iSessionControlNotify->Disconnect();} |
|
269 |
|
270 void CDummyFlow::Disconnect(TDesC8& aDisconnectData) |
|
271 {__ASSERT_DEBUG(iSessionControlNotify, User::Panic(KSpecAssert_ESockTestdmyprnt, 36)); iSessionControlNotify->Disconnect(aDisconnectData);} |
|
272 |
|
273 void CDummyFlow::IoctlComplete(TDesC8* aBuf) |
|
274 {__ASSERT_DEBUG(iSessionControlNotify, User::Panic(KSpecAssert_ESockTestdmyprnt, 37)); iSessionControlNotify->IoctlComplete(aBuf);} |
|
275 |
|
276 void CDummyFlow::DisconnectFromListener(CSubConnectionFlowBase& aSSP) |
|
277 { |
|
278 __ASSERT_DEBUG(iSessionControlNotify, User::Panic(KSpecAssert_ESockTestdmyprnt, 53)); |
|
279 iSessionControlNotify->DisconnectFromListener(aSSP); |
|
280 } |
|
281 void CDummyFlow::SetLocalNameComplete() |
|
282 { |
|
283 __ASSERT_DEBUG(iSessionControlNotify, User::Panic(KSpecAssert_ESockTestdmyprnt, 52)); |
|
284 iSessionControlNotify->SetLocalNameComplete(); |
|
285 } |
|
286 |
|
287 // MSessionDataNotify |
|
288 //------------------- |
|
289 void CDummyFlow::NewData(TUint aCount) |
|
290 {__ASSERT_DEBUG(iSessionDataNotify, User::Panic(KSpecAssert_ESockTestdmyprnt, 39)); iSessionDataNotify->NewData(aCount);} |
|
291 |
|
292 void CDummyFlow::CanSend() |
|
293 {__ASSERT_DEBUG(iSessionDataNotify, User::Panic(KSpecAssert_ESockTestdmyprnt, 40)); iSessionDataNotify->CanSend();} |
|
294 |
|
295 MFlowBinderControl* CDummyFlow::DoGetBinderControlL() |
|
296 { |
|
297 return this; |
|
298 } |
|
299 |
|
300 |
|
301 // Node stuff |
|
302 //----------- |
|
303 void CDummyFlow::ReceivedL(const TRuntimeCtxId& aSender, const TNodeId& aRecipient, TSignatureBase& aMessage) |
|
304 { |
|
305 CSubConnectionFlowBase::ReceivedL(aSender, aRecipient, aMessage); |
|
306 TInt err = KErrNone; |
|
307 |
|
308 if ( aMessage.IsMessage<TEBase::TError>() ) |
|
309 { |
|
310 ASSERT(EFalse); //To be implemented |
|
311 } |
|
312 else if ( aMessage.IsMessage<TCFControlProvider::TBearer>() ) |
|
313 { |
|
314 } |
|
315 else if (aMessage.IsMessage<TCFInternalEsock::TFlowProvision>()) |
|
316 { |
|
317 } |
|
318 else if (TEChild::ERealmId == aMessage.MessageId().Realm()) |
|
319 { |
|
320 switch (aMessage.MessageId().MessageId()) |
|
321 { |
|
322 case TEChild::TDestroy::EId : |
|
323 DeleteThisFlow(); |
|
324 break; |
|
325 default: |
|
326 __ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockTestdmyprnt, 41)); //For debug configurations |
|
327 User::Leave(KErrNotSupported); //For release configurations |
|
328 } |
|
329 } |
|
330 else if (TCFDataClient::ERealmId == aMessage.MessageId().Realm()) |
|
331 { |
|
332 switch (aMessage.MessageId().MessageId()) |
|
333 { |
|
334 case TCFDataClient::TStart::EId : |
|
335 iSubConnectionProvider.PostMessage(Id(), TCFDataClient::TStarted().CRef()); |
|
336 break; |
|
337 case TCFDataClient::TStop::EId : |
|
338 iParamBundle.Close(); //[RZ] There is a problem with RCFParameterBundle. Nominally this should be cleared (closed) on TBeaer |
|
339 //but that means that this thread (which constructed the bundle) will call Close before the recipient |
|
340 //refcounting will mean that it's the recipient that would then dealocate and crash against different heap. |
|
341 //Best if RCFParameterBundle were changed. Alternativelly, CNoBearer could get rid of the params |
|
342 //earlier. |
|
343 |
|
344 if (iLowerFlowBinderControl) |
|
345 { |
|
346 iLowerFlowBinderControl->Unbind(NULL,NULL); |
|
347 iLowerFlowBinderControl->Unbind(); |
|
348 iLowerFlowBinderControl = NULL; |
|
349 iLowerFlowControl = NULL; |
|
350 iLowerFlowData = NULL; |
|
351 } |
|
352 |
|
353 iSubConnectionProvider.PostMessage(Id(), TCFDataClient::TStopped( |
|
354 message_cast<TCFDataClient::TStop>(aMessage).iValue).CRef()); |
|
355 break; |
|
356 case TCFDataClient::TProvisionConfig::EId: |
|
357 break; |
|
358 case TCFDataClient::TBindTo::EId: |
|
359 { |
|
360 TCFDataClient::TBindTo& bindToMsg(static_cast<TCFDataClient::TBindTo&>(aMessage)); |
|
361 TRAP(err, BindToL(bindToMsg)); |
|
362 |
|
363 if(err == KErrNone) |
|
364 { |
|
365 RClientInterface::OpenPostMessageClose(Id(), aSender, TCFDataClient::TBindToComplete().CRef()); |
|
366 } |
|
367 else |
|
368 { |
|
369 RClientInterface::OpenPostMessageClose(Id(), aSender, TEBase::TError(aMessage.MessageId(), err).CRef()); |
|
370 } |
|
371 |
|
372 if (iSessionControlNotify && !iParamBundle.IsNull()) |
|
373 { |
|
374 iSessionControlNotify->SetLocalNameComplete(); |
|
375 } |
|
376 } |
|
377 break; |
|
378 default: |
|
379 __ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockTestdmyprnt, 42)); //For debug configurations |
|
380 User::Leave(KErrNotSupported); //For release configurations |
|
381 } |
|
382 } |
|
383 else |
|
384 { |
|
385 __ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockTestdmyprnt, 45)); //For debug configurations |
|
386 User::Leave(KErrNotSupported); //For release configurations |
|
387 } |
|
388 } |
|
389 |
|
390 void CDummyFlow::BindToL(TCFDataClient::TBindTo& aBindTo) |
|
391 /** |
|
392 Request from control side (at network layer) to indicate that the SubConnection is |
|
393 up and running and that we should bind to a Flow below. |
|
394 |
|
395 @param aLowerFlow Flow below to bind to. |
|
396 */ |
|
397 { |
|
398 //provisioning message must come before bindto in case we didn't get it after we've joined |
|
399 //the sub-connection |
|
400 if (aBindTo.iNodeId == Messages::TNodeId::NullId()) |
|
401 { |
|
402 return; |
|
403 } |
|
404 NM_LOG((KESockServerTag, _L8("CDummyFlow %08x:\tSynchronous call: From=%08x To=%08x Func=BindToL"), |
|
405 this, static_cast<Messages::ANode*>(this), &aBindTo.iNodeId.Node()) ) |
|
406 |
|
407 const TNodeId& commsId = aBindTo.iNodeId; |
|
408 |
|
409 #if defined(__GCCXML__) |
|
410 CSubConnectionFlowBase* flow = reinterpret_cast<CSubConnectionFlowBase*>(&commsId.Node()); |
|
411 #else |
|
412 CSubConnectionFlowBase* flow = Messages::mnode_cast<CSubConnectionFlowBase>(&commsId.Node()); |
|
413 #endif |
|
414 |
|
415 // Flows can only be directly bound when running in the same thread |
|
416 __ASSERT_DEBUG(commsId.Thread() == Id().Thread(), User::Panic(KSpecAssert_ESockTestdmyprnt, 47)); |
|
417 |
|
418 if (iLowerFlowBinderControl && iLowerFlowBinderControl->Flow() != flow ) |
|
419 { |
|
420 // Already bound to something else so unbind first |
|
421 iLowerFlowBinderControl->Unbind(NULL,NULL); |
|
422 iLowerFlowBinderControl = NULL; |
|
423 |
|
424 iLowerFlowBinderControl->Unbind(); |
|
425 iLowerFlowControl = NULL; |
|
426 iLowerFlowData = NULL; |
|
427 } |
|
428 |
|
429 if (iLowerFlowBinderControl == NULL) |
|
430 { |
|
431 // Protocol binding |
|
432 iLowerFlowBinderControl = flow->GetBinderControlL(); |
|
433 iLowerFlowControl = iLowerFlowBinderControl->GetControlL(KSockDatagram, *this); |
|
434 iLowerFlowData = iLowerFlowBinderControl->BindL(*this); |
|
435 } |
|
436 } |
|
437 |
|
438 |
|
439 |