--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/datacommsserver/esockserver/core_states/ss_coreprstates.cpp Thu Dec 17 09:22:25 2009 +0200
@@ -0,0 +1,2166 @@
+// Copyright (c) 2006-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:
+// COREPRSTATES.CPP
+// Core PR States
+// THIS API IS INTERNAL TO NETWORKING AND IS SUBJECT TO CHANGE AND NOT FOR EXTERNAL USE
+//
+//
+
+/**
+ @file
+ @internalComponent
+*/
+
+
+#include <comms-infras/ss_log.h>
+#include <ss_glob.h>
+#include <comms-infras/ss_tiermanager.h>
+#include <comms-infras/ss_tiermanager_internal.h>
+#include <comms-infras/ss_subconnprov.h>
+#include <comms-infras/ss_connprov.h>
+#include <comms-infras/ss_metaconnprov_internal.h>
+
+#include <comms-infras/ss_nodeinterfaces.h>
+
+#include "ss_coreprstates.h"
+#include <comms-infras/ss_corepractivities.h>
+#include "ss_apiext_messages.h"
+#include <cs_subconparams.h>
+
+#include <comms-infras/ss_protocolparameterset.h>
+
+#include <elements/nm_messages_errorrecovery.h>
+#include <elements/nm_messages_peer.h>
+#include <elements/nm_messages_child.h>
+
+#include "ss_flowrequest.h"
+
+#include <comms-infras/ss_nodemessages_dataclient.h>
+#include <comms-infras/ss_nodemessages_serviceprovider.h>
+#include <comms-infras/ss_nodemessages_subconn.h>
+#include <comms-infras/ss_nodemessages_rejoiningprovider.h>
+#include <comms-infras/ss_nodemessages_internal_esock.h>
+#include <comms-infras/ss_nodemessages_factory.h>
+#include <comms-infras/ss_nodemessages_mcpr.h>
+#include <comms-infras/ss_nodemessages_cpr.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_ESockCrStaCPRSC, "ESockCrStaCPRSC");
+#endif
+
+#if defined __CFLOG_ACTIVE || defined LOG || defined ESOCK_EXTLOG_ACTIVE
+ #define KCoreProviderStatesTag KESockCoreProviderTag
+ _LIT8(KCoreProviderStatesSubTag, "coreprovstate");
+#endif
+
+using namespace CoreStates;
+using namespace CoreNetStates;
+using namespace PRStates;
+using namespace PRActivities;
+using namespace CoreActivities;
+using namespace NetStateMachine;
+using namespace ESock;
+using namespace CorePanics;
+using namespace Elements;
+using namespace Messages;
+using namespace MeshMachine;
+using namespace Factories;
+
+//-=========================================================
+//
+// Panics
+//
+//-=========================================================
+_LIT (KCorePrPanic,"CorePrPanic");
+
+void CorePrPanic(TInt aCode)
+ {
+ User::Panic(KCorePrPanic, aCode);
+ }
+
+
+//-=========================================================
+//
+//Utility functions
+//
+//-=========================================================
+//[RZ TODO] This method is a real pain. This method must go.
+//This method method must be replaced with examining activity->Error()
+//or similar.
+TInt ExtractErrorCode(Messages::TSignatureBase& aMessage, MeshMachine::CNodeActivityBase* aActivity = NULL)
+ {
+ if (aActivity && aActivity->Error() != KErrNone)
+ {
+ TInt error = aActivity->Error();
+ aActivity->SetError(KErrNone);
+ return error;
+ }
+
+ TInt code = KErrCancel;
+
+ if ( (aMessage.IsMessage<TCFServiceProvider::TStopped>()) ||
+ (aMessage.IsMessage<TCFServiceProvider::TStop>()) ||
+ (aMessage.IsMessage<TCFDataClient::TStopped>()) ||
+ (aMessage.IsMessage<TCFDataClient::TStop>()) )
+ {
+ code = static_cast<const Messages::TSigNumber&>(aMessage).iValue;
+ }
+ else if ( (aMessage.IsMessage<TCFControlClient::TGoneDown>()) ||
+ (aMessage.IsMessage<TCFControlProvider::TDataClientGoneDown>()) )
+ {
+ code = static_cast<const Messages::TSigNumberNumber&>(aMessage).iValue1;
+ }
+ else if ( aMessage.IsMessage<TEErrorRecovery::TErrorRecoveryResponse>() )
+ {
+ //Action must be propagate or there is no error code (your activity flow is faulty)!
+ const Messages::TSigErrResponse& sig = static_cast<const Messages::TSigErrResponse&>(aMessage);
+ __ASSERT_DEBUG(sig.iErrResponse.iAction==Messages::TErrResponse::EPropagate, User::Panic(KSpecAssert_ESockCrStaCPRSC, 1));
+ code = sig.iErrResponse.iError;
+ }
+ return code;
+ }
+
+
+//-=========================================================
+//
+//Common States and Transitions
+//
+//-=========================================================
+
+EXPORT_C TBool ASetErrorState::Accept(TNodeContextBase& aContext, TBool aSuperAccept)
+ {
+ TEBase::TError* msg = message_cast<TEBase::TError>(&aContext.iMessage);
+ if (msg && aSuperAccept == EFalse && aContext.iNodeActivity != NULL)
+ {
+ aContext.iNodeActivity->SetError(msg->iValue);
+ msg->ClearMessageId();
+ return EFalse;
+ }
+ return aSuperAccept;
+ }
+
+EXPORT_C TInt ACancelOrErrorOrTag::TransitionTag(TNodeContextBase& aContext, TInt aTag)
+ {
+ if(aContext.iMessage.IsMessage<TEBase::TCancel>())
+ {
+ return MeshMachine::KCancelTag;
+ }
+ if(aContext.iMessage.IsMessage<TEBase::TError>())
+ {
+ return MeshMachine::KErrorTag;
+ }
+ return aTag;
+ }
+
+EXPORT_DEFINE_SMELEMENT(TForwardToControlProvider, NetStateMachine::MStateTransition, CoreStates::TContext)
+EXPORT_C void TForwardToControlProvider::DoL()
+ {
+ iContext.Node().PostToClients<TDefaultClientMatchPolicy>(iContext.NodeId(),
+ iContext.iMessage, TClientType(TCFClientType::ECtrlProvider));
+ }
+
+EXPORT_DEFINE_SMELEMENT(TForwardToControlClients, NetStateMachine::MStateTransition, PRStates::TContext)
+void TForwardToControlClients::DoL()
+ {
+ iContext.Node().PostToClients<TDefaultClientMatchPolicy>(iContext.NodeId(), iContext.iMessage, TClientType(TCFClientType::ECtrl));
+ }
+
+EXPORT_DEFINE_SMELEMENT(TPanic, NetStateMachine::MStateTransition, CoreStates::TContext)
+EXPORT_C void TPanic::DoL()
+ {
+ __ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockCrStaCPRSC, 2));
+ }
+
+EXPORT_DEFINE_SMELEMENT(TPostToOriginators, NetStateMachine::MStateTransition, CoreStates::TContext)
+EXPORT_C void TPostToOriginators::DoL()
+ {
+ iContext.iNodeActivity->PostToOriginators(iContext.iMessage);
+ }
+
+EXPORT_DEFINE_SMELEMENT(TAddAuxClient, NetStateMachine::MStateTransition, CoreNetStates::TContext)
+EXPORT_C void TAddAuxClient::DoL()
+ {
+//TODO - what is this hack about? Please raise a defect.
+ iContext.Node().AddClientL(TNodeId::NullId(), TClientType(TCFClientType::EAux));
+ }
+
+EXPORT_DEFINE_SMELEMENT(TRemoveAuxClient, NetStateMachine::MStateTransition, CoreNetStates::TContext)
+EXPORT_C void TRemoveAuxClient::DoL()
+ {
+ TNodeSignal::TMessageId noPeerIds[] = {
+ TNodeSignal::TMessageId()
+ };
+ TEChild::TLeft leaveMsg;
+
+//DEF117712: Reentering mesh engine from TRemoveAuxClient::DoL has been raised on this.
+//Must be removed or explained (as an exception - why safe here?), as re-entering the MM engine is forbidden.
+ CoreNetStates::TContext ctx(iContext.Node(), leaveMsg, iContext.iSender, iContext.iRecipient);
+ iContext.Node().Received(noPeerIds, ctx);
+ }
+
+//-=========================================================
+//
+//Control Client Join
+//
+//-=========================================================
+
+EXPORT_DEFINE_SMELEMENT(TAddControlClientAndSendJoinCompleteIfRequest, NetStateMachine::MStateTransition, PRStates::TContext)
+EXPORT_C void TAddControlClientAndSendJoinCompleteIfRequest::DoL()
+ {
+ //Make sure the client is in the client's table (add if not already there).
+ if (iContext.iMessage.IsMessage<TCFPeer::TJoinRequest>())
+ {
+ TCFPeer::TJoinRequest& msg = message_cast<TCFPeer::TJoinRequest>(iContext.iMessage);
+
+ // Client type could be Messages::TClientType::EWorker (Selection Request)
+ // or ESock::TCFClientType::ECtrl, possibly others but not ESock::TCFClientType::EData
+ // which is handled by another activity
+ __ASSERT_DEBUG(msg.iClientType.Type() != (TUint32)TCFClientType::EData, User::Panic(KSpecAssert_ESockCrStaCPRSC, 3));
+
+// iContext.Node().AddClientL(msg.iNodeId, TClientType(TCFClientType::ECtrl,msg.iValue));
+ iContext.Node().AddClientL(msg.iNodeId, TClientType(TCFClientType::ECtrl));
+ //Send confirmation
+ RClientInterface::OpenPostMessageClose(iContext.NodeId(), iContext.iSender, TCFPeer::TJoinComplete().CRef());
+ }
+ else
+ {
+ TCFFactory::TPeerFoundOrCreated& msg = message_cast<TCFFactory::TPeerFoundOrCreated>(iContext.iMessage);
+ iContext.Node().AddClientL(address_cast<TNodeId>(iContext.iSender), TClientType(TCFClientType::ECtrl, msg.iValue));
+ }
+
+ //[399TODO] RZ: this call is safe as it checks for the existence of the ControlProvider
+ //same as TSendDataClientIdle. Though it looks a bit not elegant, cos' either this has
+ //to be a separate transition (why check ControlProvider then?) or it can always be
+ //aggregated with join/leave - why separate export then?
+ TSendDataClientActive dcActive(iContext);
+ dcActive.DoL();
+ }
+
+
+EXPORT_DEFINE_SMELEMENT(TAwaitingApplyResponse, NetStateMachine::MState, CoreStates::TContext)
+EXPORT_C TBool TAwaitingApplyResponse::Accept()
+ {
+ return (iContext.iMessage.IsMessage<TCFScpr::TApplyResponse>());
+ }
+
+EXPORT_DEFINE_SMELEMENT(TSendApplyRequest, NetStateMachine::MStateTransition, CoreStates::TContext)
+EXPORT_C void TSendApplyRequest::DoL()
+ {
+ __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KSpecAssert_ESockCrStaCPRSC, 4));
+ if (iContext.Node().ServiceProvider() == NULL)
+ {
+ User::Leave(KErrNotReady);
+ }
+ iContext.iNodeActivity->PostRequestTo(*iContext.Node().ServiceProvider(),
+ TCFScpr::TApplyRequest().CRef());
+ }
+
+//-=========================================================
+//
+//Data Client Join
+//
+//-=========================================================
+
+EXPORT_DEFINE_SMELEMENT(TAddDataClient, NetStateMachine::MStateTransition, PRStates::TContext)
+EXPORT_C void TAddDataClient::DoL()
+ {
+ Messages::TNodeId* client = NULL;
+ TCFClientType::TFlags clientFlags = (TCFClientType::TFlags)0;
+ TCFFactory::TPeerFoundOrCreated* dataClientJoinedMsg = message_cast<TCFFactory::TPeerFoundOrCreated>(&iContext.iMessage);
+
+ if ( dataClientJoinedMsg )
+ {
+ // Message "TJoined" => data client already joined (normally when "freshly" created)
+ client = &dataClientJoinedMsg->iNodeId;
+ clientFlags = (TCFClientType::TFlags)(dataClientJoinedMsg->iValue);
+ }
+ else
+ {
+ // Message "TJoinRequest" => data client requesting to join (when moved from one owner to another).
+ TCFPeer::TJoinRequest& dataClientJoinReqMsg =
+ message_cast<TCFPeer::TJoinRequest>(iContext.iMessage);
+ client = &dataClientJoinReqMsg.iNodeId;
+ clientFlags = static_cast<TCFClientType::TFlags>(dataClientJoinReqMsg.iClientType.Flags());
+ //[EC120TODO]: RZ When ib earth does the sender of TJoinRequest specifies a different type than
+ // EData. API classification will clear this up though scrapping explicit Contrl/Data join msgs.
+ // So each join message will indeed carry a type.
+ __ASSERT_DEBUG(dataClientJoinReqMsg.iClientType.Type() == TCFClientType::EData, User::Panic(KSpecAssert_ESockCrStaCPRSC, 5));
+ }
+
+ __ASSERT_DEBUG(client, User::Panic(KSpecAssert_ESockCrStaCPRSC, 6));
+ __ASSERT_DEBUG(!client->IsNull(), User::Panic(KSpecAssert_ESockCrStaCPRSC, 7)); //Don't run this transition when you have received no data client from the factory!
+ iContext.iPeer = iContext.Node().AddClientL(*client, TClientType(TCFClientType::EData, clientFlags));
+ }
+
+EXPORT_C void TAddDataClient::Error(TInt aError)
+ {
+ TCFFactory::TPeerFoundOrCreated* joinMsg = message_cast<TCFFactory::TPeerFoundOrCreated>(&iContext.iMessage);
+ if (joinMsg)
+ {
+ RClientInterface::OpenPostMessageClose(iContext.NodeId(), joinMsg->iNodeId,
+ TEChild::TDestroy().CRef());
+
+ if (iContext.iPeer)
+ {
+ iContext.Node().RemoveClient(iContext.iPeer->RecipientId());
+ }
+ }
+ TStateTransition<TContext>::Error(aError);
+ }
+
+EXPORT_DEFINE_SMELEMENT(TAwaitingDataClientJoinRequest, NetStateMachine::MState, CoreNetStates::TContext)
+EXPORT_C TBool CoreNetStates::TAwaitingDataClientJoinRequest::Accept()
+ {
+ TCFPeer::TJoinRequest* msg = message_cast<TCFPeer::TJoinRequest>(&iContext.iMessage);
+ if (msg != NULL)
+ {
+ if (msg->iClientType.Type() & TCFClientType::EData)
+ return ETrue;
+ }
+ return EFalse;
+ }
+
+EXPORT_DEFINE_SMELEMENT(TAddDataClientAndRespond, NetStateMachine::MStateTransition, PRStates::TContext)
+EXPORT_C void TAddDataClientAndRespond::DoL()
+ {
+ TAddDataClient::DoL();
+ RClientInterface::OpenPostMessageClose(iContext.NodeId(), iContext.iSender,
+ TCFPeer::TJoinComplete().CRef());
+ }
+
+//-=========================================================
+//
+//Data Client Rejoin
+//
+//-=========================================================
+
+EXPORT_DEFINE_SMELEMENT(TAwaitingDataClientRejoin, NetStateMachine::MState, PRStates::TContext)
+EXPORT_C TBool TAwaitingDataClientRejoin::Accept()
+ {
+ return iContext.iMessage.IsMessage<TCFRejoiningProvider::TRejoinDataClientRequest>();
+ }
+
+EXPORT_DEFINE_SMELEMENT(TAwaitingDataClientRejoinOrApplyOrCancel, NetStateMachine::MState, PRStates::TContext)
+EXPORT_C TBool TAwaitingDataClientRejoinOrApplyOrCancel::Accept()
+ {
+ if (iContext.iMessage.IsMessage<TCFRejoiningProvider::TRejoinDataClientRequest>() ||
+ iContext.iMessage.IsMessage<TCFScpr::TApplyRequest>())
+ {
+ return ETrue;
+ }
+ else if (iContext.iMessage.IsMessage<TEBase::TCancel>())
+ {
+ __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KSpecAssert_ESockCrStaCPRSC, 8));
+ iContext.iNodeActivity->SetIdle();
+ }
+ return EFalse;
+ }
+
+
+EXPORT_DEFINE_SMELEMENT(TAwaitingRejoinDataClientComplete, NetStateMachine::MState, PRStates::TContext)
+EXPORT_C TBool TAwaitingRejoinDataClientComplete::Accept()
+ {
+ return iContext.iMessage.IsMessage<TCFRejoiningProvider::TRejoinComplete>();
+ }
+
+EXPORT_DEFINE_SMELEMENT(TSendRejoinComplete, NetStateMachine::MStateTransition, PRStates::TContext)
+EXPORT_C void TSendRejoinComplete::DoL()
+ {
+ __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KSpecAssert_ESockCrStaCPRSC, 9));
+ iContext.iNodeActivity->PostToOriginators(TCFRejoiningProvider::TRejoinComplete().CRef());
+ }
+
+
+//-=========================================================
+//
+//Client Leave && Client Leave Request
+//
+//-=========================================================
+
+EXPORT_DEFINE_SMELEMENT(TAwaitingClientLeave, NetStateMachine::MState, CoreStates::TContext)
+EXPORT_C TBool TAwaitingClientLeave::Accept()
+ {
+ return iContext.iMessage.IsMessage<TEChild::TLeft>()
+ || iContext.iMessage.IsMessage<TEPeer::TLeaveRequest>();
+ }
+
+EXPORT_DEFINE_SMELEMENT(TDestroyOrphanedDataClients, NetStateMachine::MStateTransition, PRStates::TContext)
+EXPORT_C void TDestroyOrphanedDataClients::DoL()
+ {
+ iContext.Node().DestroyOrphanedDataClients();
+ }
+
+EXPORT_DEFINE_SMELEMENT(TSendDataClientIdle, NetStateMachine::MStateTransition, PRStates::TContext)
+EXPORT_C void TSendDataClientIdle::DoL()
+ {
+ RNodeInterface* cp = iContext.Node().ControlProvider();
+ if (cp)
+ { //If there is no Control Provider we probably are an MCPR/Tier Manager/etc
+ cp->PostMessage(iContext.NodeId(), TCFControlProvider::TIdle().CRef());
+ }
+ }
+
+EXPORT_DEFINE_SMELEMENT(TSendDataClientActive, NetStateMachine::MStateTransition, PRStates::TContext)
+EXPORT_C void TSendDataClientActive::DoL()
+ {
+ RNodeInterface* cp = iContext.Node().ControlProvider();
+ if (cp)
+ { //If there is no Control Provider we probably are an MCPR/Tier Manager/etc
+ cp->PostMessage(iContext.NodeId(), TCFControlProvider::TActive().CRef());
+ }
+ }
+
+
+EXPORT_DEFINE_SMELEMENT(TSendDataClientIdleIfNoClients, NetStateMachine::MStateTransition, PRStates::TContext)
+EXPORT_C void TSendDataClientIdleIfNoClients::DoL()
+ {
+ //A node is idle if it has no EData, ECtrl nor EAux clients.
+ //If a node is idle it should send TDataClientIdle to its Control Provider,
+ //which (in a typical scenario) decides to send TDestroy as a response.
+ //We should process TDestroy by sending TClientLeaving back and destroying self.
+ //Should we be the last client of our Control Provider, the Control Provider
+ //sends TDataClientIdle to its Control Provider triggering a similar cycle.
+ if (iContext.Node().GetFirstClient<TDefaultClientMatchPolicy>(TClientType(TCFClientType::ECtrl|TCFClientType::EAux))==NULL
+ && iContext.Node().GetFirstClient<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EData, TCFClientType::EActive)) == NULL)
+ {
+ TSendDataClientIdle::DoL();
+ return;
+ }
+
+ //In the somewhat similar scenario, if the node loses its last control client
+ //and discovers it still has dataclients that are not bound to and are not
+ //started, it will assume the dataclients are idle (unbound and not started
+ //dataclients will never admit to being idle themselves).
+ RNodeInterface* cc = iContext.Node().GetFirstClient<TDefaultClientMatchPolicy>(TClientType(TCFClientType::ECtrl));
+ if (cc==NULL)
+ {
+ TClientIter<TDefaultClientMatchPolicy> dciter = iContext.Node().GetClientIter<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EData),
+ TClientType(0, TCFClientType::EActive|TCFClientType::EActivating|TCFClientType::EStarted|TCFClientType::EStarting|TCFClientType::ELeaving));
+
+ TInt i = 0;
+ RNodeInterface* dc;
+ while ((dc = dciter[i++]) != NULL)
+ {
+ RClientInterface::OpenPostMessageClose(dc->RecipientId(), iContext.iNode.Id(),
+ TCFControlProvider::TIdle().CRef());
+ }
+ }
+ }
+
+EXPORT_DEFINE_SMELEMENT(TSendLeaveCompleteIfRequest, NetStateMachine::MStateTransition, PRStates::TContext)
+EXPORT_C void TSendLeaveCompleteIfRequest::DoL()
+ {
+ if (iContext.iMessage.IsMessage<TEPeer::TLeaveRequest>())
+ {
+ iContext.PostToSender(TEPeer::TLeaveComplete().CRef());
+ }
+ }
+
+
+//-=========================================================
+//
+//Data Client Idle
+//
+//-=========================================================
+
+EXPORT_DEFINE_SMELEMENT(TAwaitingDataClientIdle, MState, PRStates::TContext)
+EXPORT_C TBool TAwaitingDataClientIdle::Accept()
+ {
+ if (! iContext.iMessage.IsMessage<TCFControlProvider::TIdle>())
+ {
+ return EFalse;
+ }
+ __ASSERT_DEBUG(iContext.iPeer, User::Panic(KSpecAssert_ESockCrStaCPRSC, 11)); //TDataClientIdle is a peer message
+ iContext.iPeer->ClearFlags(TCFClientType::EActive);
+ return ETrue;
+ }
+
+EXPORT_DEFINE_SMELEMENT(TAwaitingDataClientActive, MState, PRStates::TContext)
+EXPORT_C TBool TAwaitingDataClientActive::Accept()
+ {
+ if (! iContext.iMessage.IsMessage<TCFControlProvider::TActive>())
+ {
+ return EFalse;
+ }
+ __ASSERT_DEBUG(iContext.iPeer, User::Panic(KSpecAssert_ESockCrStaCPRSC, 12)); //TDataClientActive is a peer message
+ iContext.iPeer->SetFlags(TCFClientType::EActive);
+ return ETrue;
+ }
+
+EXPORT_DEFINE_SMELEMENT(THandleDataClientIdle, MStateTransition, PRStates::TContext)
+EXPORT_C void THandleDataClientIdle::DoL()
+ {
+ // Send Destroy to the node which has sent data client idle, but only if the node
+ // is not in use, i.e. not started/starting/activating and it has not already
+ // been sent destroy.
+
+ //This will result in a data client leaving which in turn will trigger sending
+ //of TDataClientIdle to the Control Provider if there is no more clients joined to this node.
+
+ //Activity id does not matter for TDestroy message since there is no response to it.
+ //The only action that may result from sending destroy is reception of a "no peer"
+ //data clent leaving message which is always going to be delivered to the client leaving
+ //activity.
+ //Please do not ASSERT(iContext.iNodeActivity) here!
+
+ //This transition may only be triggered by a peer message from a data client
+ __ASSERT_DEBUG(iContext.iPeer, User::Panic(KSpecAssert_ESockCrStaCPRSC, 13));
+ __ASSERT_DEBUG(iContext.iPeer->Type()==TCFClientType::EData, User::Panic(KSpecAssert_ESockCrStaCPRSC, 14));
+
+ if (!(iContext.iPeer->Flags() &
+ (TCFClientType::EActivating|TCFClientType::EStarting|TCFClientType::ELeaving|TCFClientType::EStarted)))
+ {
+ // if dataclient is default and there is a non default present, don't kill the default.
+ if (!( iContext.iPeer->Flags() & TCFClientType::EDefault &&
+ iContext.Node().CountClients<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EData),
+ TClientType(0, TCFClientType::EDefault)) > 0))
+ {
+ iContext.iPeer->PostMessage(iContext.NodeId(), TEChild::TDestroy().CRef());
+ iContext.iPeer->SetFlags(TClientType::ELeaving);
+ }
+ else
+ {
+ __CFLOG_VAR((KCoreProviderStatesTag, KCoreProviderStatesSubTag, _L8("TSendDestroyToSendingDataClient::DoL - default client not destroyed, there is an active non default one")));
+ }
+ }
+ else
+ {
+ __CFLOG_VAR((KCoreProviderStatesTag, KCoreProviderStatesSubTag, _L8("TSendDestroyToSendingDataClient::DoL - client not destroyed, because it is started or has been requested again")));
+ TSendDataClientIdleIfNoClients(iContext).DoL();
+ }
+ }
+
+EXPORT_DEFINE_SMELEMENT(TSendGoneDown, NetStateMachine::MStateTransition, PRStates::TContext)
+EXPORT_C void TSendGoneDown::DoL()
+ {
+ if ( !(iContext.iMessage.IsMessage<TCFServiceProvider::TStopped>())
+ && !(iContext.iMessage.IsMessage<TCFServiceProvider::TStop>())
+ && !(iContext.iMessage.IsMessage<TCFDataClient::TStopped>())
+ && !(iContext.iMessage.IsMessage<TCFDataClient::TStop>())
+ && !(iContext.iMessage.IsMessage<TCFControlClient::TGoneDown>())
+ && !(iContext.iMessage.IsMessage<TCFControlProvider::TDataClientGoneDown>())
+ && !(iContext.iMessage.IsMessage<TEErrorRecovery::TErrorRecoveryResponse>()) )
+ {
+ CorePrPanic(KPanicIncorrectMessage);
+ }
+
+ iStopCode = ExtractErrorCode(iContext.iMessage);
+ const TProviderInfo& providerInfo = static_cast<const TProviderInfoExt&>(iContext.Node().AccessPointConfig().FindExtensionL(
+ STypeId::CreateSTypeId(TProviderInfoExt::EUid, TProviderInfoExt::ETypeId))).iProviderInfo;
+ iContext.Node().PostToClients<TDefaultClientMatchPolicy>(iContext.NodeId(), TCFControlClient::TGoneDown(iStopCode, providerInfo.APId()).CRef(), TClientType(TCFClientType::ECtrl));
+
+ // Tell control provider that we have stopped.. for Tier Notification
+ iContext.Node().PostToClients<TDefaultClientMatchPolicy>(iContext.NodeId(), TCFControlProvider::TDataClientStatusChange(TCFControlProvider::TDataClientStatusChange::EStopped).CRef(), TClientType(TCFClientType::ECtrlProvider));
+ iContext.Node().PostToClients<TDefaultClientMatchPolicy>(iContext.NodeId(), TCFControlProvider::TDataClientGoneDown(iStopCode).CRef(), TClientType(TCFClientType::ECtrlProvider));
+ }
+
+
+//-=========================================================
+//
+//Stop
+//
+//-=========================================================
+
+EXPORT_DEFINE_SMELEMENT(TSendDataClientStopped, NetStateMachine::MStateTransition, PRStates::TContext)
+EXPORT_C void TSendDataClientStopped::DoL()
+ {
+ // Extract stop code according to the message type that initiated the sending of TCFDataClient::TStopped.
+ // Default to KErrCancel.
+ iStopCode = ExtractErrorCode(iContext.iMessage, iContext.iNodeActivity);
+
+ TCFDataClient::TStopped dataClientStoppedMessage(iStopCode);
+ if (iContext.iNodeActivity)
+ {
+ iContext.iNodeActivity->PostToOriginators(dataClientStoppedMessage);
+ }
+ else
+ {
+ __ASSERT_DEBUG(iContext.iPeer, User::Panic(KSpecAssert_ESockCrStaCPRSC, 15));
+ iContext.iPeer->PostMessage(TNodeCtxId(iContext.ActivityId(), iContext.NodeId()), dataClientStoppedMessage);
+ }
+
+ // Tell control provider that we have stopped.. for Tier Notification
+ iContext.Node().PostToClients<TDefaultClientMatchPolicy>(TNodeCtxId(iContext.ActivityId(), iContext.NodeId()),
+ TCFControlProvider::TDataClientStatusChange(TCFControlProvider::TDataClientStatusChange::EStopped).CRef(), TClientType(TCFClientType::ECtrlProvider));
+
+ TInt numStartActivities = iContext.Node().CountActivities(ECFActivityStart);
+ TInt numStopActivities = iContext.Node().CountActivities(ECFActivityStop);
+
+ if (numStartActivities == 0 &&
+ numStopActivities == 0 &&
+ (iContext.iNodeActivity == NULL || iContext.iNodeActivity->FindOriginator(iContext.NodeId()) == KErrNotFound))
+ {
+ //Send TGoneDown to every control client unless the originator is the local node,
+ //in which case the originator will be responsible for sending TGoneDowns.
+
+ const TProviderInfo& providerInfo = static_cast<const TProviderInfoExt&>(iContext.Node().AccessPointConfig().FindExtensionL(
+ STypeId::CreateSTypeId(TProviderInfoExt::EUid, TProviderInfoExt::ETypeId))).iProviderInfo;
+
+ TCFControlClient::TGoneDown goneDown(iStopCode, providerInfo.APId());
+ iContext.Node().PostToClients<TDefaultClientMatchPolicy>(TNodeCtxId(iContext.ActivityId(), iContext.NodeId()),
+ goneDown, TClientType(TCFClientType::ECtrl));
+ }
+
+ if (iContext.iNodeActivity)
+ {
+ iContext.iNodeActivity->SetError(KErrNone);
+ }
+ }
+
+EXPORT_DEFINE_SMELEMENT(TStopDataClients, NetStateMachine::MStateTransition, PRStates::TContext)
+EXPORT_C void TStopDataClients::DoL()
+ {
+ __ASSERT_DEBUG(iContext.iNodeActivity, CorePrPanic(KPanicNoActivity));
+ TInt stopCode = ExtractErrorCode(iContext.iMessage);
+
+ iContext.Node().PostToClients<TDefaultClientMatchPolicy>(TNodeCtxId(iContext.ActivityId(), iContext.NodeId()),
+ TCFDataClient::TStop(stopCode).CRef(), TClientType(TCFClientType::EData, TCFClientType::EStarted));
+ iContext.iNodeActivity->ClearPostedTo();
+ }
+
+EXPORT_DEFINE_SMELEMENT(TStopSelf, NetStateMachine::MStateTransition, PRStates::TContext)
+EXPORT_C void TStopSelf::DoL()
+ {
+ __ASSERT_DEBUG(iContext.iNodeActivity, CorePrPanic(KPanicNoActivity));
+ TInt stopCode = ExtractErrorCode(iContext.iMessage);
+
+ iContext.iNodeActivity->PostRequestTo(iContext.NodeId(),
+ TCFDataClient::TStop(stopCode).CRef());
+ }
+
+//Awaiting one data client stopped
+EXPORT_DEFINE_SMELEMENT(TAwaitingDataClientStopped, NetStateMachine::MState, PRStates::TContext)
+EXPORT_C TBool TAwaitingDataClientStopped::Accept()
+ {
+ TCFDataClient::TStopped* dcStopped = message_cast<TCFDataClient::TStopped>(&iContext.iMessage);
+ if (dcStopped == NULL)
+ {
+ return EFalse;
+ }
+ if (iContext.iPeer)
+ {
+ iContext.iPeer->ClearFlags(TCFClientType::EStarted);
+ }
+ if (iContext.iNodeActivity &&
+ (iContext.iNodeActivity->ActivitySigId() == ECFActivityStop ||
+ iContext.iNodeActivity->ActivitySigId() == ECFActivityStopDataClient))
+ {
+ iContext.iNodeActivity->SetError(dcStopped->iValue);
+ }
+ return ETrue;
+ }
+
+//Awaiting all of the data clients stopped
+EXPORT_DEFINE_SMELEMENT(TAwaitingDataClientsStopped, NetStateMachine::MState, PRStates::TContext)
+EXPORT_C TBool TAwaitingDataClientsStopped::Accept()
+ {
+ TCFDataClient::TStopped* dcStopped = message_cast<TCFDataClient::TStopped>(&iContext.iMessage);
+ if (dcStopped == NULL)
+ {
+ return EFalse;
+ }
+ if (iContext.iPeer)
+ {
+ iContext.iPeer->ClearFlags(TCFClientType::EStarted);
+ }
+ if (iContext.Node().CountClients<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EData, TCFClientType::EStarted)))
+ {
+ //There are more to wait for
+ iContext.iMessage.ClearMessageId();
+ return EFalse;
+ }
+ if (iContext.iNodeActivity &&
+ (iContext.iNodeActivity->ActivitySigId() == ECFActivityStop ||
+ iContext.iNodeActivity->ActivitySigId() == ECFActivityStopDataClient))
+ {
+ iContext.iNodeActivity->SetError(dcStopped->iValue);
+ }
+ //Last one - accept
+ return ETrue;
+ }
+
+EXPORT_DEFINE_SMELEMENT(TSendStop, NetStateMachine::MStateTransition, CoreNetStates::TContext)
+EXPORT_C void TSendStop::DoL()
+ {
+ __ASSERT_DEBUG(iContext.iNodeActivity, CorePrPanic(KPanicNoActivity));
+ __ASSERT_DEBUG(iContext.Node().ServiceProvider(), CorePrPanic(KPanicNoServiceProvider));
+
+ TInt stopCode = ExtractErrorCode(iContext.iMessage);
+
+ iContext.iNodeActivity->PostRequestTo(*iContext.Node().ServiceProvider(), TCFServiceProvider::TStop(stopCode).CRef());
+ }
+
+EXPORT_DEFINE_SMELEMENT(TAwaitingDataClientGoneDown, NetStateMachine::MState, PRStates::TContext)
+EXPORT_C TBool TAwaitingDataClientGoneDown::Accept()
+ {
+ if (! iContext.iMessage.IsMessage<TCFControlProvider::TDataClientGoneDown>())
+ {
+ return EFalse;
+ }
+
+ __ASSERT_DEBUG(iContext.iPeer, User::Panic(KSpecAssert_ESockCrStaCPRSC, 16)); //This is a peer message
+ iContext.iPeer->ClearFlags(TCFClientType::EStarted);
+ return ETrue;
+ }
+
+//-=========================================================
+//
+//NoBearer
+//
+//-=========================================================
+
+EXPORT_DEFINE_SMELEMENT(TAwaitingNoBearer, NetStateMachine::MState, CoreNetStates::TContext)
+EXPORT_C TBool TAwaitingNoBearer::Accept()
+ {
+ return iContext.iMessage.IsMessage<TCFControlProvider::TNoBearer>();
+ }
+
+EXPORT_DEFINE_SMELEMENT(TSendNoBearer, NetStateMachine::MStateTransition, PRStates::TContext)
+EXPORT_C void TSendNoBearer::DoL()
+ {
+ __ASSERT_DEBUG(iContext.Node().ServiceProvider()==NULL, CorePrPanic(KPanicUnexpectedExecutionPath));
+ RNodeInterface* ctrlProvider = iContext.Node().ControlProvider();
+ __ASSERT_DEBUG(ctrlProvider, CorePrPanic(KPanicNoControlProvider));
+ User::LeaveIfError(ctrlProvider? KErrNone : KErrCorrupt);
+ iContext.iNodeActivity->PostRequestTo(*ctrlProvider, TCFControlProvider::TNoBearer().CRef());
+ }
+
+EXPORT_DEFINE_SMELEMENT(TSendBindTo, NetStateMachine::MStateTransition, CoreStates::TContext)
+EXPORT_C void TSendBindTo::DoL()
+ {
+ //This is assumed to be executed as a direct response to TCommsBinderResponse
+ __ASSERT_DEBUG(iContext.iNodeActivity, CorePrPanic(KPanicNoActivity));
+
+ //Create a binder to send.
+ TCFServiceProvider::TCommsBinderResponse& binderResponse = message_cast<TCFServiceProvider::TCommsBinderResponse>(iContext.iMessage);
+
+ //TODO: TNodePeerId should become internal. When this happens, FirstOriginator should return
+ // RNodeInterface.
+ iContext.iNodeActivity->PostRequestTo(
+ address_cast<Messages::TNodeId>(iContext.iNodeActivity->SoleOriginator().RecipientId()),
+ TCFDataClient::TBindTo(binderResponse.iNodeId).CRef());
+ }
+
+EXPORT_DEFINE_SMELEMENT(TSendBearer, NetStateMachine::MStateTransition, CoreStates::TContext)
+EXPORT_C void TSendBearer::DoL()
+ {
+ if (iContext.iNodeActivity)
+ {
+ iContext.iNodeActivity->PostToOriginators(TCFControlProvider::TBearer().CRef());
+ }
+ else
+ {
+ RClientInterface::OpenPostMessageClose(iContext.NodeId(), iContext.iSender, TCFControlProvider::TBearer().CRef());
+ }
+ }
+
+EXPORT_DEFINE_SMELEMENT(TSendControlClientJoinRequest, NetStateMachine::MStateTransition, CoreStates::TContext)
+EXPORT_C void TSendControlClientJoinRequest::DoL()
+ {
+ __ASSERT_DEBUG(iContext.iNodeActivity, CorePrPanic(KPanicNoActivity));
+
+ //The transition can be placed after (to process) the following messages:
+
+ //(1)TCFDataClient::TBindTo - carrying the new service provider for this node.
+ const TCFDataClient::TBindTo* bindToMsg(message_cast<const TCFDataClient::TBindTo>(&iContext.iMessage));
+ //(2)TCFServiceProvider::TCommsBinderResponse - carrying the auxilary service provider for this node (this node
+ //may sometimes want to join the data client of its service provider.
+ const TCFServiceProvider::TCommsBinderResponse* binderResponseMsg(message_cast<const TCFServiceProvider::TCommsBinderResponse>(&iContext.iMessage));
+
+ __ASSERT_DEBUG(bindToMsg || binderResponseMsg , User::Panic(KSpecAssert_ESockCrStaCPRSC, 17));
+
+ TNodeId newServiceProvider = bindToMsg ? bindToMsg->iNodeId : binderResponseMsg->iNodeId;
+ RNodeInterface* sp = iContext.Node().AddClientL(newServiceProvider, TClientType(TCFClientType::EServProvider, TCFClientType::EActive));
+ __ASSERT_DEBUG(sp != NULL, CorePrPanic(KPanicNoServiceProvider));
+ User::LeaveIfError(sp? KErrNone : KErrCorrupt);
+
+ //Join the service provider
+ iContext.iNodeActivity->PostRequestTo(*sp, TCFPeer::TJoinRequest(iContext.NodeId(), TClientType(TCFClientType::ECtrl)).CRef());
+ }
+
+EXPORT_DEFINE_SMELEMENT(TRequestCommsBinder, NetStateMachine::MStateTransition, CoreStates::TContext)
+EXPORT_C void TRequestCommsBinder::DoL()
+ {
+ __ASSERT_DEBUG(iContext.iNodeActivity, CorePrPanic(KPanicNoActivity));
+
+ RNodeInterface* sp = iContext.Node().ServiceProvider();
+ __ASSERT_DEBUG(sp != NULL, CorePrPanic(KPanicNoServiceProvider));
+ User::LeaveIfError(sp? KErrNone : KErrCorrupt);
+
+ iContext.iNodeActivity->PostRequestTo(*sp, TCFServiceProvider::TCommsBinderRequest().CRef());
+ }
+
+EXPORT_DEFINE_SMELEMENT(TAwaitingDataClientStarted, NetStateMachine::MState, CoreStates::TContext)
+EXPORT_C TBool TAwaitingDataClientStarted::Accept()
+ {
+ if (iContext.iMessage.IsMessage<TCFDataClient::TStarted>())
+ {
+ __ASSERT_DEBUG(iContext.iPeer || iContext.iSender == iContext.NodeId(), User::Panic(KSpecAssert_ESockCrStaCPRSC, 18));
+ if (iContext.iPeer)
+ {
+ iContext.iPeer->ClearFlags(TCFClientType::EStarting);
+ iContext.iPeer->SetFlags(TCFClientType::EStarted);
+ }
+ return ETrue;
+ }
+
+ //If this is TError, clean the EStarting flag but do not accept, clean or otherwise process
+ if (iContext.iMessage.IsMessage<TEBase::TError>())
+ {
+ if (iContext.iPeer)
+ {
+ iContext.iPeer->ClearFlags(TCFClientType::EStarting);
+ }
+ }
+
+ return EFalse;
+ }
+
+// Status in which it waits for all the DataClients which haven't yet Started (flagged as "Starting") to Start
+EXPORT_DEFINE_SMELEMENT(TAwaitingDataClientsStarted, NetStateMachine::MState, PRStates::TContext)
+EXPORT_C TBool TAwaitingDataClientsStarted::Accept()
+ {
+ CoreNetStates::TAwaitingDataClientStarted state(iContext);
+ if (state.Accept())
+ {
+ if (iContext.Node().CountClients<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EData,TCFClientType::EStarting)))
+ /* Meaning of the line above: 'Do I have any dataclient which has already sent the TStartDataClient message to but hasn't
+ answered with TStarted yet?' */
+ {
+ // YES, so there are more to wait for
+ iContext.iMessage.ClearMessageId();
+ return EFalse;
+ }
+ return ETrue;
+ }
+ return EFalse;
+ }
+
+//-=========================================================
+//
+//Destroy
+//
+//-=========================================================
+
+EXPORT_DEFINE_SMELEMENT(TAbortAllActivitiesNodeDeletion, NetStateMachine::MStateTransition, CoreStates::TContext)
+EXPORT_C void TAbortAllActivitiesNodeDeletion::DoL()
+ {//aborts all running activities fr all originator except me
+ iContext.Node().AbortActivitiesOriginatedBy(iContext, TNodeId::NullId(), ETrue);
+ }
+
+EXPORT_DEFINE_SMELEMENT(TAbortAllActivities, NetStateMachine::MStateTransition, CoreStates::TContext)
+EXPORT_C void TAbortAllActivities::DoL()
+ {//aborts all running activities fr all originator except me
+ iContext.Node().AbortActivitiesOriginatedBy(iContext);
+ }
+
+EXPORT_DEFINE_SMELEMENT(TSetIdleIfNoServiceProviders, NetStateMachine::MStateTransition, CoreStates::TContext)
+EXPORT_C void TSetIdleIfNoServiceProviders::DoL()
+ {
+ __ASSERT_DEBUG(iContext.iNodeActivity, CorePrPanic(KPanicNoActivity));
+ if (iContext.Node().GetFirstClient<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EServProvider))==NULL)
+ {
+ iContext.iNodeActivity->SetIdle();
+ }
+ }
+
+EXPORT_DEFINE_SMELEMENT(TSetIdleIfMoreClients, NetStateMachine::MStateTransition, CoreStates::TContext)
+EXPORT_C void TSetIdleIfMoreClients::DoL()
+ {
+ __ASSERT_DEBUG(iContext.iNodeActivity, CorePrPanic(KPanicNoActivity));
+ if (iContext.Node().GetFirstClient<TDefaultClientMatchPolicy>(TClientType(TCFClientType::ECtrl|TCFClientType::EData))!=NULL)
+ {
+ iContext.iNodeActivity->SetIdle();
+ }
+ }
+
+EXPORT_DEFINE_SMELEMENT(TSendClientLeavingAndRemoveControlProvider, NetStateMachine::MStateTransition, CoreStates::TContext)
+EXPORT_C void TSendClientLeavingAndRemoveControlProvider::DoL()
+ {
+ TClientIter<TDefaultClientMatchPolicy> iter = iContext.Node().GetClientIter<TDefaultClientMatchPolicy>(TClientType(TCFClientType::ECtrlProvider));
+ RNodeInterface* cl = iter[0];
+ //It is perfectly possible that there is no Control Provider at all.
+ if (cl)
+ {
+ __ASSERT_DEBUG(iContext.iNodeActivity, CorePrPanic(KPanicNoActivity));
+ cl->PostMessage(TNodeCtxId(iContext.ActivityId(), iContext.NodeId()), TEChild::TLeft().CRef());
+ iContext.Node().RemoveClient(cl->RecipientId(),iContext);
+ __ASSERT_DEBUG(iter[1] == NULL, User::Panic(KSpecAssert_ESockCrStaCPRSC, 19)); //But it is not possible to have two Control Providers!
+ }
+ }
+
+EXPORT_DEFINE_SMELEMENT(TSendClientLeavingAndRemoveControlProviderIfNoServiceProviders, NetStateMachine::MStateTransition, CoreStates::TContext)
+EXPORT_C void TSendClientLeavingAndRemoveControlProviderIfNoServiceProviders::DoL()
+ {
+ __ASSERT_DEBUG(iContext.iNodeActivity, CorePrPanic(KPanicNoActivity));
+ if (iContext.Node().GetFirstClient<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EServProvider))==NULL)
+ {
+ TSendClientLeavingAndRemoveControlProvider::DoL();
+ }
+ }
+
+EXPORT_DEFINE_SMELEMENT(TSendClientLeavingRequestToServiceProviders, NetStateMachine::MStateTransition, CoreStates::TContext)
+EXPORT_C void TSendClientLeavingRequestToServiceProviders::DoL()
+ {
+ __ASSERT_DEBUG(iContext.iNodeActivity, CorePrPanic(KPanicNoActivity));
+
+ TClientIter<TDefaultClientMatchPolicy> iter = iContext.Node().GetClientIter<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EServProvider));
+ for (TInt i = 0; iter[i]; i++)
+ {
+ RNodeInterface* cl = iter[i];
+
+ // Do not send client leaving requests to service providers which are already leaving
+ // (e.g., gone down).
+ if (!(cl->Flags() & TClientType::ELeaving))
+ {
+ cl->PostMessage(
+ TNodeCtxId(iContext.ActivityId(), iContext.NodeId()),
+ TEPeer::TLeaveRequest().CRef()
+ );
+
+ //We are expecting answers from many service providers, set to NullCommsId.
+ iContext.iNodeActivity->ClearPostedTo();
+ iter[i]->SetFlags(TCFClientType::ELeaving);
+ }
+ else
+ {
+ MESH_LOG((KCoreProviderStatesSubTag, _L8("TSendClientLeavingRequestToServiceProviders:\tDoL - IGNORING POST!")));
+ }
+ }
+ }
+
+EXPORT_DEFINE_SMELEMENT(TSendClientLeavingRequestToServiceProvider, NetStateMachine::MStateTransition, CoreStates::TContext)
+EXPORT_C void TSendClientLeavingRequestToServiceProvider::DoL()
+ {
+ __ASSERT_DEBUG(iContext.iNodeActivity, CorePrPanic(KPanicNoActivity));
+
+ //If the sender is a service provider, send to it (there may be more than one)
+ RNodeInterface* sp = iContext.Node().FindClient(iContext.iSender);
+ if (sp == NULL || !(sp->Type()&TCFClientType::EServProvider))
+ {
+ //Otherwise there must be only one sp on the node
+ TClientIter<TDefaultClientMatchPolicy> servProviders = iContext.Node().GetClientIter<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EServProvider));
+ __ASSERT_DEBUG(servProviders[0] && servProviders[1] == NULL, CorePrPanic(KPanicNoServiceProvider));
+ sp = servProviders[0];
+ }
+
+ __ASSERT_DEBUG(sp, CorePrPanic(KPanicNoServiceProvider));
+ iContext.iNodeActivity->PostRequestTo(*sp,
+ TEPeer::TLeaveRequest().CRef());
+ sp->SetFlags(TCFClientType::ELeaving);
+ }
+
+//-=========================================================
+//
+//Service Provider Going Up
+//
+//-=========================================================
+DEFINE_SMELEMENT(TAwaitingGoneUp, NetStateMachine::MState, CoreStates::TContext)
+TBool TAwaitingGoneUp::Accept()
+ {
+ if (! iContext.iMessage.IsMessage<TCFControlClient::TGoneUp>())
+ {
+ return EFalse;
+ }
+ iContext.iPeer->SetFlags(TCFClientType::EStarted);
+ return ETrue;
+ }
+
+
+//-=========================================================
+//
+//Service Provider Going Down
+//
+//-=========================================================
+EXPORT_DEFINE_SMELEMENT(TAwaitingGoneDown, NetStateMachine::MState, CoreStates::TContext)
+EXPORT_C TBool TAwaitingGoneDown::Accept()
+ {
+ if (! iContext.iMessage.IsMessage<TCFControlClient::TGoneDown>())
+ {
+ return EFalse;
+ }
+ if (iContext.iPeer)
+ {
+ iContext.iPeer->ClearFlags(TCFClientType::EStarted);
+ }
+ if (iContext.Node().CountActivities(ECFActivityStop) ||
+ iContext.Node().CountActivities(ECFActivityStopDataClient) ||
+ iContext.Node().CountActivities(ECFActivityDestroy))
+ {
+ //we're already stopping - eat the message
+ iContext.iMessage.ClearMessageId();
+ return EFalse;
+ }
+ return ETrue;
+ }
+
+EXPORT_DEFINE_SMELEMENT(TSendClientLeavingAndRemoveServiceProvider, NetStateMachine::MStateTransition, CoreNetStates::TContext)
+EXPORT_C void TSendClientLeavingAndRemoveServiceProvider::DoL()
+ {
+ //This must be a peer message
+ __ASSERT_DEBUG(iContext.iPeer, User::Panic(KSpecAssert_ESockCrStaCPRSC, 20));
+
+ if (iContext.Node().ServiceProvider())
+ {
+ //Activity id does not matter for TClientLeaving message since there is no response to it.
+ //Please do not ASSERT(iContext.iNodeActivity) here!
+ iContext.Node().PostToClients<TDefaultClientMatchPolicy>(TNodeCtxId(iContext.ActivityId(), iContext.NodeId()),
+ TEChild::TLeft().CRef(), TClientType(TCFClientType::EServProvider));
+ // we should usually set the ELeaving flag on the RNodeInterface since we've sent ClientLeaving to
+ // the node, but there's no need here, as the client is being deleted anyhow.
+ iContext.Node().RemoveClient(iContext.Node().ServiceProvider()->RecipientId(),iContext);
+ }
+ }
+
+//-=========================================================
+//
+//Other
+//
+//-=========================================================
+
+EXPORT_DEFINE_SMELEMENT(TAwaitingStopped, NetStateMachine::MState, CoreNetStates::TContext)
+EXPORT_C TBool TAwaitingStopped::Accept()
+ {
+ if (! iContext.iMessage.IsMessage<TCFServiceProvider::TStopped>() )
+ {
+ return EFalse;
+ }
+
+ if (iContext.iPeer)
+ {
+ iContext.iPeer->ClearFlags(TCFClientType::EStarted);
+ }
+ return ETrue;
+ }
+
+EXPORT_DEFINE_SMELEMENT(TAwaitingStop, NetStateMachine::MState, CoreNetStates::TContext)
+TBool TAwaitingStop::Accept()
+ {
+ if (!iContext.iMessage.IsMessage<TCFServiceProvider::TStop>())
+ {
+ return EFalse;
+ }
+ if (iContext.Node().ServiceProvider())
+ {
+ iContext.Node().ServiceProvider()->SetFlags(TCFClientType::EStarted);
+ }
+ return ETrue;
+ }
+
+EXPORT_DEFINE_SMELEMENT(TAwaitingParamResponse, NetStateMachine::MState, CoreStates::TContext)
+EXPORT_C TBool TAwaitingParamResponse::Accept()
+ {
+#ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+ if((iContext.iMessage.IsMessage<TCFScpr::TSetParamsResponse>()) || (iContext.iMessage.IsMessage<TCFScpr::TGetParamsResponse>()))
+ {
+ return ETrue;
+ }
+ return EFalse;
+#else
+ return iContext.iMessage.IsMessage<TCFScpr::TParamsResponse>();
+#endif // SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+ }
+
+EXPORT_DEFINE_SMELEMENT(TRespondWithRetrievedParams, NetStateMachine::MStateTransition, PRStates::TContext)
+EXPORT_C void TRespondWithRetrievedParams::DoL()
+ {
+#ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+ iContext.PostToSender(TCFScpr::TGetParamsResponse(iContext.Node().iParameterBundle).CRef());
+#endif
+ }
+
+EXPORT_DEFINE_SMELEMENT(TAwaitingConEvent, NetStateMachine::MState, CoreStates::TContext)
+EXPORT_C TBool TAwaitingConEvent::Accept()
+ {
+#ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+ return iContext.iMessage.IsMessage<TCFSubConnControlClient::TPlaneNotification>();
+#else
+ return EFalse;
+#endif
+ }
+
+EXPORT_DEFINE_SMELEMENT(TAwaitingSubConEvent, NetStateMachine::MState, CoreStates::TContext)
+EXPORT_C TBool TAwaitingSubConEvent::Accept()
+ {
+ return iContext.iMessage.IsMessage<TCFSubConnControlClient::TSubConnNotification>();
+ }
+
+
+
+//-=========================================================
+//
+//Binder request
+//
+//-=========================================================
+
+EXPORT_DEFINE_SMELEMENT(TAwaitingBinderRequest, NetStateMachine::MState, PRStates::TContext)
+EXPORT_C TBool TAwaitingBinderRequest::Accept()
+ {
+ if (! iContext.iMessage.IsMessage<TCFServiceProvider::TCommsBinderRequest>())
+ {
+ return EFalse;
+ }
+
+ __ASSERT_DEBUG(iContext.iPeer, User::Panic(KSpecAssert_ESockCrStaCPRSC, 21)); //TCommsBinderRequest is a peer message only!
+ return ETrue;
+ }
+
+// Start all the DataClients
+EXPORT_DEFINE_SMELEMENT(TStartDataClients, NetStateMachine::MStateTransition, PRStates::TContext)
+EXPORT_C void TStartDataClients::DoL()
+ {
+ __ASSERT_DEBUG(iContext.iNodeActivity, CorePrPanic(KPanicNoActivity));
+
+ //there should be a panic if we don't have any dataclients which are NOT in in EStarting or in EStarted state.
+ //Reason: there is no dataclients which is possible to start (because all of them have been already started). Then why are we here?????
+ TInt cliNum = iContext.Node().CountClients<TExcludeTypeAndFlagClientMatchPolicy>(
+ TClientType(
+ TCFClientType::EData,
+ (TCFClientType::EStarted | TCFClientType::EStarting | TCFClientType::ELeaving)
+ )
+ );
+
+ // TODO When called from SCprNoBearer before the node is started the node is panic'ed.
+ // Rather than panic, ensure that the node is started and thus the service provider is started.
+ // Thus started dataclients can be ignored.
+ // __ASSERT_DEBUG(cliNum != 0, CorePrPanic(KNoClients));
+
+ if (cliNum > 0)
+ {
+ //start all of the dataclients which haven't been started yet
+ TClientIter<TExcludeTypeAndFlagClientMatchPolicy> iter = iContext.Node().GetClientIter<TExcludeTypeAndFlagClientMatchPolicy>(
+ TClientType(
+ TCFClientType::EData,
+ (TCFClientType::EStarted | TCFClientType::EStarting | TCFClientType::ELeaving)
+ )
+ );
+
+ RNodeInterface* ctl = NULL;
+ while ((ctl = iter++) != NULL)
+ {
+ iContext.iNodeActivity->PostRequestTo(*ctl, TCFDataClient::TStart().CRef());
+ ctl->SetFlags(TCFClientType::EStarting);
+ }
+ }
+ else
+ {
+ // Self Post TStarted if no clients need to be started.
+ iContext.iNodeActivity->PostRequestTo(iContext.NodeId(), TCFDataClient::TStarted().CRef());
+ }
+
+ if (cliNum >1)
+ {
+ iContext.iNodeActivity->ClearPostedTo();
+ }
+ }
+
+EXPORT_DEFINE_SMELEMENT(TSendDataClientStarted, NetStateMachine::MStateTransition, PRStates::TContext)
+EXPORT_C void TSendDataClientStarted::DoL()
+ {
+ __ASSERT_DEBUG(iContext.iNodeActivity, CorePrPanic(KPanicNoActivity));
+ iContext.iNodeActivity->PostToOriginators(TCFDataClient::TStarted().CRef());
+
+ // Tell control provider that we have started.. for Tier Notification
+
+ iContext.Node().PostToClients<TDefaultClientMatchPolicy>(TNodeCtxId(iContext.ActivityId(), iContext.NodeId()),
+ TCFControlProvider::TDataClientStatusChange(TCFControlProvider::TDataClientStatusChange::EStarted).CRef(), TClientType(TCFClientType::ECtrlProvider));
+ }
+
+EXPORT_DEFINE_SMELEMENT(TStartServiceProvider, NetStateMachine::MStateTransition, CoreNetStates::TContext)
+EXPORT_C void TStartServiceProvider::DoL()
+ {
+ RNodeInterface* sp = iContext.Node().ServiceProvider();
+ __ASSERT_DEBUG(sp, CorePrPanic(KPanicNoServiceProvider));
+ User::LeaveIfError(sp? KErrNone : KErrCorrupt);
+
+ __ASSERT_DEBUG(iContext.iNodeActivity, CorePrPanic(KPanicNoActivity));
+ iContext.iNodeActivity->PostRequestTo(*sp, TCFServiceProvider::TStart().CRef());
+
+ sp->SetFlags(TCFClientType::EStarting);
+ }
+
+//-=========================================================
+//
+// Send TGoneUp
+//
+//-=========================================================
+DEFINE_SMELEMENT(TSendGoneUp, NetStateMachine::MStateTransition, CoreNetStates::TContext)
+void TSendGoneUp::DoL()
+ {
+ TClientIter<TDefaultClientMatchPolicy> iter = iContext.Node().GetClientIter<TDefaultClientMatchPolicy>(TClientType(TCFClientType::ECtrl));
+ for (TInt i = 0; iter[i]; i++)
+ {
+ //Send TGoneUp to every Ctrl client except the originator (who would be recieving TStarted)
+ if ((iContext.iNodeActivity && iContext.iNodeActivity->FindOriginator(*iter[i]) != KErrNone)
+ && iter[i] != iContext.iPeer)
+ {
+ iter[i]->PostMessage(TNodeCtxId(iContext.ActivityId(), iContext.NodeId()), TCFControlClient::TGoneUp());
+ }
+ }
+ }
+
+EXPORT_DEFINE_SMELEMENT(TSendStarted, NetStateMachine::MStateTransition, CoreNetStates::TContext)
+EXPORT_C void TSendStarted::DoL()
+ {
+ TCFServiceProvider::TStarted msg;
+ if (iContext.iNodeActivity)
+ {
+ iContext.iNodeActivity->PostToOriginators(msg);
+
+ TSendGoneUp(iContext).DoL();
+ }
+ else
+ {
+ //This transition can also be used from a single tripple activity
+ iContext.PostToSender(msg);
+
+ TSendGoneUp(iContext).DoL();
+ }
+ }
+
+EXPORT_DEFINE_SMELEMENT(TPassPlaneEventToControlClients, NetStateMachine::MStateTransition, CoreNetStates::TContext)
+EXPORT_C void TPassPlaneEventToControlClients::DoL()
+ {
+#ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+ TCFSubConnControlClient::TPlaneNotification& event = message_cast<TCFSubConnControlClient::TPlaneNotification>(iContext.iMessage);
+
+ TClientIter<TDefaultClientMatchPolicy> iter = iContext.Node().GetClientIter<TDefaultClientMatchPolicy>(TClientType(TCFClientType::ECtrl));
+ RNodeInterface* ctl;
+ while ((ctl = iter++) != NULL)
+ {
+ event.iRefCountOwnedNotification->Open();
+ ctl->PostMessage(iContext.NodeId(), event);
+ }
+
+ // This Close() matches the Open performed by the service provider node Open() function
+ event.iRefCountOwnedNotification->Close();
+#endif
+ }
+
+EXPORT_DEFINE_SMELEMENT(TSendStopped, NetStateMachine::MStateTransition, PRStates::TContext)
+EXPORT_C void TSendStopped::DoL()
+ {
+ //Please note that PostToOriginators overwrites the activity id,
+ //RNodeInterface::PostMessage does not!
+ TCFServiceProvider::TStopped msg(KErrNone);
+ if (iContext.iNodeActivity)
+ {
+ iContext.iNodeActivity->PostToOriginators(msg);
+ }
+ else
+ {
+ //This transition can also be used from a single tripple activity
+ iContext.PostToSender(msg);
+ }
+ }
+
+EXPORT_DEFINE_SMELEMENT(TSendStoppedAndGoneDown, NetStateMachine::MStateTransition, PRStates::TContext)
+EXPORT_C void TSendStoppedAndGoneDown::DoL()
+ {
+ TInt stopCode = ExtractErrorCode(iContext.iMessage, iContext.iNodeActivity);
+
+ //Please note that PostToOriginators overwrites the activity id,
+ //RNodeInterface::PostMessage does not!
+ TCFServiceProvider::TStopped msg(stopCode);
+ if (iContext.iNodeActivity)
+ {
+ iContext.iNodeActivity->PostToOriginators(msg);
+ }
+ else
+ {
+ //This transition can also be used from a single tripple activity
+ iContext.PostToSender(msg);
+ }
+
+ const TProviderInfo& providerInfo = static_cast<const TProviderInfoExt&>(iContext.Node().AccessPointConfig().FindExtensionL(
+ STypeId::CreateSTypeId(TProviderInfoExt::EUid, TProviderInfoExt::ETypeId))).iProviderInfo;
+
+ TCFControlClient::TGoneDown goneDown(stopCode, providerInfo.APId());
+ TClientIter<TDefaultClientMatchPolicy> iter = iContext.Node().GetClientIter<TDefaultClientMatchPolicy>(TClientType(TCFClientType::ECtrl));
+ for (TInt i = 0; iter[i]; i++)
+ {
+ CNodeActivityBase* startActivity = iContext.Node().FindActivityById(ECFActivityStart);
+
+ //Send TGoneDown to every Ctrl client except
+ // * the originator (who would be recieving TStopped)
+ // * originators of the start activity (these will be errored separately)
+ if (((iContext.iNodeActivity && iContext.iNodeActivity->FindOriginator(*iter[i]) != KErrNone) ||
+ (iContext.iNodeActivity == NULL && iter[i] != iContext.iPeer))
+ && (startActivity == NULL || startActivity->FindOriginator(*iter[i]) != KErrNone))
+ {
+ iter[i]->PostMessage(TNodeCtxId(iContext.ActivityId(), iContext.NodeId()), goneDown);
+ }
+ }
+
+ if (iContext.iNodeActivity)
+ {
+ iContext.iNodeActivity->SetError(KErrNone);
+ }
+ }
+
+EXPORT_DEFINE_SMELEMENT(TAwaitingStarted, NetStateMachine::MState, CoreNetStates::TContext)
+EXPORT_C TBool TAwaitingStarted::Accept()
+ {
+ if (iContext.iMessage.IsMessage<TCFServiceProvider::TStarted>())
+ {
+ if (iContext.iPeer)
+ {
+ iContext.iPeer->ClearFlags(TCFClientType::EStarting);
+ iContext.iPeer->SetFlags(TCFClientType::EStarted);
+ }
+ return ETrue;
+ }
+
+ //If this is TError, clean the EStarting flag but do not accept, clean or otherwise process
+ if (iContext.iMessage.IsMessage<TEBase::TError>())
+ {
+ if (iContext.iPeer)
+ {
+ iContext.iPeer->ClearFlags(TCFClientType::EStarting);
+ }
+ }
+
+ return EFalse;
+ }
+
+EXPORT_DEFINE_SMELEMENT(TSendBindToComplete, NetStateMachine::MStateTransition, CoreNetStates::TContext)
+EXPORT_C void TSendBindToComplete::DoL()
+ {
+ __ASSERT_DEBUG(iContext.iNodeActivity, CorePrPanic(KPanicNoActivity));
+ iContext.iNodeActivity->PostToOriginators(TCFDataClient::TBindToComplete(iContext.iNodeActivity->Error()).CRef());
+ }
+
+EXPORT_DEFINE_SMELEMENT(TBindSelfToPresentBearer, NetStateMachine::MStateTransition, CoreNetStates::TContext)
+EXPORT_C void TBindSelfToPresentBearer::DoL()
+ {
+ __ASSERT_DEBUG(iContext.iNodeActivity, CorePrPanic(KPanicNoActivity));
+
+ __ASSERT_DEBUG(iContext.Node().ServiceProvider(), User::Panic(KSpecAssert_ESockCrStaCPRSC, 22));
+ TNodeId bearer = iContext.Node().ServiceProvider()->RecipientId();
+ iContext.iNodeActivity->PostRequestTo(iContext.NodeId(), TCFDataClient::TBindTo(bearer).CRef());
+ }
+
+EXPORT_DEFINE_SMELEMENT(TBindSelf, NetStateMachine::MStateTransition, CoreNetStates::TContext)
+EXPORT_C void TBindSelf::DoL()
+ {
+ __ASSERT_DEBUG(iContext.iNodeActivity, CorePrPanic(KPanicNoActivity));
+ const TCFDataClient::TBindTo& bindToMessage = message_cast<TCFDataClient::TBindTo>(iContext.iMessage);
+ iContext.iNodeActivity->PostRequestTo(iContext.NodeId(), TCFDataClient::TBindTo(bindToMessage.iNodeId).CRef());
+ }
+
+EXPORT_DEFINE_SMELEMENT(TStartSelf, NetStateMachine::MStateTransition, CoreNetStates::TContext)
+EXPORT_C void TStartSelf::DoL()
+ {
+ __ASSERT_DEBUG(iContext.iNodeActivity, CorePrPanic(KPanicNoActivity));
+ iContext.iNodeActivity->PostRequestTo(iContext.NodeId(), TCFDataClient::TStart().CRef());
+ }
+
+EXPORT_DEFINE_SMELEMENT(TStoreParams, NetStateMachine::MStateTransition, PRStates::TContext)
+EXPORT_C void TStoreParams::DoL()
+ {
+#ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+ if (iContext.Node().CountActivities(ECFActivityApplyChanges))
+ {
+ User::Leave(KErrInUse);
+ }
+ TCFScpr::TSetParamsRequest* setParamsRequest = message_cast<TCFScpr::TSetParamsRequest>(&iContext.iMessage);
+ TCFScpr::TSetParamsResponse* setParamsResponse = message_cast<TCFScpr::TSetParamsResponse>(&iContext.iMessage);
+ __ASSERT_DEBUG(setParamsRequest || setParamsResponse, User::Panic(KSpecAssert_ESockCrStaCPRSC, 23));
+
+ RCFParameterFamilyBundleC newParamBundle = setParamsRequest ? setParamsRequest->iFamilyBundle : setParamsResponse->iFamilyBundle;
+
+ if ( ! newParamBundle.IsNull()
+ && (iContext.Node().iParameterBundle.IsNull() ||
+ iContext.Node().iParameterBundle != newParamBundle))
+ {
+ if ( ! iContext.Node().iParameterBundle.IsNull())
+ {
+ iContext.Node().iParameterBundle.Close();
+ }
+
+ iContext.Node().iParameterBundle.Open(newParamBundle);
+ }
+#endif
+ }
+
+EXPORT_DEFINE_SMELEMENT(TRespondWithCurrentParams, NetStateMachine::MStateTransition, PRStates::TContext)
+EXPORT_C void TRespondWithCurrentParams::DoL()
+ {
+#ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+ TCFScpr::TSetParamsRequest& paramRequest = message_cast<TCFScpr::TSetParamsRequest>(iContext.iMessage);
+ if ( (! paramRequest.iFamilyBundle.IsNull()) && iContext.Node().iParameterBundle != paramRequest.iFamilyBundle )
+ {
+ //default behaviour. Parameters where supplied, though haven't been processed
+ User::Leave(KErrNotSupported);
+ }
+ iContext.PostToSender(TCFScpr::TSetParamsResponse(iContext.Node().iParameterBundle).CRef());
+#endif
+ }
+
+EXPORT_DEFINE_SMELEMENT(TSendApplyResponse, NetStateMachine::MStateTransition, PRStates::TContext)
+EXPORT_C void TSendApplyResponse::DoL()
+ {
+ __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KSpecAssert_ESockCrStaCPRSC, 24));
+ iContext.iNodeActivity->PostToOriginators(TCFScpr::TApplyResponse().CRef());
+ }
+
+EXPORT_DEFINE_SMELEMENT(TPassToServiceProvider, NetStateMachine::MStateTransition, PRStates::TContext)
+EXPORT_C void TPassToServiceProvider::DoL()
+ {
+ //If you don't have the service provider, don't use this transition.
+ __ASSERT_DEBUG(iContext.Node().ServiceProvider(), User::Panic(KSpecAssert_ESockCrStaCPRSC, 25));
+ __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KSpecAssert_ESockCrStaCPRSC, 26));
+ iContext.iNodeActivity->PostRequestTo(*iContext.Node().ServiceProvider(), iContext.iMessage);
+ }
+
+
+EXPORT_DEFINE_SMELEMENT(TSendParamsToServiceProvider, NetStateMachine::MStateTransition, PRStates::TContext)
+EXPORT_C void TSendParamsToServiceProvider::DoL()
+ {
+#ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+ __ASSERT_DEBUG( ! iContext.Node().iParameterBundle.IsNull(), User::Panic(KSpecAssert_ESockCrStaCPRSC, 27));
+ iContext.iNodeActivity->PostRequestTo(*iContext.Node().ServiceProvider(),
+ TCFScpr::TSetParamsRequest(iContext.Node().iParameterBundle).CRef());
+#endif
+ }
+
+
+//-=========================================================
+//
+//States
+//
+//-=========================================================
+
+// This allows an activity to hang (for cases where it must
+// remain in existence in order to respond to a cancel)
+EXPORT_DEFINE_SMELEMENT(TNeverAccept, NetStateMachine::MState, CoreStates::TContext)
+EXPORT_C TBool TNeverAccept::Accept()
+ {
+ return EFalse;
+ }
+
+EXPORT_DEFINE_SMELEMENT(TAwaitingDataClientStart, NetStateMachine::MState, CoreNetStates::TContext)
+EXPORT_C TBool TAwaitingDataClientStart::Accept()
+ {
+ return iContext.iMessage.IsMessage<TCFDataClient::TStart>();
+ }
+
+EXPORT_DEFINE_SMELEMENT(TAwaitingStart, NetStateMachine::MState, CoreNetStates::TContext)
+EXPORT_C TBool TAwaitingStart::Accept()
+ {
+ if (iContext.iMessage.IsMessage<TCFServiceProvider::TStart>())
+ {
+ __ASSERT_DEBUG(iContext.iPeer || iContext.iSender == iContext.NodeId(), CorePrPanic(KPanicPeerMessage));
+ if (iContext.Node().GetFirstClient<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EData, TCFClientType::EStarted)) == NULL)
+ {
+ return ETrue;
+ }
+
+ iContext.iPeer->PostMessage(TNodeCtxId(iContext.ActivityId(), iContext.NodeId()), TCFServiceProvider::TStarted().CRef());
+ //Legacy progress notification - will hopefully be ignored by anything else than CConnection.
+ iContext.iPeer->PostMessage(TNodeCtxId(iContext.ActivityId(), iContext.NodeId()), TCFMessage::TStateChange(TStateChange(KLinkLayerOpen, KErrNone)).CRef());
+ iContext.iMessage.ClearMessageId();
+ }
+ return EFalse;
+ }
+
+EXPORT_DEFINE_SMELEMENT(TAwaitingDataClientStop, NetStateMachine::MState, CoreNetStates::TContext)
+EXPORT_C TBool TAwaitingDataClientStop::Accept()
+ {
+ return iContext.iMessage.IsMessage<TCFDataClient::TStop>();
+ }
+
+
+EXPORT_DEFINE_SMELEMENT(TAwaitingBindTo, NetStateMachine::MState, CoreStates::TContext)
+EXPORT_C TBool TAwaitingBindTo::Accept()
+ {
+ const TCFDataClient::TBindTo* bindToMessage = message_cast<TCFDataClient::TBindTo>(&iContext.iMessage);
+ if (bindToMessage)
+ {
+ //TBindTo is always a response. there's gotta be an activity.
+ if (iContext.iNodeActivity && iContext.iNodeActivity->SupportsExtInterface(ABindingActivity::KInterfaceId))
+ {
+ ABindingActivity* bindingActivity = reinterpret_cast<ABindingActivity*>(iContext.iNodeActivity->FetchExtInterface(ABindingActivity::KInterfaceId));
+ bindingActivity->StoreOriginator(iContext.iSender);
+ }
+ return ETrue;
+ }
+ return EFalse;
+ }
+
+EXPORT_DEFINE_SMELEMENT(TAwaitingBindToOrCancel, NetStateMachine::MState, CoreStates::TContext)
+TBool TAwaitingBindToOrCancel::Accept()
+ {
+ TAwaitingBindTo st(iContext);
+ if (st.Accept())
+ {
+ return ETrue;
+ }
+ if (iContext.iMessage.IsMessage<TEBase::TCancel>())
+ {
+ iContext.iNodeActivity->SetError(KErrCancel);
+ iContext.iMessage.ClearMessageId();
+ return EFalse;
+ }
+ return EFalse;
+ }
+
+EXPORT_DEFINE_SMELEMENT(TAwaitingDataClientJoin, NetStateMachine::MState, CoreNetStates::TContext)
+EXPORT_C TBool TAwaitingDataClientJoin::Accept()
+ {
+ __ASSERT_DEBUG(iContext.iNodeActivity, CorePrPanic(KPanicNoActivity));
+ TCFFactory::TPeerFoundOrCreated* dcJoined = message_cast<TCFFactory::TPeerFoundOrCreated>(&iContext.iMessage);
+ if ( dcJoined )
+ {
+ if (iContext.iNodeActivity->Error() != KErrNone)
+ {
+ TNodeCtxId returnId(iContext.ActivityId(), iContext.NodeId());
+
+ RNodeInterface* clientAlreadyAdded = iContext.Node().FindClient(dcJoined->iNodeId);
+ if (clientAlreadyAdded == NULL && !dcJoined->iNodeId.IsNull())
+ {
+ RClientInterface::OpenPostMessageClose(returnId, dcJoined->iNodeId, TEChild::TDestroy().CRef());
+ // Add the node to our client list to prevent the TLeft response to the TDestroy
+ // resulting in PRClientLeaveActivity failing to find the node and panicing.
+ iContext.Node().AddClientL(dcJoined->iNodeId, TClientType(TCFClientType::EData, TClientType::ELeaving));
+ }
+ TEBase::TError simualtedErrorMessage(TCFFactory::TFindOrCreatePeer::Id(),
+ iContext.iNodeActivity->Error());
+
+ RClientInterface::OpenPostMessageClose(iContext.iSender, returnId, simualtedErrorMessage);
+ iContext.iMessage.ClearMessageId();
+ return EFalse;
+ }
+ else
+ {
+ return ETrue;
+ }
+ }
+ else if (iContext.iMessage.IsMessage<TEBase::TCancel>())
+ {
+ //We can't send TCancel to the factory, we better eat the message
+ //here and switch the activity into a cancelling mode.
+ iContext.iMessage.ClearMessageId();
+ iContext.iNodeActivity->SetError(KErrCancel);
+ }
+ return EFalse;
+ }
+
+EXPORT_DEFINE_SMELEMENT(TAwaitingJoinComplete, NetStateMachine::MState, CoreStates::TContext)
+EXPORT_C TBool TAwaitingJoinComplete::Accept()
+ {
+ if(iContext.iMessage.IsMessage<TCFPeer::TJoinComplete>())
+ {
+ return ETrue;
+ }
+ else if(iContext.iMessage.IsMessage<TEBase::TError>())
+ {
+ iContext.Node().RemoveClient(iContext.iSender);
+ }
+ return EFalse;
+ }
+
+EXPORT_DEFINE_SMELEMENT(TAwaitingBinderResponse, NetStateMachine::MState, CoreNetStates::TContext)
+EXPORT_C TBool TAwaitingBinderResponse::Accept()
+ {
+ const TCFServiceProvider::TCommsBinderResponse* binderResponseMsg = message_cast<TCFServiceProvider::TCommsBinderResponse>(&iContext.iMessage);
+ if (binderResponseMsg)
+ {
+ if (iContext.iNodeActivity && iContext.iNodeActivity->SupportsExtInterface(ABindingActivity::KInterfaceId))
+ {
+ ABindingActivity* bindingActivity = reinterpret_cast<ABindingActivity*>(iContext.iNodeActivity->FetchExtInterface(ABindingActivity::KInterfaceId));
+ __ASSERT_DEBUG(bindingActivity, User::Panic(KSpecAssert_ESockCrStaCPRSC, 28));
+ bindingActivity->StoreOriginator(iContext.iSender);
+ }
+ return ETrue;
+ }
+ return EFalse;
+ }
+
+EXPORT_DEFINE_SMELEMENT(CoreNetStates::TAwaitingBindToComplete, NetStateMachine::MState, CoreNetStates::TContext)
+EXPORT_C TBool CoreNetStates::TAwaitingBindToComplete::Accept()
+ {
+ TCFDataClient::TBindToComplete* bindToComplete = message_cast<TCFDataClient::TBindToComplete>(&iContext.iMessage);
+ if (bindToComplete)
+ {
+ __ASSERT_DEBUG(iContext.iNodeActivity, CorePrPanic(KPanicNoActivity));
+ iContext.iNodeActivity->SetError(bindToComplete->iValue);
+ return ETrue;
+ }
+ return EFalse;
+ }
+
+EXPORT_DEFINE_SMELEMENT(TAwaitingProvision, NetStateMachine::MState, PRStates::TContext)
+EXPORT_C TBool TAwaitingProvision::Accept()
+ {
+ return iContext.iMessage.IsMessage<TCFDataClient::TProvisionConfig>();
+ }
+
+EXPORT_DEFINE_SMELEMENT(TAwaitingControlClientJoin, NetStateMachine::MState, PRStates::TContext)
+EXPORT_C TBool TAwaitingControlClientJoin::Accept()
+ {
+ return iContext.iMessage.IsMessage<TCFFactory::TPeerFoundOrCreated>()
+ || iContext.iMessage.IsMessage<TCFPeer::TJoinRequest>();
+ }
+
+DEFINE_SMELEMENT(TAwaitingCSRCreated, NetStateMachine::MState, CoreNetStates::TContext)
+TBool CoreNetStates::TAwaitingCSRCreated::Accept()
+ {
+ return iContext.iMessage.IsMessage<TCFInternalEsock::TCSRCreated>();
+ }
+
+EXPORT_DEFINE_SMELEMENT(TAwaitingDataClientStatusChange, NetStateMachine::MState, CoreNetStates::TContext)
+EXPORT_C TBool CoreNetStates::TAwaitingDataClientStatusChange::Accept()
+ {
+ return iContext.iMessage.IsMessage<TCFControlProvider::TDataClientStatusChange>();
+ }
+
+EXPORT_DEFINE_SMELEMENT(TAwaitingProviderStatusChangeOrDataClientStatusChange, NetStateMachine::MState, CoreNetStates::TContext)
+EXPORT_C TBool CoreNetStates::TAwaitingProviderStatusChangeOrDataClientStatusChange::Accept()
+ {
+ return iContext.iMessage.IsMessage<TCFMcpr::TProviderStatusChange>() || iContext.iMessage.IsMessage<TCFControlProvider::TDataClientStatusChange>();
+ }
+
+EXPORT_DEFINE_SMELEMENT(TAwaitingLegacyRMessage2Ext, NetStateMachine::MState, CoreNetStates::TContext)
+EXPORT_C TBool CoreNetStates::TAwaitingLegacyRMessage2Ext::Accept()
+ {
+ return iContext.iMessage.IsTypeOf(Meta::STypeId::CreateSTypeId(TCFSigLegacyRMessage2Ext::EUid, TCFSigLegacyRMessage2Ext::ETypeId));
+ }
+
+
+EXPORT_DEFINE_SMELEMENT(TAwaitingRMessage2Processed, NetStateMachine::MState, CoreNetStates::TContext)
+EXPORT_C TBool CoreNetStates::TAwaitingRMessage2Processed::Accept()
+ {
+ return iContext.iMessage.IsMessage<TCFLegacyMessage::TLegacyRMessage2Processed>();
+ }
+
+EXPORT_C void CoreNetStates::TAwaitingRMessage2Processed::Cancel()
+ {
+ MeshMachine::CNodeParallelMessageStoreActivityBase* act = static_cast<MeshMachine::CNodeParallelMessageStoreActivityBase*>(iContext.Activity());
+
+ ASSERT(act->Message().IsTypeOf(Meta::STypeId::CreateSTypeId(TCFSigLegacyRMessage2Ext::EUid, TCFSigLegacyRMessage2Ext::ETypeId)));
+ static_cast<TCFSigLegacyRMessage2Ext&>(act->Message()).Cancel(iContext);
+
+ act->SetError(KErrCancel);
+ }
+
+EXPORT_DEFINE_SMELEMENT(TAwaitingParamRequest, NetStateMachine::MState, PRStates::TContext)
+EXPORT_C TBool TAwaitingParamRequest::Accept()
+ {
+#ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+ if(iContext.iMessage.IsMessage<TCFScpr::TSetParamsRequest>() || iContext.iMessage.IsMessage<TCFScpr::TGetParamsRequest>())
+ {
+ return ETrue;
+ }
+#endif
+ return EFalse;
+ }
+
+EXPORT_DEFINE_SMELEMENT(TAwaitingApplyRequest, NetStateMachine::MState, PRStates::TContext)
+EXPORT_C TBool TAwaitingApplyRequest::Accept()
+ {
+ return iContext.iMessage.IsMessage<TCFScpr::TApplyRequest>();
+ }
+
+//-=========================================================
+//
+//State Forks
+//
+//-=========================================================
+
+EXPORT_DEFINE_SMELEMENT(TPeerPresent, NetStateMachine::MStateFork, CoreStates::TContext)
+TInt TPeerPresent::TransitionTag()
+ {
+ return CoreStates::KPeerPresent | NetStateMachine::EForward;
+ }
+
+EXPORT_DEFINE_SMELEMENT(TNoTagOrNoPeer, NetStateMachine::MStateFork, CoreStates::TContext)
+TInt TNoTagOrNoPeer::TransitionTag()
+ {
+ if (iContext.iPeer)
+ {
+ return MeshMachine::KNoTag | NetStateMachine::EForward;
+ }
+ return CoreStates::KNoPeer | NetStateMachine::EForward;
+ }
+
+EXPORT_DEFINE_SMELEMENT(TRetryOrIgnoreOrPropagate, NetStateMachine::MStateFork, CoreStates::TContext)
+TInt TRetryOrIgnoreOrPropagate::TransitionTag()
+ {
+ TErrResponse& resp = message_cast<TEErrorRecovery::TErrorRecoveryResponse>(iContext.iMessage).iErrResponse;
+ if (resp.iAction == TErrResponse::EPropagate)
+ {
+ return CoreStates::KPropagate | NetStateMachine::EForward;
+ }
+ if (resp.iAction == TErrResponse::EIgnore)
+ {
+ return CoreStates::KIgnore | NetStateMachine::EForward;
+ }
+ return CoreStates::KRetry | NetStateMachine::EForward;
+ }
+
+// This transition tag follows the logic that any error is recoverable except for KErrCancel
+// A KErrCancel error can come from either the activity or the current message if its a TError message
+// A KErrCancel takes precedence over other errors
+EXPORT_DEFINE_SMELEMENT(TNoTagOrRecoverableErrorTagOrErrorTag, NetStateMachine::MStateFork, CoreStates::TContext)
+EXPORT_C TInt TNoTagOrRecoverableErrorTagOrErrorTag::TransitionTag()
+ {
+ TEBase::TError* msg = message_cast<TEBase::TError>(&iContext.iMessage);
+ if (KErrNone==iContext.iNodeActivity->Error() && NULL==msg)
+ {
+ // Not a TError message and no error present in the activity
+ return MeshMachine::KNoTag | NetStateMachine::EForward;
+ }
+ else if (iContext.iNodeActivity->Error() == KErrCancel || (msg && msg->iValue == KErrCancel))
+ {
+ // Non recoverable KErrCancel
+ iContext.iNodeActivity->SetError(KErrCancel);
+ return KErrorTag | NetStateMachine::EForward;
+ }
+ else
+ {
+ // Any other error
+ if (msg)
+ {
+ // If the error came from the message then update the activity's error
+ iContext.iNodeActivity->SetError(msg->iValue);
+ }
+ return CoreStates::KRecoverableErrorTag | NetStateMachine::EForward;
+ }
+ }
+
+EXPORT_DEFINE_SMELEMENT(TBearerPresent, NetStateMachine::MStateFork, CoreNetStates::TContext)
+EXPORT_C TInt TBearerPresent::TransitionTag()
+ {
+ return CoreNetStates::KBearerPresent | NetStateMachine::EForward;
+ }
+
+EXPORT_DEFINE_SMELEMENT(TNoTagOrDataClientPresent, NetStateMachine::MStateFork, CoreNetStates::TContext)
+EXPORT_C TInt TNoTagOrDataClientPresent::TransitionTag()
+ {
+ if (iContext.Node().CountClients<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EData)))
+ {
+ return CoreNetStates::KDataClientPresent | NetStateMachine::EForward;
+ }
+ return KNoTag;
+ }
+
+EXPORT_DEFINE_SMELEMENT(TNoTagOrDataClientsToStop, NetStateMachine::MStateFork, CoreNetStates::TContext)
+EXPORT_C TInt TNoTagOrDataClientsToStop::TransitionTag()
+ {
+ if (iContext.Node().GetFirstClient<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EData, TCFClientType::EStarted),
+ TClientType(0, TClientType::ELeaving)))
+ {
+ return CoreNetStates::KDataClientsToStop | NetStateMachine::EForward;
+ }
+ return KNoTag;
+ }
+
+EXPORT_DEFINE_SMELEMENT(TNoTagOrNoDataClientsToStop, NetStateMachine::MStateFork, CoreNetStates::TContext)
+TInt TNoTagOrNoDataClientsToStop::TransitionTag()
+/**
+Return:
+KNoTag There are data clients present that are not marked EStopped
+KNoDataClientsToStop There are no data clients present that are not marked EStopped
+*/
+ {
+ if (iContext.Node().CountClients<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EData, TCFClientType::EStarted)))
+ {
+ return KNoTag;
+ }
+ return CoreNetStates::KNoDataClientsToStop;
+ }
+
+EXPORT_DEFINE_SMELEMENT(TNoTagOnEvent, NetStateMachine::MStateFork, CoreNetStates::TContext)
+TInt TNoTagOnEvent::TransitionTag()
+ {
+ if (iContext.iNodeActivity)
+ {
+ iContext.iNodeActivity->RemoveOriginator(0);
+ }
+ return KNoTag;
+ }
+
+EXPORT_DEFINE_SMELEMENT(TNoTagOrNoDataClients, NetStateMachine::MStateFork, CoreNetStates::TContext)
+EXPORT_C TInt TNoTagOrNoDataClients::TransitionTag()
+ {
+ //If we have a started flow already, we should not be in here
+ if (iContext.Node().GetFirstClient<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EData)))
+ {
+ return MeshMachine::KNoTag | NetStateMachine::EForward;
+ }
+ return CoreNetStates::KNoDataClients | NetStateMachine::EForward;
+ }
+
+EXPORT_DEFINE_SMELEMENT(TNoTagOrBearerPresent, NetStateMachine::MStateFork, CoreNetStates::TContext)
+EXPORT_C TInt TNoTagOrBearerPresent::TransitionTag()
+ {
+ return iContext.Node().ServiceProvider()? CoreNetStates::KBearerPresent : MeshMachine::KNoTag;
+ }
+
+EXPORT_DEFINE_SMELEMENT(TNoTagOrBearerPresentOrErrorTag, NetStateMachine::MStateFork, CoreNetStates::TContext)
+TInt TNoTagOrBearerPresentOrErrorTag::TransitionTag()
+ {
+ TEBase::TError* msg = message_cast<TEBase::TError>(&iContext.iMessage);
+ if (KErrNone==iContext.iNodeActivity->Error() && NULL==msg)
+ {
+ CoreNetStates::TNoTagOrBearerPresent fork(iContext);
+ return fork.TransitionTag();
+ }
+ if (msg)
+ {
+ iContext.iNodeActivity->SetError(msg->iValue);
+ }
+ return KErrorTag | NetStateMachine::EForward;
+ }
+
+EXPORT_DEFINE_SMELEMENT(TNoTagOrNoBearer, NetStateMachine::MStateFork, CoreNetStates::TContext)
+TInt TNoTagOrNoBearer::TransitionTag()
+ {
+ return iContext.Node().ServiceProvider()? MeshMachine::KNoTag : CoreNetStates::KNoBearer;
+ }
+
+EXPORT_DEFINE_SMELEMENT(TNoTagOrNonDefault, NetStateMachine::MStateFork, CoreNetStates::TContext)
+TInt TNoTagOrNonDefault::TransitionTag()
+/**
+Returns KNoTag uif sender is marked EDefault, else CoreNetStates::KNonDefault.
+*/
+ {
+ __ASSERT_DEBUG(iContext.iPeer, User::Panic(KSpecAssert_ESockCrStaCPRSC, 29));
+ return (iContext.iPeer->Flags() & TCFClientType::EDefault) ? KNoTag : CoreNetStates::KNonDefault;
+ }
+
+EXPORT_DEFINE_SMELEMENT(TNoTagOrNoClients, NetStateMachine::MStateFork, CoreNetStates::TContext)
+TInt TNoTagOrNoClients::TransitionTag()
+/**
+Returns KNoTag uif sender is marked EDefault, else CoreNetStates::KNonDefault.
+*/
+ {
+ return iContext.Node().CountClients<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EData | TCFClientType::ECtrl))? KNoTag : KNoClients;
+ }
+
+EXPORT_DEFINE_SMELEMENT(TNoTagBackwardsOrProviderStopped, NetStateMachine::MStateFork, CoreNetStates::TContext)
+EXPORT_C TInt TNoTagBackwardsOrProviderStopped::TransitionTag()
+ {
+ if (iContext.Node().GetFirstClient<TDefaultClientMatchPolicy>(
+ TClientType(TCFClientType::EData, TCFClientType::EStarted)) != NULL)
+ {
+ // At least one started data client
+ return MeshMachine::KNoTag | NetStateMachine::EBackward;
+ }
+ return CoreNetStates::KProviderStopped;
+ }
+
+EXPORT_DEFINE_SMELEMENT(TNoTagOrUnbindOnStop, NetStateMachine::MStateFork, CoreNetStates::TContext)
+EXPORT_C TInt TNoTagOrUnbindOnStop::TransitionTag()
+ {
+ if (iContext.Node().ServiceProvider() &&
+ !(iContext.Node().ServiceProvider()->Flags() & TCFClientType::EStarted) &&
+ !(iContext.Node().ServiceProvider()->Flags() & TCFClientType::ELeaving) &&
+ (iContext.Node().CountActivities(ECFActivityStart) == 0))
+ {
+ return CoreNetStates::KUnbind;
+ }
+ return KNoTag;
+ }
+
+
+//-=========================================================
+//
+//Transitions
+//
+//-=========================================================
+
+EXPORT_DEFINE_SMELEMENT(TForwardStateChange, NetStateMachine::MStateTransition, PRStates::TContext)
+EXPORT_C void TForwardStateChange::DoL()
+ {
+ //Forward to control clients if there are any
+ TInt ctrlClientCount = iContext.Node().PostToClients<TDefaultClientMatchPolicy>(TNodeCtxId(iContext.ActivityId(), iContext.NodeId()), iContext.iMessage, TClientType(TCFClientType::ECtrl));
+ if (0==ctrlClientCount)
+ { //If there are no control clients any more, forward to the control provider
+ iContext.Node().PostToClients<TDefaultClientMatchPolicy>(TNodeCtxId(iContext.ActivityId(), iContext.NodeId()), iContext.iMessage, TClientType(TCFClientType::ECtrlProvider));
+ }
+ }
+
+
+EXPORT_DEFINE_SMELEMENT(TStoreProvision, NetStateMachine::MStateTransition, PRStates::TContext)
+EXPORT_C void TStoreProvision::DoL()
+ {
+ TCFDataClient::TProvisionConfig& provisionMsg = message_cast<TCFDataClient::TProvisionConfig>(iContext.iMessage);
+ iContext.Node().iAccessPointConfig.Close();
+ iContext.Node().iAccessPointConfig.Open(provisionMsg.iConfig);
+ }
+
+
+EXPORT_DEFINE_SMELEMENT(TSendProvision, NetStateMachine::MStateTransition, PRStates::TContext)
+EXPORT_C void TSendProvision::DoL()
+ {
+ __ASSERT_DEBUG(iContext.iNodeActivity, CorePrPanic(KPanicNoActivity));
+
+ RNodeInterface* client = iContext.Node().FindClient(message_cast<TCFFactory::TPeerFoundOrCreated>(iContext.iMessage).iNodeId);
+ __ASSERT_ALWAYS(NULL != client && (client->Type() == TCFClientType::EData), CorePrPanic(KPanicIncorrectMessage));
+
+ // If the data client was stopped in between the completion of the join and before we send the provision
+ // message then the client will start leaving. This means we should not send the provision message since
+ // it is now redundant and it is not legal to send a message to a client which is leaving.
+ if(!(client->Flags() & TClientType::ELeaving))
+ {
+ // The construction of the messagee will increase the ref count on the AccessPointConfig
+ // The reference will be released once the message has dispatched
+ client->PostMessage(TNodeCtxId(iContext.ActivityId(), iContext.NodeId()),
+ TCFDataClient::TProvisionConfig(iContext.Node().AccessPointConfig()).CRef());
+ }
+ else
+ {
+ MESH_LOG((KCoreProviderStatesSubTag, _L8("TSendProvision:\tDoL - IGNORING POST!")));
+ }
+ }
+
+EXPORT_DEFINE_SMELEMENT(TCreateDataClient, NetStateMachine::MStateTransition, PRStates::TContext)
+
+void TCreateDataClient::IssuePeerCreationRequestL(ESock::TCFServiceProvider::TCommsBinderRequest* aBinderRequestMessage /* = NULL */)
+ {
+ if (factoryobject_cast<CTierManagerBase>(&iContext.Node()))
+ {
+ RequestMetaConnPeer(iContext.Node().AccessPointConfig());
+ }
+ else if (factoryobject_cast<CMetaConnectionProviderBase>(&iContext.Node()))
+ {
+ RequestConnPeer(iContext.Node().AccessPointConfig());
+ }
+ else if (factoryobject_cast<CConnectionProviderBase>(&iContext.Node()))
+ {
+ RequestSubConnPeer(iContext.Node().AccessPointConfig(), aBinderRequestMessage);
+ }
+ else if (factoryobject_cast<CSubConnectionProviderBase>(&iContext.Node()))
+ {
+ RequestDataPeer(iContext.Node().AccessPointConfig(), aBinderRequestMessage);
+ }
+ else
+ {
+ User::Leave(KErrNotFound);
+ }
+ }
+
+void TCreateDataClient::RequestMetaConnPeer(const RMetaExtensionContainerC& aAccessPointCfg)
+ {
+ TAlwaysFindFactoryQuery query;
+
+ const TLayerConfig* layerCfg = static_cast<const TLayerConfig*>(aAccessPointCfg.FindExtension(
+ STypeId::CreateSTypeId(TLayerConfig::EUid,TLayerConfig::ETypeId)));
+ __ASSERT_ALWAYS(layerCfg, CorePrPanic(KPanicUnexpectedExecutionPath));
+
+ TCFFactory::TFindOrCreatePeer msg(TCFPlayerRole::EMetaConnPlane, layerCfg->MCprUid(), &query);
+
+ // Send the request to the central object broker
+ iContext.iNodeActivity->PostRequestTo(SockManGlobals::Get()->iCommsFactoryContainerBroker, msg, EFalse);
+ }
+
+void TCreateDataClient::RequestConnPeer (const RMetaExtensionContainerC& aAccessPointCfg)
+ {
+ TDefaultConnectionFactoryQuery query(iContext.Node().Id());
+
+ const TLayerConfig* layerCfg = static_cast<const TLayerConfig*>(aAccessPointCfg.FindExtension(
+ STypeId::CreateSTypeId(TLayerConfig::EUid,TLayerConfig::ETypeId)));
+ __ASSERT_ALWAYS(layerCfg, CorePrPanic(KPanicUnexpectedExecutionPath));
+
+ TCFFactory::TFindOrCreatePeer msg(TCFPlayerRole::EConnPlane, layerCfg->CprUid(), &query);
+
+ // Send the request to the central object broker
+ iContext.iNodeActivity->PostRequestTo(SockManGlobals::Get()->iCommsFactoryContainerBroker, msg, EFalse);
+ }
+
+void TCreateDataClient::RequestSubConnPeer (const RMetaExtensionContainerC& aAccessPointCfg, ESock::TCFServiceProvider::TCommsBinderRequest* aBinderRequestMessage)
+ {
+ // The subconnection type carried in the binder request is only relevant when we are expected to create an SCPR
+ TSubConnOpen::TSubConnType scprType = TSubConnOpen::EAttachToDefault;
+ // If we have a protocol extension to apply then do so but default to nothing
+
+ TUid factory = TUid::Null();
+ if (aBinderRequestMessage)
+ {
+ scprType = (TSubConnOpen::TSubConnType)aBinderRequestMessage->iValue;
+ if (!aBinderRequestMessage->iFamilyBundle.IsNull())
+ {
+ // Find the family we are interested in
+ RParameterFamily parameterFamily = aBinderRequestMessage->iFamilyBundle.FindFamily(KProtocolExtensionFamily);
+
+ if(!parameterFamily.IsNull())
+ {
+ STypeId typeId = STypeId::CreateSTypeId(CSubConnectionProtocolParameterSet::EUid, CSubConnectionProtocolParameterSet::EType);
+ CSubConnectionProtocolParameterSet* protocolParams = static_cast<CSubConnectionProtocolParameterSet*>(parameterFamily.FindParameterSet(typeId, RParameterFamily::ERequested));
+ TProtocolExtensionSpecifier protocolSpecifier;
+
+ const TLayerConfig* layerCfg = static_cast<const TLayerConfig*>(aAccessPointCfg.FindExtension(
+ STypeId::CreateSTypeId(TLayerConfig::EUid,TLayerConfig::ETypeId)));
+ __ASSERT_ALWAYS(layerCfg, CorePrPanic(KPanicUnexpectedExecutionPath));
+
+ if(protocolParams->FindAndRemoveExtension(protocolSpecifier, layerCfg->TierId()) == KErrNone)
+ {
+ // We have our protocol extension specifier
+ factory = protocolSpecifier.iSCPRFactoryUid;
+ }
+ }
+ }
+ }
+ // No special protocol extension SCPP given so revert to the default which is given in the access point config
+ if(factory == TUid::Null())
+ {
+ const TLayerConfig* layerCfg = static_cast<const TLayerConfig*>(aAccessPointCfg.FindExtension(
+ STypeId::CreateSTypeId(TLayerConfig::EUid,TLayerConfig::ETypeId)));
+ __ASSERT_ALWAYS(layerCfg, CorePrPanic(KPanicUnexpectedExecutionPath));
+
+ factory = layerCfg->SCprUid();
+ }
+ TDefaultSCPRFactoryQuery query (iContext.Node().Id(), scprType);
+ TCFFactory::TFindOrCreatePeer msg(TCFPlayerRole::ESubConnPlane, factory, &query);
+ // Send the request to the central object broker
+ iContext.iNodeActivity->PostRequestTo(SockManGlobals::Get()->iCommsFactoryContainerBroker, msg, EFalse);
+ }
+
+void TCreateDataClient::RequestDataPeer(const RMetaExtensionContainerC& aAccessPointCfg, ESock::TCFServiceProvider::TCommsBinderRequest* aBinderRequestMessage)
+ {
+ TNodeId controlProvider = iContext.Node().ControlProvider() ? iContext.Node().ControlProvider()->RecipientId() : TNodeId::NullId();
+ TSubConnOpen::TSubConnType protocolType = TSubConnOpen::EAttachToDefault;
+ // Get the flow factory identity from our access point configuration
+
+ const TLayerConfig* layerCfg = static_cast<const TLayerConfig*>(aAccessPointCfg.FindExtension(
+ STypeId::CreateSTypeId(TLayerConfig::EUid,TLayerConfig::ETypeId)));
+ __ASSERT_ALWAYS(layerCfg, CorePrPanic(KPanicUnexpectedExecutionPath));
+
+ TUid factory = layerCfg->ProtocolUid();
+
+ // Determine what protocol we want the flow factory to create
+ if(aBinderRequestMessage && ! aBinderRequestMessage->iFamilyBundle.IsNull())
+ {
+ // Find the flow parameter family of parameters
+ RParameterFamily parameterFamily = aBinderRequestMessage->iFamilyBundle.FindFamily(KFlowParametersFamily);
+
+ if(!parameterFamily.IsNull())
+ {
+ STypeId typeId = STypeId::CreateSTypeId(CFlowRequestParameters::EUid, CFlowRequestParameters::EType);
+ CFlowRequestParameters* flowParams = static_cast<CFlowRequestParameters*>(parameterFamily.FindParameterSet(typeId, RParameterFamily::ERequested));
+
+ // The type of flow created by the flow factory is dependent only on the protocol type
+ protocolType = (TSubConnOpen::TSubConnType)flowParams->GetFlowParams().iProtocol;
+ }
+ }
+ TDefaultFlowFactoryQuery query(controlProvider, iContext.Node().Id(), iContext.iMessage.MessageId(), protocolType);
+ TCFFactory::TFindOrCreatePeer msg(TCFPlayerRole::EDataPlane, factory, &query);
+ // Send the request to the central object broker
+ iContext.iNodeActivity->PostRequestTo(SockManGlobals::Get()->iCommsFactoryContainerBroker, msg, EFalse);
+ }
+
+EXPORT_C void TCreateDataClient::DoL()
+ {
+ __ASSERT_DEBUG(iContext.iNodeActivity, CorePrPanic(KPanicNoActivity));
+ TCFServiceProvider::TCommsBinderRequest* binderReq = message_cast<TCFServiceProvider::TCommsBinderRequest>(&iContext.iMessage);
+
+ __ASSERT_DEBUG(binderReq, CorePrPanic(KPanicIncorrectMessage));
+
+ // Sender must be one of the control clients
+ // Except in the special case of a CPR being asked by one of its data clients (an SCPR) to stack another below it
+ __ASSERT_DEBUG(
+ iContext.iSender == iContext.NodeId() ||
+ iContext.iPeer->Type() == TCFClientType::ECtrl ||
+ ((iContext.iPeer->Type() == TCFClientType::EData) && (factoryobject_cast<CConnectionProviderBase>(&iContext.Node()) != NULL)), User::Panic(KSpecAssert_ESockCrStaCPRSC, 30));
+
+ IssuePeerCreationRequestL(binderReq);
+
+ }
+
+EXPORT_DEFINE_SMELEMENT(TCancelDataClientStart, NetStateMachine::MStateTransition, PRStates::TContext)
+EXPORT_C void TCancelDataClientStart::DoL()
+ {
+ // Cancel must come from the same activity that sent TStart
+ // This transition will handle Data Clients started by ECFActivityStart
+ // it will not handle those started by ECFActivityStartDataClient
+ RClientInterface::OpenPostMessageClose(TNodeCtxId(ECFActivityStart, iContext.NodeId()), iContext.NodeId(), TEBase::TCancel().CRef());
+ }
+
+EXPORT_DEFINE_SMELEMENT(TProcessDataClientStop, NetStateMachine::MStateTransition, PRStates::TContext)
+EXPORT_C void TProcessDataClientStop::DoL()
+ {
+ __ASSERT_DEBUG(iContext.iNodeActivity, CorePrPanic(KPanicNoActivity));
+
+ iContext.iNodeActivity->SetError(static_cast<TSigNumber&>(iContext.iMessage).iValue);
+ }
+
+DEFINE_SMELEMENT(TCancelAndCloseZone0ClientExtIfaces, NetStateMachine::MStateTransition, CoreNetStates::TContext)
+void TCancelAndCloseZone0ClientExtIfaces::DoL()
+ {
+ //0 means we will cancel and close all open extensions!
+ TCancelAndCloseAllClientExtItf msg(0);
+ iContext.Node().PostToClients<TDefaultClientMatchPolicy>(iContext.NodeId(), msg,
+ TClientType(TCFClientType::EServProvider), TClientType(0, TCFClientType::ELeaving));
+ }
+
+EXPORT_DEFINE_SMELEMENT(THandleDataClientStatusChange, NetStateMachine::MStateTransition, PRStates::TContext)
+EXPORT_C void THandleDataClientStatusChange::DoL()
+ {
+ TCFControlProvider::TDataClientStatusChange& msg = message_cast<TCFControlProvider::TDataClientStatusChange>(iContext.iMessage);
+
+ if(msg.iValue == TCFControlProvider::TDataClientStatusChange::EStarted)
+ {
+ iContext.iPeer->SetFlags(TCFClientType::EStarted);
+
+ // One of my data clients is started, therefore, I am started
+ iContext.Node().PostToClients<TDefaultClientMatchPolicy>(TNodeCtxId(iContext.ActivityId(), iContext.NodeId()),
+ msg, TClientType(TCFClientType::ECtrlProvider));
+ }
+ else
+ {
+ iContext.iPeer->ClearFlags(TCFClientType::EStarted);
+ }
+
+ }
+
+EXPORT_DEFINE_SMELEMENT(TSendDataClientStatusChangeStarted, NetStateMachine::MStateTransition, PRStates::TContext)
+EXPORT_C void TSendDataClientStatusChangeStarted::DoL()
+ {
+ iContext.Node().PostToClients<TDefaultClientMatchPolicy>(TNodeCtxId(iContext.ActivityId(), iContext.NodeId()),
+ TCFControlProvider::TDataClientStatusChange(TCFControlProvider::TDataClientStatusChange::EStarted).CRef(), TClientType(TCFClientType::ECtrlProvider));
+ }
+
+
+EXPORT_DEFINE_SMELEMENT(TProcessOrForwardRMessage2Ext, NetStateMachine::MStateTransition, CoreNetStates::TContext)
+EXPORT_C void TProcessOrForwardRMessage2Ext::DoL()
+ {
+ ASSERT(iContext.iMessage.IsTypeOf(Meta::STypeId::CreateSTypeId(TCFSigLegacyRMessage2Ext::EUid, TCFSigLegacyRMessage2Ext::ETypeId)));
+ // static_cast as it will be a derivative and message_cast won't work
+ TCFSigLegacyRMessage2Ext& msg = static_cast<TCFSigLegacyRMessage2Ext&>(iContext.iMessage);
+
+ if (msg.CanProcess(iContext))
+ {
+ msg.ProcessL(iContext);
+ }
+ else
+ {
+ msg.ForwardL(iContext);
+ }
+ }
+
+EXPORT_DEFINE_SMELEMENT(TCancelStart, NetStateMachine::MStateTransition, CoreNetStates::TContext)
+void TCancelStart::DoL()
+ {
+ CNodeActivityBase* startActivity = iContext.Node().FindActivityById(ECFActivityStart);
+ if (startActivity)
+ {
+ startActivity->Cancel(iContext);
+ }
+ }
+