diff -r 000000000000 -r dfb7c4ff071f commsfwutils/commsbufs/reference/loopback_bearer/src/flow.cpp --- /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 +#include +#include +#include +#include + +#ifdef SYMBIAN_OLD_EXPORT_LOCATION +#include "ss_subconnflow.h" +#else +#include +#endif + +#include +#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(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(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()) + { + SubConnectionError(static_cast(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(aMessage).iValue); + break; + case TCFDataClient::TProvisionConfig::EId: + ProvisionConfig(static_cast(aMessage).iConfig); + break; + case TCFDataClient::TBindTo::EId: + { + TCFDataClient::TBindTo& bindToReq = message_cast(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(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( + 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); + } +