datacommsserver/esockserver/ssock/ss_subconn.cpp
changeset 0 dfb7c4ff071f
child 12 8b5d60ce1e94
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/datacommsserver/esockserver/ssock/ss_subconn.cpp	Thu Dec 17 09:22:25 2009 +0200
@@ -0,0 +1,582 @@
+// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include "ss_subconn.h"
+#include "ss_subconnstates.h"
+#include "ss_connstates.h"
+#include <comms-infras/ss_subconnprov.h>
+#include <comms-infras/ss_log.h>
+#include <comms-infras/ss_roles.h>
+#include <ss_glob.h>
+#include <comms-infras/ss_sapshim.h>
+#include "SS_conn.H"
+#include <comms-infras/ss_nodemessages_subconn.h>
+#include <cs_subconevents.h>
+
+#include <comms-infras/ss_msgintercept.h>
+#include "ss_internal_activities.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_ESockSSocks_sbcn, "ESockSSocks_sbcn");
+#endif
+
+using namespace ESock;
+using namespace SubSessActivities;
+using namespace NetStateMachine;
+using namespace SubConnActivities;
+using namespace SubSessStates;
+using namespace CoreStates;
+using namespace Messages;
+using namespace MeshMachine;
+
+#ifdef _DEBUG
+_LIT (KCSubConnectionPanic,"CSubConnectionPanic");
+#endif
+
+//-=========================================================
+//
+//Actvities serving client (RSubConnection) requests
+//
+//-=========================================================
+// Creates a subconnection subsession object. No longer triggers the building of the stack beneath it.
+// This now occurs only when required
+namespace SubConnectionCreate
+{
+DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivitySubConnectionCreate, SubConCreate, TCFInternalEsock::TSubSess, SubConnActivities::CCreate::NewL)
+	FIRST_NODEACTIVITY_ENTRY(SubSessStates::TAwaitingIPC<ESCCreate>, MeshMachine::TNoTag)
+	THROUGH_NODEACTIVITY_ENTRY(KNoTag, SubSessStates::TAcquireMessageOwnership, SubConnStates::TNoTagOrAttachToDefaultOrWaitForIncoming)
+
+	// We are attaching to the default subconnection and can therefore build the subconnection stack immediately
+	NODEACTIVITY_ENTRY(CoreNetStates::KAttachToDefault, SubConnStates::TSendBuildStack, SubConnStates::TAwaitingBuildStackResponse, MeshMachine::TNoTag)
+
+	// Must be `ECreateNew` in which case we defer the building of the stack. We are done
+	LAST_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing)
+
+	// Wait for incoming
+	LAST_NODEACTIVITY_ENTRY(CoreNetStates::KWaitForIncoming, MeshMachine::TDoNothing)
+NODEACTIVITY_END()
+}
+
+namespace SubConnectionNoBearer
+{
+DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityNoBearer, SubConnNoBearer, TCFControlProvider::TNoBearer, SubConnActivities::CNoBearer::NewL)
+	FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingNoBearer, MeshMachine::TNoTag)
+
+	// We don't have a bearer so get the stack built so that we do. Then we can proceed
+	THROUGH_NODEACTIVITY_ENTRY(KNoTag, SubConnActivities::CNoBearer::TStoreFlowParams, CoreNetStates::TNoTagOrNoBearer)
+	NODEACTIVITY_ENTRY(CoreNetStates::KNoBearer, SubConnStates::TSendBuildStack, SubConnStates::TAwaitingBuildStackResponse, MeshMachine::TNoTag)
+
+	// We now/already have a bearer so go ahead with fetching a bearer for the data client that kicked us off
+	NODEACTIVITY_ENTRY(KNoTag, SubConnStates::TRequestServiceProvider, TAcceptErrorState<CoreNetStates::TAwaitingBinderResponse>, MeshMachine::TNoTagOrErrorTag)
+	LAST_NODEACTIVITY_ENTRY(KErrorTag, MeshMachine::TDoNothing)
+
+	NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendBindTo, CoreNetStates::TAwaitingBindToComplete, MeshMachine::TNoTag)
+	THROUGH_NODEACTIVITY_ENTRY(KNoTag, SubConnActivities::CNoBearer::TSendBindToComplete, MeshMachine::TNoTag)
+	LAST_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing)
+NODEACTIVITY_END()
+}
+
+namespace SubConnectionBuildStack
+{
+DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityBuildStack, SubConnBuildStack, TCFInternalEsock::TBuildStackRequest, SubConnActivities::CBuildStack::NewL)
+	FIRST_NODEACTIVITY_ENTRY(SubConnActivities::CBuildStack::TAwaitingBuildStack, MeshMachine::TNoTag)
+
+	NODEACTIVITY_ENTRY(KNoTag, SubConnStates::TJoinCPR, CoreStates::TAwaitingJoinComplete, MeshMachine::TNoTag)
+
+	NODEACTIVITY_ENTRY(KNoTag, SubConnActivities::CBuildStack::TRequestServiceProviderFromCPR, TAcceptErrorState<CoreNetStates::TAwaitingBinderResponse>, MeshMachine::TNoTagOrErrorTag)
+
+	NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendControlClientJoinRequest, CoreStates::TAwaitingJoinComplete, MeshMachine::TNoTag)
+	THROUGH_NODEACTIVITY_ENTRY(KNoTag, SubConnActivities::CBuildStack::TSendBindToComplete, MeshMachine::TNoTag)
+	NODEACTIVITY_ENTRY(KNoTag, SubConnStates::TLeaveCPR, MeshMachine::TAwaitingLeaveComplete, MeshMachine::TNoTag)
+	LAST_NODEACTIVITY_ENTRY(KNoTag, CBuildStack::TSendBuildStackResponse)
+
+	NODEACTIVITY_ENTRY(KErrorTag, SubConnStates::TLeaveCPR, MeshMachine::TAwaitingLeaveComplete, MeshMachine::TTag<KErrorTag>)
+	LAST_NODEACTIVITY_ENTRY(KErrorTag, MeshMachine::TDoNothing)
+NODEACTIVITY_END()
+}
+
+namespace SubConnectionStart
+{
+DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityStart, SubConStart, TCFInternalEsock::TSubSess, SubSessActivities::CESockClientActivityBase::NewL)
+	FIRST_NODEACTIVITY_ENTRY(SubSessStates::TAwaitingIPC<ESCStart>, MeshMachine::TNoTag)
+	THROUGH_NODEACTIVITY_ENTRY(KNoTag, SubSessStates::TAcquireMessageOwnership, MeshMachine::TNoTag)
+	NODEACTIVITY_ENTRY(KNoTag, SubConnStates::TStartSubConnection, TECABState<CoreNetStates::TAwaitingStarted>, MeshMachine::TNoTag)
+	LAST_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing)
+NODEACTIVITY_END()
+}
+
+namespace SubConnectionStop
+{
+DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityStop, SubConStop, TCFInternalEsock::TSubSess, SubSessActivities::CESockClientActivityBase::NewL)
+	FIRST_NODEACTIVITY_ENTRY(SubSessStates::TAwaitingIPC<ESCStop>, MeshMachine::TNoTag)
+	THROUGH_NODEACTIVITY_ENTRY(KNoTag, SubSessStates::TAcquireMessageOwnership, MeshMachine::TNoTag)
+	NODEACTIVITY_ENTRY(KNoTag, SubConnStates::TStopSubConnection, TECABState<CoreNetStates::TAwaitingStopped>, MeshMachine::TNoTag)
+	LAST_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing)
+NODEACTIVITY_END()
+}
+
+namespace SubConnectionClose
+{
+DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityDestroy, SubConClose, TCFInternalEsock::TSubSess, SubSessActivities::CCloseActivity::New)
+	FIRST_NODEACTIVITY_ENTRY(SubSessStates::TAwaitingIPC<ESCClose>, MeshMachine::TNoTag)
+	THROUGH_NODEACTIVITY_ENTRY(KNoTag, SubSessStates::TAcquireMessageOwnership, MeshMachine::TNoTag)
+	THROUGH_NODEACTIVITY_ENTRY(KNoTag, SubSessStates::TCancelAndCloseClientExtIfaces, MeshMachine::TNoTag)
+    THROUGH_NODEACTIVITY_ENTRY(KNoTag, ConnStates::TCancelAllLegacyRMessage2Activities, ConnStates::TNoTagBlockedByLegacyRMessage2Activities)
+	NODEACTIVITY_ENTRY(KNoTag, SubConnStates::TProcessClose, MeshMachine::TAwaitingLeaveComplete, MeshMachine::TNoTag)
+	NODEACTIVITY_ENTRY(KNoTag, TECABTransition<CoreNetStates::TSetIdleIfNoServiceProviders>, MeshMachine::TAwaitingLeaveComplete, CoreActivities::CDestroyActivity::TNoTagOrNoTagBackwards)
+	LAST_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing)
+NODEACTIVITY_END()
+}
+
+namespace SubConnectionAddSocket
+{
+typedef TECABState<SubConnStates::TAwaitingBuildStackResponse> TAwaitingBuildStackResponse;
+typedef MeshMachine::TAcceptErrorState<CoreNetStates::TAwaitingApplyResponse> TAwaitingApplyResponseOrError;
+
+DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityDataClientJoin, SubConAddSocket, TCFInternalEsock::TSubSess, SubConnActivities::CRejoin::NewL)
+	FIRST_NODEACTIVITY_ENTRY(SubSessStates::TAwaitingIPC<ESCAddSocket>, MeshMachine::TNoTag)
+	THROUGH_NODEACTIVITY_ENTRY(KNoTag, SubSessStates::TAcquireMessageOwnership, CoreNetStates::TNoTagOrNoBearer)
+
+	// We have no bearer yet so must have the stack built beneath us before continuing
+	NODEACTIVITY_ENTRY(CoreNetStates::KNoBearer, SubConnStates::TSendBuildStack, TECABState<SubConnStates::TAwaitingBuildStackResponse>, MeshMachine::TNoTag)
+
+	// We have a bearer and can now go ahead adding a socket from the default sub connection
+	NODEACTIVITY_ENTRY(KNoTag, SubConnStates::TJoinTheOtherOwner, TECABState<CoreStates::TAwaitingJoinComplete>, MeshMachine::TNoTag)
+	NODEACTIVITY_ENTRY(KNoTag, SubConnStates::TSendRejoinDataClientRequestToOldOwner, TAcceptErrorState<CoreNetStates::TAwaitingRejoinDataClientComplete>, MeshMachine::TNoTagOrErrorTag)
+	NODEACTIVITY_ENTRY(KErrorTag, SubConnStates::TLeaveTheOtherOwner, MeshMachine::TAwaitingLeaveComplete, MeshMachine::TTag<KErrorTag>)
+	LAST_NODEACTIVITY_ENTRY(KErrorTag, MeshMachine::TDoNothing)
+
+	//When adding socket, add first, remove later.
+	NODEACTIVITY_ENTRY(KNoTag, SubConnStates::TSendApplyToNewOwner, TAwaitingApplyResponseOrError, MeshMachine::TNoTagOrErrorTag)
+	NODEACTIVITY_ENTRY(KNoTag, SubConnStates::TSendApplyToOldOwner, TAwaitingApplyResponseOrError, MeshMachine::TNoTagOrErrorTag)
+
+	NODEACTIVITY_ENTRY(KErrorTag, SubConnStates::TSendCancelToOldOwner, TAcceptErrorState<CoreStates::TNeverAccept>, MeshMachine::TNoTag)
+	NODEACTIVITY_ENTRY(KNoTag,    SubConnStates::TLeaveTheOtherOwner, MeshMachine::TAwaitingLeaveComplete, MeshMachine::TNoTag)
+	LAST_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing)
+NODEACTIVITY_END()
+}
+
+namespace SubConnectionRemoveSocket
+{
+DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityClientLeave, SubConRemoveSocket, TCFInternalEsock::TSubSess, SubConnActivities::CRejoin::NewL)
+	FIRST_NODEACTIVITY_ENTRY(SubSessStates::TAwaitingIPC<ESCRemoveSocket>, MeshMachine::TNoTag)
+	THROUGH_NODEACTIVITY_ENTRY(KNoTag, SubSessStates::TAcquireMessageOwnership, MeshMachine::TNoTag)
+	NODEACTIVITY_ENTRY(KNoTag, SubConnStates::TJoinTheOtherOwner, TECABState<CoreStates::TAwaitingJoinComplete>, MeshMachine::TNoTag)
+	NODEACTIVITY_ENTRY(KNoTag, SubConnStates::TSendRejoinDataClientRequestToOldOwner, TAcceptErrorState<CoreNetStates::TAwaitingRejoinDataClientComplete>, MeshMachine::TNoTagOrErrorTag)
+	//When removing socket, remove first, add later.
+	NODEACTIVITY_ENTRY(KNoTag, SubConnStates::TSendApplyToOldOwner, MeshMachine::TAcceptErrorState<CoreNetStates::TAwaitingApplyResponse>, MeshMachine::TNoTagOrErrorTag)
+	NODEACTIVITY_ENTRY(KNoTag, SubConnStates::TSendApplyToNewOwner, MeshMachine::TAcceptErrorState<CoreNetStates::TAwaitingApplyResponse>, MeshMachine::TNoTagOrErrorTag)
+
+	NODEACTIVITY_ENTRY(KNoTag,    SubConnStates::TLeaveTheOtherOwner, MeshMachine::TAwaitingLeaveComplete, MeshMachine::TNoTag)
+	NODEACTIVITY_ENTRY(KErrorTag, SubConnStates::TLeaveTheOtherOwner, MeshMachine::TAwaitingLeaveComplete, MeshMachine::TNoTag)
+	LAST_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing)
+NODEACTIVITY_END()
+}
+
+namespace SubConnectionSetParams
+{
+DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityParamRequest, SubConSetParams, TCFInternalEsock::TSubSess, SubConnActivities::CSetParameters::NewL)
+	FIRST_NODEACTIVITY_ENTRY(SubSessStates::TAwaitingIPC<ESCSetParameters>, MeshMachine::TNoTag)
+	THROUGH_NODEACTIVITY_ENTRY(KNoTag, SubSessStates::TAcquireMessageOwnership, MeshMachine::TNoTag)
+	THROUGH_NODEACTIVITY_ENTRY(KNoTag, SubConnActivities::CSetParameters::TStoreNewParams, CoreNetStates::TNoTagOrNoBearer)
+
+	// We have no bearer so are going to have to tell ourself to build the stack beneath us
+	NODEACTIVITY_ENTRY(CoreNetStates::KNoBearer, SubConnStates::TSendBuildStack, SubConnStates::TAwaitingBuildStackResponse, MeshMachine::TNoTag)
+
+	// Proceed with sending the parameters to our service provider
+	NODEACTIVITY_ENTRY(KNoTag, SubConnStates::TSendParamsToServiceProvider, TECABState<CoreNetStates::TAwaitingParamResponse>, MeshMachine::TNoTag)
+
+	//it's the legacy behaviour to complete setparams once they have been verified (TParamsResponse received)
+	//but not yet processed.
+	THROUGH_NODEACTIVITY_ENTRY(KNoTag, SubConnActivities::CSetParameters::TCompleteClient, MeshMachine::TNoTag)
+
+	// the params received in response should be stored before send apply
+	NODEACTIVITY_ENTRY(KNoTag, SubConnStates::TStoreParamsAndSendApply, TECABState<MeshMachine::TAcceptErrorState<CoreNetStates::TAwaitingApplyResponse> >, MeshMachine::TNoTag)
+	LAST_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing)
+NODEACTIVITY_END()
+}
+
+namespace SubConnectionEventNotificationSubscription
+{
+DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityNotification, SubConEventSubscr, TCFInternalEsock::TSubSess, SubConnActivities::CEventNotification::NewL)
+	FIRST_NODEACTIVITY_ENTRY(SubConnStates::TAwaitingEventNotificationSubscription, SubConnStates::TNoTagOrAllNotifications)
+	NODEACTIVITY_ENTRY        (KNoTag,                   SubConnStates::TSetupFilteredEventNotification, SubSessStates::TAwaitingIPC<ESCEventNotification>, MeshMachine::TNoTag)
+    THROUGH_NODEACTIVITY_ENTRY(ESCEventAllNotifications, SubConnStates::TSetupAllEventNotification, MeshMachine::TNoTag )
+	THROUGH_NODEACTIVITY_ENTRY(KNoTag, SubSessStates::TAcquireMessageOwnership, SubConnStates::TNoTagOrActiveWhenEventEnqued)
+
+	NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing, CoreNetStates::TAwaitingSubConEvent, TTag<KActiveTag>)
+	LAST_NODEACTIVITY_ENTRY(KActiveTag, SubConnStates::TFillInEvent)
+NODEACTIVITY_END()
+}
+
+namespace SubConnectionEventNotification
+{
+DECLARE_DEFINE_NODEACTIVITY(ECFActivityConnectionWaitForIncoming, SubConEvent, TCFSubConnControlClient::TSubConnNotification)
+	NODEACTIVITY_ENTRY(KNoTag, SubConnStates::TEnqueueEvent, CoreNetStates::TAwaitingSubConEvent, MeshMachine::TNoTag)
+NODEACTIVITY_END()
+}
+
+namespace SubConnectionGetParamLength
+{
+DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityGetParamLength, SubConGetParamLength, TCFInternalEsock::TSubSess, CESockClientActivityBase::NewL)
+	FIRST_NODEACTIVITY_ENTRY(SubSessStates::TAwaitingIPC<ESCGetParametersLength>, MeshMachine::TNoTag)
+	// We must block if SubConnectionSetParams activity is currently running (the activity continues to run after it has completed its client)
+	// as otherwise the stored parameters can be changed underneath us.  In particular, this can occur in-between
+	// SubConnectionGetParamLength and SubConnectionGetParam, with the resulting length mismatch causing a KERN-EXEC-3 in the original
+	// client RSubConnection::GetParameters() call.
+	THROUGH_NODEACTIVITY_ENTRY(KNoTag, SubSessStates::TAcquireMessageOwnership, SubConnStates::TNoTagOrParamsPresentBlockedBySetParams )
+	NODEACTIVITY_ENTRY(KNoTag, SubConnStates::TSendParamRequest, CoreNetStates::TAwaitingParamResponse, MeshMachine::TNoTag)
+	THROUGH_NODEACTIVITY_ENTRY(KNoTag, SubConnStates::TStoreParams, MeshMachine::TNoTag)
+	LAST_NODEACTIVITY_ENTRY(KNoTag, SubConnStates::TWriteSubConnParamsLength)
+	LAST_NODEACTIVITY_ENTRY(PRStates::KParamsPresent, SubConnStates::TWriteSubConnParamsLength)
+NODEACTIVITY_END()
+}
+
+namespace SubConnectionGetParam
+{
+DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityGetParam, SubConGetParams, TCFInternalEsock::TSubSess, CESockClientActivityBase::NewL)
+	FIRST_NODEACTIVITY_ENTRY(SubSessStates::TAwaitingIPC<ESCGetParameters>, MeshMachine::TNoTag)
+	THROUGH_NODEACTIVITY_ENTRY(KNoTag, SubSessStates::TAcquireMessageOwnership, SubConnStates::TNoTagOrParamsPresent )
+	NODEACTIVITY_ENTRY(KNoTag, SubConnStates::TSendParamRequest, CoreNetStates::TAwaitingParamResponse, MeshMachine::TNoTag)
+	THROUGH_NODEACTIVITY_ENTRY(KNoTag, SubConnStates::TStoreParams, MeshMachine::TNoTag)
+	LAST_NODEACTIVITY_ENTRY(KNoTag, SubConnStates::TWriteSubConnParams)
+	LAST_NODEACTIVITY_ENTRY(PRStates::KParamsPresent, SubConnStates::TWriteSubConnParams)
+NODEACTIVITY_END()
+}
+
+//
+//Activities serving framework requests
+namespace SubConnectionWaitForIncomming
+{
+DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityBindTo, SubConnBindToRequest, TCFDataClient::TBindTo, PRActivities::CBindToActivity::NewL)
+	FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingBindTo, MeshMachine::TNoTag)
+	NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendControlClientJoinRequest, CoreStates::TAwaitingJoinComplete, MeshMachine::TNoTagOrErrorTag)
+	LAST_NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendBindToComplete)
+NODEACTIVITY_END()
+}
+
+namespace SubConnectionLegacyRMessage2Activity
+{
+DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivitySubConnectionLegacyRMessage2Handler, SubConnectionLegacyRMessage2, TNodeSignal::TNullMessageId, ConnActivities::CConnLegacyRMessage2Activity::NewL)
+    FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingLegacyRMessage2Ext, MeshMachine::TNoTag)
+    NODEACTIVITY_ENTRY(KNoTag, ConnStates::TProcessLegacyRMessage2, TAcceptErrorState<CoreNetStates::TAwaitingRMessage2Processed>, MeshMachine::TNoTagOrErrorTag)
+    LAST_NODEACTIVITY_ENTRY(KNoTag, ConnStates::TCompleteRMessage2)
+    LAST_NODEACTIVITY_ENTRY(KErrorTag, MeshMachine::TDoNothing)
+NODEACTIVITY_END()
+}
+
+
+namespace SubConnectionActivities
+{
+DECLARE_DEFINE_ACTIVITY_MAP(subconnectionActivities)
+	ACTIVITY_MAP_ENTRY(CoreErrorActivity, CoreError) //Must be first in the table
+	ACTIVITY_MAP_ENTRY(SubConnectionStart, SubConStart)
+	ACTIVITY_MAP_ENTRY(SubConnectionStop, SubConStop)
+	ACTIVITY_MAP_ENTRY(SubConnectionCreate, SubConCreate)
+	ACTIVITY_MAP_ENTRY(SubConnectionClose, SubConClose)
+	ACTIVITY_MAP_ENTRY(SubConnectionAddSocket, SubConAddSocket)
+	ACTIVITY_MAP_ENTRY(SubConnectionRemoveSocket, SubConRemoveSocket)
+	ACTIVITY_MAP_ENTRY(SubConnectionSetParams, SubConSetParams)
+	ACTIVITY_MAP_ENTRY(SubConnectionEventNotificationSubscription, SubConEventSubscr)
+	ACTIVITY_MAP_ENTRY(SubConnectionEventNotification, SubConEvent)
+	ACTIVITY_MAP_ENTRY(SubConnectionGetParamLength, SubConGetParamLength)
+	ACTIVITY_MAP_ENTRY(SubConnectionGetParam, SubConGetParams)
+	ACTIVITY_MAP_ENTRY(SubConnectionWaitForIncomming, SubConnBindToRequest)
+	ACTIVITY_MAP_ENTRY(SubConnectionBuildStack, SubConnBuildStack)
+	ACTIVITY_MAP_ENTRY(SubConnectionNoBearer, SubConnNoBearer)
+    ACTIVITY_MAP_ENTRY(SubConnectionLegacyRMessage2Activity, SubConnectionLegacyRMessage2)
+	ACTIVITY_MAP_ENTRY(PRDataClientJoinActivity, PRDataClientJoin)
+	ACTIVITY_MAP_ENTRY(PRClientLeaveActivity, PRClientLeave)
+ACTIVITY_MAP_END()
+}
+
+
+
+
+
+
+
+//-=========================================================
+//
+//
+//CSubConnection implementation
+//
+//
+//-=========================================================
+CSubConnection* CSubConnection::NewL(CConnection& aConnection, CPlayer* aPlayer, const TSubSessionUniqueId aSubSessionUniqueId)
+/** Create a new CSubConnection instance
+
+@param aConnProvider Connection Provider that this subconnection is a member of
+@param aType Default or new subconnection
+@param aSession Socket Session this subsession is to be a member of
+@return pointer to new CSubConnection instance on success
+@exception leaves if could not allocate memory
+*/
+	{
+	RNodeInterface* conn = aConnection.ServiceProvider();
+	__ASSERT_DEBUG(conn, User::Panic(KSpecAssert_ESockSSocks_sbcn, 1));
+	User::LeaveIfError(conn? KErrNone : KErrNotReady);
+
+	CSubConnection* sc = new (ELeave) CSubConnection(aPlayer, aSubSessionUniqueId);
+    CleanupStack::PushL(sc);
+	sc->ConstructL(aConnection);
+	CleanupStack::Pop(sc);
+
+	ESOCK_DEBUG_REGISTER_GENERAL_NODE(ESockDebug::KSubConnectionNodeUid, sc);
+
+	return sc;
+	}
+
+
+void CSubConnection::ProcessMessageL()
+	{
+	LOG_DETAILED(ESockLog::Printf(_L("CSubConnection(%08x)::ProcessMessageL:\tCommand %d"), this, Message().Function()));
+
+	switch (Message().Function())
+     {
+		case ESCAddSocket:
+			LOG( ESockLog::Printf(KESockSubConnectionTag, _L8("CSubConnection %08x\tESCAddSocket aMessage %08x"), this, &Message()) );
+			//If successful, the ownership of the RMessage2 is taken by the activity, otherwise completed on leave
+			CMMSockSubSession::ReceivedL(ESCAddSocket, TCFInternalEsock::TSubSess(ESCAddSocket,Message()).CRef());
+			break;
+
+		case ESCRemoveSocket:
+			LOG( ESockLog::Printf(KESockSubConnectionTag, _L8("CSubConnection %08x\tESCRemoveSocket aMessage %08x"), this, &Message()) );
+			//If successful, the ownership of the RMessage2 is taken by the activity, otherwise completed on leave
+			CMMSockSubSession::ReceivedL(ESCRemoveSocket, TCFInternalEsock::TSubSess(ESCRemoveSocket,Message()).CRef());
+			break;
+
+		case ESCSetParameters:
+			LOG( ESockLog::Printf(KESockSubConnectionTag, _L8("CSubConnection %08x\tESCSetParameters aMessage %08x"), this, &Message()) );
+			//If successful, the ownership of the RMessage2 is taken by the activity, otherwise completed on leave
+			CMMSockSubSession::ReceivedL(ESCSetParameters, TCFInternalEsock::TSubSess(ESCSetParameters,Message()).CRef());
+			break;
+
+		case ESCGetParameters:
+			LOG( ESockLog::Printf(KESockSubConnectionTag, _L8("CSubConnection %08x\tESCGetParameters aMessage %08x"), this, &Message()) );
+			//If successful, the ownership of the RMessage2 is taken by the activity, otherwise completed on leave
+			CMMSockSubSession::ReceivedL(ESCGetParameters, TCFInternalEsock::TSubSess(ESCGetParameters,Message()).CRef());
+			break;
+
+		case ESCGetParametersLength:
+			LOG( ESockLog::Printf(KESockSubConnectionTag, _L8("CSubConnection %08x\tESCGetParametersLength aMessage %08x"), this, &Message()) );
+			//If successful, the ownership of the RMessage2 is taken by the activity, otherwise completed on leave
+			CMMSockSubSession::ReceivedL(ESCGetParametersLength, TCFInternalEsock::TSubSess(ESCGetParametersLength,Message()).CRef());
+			break;
+
+        case ESCEventNotificationSetup:
+			LOG( ESockLog::Printf(KESockSubConnectionTag, _L8("CSubConnection %08x\tESCEventNotificationSetup aMessage %08x"), this, &Message()) );
+			CMMSockSubSession::ReceivedL(ESCEventNotification, TCFInternalEsock::TSubSess(ESCEventNotificationSetup,Message()).CRef());
+			break;
+
+        case ESCEventNotification:
+			LOG( ESockLog::Printf(KESockSubConnectionTag, _L8("CSubConnection %08x\tESCEventNotification aMessage %08x"), this, &Message()) );
+			CMMSockSubSession::ReceivedL(ECFActivityNotification, TCFInternalEsock::TSubSess(ESCEventNotification,Message()).CRef());
+			break;
+
+        case ESCEventAllNotifications:
+			LOG( ESockLog::Printf(KESockSubConnectionTag, _L8("CSubConnection %08x\tESCEventAllNotifications aMessage %08x"), this, &Message()) );
+			CMMSockSubSession::ReceivedL(ESCEventNotification, TCFInternalEsock::TSubSess(ESCEventAllNotifications,Message()).CRef());
+			break;
+
+        case ESCEventNotificationCancel:
+			LOG( ESockLog::Printf(KESockSubConnectionTag, _L8("CSubConnection %08x\tESCEventNotificationCancel aMessage %08x"), this, &Message()) );
+			//CANCELATION - Do not call DontCompleteCurrentRequest() for ECFActivityNotification to be completed!
+			CMMSockSubSession::ReceivedL(ESCEventNotification, TEBase::TCancel().CRef());
+			break;
+
+		case ESCControl:
+			{
+			LOG( ESockLog::Printf(KESockSubConnectionTag, _L8("CSubConnection %08x\tESCControl aMessage %08x"), this, &Message()) );
+			if (ServiceProvider() == NULL)
+    			{
+    			User::Leave(KErrNotReady);
+    			}
+			TLegacyControlMessage msg(SafeMessage());
+			CMMSockSubSession::ReceivedL(SafeMessage().Function(), msg);
+			DontCompleteCurrentRequest(); //TLegacyControlMessage will complete the message
+			}
+			break;
+
+		case ESCStart:
+			LOG( ESockLog::Printf(KESockSubConnectionTag, _L8("CSubConnection %08x\tESCStart aMessage %08x"), this, &Message()) );
+			//If successful, the ownership of the RMessage2 is taken by the activity, otherwise completed on leave
+			CMMSockSubSession::ReceivedL(ESCStart, TCFInternalEsock::TSubSess(ESCStart,Message()).CRef());
+			break;
+
+		case ESCStop:
+			LOG( ESockLog::Printf(KESockSubConnectionTag, _L8("CSubConnection %08x\tESCStop aMessage %08x"), this, &Message()) );
+			//If successful, the ownership of the RMessage2 is taken by the activity, otherwise completed on leave
+			CMMSockSubSession::ReceivedL(ESCStop, TCFInternalEsock::TSubSess(ESCStop,Message()).CRef());
+			break;
+
+		case ESCClose:
+			LOG( ESockLog::Printf(KESockSubConnectionTag, _L8("CSubConnection %08x\tESCClose aMessage %08x"), this, &Message()) );
+			SetClosing();
+			//If successful, the ownership of the RMessage2 is taken by the activity, otherwise completed on leave
+			CMMSockSubSession::ReceivedL(ESCClose, TCFInternalEsock::TSubSess(ESCClose,Message()).CRef());
+			break;
+
+		default:
+			SetReturn(KErrNotSupported);
+		}
+	}
+
+/**
+Constructor - set up name
+*/
+CSubConnection::CSubConnection(CPlayer* aPlayer, const TSubSessionUniqueId aSubSessionUniqueId)
+	: CMMSockSubSession(SubConnectionActivities::subconnectionActivities::Self(), aPlayer->CurrentSession(), aPlayer, aSubSessionUniqueId),
+	ASubSessionPlatsecApiExt(UniqueId()),
+	TIfStaticFetcherNearestInHierarchy(this)
+	{
+	LOG_NODE_CREATE(KESockComponentTag, CSubConnection);
+	}
+
+class TRevertAddClient
+    {
+    public:
+    TRevertAddClient(MeshMachine::AMMNodeBase& aOwner, const TNodeId& aClient)
+    :iOwner(aOwner),
+     iClient(aClient)
+     {}
+
+    static void Do(TAny* aRevertAddClient)
+        {
+        TRevertAddClient& This = *reinterpret_cast<TRevertAddClient*>(aRevertAddClient);
+        This.Do();
+        }
+
+    void Do()
+        {
+        iOwner.RemoveClient(iClient);
+        }
+
+    private:
+    MeshMachine::AMMNodeBase&       iOwner;
+    const TNodeId&    iClient;
+    };
+
+void CSubConnection::ConstructL(CConnection& aConnection)
+	{
+	CMMSockSubSession::ConstructL();
+	AddClientL(aConnection.Id(), TClientType(TCFClientType::ECtrlProvider));
+	TRevertAddClient cleanupRevert(*this, aConnection.Id());
+	CleanupStack::PushL(TCleanupItem(TRevertAddClient::Do, &cleanupRevert));
+	aConnection.AddClientL(Id(), TClientType(TCFClientType::EData));
+	CleanupStack::Pop();
+	}
+
+/**
+Destructor, clean up connection preferences and the subconnection provider
+*/
+CSubConnection::~CSubConnection()
+	{
+	if (!iParameterBundle.IsNull())
+		{
+		iParameterBundle.Close();
+		}
+
+	if (CMMSockSubSession::ControlProvider())
+    	{
+        ControlProvider().RemoveClient(Id());
+    	RemoveClient(ControlProvider().Id());
+    	}
+
+    CRefCountOwnedSubConNotification* event = NULL;
+    while (iEventQueue.Deque(event))
+        {
+        __ASSERT_DEBUG(event, User::Panic(KSpecAssert_ESockSSocks_sbcn, 2));
+        event->Close();
+        event = NULL;
+        }
+
+    LOG_NODE_DESTROY(KESockComponentTag, CSubConnection);
+	}
+
+void CSubConnection::Received(TNodeContextBase& aContext)
+    {
+    TNodeSignal::TMessageId noPeerIds[] = {
+    	TCFInternalEsock::TSubSess::Id(),
+    	TCFPeer::TJoinRequest::Id(),
+    	TEPeer::TLeaveRequest::Id(),
+    	TNodeSignal::TMessageId()
+    	};
+    MeshMachine::AMMNodeBase::Received(noPeerIds, aContext);
+	MeshMachine::AMMNodeBase::PostReceived(aContext);
+	}
+
+void CSubConnection::ReceivedL(const TRuntimeCtxId& aSender, const TNodeId& aRecipient, TSignatureBase& aMessage)
+    {
+	ESOCK_DEBUG_MESSAGE_INTERCEPT(aSender, aMessage, aRecipient);
+
+	//First check if this is not our own error
+	if (aMessage.IsMessage<TEBase::TError>()
+		&& aSender == Id())
+		{
+		//This is our own error, generated from the client (IPC) activity
+		//It is safe to just ignore it here, as the activity is
+		//completed (and so is the client RMessage2). If the activity didn't have
+		//the chance to acquire ownership of the message it is still safe to ignore it
+		//because there was no call to DoNotCompleteCurrentMessage().
+		//return KErrNone;
+		}
+
+	TNodeContext<CSubConnection> ctx(*this, aMessage, aSender, aRecipient);
+    CSubConnection::Received(ctx);
+    User::LeaveIfError(ctx.iReturn);
+	}
+
+void CSubConnection::FinalCompleteAllBlockedMessages(TInt /*aResult*/)
+	{
+	TNodeNullContext ctx(*this);
+	AbortActivitiesOriginatedBy(ctx); //Abort all activities
+	}
+
+CConnection& CSubConnection::ControlProvider()
+    {
+    RNodeInterface* controlProv = CMMSockSubSession::ControlProvider();
+	__ASSERT_DEBUG(controlProv, User::Panic(KCSubConnectionPanic,KPanicNoConnection));
+#if defined(__GCCXML__)
+    return *reinterpret_cast<CConnection*>(&(controlProv->RecipientId().Node()));
+#else
+    return mcfnode_cast<CConnection>(controlProv->RecipientId().Node());
+#endif
+    }
+
+EXPORT_C RCFParameterFamilyBundleC& CSubConnection::GetOrCreateParameterBundleL()
+	{
+	if( ! iParameterBundle.IsNull())
+		{
+		return iParameterBundle;
+		}
+	return CreateParameterBundleL();
+	}
+
+EXPORT_C RCFParameterFamilyBundleC& CSubConnection::CreateParameterBundleL()
+	{
+	__ASSERT_DEBUG(iParameterBundle.IsNull(), User::Panic(KSpecAssert_ESockSSocks_sbcn, 3));
+
+	RCFParameterFamilyBundle newBundle;
+	newBundle.CreateL();
+	iParameterBundle.Open(newBundle);
+
+	return iParameterBundle;
+	}
+
+