datacommsserver/esockserver/test/providers/dummy/src/dummypr_flow.cpp
branchRCL_3
changeset 18 9644881fedd0
equal deleted inserted replaced
17:9ddb1d67ebaf 18:9644881fedd0
       
     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