datacommsserver/esockserver/ssock/ss_subconnstates.cpp
changeset 0 dfb7c4ff071f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/datacommsserver/esockserver/ssock/ss_subconnstates.cpp	Thu Dec 17 09:22:25 2009 +0200
@@ -0,0 +1,877 @@
+// Copyright (c) 2005-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:
+// ss_connstates.cpp
+// 
+//
+
+#include "ss_subconn.h"
+#include "ss_subconnstates.h"
+#include <comms-infras/ss_log.h>
+#include <comms-infras/ss_coreprstates.h>
+#include <comms-infras/ss_corepractivities.h>
+#include <comms-infras/ss_esockactivities.h>
+#include "ss_subconn.h"
+#include "SS_conn.H"
+#include <ss_glob.h>
+
+#include <comms-infras/ss_nodemessages_subconn.h>
+#include <comms-infras/ss_nodemessages_rejoiningprovider.h>
+#include <comms-infras/ss_nodemessages_dataclient.h>
+
+#include <elements/nm_messages_peer.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_ESockSSocksbcnst, "ESockSSocksbcnst");
+#endif
+
+using namespace ESock;
+using namespace SubSessActivities;
+using namespace Messages;
+using namespace MeshMachine;
+
+#ifdef _DEBUG
+_LIT (KCSubConnectionPanic,"CSubConnectionPanic");
+#endif
+
+//-=========================================================
+//
+//
+//States
+//
+//
+//-=========================================================
+
+//-=========================================================
+// Build stack
+//-=========================================================
+DEFINE_SMELEMENT(SubConnStates::TAwaitingBuildStackResponse, NetStateMachine::MState, SubConnStates::TContext)
+TBool SubConnStates::TAwaitingBuildStackResponse::Accept()
+	{
+	return iContext.iMessage.IsMessage<TCFInternalEsock::TBuildStackResponse>();
+	}
+
+DEFINE_SMELEMENT(SubConnStates::TSendBuildStack, NetStateMachine::MStateTransition, SubConnStates::TContext)
+void SubConnStates::TSendBuildStack::DoL()
+	{
+    // The flow request parameters are stored within the subconnection node
+    RCFParameterFamilyBundleC subConnectionParameters = iContext.Node().iParameterBundle;
+
+	// Send build stack to ourself to kick off a stack building activity
+	iContext.iNodeActivity->PostRequestTo( iContext.Node().Id(),
+	    TCFInternalEsock::TBuildStackRequest(subConnectionParameters).CRef());
+	}
+
+DEFINE_SMELEMENT(SubConnActivities::CBuildStack::TAwaitingBuildStack, NetStateMachine::MState, SubConnActivities::CBuildStack::TContext)
+TBool SubConnActivities::CBuildStack::TAwaitingBuildStack::Accept()
+	{
+	return iContext.iMessage.IsMessage<TCFInternalEsock::TBuildStackRequest>();
+	}
+
+DEFINE_SMELEMENT(SubConnActivities::CNoBearer::TStoreFlowParams, NetStateMachine::MStateTransition, SubConnActivities::CNoBearer::TContext)
+void SubConnActivities::CNoBearer::TStoreFlowParams::DoL()
+	{
+	// Store the received flow params in the activity
+	TCFControlProvider::TNoBearer& noBearerMessage = message_cast<TCFControlProvider::TNoBearer>(iContext.iMessage);
+    SubConnActivities::CNoBearer* noBearerActivity = static_cast<SubConnActivities::CNoBearer*>(iContext.iNodeActivity);
+	noBearerActivity->SetFlowRequestParameters(noBearerMessage.iFamilyBundle);
+	}
+
+//-=========================================================
+//Create
+//-=========================================================
+
+DEFINE_SMELEMENT(SubConnStates::TJoinCPR, NetStateMachine::MStateTransition, SubConnStates::TContext)
+void SubConnStates::TJoinCPR::DoL()
+	{
+	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCSubConnectionPanic,KPanicNoActivity));
+    if (iContext.Node().ControlProvider().ServiceProvider() == NULL)
+        {
+        User::Leave(KErrNotReady);
+        }
+
+    iContext.Node().AddClientL(iContext.Node().ControlProvider().ServiceProvider()->RecipientId(), TClientType(TCFClientType::EServProvider));
+    iContext.iNodeActivity->PostRequestTo(*iContext.Node().ControlProvider().ServiceProvider(),
+        TCFServiceProvider::TJoinRequest(iContext.NodeId(), TCFClientType::ECtrl).CRef());
+	}
+
+DEFINE_SMELEMENT(SubConnStates::TRequestServiceProvider, NetStateMachine::MStateTransition, SubConnStates::TContext)
+void SubConnStates::TRequestServiceProvider::DoL()
+	{
+	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCSubConnectionPanic,KPanicNoActivity));
+
+    // The flow request parameters are stored within the activity itself
+    SubConnActivities::CNoBearer* noBearerActivity = static_cast<SubConnActivities::CNoBearer*>(iContext.iNodeActivity);
+    RCFParameterFamilyBundleC flowParams = noBearerActivity->GetFlowRequestParameters();
+
+	// Send our service provider a comms binder carrying the necessary flow request parameters
+    iContext.iNodeActivity->PostRequestTo(
+		*iContext.Node().ServiceProvider(),
+        TCFServiceProvider::TCommsBinderRequest(
+			TSubConnOpen::ECreateNew,
+			flowParams
+			).CRef()
+		);
+	}
+
+DEFINE_SMELEMENT(SubConnStates::TLeaveCPR, NetStateMachine::MStateTransition, SubConnStates::TContext)
+void SubConnStates::TLeaveCPR::DoL()
+	{
+	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCSubConnectionPanic,KPanicNoActivity));
+    __ASSERT_DEBUG(iContext.Node().ControlProvider().ServiceProvider() != NULL, User::Panic(KSpecAssert_ESockSSocksbcnst, 1));
+
+#ifdef _DEBUG
+    TInt count = iContext.Node().CountClients<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EServProvider), TClientType(0, TCFClientType::EActive));
+	// Now the subconn had joined SCPR, and CPR. The relationship between subconn and CPR is temporary and 
+	// should be terminate here in this transition. So in here make sure there's ONLY 1 SP inactive and 
+	// that's supposed to be the CPR, any other cases are wrong
+    __ASSERT_DEBUG(count == 1, User::Panic(KCSubConnectionPanic, KPanicNoServiceProvider));
+#endif
+
+	// Find the SP which is not EActive because EActive is not set on the CPR's flag in the first place
+    RNodeInterface * cpr = iContext.Node().GetFirstClient<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EServProvider), TClientType(0, TCFClientType::EActive));
+    iContext.iNodeActivity->PostRequestTo(*cpr, TEPeer::TLeaveRequest().CRef());
+    cpr->SetFlags(TCFClientType::ELeaving);
+	}
+
+//-=========================================================
+//Rejoin
+//-=========================================================
+
+DEFINE_SMELEMENT(SubConnStates::TJoinTheOtherOwner, NetStateMachine::MStateTransition, SubConnStates::TContext)
+void SubConnStates::TJoinTheOtherOwner::DoL()
+	{
+	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCSubConnectionPanic,KPanicNoActivity));
+    SubConnActivities::CRejoin* rejoinActivity = static_cast<SubConnActivities::CRejoin*>(iContext.iNodeActivity);
+    rejoinActivity->InitialiseL(iContext.Node());
+
+	//MZTODO: activity using this transition - and possibly the whole approach - must be redesigned
+	//so that all destinations are safe! (used to be: TCtrlClientJoinRequestUnsafeDst).
+    rejoinActivity->SetOldOwnerIntf(iContext.Node().AddClientL(rejoinActivity->TheOtherOwner(), TClientType(TCFClientType::EServProvider)));
+	iContext.iNodeActivity->ClearPostedTo();
+
+    RClientInterface::OpenPostMessageClose(iContext.NodeId(), rejoinActivity->TheOtherOwner(),
+    	TCFServiceProvider::TJoinRequest(iContext.NodeId(), TClientType(TCFClientType::ECtrl)).CRef());
+	}
+
+DEFINE_SMELEMENT(SubConnStates::TLeaveTheOtherOwner, NetStateMachine::MStateTransition, SubConnStates::TContext)
+void SubConnStates::TLeaveTheOtherOwner::DoL()
+	{
+	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCSubConnectionPanic,KPanicNoActivity));
+    SubConnActivities::CRejoin* rejoinActivity = static_cast<SubConnActivities::CRejoin*>(iContext.iNodeActivity);
+
+    RClientInterface::OpenPostMessageClose(iContext.NodeId(), rejoinActivity->TheOtherOwner(),
+    	TEPeer::TLeaveRequest().CRef());
+		
+	rejoinActivity->OldOwnerIntf()->SetFlags(ESock::TCFClientType::ELeaving);
+	}
+
+DEFINE_SMELEMENT(SubConnStates::TSendRejoinDataClientRequestToOldOwner, NetStateMachine::MStateTransition, SubConnStates::TContext)
+void SubConnStates::TSendRejoinDataClientRequestToOldOwner::DoL()
+	{
+	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCSubConnectionPanic,KPanicNoActivity));
+    SubConnActivities::CRejoin* rejoinActivity = static_cast<SubConnActivities::CRejoin*>(iContext.iNodeActivity);
+
+    RClientInterface::OpenPostMessageClose(iContext.NodeId(), rejoinActivity->OldOwner(),
+    	TCFRejoiningProvider::TRejoinDataClientRequest(rejoinActivity->Flow(), rejoinActivity->NewOwner()).CRef());
+	}
+
+DEFINE_SMELEMENT(SubConnStates::TSendApplyToOldOwner, NetStateMachine::MStateTransition, SubConnStates::TContext)
+void SubConnStates::TSendApplyToOldOwner::DoL()
+	{
+	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCSubConnectionPanic,KPanicNoActivity));
+    SubConnActivities::CRejoin* rejoinActivity = static_cast<SubConnActivities::CRejoin*>(iContext.iNodeActivity);
+    RClientInterface::OpenPostMessageClose(iContext.NodeId(), rejoinActivity->OldOwner(),
+    	TCFScpr::TApplyRequest().CRef());
+	}
+
+DEFINE_SMELEMENT(SubConnStates::TSendApplyToNewOwner, NetStateMachine::MStateTransition, SubConnStates::TContext)
+void SubConnStates::TSendApplyToNewOwner::DoL()
+	{
+	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCSubConnectionPanic,KPanicNoActivity));
+    SubConnActivities::CRejoin* rejoinActivity = static_cast<SubConnActivities::CRejoin*>(iContext.iNodeActivity);
+    RClientInterface::OpenPostMessageClose(iContext.NodeId(), rejoinActivity->NewOwner(),
+    	TCFScpr::TApplyRequest().CRef());
+	}
+
+DEFINE_SMELEMENT(SubConnStates::TSendCancelToOldOwner, NetStateMachine::MStateTransition, SubConnStates::TContext)
+void SubConnStates::TSendCancelToOldOwner::DoL()
+	{
+	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCSubConnectionPanic,KPanicNoActivity));
+    SubConnActivities::CRejoin* rejoinActivity = static_cast<SubConnActivities::CRejoin*>(iContext.iNodeActivity);
+
+    RClientInterface::OpenPostMessageClose(iContext.NodeId(), rejoinActivity->OldOwner(),
+    	TEBase::TCancel().CRef());
+	}
+
+
+//-=========================================================
+//SetParameters
+//-=========================================================
+DEFINE_SMELEMENT(SubConnStates::TSendParamsToServiceProvider, NetStateMachine::MStateTransition, SubConnStates::TContext)
+void SubConnStates::TSendParamsToServiceProvider::DoL()
+	{
+	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCSubConnectionPanic,KPanicNoActivity));
+	SubConnActivities::CSetParameters& setParamsActivity =
+	    static_cast<SubConnActivities::CSetParameters&>(*iContext.iNodeActivity);
+
+    if (iContext.Node().SubConnType() == RSubConnection::EAttachToDefault)
+      {
+      // SubConnections opened with EAttachToDefault require the NetworkControl capability for changing QoS
+      setParamsActivity.HasCapabilityL (ECapabilityNetworkControl, "CSubConnection::SetParametersL(): EAttachToDefault requires NetworkControl");
+      }
+#ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+	iContext.iNodeActivity->PostRequestTo(*iContext.Node().ServiceProvider(),
+	    TCFScpr::TSetParamsRequest(setParamsActivity.GetParameterBundleL()).CRef());
+#else
+	iContext.iNodeActivity->PostRequestTo(*iContext.Node().ServiceProvider(),
+	    TCFScpr::TParamsRequest(setParamsActivity.GetParameterBundleL()).CRef());
+#endif // SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+	}
+
+DEFINE_SMELEMENT(SubConnStates::TStoreParams, NetStateMachine::MStateTransition, SubConnStates::TContext)
+void SubConnStates::TStoreParams::DoL()
+	{
+#ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+	TCFScpr::TSetParamsResponse& paramResponse = message_cast<TCFScpr::TSetParamsResponse>(iContext.iMessage);
+#else
+	TCFScpr::TParamsResponse& paramResponse = message_cast<TCFScpr::TParamsResponse>(iContext.iMessage);
+#endif // SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+	if(! iContext.Node().iParameterBundle.IsNull())
+    	{
+		iContext.Node().iParameterBundle.Close();
+    	}
+    iContext.Node().iParameterBundle.Open(paramResponse.iFamilyBundle);
+	}
+
+DEFINE_SMELEMENT(SubConnStates::TSendParamRequest, NetStateMachine::MStateTransition, SubConnStates::TContext)
+void SubConnStates::TSendParamRequest::DoL()
+    {
+    __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KSpecAssert_ESockSSocksbcnst, 2));
+    __ASSERT_DEBUG(iContext.Node().ServiceProvider(), User::Panic(KSpecAssert_ESockSSocksbcnst, 3));
+#ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+	iContext.iNodeActivity->PostRequestTo(*iContext.Node().ServiceProvider(),
+  	    TCFScpr::TSetParamsRequest(iContext.Node().iParameterBundle).CRef());
+#else
+	iContext.iNodeActivity->PostRequestTo(*iContext.Node().ServiceProvider(),
+  	    TCFScpr::TParamsRequest(iContext.Node().iParameterBundle).CRef());
+#endif // SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+    }
+
+DEFINE_SMELEMENT(SubConnStates::TNoTagOrParamsPresent, NetStateMachine::MStateFork, SubConnStates::TContext)
+TInt SubConnStates::TNoTagOrParamsPresent::TransitionTag()
+    {
+    return iContext.Node().iParameterBundle.IsNull() ? MeshMachine::KNoTag : PRStates::KParamsPresent;
+    }
+
+DEFINE_SMELEMENT(SubConnStates::TWriteSubConnParamsLength, NetStateMachine::MStateTransition, SubConnStates::TContext)
+void SubConnStates::TWriteSubConnParamsLength::DoL()
+	{
+	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCSubConnectionPanic,KPanicNoActivity));
+	__ASSERT_DEBUG( ! iContext.Node().iParameterBundle.IsNull() , User::Panic(KSpecAssert_ESockSSocksbcnst, 4));
+	CESockClientActivityBase& esockActivity =
+	    static_cast<CESockClientActivityBase&>(*iContext.iNodeActivity);
+
+	//I know!!
+	esockActivity.SetError(iContext.Node().iParameterBundle.IsNull() ? KErrNotReady : (TInt) iContext.Node().iParameterBundle.Length() );
+	}
+
+DEFINE_SMELEMENT(SubConnStates::TWriteSubConnParams, NetStateMachine::MStateTransition, SubConnStates::TContext)
+void SubConnStates::TWriteSubConnParams::DoL()
+	{
+	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCSubConnectionPanic,KPanicNoActivity));
+	__ASSERT_DEBUG(! iContext.Node().iParameterBundle.IsNull() , User::Panic(KSpecAssert_ESockSSocksbcnst, 5));	
+	CESockClientActivityBase& esockActivity =
+	    static_cast<CESockClientActivityBase&>(*iContext.iNodeActivity);
+	RCFParameterFamilyBundleC& pfb = iContext.Node().iParameterBundle;
+	pfb.CheckOpenL();
+
+	RBuf8 buffer;
+	buffer.CreateL(pfb.Length());
+	CleanupClosePushL(buffer);
+	User::LeaveIfError(pfb.Store(buffer));
+	#ifdef ESOCK_LOGGING_ACTIVE
+		if(esockActivity.GetDesMaxLengthL(0) < buffer.Length())
+			{
+			LOG(ESockLog::Printf(_L("ESock: SubConnStates[%x]\tTWriteSubConnParams: client supplied buffer of size %d is too small to store parameter bundle of size %d"), this, esockActivity.GetDesMaxLengthL(0), buffer.Length()));
+			}
+	#endif
+	esockActivity.WriteL(0, buffer);
+	CleanupStack::PopAndDestroy();	// buffer
+	}
+
+//-=========================================================
+//Events
+//-=========================================================
+
+DEFINE_SMELEMENT(SubConnStates::TAwaitingEventNotificationSubscription, NetStateMachine::MState, SubConnStates::TContext)
+TBool SubConnStates::TAwaitingEventNotificationSubscription::Accept()
+	{
+    if (subsessmessage_cast<ESCEventNotificationSetup>(&iContext.iMessage) ||
+        subsessmessage_cast<ESCEventAllNotifications>(&iContext.iMessage))
+        {
+        return ETrue;
+        }
+    return EFalse;
+	}
+
+DEFINE_SMELEMENT(SubConnStates::TNoTagOrAllNotifications, NetStateMachine::MStateFork, SubConnStates::TContext)
+TInt SubConnStates::TNoTagOrAllNotifications::TransitionTag()
+	{
+    if (subsessmessage_cast<ESCEventAllNotifications>(&iContext.iMessage))
+        {
+        return ESCEventAllNotifications;
+        }
+    return MeshMachine::KNoTag;
+	}
+
+DEFINE_SMELEMENT(SubConnStates::TSetupFilteredEventNotification, NetStateMachine::MStateTransition, SubConnStates::TContext)
+void SubConnStates::TSetupFilteredEventNotification::DoL()
+	{
+	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCSubConnectionPanic,KPanicNoActivity));
+	SubConnActivities::CEventNotification& eventNotificationActivity =
+	    static_cast<SubConnActivities::CEventNotification&>(*iContext.iNodeActivity);
+
+    eventNotificationActivity.RequestEventNotificationSetupL();
+	}
+
+DEFINE_SMELEMENT(SubConnStates::TSetupAllEventNotification, NetStateMachine::MStateTransition, SubConnStates::TContext)
+void SubConnStates::TSetupAllEventNotification::DoL()
+	{
+	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCSubConnectionPanic,KPanicNoActivity));
+	SubConnActivities::CEventNotification& eventNotificationActivity =
+	    static_cast<SubConnActivities::CEventNotification&>(*iContext.iNodeActivity);
+
+    eventNotificationActivity.RequestAllEventNotificationsL();
+	}
+
+DEFINE_SMELEMENT(SubConnStates::TFillInEvent, NetStateMachine::MStateTransition, SubConnStates::TContext)
+void SubConnStates::TFillInEvent::DoL()
+	{
+	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCSubConnectionPanic,KPanicNoActivity));
+	SubConnActivities::CEventNotification& eventNotificationActivity =
+	    static_cast<SubConnActivities::CEventNotification&>(*iContext.iNodeActivity);
+
+	if (iContext.iMessage.IsMessage<TCFSubConnControlClient::TSubConnNotification>())
+    	{
+        TEnqueueEvent enqueueEvent(iContext);
+        enqueueEvent.DoL();
+    	}
+
+    CRefCountOwnedSubConNotification* eventRefCountOwner = NULL;
+    TBool eventConsumed = EFalse;
+    while (iContext.Node().iEventQueue.Deque(eventRefCountOwner))
+        {
+        __ASSERT_DEBUG(eventRefCountOwner && eventRefCountOwner->Ptr(), User::Panic(KSpecAssert_ESockSSocksbcnst, 6));
+        eventConsumed = eventNotificationActivity.FillInEvent(*eventRefCountOwner->Ptr());
+        eventRefCountOwner->Close();
+        if (eventConsumed)
+            {
+            break;
+            }
+        }
+	}
+
+DEFINE_SMELEMENT(SubConnStates::TEnqueueEvent, NetStateMachine::MStateTransition, SubConnStates::TContext)
+void SubConnStates::TEnqueueEvent::CreateOrUpdateBundleL(CSubConGenEventParamsGranted* aEvent)
+    {
+	RCFParameterFamilyBundleC& myBundle = iContext.Node().GetOrCreateParameterBundleL();
+
+     RParameterFamily family=myBundle.FindFamily(KSubConQoSFamily);
+	 if ( family.IsNull() )
+        {
+       	RCFParameterFamilyBundle newBundle;
+		newBundle.CreateL();
+		newBundle.Open(myBundle);
+		family = newBundle.CreateFamilyL(KSubConQoSFamily);
+        //family = myBundle.CreateFamilyL(KSubConQoSFamily); //PJLEFT
+        newBundle.Close();
+        }
+
+	 family.ClearAllParameters (RParameterFamily::EGranted);
+
+     CSubConGenericParameterSet* origGeneric = const_cast<CSubConGenericParameterSet*>(aEvent->GetGenericSet());
+     if (origGeneric)
+        {
+        // A copy must be used because parameters owned by the event will be destructed
+        // along with it.
+        CSubConGenericParameterSet* copyGeneric = static_cast<CSubConGenericParameterSet*>(CSubConGenericParameterSet::NewL (origGeneric->GetTypeId()));
+        CleanupStack::PushL (copyGeneric);
+        copyGeneric->Copy (*origGeneric);
+        family.AddParameterSetL (copyGeneric, RParameterFamily::EGranted);
+        CleanupStack::Pop (copyGeneric);
+        }
+
+     TInt max = aEvent->GetNumExtensionSets();
+     for (TInt i=0; i<max; i++)
+        {
+        CSubConExtensionParameterSet* origExtension = const_cast<CSubConExtensionParameterSet*>(aEvent->GetExtensionSet (i));
+        CSubConExtensionParameterSet* copyExtension = static_cast<CSubConExtensionParameterSet*>(CSubConExtensionParameterSet::NewL(origExtension->GetTypeId()));
+        CleanupStack::PushL (copyExtension);
+        copyExtension->Copy (*origExtension);
+        family.AddParameterSetL(copyExtension, RParameterFamily::EGranted);
+        CleanupStack::Pop (copyExtension);
+        }
+    }
+
+
+void SubConnStates::TEnqueueEvent::DoL()
+	{
+	TCFSubConnControlClient::TSubConnNotification& eventMsg = message_cast<TCFSubConnControlClient::TSubConnNotification>(iContext.iMessage);
+	__ASSERT_DEBUG(eventMsg.iRefCountOwnedSubConNotification, User::Panic(KSpecAssert_ESockSSocksbcnst, 7));
+	__ASSERT_DEBUG(eventMsg.iRefCountOwnedSubConNotification->Ptr(), User::Panic(KSpecAssert_ESockSSocksbcnst, 8));
+	iContext.Node().iEventQueue.Enque(eventMsg.iRefCountOwnedSubConNotification);
+    const CSubConNotificationEvent* event = eventMsg.iRefCountOwnedSubConNotification->Ptr();
+	//If param related event - update the params.
+    if (event->GroupId() == KSubConnGenericEventsImplUid
+      && (event->Id() == KSubConGenericEventParamsGranted
+         || event->Id() == KSubConGenericEventParamsChanged))
+        {
+        CreateOrUpdateBundleL(const_cast<CSubConGenEventParamsGranted*>(static_cast<const CSubConGenEventParamsGranted*>(event)));
+        }
+	}
+
+DEFINE_SMELEMENT(SubConnStates::TNoTagOrActiveWhenEventEnqued, NetStateMachine::MStateFork, SubConnStates::TContext)
+TInt SubConnStates::TNoTagOrActiveWhenEventEnqued::TransitionTag()
+	{
+	if (!iContext.Node().iEventQueue.IsEmpty())
+    	{
+    	return KActiveTag;
+    	}
+    return MeshMachine::KNoTag;
+	}
+
+
+//-=========================================================
+//Start/Stop Connection
+//-=========================================================
+DEFINE_SMELEMENT(SubConnStates::TStartSubConnection, NetStateMachine::MStateTransition, SubConnStates::TContext)
+void SubConnStates::TStartSubConnection::DoL()
+	{
+	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCSubConnectionPanic,KPanicNoActivity));
+    if (iContext.Node().ServiceProvider() == NULL)
+        {
+        User::Leave(KErrNotReady);
+        }
+    iContext.iNodeActivity->PostRequestTo(*iContext.Node().ServiceProvider(),
+        TCFServiceProvider::TStart().CRef());
+	}
+
+DEFINE_SMELEMENT(SubConnStates::TStopSubConnection, NetStateMachine::MStateTransition, SubConnStates::TContext)
+void SubConnStates::TStopSubConnection::DoL()
+	{
+	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCSubConnectionPanic,KPanicNoActivity));
+    if (iContext.Node().ServiceProvider() == NULL)
+        {
+        iContext.iNodeActivity->SetIdle();
+        }
+    else
+        {
+        iContext.iNodeActivity->PostRequestTo(*iContext.Node().ServiceProvider(),
+            TCFServiceProvider::TStop(KErrCancel).CRef());
+        }
+	}
+
+//-=========================================================
+//Close
+//-=========================================================
+DEFINE_SMELEMENT(SubConnStates::TDetachControlProvider, NetStateMachine::MStateTransition, SubConnStates::TContext)
+void SubConnStates::TDetachControlProvider::DoL()
+	{
+   	TClientIter<TDefaultClientMatchPolicy> iter = iContext.Node().GetClientIter<TDefaultClientMatchPolicy>(TClientType(TCFClientType::ECtrlProvider));
+	if (iter[0])
+    	{
+#if defined(__GCCXML__)
+    	CConnection& conn = *reinterpret_cast<CConnection*>(&(iter[0]->RecipientId().Node()));
+#else
+    	CConnection& conn = mcfnode_cast<CConnection>(iter[0]->RecipientId().Node());
+#endif
+    	iContext.Node().RemoveClient(conn.Id());
+    	conn.RemoveClient(iContext.NodeId());
+    	}
+	}
+//-=========================================================
+//
+//
+//Activities
+//
+//
+//-=========================================================
+//-=========================================================
+//CNoBearer
+//-=========================================================
+MeshMachine::CNodeActivityBase* SubConnActivities::CNoBearer::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode)
+    {
+    SubConnActivities::CNoBearer* noBearerActivity = new SubConnActivities::CNoBearer(aActivitySig, aNode);
+    if (noBearerActivity == NULL)
+        {
+    	User::Leave(KErrNoMemory);
+        }
+    return noBearerActivity;
+    }
+
+SubConnActivities::CNoBearer::~CNoBearer()
+    {
+    //Destroy the subconnection if the ownership hasn't been released!
+    iFlowRequestBundle.Close();
+	if(Error() != KErrNone)
+		{
+		PostToOriginators(TEBase::TError(KickOffMessageId(), Error()).CRef());
+		}
+    }
+
+void SubConnActivities::CNoBearer::SetFlowRequestParameters(const ESock::RCFParameterFamilyBundleC& aParams)
+    {
+    if(!iFlowRequestBundle.IsNull())
+    	{
+    	iFlowRequestBundle.Close();
+    	}
+    iFlowRequestBundle.Open(aParams);
+    }
+
+//-=========================================================
+//CBuildStack
+//-=========================================================
+MeshMachine::CNodeActivityBase* SubConnActivities::CBuildStack::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode)
+    {
+    SubConnActivities::CBuildStack* createActivity = new SubConnActivities::CBuildStack(aActivitySig, aNode);
+    if (createActivity == NULL)
+        {
+    	User::Leave(KErrNoMemory);
+        }
+    return createActivity;
+    }
+
+SubConnActivities::CBuildStack::CBuildStack(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode)
+	:	MeshMachine::CNodeActivityBase(aActivitySig, aNode),
+		CoreActivities::ABindingActivity(aNode.Id()),
+		TIfStaticFetcherNearestInHierarchy(this)
+		{
+		}
+
+SubConnActivities::CBuildStack::~CBuildStack()
+    {
+    }
+
+DEFINE_SMELEMENT(SubConnActivities::CBuildStack::TSendBuildStackResponse, NetStateMachine::MStateTransition, CBuildStack::TContext)
+void SubConnActivities::CBuildStack::TSendBuildStackResponse::DoL()
+	{
+	iContext.iNodeActivity->PostToOriginators(
+	    TCFInternalEsock::TBuildStackResponse().CRef());
+	}
+
+DEFINE_SMELEMENT(SubConnActivities::CBuildStack::TRequestServiceProviderFromCPR, NetStateMachine::MStateTransition, SubConnStates::TContext)
+void SubConnActivities::CBuildStack::TRequestServiceProviderFromCPR::DoL()
+	{
+	// This transition sends a request for a comms binder to the CPR
+	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCSubConnectionPanic,KPanicNoActivity));
+	SubConnActivities::CBuildStack& buildStackActivity =
+		static_cast<SubConnActivities::CBuildStack&>(*iContext.iNodeActivity);
+
+	// The activity is a friend of the subconn so lets call on it to do the job
+	buildStackActivity.RequestServiceProviderFromCPRL(iContext);
+	}
+
+void SubConnActivities::CBuildStack::RequestServiceProviderFromCPRL(TContext& aContext)
+	{
+    if (aContext.Node().ControlProvider().ServiceProvider() == NULL)
+        {
+        User::Leave(KErrNotReady);
+        }
+
+	// Post the request to our controls provider's service provider (that the top level CPR that manages our connection)
+	aContext.iNodeActivity->PostRequestTo(
+		*aContext.Node().ControlProvider().ServiceProvider(),
+		TCFServiceProvider::TCommsBinderRequest(aContext.Node().iSubConnType,
+			aContext.Node().iParameterBundle
+			).CRef()
+		);
+	}
+
+
+//-=========================================================
+//CCreate
+//-=========================================================
+MeshMachine::CNodeActivityBase* SubConnActivities::CCreate::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode)
+    {
+    SubConnActivities::CCreate* createActivity = new SubConnActivities::CCreate(aActivitySig, aNode);
+    if (createActivity == NULL)
+        {
+#ifndef __GCCXML__
+		RClientInterface::OpenPostMessageClose(aNode.Id(), aNode.Id(), TCFInternalEsock::TSubSess(ESCClose,RMessage2()).CRef());
+#endif
+    	User::Leave(KErrNoMemory);
+        }
+    return createActivity;
+    }
+
+SubConnActivities::CCreate::~CCreate()
+    {
+    //Destroy the subconnection if the ownership hasn't been released!
+    if (Error() != KErrNone)
+    	{
+    	RClientInterface::OpenPostMessageClose(iSubConnectionNode, iSubConnectionNode,
+    		TCFInternalEsock::TSubSess(ESCClose,RMessage2()).CRef());
+    	}
+    }
+
+DEFINE_SMELEMENT(SubConnStates::TNoTagOrWaitForIncoming, NetStateMachine::MStateFork, SubConnStates::TContext)
+TInt SubConnStates::TNoTagOrWaitForIncoming::TransitionTag()
+	{
+	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCSubConnectionPanic,KPanicNoActivity));
+	CESockClientActivityBase& ac = static_cast<CESockClientActivityBase&>(*iContext.iNodeActivity);
+
+	TPckgBuf<TSubConnOpen> argPkg;
+	ac.ReadL(0,argPkg);
+	iContext.Node().iSubConnType = static_cast<RSubConnection::TSubConnType>(argPkg().iType);
+	if (iContext.Node().iSubConnType == RSubConnection::EWaitIncoming)
+    	{
+    	return CoreNetStates::KWaitForIncoming;
+    	}
+	return MeshMachine::KNoTag;
+ 	}
+
+DEFINE_SMELEMENT(SubConnStates::TNoTagOrAttachToDefaultOrWaitForIncoming, NetStateMachine::MStateFork, SubConnStates::TContext)
+TInt SubConnStates::TNoTagOrAttachToDefaultOrWaitForIncoming::TransitionTag()
+	{
+	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCSubConnectionPanic,KPanicNoActivity));
+	CESockClientActivityBase& ac = static_cast<CESockClientActivityBase&>(*iContext.iNodeActivity);
+
+	TPckgBuf<TSubConnOpen> argPkg;
+	ac.ReadL(0,argPkg);
+	iContext.Node().iSubConnType = static_cast<RSubConnection::TSubConnType>(argPkg().iType);
+	if (iContext.Node().iSubConnType == RSubConnection::EWaitIncoming)
+    	{
+    	return CoreNetStates::KWaitForIncoming;
+    	}
+    else if (iContext.Node().iSubConnType == RSubConnection::EAttachToDefault)
+    	{
+    	return CoreNetStates::KAttachToDefault;
+		}
+	return MeshMachine::KNoTag;
+ 	}
+
+//-=========================================================
+//CRejoin
+//-=========================================================
+MeshMachine::CNodeActivityBase* SubConnActivities::CRejoin::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode)
+    {
+    return new (ELeave) SubConnActivities::CRejoin(aActivitySig, aNode);
+    }
+
+SubConnActivities::CRejoin::~CRejoin()
+    {
+    }
+
+void SubConnActivities::CRejoin::InitialiseL(CSubConnection& aSC)
+    {
+    if (!iNewOwner.IsNull())
+        {
+        __ASSERT_DEBUG(!iOldOwner.IsNull() && !iFlow.IsNull(), User::Panic(KSpecAssert_ESockSSocksbcnst, 9));
+        return;
+        }
+
+    if (aSC.ServiceProvider() == NULL)
+        {
+        User::Leave(KErrNotReady);
+        }
+
+    __ASSERT_DEBUG(aSC.Session(), User::Panic(KSpecAssert_ESockSSocksbcnst, 10));
+    if (!aSC.Session()->FlowAndSCPRFromSocketHandle(iMessage.Int0(), iFlow, iOldOwner))
+    	{
+    	User::Leave(KErrNotFound);
+    	}
+
+    if (iMessage.Function() == ESCRemoveSocket)
+        {
+    	RNodeInterface* conn = aSC.ControlProvider().ServiceProvider();
+    	__ASSERT_DEBUG(conn, User::Panic(KSpecAssert_ESockSSocksbcnst, 11));
+    	User::LeaveIfError(conn? KErrNone : KErrArgument);
+
+#if defined(__GCCXML__)
+    	CConnectionProviderBase& p = *reinterpret_cast<CConnectionProviderBase*>(&(conn->RecipientId().Node()));
+#else
+    	CConnectionProviderBase& p = mcfnode_cast<CConnectionProviderBase>(conn->RecipientId().Node());
+#endif
+    	RNodeInterface* primarySc = p.DefaultSubConnectionProvider();
+    	__ASSERT_DEBUG( primarySc , User::Panic(KSpecAssert_ESockSSocksbcnst, 12));
+
+        iNewOwner = primarySc->RecipientId();
+        }
+    else if (iMessage.Function() == ESCAddSocket)
+        {
+        iNewOwner = aSC.ServiceProvider()->RecipientId();
+        }
+    else
+        {
+        __ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockSSocksbcnst, 13));
+        }
+    if (iNewOwner == iOldOwner)
+        {
+        User::Leave(KErrAlreadyExists);
+        }
+    }
+
+//-=========================================================
+//CSetParameters
+//-=========================================================
+MeshMachine::CNodeActivityBase* SubConnActivities::CSetParameters::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode)
+    {
+    return new (ELeave) SubConnActivities::CSetParameters(aActivitySig, aNode);
+    }
+
+SubConnActivities::CSetParameters::~CSetParameters()
+    {
+    if (! iParameterBundle.IsNull())
+        {
+	    iParameterBundle.Close();
+        }
+    }
+
+RCFParameterFamilyBundleC& SubConnActivities::CSetParameters::GetParameterBundleL()
+    {
+    if ( ! iParameterBundle.IsNull() )
+        {
+        return iParameterBundle;
+        }
+    //Extract the parameter bundle.
+	TInt length = iMessage.GetDesLengthL(0);
+	RBuf8 buffer;
+	buffer.CreateL(length);
+	CleanupClosePushL(buffer);
+	iMessage.ReadL(0, buffer);
+
+	iParameterBundle.LoadL(buffer);
+	CleanupStack::PopAndDestroy(&buffer);
+	return iParameterBundle;
+    }
+
+void SubConnActivities::CSetParameters::CompleteMessage()
+    {
+	LOG(ESockLog::Printf(_L("SubConnActivities::CSetParameters::CompleteMessage - (%08X) with %d"), iMessage.Handle(), Error()));
+	
+	__ASSERT_DEBUG(!iMessage.IsNull(), User::Panic(KSpecAssert_ESockSSocksbcnst, 14));
+	iMessage.Complete(Error());
+    }
+
+DEFINE_SMELEMENT(SubConnActivities::CSetParameters::TCompleteClient, NetStateMachine::MStateTransition, TContext)
+void SubConnActivities::CSetParameters::TCompleteClient::DoL()
+	{
+	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCSubConnectionPanic,KPanicNoActivity));
+	SubConnActivities::CSetParameters& setparamActivity = static_cast<SubConnActivities::CSetParameters&>(*iContext.Activity());
+    setparamActivity.CompleteMessage();
+	}
+DEFINE_SMELEMENT(SubConnActivities::CSetParameters::TStoreNewParams, NetStateMachine::MStateTransition, SubConnStates::TContext)
+void SubConnActivities::CSetParameters::TStoreNewParams::DoL()
+	{
+	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCSubConnectionPanic,KPanicNoActivity));
+	SubConnActivities::CSetParameters& setParamsActivity =
+		static_cast<SubConnActivities::CSetParameters&>(*iContext.iNodeActivity);
+
+	// Store the parameters in the subconnection node
+	setParamsActivity.StoreParametersInSubConn(iContext);
+	}
+
+void SubConnActivities::CSetParameters::StoreParametersInSubConn(TContext& aContext)
+	{
+	// Store the parameters in the CSubConnection node
+	if (!aContext.Node().iParameterBundle.IsNull())
+    	{
+		aContext.Node().iParameterBundle.Close();
+    	}
+    aContext.Node().iParameterBundle.Open(GetParameterBundleL());
+    aContext.Node().iParameterBundle.Open();
+	}
+
+//-=========================================================
+//CEventNotification
+//-=========================================================
+MeshMachine::CNodeActivityBase* SubConnActivities::CEventNotification::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode)
+    {
+    return new (ELeave) SubConnActivities::CEventNotification(aActivitySig, aNode);
+    }
+
+SubConnActivities::CEventNotification::~CEventNotification()
+    {
+    }
+
+void SubConnActivities::CEventNotification::RequestEventNotificationSetupL()
+    {
+	if (iMessage.Ptr0())
+		{
+		TPtr8 ptr((TUint8*)iEventUidFilterList, KMaxUidFilterListLen*sizeof(RSubConnection::TEventFilter));
+		TInt ret = iMessage.Read(0, ptr, 0);
+		iEventUidFilterListLength = ptr.Length() / sizeof(RSubConnection::TEventFilter);
+
+		if (ret != KErrNone)
+			{
+			// Null filter list
+			Mem::FillZ ((void*)iEventUidFilterList, KMaxUidFilterListLen*sizeof(RSubConnection::TEventFilter));
+			iEventUidFilterListLength = 0;
+			}
+		}
+	else
+		{
+		// Null filter list
+		Mem::FillZ ((void*)iEventUidFilterList, KMaxUidFilterListLen*sizeof(RSubConnection::TEventFilter));
+		iEventUidFilterListLength = 0;
+		}
+    }
+
+void SubConnActivities::CEventNotification::RequestAllEventNotificationsL()
+    {
+    RSubConnection::TEventFilter & filter = iEventUidFilterList[0];
+    if ( iMessage.Int1() ) //ie request only generic events
+        {
+        filter.iEventGroupUid = KSubConnGenericEventsImplUid;
+        filter.iEventMask = 0xffffffff;
+        iEventUidFilterListLength = 1;
+        }
+    else
+        {
+        iEventUidFilterListLength = 0;
+        }
+    }
+
+
+TBool SubConnActivities::CEventNotification::FillInEvent(const CSubConNotificationEvent& aEvent)
+    {
+	TBool sendEvent(iEventUidFilterListLength == 0);
+	for (TUint i = 0; i < iEventUidFilterListLength; ++i)
+		{
+		if (iEventUidFilterList[i].iEventGroupUid == aEvent.GroupId() &&
+			iEventUidFilterList[i].iEventMask & aEvent.Id())
+			{
+			sendEvent = ETrue;
+			break;
+			}
+		}
+	if (sendEvent)
+		{
+		TBuf8<KMaxSubConnectionEventSize> eventBuffer;
+		TPtr8 ptr((TUint8*)eventBuffer.Ptr(),eventBuffer.MaxLength());
+		if (aEvent.Store(ptr) == KErrNone)
+			{
+			LOG(ESockLog::Printf(_L("ESock: CSubConnection[%x]: Notification Sent.  Event Type %d"), this, aEvent.Id()));
+			eventBuffer.SetLength(ptr.Length());
+			TInt err = iMessage.Write(0, eventBuffer);
+			}
+		}
+	return sendEvent;
+    }
+
+
+