--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/telephonyprotocols/pdplayer/src/PDPSCPR.cpp Tue Feb 02 01:41:59 2010 +0200
@@ -0,0 +1,594 @@
+// 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:
+// PDP SubConnection Provider implementation
+//
+//
+
+/**
+ @file
+ @internalComponent
+*/
+
+
+#include "PDPSCPRStates.h"
+#include "PDPDeftSCPR.h"
+#include "PDPSCPR.h"
+#include "PDPSCPRFactory.h"
+#include <comms-infras/ss_log.h>
+#include <comms-infras/ss_msgintercept.h>
+#include <comms-infras/agentscprstates.h>
+#include <comms-infras/agentscpractivities.h>
+#include <comms-infras/ss_nodemessages_factory.h>
+
+#if defined __FLOG_ACTIVE || defined SYMBIAN_TRACE_ENABLE
+#define KPDPSCprTag KESockSubConnectionTag
+_LIT8(KPDPSCprSubTag, "pdpscpr");
+#endif
+
+using namespace Messages;
+using namespace MeshMachine;
+using namespace ESock;
+using namespace NetStateMachine;
+using namespace Factories;
+
+//We reserve space for two preallocated activities that may start concurrently on the 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 KPDPSCPRPreallocatedActivityBufferSize = KDefaultMaxPreallocatedActivityCount * KMaxPreallocatedActivitySize;
+
+//-=========================================================
+//
+// CPDPSubConnectionProvider Activities
+//
+//-=========================================================
+
+namespace PDPSCprProvisionActivity
+{
+DECLARE_DEFINE_NODEACTIVITY(ECFActivityStoreProvision, provision, TCFDataClient::TProvisionConfig)
+ NODEACTIVITY_ENTRY(KNoTag, PDPSCprStates::TStoreProvisionAndInitSelf, CoreNetStates::TAwaitingProvision, MeshMachine::TNoTag)
+NODEACTIVITY_END()
+}
+
+namespace PDPSCprStartActivity
+{
+DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityStart, PDPScprStart, TCFServiceProvider::TStart, MeshMachine::CNodeRetryActivity::NewL)
+ FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingStart, CoreNetStates::TNoTagOrBearerPresentBlockedByStop)
+ NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TStartSelf, CoreNetStates::TAwaitingDataClientStarted, MeshMachine::TNoTag)
+ LAST_NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendStarted)
+ LAST_NODEACTIVITY_ENTRY(CoreNetStates::KBearerPresent, CoreStates::TPanic)
+NODEACTIVITY_END()
+}
+
+namespace PDPSCprDataClientStartActivity
+{
+typedef MeshMachine::TAcceptErrorState<CoreNetStates::TAwaitingDataClientStarted> TAwaitingDataClientStartedOrError;
+
+DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityStartDataClient, pdpDataClientStart, TCFDataClient::TStart, PDPSCprStates::CStartActivity::NewL)
+ FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingDataClientStart, MeshMachine::TNoTag)
+ NODEACTIVITY_ENTRY(KNoTag, PDPSCprStates::TCreateSecondaryOrMbmsPDPCtx, PDPSCprStates::TAwaitingPDPCtxCreated, PDPSCprStates::TNoTagOrError)
+ NODEACTIVITY_ENTRY(KNoTag, PDPSCprStates::TSetTFT, PDPSCprStates::TAwaitingTFTSet, PDPSCprStates::TNoTagOrError)
+ NODEACTIVITY_ENTRY(KNoTag, PDPSCprStates::TSetQoS, PDPSCprStates::TAwaitingQoSSet, PDPSCprStates::TNoTagOrError)
+ NODEACTIVITY_ENTRY(KNoTag, PDPSCprStates::TActivatePDPContext, PDPSCprStates::TAwaitingPDPContextActive, PDPSCprStates::TNoTagOrError)
+ NODEACTIVITY_ENTRY(KNoTag, PDPSCprStates::TOverrideProvisionAndStartDataClient, TAwaitingDataClientStartedOrError, MeshMachine::TNoTagOrErrorTag)
+ //This call below is somewhat obscure, but must be performed for the final activation of a pdp context.
+ NODEACTIVITY_ENTRY(KNoTag, PDPSCprStates::TGetNegotiatedQoS, PDPSCprStates::TAwaitingNegotiatedQoSRetrieved, PDPSCprStates::TNoTagOrError)
+ LAST_NODEACTIVITY_ENTRY(KNoTag, PDPSCprStates::TRaiseParamsGrantedAndSendDataClientStarted)
+
+ // Cleanup if error occurred
+ THROUGH_NODEACTIVITY_ENTRY(KErrorTag, MeshMachine::TDoNothing, CoreNetStates::TNoTagOrNoDataClientsToStop)
+ NODEACTIVITY_ENTRY(KNoTag, SCprStates::TStopYourFlows, CoreNetStates::TAwaitingDataClientStopped, MeshMachine::TTag<CoreNetStates::KNoDataClientsToStop>)
+ THROUGH_NODEACTIVITY_ENTRY(CoreNetStates::KNoDataClientsToStop, MeshMachine::TDoNothing, PDPSCprStates::TNoTagOrProviderStopped)
+ NODEACTIVITY_ENTRY(KNoTag, PDPSCprStates::TDestroyPDPContext, PDPSCprStates::TAwaitingPDPContextDestroyed, MeshMachine::TTag<CoreNetStates::KProviderStopped>)
+ THROUGH_NODEACTIVITY_ENTRY(CoreNetStates::KProviderStopped, PRStates::TDestroyOrphanedDataClients, MeshMachine::TTag<CoreNetStates::KProviderStopped>)
+ LAST_NODEACTIVITY_ENTRY(CoreNetStates::KProviderStopped, MeshMachine::TRaiseActivityError)
+NODEACTIVITY_END()
+}
+
+namespace PDPSCprStopActivity
+{
+DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityStopDataClient, Stop, TCFDataClient::TStop, MeshMachine::CNodeRetryActivity::NewL)
+ FIRST_NODEACTIVITY_ENTRY(PDPSCprStates::TAwaitingDataClientStopOrCancel, MeshMachine::TNoTag)
+ THROUGH_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing, PRDataClientStopActivity::TNoTagOrProviderStoppedBlockedByStart)
+
+ // stopping
+ NODEACTIVITY_ENTRY(KNoTag, SCprStates::TStopYourFlows, CoreNetStates::TAwaitingDataClientStopped, MeshMachine::TTag<CoreNetStates::KProviderStopped>)
+ THROUGH_NODEACTIVITY_ENTRY(CoreNetStates::KProviderStopped, MeshMachine::TDoNothing, PDPSCprStates::TNoTagOrProviderStopped)
+ NODEACTIVITY_ENTRY(KNoTag, PDPSCprStates::TDestroyPDPContext, PDPSCprStates::TAwaitingPDPContextDestroyed, MeshMachine::TTag<CoreNetStates::KProviderStopped>)
+ THROUGH_NODEACTIVITY_ENTRY(CoreNetStates::KProviderStopped, PRStates::TDestroyOrphanedDataClients, MeshMachine::TTag<CoreNetStates::KProviderStopped>)
+ LAST_NODEACTIVITY_ENTRY(CoreNetStates::KProviderStopped, PDPSCprStates::TSendDataClientStopped)
+NODEACTIVITY_END()
+}
+
+namespace PDPSCprGoneDownActivity
+{
+DECLARE_DEFINE_NODEACTIVITY(ECFActivityGoneDown, goneDown, TPDPFSMMessages::TPDPFSMMessage)
+ FIRST_NODEACTIVITY_ENTRY(PDPSCprStates::TAwaitingPDPContextGoneDown, MeshMachine::TActiveOrNoTag<ECFActivityStartDataClient>)
+ THROUGH_NODEACTIVITY_ENTRY(KNoTag, PDPSCprStates::TSendGoneDown, CoreNetStates::TNoTagOrNoDataClientsToStop)
+ NODEACTIVITY_ENTRY(KNoTag, SCprStates::TStopYourFlows, CoreNetStates::TAwaitingDataClientStopped, MeshMachine::TTag<CoreNetStates::KNoDataClientsToStop>)
+
+ LAST_NODEACTIVITY_ENTRY(KActiveTag, CoreNetStates::TCancelDataClientStart) //MZTODO: This triple should wait for TError sent as a response to TCancel
+ LAST_NODEACTIVITY_ENTRY(CoreNetStates::KNoDataClientsToStop, MeshMachine::TClearError)
+NODEACTIVITY_END()
+}
+
+namespace PDPSCprSetParameters
+{
+#ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+DECLARE_DEFINE_NODEACTIVITY(ECFActivityParamRequest, paramRequest, TCFScpr::TSetParamsRequest)
+ NODEACTIVITY_ENTRY(KNoTag, PDPSCprStates::TStoreAndRespondWithCurrentParams, PRStates::TAwaitingParamRequest, MeshMachine::TNoTag)
+#else
+DECLARE_DEFINE_NODEACTIVITY(ECFActivityParamRequest, paramRequest, TCFScpr::TParamsRequest)
+ NODEACTIVITY_ENTRY(KNoTag, PDPSCprStates::TStoreParamsAndRespond, SCprStates::TAwaitingParamRequest, MeshMachine::TNoTag)
+#endif // SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+NODEACTIVITY_END()
+}
+
+namespace PDPSCprApply
+{
+DECLARE_DEFINE_NODEACTIVITY(ECFActivityApplyChanges, pdpApplyReq, TCFScpr::TApplyRequest)
+#ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+ FIRST_NODEACTIVITY_ENTRY(PRStates::TAwaitingApplyRequest, MeshMachine::TNoTag)
+#else
+ FIRST_NODEACTIVITY_ENTRY(SCprStates::TAwaitingApplyRequest, MeshMachine::TNoTag)
+#endif // SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+ NODEACTIVITY_ENTRY(KNoTag, PDPSCprStates::TSetTFT, PDPSCprStates::TAwaitingTFTSet, PDPSCprStates::TNoTagOrError)
+ NODEACTIVITY_ENTRY(KNoTag, PDPSCprStates::TSetQoS, PDPSCprStates::TAwaitingQoSSet, PDPSCprStates::TNoTagOrError)
+ NODEACTIVITY_ENTRY(KNoTag, PDPSCprStates::TModifyActivePDPContext, PDPSCprStates::TAwaitingActivePDPContextModified, PDPSCprStates::TNoTagOrError)
+ LAST_NODEACTIVITY_ENTRY(KNoTag, PDPSCprStates::TRaiseParamsGrantedAndSendApplyResponse)
+ LAST_NODEACTIVITY_ENTRY(KErrorTag, PDPSCprStates::TRaiseParamsRejectedL)
+NODEACTIVITY_END()
+}
+
+namespace PDPSCprParamsChanged
+{
+DECLARE_DEFINE_NODEACTIVITY(ECFActivityParamRequest, paramsChanged, TPDPFSMMessages::TPDPFSMMessage)
+ FIRST_NODEACTIVITY_ENTRY(PDPSCprStates::TAwaitingParamsChanged, PDPSCprStates::TNoTagOrError)
+ LAST_NODEACTIVITY_ENTRY(KNoTag, PDPSCprStates::TRaiseParamsChanged)
+ LAST_NODEACTIVITY_ENTRY(KErrorTag, PDPSCprStates::TRaiseParamsRejectedL)
+NODEACTIVITY_END()
+}
+
+namespace PDPSCprContextBlockedUnblockedActivity
+{
+DECLARE_DEFINE_NODEACTIVITY(ECFActivityParamRequest, ctxBlockedUnblocked, TPDPFSMMessages::TPDPFSMMessage)
+ FIRST_NODEACTIVITY_ENTRY(PDPSCprStates::TAwaitingContextBlockedOrUnblocked, MeshMachine::TNoTag)
+ THROUGH_NODEACTIVITY_ENTRY(KNoTag, PDPSCprStates::TForwardContextBlockedOrUnblockedToDC, PDPSCprStates::TBlockedOrUnblocked)
+ LAST_NODEACTIVITY_ENTRY(PDPSCprStates::KBlocked, PDPSCprStates::TSendDataTransferTemporarilyBlocked)
+ /**
+ This needs to send DataTransferUnblocked progress, but this needs to be discussed with people in finland
+ when they return. In old world, KLinkLayerOpen was sent in this case, but KLinkLayerOpen has changed and is misused for
+ this purpose. Should be a new, functionallity specific progress .
+ */
+ LAST_NODEACTIVITY_ENTRY(PDPSCprStates::KUnblocked, PDPSCprStates::TSendDataTransferUnblocked)
+NODEACTIVITY_END()
+}
+
+namespace PDPSCprStateChangeActivity
+{
+DECLARE_DEFINE_NODEACTIVITY(ECFActivityForwardStateChange, forwardStateChange, TCFMessage::TStateChange)
+ //Bin all the progresses received, PDP.SCPR will generate its own ones.
+ NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing, MeshMachine::TAwaitingMessageState<TCFMessage::TStateChange>, MeshMachine::TNoTag)
+NODEACTIVITY_END()
+}
+
+namespace PDPSCprAuthenticationActivity
+{
+DECLARE_DEFINE_NODEACTIVITY(ECFActivityAuthentication, PDPSCprAuthentication, TLinkMessage::TAuthenticate)
+ NODEACTIVITY_ENTRY(KNoTag, AgentSCprStates::TSendAuthenticateComplete, AgentSCprStates::TAwaitingAuthenticate, MeshMachine::TNoTag)
+NODEACTIVITY_END()
+}
+
+namespace PDPSCprActivities
+{
+DEFINE_ACTIVITY_MAP(activityMap)
+ ACTIVITY_MAP_ENTRY(PDPSCprProvisionActivity, provision)
+ ACTIVITY_MAP_ENTRY(PDPSCprStartActivity, PDPScprStart)
+ ACTIVITY_MAP_ENTRY(PDPSCprDataClientStartActivity, pdpDataClientStart)
+ ACTIVITY_MAP_ENTRY(PDPSCprSetParameters, paramRequest)
+ ACTIVITY_MAP_ENTRY(PDPSCprParamsChanged, paramsChanged)
+ ACTIVITY_MAP_ENTRY(PDPSCprContextBlockedUnblockedActivity, ctxBlockedUnblocked)
+ ACTIVITY_MAP_ENTRY(PDPSCprApply, pdpApplyReq)
+ ACTIVITY_MAP_ENTRY(PDPSCprStopActivity, Stop)
+ ACTIVITY_MAP_ENTRY(PDPSCprGoneDownActivity, goneDown)
+ ACTIVITY_MAP_ENTRY(PDPSCprStateChangeActivity, forwardStateChange)
+ ACTIVITY_MAP_ENTRY(PDPSCprAuthenticationActivity, PDPSCprAuthentication)
+ACTIVITY_MAP_END_BASE(SCprActivities, coreSCprActivities)
+}
+
+//-=========================================================
+//
+// CPDPSubConnectionProvider methods
+//
+//-=========================================================
+CPDPSubConnectionProvider* CPDPSubConnectionProvider::NewL(CPDPSubConnectionProviderFactory& aFactory)
+/**
+Construct a new PDP SubConnection Provider Object
+
+@params aFactory factory that create this object
+@param aConnProvider Connection Provider associated with this object
+*/
+ {
+ CPDPSubConnectionProvider* ptr = new (ELeave) CPDPSubConnectionProvider(aFactory);
+ CleanupStack::PushL(ptr);
+ ptr->ConstructL();
+ CleanupStack::Pop();
+ return ptr;
+ }
+
+
+CPDPSubConnectionProvider::~CPDPSubConnectionProvider()
+ {
+ LOG_NODE_DESTROY(KPDPSCprSubTag, CPDPSubConnectionProvider)
+ __FLOG_CLOSE;
+ if (iPdpFsmInterface)
+ {
+ iPdpFsmInterface->Close();
+ }
+ }
+
+
+CPDPSubConnectionProvider::CPDPSubConnectionProvider(ESock::CSubConnectionProviderFactoryBase& aFactory)
+:CCoreSubConnectionProvider(aFactory, PDPSCprActivities::activityMap::Self()),
+ iPDPFsmContextId(EInvalidContextId),
+ iPdpFsmInterface(NULL),
+ iActivityAwaitingResponse(KActivityNull)
+ {
+ LOG_NODE_CREATE1(KPDPSCprSubTag, CPDPSubConnectionProvider, " [factory=%08x]", &aFactory)
+ __FLOG_OPEN(KCFNodeTag, KPDPSCprSubTag);
+ }
+
+
+CPDPSubConnectionProvider::CPDPSubConnectionProvider(ESock::CSubConnectionProviderFactoryBase& aFactory,
+ const MeshMachine::TNodeActivityMap& aActivityMap)
+:CCoreSubConnectionProvider(aFactory, aActivityMap),
+ iPDPFsmContextId(EInvalidContextId),
+ iPdpFsmInterface(NULL),
+ iActivityAwaitingResponse(KActivityNull),
+ iParamsRelease(MPDPParamMapper::KParameterRelInvalid)
+ {
+ }
+
+void CPDPSubConnectionProvider::ConstructL()
+/**
+IP SubConnection Provider Second Phase Constructor
+*/
+ {
+ CCoreSubConnectionProvider::ConstructL(KPDPSCPRPreallocatedActivityBufferSize);
+ }
+
+void CPDPSubConnectionProvider::Received(TNodeContextBase& aContext)
+ {
+ Messages::TNodeSignal::TMessageId noPeerIds[] = {
+ TCFFactory::TPeerFoundOrCreated::Id(),
+ TCFPeer::TJoinRequest::Id(),
+ TCFMessage::TStateChange::Id(),
+ Messages::TNodeSignal::TNullMessageId::Id()
+ };
+ MeshMachine::AMMNodeBase::Received(noPeerIds, aContext);
+ MeshMachine::AMMNodeBase::PostReceived(aContext);
+ }
+
+void CPDPSubConnectionProvider::ReceivedL(const TRuntimeCtxId& aSender, const TNodeId& aRecipient, TSignatureBase& aMessage)
+ {
+ ESOCK_DEBUG_MESSAGE_INTERCEPT(aSender, aMessage, aRecipient);
+
+ PDPSCprStates::TContext ctx(*this, aMessage, aSender, aRecipient);
+ CPDPSubConnectionProvider::Received(ctx);
+ User::LeaveIfError(ctx.iReturn);
+ }
+
+void CPDPSubConnectionProvider::Event(TInt aEvent, TInt aParam)
+ {
+ TPDPFSMMessages::TPDPFSMMessage msg(aEvent, aParam);
+
+ RClientInterface::OpenPostMessageClose(TNodeCtxId(iActivityAwaitingResponse, Id()), Id(), msg);
+ iActivityAwaitingResponse = KActivityNull;
+ }
+
+void CPDPSubConnectionProvider::LinkUp()
+ {
+ if (iLinkUps++ == 0)
+ {
+ iDefaultSCPR->LinkUp();
+ }
+ }
+
+void CPDPSubConnectionProvider::LinkDown(TInt aCause)
+ {
+ if (--iLinkUps == 0)
+ {
+ iDefaultSCPR->LinkDown(aCause);
+ }
+ }
+
+CSubConQosR99ParamSet* CPDPSubConnectionProvider::GrantedQoS()
+ {
+ if(static_cast<CSubConnectionProviderBase*>(this)->GetParameterBundle().IsNull())
+ {
+ return NULL;
+ }
+ RParameterFamily qosFamily=static_cast<CSubConnectionProviderBase*>(this)->GetParameterBundle().FindFamily(KSubConQoSFamily);
+ if (qosFamily.IsNull())
+ {
+ return NULL;
+ }
+ CSubConQosR99ParamSet* qosParams = static_cast<CSubConQosR99ParamSet*>(qosFamily.FindParameterSet(
+ STypeId::CreateSTypeId(KSubCon3GPPExtParamsFactoryUid,KSubConQosR99ParamsType), RParameterFamily::EGranted));
+ if (!qosParams)
+ {
+ qosParams = static_cast<CSubConQosR99ParamSet*>(qosFamily.FindParameterSet(
+ STypeId::CreateSTypeId(KSubCon3GPPExtParamsFactoryUid,KSubConQosR5ParamsType), RParameterFamily::EGranted));
+ }
+ ASSERT(qosParams);
+ return qosParams;
+ }
+
+TInt CPDPSubConnectionProvider::QoSRank()
+/**
+This method calculates the qos ranking as specified in 3GPP TS 23.107 Annex C.
+Magic number usage is deemed justified based on the content of 3GPP TS 23.107.
+*/
+ {
+ CSubConQosR99ParamSet* qosParams = GrantedQoS();
+ ASSERT(qosParams);
+
+ switch (qosParams->GetTrafficClass())
+ {
+ case RPacketQoS::ETrafficClassConversational:
+ return 2;
+ case RPacketQoS::ETrafficClassStreaming:
+ return 3;
+ case RPacketQoS::ETrafficClassInteractive:
+ {
+ switch (qosParams->GetTrafficHandlingPriority())
+ {
+ case RPacketQoS::ETrafficPriority1:
+ return 1;
+ case RPacketQoS::ETrafficPriority2:
+ return 4;
+ case RPacketQoS::ETrafficPriority3:
+ return 5;
+ default:
+ ;
+ }
+ break;
+ }
+ case RPacketQoS::ETrafficClassBackground:
+ return 6;
+ default:
+ ;
+ }
+ return 7;
+ }
+
+
+MFactoryQuery::TMatchResult THighestQoSQuery::Match(TFactoryObjectInfo& aSubConnectionInfo)
+ {
+ CPDPSubConnectionProvider* sc = static_cast<CPDPSubConnectionProvider*>(aSubConnectionInfo.iInfo.iFactoryObject);
+ ASSERT(sc && sc->ControlProvider());
+ if (sc->ControlProvider()->RecipientId() == iCtrlProvider &&
+ sc->iPDPFsmContextId != CPDPSubConnectionProvider::EInvalidContextId)
+ {
+ if (NULL == iHighestQoSProvider)
+ {
+ iHighestQoSProvider = sc;
+ }
+ else if (sc->QoSRank() > iHighestQoSProvider->QoSRank())
+ {
+ iHighestQoSProvider = sc;
+ }
+ }
+ return MFactoryQuery::EContinue;
+ }
+
+TTFTInfo CPDPSubConnectionProvider::GetTftInfoL(CSubConIPAddressInfoParamSet* aParamSet)
+ {
+ /** TODO: What to do if there will be second request before ggsn responce back and first one will go to the granted list
+ Assigning of id's is not correct in that case*/
+
+ TTFTInfo tft;
+ RPacketContext::TPacketFilterV2 pf;
+
+ TUint aParamSetNum = aParamSet->GetParamNum();
+ /** TODO: It should be only one in the queue, so remove the loop */
+ for (TUint i=0; i<aParamSetNum; ++i)
+ {
+ // TUint8* pfAddr(pf.iSrcAddr);
+
+ CSubConIPAddressInfoParamSet::TSubConIPAddressInfo paramInfo(aParamSet->GetParamInfoL(i));
+
+ TInetAddr addr(paramInfo.iCliDstAddr);
+ TUint32 ipv4Addr = addr.Address();
+
+ if(ipv4Addr)
+ {
+ addr.ConvertToV4Mapped();
+ }
+
+ TIp6Addr ipv6 = addr.Ip6Address();
+ Mem::Copy(&pf.iSrcAddr,&ipv6,RPacketContext::KIPAddressSize);
+
+ pf.iId = FindPacketFilterIdL(paramInfo);
+ Mem::Fill(pf.iSrcAddrSubnetMask, sizeof(pf.iSrcAddrSubnetMask), 0xFF);
+ pf.iSrcPortMin = pf.iSrcPortMax = paramInfo.iCliDstAddr.Port();
+ pf.iDestPortMin = pf.iDestPortMax = paramInfo.iCliSrcAddr.Port();
+ pf.iProtocolNumberOrNextHeader = paramInfo.iProtocolId;
+
+ tft.AddPacketFilter(pf);
+ }
+
+ return tft;
+ }
+
+TTFTOperationCode CPDPSubConnectionProvider::GetOperationCodeL(CSubConIPAddressInfoParamSet* aParamSet)
+ {
+ TTFTOperationCode result(0);
+ TInt count = aParamSet->GetParamNum();
+ if(count > 0)
+ {
+ CSubConIPAddressInfoParamSet::TSubConIPAddressInfo paramInfo(aParamSet->GetParamInfoL(0));
+ switch(paramInfo.iState)
+ {
+ case CSubConIPAddressInfoParamSet::TSubConIPAddressInfo::EAdd:
+ result = KAddFilters;
+ break;
+ case CSubConIPAddressInfoParamSet::TSubConIPAddressInfo::ERemove:
+ result = KRemoveFilters;
+ break;
+ case CSubConIPAddressInfoParamSet::TSubConIPAddressInfo::ENone:
+ if(aParamSet->GetOperationCode() == CSubConIPAddressInfoParamSet::EDelete)
+ {
+ result = KDeleteTFT;
+ }
+ break;
+ default: ;
+ /** TODO: What to do with an error */
+ }
+ }
+ else
+ {
+ /** TODO: Panic? */
+ }
+
+ return result;
+ }
+
+TUint CPDPSubConnectionProvider::FindPacketFilterIdL(CSubConIPAddressInfoParamSet::TSubConIPAddressInfo aParamInfo)
+ {
+ TUint id = 0;
+
+ switch(aParamInfo.iState)
+ {
+ case CSubConIPAddressInfoParamSet::TSubConIPAddressInfo::EAdd :
+ {
+ TUint i = 0;
+ TUint mask = 1;
+
+ // search bitwise for an empty slot
+ while(!(mask & iPacketFilterMaskId) && i<8)
+ {
+ mask <<= 1;
+ ++i;
+ }
+
+ // if not found assigne the first slot
+ id = (i>=8) ? 1 : i;
+ }
+ break;
+ case CSubConIPAddressInfoParamSet::TSubConIPAddressInfo::ERemove :
+ id = FindIdOfMatchingParamSetL(aParamInfo);
+ break;
+ case CSubConIPAddressInfoParamSet::TSubConIPAddressInfo::ENone :
+ break;
+ default: ;
+ /** TODO: What to do with an error */
+ }
+
+ // increase by one since id is starting from 1
+ return id;
+ }
+
+TUint CPDPSubConnectionProvider::FindIdOfMatchingParamSetL(CSubConIPAddressInfoParamSet::TSubConIPAddressInfo aParamInfo)
+ {
+ // check the list of the granted params for an index
+ if(GetParameterBundle().IsNull())
+ {
+ return 0;
+ }
+ RParameterFamily ipAddressInfoFamily=GetParameterBundle().FindFamily(KSubConIPAddressInfoFamily);
+ if( ipAddressInfoFamily.IsNull() )
+ {
+ return 0;
+ }
+
+ CSubConIPAddressInfoParamSet* ipAddressInfoSet =
+ static_cast<CSubConIPAddressInfoParamSet*>(
+ ipAddressInfoFamily.FindParameterSet(
+ STypeId::CreateSTypeId(CSubConIPAddressInfoParamSet::EUid,CSubConIPAddressInfoParamSet::ETypeId),
+ RParameterFamily::EGranted));
+ if( ipAddressInfoSet == NULL )
+ {
+ return 0;
+ }
+ TUint count = ipAddressInfoSet->GetParamNum();
+
+ TBool found(EFalse);
+ TUint i=0;
+
+ for(i=0; i<count && !found; ++i)
+ {
+ CSubConIPAddressInfoParamSet::TSubConIPAddressInfo paramInfo(ipAddressInfoSet->GetParamInfoL(i));
+
+ found = paramInfo.Compare(aParamInfo);
+ }
+ // use the index against corresponding array of id's
+ return found ? iPacketFilterId[i] : 0;
+ }
+
+void CPDPSubConnectionProvider::NewPacketFilterAddedL(CSubConIPAddressInfoParamSet::TSubConIPAddressInfo aParamInfo, TUint aId)
+ {
+ RParameterFamily ipAddressInfoFamily = GetParameterBundle().FindFamily(KSubConIPAddressInfoFamily);
+ if ( ! ipAddressInfoFamily.IsNull())
+ {
+ CSubConIPAddressInfoParamSet* grantedIPAddressInfo = CSubConIPAddressInfoParamSet::NewL(ipAddressInfoFamily, RParameterFamily::EGranted);
+
+ if(grantedIPAddressInfo)
+ {
+ grantedIPAddressInfo->AddParamInfo(aParamInfo);
+
+ iPacketFilterId.Append(aId);
+ iPacketFilterMaskId |= 1 << aId;
+ }
+ else
+ {
+ User::Leave(KErrNotFound);
+ }
+ }
+ }
+
+void CPDPSubConnectionProvider::PacketFilterRemovedL(TUint aId)
+ {
+ RParameterFamily ipAddressInfoFamily = GetParameterBundle().FindFamily(KSubConIPAddressInfoFamily);
+
+ if ( ! ipAddressInfoFamily.IsNull())
+ {
+ // find an index from given id value
+ //TUint count = iPacketFilterId.Count();
+ TInt index = iPacketFilterId.Find(aId);
+
+ //for (index = 0; (index < count) && (iPacketFilterId[index] != aId); ++index){}
+
+ if(index >= 0)
+ {
+ CSubConIPAddressInfoParamSet* grantedIPAddressInfo = CSubConIPAddressInfoParamSet::NewL(ipAddressInfoFamily, RParameterFamily::EGranted);
+
+ if(grantedIPAddressInfo)
+ {
+ grantedIPAddressInfo->RemoveParamInfo(index);
+
+ iPacketFilterId.Remove(index);
+ iPacketFilterMaskId &= !(1 << aId);
+ }
+ else
+ {
+ User::Leave(KErrNotFound);
+ }
+ }
+ else
+ {
+ User::Leave(KErrNotFound);
+ }
+ }
+ }