diff -r 000000000000 -r 3553901f7fa8 telephonyprotocols/pdplayer/src/PDPDeftSCPR.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/telephonyprotocols/pdplayer/src/PDPDeftSCPR.cpp Tue Feb 02 01:41:59 2010 +0200 @@ -0,0 +1,265 @@ +// 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 +#include "PDPDeftSCPR.h" +#include "PDPSCPRStates.h" +#include "PDPSCPRFactory.h" +#include +#include +#include + +#if defined(__CFLOG_ACTIVE) || defined(SYMBIAN_TRACE_ENABLE) +#define KPDPSCprTag KESockSubConnectionTag +_LIT8(KPDPSCprSubTag, "pdpscpr"); +#endif + +using namespace Messages; +using namespace MeshMachine; +using namespace ESock; +using namespace NetStateMachine; + + +//-========================================================= +// +// Activities +// +//-========================================================= + +namespace PDPDeftSCprDataClientStartActivity +{ +typedef MeshMachine::TAcceptErrorState TAwaitingDataClientStartedOrError; + +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityStartDataClient, PDPDeftDataClientStart, TCFDataClient::TStart, PDPSCprStates::CStartActivity::NewL) + FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingDataClientStart, PDPSCprStates::TNoTagOrAlreadyStarted) + LAST_NODEACTIVITY_ENTRY(CoreNetStates::KAlreadyStarted, PRStates::TSendDataClientStarted) + + NODEACTIVITY_ENTRY(KNoTag, PDPSCprStates::TCreatePrimaryPDPCtx, PDPSCprStates::TAwaitingPrimaryPDPCtxCreated, PDPSCprStates::TNoTagOrSendErrorRecoveryRequestOrError) + NODEACTIVITY_ENTRY(PDPSCprStates::KSendErrorRecoveryRequest, PDPSCprStates::TSendErrorRecoveryRequest, MeshMachine::TAwaitingErrorRecoveryResponseOrError, PDPSCprStates::TNoTagBackwardOrErrorTag) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, PDPSCprStates::TFillInGrantedParamsAndImsExtParams, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, PDPSCprStates::TOverrideProvisionAndStartDataClient, TAwaitingDataClientStartedOrError, MeshMachine::TNoTagOrErrorTag) + LAST_NODEACTIVITY_ENTRY(KNoTag, PDPSCprStates::TSendDataClientStarted) + + // Cleanup if error occurred + THROUGH_NODEACTIVITY_ENTRY(KErrorTag, MeshMachine::TDoNothing, CoreNetStates::TNoTagOrNoDataClientsToStop) + NODEACTIVITY_ENTRY(KNoTag, SCprStates::TStopYourFlows, CoreNetStates::TAwaitingDataClientStopped, MeshMachine::TTag) + THROUGH_NODEACTIVITY_ENTRY(CoreNetStates::KNoDataClientsToStop, MeshMachine::TDoNothing, PDPSCprStates::TNoTagOrProviderStopped) + NODEACTIVITY_ENTRY(KNoTag, PDPSCprStates::TDestroyPDPContext, PDPSCprStates::TAwaitingPDPContextDestroyed, MeshMachine::TTag) + THROUGH_NODEACTIVITY_ENTRY(CoreNetStates::KProviderStopped, PRStates::TDestroyOrphanedDataClients, MeshMachine::TTag) + LAST_NODEACTIVITY_ENTRY(CoreNetStates::KProviderStopped, MeshMachine::TRaiseActivityError) +NODEACTIVITY_END() +} + +namespace PDPSCprNetworkStatusEventActivity +{ +DECLARE_DEFINE_NODEACTIVITY(ECFActivityNotification, subConnStatusEvent, TPDPFSMMessages::TPDPFSMMessage) + FIRST_NODEACTIVITY_ENTRY(PDPSCprStates::TAwaitingNetworkStatusEvent, PDPSCprStates::TNetworkStatusEventTypeTag) + LAST_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing) + + // Assume that anything other than EStatusUnattached means the network + // is still up, so just ignore this event. + LAST_NODEACTIVITY_ENTRY(RPacketService::EStatusAttached, MeshMachine::TDoNothing) + LAST_NODEACTIVITY_ENTRY(RPacketService::EStatusActive, MeshMachine::TDoNothing) + LAST_NODEACTIVITY_ENTRY(RPacketService::EStatusSuspended, MeshMachine::TDoNothing) + + NODEACTIVITY_ENTRY(RPacketService::EStatusUnattached, CoreNetStates::TStopSelf, CoreNetStates::TAwaitingDataClientStopped, MeshMachine::TNoTag) + LAST_NODEACTIVITY_ENTRY(KNoTag, SCprStates::TSendDataClientGoneDown) +NODEACTIVITY_END() +} + +namespace PDPDeftSCprGoneDownActivity +{ +//TODO perhaps get this from a header file since its used in a number of places - see ss_subconn.cpp +typedef MeshMachine::TAcceptErrorState TAwaitingApplyResponseOrError; + +//mandated by 3GPP TS 23.107 Annex C, the default going down needs to select a new default +//among the non-defaults and swap the datapath. Swapping datapath is now done +//transparently, i.e.: without the upper layer knowing (binders are kept, flows are swapped). +//This arguably isn't pretty and could be changed to something more explicit, i.e.: +//sending TBindToRequest to the upper layer SCPR so that it does an explit rebind. +//[401TODO]: the swap only works for rawIp, doesn't for PPP. +//[401TODO]: if we stick to the transpartent swap, we need to change the message +// this scpr sends to the flow. The flow responds with a full swap +// to TRejoin, whereas TRejoin doesn't mean swap - suggesting to +// introduce PDP level msg: TRejoinAndSwap. +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityGoneDown, PDPDeftSCprGoneDown, TPDPFSMMessages::TPDPFSMMessage, PDPSCprStates::CPrimaryPDPGoneDownActivity::NewL) + FIRST_NODEACTIVITY_ENTRY(PDPSCprStates::TAwaitingPDPContextGoneDown, MeshMachine::TActiveOrNoTag) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing, PDPSCprStates::CPrimaryPDPGoneDownActivity::TNoTagOrProviderStopped) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, PDPSCprStates::CPrimaryPDPGoneDownActivity::TStoreOriginalDataClient, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, PDPSCprStates::CPrimaryPDPGoneDownActivity::TRejoinDataClient, CoreNetStates::TAwaitingRejoinDataClientComplete, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, PDPSCprStates::CPrimaryPDPGoneDownActivity::TApplyNewDefault, TAwaitingApplyResponseOrError, MeshMachine::TNoTag) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, PDPSCprStates::CPrimaryPDPGoneDownActivity::TSwitchToNewDefault, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, PDPSCprStates::CPrimaryPDPGoneDownActivity::TStopOriginalDataClient, CoreNetStates::TAwaitingDataClientStopped, MeshMachine::TNoTag) + + LAST_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TClearError) + THROUGH_NODEACTIVITY_ENTRY(KActiveTag, MeshMachine::TDoNothing, PDPSCprStates::TNoTagOrContentionTag) + //Awaiting for contention result, do not stop the start activity. + LAST_NODEACTIVITY_ENTRY(PDPSCprStates::KContentionTag, MeshMachine::TDoNothing) + + LAST_NODEACTIVITY_ENTRY(KNoTag, PDPSCprStates::TCancelDataClientStartInPDP) + + NODEACTIVITY_ENTRY(CoreNetStates::KProviderStopped, CoreNetStates::TStopSelf, CoreNetStates::TAwaitingDataClientStopped, MeshMachine::TTag) + LAST_NODEACTIVITY_ENTRY(CoreNetStates::KProviderStopped, PDPSCprStates::TSendGoneDown) +NODEACTIVITY_END() +} + +namespace PDPDeftSCprClientLeaveActivity +{ //This activity will wait for ECFActivityBinderRequest to complete +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityClientLeave, PDPDeftSCprClientLeave, TNodeSignal::TNullMessageId, MeshMachine::CNodeRetryActivity::NewL) //May be waiting for both messages + NODEACTIVITY_ENTRY(KNoTag, PRStates::TRemoveClientAndSendLeaveCompleteIfRequest, CoreStates::TAwaitingClientLeave, CoreNetStates::TNoTagBlockedByBindToAndNoClients) + LAST_NODEACTIVITY_ENTRY(KNoTag, PDPSCprStates::TSendDataClientIdleIfNoSubconnsAndNoClients) +NODEACTIVITY_END() +} + +namespace PDPDeftSCprIoctlActivity +{ +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityIoctl, PDPDeftSCprIoctl, TNodeSignal::TNullMessageId, MeshMachine::CNodeParallelMessageStoreActivityBase::NewL) + FIRST_NODEACTIVITY_ENTRY(PDPSCprStates::TAwaitingIoctlMessage, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, PDPSCprStates::TRetrieveSipAddr, CoreNetStates::TAwaitingRMessage2Processed, MeshMachine::TNoTag) + LAST_NODEACTIVITY_ENTRY(KNoTag, CoreStates::TPostToOriginators) +NODEACTIVITY_END() +} + +namespace PDPDefSCprActivities +{ +DECLARE_DEFINE_ACTIVITY_MAP(activityMap) + ACTIVITY_MAP_ENTRY(PDPDeftSCprDataClientStartActivity, PDPDeftDataClientStart) + ACTIVITY_MAP_ENTRY(PDPSCprNetworkStatusEventActivity, subConnStatusEvent) + ACTIVITY_MAP_ENTRY(PDPDeftSCprGoneDownActivity, PDPDeftSCprGoneDown) + ACTIVITY_MAP_ENTRY(PDPDeftSCprClientLeaveActivity, PDPDeftSCprClientLeave) + ACTIVITY_MAP_ENTRY(PDPDeftSCprIoctlActivity, PDPDeftSCprIoctl) +ACTIVITY_MAP_END_BASE(PDPSCprActivities, activityMap) +} + +//-========================================================= +// +// CPDPDefaultSubConnectionProvider methods +// +//-========================================================= + +CPDPDefaultSubConnectionProvider::CPDPDefaultSubConnectionProvider(ESock::CSubConnectionProviderFactoryBase& aFactory) + : CPDPSubConnectionProvider(aFactory, PDPDefSCprActivities::activityMap::Self()) + { + LOG_NODE_CREATE1(KPDPSCprSubTag, CPDPDefaultSubConnectionProvider, " [factory=%08x]", &aFactory) + __FLOG_OPEN(KCFNodeTag, KPDPSCprSubTag); + } + +CPDPDefaultSubConnectionProvider::~CPDPDefaultSubConnectionProvider() + { + LOG_NODE_DESTROY(KPDPSCprSubTag, CPDPDefaultSubConnectionProvider) + __FLOG_CLOSE; + } + +CPDPDefaultSubConnectionProvider* CPDPDefaultSubConnectionProvider::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 +*/ + { + CPDPDefaultSubConnectionProvider* ptr = new (ELeave) CPDPDefaultSubConnectionProvider(aFactory); + CleanupStack::PushL(ptr); + ptr->ConstructL(); + CleanupStack::Pop(); + return ptr; + } + +void CPDPDefaultSubConnectionProvider::ConstructL() + { + CPDPSubConnectionProvider::ConstructL(); + iPdpFsmInterface = new (ELeave) CPdpFsmInterface(*this); + } + +void CPDPDefaultSubConnectionProvider::PdpFsmAllContextEvent(TInt aNotification, TInt /*aParam*/) + { + if (aNotification == KNetworkStatusEvent) + { + TPDPFSMMessages::TPDPFSMMessage statusMsg(KNetworkStatusEvent, KErrNone); + TRAP_IGNORE(ReceivedL(TNodeId(Id()), TNodeCtxId(0, Id()), statusMsg)); //TODO - use trap assert? + } + } + +void CPDPDefaultSubConnectionProvider::LinkUp() + { + if (iLinkUps++ == 0) + { + TCFMessage::TStateChange msg(Elements::TStateChange(KLinkLayerOpen, KErrNone)); + //Forward to control clients if there are any + TInt ctrlClientCount = PostToClients(Id(), msg, TClientType(TCFClientType::ECtrl)); + if (0==ctrlClientCount) + { //If there are no control clients any more, forward to the control provider + PostToClients(Id(), msg, TClientType(TCFClientType::ECtrlProvider)); + } + } + } + +void CPDPDefaultSubConnectionProvider::LinkDown(TInt aCause) + { + if (++iLinkDowns-iLinkUps == 0 || iLinkUps == 0) + { + ControlProvider()->PostMessage(Id(), + TCFMessage::TStateChange(Elements::TStateChange(KLinkLayerClosed, aCause)).CRef()); + } + SendDataClientIdleIfNoSubconnsAndNoClientsL(); + } + +void CPDPDefaultSubConnectionProvider::SendDataClientIdleIfNoSubconnsAndNoClientsL() + { + // linkDowns is called more places than linkup, so it may in fact be higher, would be nice if something was + // done in the future to make iLinkDowns and iLinkUps are symettrical + if (iLinkDowns-iLinkUps >= 0 || iLinkUps == 0) + { + if (GetFirstClient(TClientType(TCFClientType::ECtrl|TCFClientType::EAux))==NULL + && GetFirstClient(TClientType(TCFClientType::EData, TCFClientType::EActive)) == NULL) + { + RNodeInterface* cp = ControlProvider(); + if (cp) + { //If there is no Control Provider we probably are an MCPR/Tier Manager/etc + cp->PostMessage(Id(), TCFControlProvider::TIdle().CRef()); + } + return; + } + + RNodeInterface* cc = GetFirstClient(TClientType(TCFClientType::ECtrl)); + if (cc==NULL) + { + TClientIter dciter = GetClientIter( + TClientType( + TCFClientType::EData, + TCFClientType::EActive + |TCFClientType::EActivating + |TCFClientType::EStarted + |TCFClientType::EStarting + |TCFClientType::ELeaving + ) + ); + + TInt i = 0; + RNodeInterface* dc; + while ((dc = dciter[i++]) != NULL) + { + dc->PostMessage(Id(), TCFControlProvider::TIdle().CRef()); + } + } + } + }