datacommsserver/esockserver/test/providers/dummy/src/dummypr_network_flow.cpp
changeset 0 dfb7c4ff071f
child 12 8b5d60ce1e94
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/datacommsserver/esockserver/test/providers/dummy/src/dummypr_network_flow.cpp	Thu Dec 17 09:22:25 2009 +0200
@@ -0,0 +1,584 @@
+// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Dummy implementation file for network tier flow
+//
+//
+
+/**
+ @file
+ @internalComponent
+*/
+
+#include <ss_std.h>
+#include <comms-infras/ss_log.h>
+#include <ss_pman.h>
+#include "dummypr_network_flow.h"
+#include <comms-infras/ss_sapshim.h>
+#include <comms-infras/ss_nodemessages_internal_esock.h>
+
+
+#ifdef _DEBUG
+// Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module
+// (if it could happen through user error then you should give it an explicit, documented, category + code)
+_LIT(KSpecAssert_ESockTestdmyprnt, "ESockTestdmyprnt");
+#endif
+
+using namespace ESock;
+using namespace Messages;
+
+#if defined(_DEBUG)
+void ESockLog::Printf(TRefByValue<const TDesC> /*aFmt*/,...) {}
+void ESockLog::Printf(TRefByValue<const TDesC8> /*aFmt*/,...) {}
+void ESockLog::Printf(const TDesC8& /*aSubTag*/, TRefByValue<const TDesC8> /*aFmt*/, ...) {}
+void ESockLog::Printf(const TDesC8& /*aSubTag*/, TRefByValue<const TDesC> /*aFmt*/, ...) {}
+void ESockLog::Printf(const TDesC8& /*aMajorTag*/, const TDesC8& /*aSubTag*/, TRefByValue<const TDesC> /*aFmt*/, VA_LIST& /*aList*/) {}
+#endif
+
+
+
+// Construction
+//-------------
+CDummyNetworkFlow* CDummyNetworkFlow::NewL(CSubConnectionFlowFactoryBase& aFactory, const Messages::TNodeId& aSubConn, CProtocolIntfBase* aProtocolIntf)
+	{
+	CDummyNetworkFlow* self = new (ELeave) CDummyNetworkFlow(aFactory, aSubConn, aProtocolIntf);
+	return self;
+	}
+
+CDummyNetworkFlow::CDummyNetworkFlow(CSubConnectionFlowFactoryBase& aFactory, const Messages::TNodeId& aSubConn, CProtocolIntfBase* aProtocolIntf)
+: CSubConnectionFlowBase(aFactory, aSubConn, aProtocolIntf)
+	{
+    LOG_NODE_CREATE(KESockFlowTag, CDummyNetworkFlow)
+	}
+
+CDummyNetworkFlow::~CDummyNetworkFlow()
+	{
+	TEBase::TError err(
+		TEBase::TNull::Id(),
+		KErrBindersInvalid);
+
+    SubConnectionError(err, EErrorAllOperations);
+    LOG_NODE_DESTROY(KESockFlowTag, CDummyNetworkFlow)
+	}
+
+MSessionControl* CDummyNetworkFlow::GetControlL(
+	TInt /*aSessionType*/,
+	MSessionControlNotify& aSessionControlNotify)
+    {
+	// Apply binding locally
+	__ASSERT_DEBUG(iSessionControlNotify == NULL, User::Panic(KSpecAssert_ESockTestdmyprnt, 1));
+	iSessionControlNotify = &aSessionControlNotify;
+
+    // We should already be bound to the transport shim flow below
+    __ASSERT_DEBUG(iLowerFlow, User::Panic(KSpecAssert_ESockTestdmyprnt, 2));
+	return this;
+    }
+
+MSessionData* CDummyNetworkFlow::BindL(MSessionDataNotify& aNotify)
+    {
+	LOG( ESockLog::Printf(_L8("CDummyNetworkFlow %08x:\tBindL(aNotify 0x%08x)"), this, &aNotify) );
+
+	// Apply binding locally
+	__ASSERT_DEBUG(iSessionDataNotify == NULL, User::Panic(KSpecAssert_ESockTestdmyprnt, 3));
+	iSessionDataNotify = &aNotify;
+	iSubConnectionProvider.RNodeInterface::PostMessage(
+		Id(),
+		TCFControlProvider::TActive().CRef());
+
+    // We should already be bound to the transport shim flow below
+	__ASSERT_DEBUG(iFlowShim, User::Panic(KSpecAssert_ESockTestdmyprnt, 4));
+	return this;
+    }
+
+void CDummyNetworkFlow::Unbind()
+    {
+	LOG( ESockLog::Printf(_L8("CDummyNetworkFlow %08x:\tUnbind()"), this) );
+
+    // Forward to the flow shim beneath us
+	iLowerFlow->Unbind();
+
+    // And the local unbinding
+    if (iSessionDataNotify)
+    	{
+    	iSessionControlNotify = NULL;
+		iSessionDataNotify = NULL;
+
+		__ASSERT_DEBUG(iSubConnectionProvider.IsOpen(), User::Panic(KSpecAssert_ESockTestdmyprnt, 5));
+		if(iDCIdle < EIdle)
+			{
+			iDCIdle = EIdle;
+			ProcessDCIdleState();
+			}
+    	}
+    }
+
+ESock::CSubConnectionFlowBase& CDummyNetworkFlow::CloneFlowL()
+    {
+    TDefaultFlowFactoryQuery query (iProtocolIntf->ControlProviderId(), iSubConnectionProvider.RecipientId());
+
+	ESock::CSubConnectionFlowBase& flow = static_cast<ESock::CSubConnectionFlowBase&>(*(Factory().CreateObjectL(query)));
+
+	// Have the new flow become a data client of our subconnection too
+	__ASSERT_DEBUG(iSubConnectionProvider.IsOpen(), User::Panic(KSpecAssert_ESockTestdmyprnt, 6));
+	TCFPeer::TJoinRequest msg(
+		flow.Id(),
+		TCFClientType(TCFClientType::EData, TCFClientType::EActive)
+		);
+
+	iSubConnectionProvider.PostMessage(Id(), msg);
+
+	return flow;
+    }
+
+CSubConnectionFlowBase* CDummyNetworkFlow::Flow()
+	{
+	return this;
+	}
+
+
+// MSessionControl
+//----------------
+void CDummyNetworkFlow::Start()
+	{__ASSERT_DEBUG(iFlowShim, User::Panic(KSpecAssert_ESockTestdmyprnt, 7)); return iFlowShim->Start();}
+
+void CDummyNetworkFlow::LocalName(TSockAddr& anAddr) const
+	{__ASSERT_DEBUG(iFlowShim, User::Panic(KSpecAssert_ESockTestdmyprnt, 8)); return iFlowShim->LocalName(anAddr);}
+void CDummyNetworkFlow::SetLocalName(TSockAddr& anAddr)
+	{
+	__ASSERT_DEBUG(iFlowShim, User::Panic(KSpecAssert_ESockTestdmyprnt, 54));
+	iFlowShim->SetLocalName(anAddr);
+	}
+
+void CDummyNetworkFlow::RemName(TSockAddr& anAddr) const
+	{__ASSERT_DEBUG(iFlowShim, User::Panic(KSpecAssert_ESockTestdmyprnt, 10)); iFlowShim->RemName(anAddr);}
+
+TInt CDummyNetworkFlow::SetRemName(TSockAddr& anAddr)
+	{__ASSERT_DEBUG(iFlowShim, User::Panic(KSpecAssert_ESockTestdmyprnt, 11)); return iFlowShim->SetRemName(anAddr);}
+
+const TInt KDummyNetworkFlowOptionLevel = CDummyNetworkFlowFactory::iUid;
+const TInt KFlowProtocolName = 1;
+
+TInt CDummyNetworkFlow::GetOption(TUint aLevel, TUint aName, TDes8& anOption) const
+	{
+	__ASSERT_DEBUG(iFlowShim, User::Panic(KSpecAssert_ESockTestdmyprnt, 12));
+
+	if(aLevel == KDummyNetworkFlowOptionLevel && aName == KFlowProtocolName)
+		{
+		anOption.Copy(KDummyProtocolName);
+		return KErrNone;
+		}
+	else
+		{
+		return iFlowShim->GetOption(aLevel, aName, anOption);
+		}
+	}
+
+void CDummyNetworkFlow::Ioctl(TUint aLevel, TUint aName, TDes8* anOption)
+	{__ASSERT_DEBUG(iFlowShim, User::Panic(KSpecAssert_ESockTestdmyprnt, 13)); iFlowShim->Ioctl(aLevel, aName, anOption);}
+
+void CDummyNetworkFlow::CancelIoctl(TUint aLevel, TUint aName)
+	{__ASSERT_DEBUG(iFlowShim, User::Panic(KSpecAssert_ESockTestdmyprnt, 14)); iFlowShim->CancelIoctl(aLevel, aName);}
+
+TInt CDummyNetworkFlow::SetOption(TUint aLevel, TUint aName, const TDesC8 &anOption)
+	{__ASSERT_DEBUG(iFlowShim, User::Panic(KSpecAssert_ESockTestdmyprnt, 15)); return iFlowShim->SetOption(aLevel, aName, anOption);}
+
+void CDummyNetworkFlow::ActiveOpen()
+	{__ASSERT_DEBUG(iFlowShim, User::Panic(KSpecAssert_ESockTestdmyprnt, 16)); iFlowShim->ActiveOpen();}
+
+void CDummyNetworkFlow::ActiveOpen(const TDesC8& aConnectionData)
+	{__ASSERT_DEBUG(iFlowShim, User::Panic(KSpecAssert_ESockTestdmyprnt, 17)); iFlowShim->ActiveOpen(aConnectionData);}
+
+TInt CDummyNetworkFlow::PassiveOpen(TUint aQueueSize)
+	{__ASSERT_DEBUG(iFlowShim, User::Panic(KSpecAssert_ESockTestdmyprnt, 18)); return iFlowShim->PassiveOpen(aQueueSize);}
+
+TInt CDummyNetworkFlow::PassiveOpen(TUint aQueueSize, const TDesC8& aConnectionData)
+	{__ASSERT_DEBUG(iFlowShim, User::Panic(KSpecAssert_ESockTestdmyprnt, 19)); return iFlowShim->PassiveOpen(aQueueSize, aConnectionData);}
+
+void CDummyNetworkFlow::Shutdown(MSessionControl::TCloseType aOption)
+	{__ASSERT_DEBUG(iFlowShim, User::Panic(KSpecAssert_ESockTestdmyprnt, 20)); iFlowShim->Shutdown(aOption);}
+
+void CDummyNetworkFlow::Shutdown(MSessionControl::TCloseType aOption, const TDesC8& aDisconnectionData)
+	{__ASSERT_DEBUG(iFlowShim, User::Panic(KSpecAssert_ESockTestdmyprnt, 21)); iFlowShim->Shutdown(aOption, aDisconnectionData);}
+
+void CDummyNetworkFlow::AutoBind()
+	{__ASSERT_DEBUG(iFlowShim, User::Panic(KSpecAssert_ESockTestdmyprnt, 22));	iFlowShim->AutoBind();}
+
+TInt CDummyNetworkFlow::SecurityCheck(MProvdSecurityChecker* aChecker)
+	{__ASSERT_DEBUG(iFlowShim, User::Panic(KSpecAssert_ESockTestdmyprnt, 23));	return iFlowShim->SecurityCheck(aChecker);}
+
+
+// MSessionData
+//-------------
+TUint CDummyNetworkFlow::Write(const TDesC8& aDesc, TUint aOptions, TSockAddr* anAddr)
+	{__ASSERT_DEBUG(iFlowShimData, User::Panic(KSpecAssert_ESockTestdmyprnt, 24));	return iFlowShimData->Write(aDesc, aOptions, anAddr);}
+
+TInt CDummyNetworkFlow::Write(RMBufChain& aData, TUint aOptions, TSockAddr* anAddr)
+	{__ASSERT_DEBUG(iFlowShimData, User::Panic(KSpecAssert_ESockTestdmyprnt, 25));	return iFlowShimData->Write(aData, aOptions, anAddr);}
+
+void CDummyNetworkFlow::GetData(TDes8& aDesc, TUint aOptions, TSockAddr* anAddr)
+	{__ASSERT_DEBUG(iFlowShimData, User::Panic(KSpecAssert_ESockTestdmyprnt, 26));	iFlowShimData->GetData(aDesc, aOptions, anAddr);}
+
+TInt CDummyNetworkFlow::GetData(RMBufChain& aData, TUint aLength, TUint aOptions, TSockAddr* anAddr)
+	{__ASSERT_DEBUG(iFlowShimData, User::Panic(KSpecAssert_ESockTestdmyprnt, 27));	return iFlowShimData->GetData(aData, aLength, aOptions, anAddr);}
+
+
+// MSessionControlNotify
+//----------------------
+void CDummyNetworkFlow::ConnectComplete()
+	{__ASSERT_DEBUG(iSessionControlNotify, User::Panic(KSpecAssert_ESockTestdmyprnt, 28));	iSessionControlNotify->ConnectComplete();}
+
+void CDummyNetworkFlow::ConnectComplete(const TDesC8& aConnectData)
+	{__ASSERT_DEBUG(iSessionControlNotify, User::Panic(KSpecAssert_ESockTestdmyprnt, 29));	iSessionControlNotify->ConnectComplete(aConnectData);}
+
+void CDummyNetworkFlow::ConnectComplete(CSubConnectionFlowBase& anSSP)
+	{__ASSERT_DEBUG(iSessionControlNotify, User::Panic(KSpecAssert_ESockTestdmyprnt, 30));	iSessionControlNotify->ConnectComplete(anSSP);}
+
+void CDummyNetworkFlow::ConnectComplete(CSubConnectionFlowBase& anSSP,const TDesC8& aConnectData)
+	{__ASSERT_DEBUG(iSessionControlNotify, User::Panic(KSpecAssert_ESockTestdmyprnt, 31));	iSessionControlNotify->ConnectComplete(anSSP, aConnectData);}
+
+void CDummyNetworkFlow::CanClose(MSessionControlNotify::TDelete aDelete)
+	{__ASSERT_DEBUG(iSessionControlNotify, User::Panic(KSpecAssert_ESockTestdmyprnt, 32));	iSessionControlNotify->CanClose(aDelete);}
+
+void CDummyNetworkFlow::CanClose(
+	const TDesC8& aDisconnectData,
+	MSessionControlNotify::TDelete aDelete)
+	{__ASSERT_DEBUG(iSessionControlNotify, User::Panic(KSpecAssert_ESockTestdmyprnt, 33));	iSessionControlNotify->CanClose(aDisconnectData, aDelete);}
+
+TInt CDummyNetworkFlow::Error(TInt anError,TUint anOperationMask)
+	{__ASSERT_DEBUG(iSessionControlNotify, User::Panic(KSpecAssert_ESockTestdmyprnt, 34));	return iSessionControlNotify->Error(anError, anOperationMask);}
+
+void CDummyNetworkFlow::Disconnect()
+	{__ASSERT_DEBUG(iSessionControlNotify, User::Panic(KSpecAssert_ESockTestdmyprnt, 35));	iSessionControlNotify->Disconnect();}
+
+void CDummyNetworkFlow::Disconnect(TDesC8& aDisconnectData)
+	{__ASSERT_DEBUG(iSessionControlNotify, User::Panic(KSpecAssert_ESockTestdmyprnt, 36));	iSessionControlNotify->Disconnect(aDisconnectData);}
+
+void CDummyNetworkFlow::IoctlComplete(TDesC8* aBuf)
+	{__ASSERT_DEBUG(iSessionControlNotify, User::Panic(KSpecAssert_ESockTestdmyprnt, 37));	iSessionControlNotify->IoctlComplete(aBuf);}
+
+void CDummyNetworkFlow::DisconnectFromListener(CSubConnectionFlowBase& aSSP)
+	{
+		__ASSERT_DEBUG(iSessionControlNotify, User::Panic(KSpecAssert_ESockTestdmyprnt, 53));
+        iSessionControlNotify->DisconnectFromListener(aSSP);
+    }
+void CDummyNetworkFlow::SetLocalNameComplete()
+	{
+	__ASSERT_DEBUG(iSessionControlNotify, User::Panic(KSpecAssert_ESockTestdmyprnt, 52));
+	iSessionControlNotify->SetLocalNameComplete();
+	}
+
+// MSessionDataNotify
+//-------------------
+void CDummyNetworkFlow::NewData(TUint aCount)
+	{__ASSERT_DEBUG(iSessionDataNotify, User::Panic(KSpecAssert_ESockTestdmyprnt, 39)); iSessionDataNotify->NewData(aCount);}
+
+void CDummyNetworkFlow::CanSend()
+	{__ASSERT_DEBUG(iSessionDataNotify, User::Panic(KSpecAssert_ESockTestdmyprnt, 40)); iSessionDataNotify->CanSend();}
+
+MFlowBinderControl* CDummyNetworkFlow::DoGetBinderControlL()
+	{
+	return this;
+	}
+
+
+// Node stuff
+//-----------
+void CDummyNetworkFlow::ReceivedL(const TRuntimeCtxId& aSender, const TNodeId& aRecipient, TSignatureBase& aMessage)
+    {
+    CSubConnectionFlowBase::ReceivedL(aSender, aRecipient, aMessage);
+
+	if ( aMessage.IsMessage<TEBase::TError>() )
+		{
+		SubConnectionError(static_cast<TEBase::TError&>(aMessage));
+		}
+	else if (TEChild::ERealmId == aMessage.MessageId().Realm())
+		{
+		switch (aMessage.MessageId().MessageId())
+			{
+		case TEChild::TDestroy::EId :
+			Destroy();
+			break;
+		default:
+			//TODO - logging
+			//LOG(ESockLog::Printf(KESockMetaConnectionTag, _L("ERROR: CTransportFlowShim %08x:\tReceivedL(%s) - KErrNotSupported"), this, aMessage.Printable()));
+			__ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockTestdmyprnt, 41)); //For debug configurations
+			User::Leave(KErrNotSupported); //For release configurations
+			}
+		}
+	else if (TCFDataClient::ERealmId == aMessage.MessageId().Realm())
+		{
+		switch (aMessage.MessageId().MessageId())
+			{
+		case TCFDataClient::TStart::EId :
+			StartFlow();
+			break;
+		case TCFDataClient::TStop::EId :
+			StopFlow(static_cast<TCFDataClient::TStop&>(aMessage));
+			break;
+		case TCFDataClient::TProvisionConfig::EId:
+			break;
+		case TCFDataClient::TBindTo::EId:
+		{
+			TCFDataClient::TBindTo& bindToMsg(static_cast<TCFDataClient::TBindTo&>(aMessage));
+			TRAPD(err,BindToL(bindToMsg));
+			ProcessDCIdleState();	// in case we were waiting to send idle
+			RClientInterface::OpenPostMessageClose(Id(), aSender, TCFDataClient::TBindToComplete(err).CRef());
+			//If we have received TCDDataClient::TStart before (when we did not yet have a bearer),
+			//we complete the start here as well
+			if (iIsStarting)
+				{
+				CompleteStart(err);
+				}
+		}
+			break;
+		default:
+			//TODO - logging
+			//LOG(ESockLog::Printf(KESockMetaConnectionTag, _L("ERROR: CTransportFlowShim %08x:\tReceivedL(%s) - KErrNotSupported"), this, aMessage.Printable()));
+			__ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockTestdmyprnt, 42)); //For debug configurations
+			User::Leave(KErrNotSupported); //For release configurations
+			}
+		}
+	else if (TCFFlow::ERealmId == aMessage.MessageId().Realm())
+		{
+		switch (aMessage.MessageId().MessageId())
+			{
+		case TCFFlow::TRejoin::EId :
+			Rejoin(static_cast<TCFFlow::TRejoin&>(aMessage));
+			break;
+		default:
+			//TODO - logging
+			//LOG(ESockLog::Printf(KESockMetaConnectionTag, _L("ERROR: CTransportFlowShim %08x:\tReceivedL(%s) - KErrNotSupported"), this, aMessage.Printable()));
+			__ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockTestdmyprnt, 43)); //For debug configurations
+			User::Leave(KErrNotSupported); //For release configurations
+			}
+		}
+	else if (TCFInternalEsock::ERealmId == aMessage.MessageId().Realm())
+		{
+		switch (aMessage.MessageId().MessageId())
+			{
+		case TCFInternalEsock::TFlowProvision::EId :
+			break;
+		default:
+			//TODO - logging
+			//LOG(ESockLog::Printf(KESockMetaConnectionTag, _L("ERROR: CTransportFlowShim %08x:\tReceivedL(%s) - KErrNotSupported"), this, aMessage.Printable()));
+			__ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockTestdmyprnt, 44)); //For debug configurations
+			User::Leave(KErrNotSupported); //For release configurations
+			}
+		}
+	else if ( aMessage.IsMessage<TCFPeer::TJoinComplete>() )
+		{;}
+	else
+		{
+		//TODO - logging
+		//LOG(ESockLog::Printf(KESockMetaConnectionTag, _L("ERROR: CTransportFlowShim %08x:\tReceivedL(%s) - KErrNotSupported"), this, aMessage.Printable()));
+    	__ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockTestdmyprnt, 45)); //For debug configurations
+    	User::Leave(KErrNotSupported); //For release configurations
+		}
+    }
+
+void CDummyNetworkFlow::SubConnectionError(
+	const TEBase::TError& errorMsg,
+	TUint anOperationMask)
+	{
+	if (errorMsg.iMsgId == TCFControlProvider::TNoBearer::Id())
+		{
+		ClearNoBearerGuard();
+		}
+
+	if (IsBoundToSession())
+	    {
+    	Error(errorMsg.iValue, anOperationMask);
+	    }
+	}
+
+void CDummyNetworkFlow::BindToL(TCFDataClient::TBindTo& aBindTo)
+/**
+Request from control side (at network layer) to indicate that the SubConnection is
+up and running and that we should bind to a Flow below.
+
+@param aLowerFlow Flow below to bind to.
+*/
+	{
+	//provisioning message must come before bindto in case we didn't get it after we've joined
+	//the sub-connection
+	NM_LOG((KESockServerTag, _L8("CDummyNetworkFlow %08x:\tSynchronous call: From=%08x To=%08x Func=BindToL"),
+			this, static_cast<Messages::ANode*>(this), &aBindTo.iNodeId.Node()) )
+
+	ClearNoBearerGuard();
+
+	const TNodeId& commsId = aBindTo.iNodeId;
+
+#if defined(__GCCXML__)
+    CSubConnectionFlowBase* flow = reinterpret_cast<CSubConnectionFlowBase*>(&commsId.Node());
+#else
+	CSubConnectionFlowBase* flow = Messages::mnode_cast<CSubConnectionFlowBase>(&commsId.Node());
+#endif
+
+	if (flow == NULL)
+		{
+		__ASSERT_DEBUG(!commsId.IsNull(), User::Panic(KSpecAssert_ESockTestdmyprnt, 46));
+		iSubConnectionProvider.PostMessage(
+			Id(),
+			TCFDataClient::TStopped(KErrDisconnected).CRef()
+			);
+		}
+
+	// Flows can only be directly bound when running in the same thread
+	__ASSERT_DEBUG(commsId.Thread() == Id().Thread(), User::Panic(KSpecAssert_ESockTestdmyprnt, 47));
+
+	if (iLowerFlow && iLowerFlow->Flow() != flow )
+		{
+		// Already bound to something else so unbind first
+		iLowerFlow->Unbind(NULL,NULL);
+		iLowerFlow = NULL;
+		iLowerControl = NULL;
+
+		iLowerFlow->Unbind();
+		iFlowShim = NULL;
+		iFlowShimData = NULL;
+		}
+
+	if (iLowerFlow == NULL)
+		{
+		// Protocol binding
+		iLowerFlow = flow->GetBinderControlL();
+		iFlowShim = iLowerFlow->GetControlL(KSockDatagram, *this);
+		iFlowShimData = iLowerFlow->BindL(*this);
+		}
+	}
+
+
+void CDummyNetworkFlow::Rejoin(const TCFFlow::TRejoin& aRejoinMessage)
+    {
+	LOG( ESockLog::Printf(_L("CDummyNetworkFlow %08x:\tRejoin()"), this ));
+	iSubConnectionProvider.Close();
+	iSubConnectionProvider.Open(TNodeCtxId(0, aRejoinMessage.iNodeId));
+    //If already bound there's a potential need to rebind.
+    //As the new control provider for the flow - if different than
+    //the current, rebind.
+    if (iLowerFlow)
+        {
+        PostNoBearer();
+        }
+    }
+
+void CDummyNetworkFlow::StartFlow()
+	{
+	__ASSERT_DEBUG(!iIsStarted, User::Panic(KSpecAssert_ESockTestdmyprnt, 48));
+	__ASSERT_DEBUG(iSubConnectionProvider.IsOpen(), User::Panic(KSpecAssert_ESockTestdmyprnt, 49));	// legacy flows have no control side; should never get here
+
+	if (iDCIdle != EClientsPresent)
+		{
+		iSubConnectionProvider.PostMessage(Id(), TEBase::TError(TCFDataClient::TStart::Id(), KErrNotReady).CRef());
+		return;
+		}
+
+	if (iLowerFlow)
+		{
+		iSubConnectionProvider.PostMessage(Id(), TCFDataClient::TStarted().CRef());
+		iIsStarted = ETrue;
+		iIsStopped = EFalse;
+		return;
+		}
+
+	//We need a bearer
+	if (!NoBearerGuard())
+		{
+		PostNoBearer(); //Ask for bearer if not requested already
+		}
+
+	//We will wait for it and complete the start after we have received it
+	iIsStarting = ETrue;
+	}
+
+void CDummyNetworkFlow::StopFlow(TCFDataClient::TStop& aMessage)
+	{
+	__ASSERT_DEBUG(iIsStarted, User::Panic(KSpecAssert_ESockTestdmyprnt, 50)); //Must be started now
+	__ASSERT_DEBUG(iSubConnectionProvider.IsOpen(), User::Panic(KSpecAssert_ESockTestdmyprnt, 51));	// legacy flows have no control side; should never get here
+
+	// We need to error the socket if the lower protocol stack is not going to do this.  Once a
+	// Bearer() upcall has been received, the lower protocol will call Error() if the connection
+	// goes down.  Before this point, the lower protocol will not call Error(), so StopFlow() calls
+	// from the SCPR are used to error the socket (if the interface start fails).
+	//
+	// The main scenario is the TCP/IP stack as lower protocol which will only call Error() once it
+	// has attached a flow to a route (and hence an interface) which, in turn, only occurs once the
+	// interface is up and data has been sent over the socket.  Note that opening an RSocket on an
+	// RConnection but not transferring any data will not cause the TCP/IP stack to attach the flow
+	// to the route and hence not call Error() if the interface comes down.
+	//
+	// Note that it is possible for the SCPR to send DataClientStop messages in all circumstances, and
+	// the CTransportFlowShim will simply ignore them.  However, this is considered very
+	// inefficient as the common case scenario will mean that these StopFlow/FlowDown exchanges
+	// sent to every socket on a connection by the SCPR will most of the time be ignored by the
+	// CTransportFlowShim and hence obsolete.
+
+	if (IsBoundToSession() && !iUseBearerErrors)
+	    {
+    	Error(aMessage.iValue, EErrorAllOperations);
+	    }
+
+	if (iLowerFlow)
+		{
+		iLowerFlow->Unbind(NULL,NULL);
+		iLowerFlow = NULL;
+		}
+	iLowerControl = NULL;
+
+	iSubConnectionProvider.PostMessage(Id(), TCFDataClient::TStopped(aMessage.iValue).CRef());
+	iIsStarted = EFalse;
+	iIsStopped = ETrue;
+	}
+
+void CDummyNetworkFlow::ProcessDCIdleState()
+	{
+	if(iDCIdle == EIdle && !iNoBearerRunning)
+		{
+		iDCIdle = EIdleSent;
+		iSubConnectionProvider.RNodeInterface::PostMessage(
+			Id(),
+			TCFControlProvider::TIdle().CRef()
+			);
+		}
+	}
+
+void CDummyNetworkFlow::CompleteStart(TInt aError)
+	{
+	if (aError==KErrNone)
+		{
+		iStartRequest.ReplyTo(Id(), TCFDataClient::TStarted().CRef());
+		iIsStarted = ETrue;
+		iIsStopped = EFalse;
+		}
+	else
+		{
+		iStartRequest.ReplyTo(Id(), TEBase::TError(TCFDataClient::TStart::Id(),aError).CRef());
+		}
+	iIsStarting = EFalse;
+	}
+
+void CDummyNetworkFlow::Destroy()
+	{
+	DeleteThisFlow();
+	}
+
+void CDummyNetworkFlow::PostNoBearer()
+	{
+	if (!NoBearerGuard())
+		{
+		iSubConnectionProvider.PostMessage(Id(), TCFControlProvider::TNoBearer().CRef());
+		SetNoBearerGuard();
+		}
+	}
+
+