commsfwutils/commsbufs/reference/loopback_bearer/src/flow.cpp
changeset 0 dfb7c4ff071f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commsfwutils/commsbufs/reference/loopback_bearer/src/flow.cpp	Thu Dec 17 09:22:25 2009 +0200
@@ -0,0 +1,506 @@
+/*
+* Copyright (c) 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: 
+*
+*/
+#include <e32std.h>
+#include <ecom/ecom.h>
+#include <ecom/implementationproxy.h>
+#include <elements/nm_messages_base.h>
+#include <elements/nm_messages_child.h>
+
+#ifdef SYMBIAN_OLD_EXPORT_LOCATION
+#include "ss_subconnflow.h"
+#else
+#include <comms-infras/ss_subconnflow.h>
+#endif
+
+#include <comms-infras/ss_log.h>
+#include "flow.h"
+#include "binder.h"
+#include "provision.h"
+
+using namespace Messages;
+using namespace MeshMachine;
+using namespace ESock;
+
+_LIT8(KNif,"legacy_loopback_link_protocol");
+
+CLegacyLoopbackSubConnectionFlowFactory* CLegacyLoopbackSubConnectionFlowFactory::NewL(TAny* aConstructionParameters)
+/**
+Constructs a Default SubConnection Flow Factory
+
+@param aConstructionParameters construction data passed by ECOM
+
+@returns pointer to a constructed factory
+*/
+	{
+	CLegacyLoopbackSubConnectionFlowFactory* ptr = new (ELeave) CLegacyLoopbackSubConnectionFlowFactory(TUid::Uid(KLegacyLoopbackFlowImplementationUid), *(reinterpret_cast<CSubConnectionFlowFactoryContainer*>(aConstructionParameters)));
+	return ptr;
+	}
+
+
+CLegacyLoopbackSubConnectionFlowFactory::CLegacyLoopbackSubConnectionFlowFactory(TUid aFactoryId, CSubConnectionFlowFactoryContainer& aParentContainer)
+:	CSubConnectionFlowFactoryBase(aFactoryId, aParentContainer)
+/**
+Default SubConnection Flow Factory Constructor
+
+@param aFactoryId ECOM Implementation Id
+@param aParentContainer Object Owner
+*/
+	{
+	}
+
+
+CSubConnectionFlowBase* CLegacyLoopbackSubConnectionFlowFactory::DoCreateFlowL(CProtocolIntfBase* aProtocolIntf, TFactoryQueryBase& aQuery)
+	{
+	const TDefaultFlowFactoryQuery& query = static_cast<const TDefaultFlowFactoryQuery&>(aQuery);
+	return CLegacyLoopbackSubConnectionFlow::NewL(*this, query.iSCprId, aProtocolIntf);
+	}
+
+
+//=======================================================================================
+// CLegacyLoopbackSubConnectionFlow
+//
+
+CLegacyLoopbackSubConnectionFlow::CLegacyLoopbackSubConnectionFlow(CSubConnectionFlowFactoryBase& aFactory, const TNodeId& aSubConnId, CProtocolIntfBase* aProtocolIntf)
+:	CSubConnectionFlowBase(aFactory, aSubConnId, aProtocolIntf)
+	{
+    __FLOG_OPEN(KCFNodeTag, KNif);
+    LOG_NODE_CREATE(KNif, CLegacyLoopbackSubConnectionFlow);
+    }
+
+CLegacyLoopbackSubConnectionFlow::~CLegacyLoopbackSubConnectionFlow()
+/**
+Destroys 'this'
+*/
+    {
+    ASSERT(iBinder4 == NULL);
+    ASSERT(iBinder6 == NULL);
+
+    LOG_NODE_DESTROY(KNif, CLegacyLoopbackSubConnectionFlow);
+    __FLOG_CLOSE;
+    }
+
+CLegacyLoopbackSubConnectionFlow* CLegacyLoopbackSubConnectionFlow::NewL(CSubConnectionFlowFactoryBase& aFactory, const TNodeId& aSubConnId, CProtocolIntfBase* aProtocolIntf)
+	{
+	CLegacyLoopbackSubConnectionFlow* flow = new (ELeave) CLegacyLoopbackSubConnectionFlow(aFactory, aSubConnId, aProtocolIntf);
+	return flow;
+	}
+
+// Methods called from Binders
+
+void CLegacyLoopbackSubConnectionFlow::FlowDown(TInt aError, TInt aAction /*= MNifIfNotify::EDisconnect*/)
+/**
+Binder requesting a FlowDown() message be sent to SCPR
+*/
+    {
+	PostFlowDownMessage(aError, aAction);
+	iAgentProvision = NULL;
+    }
+
+void CLegacyLoopbackSubConnectionFlow::Progress(TInt aStage, TInt aError)
+/**
+Binder requesting a Progress() message be sent to SCPR
+*/
+    {
+    PostProgressMessage(aStage, aError);
+    }
+
+const TLegacyLoopbackIp6Provision* CLegacyLoopbackSubConnectionFlow::Ip6Provision() const
+/**
+Return a pointer to the IPv6 provisioning structure
+*/
+	{
+	ASSERT(iProvision);
+	return &iProvision->iIp6Provision;
+	}
+
+const TLegacyLoopBackAgentProvision* CLegacyLoopbackSubConnectionFlow::AgentProvision() const
+/**
+Return a pointer to the Agent provisioning structure
+*/
+	{
+	ASSERT(iAgentProvision);
+	return iAgentProvision;
+	}
+
+//-=========================================================
+// Messages::ANode methods
+//-=========================================================
+
+void CLegacyLoopbackSubConnectionFlow::ReceivedL(const TRuntimeCtxId& aSender, const TNodeId& aRecipient, TSignatureBase& aMessage)
+/**
+Method called on incoming SCPR messages
+
+@param aCFMessage message base
+*/
+    {
+    CSubConnectionFlowBase::ReceivedL(aSender, aRecipient, aMessage);
+	if (aMessage.IsMessage<TEBase::TError>())
+		{
+		SubConnectionError(static_cast<TEBase::TError&>(aMessage).iValue);
+		}
+	else if (TEChild::ERealmId == aMessage.MessageId().Realm())
+		{
+		switch (aMessage.MessageId().MessageId())
+			{
+		case TEChild::TDestroy::EId :
+			Destroy();
+			break;
+		default:
+//TODO - logging
+			ASSERT(EFalse);
+			}
+		}
+	else if (TCFDataClient::ERealmId == aMessage.MessageId().Realm())
+		{
+		switch (aMessage.MessageId().MessageId())
+			{
+		case TCFDataClient::TStart::EId :
+			StartFlowL();
+			break;
+		case TCFDataClient::TStop::EId :
+			StopFlow(static_cast<TCFDataClient::TStop&>(aMessage).iValue);
+			break;
+		case TCFDataClient::TProvisionConfig::EId:
+			ProvisionConfig(static_cast<TCFDataClient::TProvisionConfig&>(aMessage).iConfig);
+			break;
+		case TCFDataClient::TBindTo::EId:
+            {
+			TCFDataClient::TBindTo& bindToReq = message_cast<TCFDataClient::TBindTo>(aMessage);
+			if (!bindToReq.iNodeId.IsNull())
+				{
+				User::Leave(KErrNotSupported);
+				}
+			RClientInterface::OpenPostMessageClose(Id(), aSender, TCFDataClient::TBindToComplete().CRef());
+            }
+			break;
+		default:
+//TODO - logging
+			ASSERT(EFalse);
+			}
+		}
+	else		// realm != TCFMessage::ERealmId
+		{
+		Panic(EUnexpectedMessage);
+		}
+    }
+
+//
+// Methods for handling received SCPR messages
+//
+
+void CLegacyLoopbackSubConnectionFlow::StartFlowL()
+	{
+    __FLOG(_L8("CLegacyLoopbackSubConnectionFlow:\tStartFlowL()"));
+    if (iDisableStart)
+    	{
+    	User::Leave(KErrCouldNotConnect);
+    	}
+
+    if (iFlowStarted)
+    	{
+    	//Flow can be started multiple times.
+    	//For example a start may fail on an upper layer in which case the upper layer will not be able
+    	//to stop our layer and we need to accept start again.
+    	PostProgressMessage(KLinkLayerOpen, KErrNone);
+    	PostDataClientStartedMessage();
+    	return;
+    	}
+
+    iFlowStarted = ETrue;
+
+	// If the processing of the ProvisionConfig message failed earlier, send the error response
+	// here to the StartFlow message as there is no response to ProvisionConfig.
+
+	User::LeaveIfError(iSavedError);
+
+	AgentProvisionConfigL();		// retrieve and validate the Agent provisioning information
+
+	PostProgressMessage(KLinkLayerOpen, KErrNone);
+	PostDataClientStartedMessage();
+
+	if (iBinder4)
+   	    {
+		iBinder4->BinderReady();
+       	}
+	if (iBinder6)
+		{
+		iBinder6->BinderReady();
+		}
+	}
+
+void CLegacyLoopbackSubConnectionFlow::StopFlow(TInt aError)
+	{
+    __FLOG_1(_L8("CLegacyLoopbackSubConnectionFlow:\tStopFlow(%d)"), aError);
+
+	PostProgressMessage(KLinkLayerClosed, aError);
+    iFlowStarted = EFalse;
+	PostFlowDownMessage(aError);
+	iAgentProvision = NULL;
+	}
+
+
+/*
+Provisioning description for Dummy CFProtocol Flow:
+
+- on receipt of the ProvisionConfig message, the pointer contained within it is stored
+  in iAccessPointConfig and the information contained within the iAccessPointConfig
+  array is validated:
+	- CDummyProtoProvision must be present.  It is added by the DummyProtoMCPr and populated from CommsDat.
+	  It is a 'C' class to take advantage of zero initialisation.
+  Any errors are saved in iSavedError - there is no response to ProvisionConfig, so an error
+  response is sent later to StartFlow message.
+
+- on receipt of TCFDataClient::TStart:
+  - iSavedError is checked and, if non-zero, an Error message is sent to the SCPr
+  - TLegacyLoopBackAgentProvision must be present.  It is added by the DummyAgentHandler and populated via calls
+	  to the Agent.  It is a 'T' class because it requires no zero initialisation.  If missing,
+	  an Error message is signalled to the SCPr.
+*/
+
+void CLegacyLoopbackSubConnectionFlow::ProvisionConfig(const ESock::RMetaExtensionContainerC& aConfigData)
+/**
+Save the provisioning structure pointer passed in the TProvisionConfig message
+
+@param aData pointer to provisioning structure
+*/
+	{
+	__FLOG_0(_L8("CLegacyLoopbackSubConnectionFlow:\tProvisionConfig message received"));
+
+	iAccessPointConfig.Close();
+	iAccessPointConfig.Open(aConfigData);
+
+	const CLegacyLoopbackProvision* provision = static_cast<const CLegacyLoopbackProvision*>(AccessPointConfig().FindExtension(
+		STypeId::CreateSTypeId(CLegacyLoopbackProvision::EUid, CLegacyLoopbackProvision::ETypeId)));
+	if (provision == NULL)
+		{
+		__FLOG_0(_L8("CLegacyLoopbackSubConnectionFlow:\tProvisionConfigL() - config not found"));
+		iSavedError = KErrCorrupt;
+		}
+
+	// Save pointer to provisioning information
+	iProvision = provision;
+	}
+
+
+void CLegacyLoopbackSubConnectionFlow::AgentProvisionConfigL()
+/**
+Validate and process the Agent provisioning information.
+
+This information is not valid when TProvisionConfig message is received, but only
+becomes valid at TCFDataClient::TStart.
+*/
+	{
+    const TLegacyLoopBackAgentProvision* agentProvision = static_cast<const TLegacyLoopBackAgentProvision*>(
+		AccessPointConfig().FindExtension(
+			STypeId::CreateSTypeId(TLegacyLoopBackAgentProvision::EUid, TLegacyLoopBackAgentProvision::ETypeId)));
+
+    if (agentProvision == NULL)
+        {
+        __FLOG_0(_L8("CLegacyLoopbackSubConnectionFlow:\tProvisionConfigL() - DummyProto Agent config not found"));
+		User::Leave(KErrCorrupt);
+        }
+
+	ASSERT(iAgentProvision == NULL);
+	iAgentProvision = agentProvision;
+	}
+
+void CLegacyLoopbackSubConnectionFlow::Destroy()
+/**
+Request from SCPR to destroy
+*/
+	{
+	// No-one should be bound to us from above if we are about to disappear.
+	ASSERT(iBinder4 == NULL && iBinder6 == NULL);
+	DeleteThisFlow();
+	}
+
+void CLegacyLoopbackSubConnectionFlow::SubConnectionGoingDown()
+	{
+    __FLOG(_L8("CLegacyLoopbackSubConnectionFlow:\tSubConnectionGoingDown"));
+	}
+
+void CLegacyLoopbackSubConnectionFlow::SubConnectionError(TInt /*aError*/)
+	{
+    __FLOG(_L8("CLegacyLoopbackSubConnectionFlow:\tSubConnectionError"));
+	}
+
+MFlowBinderControl* CLegacyLoopbackSubConnectionFlow::DoGetBinderControlL()
+/**
+Return MFlowBinderControl instance.
+
+Called by upper layer for binding
+
+@return MFlowBinderControl instance
+*/
+	{
+    __FLOG(_L8("CLegacyLoopbackSubConnectionFlow::DoGetBinderControlL"));
+	return this;
+	}
+
+//-=========================================================
+// MFlowBinderControl methods
+//
+
+MLowerControl* CLegacyLoopbackSubConnectionFlow::GetControlL(const TDesC8& aProtocol)
+/**
+Create and return an MLowerControl instance of the specified binder type.
+
+Called from upper layer during binding procedure.
+
+@param aProtocol Protocol type of the binder
+@return MLowerControl instance of the protocol type
+*/
+	{
+
+	MLowerControl* lowerControl = NULL;
+
+	if (aProtocol.CompareF(KProtocol4()) == 0)
+		{
+        __FLOG(_L8("CLegacyLoopbackSubConnectionFlow:\tGetLowerControlL(KProtocol4)"));
+		iBinder4 = CLegacyLoopbackBinder4::NewL(*this);
+		lowerControl = iBinder4;
+		}
+	else
+	if (aProtocol.CompareF(KProtocol6()) == 0)
+		{
+        __FLOG(_L8("CLegacyLoopbackSubConnectionFlow::GetLowerControlL(KProtocol6)"));
+
+        iBinder6 = CLegacyLoopbackBinder6::NewL(*this);
+		lowerControl = iBinder6;
+		}
+
+	ASSERT(lowerControl);
+	return lowerControl;
+	}
+
+MLowerDataSender* CLegacyLoopbackSubConnectionFlow::BindL(const TDesC8& aProtocol, MUpperDataReceiver* aReceiver, MUpperControl* aControl)
+/**
+Create and return an MLowerDataSender instance of the specified protocol type.
+This is bound to the specified upper layer objects.
+
+Called from upper layer to bind to this layer.
+
+@param aProtocol Protocol type of the binder (same as in GetControlL())
+@param aReceiver upper layer's MUpperDataReceiver instance for this binder to associate with
+@param aControl upper layer's MUpperControl instance for this binder to associate with
+@return MLowerDataSender instance
+*/
+	{
+    __FLOG(_L8("CLegacyLoopbackSubConnectionFlow:\tBindL()"));
+
+	MLowerDataSender* lowerDataSender = NULL;
+
+	if (aProtocol.CompareF(KProtocol4()) == 0)
+		{
+		lowerDataSender = iBinder4->Bind(*aReceiver, *aControl);
+		}
+	else
+	if (aProtocol.CompareF(KProtocol6()) == 0)
+		{
+		lowerDataSender = iBinder6->Bind(*aReceiver, *aControl);
+		}
+
+    iSubConnectionProvider.PostMessage(Id(), TCFControlProvider::TActive().CRef());
+	ASSERT(lowerDataSender);
+	return lowerDataSender;
+	}
+
+void CLegacyLoopbackSubConnectionFlow::Unbind(MUpperDataReceiver* aReceiver, MUpperControl* aControl)
+/**
+Unbind from the upper layer.
+
+Called from the upper layer during unbinding.
+
+@param aReceiver
+@param aControl
+
+*/
+	{
+    __FLOG(_L8("CLegacyLoopbackSubConnectionFlow:\tUnbind()"));
+
+	if (iBinder4 && iBinder4->MatchesUpperControl(aControl))
+		{
+		iBinder4->Unbind(*aReceiver, *aControl);
+		delete iBinder4;
+		iBinder4 = NULL;
+		}
+	else if (iBinder6 && iBinder6->MatchesUpperControl(aControl))
+		{
+		iBinder6->Unbind(*aReceiver, *aControl);
+		delete iBinder6;
+		iBinder6 = NULL;
+		}
+
+
+    MaybePostDataClientIdle();
+	}
+
+ESock::CSubConnectionFlowBase* CLegacyLoopbackSubConnectionFlow::Flow()
+/**
+Return the flow object corresponding to the MFlowBinderControl
+*/
+	{
+	return this;
+	}
+
+//
+// Utilities for posting SCPR messages
+//
+
+void CLegacyLoopbackSubConnectionFlow::PostProgressMessage(TInt aStage, TInt aError)
+	{
+	iSubConnectionProvider.PostMessage(Id(), TCFMessage::TStateChange(Elements::TStateChange(aStage, aError)).CRef());
+	}
+
+void CLegacyLoopbackSubConnectionFlow::PostDataClientStartedMessage()
+	{
+	iLastRequestOriginator.ReplyTo(Id(), TCFDataClient::TStarted().CRef());
+	}
+
+void CLegacyLoopbackSubConnectionFlow::PostFlowDownMessage(TInt aError, TInt aAction /*= MNifIfNotify::EDisconnect*/)
+	{
+	if (iFlowStarted)
+		{
+		iFlowStarted = EFalse;
+		iSubConnectionProvider.PostMessage(Id(), TCFControlProvider::TDataClientGoneDown(aError, aAction).CRef());
+		}
+	else
+		{
+		iLastRequestOriginator.ReplyTo(Id(), TCFDataClient::TStopped(aError).CRef());
+		}
+	iAgentProvision = NULL;
+	}
+
+void CLegacyLoopbackSubConnectionFlow::MaybePostDataClientIdle()
+    {
+    // Can only send DataClientIdle when the upper layer has unbound and the flow is stopped
+	if (iBinder4 == NULL && iBinder6 == NULL)
+		{
+   		iSubConnectionProvider.PostMessage(Id(), TCFControlProvider::TIdle().CRef());
+		}
+    }
+
+//
+// Other utilities
+//
+
+void Panic(TLegacyLoopbackPanicNum aNum)
+	{
+	_LIT(KLegacyLoopbackPanicString, "legacy_loopback");
+	User::Panic(KLegacyLoopbackPanicString, aNum);
+	}
+