networkcontrol/iptransportlayer/src/ipdeftbasescpr.cpp
changeset 0 af10295192d8
child 19 3652a10b304a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/networkcontrol/iptransportlayer/src/ipdeftbasescpr.cpp	Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,397 @@
+// 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:
+// IP Default Base SubConnection Provider implementation
+// 
+//
+
+/**
+ @file
+ @internalComponent
+*/
+
+#define SYMBIAN_NETWORKING_UPS
+
+#include "IPMessages.h"
+
+#include <comms-infras/corescpractivities.h>
+#include <comms-infras/ss_corepractivities.h>
+#include <comms-infras/ss_nodemessages_rejoiningprovider.h>
+#include <comms-infras/ss_nodemessages_dataclient.h>
+#include "ipdeftbasescpr.h"
+#include <comms-infras/ss_log.h>
+#include <comms-infras/ss_platsec_apiext.h>
+#include <networking/qos3gpp_subconparams.h>
+
+#include <comms-infras/ss_msgintercept.h>
+#ifdef SYMBIAN_NETWORKING_UPS
+#include <comms-infras/upspractivities.h>
+#endif
+
+#ifdef SYMBIAN_TRACE_ENABLE
+	#define KIPDeftSCprTag KESockSubConnectionTag
+#endif // SYMBIAN_TRACE_ENABLE
+
+
+using namespace Messages;
+using namespace MeshMachine;
+using namespace ESock;
+using namespace IPDeftSCprBaseActivities;
+using namespace PRActivities;
+using namespace CoreNetStates;
+
+//We reserve space for two preallocated activities that may start concurrently on the default base SCPR
+//node: destroy and data client stop.
+static const TUint KDefaultMaxPreallocatedActivityCount = 2;
+static const TUint KMaxPreallocatedActivitySize = sizeof(MeshMachine::CNodeRetryParallelActivity) + sizeof(MeshMachine::APreallocatedOriginators<4>);
+static const TUint KIPDeftBaseSCPRPreallocatedActivityBufferSize = KDefaultMaxPreallocatedActivityCount * KMaxPreallocatedActivitySize;
+
+//-=========================================================
+//
+// States
+//
+//-=========================================================
+namespace IPBaseSCprStates
+{
+DEFINE_SMELEMENT(TAwaitingAddressUpdate, NetStateMachine::MState, IPBaseSCprStates::TContext)
+TBool TAwaitingAddressUpdate::Accept()
+	{
+	return iContext.iMessage.IsMessage<TCFIPMessage::TDataClientRouted>();
+	}
+
+DEFINE_SMELEMENT(TStoreAddressUpdate, NetStateMachine::MStateTransition, IPBaseSCprStates::TContext)
+void TStoreAddressUpdate::DoL()
+	{
+    RIPDataClientNodeInterface* client = static_cast<RIPDataClientNodeInterface*>(iContext.iPeer);
+    if (NULL == client)
+        {
+        User::Leave(KErrNotFound);
+        }
+
+    TCFIPMessage::TDataClientRouted& addressUpdateMsg = message_cast<TCFIPMessage::TDataClientRouted>(iContext.iMessage);
+    client->iCliDstAddr = addressUpdateMsg.iAddrUpdate.iDestSockAddr;
+    client->iCliSrcAddr = addressUpdateMsg.iAddrUpdate.iSrcSockAddr;
+    client->iProtocolId = addressUpdateMsg.iAddrUpdate.iProtocolId;
+    if (iContext.Node().iIapId == CIpSubConnectionProviderBase::KInvalidIapId)
+        {
+        iContext.Node().iIapId = addressUpdateMsg.iAddrUpdate.iIapId;
+        }
+	}
+
+DEFINE_SMELEMENT(TRejoinDataClient, NetStateMachine::MStateTransition, IPBaseSCprStates::TContext)
+void TRejoinDataClient::DoL()
+	{
+    PRActivities::CRejoinDataClientActivity::TRejoinDataClient sendRejoinReq(iContext);
+    sendRejoinReq.DoL();
+	ASSERT(iContext.iNodeActivity);
+	PRActivities::CRejoinDataClientActivity* rejoinActivity =
+	    static_cast<PRActivities::CRejoinDataClientActivity*>(iContext.iNodeActivity);
+    RIPDataClientNodeInterface& dc =
+        static_cast<RIPDataClientNodeInterface&>(
+        rejoinActivity->iDataClients[rejoinActivity->iDataClients.Count()-1].iDataClient);
+    TNodeId& newOwner = rejoinActivity->iDataClients[rejoinActivity->iDataClients.Count()-1].iNewOwner;
+
+	RClientInterface::OpenPostMessageClose(dc.RecipientId(), newOwner,
+		TCFIPMessage::TDataClientRouted(TAddrUpdate(dc.iCliSrcAddr, dc.iCliDstAddr, dc.iProtocolId, iContext.Node().iIapId)).CRef());
+	}
+	
+
+#ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+/*
+State waiting for TTransportNotification message which carries TCP Receive window.
+*/
+DEFINE_SMELEMENT(TAwaitingTransportNotification, NetStateMachine::MState, IPBaseSCprStates::TContext)
+TBool IPBaseSCprStates::TAwaitingTransportNotification::Accept()
+	{
+	return iContext.iMessage.IsMessage<TCFMessage::TTransportNotification>();
+	}
+/*
+StateTransition which will iterate thru all the data clients, send the TCP receive window size to them.
+*/
+DEFINE_SMELEMENT(TSendTransportNotificationToDataClients, NetStateMachine::MStateTransition,IPBaseSCprStates::TContext)
+void IPBaseSCprStates::TSendTransportNotificationToDataClients::DoL()
+	{
+	
+	//data client iterator.
+	//Exclude data clients that are ELeaving otherwise the PostMessage() below will panic.
+	TClientIter<TDefaultClientMatchPolicy> iter = iContext.Node().GetClientIter<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EData), TClientType(0, TCFClientType::ELeaving));
+   	//Data Client number
+   	TInt dataCliNum =NULL;
+  	//Send message to all data clients.
+   	RNodeInterface* dataClient = iter[dataCliNum];
+   	
+   	TCFMessage::TTransportNotification message;
+  	while (dataClient)
+   		{
+		//Post messages to the data client. Message will flow to all the data clients i.e. socket flows.
+ 		dataClient->PostMessage(iContext.NodeId(), message);
+ 		dataCliNum++;
+ 		dataClient = iter[dataCliNum];
+   		}
+	}
+#endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+
+}
+
+
+//-=========================================================
+//
+// Activities
+//
+//-=========================================================
+
+namespace IPDeftBaseSCprAddressUpdate
+{
+DECLARE_DEFINE_NODEACTIVITY(ECFActivityAddressUpdate, IPDeftBaseSCprAddressUpdate, TCFIPMessage::TDataClientRouted)
+	NODEACTIVITY_ENTRY(KNoTag, IPBaseSCprStates::TStoreAddressUpdate, IPBaseSCprStates::TAwaitingAddressUpdate, MeshMachine::TNoTag)
+NODEACTIVITY_END()
+}
+
+namespace IPDeftSCprRejoinDataClient
+{
+DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityRejoin, IPDeftSCprRejoin, TCFRejoiningProvider::TRejoinDataClientRequest, PRActivities::CRejoinDataClientActivity::NewL)
+	// If an SCprNoBearer is being processed (e.g. RSocket::Connect()) when IPDeftSCprRejoin is started (RSubConnection::AddSocket()),
+	// park until the SCprNoBearer completes.  This ensures that the EStarting flag (set temporarily during SCprNoBearer)
+	// is not inadvertantly propagated (via the DataClientJoiningRequest message) to the receiving SCpr.  If this happens,
+	// EStarting will never get reset on the receiving SCpr and can cause activities (like PRDataClientStop) to park
+	// permanently on that SCpr.
+	FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingDataClientRejoin, CoreNetStates::TNoTagBlockedByNoBearer)
+	NODEACTIVITY_ENTRY(KNoTag,               IPBaseSCprStates::TRejoinDataClient, PRActivities::CRejoinDataClientActivity::TAwaitingJoinComplete, MeshMachine::TNoTag)
+	NODEACTIVITY_ENTRY(CoreStates::KLoopTag, IPBaseSCprStates::TRejoinDataClient, PRActivities::CRejoinDataClientActivity::TAwaitingJoinComplete, MeshMachine::TNoTag)
+
+	NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendRejoinComplete, CoreNetStates::TAwaitingDataClientRejoinOrApplyOrCancel, PRActivities::CRejoinDataClientActivity::TRejoinLoopTag)
+	NODEACTIVITY_ENTRY(KNoTag, PRActivities::CRejoinDataClientActivity::TApplyRejoin, CoreNetStates::TAwaitingApplyResponse, MeshMachine::TNoTag)
+#ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+	LAST_NODEACTIVITY_ENTRY(KNoTag, PRStates::TSendApplyResponse)
+#else
+	LAST_NODEACTIVITY_ENTRY(KNoTag, SCprStates::TSendApplyResponse)
+#endif // SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+NODEACTIVITY_END()
+}
+
+namespace IPDeftBaseSCprBinderRequestActivity
+{
+DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityBinderRequest, IPDeftBaseSCprBinderRequest, TCFServiceProvider::TCommsBinderRequest, CCommsBinderActivity::NewL)
+	FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingBinderRequest, TNoTagOrUseExistingOrPermissionDenied)
+
+	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(KPermissionDenied, MeshMachine::TRaiseAndClearActivityError)
+NODEACTIVITY_END()
+}
+
+namespace IPDeftBaseSCprBinderRequestActivity
+{
+const TUint32 KSIPSecureId  = 270490934;
+const TUint32 KDHCPSecureId = 270522821;
+const TUint32 KDNSSecureId  = 268437634;
+
+DEFINE_SMELEMENT(TNoTagOrUseExistingOrPermissionDenied, NetStateMachine::MStateFork, TContext)
+TInt TNoTagOrUseExistingOrPermissionDenied::TransitionTag()
+	{
+	ASSERT(iContext.iNodeActivity);
+
+	// have to cast the context sicne we're inheriting
+	NetStateMachine::TContextAccessor<IPDeftBaseSCprBinderRequestActivity::TContext,CCommsBinderActivity::TContext> ctxAccessor(iContext);
+
+	if (ctxAccessor.Context().Node().ImsFlag())
+		{
+		TSecureId secureId = 0;
+		MPlatsecApiExt* extn = NULL;
+		TRAPD(err, extn = reinterpret_cast<MPlatsecApiExt*>(address_cast<TNodeId>(iContext.iSender).Node().FetchNodeInterfaceL(MPlatsecApiExt::KInterfaceId)));
+		if (err == KErrNone || extn != NULL)
+			{
+			if ((extn->SecureId(secureId) != KErrNone) ||
+				(secureId.iId != KSIPSecureId && secureId.iId != KDHCPSecureId && secureId.iId != KDNSSecureId))
+				{
+				iContext.iNodeActivity->SetError(KErrPermissionDenied);
+				return KPermissionDenied;
+				}
+			}
+		}
+
+	return PRActivities::CCommsBinderActivity::TNoTagOrUseExisting::TransitionTag();
+	}
+}
+
+namespace IPDeftBaseSCprDataClientStartActivity
+{
+DEFINE_SMELEMENT(TGetParams, NetStateMachine::MStateTransition, TContext)
+void TGetParams::DoL()
+	{
+	ASSERT(iContext.iNodeActivity);
+	if(iContext.Node().ServiceProvider() == NULL)
+    	{
+    	//The service provider could have dissapeared by now.
+    	User::Leave(KErrDied);
+    	}
+#ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+	iContext.iNodeActivity->PostRequestTo(*iContext.Node().ServiceProvider(),
+		TCFScpr::TGetParamsRequest(RCFParameterFamilyBundleC()).CRef());
+#else
+ 	iContext.iNodeActivity->PostRequestTo(*iContext.Node().ServiceProvider(),
+		TCFScpr::TParamsRequest(RCFParameterFamilyBundleC()).CRef());
+#endif // SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+	}
+}
+
+
+namespace IPDeftBaseSCprDataClientStartActivity
+{
+DECLARE_DEFINE_NODEACTIVITY(ECFActivityStartDataClient, IPDeftBaseSCprDataClientStart, TCFDataClient::TStart )
+    FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingDataClientStart, MeshMachine::TNoTag)
+#ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+	NODEACTIVITY_ENTRY(KNoTag, IPDeftBaseSCprDataClientStartActivity::TGetParams, CoreNetStates::TAwaitingParamResponse, CoreNetStates::TNoTagOrNoDataClients)
+#else
+	NODEACTIVITY_ENTRY(KNoTag, IPDeftBaseSCprDataClientStartActivity::TGetParams, CoreNetStates::TAwaitingParamResponse, MeshMachine::TNoTag)
+	THROUGH_NODEACTIVITY_ENTRY(KNoTag, SCprStates::TStoreParams, CoreNetStates::TNoTagOrNoDataClients)
+#endif // SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW	
+	NODEACTIVITY_ENTRY(KNoTag, PRStates::TStartDataClients, CoreNetStates::TAwaitingDataClientsStarted, MeshMachine::TTag<CoreNetStates::KNoDataClients>)
+	LAST_NODEACTIVITY_ENTRY(CoreNetStates::KNoDataClients, PRStates::TSendDataClientStarted)
+NODEACTIVITY_END()
+}
+
+#ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+
+/*
+Custom activity which waits for TTransportNotification message from IPCPR.
+Stores the TCP receive window size in pointer appended to TProvisionConfig
+and sends the window to all data clients.
+*/
+namespace IPDeftBaseSCPRBearerCharActivity
+{
+DECLARE_DEFINE_NODEACTIVITY(IPDeftSCprBaseActivities::ECFActivityReceiveWin, IPDeftBaseSCPRBearerCharActivity, TCFMessage::TTransportNotification)
+	FIRST_NODEACTIVITY_ENTRY(IPBaseSCprStates::TAwaitingTransportNotification, MeshMachine::TNoTag)
+	THROUGH_NODEACTIVITY_ENTRY(KNoTag, IPBaseSCprStates::TSendTransportNotificationToDataClients, MeshMachine::TNoTag)
+	LAST_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing)
+NODEACTIVITY_END()
+}
+
+#endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+
+namespace IPDeftSCprBaseActivities
+{
+DEFINE_ACTIVITY_MAP(ipscprbaseActivityMap)
+	ACTIVITY_MAP_ENTRY(IPDeftSCprRejoinDataClient, IPDeftSCprRejoin)
+
+#ifdef SYMBIAN_NETWORKING_UPS
+ACTIVITY_MAP_END_BASE(UpsActivities, upsActivitiesSCpr)
+#else
+ACTIVITY_MAP_END_BASE(SCprActivities, coreSCprActivities)
+#endif
+}
+
+
+namespace IPDeftBaseSCprActivities
+{
+DEFINE_ACTIVITY_MAP(ipdeftbasescprActivityMap)
+	ACTIVITY_MAP_ENTRY(IPDeftBaseSCprAddressUpdate, IPDeftBaseSCprAddressUpdate)
+	ACTIVITY_MAP_ENTRY(IPDeftBaseSCprDataClientStartActivity, IPDeftBaseSCprDataClientStart)
+	
+#ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+	ACTIVITY_MAP_ENTRY(IPDeftBaseSCPRBearerCharActivity, IPDeftBaseSCPRBearerCharActivity)
+#endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+	
+	ACTIVITY_MAP_ENTRY(IPDeftBaseSCprBinderRequestActivity, IPDeftBaseSCprBinderRequest)
+ACTIVITY_MAP_END_BASE(IPDeftSCprBaseActivities, ipscprbaseActivityMap)
+}
+
+
+//-=========================================================
+//
+// CIpSubConnectionProviderBase methods
+//
+//-=========================================================
+CIpSubConnectionProviderBase::CIpSubConnectionProviderBase(ESock::CSubConnectionProviderFactoryBase& aFactory,
+                             const MeshMachine::TNodeActivityMap& aActivityMap)
+:CCoreSubConnectionProvider(aFactory, aActivityMap),
+ iIapId(KInvalidIapId)
+    {
+    }
+
+RNodeInterface* CIpSubConnectionProviderBase::NewClientInterfaceL(const TClientType& aClientType, TAny* aClientInfo)
+    {
+    if (aClientType.Type() & TCFClientType::EData)
+        {
+        return new (ELeave) RIPDataClientNodeInterface();
+        }
+    return CCoreSubConnectionProvider::NewClientInterfaceL(aClientType, aClientInfo);
+    }
+
+
+//-=========================================================
+//
+// CIpDefaultBaseSubConnectionProvider methods
+//
+//-=========================================================
+CIpDefaultBaseSubConnectionProvider::~CIpDefaultBaseSubConnectionProvider()
+    {
+    LOG_NODE_DESTROY(KIPDeftSCprTag, CIpDefaultBaseSubConnectionProvider);
+    }
+
+CIpDefaultBaseSubConnectionProvider::CIpDefaultBaseSubConnectionProvider(ESock::CSubConnectionProviderFactoryBase& aFactory,
+                             const MeshMachine::TNodeActivityMap& aActivityMap)
+    : CIpSubConnectionProviderBase(aFactory, aActivityMap)
+    {
+    LOG_NODE_CREATE(KIPDeftSCprTag, CIpDefaultBaseSubConnectionProvider);
+    }
+
+CIpDefaultBaseSubConnectionProvider* CIpDefaultBaseSubConnectionProvider::NewL(ESock::CSubConnectionProviderFactoryBase& aFactory)
+    {
+    CIpDefaultBaseSubConnectionProvider* provider = new (ELeave) CIpDefaultBaseSubConnectionProvider(aFactory, IPDeftBaseSCprActivities::ipdeftbasescprActivityMap::Self());
+    CleanupStack::PushL(provider);
+    provider->ConstructL(KIPDeftBaseSCPRPreallocatedActivityBufferSize);
+
+    CleanupStack::Pop(provider);
+    return provider;
+    }
+
+void CIpDefaultBaseSubConnectionProvider::ReceivedL(const TRuntimeCtxId& aSender, const TNodeId& aRecipient, TSignatureBase& aMessage)
+	{
+   	TNodeContext<CIpDefaultBaseSubConnectionProvider> ctx(*this, aMessage, aSender, aRecipient);
+	ESOCK_DEBUG_MESSAGE_INTERCEPT(aSender, aMessage, aRecipient);
+	CCoreSubConnectionProvider::ReceivedL(aSender, aRecipient, aMessage);
+	User::LeaveIfError(ctx.iReturn);
+	}
+
+TBool CIpDefaultBaseSubConnectionProvider::ImsFlag()
+	{
+	TBool imsFlagSet = EFalse;
+	if ( iParameterBundle.IsNull() )
+		{
+		return imsFlagSet;
+		}
+
+	RParameterFamily family=iParameterBundle.FindFamily(KSubConnContextDescrParamsFamily);
+	if( ! family.IsNull())
+		{
+		CSubConImsExtParamSet* imsExtGranted = static_cast<CSubConImsExtParamSet*>(
+			family.FindParameterSet(STypeId::CreateSTypeId(KSubCon3GPPExtParamsFactoryUid,KSubConImsExtParamsType),
+									 RParameterFamily::EGranted));
+
+		if (imsExtGranted)
+			imsFlagSet = imsExtGranted->GetImsSignallingIndicator();
+		}
+
+	return imsFlagSet;
+	}
+