datacommsserver/esockserver/CoreProviders/src/corecpractivities.cpp
changeset 0 dfb7c4ff071f
child 18 9644881fedd0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/datacommsserver/esockserver/CoreProviders/src/corecpractivities.cpp	Thu Dec 17 09:22:25 2009 +0200
@@ -0,0 +1,313 @@
+// 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:
+// Core CPR Activities
+// THIS API IS INTERNAL TO NETWORKING AND IS SUBJECT TO CHANGE AND NOT FOR EXTERNAL USE
+//
+//
+
+/**
+ @file
+ @internalComponent
+*/
+
+#define SYMBIAN_NETWORKING_UPS
+
+#include "corecpractivities.h"
+
+#include <comms-infras/ss_log.h>
+#include <comms-infras/corescpractivities.h>
+#include <comms-infras/ss_nodemessages_dataclient.h>
+#include <comms-infras/ss_nodemessages_mcpr.h>
+#include "ss_internal_activities.h"
+#ifdef SYMBIAN_NETWORKING_UPS
+#include <comms-infras/upsmessages.h>
+#include <comms-infras/upsprstates.h>
+#endif
+
+using namespace ESock;
+using namespace CprActivities;
+using namespace NetStateMachine;
+using namespace PRActivities;
+using namespace CoreNetStates;
+using namespace MeshMachine;
+using namespace Messages;
+
+
+
+//-=========================================================
+//
+// Activities
+//
+//-=========================================================
+
+namespace CprControlClientJoinActivity
+{
+DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityClientJoin, CprControlClientJoin, TNodeSignal::TNullMessageId, CControlClientJoinActivity::NewL)
+	FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingControlClientJoin,  CControlClientJoinActivity::TAddClientOrUpdatePriority)
+	THROUGH_NODEACTIVITY_ENTRY(CprStates::KUpdatePriority, MeshMachine::TDoNothing, CControlClientJoinActivity::TNoTagOrSendPriorityToCtrlProvider)
+	THROUGH_NODEACTIVITY_ENTRY(CprStates::KAddClient, CprStates::TAddControlClient, CControlClientJoinActivity::TNoTagOrSendPriorityToCtrlProvider)
+	NODEACTIVITY_ENTRY(CprStates::KSendPriorityToCtrlProvider, CControlClientJoinActivity::TUpdatePriorityForControlProvider, CoreStates::TAwaitingJoinComplete, CControlClientJoinActivity::TNoTagOrSendPriorityToServProvider)
+	NODEACTIVITY_ENTRY(CprStates::KSendPriorityToServProvider, CControlClientJoinActivity::TUpdatePriorityForServiceProviders, CoreStates::TAwaitingJoinComplete, MeshMachine::TNoTag)
+	THROUGH_NODEACTIVITY_ENTRY(KNoTag, CControlClientJoinActivity::TSendJoinCompleteIfRequest, CControlClientJoinActivity::TNoTagOrSendActive)
+	LAST_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing)
+	LAST_NODEACTIVITY_ENTRY(CprStates::KSendActive, CoreNetStates::TSendDataClientActive)
+NODEACTIVITY_END()
+}
+
+namespace CprNoBearerActivity
+{
+// Note that there is an issue here with multiple NoBearer messages being received in rapid succession which
+// results in several of these activities running in parallel.  This will not be resolved by the
+// CoreNetStates::TNoTagOrBearerPresent due to the almost simultaneous reception of the messages.  This
+// could possibly be resolved with a custom mutex that checks for a ServiceProvider() as part of its
+// IsBlocked() check.
+
+DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityNoBearer, CprNoBearer, TCFControlProvider::TNoBearer, PRActivities::CNoBearer::NewL)
+	FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingNoBearer, MeshMachine::TNoTag)
+	THROUGH_NODEACTIVITY_ENTRY(KNoTag, PRActivities::CNoBearer::TStoreRequestParameters, CNoBearer::TNoTagOrBearerPresentBlockedByNoBearer)
+	NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendNoBearer, MeshMachine::TAwaitingMessageState<TCFControlProvider::TBearer>, CoreNetStates::TNoTagOrBearerPresentOrErrorTag)
+
+	NODEACTIVITY_ENTRY(CoreNetStates::KBearerPresent, PRActivities::CNoBearer::TRequestCommsBinderRetry, CoreNetStates::TAwaitingBinderResponse, MeshMachine::TTag<CoreNetStates::KBearerPresent>)
+	NODEACTIVITY_ENTRY(CoreNetStates::KBearerPresent, CoreNetStates::TSendBindTo, CoreNetStates::TAwaitingBindToComplete, MeshMachine::TTag<CoreNetStates::KBearerPresent>)
+	THROUGH_NODEACTIVITY_ENTRY(CoreNetStates::KBearerPresent, CoreActivities::ABindingActivity::TSendBindToComplete, CNoBearer::TNoTagOrBearerPresentForAutostart)
+
+	//Autostart on NoBearer.
+ 	//The philosphy here is that if the local node doesn't have a control client, then there's noone
+ 	//that could posibly start it. It will hence decide to autostart as the top layer of what looks
+ 	//like an implicit connection. In the future this autostart behaviour should become a specialty
+ 	//of someone more concrete (rather than generic function). We are speculating about the implicit
+ 	//top layer that could acquire this function if it ever comes into being.
+	NODEACTIVITY_ENTRY(CoreNetStates::KBearerPresent, CoreNetStates::TStartServiceProviderRetry, CoreNetStates::TAwaitingStarted, MeshMachine::TNoTag)
+
+	LAST_NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendBearer)
+    LAST_NODEACTIVITY_ENTRY(KErrorTag, MeshMachine::TDoNothing)
+NODEACTIVITY_END()
+}
+
+namespace CprBindToActivity
+{
+DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityBindTo, CprBindTo, TCFDataClient::TBindTo, CCprBindToActivity::NewL)
+	FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingBindTo, CCprBindToActivity::TNoTagOrBearerReady)
+    //TBindTo can hold:
+    //[KNoTag] 		 - a valid serviceProvider cookie that this node isn't bound to;
+    //[KBearerReady] - a valid serviceProvider cookie that this node is already bound to;
+    //[KBearerReady] - a NULL serviceProvider (this node is at the stack's bottom);
+
+	  //{ JOINING NEW SERVICE PROVIDER
+		//a valid serviceProvider supplied, new to this node, let's join it;
+	    NODEACTIVITY_ENTRY(KNoTag, CCprBindToActivity::TSendControlClientJoinRequestWithPriority, CoreStates::TAwaitingJoinComplete, TTag<KBearerReady>)
+	  //}
+
+	//serviceProvider provisionally joined. Now the activity needs to construct the configuration access points
+	THROUGH_NODEACTIVITY_ENTRY(KDataClientReady, MeshMachine::TDoNothing, CprStates::TCreateAdditionalDataClientOrDataClientReady)
+		NODEACTIVITY_ENTRY(CprStates::KCreateAdditionalDataClient, CprStates::TCreateAdditionalDataClient, CoreNetStates::TAwaitingDataClientJoin, MeshMachine::TTag<CprStates::KCreatingAdditionalDataClient>)
+		NODEACTIVITY_ENTRY(CprStates::KCreatingAdditionalDataClient, CprStates::TProcessAdditionalDataClientCreationAndBindToPrimary, CoreNetStates::TAwaitingBindToComplete, CprStates::TCreateAdditionalDataClientBackwardOrDataClientReady)
+
+	//Now the activity needs to propagate iteslf (TBindTo) to its dataclients.
+	//The dataclients are either present or not. If not this activity will assume this is the layer construction phase
+	//and will attempt to construct a default dataclient.
+	THROUGH_NODEACTIVITY_ENTRY(KBearerReady, MeshMachine::TDoNothing, CCprBindToActivity::TNoTagOrDataClientReady)
+
+	  //{ DATA CLIENT CREATION
+		//No dataclients present, assume this is the layer creation phase. Attempt to create a dataclient.
+		NODEACTIVITY_ENTRY(KNoTag, CCprBindToActivity::TCreateDataClient, TAcceptErrorState<CoreNetStates::TAwaitingDataClientJoin>, MeshMachine::TErrorTagOr<CCprBindToActivity::TNoTagOrBindToComplete>)
+	    //BindTo activity is the pre-start layer builder, hence it always requests the dataclient from the factory.
+	    //The factory (being aware of the phase) may decide to:
+	    //1. create a new dataclient          -> process dataclient creation            [KNoTag]
+	    //2. return a preexisting dataclient  -> bind the client                        [KDataClientReady]
+	    //3. not to create a dataclient       -> send TBindToComplete to the originator [KBindToComplete]
+		THROUGH_NODEACTIVITY_ENTRY(KNoTag, PRStates::TProcessDataClientCreation, TTag<KDataClientReady>)
+	  //}
+
+    THROUGH_NODEACTIVITY_ENTRY(KDataClientReady, MeshMachine::TDoNothing, CCprBindToActivity::TNoTagOrBearerReadyOrBindToComplete)
+      //{ BINDING DATACLIENTS LOOP
+	    //Dataclient(s) is/are ready. Depending on whether the node has the lower layer or not,
+	    //we will [KNoTag] or will not [KNoBearer] need to request a binder for the dataclient.
+
+		  //{SERVICE PROVIDER PRESENT
+			NODEACTIVITY_ENTRY(KNoTag, CCprBindToActivity::TRequestCommsBinder, TAcceptErrorState<CoreNetStates::TAwaitingBinderResponse>, TErrorTagOr<TTag<KBearerReady> >)
+	      //}
+		NODEACTIVITY_ENTRY(KBearerReady, CCprBindToActivity::TSendBindTo, CCprBindToActivity::TAwaitingBindToCompleteOrError,
+																					 TErrorTagOr<TTag<KDataClientReady | NetStateMachine::EBackward> >)
+	  //}
+
+	//Binding is finished. If this is not autocommit (see TCFDataClient::TBindTo), the activity will reply TCFDataClient::TBindToComplete
+	//to the sender await for the confirmation (TCFDataClient::TCommitBindTo) or cancelation (TBase::TCancel) from the sender.
+	//If this is autommit, the activity will skip awaiting for TCFDataClient::TCommitBindTo and commit itself.
+	THROUGH_NODEACTIVITY_ENTRY(KBindToComplete, CCprBindToActivity::TSendBindToComplete, CCprBindToActivity::TNoTagOrCommit)
+	NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing, MeshMachine::TAwaitingMessageState<TCFDataClient::TCommitBindTo>, TErrorTagOr<TTag<CoreStates::KCommit> >)
+
+	//commiting (either implicit or explicit).
+	NODEACTIVITY_ENTRY(CoreStates::KCommit, CCprBindToActivity::TCommit, MeshMachine::TAwaitingLeaveComplete, MeshMachine::TNoTag)
+
+	//This is not autocommit and the sender has just explicitly cancelled. Alternativelly this is an error path.
+	//Cancelling/processing error entiles sending TCancel to all dataclients awaiting confirmation
+	//as well as it entiles leaving the new service provider.
+	NODEACTIVITY_ENTRY(KErrorTag, CCprBindToActivity::TCancel, MeshMachine::TAwaitingLeaveComplete, MeshMachine::TNoTag)
+
+	LAST_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing)
+NODEACTIVITY_END()
+}
+
+namespace CprBinderRequestActivity
+{
+DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityBinderRequest, CprBinderRequest, TCFServiceProvider::TCommsBinderRequest, CCommsBinderActivity::NewL)
+	FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingBinderRequest, CCommsBinderActivity::TNoTagOrWaitForIncomingOrUseExistingDefaultBlockedByBinderRequest)
+	NODEACTIVITY_ENTRY(KNoTag, PRStates::TCreateDataClient, CoreNetStates::TAwaitingDataClientJoin, MeshMachine::TNoTag)
+
+	// Below this point we need to modify the error handling approach. If we're getting a TError on TBinderResponse,
+	// this means the client requesting the binder couldn't bind to it. As far as the client is concerned, this
+	// activity is finished (it has flagged an error). The standard error handling will result in erroring
+	// the originator. In this case we shouoldn't error the originator, instead, wrap up quietly.
+	THROUGH_NODEACTIVITY_ENTRY(KNoTag, CCommsBinderActivity::TProcessDataClientCreation, MeshMachine::TTag<CoreStates::KUseExisting>)
+
+	NODEACTIVITY_ENTRY(CoreStates::KUseExisting, CCommsBinderActivity::TSendBinderResponse, CCommsBinderActivity::TAwaitingBindToComplete, MeshMachine::TNoTagOrErrorTag)
+	LAST_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing)
+
+	LAST_NODEACTIVITY_ENTRY(KErrorTag, MeshMachine::TClearError)
+	LAST_NODEACTIVITY_ENTRY(CoreNetStates::KWaitForIncoming, MeshMachine::TRaiseError<KErrNotSupported>)
+NODEACTIVITY_END()
+}
+
+namespace CprDataClientStartActivity
+{
+DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityStartDataClient, CprDataClientStart, TCFDataClient::TStart, CDataClientStartActivity::NewL)
+    FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingDataClientStart, CoreNetStates::TNoTagOrNoDataClients)
+	NODEACTIVITY_ENTRY(KNoTag, CprDataClientStartActivity::TStartDataClient, MeshMachine::TAcceptErrorState<CoreNetStates::TAwaitingDataClientStarted>, MeshMachine::TErrorTagOr<CprDataClientStartActivity::TNoTagOrNoTagBackward>)
+	LAST_NODEACTIVITY_ENTRY(KNoTag, PRStates::TSendDataClientStarted)
+	LAST_NODEACTIVITY_ENTRY(CoreNetStates::KNoDataClients, PRStates::TSendDataClientStarted)
+
+	NODEACTIVITY_ENTRY(KErrorTag, CoreNetStates::TStopSelf, CoreNetStates::TAwaitingDataClientStopped, MeshMachine::TErrorTag)
+	LAST_NODEACTIVITY_ENTRY(KErrorTag, MeshMachine::TDoNothing)
+NODEACTIVITY_END()
+}
+
+namespace CprDataClientIdleActivity
+{
+DECLARE_DEFINE_NODEACTIVITY(ECFActivityDataClientIdle, CprDataClientIdle, TCFControlProvider::TIdle)
+    NODEACTIVITY_ENTRY(KNoTag, CprStates::THandleDataClientIdle, CoreNetStates::TAwaitingDataClientIdle, MeshMachine::TNoTag)
+NODEACTIVITY_END()
+}
+
+namespace CprClientLeaveActivity
+{
+DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityClientLeave, CprClientLeave, TNodeSignal::TNullMessageId, CClientLeaveActivity::NewL)
+	FIRST_NODEACTIVITY_ENTRY(CoreStates::TAwaitingClientLeave, MeshMachine::TNoTag)
+	THROUGH_NODEACTIVITY_ENTRY(KNoTag, CClientLeaveActivity::TRemoveClientAndDestroyOrphanedDataClients, CClientLeaveActivity::TNoTagOrSendPriorityToCtrlProvider)
+	NODEACTIVITY_ENTRY(CprStates::KSendPriorityToCtrlProvider, CClientLeaveActivity::TUpdatePriorityForControlProvider, CoreStates::TAwaitingJoinComplete, CClientLeaveActivity::TNoTagOrSendPriorityToServProvider)
+	NODEACTIVITY_ENTRY(CprStates::KSendPriorityToServProvider, CClientLeaveActivity::TUpdatePriorityForServiceProviders, CoreStates::TAwaitingJoinComplete, MeshMachine::TNoTag)
+	THROUGH_NODEACTIVITY_ENTRY(KNoTag, CClientLeaveActivity::TSendLeaveCompleteAndSendDataClientIdleIfNeeded, MeshMachine::TNoTag)
+	LAST_NODEACTIVITY_ENTRY(KNoTag, CprStates::TSendDataClientStatusStoppedIfNoControlClient)
+NODEACTIVITY_END()
+}
+
+namespace CprDataClientGoneDownActivity
+{
+DECLARE_DEFINE_NODEACTIVITY(ECFActivityDataClientGoneDown, CprDataClientGoneDown, TCFControlProvider::TDataClientGoneDown)
+	// The only thing we do is to clear(unset) the "Flags" of
+	//	the relative DataClient from "EStart": this is done
+	//	in "TAwaitingDataClientGoneDown".
+	FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingDataClientGoneDown, MeshMachine::TNoTag)
+	LAST_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing)
+NODEACTIVITY_END()
+}
+
+namespace CprPolicyCheckRequestActivity
+{
+#ifdef SYMBIAN_NETWORKING_UPS
+DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityPolicyCheckRequest, CPrPolicyCheckRequest, UpsMessage::TPolicyCheckRequest, CNodeParallelActivityBase::NewL)
+	// TODO: decide whether we should move some of these transitions/forks to the UpsCoreProviders
+	FIRST_NODEACTIVITY_ENTRY(UpsStates::TAwaitingPolicyCheckRequest, MeshMachine::TNoTag)
+	LAST_NODEACTIVITY_ENTRY(KNoTag, CprStates::TPostPolicyCheckResponseToOriginators)
+NODEACTIVITY_END()
+#endif
+}
+
+namespace CprActivities
+{
+DEFINE_EXPORT_ACTIVITY_MAP(coreCprActivities)
+	ACTIVITY_MAP_ENTRY(CprControlClientJoinActivity, CprControlClientJoin)
+	ACTIVITY_MAP_ENTRY(CprNoBearerActivity, CprNoBearer)
+	ACTIVITY_MAP_ENTRY(CprBinderRequestActivity, CprBinderRequest)
+	ACTIVITY_MAP_ENTRY(CprBindToActivity, CprBindTo)
+	ACTIVITY_MAP_ENTRY(CprDataClientStartActivity, CprDataClientStart)
+	ACTIVITY_MAP_ENTRY(CprDataClientIdleActivity, CprDataClientIdle)
+    ACTIVITY_MAP_ENTRY(CprClientLeaveActivity, CprClientLeave)
+	ACTIVITY_MAP_ENTRY(CprDataClientGoneDownActivity, CprDataClientGoneDown)
+#ifdef SYMBIAN_NETWORKING_UPS
+	ACTIVITY_MAP_ENTRY(CprPolicyCheckRequestActivity, CPrPolicyCheckRequest)
+#endif
+ACTIVITY_MAP_END_BASE(PRActivities, coreActivitiesCpr)
+}
+
+namespace CprDataClientStartActivity
+{
+EXPORT_C CDataClientStartActivity::CDataClientStartActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode)
+	: MeshMachine::CNodeActivityBase(aActivitySig, aNode), iClientIter(aNode.GetClientIter<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EData)))
+	{}
+}
+
+namespace CprPriorityUpdateActivity
+{
+CPriorityUpdateActivity::CPriorityUpdateActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode, TUint aActivitiesCount)
+:	MeshMachine::CNodeParallelActivityBase(aActivitySig, aNode, aActivitiesCount)
+	{
+	}
+}
+
+namespace CprControlClientJoinActivity
+{
+EXPORT_C MeshMachine::CNodeActivityBase* CControlClientJoinActivity::NewL( const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode )
+	{
+	TUint c = GetNextActivityCountL(aActivitySig,aNode);
+	return new(ELeave)CControlClientJoinActivity(aActivitySig, aNode, c);
+	}
+
+CControlClientJoinActivity::CControlClientJoinActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode, TUint aActivitiesCount)
+:	CprPriorityUpdateActivity::CPriorityUpdateActivity(aActivitySig, aNode, aActivitiesCount)
+	{
+	}
+
+EXPORT_C CControlClientJoinActivity::~CControlClientJoinActivity()
+	{
+	}
+}
+
+namespace CprClientLeaveActivity
+{
+EXPORT_C MeshMachine::CNodeActivityBase* CClientLeaveActivity::NewL(  const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode )
+	{
+	TUint c = GetNextActivityCountL(aActivitySig,aNode);
+	return new(ELeave)CClientLeaveActivity(aActivitySig, aNode, c);
+	}
+
+CClientLeaveActivity::CClientLeaveActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode, TUint aActivitiesCount)
+:	CprPriorityUpdateActivity::CPriorityUpdateActivity(aActivitySig, aNode, aActivitiesCount)
+	{
+	}
+
+EXPORT_C CClientLeaveActivity::~CClientLeaveActivity()
+	{
+	}
+}
+
+namespace CprBindToActivity
+{
+CCprBindToActivity::CCprBindToActivity(const MeshMachine::TNodeActivity& aActivitySig,  MeshMachine::AMMNodeBase& aNode, TInt aNextActivityCount)
+:	CBindToActivity(aActivitySig, aNode, aNextActivityCount)
+	{
+	}
+}
+
+