--- /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);
+ }
+