# HG changeset patch # User Dremov Kirill (Nokia-D-MSW/Tampere) # Date 1262864093 -7200 # Node ID 21d2ab05f085e043bf962aebe4d97736ba7f8640 # Parent dfb7c4ff071fb7dd41f95ad1e1d4484caa739c8d Revision: 201001 Kit: 201001 diff -r dfb7c4ff071f -r 21d2ab05f085 commsfwsupport/commselements/meshmachine/src/mm_node.cpp --- a/commsfwsupport/commselements/meshmachine/src/mm_node.cpp Thu Dec 17 09:22:25 2009 +0200 +++ b/commsfwsupport/commselements/meshmachine/src/mm_node.cpp Thu Jan 07 13:34:53 2010 +0200 @@ -401,11 +401,12 @@ TBool awoke = ETrue; TInt c = iActivities.Count(); TNodeNullContext context(*this); + //Clean up.. - while (awoke && c > 0) + while (awoke) { awoke = EFalse; - for (TInt i = c - 1 ; i>=0 ; --i) + for (TInt i = iActivities.Count() - 1 ; i>=0 ; --i) { //Signal to waiting activities if: //1) an event was received (& the state has potentialy changed as a result) @@ -414,25 +415,18 @@ //If any signalled activity reacted, the state could change and all other activities need to be signalled again. context.iNodeActivity = iActivities[i]; awoke |= context.iNodeActivity->Signal(context); - if(context.iNodeActivity->IsIdle()) - { - iActivities.Remove(i); - context.iNodeActivity->Destroy(); - context.iNodeActivity = NULL; - // NOTE: if "aContext.iNodeActivity" is the destroy activity, then deleting - // it will destroy the node (i.e. "this") as well, so don't put anything after this line ! - if (c == 1) - { - // c == 1 means that we've just removed the last activity (also means i will be zero) - // i == 0 means that this round of signalling parked activities has been completed - // This is effectively safeguarding the access to iActivities which may or may not be - // there (based on the note above). The destroy activity will always be placed at the - // head of the list, and will therefore be the last to get processed. - return; - } - } } - c = iActivities.Count(); + } + + for (TInt i = iActivities.Count() - 1 ; i>=0 ; --i) + { + context.iNodeActivity = iActivities[i]; + if(context.iNodeActivity->IsIdle()) + { + iActivities.Remove(i); + context.iNodeActivity->Destroy(); + context.iNodeActivity = NULL; + } } } diff -r dfb7c4ff071f -r 21d2ab05f085 commsfwsupport/commselements/serverden/src/sd_workersession.cpp --- a/commsfwsupport/commselements/serverden/src/sd_workersession.cpp Thu Dec 17 09:22:25 2009 +0200 +++ b/commsfwsupport/commselements/serverden/src/sd_workersession.cpp Thu Jan 07 13:34:53 2010 +0200 @@ -694,7 +694,8 @@ EXPORT_C CWorkerSubSession::~CWorkerSubSession() { - COMMONLOG((Session()->WorkerId(),KECommonServerTag, _L8("CWorkerSubSession(%08x):\t~CWorkerSubSession() Session(%08x)"), this, iSession)); + // Session may be disappeared by now, so DO NOT USE IT + COMMONLOG((CommsFW::KInvalidWorkerId, KECommonServerTag, _L8("CWorkerSubSession(%08x):\t~CWorkerSubSession() Session(%08x)"), this, iSession)); //All interfaces must be closed by now (by the derived subsession's destructor the latest) __ASSERT_DEBUG(iApiExtRegister.InterfaceCount() == 0, User::Panic(KSpecAssert_ElemSvrDenWrkrSC, 15)); diff -r dfb7c4ff071f -r 21d2ab05f085 commsfwtools/commstools/svg/parselog.pl --- a/commsfwtools/commstools/svg/parselog.pl Thu Dec 17 09:22:25 2009 +0200 +++ b/commsfwtools/commstools/svg/parselog.pl Thu Jan 07 13:34:53 2010 +0200 @@ -428,17 +428,12 @@ ClearActivity($actAddr); } elsif ($action eq "Abort") { - print "t ", objectName($activityNode{$actAddr}), " (Abort ", $activityName{$actAddr}, ")\n"; + print "t ", objectName($activityNode{$actAddr}), " ($activityName{$actAddr}) Abort()\n"; } - elsif ($action eq "Next->cancel") { - my $tuple = ""; - if (m/\[Triple=([^]]+)\]/) { - $tuple = $1; - print "t ", objectName($activityNode{$actAddr}), " (Cancel $activityName{$actAddr}, $tuple)\n"; - } - else { - print "t ", objectName($activityNode{$actAddr}), " (Cancel ", $activityName{$actAddr}, ")\n"; - } + elsif ($action =~ m/Cancel\(\)/) { + m/iPostedToId ([0-9a-f]{8})/; + my $postedToId = $1; + print "t ", objectName($activityNode{$actAddr}), " ($activityName{$actAddr}) Cancel(). Posted to ", objectName($postedToId), "\n"; } } elsif (($opt_X & 4) == 0 && /UnparkState->unparked\s+\[MNode=0x([0-9a-fA-F]{8})\].*\[Activity=(\w+)\].*\[Triple=(.*?)\]/) diff -r dfb7c4ff071f -r 21d2ab05f085 commsfwtools/preparedefaultcommsdatabase/Tools/ced/inc/dbdef.h --- a/commsfwtools/preparedefaultcommsdatabase/Tools/ced/inc/dbdef.h Thu Dec 17 09:22:25 2009 +0200 +++ b/commsfwtools/preparedefaultcommsdatabase/Tools/ced/inc/dbdef.h Thu Jan 07 13:34:53 2010 +0200 @@ -1335,7 +1335,7 @@ #endif // __COMMDB_ROHID_SUPPORT__ COMMDB_ID, COMMDB_NAME, - VPN_SERVICE_POLICY,VPN_SERVICE_IAP,VPN_SERVICE_NETWORKID, + VPN_SERVICE_POLICY,VPN_SERVICE_IAP,KCDTypeNameVPNSNAPRecord,VPN_SERVICE_NETWORKID, VPN_SERVICE_ENABLE_LLMNR, NO_MORE_RECORDS }; @@ -3022,6 +3022,12 @@ NO_MORE_RECORDS }; #endif //SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY + +const TText* const LINK_REC_VPNSERVICEcolumnArray [] = + { + KCDTypeNameVPNSNAPRecord, + NO_MORE_RECORDS + }; /** This enum is used as index for LinkRecords Arrays @@ -3041,6 +3047,7 @@ ELRAPPrioritySel, ELRTier, #endif //SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY + ELRVPNService, ELRWAPIPBearer }; @@ -3062,6 +3069,7 @@ AP_PRIORITY_SELECTION_POLICY_TABLE, TIER_TABLE, #endif //SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY + VPN_SERVICE, WAP_IP_BEARER, NO_MORE_RECORDS }; @@ -3083,6 +3091,7 @@ (const TText** const)LINK_REC_APPRIORITYSELECTIONPOLICYcolumnArray, (const TText** const)LINK_REC_TIERcolumnArray, #endif //SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY + (const TText** const)LINK_REC_VPNSERVICEcolumnArray, (const TText** const)LINK_REC_WAPIPBEARER_Array }; @@ -3100,10 +3109,11 @@ _S("AccessPointTable"), _S("WLANServiceExtensionTable"), _S("EAPSecuritySettingsTable"), - _S("TunnelledEAPSettingsTable") + _S("TunnelledEAPSettingsTable"), + KCDTypeNameVPNSNAPRecord }; -const TInt LinkedRecordTableNum = 7; +const TInt LinkedRecordTableNum = 8; const TText* const LegacyLinkFields[] = diff -r dfb7c4ff071f -r 21d2ab05f085 commsfwtools/preparedefaultcommsdatabase/Tools/ced/src/database.cpp --- a/commsfwtools/preparedefaultcommsdatabase/Tools/ced/src/database.cpp Thu Dec 17 09:22:25 2009 +0200 +++ b/commsfwtools/preparedefaultcommsdatabase/Tools/ced/src/database.cpp Thu Jan 07 13:34:53 2010 +0200 @@ -1010,6 +1010,9 @@ err = SetLinkedRecord(ELRTier, aPtrField,aColumn,aSetting,aAttribute); break; #endif //SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY + case KCDTIdVPNServiceRecord: + err = SetLinkedRecord(ELRVPNService, aPtrField,aColumn,aSetting,aAttribute); + break; default: ; } diff -r dfb7c4ff071f -r 21d2ab05f085 commsfwtools/preparedefaultcommsdatabase/inc/CommsDatTypeInfoV1_1.h --- a/commsfwtools/preparedefaultcommsdatabase/inc/CommsDatTypeInfoV1_1.h Thu Dec 17 09:22:25 2009 +0200 +++ b/commsfwtools/preparedefaultcommsdatabase/inc/CommsDatTypeInfoV1_1.h Thu Jan 07 13:34:53 2010 +0200 @@ -636,13 +636,15 @@ // FieldTIds - const TMDBElementId KCDTIdVPNPolicyName = 0x05830000; //< Commsdat field id for field: Policy. Policy name. Field is declared in the VPNService table. - const TMDBElementId KCDTIdVPNIAPRecord = 0x05840000; //< Commsdat field id for field: HomeIAP. Link to a IAP record. Field is declared in the VPNService table. - const TMDBElementId KCDTIdVPNNetwork = 0x05850000; //< Commsdat field id for field: HomeNetwork. Link to a Network record. Field is declared in the VPNService table. + const TMDBElementId KCDTIdVPNPolicyName = 0x05830000; ///< Commsdat field id for field: Policy. Policy name. Field is declared in the VPNService table. + const TMDBElementId KCDTIdVPNIAPRecord = 0x05840000; ///< Commsdat field id for field: HomeIAP. Link to a IAP record. Field is declared in the VPNService table. + const TMDBElementId KCDTIdVPNSNAPRecord = 0x05860000; ///< Commsdat field id for field: SNAPIAP. Link to a snap iap record. Field is declared in the VPNService table. + const TMDBElementId KCDTIdVPNNetwork = 0x05850000; ///< Commsdat field id for field: HomeNetwork. Link to a Network record. Field is declared in the VPNService table. #define KCDTypeNameVPNPolicyName _S("Policy") #define KCDTypeNameVPNIAPRecord _S("HomeIAP") + #define KCDTypeNameVPNSNAPRecord _S("HomeSNAP") #define KCDTypeNameVPNNetwork _S("HomeNetwork") diff -r dfb7c4ff071f -r 21d2ab05f085 commsfwtools/preparedefaultcommsdatabase/inc/CommsDatTypesV1_1.h --- a/commsfwtools/preparedefaultcommsdatabase/inc/CommsDatTypesV1_1.h Thu Dec 17 09:22:25 2009 +0200 +++ b/commsfwtools/preparedefaultcommsdatabase/inc/CommsDatTypesV1_1.h Thu Jan 07 13:34:53 2010 +0200 @@ -833,9 +833,10 @@ public: // Member Data - CMDBField iServicePolicy; //< Policy id of the policy file- this is a reference to the policy file. - CMDBRecordLink iServiceIAP; //< Record id of the real IAP used by the IPSEC software to communicate with the VPN gateway. - CMDBRecordLink iServiceNetwork;//< Record id of the real Network to be connected to by the virtual tunnel. + CMDBField iServicePolicy; ///< Policy id of the policy file- this is a reference to the policy file. + CMDBRecordLink iServiceIAP; ///< Record id of the real IAP used by the IPSEC software to communicate with the VPN gateway. + CMDBRecordLink iServiceSNAP; ///< Record id of the SNAP id used by the IPSEC software to communicate with the VPN gateway. + CMDBRecordLink iServiceNetwork;///< Record id of the real Network to be connected to by the virtual tunnel. private: diff -r dfb7c4ff071f -r 21d2ab05f085 commsfwtools/preparedefaultcommsdatabase/src/CommsDatSchema.cpp --- a/commsfwtools/preparedefaultcommsdatabase/src/CommsDatSchema.cpp Thu Dec 17 09:22:25 2009 +0200 +++ b/commsfwtools/preparedefaultcommsdatabase/src/CommsDatSchema.cpp Thu Jan 07 13:34:53 2010 +0200 @@ -451,6 +451,7 @@ // This class { KCDTIdVPNPolicyName, EText, ENotNull, KCDTypeNameVPNPolicyName }, { KCDTIdVPNIAPRecord, ELinkIAPRecord, ENoAttrs, KCDTypeNameVPNIAPRecord }, + { KCDTIdVPNSNAPRecord, ELinkAPRecord, ENoAttrs, KCDTypeNameVPNSNAPRecord }, { KCDTIdVPNNetwork, ELinkNetworkRecord, ENoAttrs, KCDTypeNameVPNNetwork }, /**** add new fields above this comment ****/ // service base class diff -r dfb7c4ff071f -r 21d2ab05f085 commsfwtools/preparedefaultcommsdatabase/src/CommsDatTypesV1_1.cpp --- a/commsfwtools/preparedefaultcommsdatabase/src/CommsDatTypesV1_1.cpp Thu Dec 17 09:22:25 2009 +0200 +++ b/commsfwtools/preparedefaultcommsdatabase/src/CommsDatTypesV1_1.cpp Thu Jan 07 13:34:53 2010 +0200 @@ -811,10 +811,14 @@ X_REGISTER_ATTRIBUTE( CCDVPNServiceRecord, iServicePolicy, TMDBText ) #ifdef SYMBIAN_COMMSDAT_USE_INT_RECORD_LINKS X_REGISTER_ATTRIBUTE( CCDVPNServiceRecord, iServiceIAP, TMDBNum ) + X_REGISTER_ATTRIBUTE( CCDVPNServiceRecord, iServiceSNAP, TMDBNum ) X_REGISTER_ATTRIBUTE( CCDVPNServiceRecord, iServiceNetwork, TMDBNum ) #else X_REGISTER_ATTRIBUTE( CCDVPNServiceRecord, iServiceIAP, TMDBLinkNum ) - X_REGISTER_ATTRIBUTE( CCDVPNServiceRecord, iServiceNetwork, TMDBLinkNum ) +#endif + X_REGISTER_ATTRIBUTE( CCDVPNServiceRecord, iServiceSNAP, TMDBLinkNum ) +#ifndef SYMBIAN_COMMSDAT_USE_INT_RECORD_LINKS + X_REGISTER_ATTRIBUTE( CCDVPNServiceRecord, iServiceNetwork, TMDBLinkNum ) #endif // SYMBIAN_COMMSDAT_USE_INT_RECORD_LINKS END_ATTRIBUTE_TABLE_BASE( CCDServiceRecordBase, KCDTIdServiceRecordBase) diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/CoreProviders/src/corecprstates.cpp --- a/datacommsserver/esockserver/CoreProviders/src/corecprstates.cpp Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/CoreProviders/src/corecprstates.cpp Thu Jan 07 13:34:53 2010 +0200 @@ -21,6 +21,7 @@ @file @internalComponent */ + #define SYMBIAN_NETWORKING_UPS #include @@ -328,13 +329,15 @@ const TCFDataClient::TBindTo& bindToMsg(message_cast(iContext.iMessage)); __ASSERT_DEBUG(!bindToMsg.iNodeId.IsNull(), User::Panic(KCoreCprPanic, KPanicNoServiceProvider)); - activity.iNewServiceProvider = iContext.Node().AddClientL(bindToMsg.iNodeId, - TClientType(TCFClientType::EServProvider, TCFClientType::EActivating)); - //Join the new service provider - iContext.iNodeActivity->PostRequestTo(*activity.iNewServiceProvider, - TCFControlClient::TJoinRequest(iContext.NodeId(), TClientType(TCFClientType::ECtrl), iContext.Node().Priority()).CRef()); + + RNodeInterface* newServiceProvider = iContext.Node().AddClientL(bindToMsg.iNodeId, + TClientType(TCFClientType::EServProvider, TCFClientType::EActivating)); + __ASSERT_DEBUG(newServiceProvider, User::Panic(KCoreCprPanic, KPanicNoServiceProvider)); + activity.iNewServiceProvider = bindToMsg.iNodeId; + //Join the new service provider + activity.PostRequestTo(*newServiceProvider, + TCFControlClient::TJoinRequest(iContext.NodeId(), TClientType(TCFClientType::ECtrl), iContext.Node().Priority()).CRef()); } - } EXPORT_DEFINE_SMELEMENT(THandleDataClientIdle, NetStateMachine::MStateTransition, CprStates::TContext) diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/CoreProviders/src/coremcpractivities.cpp --- a/datacommsserver/esockserver/CoreProviders/src/coremcpractivities.cpp Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/CoreProviders/src/coremcpractivities.cpp Thu Jan 07 13:34:53 2010 +0200 @@ -144,7 +144,7 @@ DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityNoBearer, MCprNoBearer, TCFControlProvider::TNoBearer, PRActivities::CNoBearer::NewL) FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingNoBearer, CNoBearer::TNoTagOrBearerPresentBlockedByNoBearer) NODEACTIVITY_ENTRY(KNoTag, MCprStates::TSelectNextLayer, MCprStates::TAwaitingSelectNextLayerCompleted, CoreNetStates::TNoTagOrBearerPresent) - + //Special for the Meta Plane (don't just copy & paste) NODEACTIVITY_ENTRY(CoreNetStates::KBearerPresent, CoreNetStates::TStartServiceProvider, CoreNetStates::TAwaitingStarted, TTag) NODEACTIVITY_ENTRY(CoreNetStates::KBearerPresent, CoreNetStates::TRequestCommsBinderRetry, CoreNetStates::TAwaitingBinderResponse, TTag) @@ -443,7 +443,7 @@ const TLayerSelectionInfo* selectInfo = static_cast(iContext.Node().AccessPointConfig().FindExtension( STypeId::CreateSTypeId(TLayerSelectionInfo::EUid, TLayerSelectionInfo::ETypeId))); __ASSERT_ALWAYS(selectInfo, CoreMCprPanic(KPanicUnexpectedExecutionPath)); - + TUint selectionPolicyId = selectInfo->CustomSelectionPolicy(); //Running this transition, we can't be at the bottom of the stack! @@ -486,7 +486,7 @@ const TLayerSelectionInfo* selectInfo = static_cast(iContext.Node().AccessPointConfig().FindExtension( STypeId::CreateSTypeId(TLayerSelectionInfo::EUid, TLayerSelectionInfo::ETypeId))); __ASSERT_ALWAYS(selectInfo, CoreMCprPanic(KPanicUnexpectedExecutionPath)); - + TUint selectionPolicyId = selectInfo->SelectionPolicy(); //Running this transition, we can't be at the bottom of the stack! @@ -580,7 +580,7 @@ const TLayerSelectionInfo* selectInfo = static_cast(iContext.Node().AccessPointConfig().FindExtension( STypeId::CreateSTypeId(TLayerSelectionInfo::EUid, TLayerSelectionInfo::ETypeId))); __ASSERT_ALWAYS(selectInfo, CoreMCprPanic(KPanicUnexpectedExecutionPath)); - + TUint selectionPolicyId = selectInfo->CustomSelectionPolicy(); //Running this transition, we can't be at the bottom of the stack! diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/CoreProviders/src/coremcpractivities.cpp.orig --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/datacommsserver/esockserver/CoreProviders/src/coremcpractivities.cpp.orig Thu Jan 07 13:34:53 2010 +0200 @@ -0,0 +1,975 @@ +// 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: +// + +#include "coremcpractivities.h" + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include "ss_internal_activities.h" +#include + +#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_ESockCoreProvcprac, "ESockCrPrvcprac"); +#endif + +#ifdef __CFLOG_ACTIVE + #define KCoreMCprStatesTag KESockMetaConnectionTag + _LIT8(KCoreMCprStatesSubTag, "coremcprstate"); +#endif + +using namespace ESock; +using namespace MCprActivities; +using namespace NetStateMachine; +using namespace PRActivities; +using namespace CorePanics; +using namespace Messages; +using namespace MeshMachine; + + +// +//Panics +void CoreMCprPanic(TInt aCode) + { + _LIT(KCoreMCprPanic, "CoreMCprPanic"); + User::Panic(KCoreMCprPanic, aCode); + } + + +namespace MCprControlClientJoinActivity +{ //This activity needs the activity object (& it can fail on AddClientL, so no point converting) +DECLARE_DEFINE_NODEACTIVITY(ECFActivityClientJoin, MCprControlClientJoin, Messages::TNodeSignal::TNullMessageId) //May be waiting for both messages + FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingControlClientJoin, MeshMachine::TNoTag) + LAST_NODEACTIVITY_ENTRY(KNoTag, MCprStates::TDecrementBlockingDestroyAndAddControlClientAndSendJoinCompleteIfRequest) +NODEACTIVITY_END() +} + +namespace MCprDataClientJoinActivity +{ //This activity needs the activity object (& it can fail on AddClientL, so no point converting) +DECLARE_DEFINE_NODEACTIVITY(ECFActivityDataClientJoin, MCprDataClientJoin, TCFControlProvider::TJoinRequest) + FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingDataClientJoinRequest, MCprStates::TNoTagOrRejoinTag) + LAST_NODEACTIVITY_ENTRY(MCprStates::KRejoinTag, MCprStates::TProcessDataClientRejoin) + LAST_NODEACTIVITY_ENTRY(KNoTag, MCprStates::TDecrementBlockingDestroyAndAddDataClientAndRespond) +NODEACTIVITY_END() +} + +namespace MCprDestroyActivity +{ +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityDestroy, MCprDestroy, Messages::TNodeSignal::TNullMessageId, CoreActivities::CDestroyActivity::New) //May be waiting for both messages + FIRST_NODEACTIVITY_ENTRY(MCprStates::TAwaitingClientLeaveAndNoClients, MeshMachine::TNoTag) + //MCprStates::TProcessClientLeave removes the client and marks the node for deletion. + //If there are no servce providers it also terminates the activity. + //If there are service providers it continues to following triples. + THROUGH_NODEACTIVITY_ENTRY(KNoTag, MCprStates::TProcessClientLeave, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing, MeshMachine::TAwaitingLeaveComplete, CoreActivities::CDestroyActivity::TNoTagOrNoTagBackwards) + LAST_NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendClientLeavingAndRemoveControlProvider) +NODEACTIVITY_END() +} + +namespace MCprSimpleSelectActivity +{ +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivitySelect, MCprSimpleSelect, TCFSelector::TSimpleSelect, CSelectNextLayerActivity::NewL) + //Reply from TAwaitingSelectNextLayer if no choices, otherwise accept + FIRST_NODEACTIVITY_ENTRY(MCprStates::TAwaitingSelectNextLayer, MeshMachine::TNoTag) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, CSelectNextLayerActivity::TProcessSimpleSelectionPolicy, MCprStates::TSelectedProvider) + //Start the selection main loop + NODEACTIVITY_ENTRY(MCprStates::KSelectedProvider, CSelectNextLayerActivity::TFindOrCreateTierManager, MCprStates::TAwaitingTierManagerCreated, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, CSelectNextLayerActivity::TJoinTierManager, CoreStates::TAwaitingJoinComplete, MeshMachine::TNoTag) + //Select next provider and enter the selection internal loop if provider received. Break if SelectComplete(NULL). + NODEACTIVITY_ENTRY(KNoTag, CSelectNextLayerActivity::TSelectNextLayer, MCprStates::TAwaitingSelectComplete, CSelectNextLayerActivity::TNoTagOrSelectedProviderIsNull) + NODEACTIVITY_ENTRY(KNoTag, CSelectNextLayerActivity::TAddProviderInfo, MCprStates::TAwaitingSelectComplete, CSelectNextLayerActivity::TNoTagBackwardsOrJoinServiceProvider) + //Break the selection internal loop if SelectComplete(NULL), otherwise stay in this tripple + NODEACTIVITY_ENTRY(MCprStates::KJoinServiceProvider, CSelectNextLayerActivity::TJoinServiceProvider, CoreStates::TAwaitingJoinComplete, MeshMachine::TNoTag) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, CSelectNextLayerActivity::TSendSelectComplete, CSelectNextLayerActivity::TSelectedProviderIsNullOrJoinServiceProviderBackward) + //Break the selection main loop if no more choices, otherwise go back again + THROUGH_NODEACTIVITY_ENTRY(MCprStates::KSelectedProviderIsNull, CSelectNextLayerActivity::TLeaveTierManager, CSelectNextLayerActivity::TNoTagOrSelectedProviderBackward) + //Finish the activity + LAST_NODEACTIVITY_ENTRY(KNoTag, MCprStates::TSendFinalSelectComplete) +NODEACTIVITY_END() +} + +namespace MCprSimpleSelectActivitySuper +{ +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivitySelect, MCprSimpleSelect, TCFSelector::TSelect, CSelectNextLayerActivity::NewL) + //Reply from TAwaitingSelectNextLayer if no choices, otherwise accept + FIRST_NODEACTIVITY_ENTRY(MCprStates::TAwaitingSelectNextLayerSuper, MeshMachine::TNoTag) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, CSelectNextLayerActivity::TProcessPrioritisedSelectionPolicySuper, MCprStates::TSelectedProvider) + //Start the selection main loop + NODEACTIVITY_ENTRY(MCprStates::KSelectedProvider, CSelectNextLayerActivity::TFindOrCreateTierManagerSuper, MCprStates::TAwaitingTierManagerCreated, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, CSelectNextLayerActivity::TJoinTierManager, CoreStates::TAwaitingJoinComplete, MeshMachine::TNoTag) + //Select next provider and enter the selection internal loop if provider received. Break if SelectComplete(NULL). + NODEACTIVITY_ENTRY(KNoTag, CSelectNextLayerActivity::TSelectNextLayerSuper, MCprStates::TAwaitingSelectComplete, CSelectNextLayerActivity::TNoTagOrSelectedProviderIsNull) + NODEACTIVITY_ENTRY(KNoTag, CSelectNextLayerActivity::TAddProviderInfo, MCprStates::TAwaitingSelectComplete, CSelectNextLayerActivity::TNoTagBackwardsOrJoinServiceProvider) + //Break the selection internal loop if SelectComplete(NULL), otherwise stay in this tripple + NODEACTIVITY_ENTRY(MCprStates::KJoinServiceProvider, CSelectNextLayerActivity::TJoinServiceProvider, CoreStates::TAwaitingJoinComplete, MeshMachine::TNoTag) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, CSelectNextLayerActivity::TSendSelectComplete, CSelectNextLayerActivity::TSelectedProviderIsNullOrJoinServiceProviderBackward) + //Break the selection main loop if no more choices, otherwise go back again + THROUGH_NODEACTIVITY_ENTRY(MCprStates::KSelectedProviderIsNull, CSelectNextLayerActivity::TLeaveTierManager, CSelectNextLayerActivity::TNoTagOrSelectedProviderBackwardSuper) + //Finish the activity + LAST_NODEACTIVITY_ENTRY(KNoTag, MCprStates::TSendFinalSelectComplete) +NODEACTIVITY_END() +} + +namespace MCprNoBearerActivity +{ +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityNoBearer, MCprNoBearer, TCFControlProvider::TNoBearer, PRActivities::CNoBearer::NewL) + FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingNoBearer, CNoBearer::TNoTagOrBearerPresentBlockedByNoBearer) + NODEACTIVITY_ENTRY(KNoTag, MCprStates::TSelectNextLayer, MCprStates::TAwaitingSelectNextLayerCompleted, CoreNetStates::TNoTagOrBearerPresent) + + //Special for the Meta Plane (don't just copy & paste) +// NODEACTIVITY_ENTRY(CoreNetStates::KBearerPresent, CoreNetStates::TStartServiceProvider, CoreNetStates::TAwaitingStarted, TTag) + NODEACTIVITY_ENTRY(CoreNetStates::KBearerPresent, CoreNetStates::TRequestCommsBinderRetry, CoreNetStates::TAwaitingBinderResponse, TTag) + NODEACTIVITY_ENTRY(CoreNetStates::KBearerPresent, CoreNetStates::TSendBindTo, CoreNetStates::TAwaitingBindToComplete, TTag) + THROUGH_NODEACTIVITY_ENTRY(CoreNetStates::KBearerPresent, CoreActivities::ABindingActivity::TSendBindToComplete, MeshMachine::TNoTag) + + LAST_NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendBearer) +NODEACTIVITY_END() +} + +namespace MCprReConnectActivity +{ +//MCprConnectionStartRecovery activity belongs to a group of Error Recovery Activities. +//Error Recovery Activities need to handle their own errors (generated as well as returned). +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityReConnect, MCprReConnect, TCFMcpr::TReConnect, CReConnectActivity::NewL) + FIRST_NODEACTIVITY_ENTRY(MCprStates::TAwaitingReConnectRequest, MeshMachine::TNoTag) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, CReConnectActivity::TProcessReConnectRequest, MeshMachine::TNoTag) + + //Build lower layer + NODEACTIVITY_ENTRY(KNoTag, CReConnectActivity::TBuildLowerLayer, CoreNetStates::TAwaitingBindToComplete, MeshMachine::TNoTag) + + //Respond + LAST_NODEACTIVITY_ENTRY(KNoTag, CReConnectActivity::TSendReConnectResponse) +NODEACTIVITY_END() +} + +namespace MCprErrorRecoveryDefaultActivity +{ +//This is a default error recovery activity. +//It always replies with TErrorRecoveryResponse(EPropagate). +DECLARE_DEFINE_NODEACTIVITY(ECFActivityErrorRecovery, DefaultErrorRecovery, TEErrorRecovery::TErrorRecoveryRequest) + NODEACTIVITY_ENTRY(KNoTag, MCprStates::TSendPropagateRecoveryResponse, MCprStates::TAwaitingErrorRecoveryRequest, MeshMachine::TNoTag) +NODEACTIVITY_END() +} + +namespace MCprBinderRequestActivity +{ +// MCPRs can only have one data client, hence the use of CoreNetStates::TNoTagOrDataClientPresent. +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityBinderRequest, MCprBinderRequest, TCFServiceProvider::TCommsBinderRequest, CCommsBinderActivity::NewL) + FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingBinderRequest, CCommsBinderActivity::TNoTagOrUseExistingBlockedByBinderRequest) + 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, TTag) + + NODEACTIVITY_ENTRY(CoreStates::KUseExisting, CCommsBinderActivity::TSendBinderResponse, CCommsBinderActivity::TAwaitingBindToComplete, MeshMachine::TNoTagOrErrorTag) + LAST_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing) + LAST_NODEACTIVITY_ENTRY(KErrorTag, MeshMachine::TClearError) +NODEACTIVITY_END() +} + +namespace MCprReportProviderStatusActivity +{ +DECLARE_DEFINE_NODEACTIVITY(ECFActivityReportProviderStatus, MCprReportProviderStatus, TCFMcpr::TProviderStatusChangeRegistration) + // for other requests "joining in" + NODEACTIVITY_ENTRY(KNoTag, MCprStates::TProcessProviderStatusChangeRegistration, MeshMachine::TAwaitingAny, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing, CoreNetStates::TAwaitingProviderStatusChangeOrDataClientStatusChange, MCprStates::TDataClientStatusChangeOrNoTag) + // Process the provider status change notification sent from provider on left + THROUGH_NODEACTIVITY_ENTRY(MCprStates::KDataClientStatusChange, PRStates::THandleDataClientStatusChangeAndDestroyOrphans, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, MCprStates::TPostStatusChangeToOriginators, CoreNetStates::TAwaitingProviderStatusChangeOrDataClientStatusChange, MCprStates::TDataClientStatusChangeBackwardsOrNoTagBackwards) + // Never get past this point +NODEACTIVITY_END() +} + +namespace MCprAvailabilityNotificationActivity +{ +// Reference availability notification activity. +// Forwards availability registrations down to lower MCPRs +// Then combines their responses into a single TAvailability object and sends the notification upwards if anything has changed +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityAvailabilityNotification, MCprAvailability, TCFAvailabilityProvider::TAvailabilityNotificationRegistration, CAvailabilityActivity::NewL) + FIRST_NODEACTIVITY_ENTRY(MeshMachine::TAwaitingMessageState, MeshMachine::TNoTag) + + //Select Service Providers (availability sources - if any) + NODEACTIVITY_ENTRY(KNoTag, MCprStates::TSelectNextLayer, MCprStates::TAwaitingSelectNextLayerCompleted, MeshMachine::TNoTagOrErrorTag) + + //Register for notifications with all Service Providers (if any) + NODEACTIVITY_ENTRY(KNoTag, CAvailabilityActivity::TRegisterForNotifications, MCprStates::TAwaitingAvailabilityNotificationOrError, TErrorTagOr >) + + //Process the availability notification and loop (if success, or finish on failure) + NODEACTIVITY_ENTRY(MCprStates::KProcessAvailability, CAvailabilityActivity::TProcessNotification, MCprStates::TAwaitingAvailabilityNotificationOrError, TErrorTagOr >) + + LAST_NODEACTIVITY_ENTRY(KErrorTag, MeshMachine::TRaiseAndClearActivityError) +NODEACTIVITY_END() +} + +// Also if this Message is not expected to be received from the MCpr, we +// manage it. +namespace MCprDataClientGoneDownActivity +{ +DECLARE_DEFINE_NODEACTIVITY(ECFActivityDataClientGoneDown, MCprDataClientGoneDown, TCFControlProvider::TDataClientGoneDown) + // The only thing we do is to clear(unset) the "Flags" of + // the relative DataClient from "EStart": this is done + // in "TAwaitingDataClientGoneDown". + FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingDataClientGoneDown, MeshMachine::TNoTag) + LAST_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing) +NODEACTIVITY_END() +} + +namespace MCprStartActivity +{ +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityStart, MCprStart, TCFServiceProvider::TStart, PRActivities::CStartActivity::NewL) + FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingStart, CoreNetStates::TNoTagOrBearerPresentBlockedByStop) + NODEACTIVITY_ENTRY(KNoTag, MCprStates::TSelectNextLayer, MCprStates::TAwaitingSelectNextLayerCompleted, CoreNetStates::TNoTagOrBearerPresent) + NODEACTIVITY_ENTRY(CoreNetStates::KBearerPresent, CoreNetStates::TBindSelfToPresentBearer, CoreNetStates::TAwaitingBindToComplete, TTag) + + //Start the service provider, use the default cancellation. + //Forward TCancel to the service provider, wait for TStarted or TError (via the Error Activity) + //When TStarted arrives after TCancel the activity will move to the nearest KErrorTag + NODEACTIVITY_ENTRY(CoreNetStates::KBearerPresent, CoreNetStates::TStartServiceProviderRetry, CoreNetStates::TAwaitingStarted, MeshMachine::TNoTagOrErrorTag) + LAST_NODEACTIVITY_ENTRY(KErrorTag, MeshMachine::TDoNothing) + //Start data clients, use the default cancellation. + //Forward TCancel to the self, wait for TCFDataClient::TStarted or TError (via the Error Activity) + //When TCFDataClient::TStarted arrives after TCancel the activity will move to the nearest KErrorTag + NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TStartSelf, CoreNetStates::TAwaitingDataClientStarted, MeshMachine::TNoTagOrErrorTag) + NODEACTIVITY_ENTRY(KErrorTag, CoreNetStates::TStopSelf, CoreNetStates::TAwaitingDataClientStopped, MeshMachine::TErrorTag) + LAST_NODEACTIVITY_ENTRY(KErrorTag, MeshMachine::TDoNothing) + LAST_NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendStarted) +NODEACTIVITY_END() +} + +namespace MCprStopActivity +{ +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityStop, MCprStop, TCFServiceProvider::TStop, MeshMachine::CNodeRetryActivity::NewL) + FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingStop, CoreNetStates::TActiveOrNoTagBlockedByBindTo) + THROUGH_NODEACTIVITY_ENTRY(KActiveTag, CoreNetStates::TCancelDataClientStart, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TStopSelf, CoreNetStates::TAwaitingDataClientStopped, CoreNetStates::TNoTagOrNoBearer) + NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendStop, CoreNetStates::TAwaitingStopped, TTag) + LAST_NODEACTIVITY_ENTRY(CoreNetStates::KNoBearer, PRStates::TSendStoppedAndGoneDown) +NODEACTIVITY_END() +} + +namespace MCprActivities +{ +//This activity map should be used if the MCPR only supports the +//selection message TSelectNextLayerConnPrefList. Nodes using this activity +//map will not support legacy selection +DEFINE_EXPORT_ACTIVITY_MAP(coreMCprActivitiesSuper) + ACTIVITY_MAP_ENTRY(MCprDestroyActivity, MCprDestroy) + ACTIVITY_MAP_ENTRY(MCprSimpleSelectActivitySuper, MCprSimpleSelect) + ACTIVITY_MAP_ENTRY(MCprNoBearerActivity, MCprNoBearer) + ACTIVITY_MAP_ENTRY(MCprReConnectActivity, MCprReConnect) + ACTIVITY_MAP_ENTRY(MCprAvailabilityNotificationActivity, MCprAvailability) + ACTIVITY_MAP_ENTRY(MCprBinderRequestActivity, MCprBinderRequest) + ACTIVITY_MAP_ENTRY(MCprReportProviderStatusActivity, MCprReportProviderStatus) + ACTIVITY_MAP_ENTRY(MCprDataClientJoinActivity, MCprDataClientJoin) + ACTIVITY_MAP_ENTRY(MCprControlClientJoinActivity, MCprControlClientJoin) + ACTIVITY_MAP_ENTRY(MCprErrorRecoveryDefaultActivity, DefaultErrorRecovery) + ACTIVITY_MAP_ENTRY(MCprDataClientGoneDownActivity, MCprDataClientGoneDown) + ACTIVITY_MAP_ENTRY(MCprStopActivity, MCprStop) + ACTIVITY_MAP_ENTRY(MCprStartActivity, MCprStart) +ACTIVITY_MAP_END_BASE(PRActivities, coreActivitiesMCpr) + +//This activiy map supports legacy selection and the additional activity +//is that support. It should be used where tier managers need to support +//selection message TSelectNextLayer +DEFINE_EXPORT_ACTIVITY_MAP(coreMCprActivities) + ACTIVITY_MAP_ENTRY(MCprSimpleSelectActivity, MCprSimpleSelect) +ACTIVITY_MAP_END_BASE(MCprActivities, coreMCprActivitiesSuper) +} + +// +//CSelectNextLayerActivity +EXPORT_C MeshMachine::CNodeActivityBase* CSelectNextLayerActivity::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) + { + CSelectNextLayerActivity* self = new (ELeave) CSelectNextLayerActivity(aActivitySig, aNode); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +EXPORT_C void CSelectNextLayerActivity::ConstructL() + { + iDbs = CommsDat::CMDBSession::NewL(KCDVersion1_2); + + } + +EXPORT_C CSelectNextLayerActivity::~CSelectNextLayerActivity() + { + if (!iTierManager.IsNull()) + { + // Only leave if the iTierManager is still a client - only happens in some + // error cases for example if the Join fails the generic TError handling + // does not call iTierManager.SetNull(), also if AddClientL() leaves. + // TierManager is always a special case because the relationship with + // MCPR is always temporary. + RNodeInterface* client = iNode.FindClient(iTierManager); + if (client) + { + RClientInterface::OpenPostMessageClose(iNode.Id(), iTierManager, TEChild::TLeft().CRef()); + iNode.RemoveClient(iTierManager); + } + iTierManager.SetNull(); + } + delete iDbs; + iSelectCompleteMessages.Close(); + } + +EXPORT_C TConnIdList& CSelectNextLayerActivity::SelectionChoices() + { + return iSelectionChoices; + } + +EXPORT_C ESock::RConnPrefList& CSelectNextLayerActivity::SelectionConnPrefList() + { + return iSelectionConnPrefList; + } + +EXPORT_DEFINE_SMELEMENT(CSelectNextLayerActivity::TNoTagOrSelectedProviderIsNull, NetStateMachine::MStateFork, CSelectNextLayerActivity::TContext) +TInt CSelectNextLayerActivity::TNoTagOrSelectedProviderIsNull::TransitionTag() + { + //We proceede forward through a transision that will process our concrete message received (NULL or not NULL). + TInt tag = MeshMachine::KNoTag | NetStateMachine::EForward; + if (message_cast(iContext.iMessage).iNodeId.IsNull()) + { + tag = MCprStates::KSelectedProviderIsNull | NetStateMachine::EForward; + } + return tag; + } + +EXPORT_DEFINE_SMELEMENT(CSelectNextLayerActivity::TNoTagBackwardsOrJoinServiceProvider, NetStateMachine::MStateFork, CSelectNextLayerActivity::TContext) +TInt CSelectNextLayerActivity::TNoTagBackwardsOrJoinServiceProvider::TransitionTag() + { + TInt tag = MeshMachine::KNoTag | NetStateMachine::EBackward; + if (message_cast(iContext.iMessage).iNodeId.IsNull()) + { + //This is the final select complete that we have received from the selector. + tag = MCprStates::KJoinServiceProvider | NetStateMachine::EForward; + } + return tag; + } + +EXPORT_DEFINE_SMELEMENT(CSelectNextLayerActivity::TSelectedProviderIsNullOrJoinServiceProviderBackward, NetStateMachine::MStateFork, CSelectNextLayerActivity::TContext) +TInt CSelectNextLayerActivity::TSelectedProviderIsNullOrJoinServiceProviderBackward::TransitionTag() + { + __ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity)); + CSelectNextLayerActivity& ac = static_cast(*iContext.iNodeActivity); + if (ac.iSelectCompleteMessages.Count() > 0) + { + return MCprStates::KJoinServiceProvider | NetStateMachine::EBackward; + } + + return MCprStates::KSelectedProviderIsNull | NetStateMachine::EForward; + } + +EXPORT_DEFINE_SMELEMENT(CSelectNextLayerActivity::TNoTagOrSelectedProviderBackward, NetStateMachine::MStateFork, CSelectNextLayerActivity::TContext) +TInt CSelectNextLayerActivity::TNoTagOrSelectedProviderBackward::TransitionTag() + { + __ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity)); + CSelectNextLayerActivity& ac = static_cast(*iContext.iNodeActivity); + if (ac.SelectionChoices().Count() > (ac.iCurrentIndex + 1)) + { + return MCprStates::KSelectedProvider | NetStateMachine::EBackward; + } + + return MeshMachine::KNoTag | NetStateMachine::EForward; + } + +EXPORT_DEFINE_SMELEMENT(CSelectNextLayerActivity::TProcessSimpleSelectionPolicy, NetStateMachine::MStateTransition, CSelectNextLayerActivity::TContext) +void CSelectNextLayerActivity::TProcessSimpleSelectionPolicy::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity)); + CSelectNextLayerActivity& ac = static_cast(*iContext.iNodeActivity); + __ASSERT_DEBUG(ac.SelectionChoices().Count() == 0, User::Panic(KSpecAssert_ESockCoreProvcprac, 1)); //It should be empty + + //We are going to process our own selection policy to determine choices + //for selection of the next layer. + + //This simple transition interprets the selection policy id + //directly as a next layer access point id. + + //This transition is an entry point to the main selection loop which + //will process all the inforamtion gathered in this transition. + //We initialise the current index to start from the beginning of the list + //(next step preincrements). + ac.iCurrentIndex = -1; + + if (iContext.Node().AccessPointConfig().FindExtension(TOverridenSelectionPrefsExt::TypeId())) + { + //Our selection has been overriden by special preferences (so called pass-through + //preference) given to us by our control client. + __CFLOG_VAR((KCoreMCprStatesTag, KCoreMCprStatesSubTag, _L8("TProcessSimpleSelectionPolicy::DoL() - Selection policy overriden!."))); + return; + } + + //Now we can interpret the selection policy and store the results for further + //processing + const TLayerSelectionInfo* selectInfo = static_cast(iContext.Node().AccessPointConfig().FindExtension( + STypeId::CreateSTypeId(TLayerSelectionInfo::EUid, TLayerSelectionInfo::ETypeId))); + __ASSERT_ALWAYS(selectInfo, CoreMCprPanic(KPanicUnexpectedExecutionPath)); + + TUint selectionPolicyId = selectInfo->CustomSelectionPolicy(); + + //Running this transition, we can't be at the bottom of the stack! + __ASSERT_DEBUG(selectionPolicyId, User::Panic(KSpecAssert_ESockCoreProvcprac, 2)); + + //And, of course, for nodes using this transition, it is only one single + //access point below. + ac.SelectionChoices().Append(selectionPolicyId); + } + +EXPORT_DEFINE_SMELEMENT(CSelectNextLayerActivity::TProcessPrioritisedSelectionPolicy, NetStateMachine::MStateTransition, CSelectNextLayerActivity::TContext) +void CSelectNextLayerActivity::TProcessPrioritisedSelectionPolicy::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity)); + CSelectNextLayerActivity& ac = static_cast(*iContext.iNodeActivity); + __ASSERT_DEBUG(ac.SelectionChoices().Count() == 0, User::Panic(KSpecAssert_ESockCoreProvcprac, 3)); //It should be empty + + //We are going to process our own selection policy to determine choices + //for selection of the next layer. + + //This simple transition interprets the selection policy id + //directly as a next layer access point id. + + //This transition is an entry point to the main selection loop which + //will process all the inforamtion gathered in this transition. + //We initialise the current index to start from the beginning of the list + //(next step preincrements). + ac.iCurrentIndex = -1; + + if (iContext.Node().AccessPointConfig().FindExtension(TOverridenSelectionPrefsExt::TypeId())) + { + //Our selection has been overriden by special preferences (so called pass-through + //preference) given to us by our control client. + __CFLOG_VAR((KCoreMCprStatesTag, KCoreMCprStatesSubTag, _L8("TProcessPrioritisedSelectionPolicy::DoL() - Selection policy overriden!."))); + return; + } + + //Now we can interpret the selection policy and store the results for further + //processing + const TLayerSelectionInfo* selectInfo = static_cast(iContext.Node().AccessPointConfig().FindExtension( + STypeId::CreateSTypeId(TLayerSelectionInfo::EUid, TLayerSelectionInfo::ETypeId))); + __ASSERT_ALWAYS(selectInfo, CoreMCprPanic(KPanicUnexpectedExecutionPath)); + + TUint selectionPolicyId = selectInfo->SelectionPolicy(); + + //Running this transition, we can't be at the bottom of the stack! + __ASSERT_DEBUG(selectionPolicyId, User::Panic(KSpecAssert_ESockCoreProvcprac, 4)); + + //And, of course, for nodes using this transition, all of the choices come + //from the simple prioritised selection policy + TierManagerUtils::FillListL(ac.SelectionChoices(),selectionPolicyId,ac.Dbs()); + } + +EXPORT_DEFINE_SMELEMENT(CSelectNextLayerActivity::TFindOrCreateTierManager, NetStateMachine::MStateTransition, CSelectNextLayerActivity::TContext) +void CSelectNextLayerActivity::TFindOrCreateTierManager::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity)); + CSelectNextLayerActivity& ac = static_cast(*iContext.iNodeActivity); + + //Preincrement the current index + ++ac.iCurrentIndex; + + //If we do not have our choices now, this may only mean that our selection + //policy has been overriden by our control client. + TUid tierId; + if (ac.SelectionChoices().Count()) + { + __ASSERT_DEBUG(ac.SelectionChoices().Count() > ac.iCurrentIndex, User::Panic(KSpecAssert_ESockCoreProvcprac, 5)); //Specified choice must be present + __ASSERT_DEBUG(iContext.Node().AccessPointConfig().FindExtension(TOverridenSelectionPrefsExt::TypeId()) == NULL, User::Panic(KSpecAssert_ESockCoreProvcprac, 6)); + tierId = TierManagerUtils::ReadTierIdL(ac.SelectionChoices().Get(ac.iCurrentIndex), ac.Dbs()) ; + } + else + { + //Our policy has been overriden + const TOverridenSelectionPrefsExt& override = static_cast(iContext.Node().AccessPointConfig().FindExtensionL(TOverridenSelectionPrefsExt::TypeId())); + tierId = override.iTierId; + } + + //The tier id must be set now! + __ASSERT_DEBUG(tierId.iUid!=0, User::Panic(KSpecAssert_ESockCoreProvcprac, 7)); + User::LeaveIfError(tierId.iUid!=0? KErrNone : KErrCorrupt); //Check your configuration! + TAlwaysFindFactoryQuery query; + iContext.iNodeActivity->PostRequestTo(SockManGlobals::Get()->GetPlaneFC(TCFPlayerRole(TCFPlayerRole::ETierMgrPlane)), TCFFactory::TFindOrCreatePeer(TCFPlayerRole::ETierMgrPlane, tierId, &query).CRef(), EFalse); + } + +//This is a default implementation of the TSelectNextLayer transition, +//Other mcprs, especially those with custom selection policies may want +//to use their own logic to populate the selection preferences for the next layer. +EXPORT_DEFINE_SMELEMENT(CSelectNextLayerActivity::TSelectNextLayer, NetStateMachine::MStateTransition, CSelectNextLayerActivity::TContext) +void CSelectNextLayerActivity::TSelectNextLayer::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity)); + CSelectNextLayerActivity& ac = static_cast(*iContext.iNodeActivity); + + if (ac.SelectionChoices().Count()) + { + //We use choices derived from our own selection policy + __ASSERT_DEBUG(ac.SelectionChoices().Count() > ac.iCurrentIndex, User::Panic(KSpecAssert_ESockCoreProvcprac, 8)); //Specified choice must be present + __ASSERT_DEBUG(iContext.Node().AccessPointConfig().FindExtension(TOverridenSelectionPrefsExt::TypeId())==NULL, User::Panic(KSpecAssert_ESockCoreProvcprac, 9)); + + TConnIdList list; + list.Append(ac.SelectionChoices().Get(ac.iCurrentIndex)); + + TSelectionPrefs newPrefs; + newPrefs.SetPrefs(list); + + iContext.iNodeActivity->PostRequestTo(ac.iTierManager, TCFSelector::TSimpleSelect(newPrefs).CRef()); + } + else + { + //We have been given preferences for the next layer and we use them here + const TOverridenSelectionPrefsExt& override = static_cast(iContext.Node().AccessPointConfig().FindExtensionL(TOverridenSelectionPrefsExt::TypeId())); + + iContext.iNodeActivity->PostRequestTo(ac.iTierManager, TCFSelector::TSimpleSelect(override.iPrefs).CRef()); + } + } +EXPORT_DEFINE_SMELEMENT(CSelectNextLayerActivity::TProcessSimpleSelectionPolicySuper, NetStateMachine::MStateTransition, CSelectNextLayerActivity::TContext) +void CSelectNextLayerActivity::TProcessSimpleSelectionPolicySuper::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity)); + CSelectNextLayerActivity& ac = static_cast(*iContext.iNodeActivity); + + //We are going to process our own selection policy to determine choices + //for selection of the next layer. + + //This simple transition interprets the selection policy id + //directly as a next layer access point id. + + //This transition is an entry point to the main selection loop which + //will process all the inforamtion gathered in this transition. + + //Now we can interpret the selection policy and store the results for further + //processing + const TLayerSelectionInfo* selectInfo = static_cast(iContext.Node().AccessPointConfig().FindExtension( + STypeId::CreateSTypeId(TLayerSelectionInfo::EUid, TLayerSelectionInfo::ETypeId))); + __ASSERT_ALWAYS(selectInfo, CoreMCprPanic(KPanicUnexpectedExecutionPath)); + + TUint selectionPolicyId = selectInfo->CustomSelectionPolicy(); + + //Running this transition, we can't be at the bottom of the stack! + __ASSERT_DEBUG(selectionPolicyId, User::Panic(KSpecAssert_ESockCoreProvcprac, 10)); + + //And, of course, for nodes using this transition, it is only one single + //access point below. + + //This constructs a TConnAPPref to represent the access point to be created + ac.SelectionConnPrefList() = message_cast(iContext.iMessage).iConnPrefList; + + if (selectionPolicyId != (TUint)CommsDat::CCDAccessPointRecord::KNoPolicy) + { + TConnAPPref* nextAP = TConnAPPref::NewL(selectionPolicyId); + CleanupStack::PushL(nextAP); + ac.SelectionConnPrefList().AppendL(nextAP); + CleanupStack::Pop(); + } + + //The current index is set to the length of the list, this is decremented + //in the next step so the correct tier manager is created (the one + //relating to this access point + } + +EXPORT_DEFINE_SMELEMENT(CSelectNextLayerActivity::TProcessPrioritisedSelectionPolicySuper, NetStateMachine::MStateTransition, CSelectNextLayerActivity::TContext) +void CSelectNextLayerActivity::TProcessPrioritisedSelectionPolicySuper::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity)); + CSelectNextLayerActivity& ac = static_cast(*iContext.iNodeActivity); + + ac.SelectionConnPrefList() = message_cast(iContext.iMessage).iConnPrefList; + + //We are going to process our own selection policy to determine choices + //for selection of the next layer. + + //This simple transition interprets the selection policy id + //directly as a next layer access point id. + + //Now we can interpret the selection policy and store the results for further + //processing + const TLayerSelectionInfo* selectInfo = static_cast(iContext.Node().AccessPointConfig().FindExtension( + STypeId::CreateSTypeId(TLayerSelectionInfo::EUid, TLayerSelectionInfo::ETypeId))); + __ASSERT_ALWAYS(selectInfo, CoreMCprPanic(KPanicUnexpectedExecutionPath)); + TUint selectionPolicyId = selectInfo->SelectionPolicy(); + + //Running this transition, we can't be at the bottom of the stack! + __ASSERT_DEBUG(selectionPolicyId, User::Panic(KSpecAssert_ESockCoreProvcprac, 11)); + + //And, of course, for nodes using this transition, all of the choices come + //from the simple prioritised selection policy + + TierManagerUtils::FillListL(ac.SelectionConnPrefList(),selectionPolicyId,ac.Dbs()); + } + +EXPORT_DEFINE_SMELEMENT(CSelectNextLayerActivity::TFindOrCreateTierManagerSuper, NetStateMachine::MStateTransition, CSelectNextLayerActivity::TContext) +void CSelectNextLayerActivity::TFindOrCreateTierManagerSuper::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity)); + CSelectNextLayerActivity& ac = static_cast(*iContext.iNodeActivity); + + //This takes the first TConnAPPref from the list and creates the tier manager it + //is associated with. + ESock::RConnPrefList::TIter iterAP = ac.SelectionConnPrefList().getIter(); + + __ASSERT_DEBUG(!iterAP.IsEnd(), User::Panic(KSpecAssert_ESockCoreProvcprac, 12)); + + TUid tierId = TierManagerUtils::ReadTierIdL(iterAP->GetAP(), ac.Dbs()) ; + + //The tier id must be set now! + __ASSERT_DEBUG(tierId.iUid!=0, User::Panic(KSpecAssert_ESockCoreProvcprac, 13)); + User::LeaveIfError(tierId.iUid!=0? KErrNone : KErrCorrupt); //Check your configuration! + TAlwaysFindFactoryQuery query; + iContext.iNodeActivity->PostRequestTo(SockManGlobals::Get()->GetPlaneFC( + TCFPlayerRole(TCFPlayerRole::ETierMgrPlane)), + TCFFactory::TFindOrCreatePeer(TCFPlayerRole::ETierMgrPlane, tierId, &query).CRef(), EFalse); + } + + +EXPORT_DEFINE_SMELEMENT(CSelectNextLayerActivity::TSelectNextLayerSuper, NetStateMachine::MStateTransition, CSelectNextLayerActivity::TContext) +void CSelectNextLayerActivity::TSelectNextLayerSuper::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity)); + CSelectNextLayerActivity& ac = static_cast(*iContext.iNodeActivity); + + // We should not have got here if the list is empty + __ASSERT_DEBUG(ac.SelectionConnPrefList().Count() != 0, User::Panic(KSpecAssert_ESockCoreProvcprac, 14)); + + // The handle to the complete list is passed to the tier manager + iContext.iNodeActivity->PostRequestTo(ac.iTierManager, TCFSelector::TSelect(ac.SelectionConnPrefList()).CRef()); + } + +EXPORT_DEFINE_SMELEMENT(CSelectNextLayerActivity::TNoTagOrSelectedProviderBackwardSuper, NetStateMachine::MStateFork, CSelectNextLayerActivity::TContext) +EXPORT_C TInt CSelectNextLayerActivity::TNoTagOrSelectedProviderBackwardSuper::TransitionTag() + { + __ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity)); + CSelectNextLayerActivity& ac = static_cast(*iContext.iNodeActivity); + ESock::RConnPrefList::TIter iterAP = ac.SelectionConnPrefList().getIter(); + + if (!iterAP.IsEnd()) + { + return MCprStates::KSelectedProvider | NetStateMachine::EBackward; + } + + return MeshMachine::KNoTag | NetStateMachine::EForward; + } + +EXPORT_DEFINE_SMELEMENT(CSelectNextLayerActivity::TAddProviderInfo, NetStateMachine::MStateTransition, CSelectNextLayerActivity::TContext) +void CSelectNextLayerActivity::TAddProviderInfo::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity)); + CSelectNextLayerActivity& ac = static_cast(*iContext.iNodeActivity); + + TCFSelector::TSelectComplete& msg = message_cast(iContext.iMessage); + ac.iSelectCompleteMessages.Append(msg); + } + +EXPORT_DEFINE_SMELEMENT(CSelectNextLayerActivity::TJoinTierManager, NetStateMachine::MStateTransition, CSelectNextLayerActivity::TContext) +void CSelectNextLayerActivity::TJoinTierManager::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity)); + CSelectNextLayerActivity& ac = static_cast(*iContext.iNodeActivity); + + ac.iTierManager = message_cast(iContext.iMessage).iNodeId; + __ASSERT_DEBUG(!ac.iTierManager.IsNull(), User::Panic(KSpecAssert_ESockCoreProvcprac, 15)); //Must always be valid. + + //Ensure that the MCPR remains active by adding the lower TierManager as an + //auxiliary client. This is only a temporary association with the TierManager + //in the layer below and is only active for the duration of the select. + //Note that this might leave resulting in ac.iTierManager non-Null in destructor + iContext.Node().AddClientL(ac.iTierManager, TClientType(TCFClientType::EAux)); + ac.PostRequestTo(ac.iTierManager, TCFPeer::TJoinRequest(iContext.NodeId(), TClientType(TCFClientType::ECtrl)).CRef()); + } + +EXPORT_DEFINE_SMELEMENT(CSelectNextLayerActivity::TJoinServiceProvider, NetStateMachine::MStateTransition, MCprStates::TContext) +void CSelectNextLayerActivity::TJoinServiceProvider::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity)); + CSelectNextLayerActivity& ac = static_cast(*iContext.iNodeActivity); + + __ASSERT_DEBUG(ac.iSelectCompleteMessages.Count() > 0, User::Panic(KSpecAssert_ESockCoreProvcprac, 16)); + ESock::TSigSelectComplete& msg = ac.iSelectCompleteMessages[0]; + + //This transition assumes that the first service provider supplied will be the chosen one (EActive denotes 'the' service provider). + TInt flags = 0; + if (iContext.Node().ServiceProvider() == NULL) + { + flags = TCFClientType::EActive; + } + + RNodeInterface* client = iContext.Node().AddClientL(msg.iNodeId, TClientType(TCFClientType::EServProvider, flags), &msg.iProviderInfo); + + iContext.iNodeActivity->PostRequestTo(*client, TCFServiceProvider::TJoinRequest(iContext.NodeId(), TCFClientType::ECtrl).CRef()); + } + +EXPORT_DEFINE_SMELEMENT(CSelectNextLayerActivity::TSendSelectComplete, NetStateMachine::MStateTransition, MCprStates::TContext) +void CSelectNextLayerActivity::TSendSelectComplete::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity)); + CSelectNextLayerActivity& ac = static_cast(*iContext.iNodeActivity); + + __ASSERT_DEBUG(ac.iSelectCompleteMessages.Count() > 0, User::Panic(KSpecAssert_ESockCoreProvcprac, 17)); + ESock::TSigSelectComplete& selectcompletemsg = ac.iSelectCompleteMessages[0]; + iContext.iNodeActivity->PostToOriginators(TCFSelector::TSelectComplete(iContext.iPeer->RecipientId(), selectcompletemsg.iProviderInfo).CRef()); + ac.iSelectCompleteMessages.Remove(0); + } + +EXPORT_DEFINE_SMELEMENT(CSelectNextLayerActivity::TLeaveTierManager, NetStateMachine::MStateTransition, CSelectNextLayerActivity::TContext) +void CSelectNextLayerActivity::TLeaveTierManager::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity)); + CSelectNextLayerActivity& ac = static_cast(*iContext.iNodeActivity); + __ASSERT_DEBUG(!ac.iTierManager.IsNull(), User::Panic(KSpecAssert_ESockCoreProvcprac, 18)); //Must always be valid. + ac.PostRequestTo(ac.iTierManager, TEChild::TLeft().CRef()); + iContext.Node().RemoveClient(ac.iTierManager); + ac.iTierManager.SetNull(); + + } +// +//CReConnectActivity +CReConnectActivity::CReConnectActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) +: MeshMachine::CNodeActivityBase(aActivitySig, aNode) + { + } + +MeshMachine::CNodeActivityBase* CReConnectActivity::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) + { + return new(ELeave)CReConnectActivity(aActivitySig, aNode); + } + +void CReConnectActivity::StartL(TNodeContextBase& aContext, const Messages::XNodePeerId& aOriginator, const TStateTriple& aFirst) + { + //This activity provides service for only one single requestor at a time. + __ASSERT_DEBUG(iOriginators.Count()==0, User::Panic(KSpecAssert_ESockCoreProvcprac, 19)); //Diagnostic panic + User::LeaveIfError(iOriginators.Count()? KErrInUse : KErrNone); + iOriginators.AppendL(aOriginator); + MESH_LOG_CONTEXT_EXT(KESockMeshMachine, aContext, (_L8("CReConnectActivity %08x:\tStartL->starting activity"), this)); + __ASSERT_DEBUG(IsIdle(), User::Panic(KSpecAssert_ESockCoreProvcprac, 20)); + NetStateMachine::ACore::Start(&aContext, aFirst); + MESH_LOG((KESockMeshMachine, _L8("CReConnectActivity %08x:\tStartL->activity started"), this)); + } + +DEFINE_SMELEMENT(CReConnectActivity::TProcessReConnectRequest, NetStateMachine::MStateTransition, CReConnectActivity::TContext) +void CReConnectActivity::TProcessReConnectRequest::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity)); + CReConnectActivity& activity = static_cast(*iContext.iNodeActivity); + TCFMcpr::TReConnect& msg = message_cast(iContext.iMessage); + + activity.iStoppingSP = iContext.Node().FindClientL(msg.iNodeId1); + __ASSERT_DEBUG(activity.iStoppingSP->Type()&TCFClientType::EServProvider, User::Panic(KSpecAssert_ESockCoreProvcprac, 21)); + + activity.iStartingSP = iContext.Node().FindClientL(msg.iNodeId2); + __ASSERT_DEBUG(activity.iStartingSP->Type()&TCFClientType::EServProvider, User::Panic(KSpecAssert_ESockCoreProvcprac, 22)); + } + +DEFINE_SMELEMENT(CReConnectActivity::TBuildLowerLayer, NetStateMachine::MStateTransition, CReConnectActivity::TContext) +void CReConnectActivity::TBuildLowerLayer::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity)); + CReConnectActivity& activity = static_cast(*iContext.iNodeActivity); + + //Post a TBuildLowerLayer to self, initiating building of the new layer below + //Use the new service provider to prime the new layer + __ASSERT_DEBUG(activity.iStartingSP, User::Panic(KSpecAssert_ESockCoreProvcprac, 25)); + iContext.iNodeActivity->PostRequestTo(iContext.NodeId(), TCFDataClient::TBindTo(activity.iStartingSP->RecipientId()).CRef()); + } + + +DEFINE_SMELEMENT(CReConnectActivity::TSendReConnectResponse, NetStateMachine::MStateTransition, CReConnectActivity::TContext) +void CReConnectActivity::TSendReConnectResponse::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity)); + iContext.iNodeActivity->PostToOriginators(TCFMcpr::TReConnectComplete().CRef()); + } + + +// +//CAvailabilityActivity +MeshMachine::CNodeActivityBase* CAvailabilityActivity::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) + { + return new (ELeave) CAvailabilityActivity(aActivitySig, aNode); + } + +CAvailabilityActivity::~CAvailabilityActivity() + { + static_cast(iNode).CancelAvailabilityMonitoring(); + + //Unmark all remaining availability providers + TClientIter iter = iNode.GetClientIter(TClientType(0, TCFClientType::EAvailabilityProvider)); + RNodeInterface* provider = iter++; + while (provider) + { + provider->ClearFlags(TCFClientType::EAvailabilityProvider); + provider = static_cast(iter++); + } + } + +void CAvailabilityActivity::StartL(TNodeContextBase& aContext, const Messages::XNodePeerId& aOriginator, const TStateTriple& aFirst) + { + TCFAvailabilityProvider::TAvailabilityNotificationRegistration& msg = + message_cast(aContext.iMessage); + + CSubscriberInfo* info = new (ELeave) CSubscriberInfo; + const_cast(aOriginator).iInfo = info; + info->SetSubscriptionOptions(msg.iAvailabilitySubscriptionOptions); + CleanupStack::PushL(info); + MeshMachine::CNodeActivityBase::StartL(aContext, aOriginator, aFirst); + CleanupStack::Pop(info); + + if (IsAvailabilityKnown()) + { + info->SetReportedStatus(iCurrentAvailabilityStatus); + aContext.PostToSender(TCFAvailabilityControlClient::TAvailabilityNotification(iCurrentAvailabilityStatus).CRef()); + } + } + +void CAvailabilityActivity::Cancel(TNodeContextBase& aContext) + { + //Post TCancel to all availability providers + iNode.PostToClients(TNodeCtxId(ActivityId(), iNode.Id()), TEBase::TCancel().CRef(), + TClientType(0, TCFClientType::EAvailabilityProvider)); + MeshMachine::CNodeActivityBase::Cancel(aContext); + } + +void CAvailabilityActivity::CalculateCurrentAvailabilityStatus() + { + iCurrentAvailabilityStatus.SetUnknown(); + TClientIter iter = iNode.GetClientIter(TClientType(0, TCFClientType::EAvailabilityProvider)); + RNodeAvailabilityProviderInterface* provider = static_cast(iter++); + __ASSERT_DEBUG(provider, User::Panic(KSpecAssert_ESockCoreProvcprac, 26)); //There must be at least availability provider registered at this stage (or there are no originators == this activity should not run) + while (provider) + { + __ASSERT_DEBUG(provider->Type()&(TCFClientType::EServProvider|TClientType::ERegistrar), User::Panic(KSpecAssert_ESockCoreProvcprac, 27)); + const TAvailabilityStatus& availabilityStatus = provider->AvailabilityStatus(); + if (!availabilityStatus.IsKnown()) + { + //If the immediate response from any of the remaining providers is still in transport, + //set the whole as unknown. + iCurrentAvailabilityStatus.SetUnknown(); + return; + } + else if (availabilityStatus.Score() > iCurrentAvailabilityStatus.Score()) + { + iCurrentAvailabilityStatus.SetScore(availabilityStatus.Score()); + } + provider = static_cast(iter++); + } + } + +TBool CAvailabilityActivity::IsAvailabilityKnown() const + { + return iCurrentAvailabilityStatus.IsKnown(); + } + +void CAvailabilityActivity::NotifyInterestedSubscribers() + { + __ASSERT_DEBUG(IsAvailabilityKnown(), User::Panic(KSpecAssert_ESockCoreProvcprac, 28)); //Use only with known availability! + TCFAvailabilityControlClient::TAvailabilityNotification msg(iCurrentAvailabilityStatus); //KActivityNull will be overriden + + for (TInt i = iOriginators.Count() - 1; i >= 0; --i) + { + XNodePeerId& originator = iOriginators[i]; + CSubscriberInfo* info = static_cast(originator.iInfo); + __ASSERT_DEBUG(info, User::Panic(KSpecAssert_ESockCoreProvcprac, 29)); + + if (!info->ReportedStatus().IsKnown() + || info->SubscriptionOptions().IsChangeSignificant(info->ReportedStatus(), iCurrentAvailabilityStatus)) + { + info->SetReportedStatus(iCurrentAvailabilityStatus); + originator.PostMessage(TNodeCtxId(ActivityId(), iNode.Id()), msg); + } + } + } + +void CAvailabilityActivity::RegisterForNotifications(TClientIterBase& aClientIter) const + { + RNodeAvailabilityProviderInterface* provider = static_cast(aClientIter++); + + //We can ignore the fact that tere is no service providers we can register with, provided + //the node has ensured there are some other availability providers! + //If there are no service nor other availability providers the condition is serious. + //__ASSERT_ALWAYS is required as the verified conditions are of a run time nature + __ASSERT_ALWAYS(provider!=NULL || iNode.CountClients(TClientType(0, TCFClientType::EAvailabilityProvider))>0, + CoreMCprPanic(KPanicNoAvailabilityProvider)); + + TAvailabilitySubscriptionOptions subscriptionOptions; //By default register for all notifications - may need to be modified in the future + TCFAvailabilityProvider::TAvailabilityNotificationRegistration msg(subscriptionOptions); + + //Iterate through service providers if any, setting EAvailabilityProvider flags + while (provider) + { + provider->SetFlags(TCFClientType::EAvailabilityProvider); + provider->PostMessage(TNodeCtxId(ActivityId(), iNode.Id()), msg); + provider = static_cast(aClientIter++); + } + } + +DEFINE_SMELEMENT(CAvailabilityActivity::TRegisterForNotifications, NetStateMachine::MStateTransition, CAvailabilityActivity::TContext) +void CAvailabilityActivity::TRegisterForNotifications::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity)); + CAvailabilityActivity& activity = static_cast(*iContext.iNodeActivity); + + //Start monitoring on the node if necessary + iContext.Node().StartAvailabilityMonitoringL(TNodeCtxId(iContext.ActivityId(), iContext.NodeId())); + + TClientIter iter = iContext.Node().GetClientIter(TClientType(TCFClientType::EServProvider)); + activity.RegisterForNotifications(iter); + } + +DEFINE_SMELEMENT(CAvailabilityActivity::TProcessNotification, NetStateMachine::MStateTransition, CAvailabilityActivity::TContext) +void CAvailabilityActivity::TProcessNotification::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity)); + CAvailabilityActivity& activity = static_cast(*iContext.iNodeActivity); + + //Register with any new service providers (if any) == not with EAvailabilityProvider(s) + TClientIter iter = iContext.Node().GetClientIter(TClientType(TCFClientType::EServProvider), TClientType(0, TCFClientType::EAvailabilityProvider)); + activity.RegisterForNotifications(iter); + + //Now the iPeer must be set (and we need to have the RNodeAvailabilityProviderInterface behind it) + __ASSERT_DEBUG(iContext.iPeer, User::Panic(KSpecAssert_ESockCoreProvcprac, 30)); + TCFAvailabilityControlClient::TAvailabilityNotification& msg = message_cast(iContext.iMessage); + + //RNodeAvailabilityProviderInterface stores information (on this node) about the availability provider + RNodeAvailabilityProviderInterface* provider = static_cast(iContext.iPeer); + __ASSERT_DEBUG(provider->Flags()&TCFClientType::EAvailabilityProvider, User::Panic(KSpecAssert_ESockCoreProvcprac, 31)); + provider->SetAvailabilityStatus(msg.iAvailabilityStatus); + + //Compute the overal availability and report if known already + activity.CalculateCurrentAvailabilityStatus(); + if (activity.IsAvailabilityKnown()) + { + activity.NotifyInterestedSubscribers(); + } + } + diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/CoreProviders/src/coretiernotificationstates.cpp --- a/datacommsserver/esockserver/CoreProviders/src/coretiernotificationstates.cpp Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/CoreProviders/src/coretiernotificationstates.cpp Thu Jan 07 13:34:53 2010 +0200 @@ -110,7 +110,7 @@ EXPORT_DEFINE_SMELEMENT(TAwaitingCancelOrErrorOrDestroy, NetStateMachine::MState, TierNotification::TContext) EXPORT_C TBool TAwaitingCancelOrErrorOrDestroy::Accept() { - return( iContext.iMessage.IsMessage() || + return( ( iContext.iMessage.IsMessage() && iContext.Activity()->FindOriginator(iContext.iSender) != KErrNotFound ) || iContext.iMessage.IsMessage() || iContext.iMessage.IsMessage() ); } diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/MobilityCoreProviders/inc/mobilitymcpractivities.h --- a/datacommsserver/esockserver/MobilityCoreProviders/inc/mobilitymcpractivities.h Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/MobilityCoreProviders/inc/mobilitymcpractivities.h Thu Jan 07 13:34:53 2010 +0200 @@ -1,9 +1,9 @@ // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). // All rights reserved. // This component and the accompanying materials are made available -// under the terms of the License "Symbian Foundation License v1.0" +// under the terms of "Eclipse Public License v1.0" // which accompanies this distribution, and is available -// at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html". +// at the URL "http://www.eclipse.org/legal/epl-v10.html". // // Initial Contributors: // Nokia Corporation - initial contribution. @@ -12,7 +12,7 @@ // // Description: // Mobility Meta Connection Provider Activities -// +// // /** @@ -38,7 +38,7 @@ DECLARE_EXPORT_ACTIVITY_MAP(mobilityMCprActivities) -/////////////////////////////////////////////////////////////////////////////// +// //CMobilityActivity class CMobilityActivity : public MeshMachine::CNodeRetryActivity { @@ -49,7 +49,7 @@ CMobilityActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode); virtual ~CMobilityActivity(); typedef MeshMachine::TNodeContext TContext; - + private: TBool EvaluatePreference(TContext& aContext); void SetHandshakingFlag(); @@ -57,33 +57,28 @@ private: ESock::RMetaServiceProviderInterface* iCurrent; - ESock::RMetaServiceProviderInterface* iAvailable; - ESock::RMetaServiceProviderInterface* iCandidate; + ESock::RMetaServiceProviderInterface* iPreferred; const TUint iAvailabilityScoreTreshold; public: - + DECLARE_SMELEMENT_HEADER(TAwaitingCurrentCarrierRejectedOrAvailabilityChange, MeshMachine::TState, NetStateMachine::MState, TContext) virtual TBool Accept(); DECLARE_SMELEMENT_FOOTER(TAwaitingCurrentCarrierRejectedOrAvailabilityChange) - + DECLARE_SMELEMENT_HEADER(TNoTagOrAwaitMobility, MeshMachine::TStateFork, NetStateMachine::MStateFork, CMobilityActivity::TContext) virtual TInt TransitionTag(); - DECLARE_SMELEMENT_FOOTER(TNoTagOrAwaitMobility) - - DECLARE_SMELEMENT_HEADER(TNoTagOrReConnectOrStartMobilityHandshakeBackwards, MeshMachine::TStateFork, NetStateMachine::MStateFork, CMobilityActivity::TContext) - virtual TInt TransitionTag(); - DECLARE_SMELEMENT_FOOTER(TNoTagOrReConnectOrStartMobilityHandshakeBackwards) + DECLARE_SMELEMENT_FOOTER(TNoTagOrAwaitMobility) DECLARE_SMELEMENT_HEADER(TNoTagOrStartMobilityHandshakeBackwards, MeshMachine::TStateFork, NetStateMachine::MStateFork, CMobilityActivity::TContext) virtual TInt TransitionTag(); DECLARE_SMELEMENT_FOOTER(TNoTagOrStartMobilityHandshakeBackwards) - + DECLARE_SMELEMENT_HEADER(TNoTagOrAwaitMobilityBackwardsOnMobilityTrigger, MeshMachine::TStateFork, NetStateMachine::MStateFork, CMobilityActivity::TContext) virtual TInt TransitionTag(); DECLARE_SMELEMENT_FOOTER(TNoTagOrAwaitMobilityBackwardsOnMobilityTrigger) - + DECLARE_SMELEMENT_HEADER(TClearHandshakingFlag, MeshMachine::TStateTransition, NetStateMachine::MStateTransition, CMobilityActivity::TContext) virtual void DoL(); DECLARE_SMELEMENT_FOOTER(TClearHandshakingFlag) @@ -121,7 +116,7 @@ ) }; -/////////////////////////////////////////////////////////////////////////////// +// //CConnectionRecoveryActivity class CConnectionRecoveryActivity : public MeshMachine::CNodeRetryActivity { diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/MobilityCoreProviders/inc/mobilitymcpractivities.h.orig --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/datacommsserver/esockserver/MobilityCoreProviders/inc/mobilitymcpractivities.h.orig Thu Jan 07 13:34:53 2010 +0200 @@ -0,0 +1,180 @@ +// Copyright (c) 2007-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: +// Mobility Meta Connection Provider Activities +// +// + +/** + @file + @internalComponent +*/ + + +#ifndef MOBILITYMCPRACTIVITIES_H +#define MOBILITYMCPRACTIVITIES_H + +#include +#include +#include + +enum TMobilityMCprActivities + { + ECFActivityMCprMobility = ESock::ECFActivityCustom + 1, + }; + +namespace MobilityMCprActivities +{ +DECLARE_EXPORT_ACTIVITY_MAP(mobilityMCprActivities) + + +// +//CMobilityActivity +class CMobilityActivity : public MeshMachine::CNodeRetryActivity + { +public: + static MeshMachine::CNodeActivityBase* NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode); + +protected: + CMobilityActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode); + virtual ~CMobilityActivity(); + typedef MeshMachine::TNodeContext TContext; + +private: + TBool EvaluatePreference(TContext& aContext); + void SetHandshakingFlag(); + void ClearHandshakingFlag(); + +private: + ESock::RMetaServiceProviderInterface* iCurrent; + ESock::RMetaServiceProviderInterface* iPreferred; + const TUint iAvailabilityScoreTreshold; + + +public: + + DECLARE_SMELEMENT_HEADER(TAwaitingCurrentCarrierRejectedOrAvailabilityChange, MeshMachine::TState, NetStateMachine::MState, TContext) + virtual TBool Accept(); + DECLARE_SMELEMENT_FOOTER(TAwaitingCurrentCarrierRejectedOrAvailabilityChange) + + DECLARE_SMELEMENT_HEADER(TNoTagOrAwaitMobility, MeshMachine::TStateFork, NetStateMachine::MStateFork, CMobilityActivity::TContext) + virtual TInt TransitionTag(); + DECLARE_SMELEMENT_FOOTER(TNoTagOrAwaitMobility) + + DECLARE_SMELEMENT_HEADER(TNoTagOrStartMobilityHandshakeBackwards, MeshMachine::TStateFork, NetStateMachine::MStateFork, CMobilityActivity::TContext) + virtual TInt TransitionTag(); + DECLARE_SMELEMENT_FOOTER(TNoTagOrStartMobilityHandshakeBackwards) + + DECLARE_SMELEMENT_HEADER(TNoTagOrAwaitMobilityBackwardsOnMobilityTrigger, MeshMachine::TStateFork, NetStateMachine::MStateFork, CMobilityActivity::TContext) + virtual TInt TransitionTag(); + DECLARE_SMELEMENT_FOOTER(TNoTagOrAwaitMobilityBackwardsOnMobilityTrigger) + + DECLARE_SMELEMENT_HEADER(TClearHandshakingFlag, MeshMachine::TStateTransition, NetStateMachine::MStateTransition, CMobilityActivity::TContext) + virtual void DoL(); + DECLARE_SMELEMENT_FOOTER(TClearHandshakingFlag) + + DECLARE_SMELEMENT_HEADER(TSendAvailabilityRequest, MeshMachine::TStateTransition, NetStateMachine::MStateTransition, CMobilityActivity::TContext) + virtual void DoL(); + DECLARE_SMELEMENT_FOOTER(TSendAvailabilityRequest) + + DECLARE_SMELEMENT_HEADER(TInformMigrationAvailableAndSetHandshakingFlag, MeshMachine::TStateTransition, NetStateMachine::MStateTransition, CMobilityActivity::TContext) + virtual void DoL(); + DECLARE_SMELEMENT_FOOTER(TInformMigrationAvailableAndSetHandshakingFlag) + + // For the moment it is sufficient to use the re-connect activity, in the future we may want to + // customise the behavior, for example start the new layer before rebinding it, etc. + DECLARE_SMELEMENT_HEADER(TRequestReConnect, MeshMachine::TStateTransition, NetStateMachine::MStateTransition, CMobilityActivity::TContext) + virtual void DoL(); + DECLARE_SMELEMENT_FOOTER(TRequestReConnect) + + DECLARE_SMELEMENT_HEADER(TInformMigrationCompleted, MeshMachine::TStateTransition, NetStateMachine::MStateTransition, CMobilityActivity::TContext) + virtual void DoL(); + DECLARE_SMELEMENT_FOOTER(TInformMigrationCompleted) + + typedef MeshMachine::TActivitiesIdMutex TActivityErrorRecoveryMutex; + DECLARE_SERIALIZABLE_STATE( + TNoTagOrAwaitMobilityBackwardsOnMobilityTriggerBlockedByErrorRecovery, + TActivityErrorRecoveryMutex, + TNoTagOrAwaitMobilityBackwardsOnMobilityTrigger + ) + + DECLARE_SERIALIZABLE_STATE( + TNoTagOrAwaitMobilityBlockedByErrorRecovery, + TActivityErrorRecoveryMutex, + TNoTagOrAwaitMobility + ) + }; + +// +//CConnectionRecoveryActivity +class CConnectionRecoveryActivity : public MeshMachine::CNodeRetryActivity + { +public: + static MeshMachine::CNodeActivityBase* NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode); + void ReplyToOriginators(Messages::TEErrorRecovery::TErrorRecoveryResponse& aCFMessageSig); + +protected: + CConnectionRecoveryActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode); + +public: + Messages::TErrContext iOriginalErrContext; //Error context on which this activity started + +protected: + typedef MeshMachine::TNodeContext TContext; + +public: + DECLARE_SMELEMENT_HEADER(TAwaitingReConnectComplete, MeshMachine::TState, NetStateMachine::MState, TContext) + virtual TBool Accept(); + DECLARE_SMELEMENT_FOOTER(TAwaitingReConnectComplete) + + class TTransitionBase : public MeshMachine::TStateTransition + { + public: + TTransitionBase(TContext& aContext) + : MeshMachine::TStateTransition(aContext) + { + } + + virtual void Error(TInt aError); + }; + + DECLARE_SMELEMENT_HEADER(TStoreErrorContext, CConnectionRecoveryActivity::TTransitionBase, NetStateMachine::MStateTransition, TContext) + virtual void DoL(); + DECLARE_SMELEMENT_FOOTER(TStoreErrorContext) + + DECLARE_SMELEMENT_HEADER(TProcessConnectionStartRecoveryRequest, CConnectionRecoveryActivity::TTransitionBase, NetStateMachine::MStateTransition, TContext) + virtual void DoL(); + DECLARE_SMELEMENT_FOOTER(TProcessConnectionStartRecoveryRequest) + + DECLARE_SMELEMENT_HEADER(TProcessConnectionGoneDownRecoveryRequest, CConnectionRecoveryActivity::TTransitionBase, NetStateMachine::MStateTransition, TContext) + virtual void DoL(); + DECLARE_SMELEMENT_FOOTER(TProcessConnectionGoneDownRecoveryRequest) + + DECLARE_SMELEMENT_HEADER(TSendRetryRecoveryResponse, CConnectionRecoveryActivity::TTransitionBase, NetStateMachine::MStateTransition, TContext) + virtual void DoL(); + DECLARE_SMELEMENT_FOOTER(TSendRetryRecoveryResponse) + + DECLARE_SMELEMENT_HEADER(TSendPropagateRecoveryResponse, CConnectionRecoveryActivity::TTransitionBase, NetStateMachine::MStateTransition, TContext) + virtual void DoL(); + DECLARE_SMELEMENT_FOOTER(TSendPropagateRecoveryResponse) + + DECLARE_SMELEMENT_HEADER(TSendIgnoreRecoveryResponse, CConnectionRecoveryActivity::TTransitionBase, NetStateMachine::MStateTransition, TContext) + virtual void DoL(); + DECLARE_SMELEMENT_FOOTER(TSendIgnoreRecoveryResponse) + }; + +} // namespace MobilityMCprActivities + +#endif // MOBILITYMCPRACTIVITIES_H + diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/MobilityCoreProviders/inc/mobilitymcpractivities.h.rej --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/datacommsserver/esockserver/MobilityCoreProviders/inc/mobilitymcpractivities.h.rej Thu Jan 07 13:34:53 2010 +0200 @@ -0,0 +1,176 @@ +*************** +*** 9,21 **** + // Nokia Corporation - initial contribution. + // + // Contributors: + // + // Description: + // Mobility Meta Connection Provider Activities +- // + // + + /** + @file + @internalComponent + */ +--- 9,21 ---- + // Nokia Corporation - initial contribution. + // + // Contributors: + // + // Description: + // Mobility Meta Connection Provider Activities ++ // + // + + /** + @file + @internalComponent + */ +*************** +*** 46,92 **** + static MeshMachine::CNodeActivityBase* NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode); + + protected: + CMobilityActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode); + virtual ~CMobilityActivity(); + typedef MeshMachine::TNodeContext TContext; +- + private: + TBool EvaluatePreference(TContext& aContext); + void SetHandshakingFlag(); + void ClearHandshakingFlag(); + + private: + ESock::RMetaServiceProviderInterface* iCurrent; +- ESock::RMetaServiceProviderInterface* iAvailable; +- ESock::RMetaServiceProviderInterface* iCandidate; + const TUint iAvailabilityScoreTreshold; + + + public: +- + DECLARE_SMELEMENT_HEADER(TAwaitingCurrentCarrierRejectedOrAvailabilityChange, MeshMachine::TState, NetStateMachine::MState, TContext) + virtual TBool Accept(); + DECLARE_SMELEMENT_FOOTER(TAwaitingCurrentCarrierRejectedOrAvailabilityChange) +- + DECLARE_SMELEMENT_HEADER(TNoTagOrAwaitMobility, MeshMachine::TStateFork, NetStateMachine::MStateFork, CMobilityActivity::TContext) + virtual TInt TransitionTag(); +- DECLARE_SMELEMENT_FOOTER(TNoTagOrAwaitMobility) + +- DECLARE_SMELEMENT_HEADER(TNoTagOrReConnectOrStartMobilityHandshakeBackwards, MeshMachine::TStateFork, NetStateMachine::MStateFork, CMobilityActivity::TContext) +- virtual TInt TransitionTag(); +- DECLARE_SMELEMENT_FOOTER(TNoTagOrReConnectOrStartMobilityHandshakeBackwards) +- + DECLARE_SMELEMENT_HEADER(TNoTagOrStartMobilityHandshakeBackwards, MeshMachine::TStateFork, NetStateMachine::MStateFork, CMobilityActivity::TContext) + virtual TInt TransitionTag(); + DECLARE_SMELEMENT_FOOTER(TNoTagOrStartMobilityHandshakeBackwards) +- + DECLARE_SMELEMENT_HEADER(TNoTagOrAwaitMobilityBackwardsOnMobilityTrigger, MeshMachine::TStateFork, NetStateMachine::MStateFork, CMobilityActivity::TContext) + virtual TInt TransitionTag(); + DECLARE_SMELEMENT_FOOTER(TNoTagOrAwaitMobilityBackwardsOnMobilityTrigger) +- + DECLARE_SMELEMENT_HEADER(TClearHandshakingFlag, MeshMachine::TStateTransition, NetStateMachine::MStateTransition, CMobilityActivity::TContext) + virtual void DoL(); + DECLARE_SMELEMENT_FOOTER(TClearHandshakingFlag) + + DECLARE_SMELEMENT_HEADER(TSendAvailabilityRequest, MeshMachine::TStateTransition, NetStateMachine::MStateTransition, CMobilityActivity::TContext) + virtual void DoL(); +--- 46,87 ---- + static MeshMachine::CNodeActivityBase* NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode); + + protected: + CMobilityActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode); + virtual ~CMobilityActivity(); + typedef MeshMachine::TNodeContext TContext; ++ + private: + TBool EvaluatePreference(TContext& aContext); + void SetHandshakingFlag(); + void ClearHandshakingFlag(); + + private: + ESock::RMetaServiceProviderInterface* iCurrent; ++ ESock::RMetaServiceProviderInterface* iPreferred; + const TUint iAvailabilityScoreTreshold; + + + public: ++ + DECLARE_SMELEMENT_HEADER(TAwaitingCurrentCarrierRejectedOrAvailabilityChange, MeshMachine::TState, NetStateMachine::MState, TContext) + virtual TBool Accept(); + DECLARE_SMELEMENT_FOOTER(TAwaitingCurrentCarrierRejectedOrAvailabilityChange) ++ + DECLARE_SMELEMENT_HEADER(TNoTagOrAwaitMobility, MeshMachine::TStateFork, NetStateMachine::MStateFork, CMobilityActivity::TContext) + virtual TInt TransitionTag(); ++ DECLARE_SMELEMENT_FOOTER(TNoTagOrAwaitMobility) + + DECLARE_SMELEMENT_HEADER(TNoTagOrStartMobilityHandshakeBackwards, MeshMachine::TStateFork, NetStateMachine::MStateFork, CMobilityActivity::TContext) + virtual TInt TransitionTag(); + DECLARE_SMELEMENT_FOOTER(TNoTagOrStartMobilityHandshakeBackwards) ++ + DECLARE_SMELEMENT_HEADER(TNoTagOrAwaitMobilityBackwardsOnMobilityTrigger, MeshMachine::TStateFork, NetStateMachine::MStateFork, CMobilityActivity::TContext) + virtual TInt TransitionTag(); + DECLARE_SMELEMENT_FOOTER(TNoTagOrAwaitMobilityBackwardsOnMobilityTrigger) ++ + DECLARE_SMELEMENT_HEADER(TClearHandshakingFlag, MeshMachine::TStateTransition, NetStateMachine::MStateTransition, CMobilityActivity::TContext) + virtual void DoL(); + DECLARE_SMELEMENT_FOOTER(TClearHandshakingFlag) + + DECLARE_SMELEMENT_HEADER(TSendAvailabilityRequest, MeshMachine::TStateTransition, NetStateMachine::MStateTransition, CMobilityActivity::TContext) + virtual void DoL(); +*************** +*** 102,127 **** + virtual void DoL(); + DECLARE_SMELEMENT_FOOTER(TRequestReConnect) + + DECLARE_SMELEMENT_HEADER(TInformMigrationCompleted, MeshMachine::TStateTransition, NetStateMachine::MStateTransition, CMobilityActivity::TContext) + virtual void DoL(); + DECLARE_SMELEMENT_FOOTER(TInformMigrationCompleted) +- +- typedef MeshMachine::TActivitiesIdMutex TActivityErrorRecoveryMutex; + DECLARE_SERIALIZABLE_STATE( + TNoTagOrAwaitMobilityBackwardsOnMobilityTriggerBlockedByErrorRecovery, + TActivityErrorRecoveryMutex, + TNoTagOrAwaitMobilityBackwardsOnMobilityTrigger +- ) +- + DECLARE_SERIALIZABLE_STATE( + TNoTagOrAwaitMobilityBlockedByErrorRecovery, + TActivityErrorRecoveryMutex, + TNoTagOrAwaitMobility +- ) + }; + + /////////////////////////////////////////////////////////////////////////////// + //CConnectionRecoveryActivity + class CConnectionRecoveryActivity : public MeshMachine::CNodeRetryActivity + { +--- 97,122 ---- + virtual void DoL(); + DECLARE_SMELEMENT_FOOTER(TRequestReConnect) + + DECLARE_SMELEMENT_HEADER(TInformMigrationCompleted, MeshMachine::TStateTransition, NetStateMachine::MStateTransition, CMobilityActivity::TContext) + virtual void DoL(); + DECLARE_SMELEMENT_FOOTER(TInformMigrationCompleted) ++ ++ typedef MeshMachine::TActivitiesIdMutex TActivityErrorRecoveryMutex; + DECLARE_SERIALIZABLE_STATE( + TNoTagOrAwaitMobilityBackwardsOnMobilityTriggerBlockedByErrorRecovery, + TActivityErrorRecoveryMutex, + TNoTagOrAwaitMobilityBackwardsOnMobilityTrigger ++ ) ++ + DECLARE_SERIALIZABLE_STATE( + TNoTagOrAwaitMobilityBlockedByErrorRecovery, + TActivityErrorRecoveryMutex, + TNoTagOrAwaitMobility ++ ) + }; + + /////////////////////////////////////////////////////////////////////////////// + //CConnectionRecoveryActivity + class CConnectionRecoveryActivity : public MeshMachine::CNodeRetryActivity + { diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/MobilityCoreProviders/inc/mobilitymcprstates.h --- a/datacommsserver/esockserver/MobilityCoreProviders/inc/mobilitymcprstates.h Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/MobilityCoreProviders/inc/mobilitymcprstates.h Thu Jan 07 13:34:53 2010 +0200 @@ -1,9 +1,9 @@ // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). // All rights reserved. // This component and the accompanying materials are made available -// under the terms of the License "Symbian Foundation License v1.0" +// under the terms of "Eclipse Public License v1.0" // which accompanies this distribution, and is available -// at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html". +// at the URL "http://www.eclipse.org/legal/epl-v10.html". // // Initial Contributors: // Nokia Corporation - initial contribution. @@ -12,7 +12,7 @@ // // Description: // Mobility Meta Connection Provider States -// +// // /** @@ -39,9 +39,9 @@ // //-========================================================= -const TInt KStartMobilityHandshake = 10000; +const TInt KStartMobilityHandshake = 10000; const TInt KAwaitMobility = 10001; -const TInt KReConnect = 10002; + //-========================================================= // diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/MobilityCoreProviders/inc/mobilitymcprstates.h.orig --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/datacommsserver/esockserver/MobilityCoreProviders/inc/mobilitymcprstates.h.orig Thu Jan 07 13:34:53 2010 +0200 @@ -0,0 +1,117 @@ +// Copyright (c) 2007-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: +// Mobility Meta Connection Provider States +// +// + +/** + @file + @internalComponent +*/ + + +#ifndef MOBILITYMCPRSTATES_H +#define MOBILITYMCPRSTATES_H + +#include +#include +#include + +namespace MobilityMCprStates +{ + +typedef MeshMachine::TNodeContext TContext; + +//-========================================================= +// +//Core Mobile Meta Connection Provider Transition Ids 10000..11000 +// +//-========================================================= + +const TInt KStartMobilityHandshake = 10000; +const TInt KAwaitMobility = 10001; +const TInt KReConnect = 10002; + +//-========================================================= +// +//Mutexes +// +//-========================================================= + +//This mutex blocks when the mobility is handshaking on the node +class THandshakingMobilityMutex + { +public: + static TBool IsBlocked(MeshMachine::TNodeContextBase& aContext); + }; + +//-========================================================= +// +//States +// +//-========================================================= + +DECLARE_SMELEMENT_HEADER(TAwaitingStartMobility, MeshMachine::TState, NetStateMachine::MState, TContext) + virtual TBool Accept(); +DECLARE_SMELEMENT_FOOTER(TAwaitingStartMobility) + +/** + Mobility base state implementing generic cancellation behaviour. +*/ +class TStateBase : public MeshMachine::TState + { +public: + explicit TStateBase(TContext& aContext) : MeshMachine::TState(aContext) + { + } + virtual void Cancel(); + }; + +DECLARE_SMELEMENT_HEADER(TAwaitingMigrationRequestedOrRejected, MobilityMCprStates::TStateBase, NetStateMachine::MState, TContext) + virtual TBool Accept(); +DECLARE_SMELEMENT_FOOTER(TAwaitingMigrationRequestedOrRejected) + +DECLARE_SMELEMENT_HEADER(TAwaitingMigrationAcceptedOrRejected, MobilityMCprStates::TStateBase, NetStateMachine::MState, TContext) + virtual TBool Accept(); +DECLARE_SMELEMENT_FOOTER(TAwaitingMigrationAcceptedOrRejected) + +//-========================================================= +// +//State Forks +// +//-========================================================= +DECLARE_SMELEMENT_HEADER(TNoTagOrErrorTagIfMobilityRunning, MeshMachine::TStateFork, NetStateMachine::MStateFork, TContext) + virtual TInt TransitionTag(); +DECLARE_SMELEMENT_FOOTER(TNoTagOrErrorTagIfMobilityRunning) + +DECLARE_SERIALIZABLE_STATE( + TNoTagBlockedByMobilityHandshaking, + THandshakingMobilityMutex, + MeshMachine::TNoTag + ) + +//-========================================================= +// +//Transitions +// +//-========================================================= + +DECLARE_SMELEMENT_HEADER(TReplyMobilityStarted, MeshMachine::TStateTransition, NetStateMachine::MStateTransition, TContext) + virtual void DoL(); +DECLARE_SMELEMENT_FOOTER(TReplyMobilityStarted) + +} //namespace MobilityMCprStates + +#endif // MOBILITYMCPRSTATES_H + diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/MobilityCoreProviders/src/mobilitymcpractivities.cpp --- a/datacommsserver/esockserver/MobilityCoreProviders/src/mobilitymcpractivities.cpp Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/MobilityCoreProviders/src/mobilitymcpractivities.cpp Thu Jan 07 13:34:53 2010 +0200 @@ -1,9 +1,9 @@ // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). // All rights reserved. // This component and the accompanying materials are made available -// under the terms of the License "Symbian Foundation License v1.0" +// under the terms of "Eclipse Public License v1.0" // which accompanies this distribution, and is available -// at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html". +// at the URL "http://www.eclipse.org/legal/epl-v10.html". // // Initial Contributors: // Nokia Corporation - initial contribution. @@ -16,10 +16,10 @@ #include #include #include "mobilitymcpractivities.h" -#include "mobilitymcprstates.h" -#include "ss_nodemessages_selector.h" -#include "ss_nodemessages_mobility.h" -#include "ss_nodemessages_availability.h" +#include +#include +#include +#include #include @@ -43,7 +43,7 @@ using namespace Messages; using namespace MeshMachine; -/////////////////////////////////////////////////////////////////////////////// +// //Panics #ifdef _DEBUG _LIT (KCoreMobileMCprPanic,"CoreMobileMCprPanic"); @@ -87,7 +87,7 @@ //if it sees that the availability notification has influcenced what the currently preffered bearer should be. THROUGH_NODEACTIVITY_ENTRY(KNoTag, CMobilityActivity::TSendAvailabilityRequest, MeshMachine::TTag) - // MAIN LOOP **************** + // MAIN LOOP **************** //The main mobility handshake loop. The loop is executed when performing migration from one service provider to another. //The entry condition for the loop is that: //- upgrade: a better then current access point is now available (a better access point reported available) @@ -97,21 +97,21 @@ // NOTE: if the current bearer ceases to be available completely (goes down), then this will be assisted by an error recovery request; // NOTE: This tuple doesn't actually do (b), i.e.: assumes the threshold of '1' (in 0..100 availability score range) //Before awaitng for availability change or rejection by the client (TAwaitingCurrentCarrierRejectedOrAvailabilityChange), the activity - //first checks (TNoTagOrAwaitMobilityBlockedByErrorRecovery) if the availability has changed since it last checked - //(availability could have been reported amidst the previous handshake loop) + //first checks (TNoTagOrAwaitMobilityBlockedByErrorRecovery) if the availability has changed since it last checked + //(availability could have been reported amidst the previous handshake loop) THROUGH_NODEACTIVITY_ENTRY(MobilityMCprStates::KStartMobilityHandshake, CMobilityActivity::TClearHandshakingFlag, CMobilityActivity::TNoTagOrAwaitMobilityBlockedByErrorRecovery) NODEACTIVITY_ENTRY(MobilityMCprStates::KAwaitMobility, MeshMachine::TDoNothing, CMobilityActivity::TAwaitingCurrentCarrierRejectedOrAvailabilityChange, CMobilityActivity::TNoTagOrAwaitMobilityBackwardsOnMobilityTriggerBlockedByErrorRecovery) - //Mobility has been triggered ((a) or (b)). Start mobility handshake (set handshaking flag and inform the client about the preferred bearer) - NODEACTIVITY_ENTRY(KNoTag, CMobilityActivity::TInformMigrationAvailableAndSetHandshakingFlag, MobilityMCprStates::TAwaitingMigrationRequestedOrRejected, CMobilityActivity::TNoTagOrReConnectOrStartMobilityHandshakeBackwards) - //The client accepts the new access point. + //Mobility has been triggered ((a) or (b)). Start mobility handshake (set handshaking flag and inform the client about the preferred bearer) + NODEACTIVITY_ENTRY(KNoTag, CMobilityActivity::TInformMigrationAvailableAndSetHandshakingFlag, MobilityMCprStates::TAwaitingMigrationRequestedOrRejected, CMobilityActivity::TNoTagOrStartMobilityHandshakeBackwards) + //The client accepts the new access point. //For the moment it is sufficient to use the re-connect activity, in the future we may want to //customise the behavior, for example start the new layer before rebinding it, etc. //Should rebinding fail, the mobility activity will be set to an error mode. The error mode will be cleared if //there are other bearers this activity can offer. If there aren't the data client will be errored. - NODEACTIVITY_ENTRY(MobilityMCprStates::KReConnect, CMobilityActivity::TRequestReConnect, MCprStates::TAwaitingReConnectCompleteOrError, CMobilityActivity::TNoTagOrStartMobilityHandshakeBackwards) + NODEACTIVITY_ENTRY(KNoTag, CMobilityActivity::TRequestReConnect, MCprStates::TAwaitingReConnectCompleteOrError, CMobilityActivity::TNoTagOrStartMobilityHandshakeBackwards) //Rebinding has been successful. As far as MCPR is concerned, the mobility is finished, but the MCPR must await - //for the handshake (accept|reject) before it can offer another bearer. + //for the handshake (accept|reject) before it can offer another bearer. NODEACTIVITY_ENTRY(KNoTag, CMobilityActivity::TInformMigrationCompleted, MobilityMCprStates::TAwaitingMigrationAcceptedOrRejected, MeshMachine::TTag) NODEACTIVITY_END() } @@ -164,7 +164,7 @@ ACTIVITY_MAP_END_BASE(MCprActivities, coreMCprActivities) } -/////////////////////////////////////////////////////////////////////////////// +// // CMobilityActivity MeshMachine::CNodeActivityBase* MobilityMCprActivities::CMobilityActivity::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) { @@ -210,12 +210,11 @@ // - current bearer rejected; // - proposed bearer rejected; // - failure to migrate to the proposed bearer; - lastRejected = iAvailable ? iAvailable : - static_cast(aContext.Node().ServiceProvider()); + lastRejected = iPreferred ? iPreferred : + static_cast(aContext.Node().ServiceProvider()); } - - iCandidate = iAvailable; - iAvailable = NULL; //Do not remember rejected candidate any longer + + iPreferred = NULL; //Do not remember rejected candidate any longer while ((candidate = static_cast(iter++)) != NULL) { const TAvailabilityStatus& status = candidate->AvailabilityStatus(); @@ -230,8 +229,7 @@ if (status.Score() > iAvailabilityScoreTreshold && candidate!=lastRejected) { - if (candidate==aContext.Node().ServiceProvider() - && Error() == KErrNone ) + if (candidate->Flags() & TCFClientType::EStarted) { //The preferred one is the current one, is still available and was not just rejected. //No need to do anything more. @@ -239,7 +237,7 @@ } //A new match found - iAvailable = candidate; + iPreferred = candidate; return ETrue; } } @@ -258,22 +256,6 @@ static_cast(iNode).iIsHandshakingNow = EFalse; } -DEFINE_SMELEMENT(CMobilityActivity::TNoTagOrReConnectOrStartMobilityHandshakeBackwards, NetStateMachine::MStateFork, CMobilityActivity::TContext) -TInt CMobilityActivity::TNoTagOrReConnectOrStartMobilityHandshakeBackwards::TransitionTag() - { - if (iContext.Activity()->Error() == KErrNone && - (message_cast(&iContext.iMessage) || - message_cast(&iContext.iMessage))) - { - CMobilityActivity& activity = static_cast(*iContext.iNodeActivity); - if( activity.iCurrent!=activity.iAvailable ) - return MobilityMCprStates::KReConnect | NetStateMachine::EForward; - else - return MeshMachine::KNoTag | NetStateMachine::EForward; - } - return MobilityMCprStates::KStartMobilityHandshake | NetStateMachine::EBackward; - } - DEFINE_SMELEMENT(CMobilityActivity::TNoTagOrStartMobilityHandshakeBackwards, NetStateMachine::MStateFork, CMobilityActivity::TContext) TInt CMobilityActivity::TNoTagOrStartMobilityHandshakeBackwards::TransitionTag() { @@ -281,7 +263,7 @@ (message_cast(&iContext.iMessage) || message_cast(&iContext.iMessage))) { - return MeshMachine::KNoTag | NetStateMachine::EForward; + return MeshMachine::KNoTag | NetStateMachine::EForward; } return MobilityMCprStates::KStartMobilityHandshake | NetStateMachine::EBackward; } @@ -290,13 +272,13 @@ TInt CMobilityActivity::TNoTagOrAwaitMobilityBackwardsOnMobilityTrigger::TransitionTag() { //This is where the judgement is made on whether to trigger mobility (offer the client another bearer) - //or ignore and come back waiting. + //or ignore and come back waiting. __ASSERT_DEBUG(iContext.iMessage.IsMessage() || - iContext.iMessage.IsMessage(), + iContext.iMessage.IsMessage(), User::Panic(KCoreMobileMCprPanic, KPanicIncorrectMessage)); - __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity)); + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity)); CMobilityActivity& activity = static_cast(*iContext.iNodeActivity); - + if (activity.EvaluatePreference(iContext)) { activity.SetError(KErrNone); @@ -313,9 +295,9 @@ DEFINE_SMELEMENT(CMobilityActivity::TNoTagOrAwaitMobility, NetStateMachine::MStateFork, CMobilityActivity::TContext) TInt CMobilityActivity::TNoTagOrAwaitMobility::TransitionTag() { - __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity)); + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity)); CMobilityActivity& activity = static_cast(*iContext.iNodeActivity); - + if (activity.EvaluatePreference(iContext)) { activity.SetError(KErrNone); @@ -350,41 +332,26 @@ //Inform the CPR that a potential migration is available. We only support a single data client //in this implementation. - __ASSERT_DEBUG(activity.iAvailable, User::Panic(KCoreMobileMCprPanic, KPanicNoServiceProvider)); + __ASSERT_DEBUG(activity.iPreferred, User::Panic(KCoreMobileMCprPanic, KPanicNoServiceProvider)); //Compute all this here to keep EvaluatePreference() as fast as possible - activity.iCurrent = static_cast(iContext.Node().ServiceProvider()); + activity.iCurrent = static_cast(iContext.Node().GetFirstClient(TClientType(TCFClientType::EServProvider, TCFClientType::EStarted))); __ASSERT_DEBUG(activity.iCurrent, User::Panic(KCoreMobileMCprPanic, KPanicNoServiceProvider)); //Perform a simple check if this is an upgrade or not TClientIter iter = iContext.Node().GetClientIter(TClientType(TCFClientType::EServProvider)); RNodeInterface* sp = iter++; - while (sp && sp!=activity.iCurrent && sp!=activity.iAvailable) + while (sp && sp!=activity.iCurrent && sp!=activity.iPreferred) { sp = iter++; } TBool isUpgrade = (sp != activity.iCurrent); //If current was found first -> this is not an upgrade - if( activity.iCurrent == activity.iAvailable && activity.iCandidate ) - { - // The available client is the same as the current and a candidate exists, this indicates that - // an error has occured when trying to start the candidate bearer and the control as reverted to - // the current bearer. In this situation the notification needs to look as if the bearer has - // migrated from the failed candidate to the current bearer. - TCFMobilityControlClient::TMigrationNotification msg(activity.iCandidate->ProviderInfo().APId(), - activity.iAvailable->ProviderInfo().APId(), - isUpgrade, EFalse); - activity.PostToOriginators(msg); - } - else - { - // Standard case where migration is going from current to available. - TCFMobilityControlClient::TMigrationNotification msg(activity.iCurrent->ProviderInfo().APId(), - activity.iAvailable->ProviderInfo().APId(), - isUpgrade, EFalse); - activity.PostToOriginators(msg); - } + TCFMobilityControlClient::TMigrationNotification msg(activity.iCurrent->ProviderInfo().APId(), + activity.iPreferred->ProviderInfo().APId(), + isUpgrade, EFalse); + activity.PostToOriginators(msg); activity.ClearPostedTo(); activity.SetHandshakingFlag(); } @@ -408,13 +375,13 @@ __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity)); CMobilityActivity& activity = static_cast(*iContext.iNodeActivity); - __ASSERT_DEBUG(activity.iAvailable, User::Panic(KCoreMobileMCprPanic, KPanicNoServiceProvider)); + __ASSERT_DEBUG(activity.iPreferred, User::Panic(KCoreMobileMCprPanic, KPanicNoServiceProvider)); __ASSERT_DEBUG(activity.iCurrent, User::Panic(KCoreMobileMCprPanic, KPanicNoServiceProvider)); - __ASSERT_DEBUG(activity.iCurrent!=activity.iAvailable, User::Panic(KSpecAssert_ESockMbCrMCPRAct, 1)); + __ASSERT_DEBUG(activity.iCurrent!=activity.iPreferred, User::Panic(KSpecAssert_ESockMbCrMCPRAct, 1)); // For the moment it is sufficient to use the re-connect activity, in the future we may want to // customise the behavior, for example start the new layer before rebinding it, etc. - TCFMcpr::TReConnect msg(activity.iCurrent->RecipientId(), activity.iAvailable->RecipientId()); + TCFMcpr::TReConnect msg(activity.iCurrent->RecipientId(), activity.iPreferred->RecipientId()); activity.PostRequestTo(iContext.NodeId(), msg); } @@ -435,7 +402,7 @@ } -/////////////////////////////////////////////////////////////////////////////// +// //CConnectionRecoveryActivity MeshMachine::CNodeActivityBase* CConnectionRecoveryActivity::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) { @@ -501,26 +468,27 @@ void CConnectionRecoveryActivity::TProcessConnectionStartRecoveryRequest::DoL() { __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity)); - RNodeInterface* newSP = NULL; - RNodeInterface* curSP = iContext.Node().ServiceProvider(); //Our current started Service Provider. + RNodeInterface* startingSP = NULL; + RNodeInterface* stoppingSP = NULL; //Choose Service Providers to work on TClientIter iter = iContext.Node().GetClientIter(TClientType(TCFClientType::EServProvider)); RNodeInterface* itf = NULL; - for (itf = iter++; itf!=NULL && newSP==NULL; itf = iter++) + for (itf = iter++; itf!=NULL && stoppingSP==NULL; itf = iter++) { - if (itf==curSP) + if (itf->Flags() & TCFClientType::EStarted) { - newSP = iter++; //And the new one to try next + stoppingSP = itf; //Our current started Service Provider. + startingSP = iter++; //And the new one to try next } } //Sanity check. //The new provider must not be started, there can be only one started at a time. - __ASSERT_DEBUG(newSP==NULL || (newSP->Flags() & TCFClientType::EStarted)==0, User::Panic(KSpecAssert_ESockMbCrMCPRAct, 3)); + __ASSERT_DEBUG(startingSP==NULL || (startingSP->Flags() & TCFClientType::EStarted)==0, User::Panic(KSpecAssert_ESockMbCrMCPRAct, 3)); //If there is no other Service Provider to try, return KErrNotFound - if (newSP==NULL || curSP == NULL) + if (startingSP==NULL || stoppingSP == NULL) { #ifdef __CFLOG_ACTIVE __CFLOG_VAR((KCoreMCprStatesTag, KCoreMCprStatesSubTag, _L8("WARNING: CConnectionRecoveryActivity::TProcessConnectionStartRecoveryRequest::DoL() - no more choices, abandoning recovery."))); @@ -531,7 +499,7 @@ //Diagnostinc - there must be a data client or we cannot be here __ASSERT_DEBUG(iContext.Node().GetFirstClient(TClientType(TCFClientType::EData)), User::Panic(KCoreMobileMCprPanic, KPanicNoDataClient)); iContext.iNodeActivity->PostRequestTo(iContext.NodeId(), - TCFMcpr::TReConnect(curSP->RecipientId(), newSP->RecipientId()).CRef()); + TCFMcpr::TReConnect(stoppingSP->RecipientId(), startingSP->RecipientId()).CRef()); } DEFINE_SMELEMENT(CConnectionRecoveryActivity::TProcessConnectionGoneDownRecoveryRequest, NetStateMachine::MStateTransition, CConnectionRecoveryActivity::TContext) @@ -540,7 +508,7 @@ __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity)); CConnectionRecoveryActivity& activity = static_cast(*iContext.iNodeActivity); - RNodeInterface* started = iContext.Node().ServiceProvider(); + RNodeInterface* started = iContext.Node().GetFirstClient(TClientType(TCFClientType::EServProvider, TCFClientType::EStarted)); TUint apId = (TUint)activity.iOriginalErrContext.iInfo; RNodeInterface* gonedownsp = iContext.Node().FindServiceProvider(apId); if (started && started != gonedownsp) diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/MobilityCoreProviders/src/mobilitymcpractivities.cpp.orig --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/datacommsserver/esockserver/MobilityCoreProviders/src/mobilitymcpractivities.cpp.orig Thu Jan 07 13:34:53 2010 +0200 @@ -0,0 +1,586 @@ +// Copyright (c) 2007-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 +#include +#include "mobilitymcpractivities.h" +#include +#include +#include +#include +#include + + +#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_ESockMbCrMCPRAct, "ESockMbCrMCPRAct"); +#endif + +#ifdef __CFLOG_ACTIVE + #define KCoreMCprStatesTag KESockMetaConnectionTag + _LIT8(KCoreMCprStatesSubTag, "coremcprstate"); +#endif + +using namespace ESock; +using namespace CorePanics; +using namespace MCprStates; +using namespace NetStateMachine; +using namespace MCprActivities; +using namespace MobilityMCprActivities; +using namespace Messages; +using namespace MeshMachine; + +// +//Panics +#ifdef _DEBUG +_LIT (KCoreMobileMCprPanic,"CoreMobileMCprPanic"); +#endif + +namespace MobilityMCprPrioritisedSelectActivity +{ +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivitySelect, MCprPrioritisedSelect, TCFSelector::TSimpleSelect, CSelectNextLayerActivity::NewL) + //Reply from TAwaitingSelectNextLayer if no choices, otherwise accept + FIRST_NODEACTIVITY_ENTRY(MCprStates::TAwaitingSelectNextLayer, MeshMachine::TNoTag) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, CSelectNextLayerActivity::TProcessPrioritisedSelectionPolicy, MCprStates::TSelectedProvider) + //Start the selection main loop + NODEACTIVITY_ENTRY(MCprStates::KSelectedProvider, CSelectNextLayerActivity::TFindOrCreateTierManager, MCprStates::TAwaitingTierManagerCreated, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, CSelectNextLayerActivity::TJoinTierManager, CoreStates::TAwaitingJoinComplete, MeshMachine::TNoTag) + //Select next provider and enter the selection internal loop if provider received. Break if SelectComplete(NULL). + NODEACTIVITY_ENTRY(KNoTag, CSelectNextLayerActivity::TSelectNextLayer, MCprStates::TAwaitingSelectComplete, CSelectNextLayerActivity::TNoTagOrSelectedProviderIsNull) + NODEACTIVITY_ENTRY(KNoTag, CSelectNextLayerActivity::TAddProviderInfo, MCprStates::TAwaitingSelectComplete, CSelectNextLayerActivity::TNoTagBackwardsOrJoinServiceProvider) + //Break the selection internal loop if SelectComplete(NULL), otherwise stay in this tripple + NODEACTIVITY_ENTRY(MCprStates::KJoinServiceProvider, CSelectNextLayerActivity::TJoinServiceProvider, CoreStates::TAwaitingJoinComplete, MeshMachine::TNoTag) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, CSelectNextLayerActivity::TSendSelectComplete, CSelectNextLayerActivity::TSelectedProviderIsNullOrJoinServiceProviderBackward) + //Break the selection main loop if no more choices, otherwise go back again + THROUGH_NODEACTIVITY_ENTRY(MCprStates::KSelectedProviderIsNull, CSelectNextLayerActivity::TLeaveTierManager, CSelectNextLayerActivity::TNoTagOrSelectedProviderBackward) + //Finish the activity + LAST_NODEACTIVITY_ENTRY(KNoTag, MCprStates::TSendFinalSelectComplete) +NODEACTIVITY_END() +} + +namespace MobilityMCprMobilityActivity +{ +//This activity monitors availability status on this node +//NOTE: This activity assumes there is only one data client (Cpr) of this MCpr! +//NOTE: This activity can only be executed in the context of CMobilityMetaConnectionProvider (or derived) +//NOTE: TError may come from the availability activity only. It is handled by the ECFActivityError. +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityMCprMobility, MCprMobility, TCFMobilityProvider::TStartMobility, MobilityMCprActivities::CMobilityActivity::NewL) + //The activity only makes sense after the startup sequence completed on this layer + FIRST_NODEACTIVITY_ENTRY(MobilityMCprStates::TAwaitingStartMobility, MeshMachine::TNoTag/*BlockedByNoServiceProviderStarted*/) + //Report to the client that we have successfully started + THROUGH_NODEACTIVITY_ENTRY(KNoTag, MobilityMCprStates::TReplyMobilityStarted, MeshMachine::TNoTag) + //Register with self for availability notifications. Self will report _any_ availabilty change (even available->available) back to + //this activity. This activity can trigger mobility (see CMobilityActivity::TNoTagOrErrorTagOrStartMobilityHandshakeBackwardsOnMobilityTriggerBlockedByErrorRecovery) + //if it sees that the availability notification has influcenced what the currently preffered bearer should be. + THROUGH_NODEACTIVITY_ENTRY(KNoTag, CMobilityActivity::TSendAvailabilityRequest, MeshMachine::TTag) + + // MAIN LOOP **************** + //The main mobility handshake loop. The loop is executed when performing migration from one service provider to another. + //The entry condition for the loop is that: + //- upgrade: a better then current access point is now available (a better access point reported available) + //- downgrade: + // (a) the current access point is being rejected by the client (e.g.: the current access point doesn't seem to route traffic where required) + // (b) the current access point ceases to be available (reports availability below reasonable threshold). + // NOTE: if the current bearer ceases to be available completely (goes down), then this will be assisted by an error recovery request; + // NOTE: This tuple doesn't actually do (b), i.e.: assumes the threshold of '1' (in 0..100 availability score range) + //Before awaitng for availability change or rejection by the client (TAwaitingCurrentCarrierRejectedOrAvailabilityChange), the activity + //first checks (TNoTagOrAwaitMobilityBlockedByErrorRecovery) if the availability has changed since it last checked + //(availability could have been reported amidst the previous handshake loop) + THROUGH_NODEACTIVITY_ENTRY(MobilityMCprStates::KStartMobilityHandshake, CMobilityActivity::TClearHandshakingFlag, CMobilityActivity::TNoTagOrAwaitMobilityBlockedByErrorRecovery) + NODEACTIVITY_ENTRY(MobilityMCprStates::KAwaitMobility, MeshMachine::TDoNothing, CMobilityActivity::TAwaitingCurrentCarrierRejectedOrAvailabilityChange, CMobilityActivity::TNoTagOrAwaitMobilityBackwardsOnMobilityTriggerBlockedByErrorRecovery) + + //Mobility has been triggered ((a) or (b)). Start mobility handshake (set handshaking flag and inform the client about the preferred bearer) + NODEACTIVITY_ENTRY(KNoTag, CMobilityActivity::TInformMigrationAvailableAndSetHandshakingFlag, MobilityMCprStates::TAwaitingMigrationRequestedOrRejected, CMobilityActivity::TNoTagOrReConnectOrStartMobilityHandshakeBackwards) + //The client accepts the new access point. + //For the moment it is sufficient to use the re-connect activity, in the future we may want to + //customise the behavior, for example start the new layer before rebinding it, etc. + //Should rebinding fail, the mobility activity will be set to an error mode. The error mode will be cleared if + //there are other bearers this activity can offer. If there aren't the data client will be errored. + NODEACTIVITY_ENTRY(MobilityMCprStates::KReConnect, CMobilityActivity::TRequestReConnect, MCprStates::TAwaitingReConnectCompleteOrError, CMobilityActivity::TNoTagOrStartMobilityHandshakeBackwards) + //Rebinding has been successful. As far as MCPR is concerned, the mobility is finished, but the MCPR must await + //for the handshake (accept|reject) before it can offer another bearer. + NODEACTIVITY_ENTRY(KNoTag, CMobilityActivity::TInformMigrationCompleted, MobilityMCprStates::TAwaitingMigrationAcceptedOrRejected, MeshMachine::TTag) +NODEACTIVITY_END() +} + +namespace MCprConnectionStartRecoveryActivity +{ +//MCprConnectionStartRecovery activity belongs to a group of Error Recovery Activities. +//Error Recovery Activities need to handle their own errors (generated as well as returned). + +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityConnectionStartRecovery, MCprConnectionStartRecovery, TEErrorRecovery::TErrorRecoveryRequest, CConnectionRecoveryActivity::NewL) + FIRST_NODEACTIVITY_ENTRY(MCprStates::TAwaitingConnectionStartRecoveryRequest, MobilityMCprStates::TNoTagOrErrorTagIfMobilityRunning) + LAST_NODEACTIVITY_ENTRY(KErrorTag, CConnectionRecoveryActivity::TSendIgnoreRecoveryResponse) + + THROUGH_NODEACTIVITY_ENTRY(KNoTag, CConnectionRecoveryActivity::TStoreErrorContext, MeshMachine::TNoTag) + //Decide if it it possible/sensible to reconnect and retry + //This transition will leave if not possible to recover (==TSendPropagateRecoveryResponse from Transition::Error()) + NODEACTIVITY_ENTRY(KNoTag, CConnectionRecoveryActivity::TProcessConnectionStartRecoveryRequest, MCprStates::TAwaitingReConnectCompleteOrError, MeshMachine::TNoTagOrErrorTag) //Own error handling + //Respond with retry + LAST_NODEACTIVITY_ENTRY(KNoTag, CConnectionRecoveryActivity::TSendRetryRecoveryResponse) + //Respond with propagate - the reconnect failed (we could think of re-trying reconnect again though..) + LAST_NODEACTIVITY_ENTRY(KErrorTag, CConnectionRecoveryActivity::TSendPropagateRecoveryResponse) +NODEACTIVITY_END() +} + +namespace MCprConnectionGoneDownRecoveryActivity +{ +//MCprConnectionGoneDownRecovery activity belongs to a group of Error Recovery Activities. +//Error Recovery Activities need to handle their own errors (generated as well as returned). + +//NOTE: This activity is only a reference one. All it does it waits for the mobility handshake to finish before +//continuing with the stack cleanup originated by TGoneDown. +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityConnectionGoneDownRecovery, MCprConnectionGoneDownRecovery, TEErrorRecovery::TErrorRecoveryRequest, CConnectionRecoveryActivity::NewL) + FIRST_NODEACTIVITY_ENTRY(MCprStates::TAwaitingConnectionGoneDownRecoveryRequest, MeshMachine::TNoTag) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, CConnectionRecoveryActivity::TStoreErrorContext, CoreStates::TNoTagOrNoPeer) + LAST_NODEACTIVITY_ENTRY(CoreStates::KNoPeer, MCprStates::TSendPropagateRecoveryResponse) //Take error codes directly from the request + THROUGH_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing, MobilityMCprStates::TNoTagBlockedByMobilityHandshaking) + //Decide if it it possible/sensible to retry + //This transition will leave if not possible to recover (==TSendPropagateRecoveryResponse from Transition::Error()) + LAST_NODEACTIVITY_ENTRY(KNoTag, CConnectionRecoveryActivity::TProcessConnectionGoneDownRecoveryRequest) //Take error codes from the request directly +NODEACTIVITY_END() +} + +namespace MobilityMCprActivities +{ +DEFINE_EXPORT_ACTIVITY_MAP(mobilityMCprActivities) + ACTIVITY_MAP_ENTRY(MobilityMCprPrioritisedSelectActivity, MCprPrioritisedSelect) + ACTIVITY_MAP_ENTRY(MobilityMCprMobilityActivity, MCprMobility) + ACTIVITY_MAP_ENTRY(MCprConnectionStartRecoveryActivity,MCprConnectionStartRecovery) + ACTIVITY_MAP_ENTRY(MCprConnectionGoneDownRecoveryActivity,MCprConnectionGoneDownRecovery) +ACTIVITY_MAP_END_BASE(MCprActivities, coreMCprActivities) +} + +// +// CMobilityActivity +MeshMachine::CNodeActivityBase* MobilityMCprActivities::CMobilityActivity::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) + { + return new (ELeave) CMobilityActivity(aActivitySig, aNode); + } + +CMobilityActivity::CMobilityActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) +: MeshMachine::CNodeRetryActivity(aActivitySig, aNode), + //NOTE: This reference implementation will currently only react to availability oscilating around + //the middle point on the availability scale + iAvailabilityScoreTreshold((TAvailabilityStatus::EMinAvailabilityScore + TAvailabilityStatus::EMaxAvailabilityScore) / 2) + { + } + +CMobilityActivity::~CMobilityActivity() + { + //cancel availablilty subscription. + RClientInterface::OpenPostMessageClose(TNodeCtxId(ActivityId(), iNode.Id()), iNode.Id(), TEBase::TCancel().CRef()); + ClearHandshakingFlag(); + } + +TBool CMobilityActivity::EvaluatePreference(CMobilityActivity::TContext& aContext) + { + //Find the most preferred Service Provider + TClientIter iter = iNode.GetClientIter(TClientType(TCFClientType::EServProvider)); + __ASSERT_DEBUG(iter[0], User::Panic(KCoreMobileMCprPanic, KPanicNoServiceProvider)); //A Service Provider must exist! + + //If we are evaluating the preferences as a result of carrier rejection, we will + //not propose the most recently rejected one. + //NOTE: This implementation does not provide a blacklisting mechanism. + //It does not store any blacklisting information. + //lastRejected is only the recently rejected carrier that may not be proposed again for the client + //to be able to renegotiate the old bearer and continue using the connection. + //NOTE: This reference implementation will work only when at least one of the two most preferred carriers + //can be used (accepted) by the mobility client at any given time. + RMetaServiceProviderInterface* candidate = NULL; + RMetaServiceProviderInterface* lastRejected = NULL; + if ( Error() != KErrNone ) + { + //The activity is running in an error mode attempting to recover from it. + //There's a couple of reasons why the activity may be in an error mode: + //- rejection + // - current bearer rejected; + // - proposed bearer rejected; + // - failure to migrate to the proposed bearer; + lastRejected = iAvailable ? iAvailable : + static_cast(aContext.Node().ServiceProvider()); + } + + iCandidate = iAvailable; + iAvailable = NULL; //Do not remember rejected candidate any longer + while ((candidate = static_cast(iter++)) != NULL) + { + const TAvailabilityStatus& status = candidate->AvailabilityStatus(); + if (!status.IsKnown()) + { + //We are still waiting for the availability check results for this AP + //Ignore the whole evaluation now as we may soon receive a better candidate + //to propose to the mobility client. + return EFalse; + } + + if (status.Score() > iAvailabilityScoreTreshold + && candidate!=lastRejected) + { + if (candidate==aContext.Node().ServiceProvider() + && Error() == KErrNone ) + { + //The preferred one is the current one, is still available and was not just rejected. + //No need to do anything more. + return EFalse; + } + + //A new match found + iAvailable = candidate; + return ETrue; + } + } + + //There is no choice for migration + return EFalse; //No match found + } + +void CMobilityActivity::SetHandshakingFlag() + { + static_cast(iNode).iIsHandshakingNow = ETrue; + } + +void CMobilityActivity::ClearHandshakingFlag() + { + static_cast(iNode).iIsHandshakingNow = EFalse; + } + +DEFINE_SMELEMENT(CMobilityActivity::TNoTagOrReConnectOrStartMobilityHandshakeBackwards, NetStateMachine::MStateFork, CMobilityActivity::TContext) +TInt CMobilityActivity::TNoTagOrReConnectOrStartMobilityHandshakeBackwards::TransitionTag() + { + if (iContext.Activity()->Error() == KErrNone && + (message_cast(&iContext.iMessage) || + message_cast(&iContext.iMessage))) + { + CMobilityActivity& activity = static_cast(*iContext.iNodeActivity); + if( activity.iCurrent!=activity.iAvailable ) + return MobilityMCprStates::KReConnect | NetStateMachine::EForward; + else + return MeshMachine::KNoTag | NetStateMachine::EForward; + } + return MobilityMCprStates::KStartMobilityHandshake | NetStateMachine::EBackward; + } + +DEFINE_SMELEMENT(CMobilityActivity::TNoTagOrStartMobilityHandshakeBackwards, NetStateMachine::MStateFork, CMobilityActivity::TContext) +TInt CMobilityActivity::TNoTagOrStartMobilityHandshakeBackwards::TransitionTag() + { + if (iContext.Activity()->Error() == KErrNone && + (message_cast(&iContext.iMessage) || + message_cast(&iContext.iMessage))) + { + return MeshMachine::KNoTag | NetStateMachine::EForward; + } + return MobilityMCprStates::KStartMobilityHandshake | NetStateMachine::EBackward; + } + +DEFINE_SMELEMENT(CMobilityActivity::TNoTagOrAwaitMobilityBackwardsOnMobilityTrigger, NetStateMachine::MStateFork, CMobilityActivity::TContext) +TInt CMobilityActivity::TNoTagOrAwaitMobilityBackwardsOnMobilityTrigger::TransitionTag() + { + //This is where the judgement is made on whether to trigger mobility (offer the client another bearer) + //or ignore and come back waiting. + __ASSERT_DEBUG(iContext.iMessage.IsMessage() || + iContext.iMessage.IsMessage(), + User::Panic(KCoreMobileMCprPanic, KPanicIncorrectMessage)); + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity)); + CMobilityActivity& activity = static_cast(*iContext.iNodeActivity); + + if (activity.EvaluatePreference(iContext)) + { + activity.SetError(KErrNone); + return KNoTag; + } + else if (activity.Error() != KErrNone ) + { + activity.PostToOriginators(TEBase::TError(activity.Error()).CRef()); + activity.SetError(KErrNone); + } + return MobilityMCprStates::KAwaitMobility | NetStateMachine::EBackward; + } + +DEFINE_SMELEMENT(CMobilityActivity::TNoTagOrAwaitMobility, NetStateMachine::MStateFork, CMobilityActivity::TContext) +TInt CMobilityActivity::TNoTagOrAwaitMobility::TransitionTag() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity)); + CMobilityActivity& activity = static_cast(*iContext.iNodeActivity); + + if (activity.EvaluatePreference(iContext)) + { + activity.SetError(KErrNone); + return KNoTag; + } + else if (activity.Error() != KErrNone ) + { + activity.PostToOriginators(TEBase::TError(activity.Error()).CRef()); + activity.SetError(KErrNone); + } + return MobilityMCprStates::KAwaitMobility; + } + +DEFINE_SMELEMENT(CMobilityActivity::TSendAvailabilityRequest, NetStateMachine::MStateTransition, CMobilityActivity::TContext) +void CMobilityActivity::TSendAvailabilityRequest::DoL() + { + //Issue availability notification registration to start the availability activity on this node. + //NOTE: since we've requested availability from self, we are interested in any change (even available->available) + //since we could be switching from AP1 available to AP2 available. Either way we must recalculate. + //We're hence interested in TAvailabilitySubscriptionOptions::EAnyNestedChange. + TAvailabilitySubscriptionOptions availabilityOptions(TAvailabilitySubscriptionOptions::EAnyNestedChange); + TCFAvailabilityProvider::TAvailabilityNotificationRegistration msg(availabilityOptions); + RClientInterface::OpenPostMessageClose(TNodeCtxId(iContext.ActivityId(), iContext.NodeId()), iContext.NodeId(), msg); + //Do not set iPostedTo. We are not waiting for the responses. + } + +DEFINE_SMELEMENT(CMobilityActivity::TInformMigrationAvailableAndSetHandshakingFlag, NetStateMachine::MStateTransition, CMobilityActivity::TContext) +void CMobilityActivity::TInformMigrationAvailableAndSetHandshakingFlag::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity)); + CMobilityActivity& activity = static_cast(*iContext.iNodeActivity); + + //Inform the CPR that a potential migration is available. We only support a single data client + //in this implementation. + __ASSERT_DEBUG(activity.iAvailable, User::Panic(KCoreMobileMCprPanic, KPanicNoServiceProvider)); + + //Compute all this here to keep EvaluatePreference() as fast as possible + activity.iCurrent = static_cast(iContext.Node().ServiceProvider()); + __ASSERT_DEBUG(activity.iCurrent, User::Panic(KCoreMobileMCprPanic, KPanicNoServiceProvider)); + + //Perform a simple check if this is an upgrade or not + TClientIter iter = iContext.Node().GetClientIter(TClientType(TCFClientType::EServProvider)); + RNodeInterface* sp = iter++; + while (sp && sp!=activity.iCurrent && sp!=activity.iAvailable) + { + sp = iter++; + } + + TBool isUpgrade = (sp != activity.iCurrent); //If current was found first -> this is not an upgrade + if( activity.iCurrent == activity.iAvailable && activity.iCandidate ) + { + // The available client is the same as the current and a candidate exists, this indicates that + // an error has occured when trying to start the candidate bearer and the control as reverted to + // the current bearer. In this situation the notification needs to look as if the bearer has + // migrated from the failed candidate to the current bearer. + TCFMobilityControlClient::TMigrationNotification msg(activity.iCandidate->ProviderInfo().APId(), + activity.iAvailable->ProviderInfo().APId(), + isUpgrade, EFalse); + activity.PostToOriginators(msg); + } + else + { + // Standard case where migration is going from current to available. + TCFMobilityControlClient::TMigrationNotification msg(activity.iCurrent->ProviderInfo().APId(), + activity.iAvailable->ProviderInfo().APId(), + isUpgrade, EFalse); + activity.PostToOriginators(msg); + } + + activity.ClearPostedTo(); + activity.SetHandshakingFlag(); + } + + +DEFINE_SMELEMENT(CMobilityActivity::TAwaitingCurrentCarrierRejectedOrAvailabilityChange, NetStateMachine::MState, CMobilityActivity::TContext) +TBool CMobilityActivity::TAwaitingCurrentCarrierRejectedOrAvailabilityChange::Accept() + { + if (iContext.iMessage.IsMessage()) + { + iContext.Activity()->SetError(KErrNotFound); + return ETrue; + } + return iContext.iMessage.IsMessage(); + } + + +DEFINE_SMELEMENT(CMobilityActivity::TRequestReConnect, NetStateMachine::MStateTransition, CMobilityActivity::TContext) +void CMobilityActivity::TRequestReConnect::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity)); + CMobilityActivity& activity = static_cast(*iContext.iNodeActivity); + + __ASSERT_DEBUG(activity.iAvailable, User::Panic(KCoreMobileMCprPanic, KPanicNoServiceProvider)); + __ASSERT_DEBUG(activity.iCurrent, User::Panic(KCoreMobileMCprPanic, KPanicNoServiceProvider)); + __ASSERT_DEBUG(activity.iCurrent!=activity.iAvailable, User::Panic(KSpecAssert_ESockMbCrMCPRAct, 1)); + + // For the moment it is sufficient to use the re-connect activity, in the future we may want to + // customise the behavior, for example start the new layer before rebinding it, etc. + TCFMcpr::TReConnect msg(activity.iCurrent->RecipientId(), activity.iAvailable->RecipientId()); + activity.PostRequestTo(iContext.NodeId(), msg); + } + +DEFINE_SMELEMENT(CMobilityActivity::TInformMigrationCompleted, NetStateMachine::MStateTransition, CMobilityActivity::TContext) +void CMobilityActivity::TInformMigrationCompleted::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity)); + iContext.iNodeActivity->PostToOriginators(TCFMobilityProvider::TMigrationComplete().CRef()); + iContext.iNodeActivity->ClearPostedTo(); + } + +DEFINE_SMELEMENT(CMobilityActivity::TClearHandshakingFlag, NetStateMachine::MStateTransition, CMobilityActivity::TContext) +void CMobilityActivity::TClearHandshakingFlag::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity)); + CMobilityActivity& activity = static_cast(*iContext.iNodeActivity); + activity.ClearHandshakingFlag(); + } + + +// +//CConnectionRecoveryActivity +MeshMachine::CNodeActivityBase* CConnectionRecoveryActivity::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) + { + return new (ELeave) CConnectionRecoveryActivity(aActivitySig, aNode); + } + +CConnectionRecoveryActivity::CConnectionRecoveryActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) +: MeshMachine::CNodeRetryActivity(aActivitySig, aNode) + { + } + +void CConnectionRecoveryActivity::ReplyToOriginators(TEErrorRecovery::TErrorRecoveryResponse& aCFMessageSig) + { + NM_LOG_START_BLOCK(KESockMeshMachine, _L8("CConnectionRecoveryActivity::ReplyToOriginators")); + NM_LOG((KESockMeshMachine, _L8("[this=0x%08x] "), this)); + NM_LOG_MESSAGE(KESockMeshMachine, aCFMessageSig); + NM_LOG_END_BLOCK(KESockMeshMachine, _L8("CConnectionRecoveryActivity::ReplyToOriginators")); + for (TInt n = iOriginators.Count() - 1;n>=0; n--) + { + Messages::TNodePeerId& peerId = iOriginators[n]; + TCFSafeMessage::TResponseCarrierWest resp(aCFMessageSig, peerId.RecipientId()); + peerId.PostMessage(iNode.Id(), resp); + } + } + +DEFINE_SMELEMENT(CConnectionRecoveryActivity::TAwaitingReConnectComplete, NetStateMachine::MState, CConnectionRecoveryActivity::TContext) +TBool CConnectionRecoveryActivity::TAwaitingReConnectComplete::Accept() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity)); + TEBase::TError* msg = message_cast(&iContext.iMessage); + if(msg) + { + CConnectionRecoveryActivity& ac = static_cast(*iContext.iNodeActivity); + TErrResponse propagateResp(TErrResponse::EPropagate,ac.iOriginalErrContext.iStateChange.iError,ac.iOriginalErrContext.iMessageId); + TEErrorRecovery::TErrorRecoveryResponse errResp(propagateResp); + ac.ReplyToOriginators(errResp); + ac.SetIdle(); + iContext.iMessage.ClearMessageId(); + return EFalse; + } + return (iContext.iMessage.IsMessage())? ETrue : EFalse; + } + +void CConnectionRecoveryActivity::TTransitionBase::Error(TInt /*aError*/) + { + //Reply to the Error Activity and terminate + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity)); + CConnectionRecoveryActivity& ac = static_cast(*iContext.iNodeActivity); + TEErrorRecovery::TErrorRecoveryResponse errResp(TErrResponse(TErrResponse::EPropagate,ac.iOriginalErrContext.iStateChange.iError,ac.iOriginalErrContext.iMessageId)); + ac.ReplyToOriginators(errResp); + iContext.iNodeActivity->SetIdle(); + } + +DEFINE_SMELEMENT(CConnectionRecoveryActivity::TStoreErrorContext, NetStateMachine::MStateTransition, CConnectionRecoveryActivity::TContext) +void CConnectionRecoveryActivity::TStoreErrorContext::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity)); + CConnectionRecoveryActivity& activity = static_cast(*iContext.iNodeActivity); + activity.iOriginalErrContext = message_cast(iContext.iMessage).iErrContext; + } + +DEFINE_SMELEMENT(CConnectionRecoveryActivity::TProcessConnectionStartRecoveryRequest, NetStateMachine::MStateTransition, CConnectionRecoveryActivity::TContext) +void CConnectionRecoveryActivity::TProcessConnectionStartRecoveryRequest::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity)); + RNodeInterface* newSP = NULL; + RNodeInterface* curSP = iContext.Node().ServiceProvider(); //Our current started Service Provider. + + //Choose Service Providers to work on + TClientIter iter = iContext.Node().GetClientIter(TClientType(TCFClientType::EServProvider)); + RNodeInterface* itf = NULL; + for (itf = iter++; itf!=NULL && newSP==NULL; itf = iter++) + { + if (itf==curSP) + { + newSP = iter++; //And the new one to try next + } + } + + //Sanity check. + //The new provider must not be started, there can be only one started at a time. + __ASSERT_DEBUG(newSP==NULL || (newSP->Flags() & TCFClientType::EStarted)==0, User::Panic(KSpecAssert_ESockMbCrMCPRAct, 3)); + + //If there is no other Service Provider to try, return KErrNotFound + if (newSP==NULL || curSP == NULL) + { +#ifdef __CFLOG_ACTIVE + __CFLOG_VAR((KCoreMCprStatesTag, KCoreMCprStatesSubTag, _L8("WARNING: CConnectionRecoveryActivity::TProcessConnectionStartRecoveryRequest::DoL() - no more choices, abandoning recovery."))); +#endif + User::Leave(KErrNotFound); + } + + //Diagnostinc - there must be a data client or we cannot be here + __ASSERT_DEBUG(iContext.Node().GetFirstClient(TClientType(TCFClientType::EData)), User::Panic(KCoreMobileMCprPanic, KPanicNoDataClient)); + iContext.iNodeActivity->PostRequestTo(iContext.NodeId(), + TCFMcpr::TReConnect(curSP->RecipientId(), newSP->RecipientId()).CRef()); + } + +DEFINE_SMELEMENT(CConnectionRecoveryActivity::TProcessConnectionGoneDownRecoveryRequest, NetStateMachine::MStateTransition, CConnectionRecoveryActivity::TContext) +void CConnectionRecoveryActivity::TProcessConnectionGoneDownRecoveryRequest::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity)); + CConnectionRecoveryActivity& activity = static_cast(*iContext.iNodeActivity); + + RNodeInterface* started = iContext.Node().ServiceProvider(); + TUint apId = (TUint)activity.iOriginalErrContext.iInfo; + RNodeInterface* gonedownsp = iContext.Node().FindServiceProvider(apId); + if (started && started != gonedownsp) + { + CConnectionRecoveryActivity::TSendRetryRecoveryResponse tr(iContext); + tr.DoL(); + } + else + { + CConnectionRecoveryActivity::TSendPropagateRecoveryResponse tr(iContext); + tr.DoL(); + } + } + +DEFINE_SMELEMENT(CConnectionRecoveryActivity::TSendRetryRecoveryResponse, NetStateMachine::MStateTransition, CConnectionRecoveryActivity::TContext) +void CConnectionRecoveryActivity::TSendRetryRecoveryResponse::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity)); + CConnectionRecoveryActivity& activity = static_cast(*iContext.iNodeActivity); + TEErrorRecovery::TErrorRecoveryResponse err(TErrResponse(TErrResponse::ERetry,KErrNone,activity.iOriginalErrContext.iMessageId)); + activity.ReplyToOriginators(err); + } + +DEFINE_SMELEMENT(CConnectionRecoveryActivity::TSendPropagateRecoveryResponse, NetStateMachine::MStateTransition, CConnectionRecoveryActivity::TContext) +void CConnectionRecoveryActivity::TSendPropagateRecoveryResponse::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity)); + CConnectionRecoveryActivity& activity = static_cast(*iContext.iNodeActivity); + TEErrorRecovery::TErrorRecoveryResponse err(TErrResponse(TErrResponse::EPropagate, + activity.iOriginalErrContext.iStateChange.iError,activity.iOriginalErrContext.iMessageId)); + activity.ReplyToOriginators(err); + } + +DEFINE_SMELEMENT(CConnectionRecoveryActivity::TSendIgnoreRecoveryResponse, NetStateMachine::MStateTransition, CConnectionRecoveryActivity::TContext) +void CConnectionRecoveryActivity::TSendIgnoreRecoveryResponse::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity)); + CConnectionRecoveryActivity& activity = static_cast(*iContext.iNodeActivity); + TEErrorRecovery::TErrorRecoveryResponse err(TErrResponse(TErrResponse::EIgnore,KErrNone,activity.iOriginalErrContext.iMessageId)); + activity.ReplyToOriginators(err); + } + + diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/core_states/ss_corepractivities.cpp --- a/datacommsserver/esockserver/core_states/ss_corepractivities.cpp Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/core_states/ss_corepractivities.cpp Thu Jan 07 13:34:53 2010 +0200 @@ -1,9 +1,9 @@ // 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 the License "Symbian Foundation License v1.0" +// under the terms of "Eclipse Public License v1.0" // which accompanies this distribution, and is available -// at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html". +// at the URL "http://www.eclipse.org/legal/epl-v10.html". // // Initial Contributors: // Nokia Corporation - initial contribution. @@ -24,12 +24,14 @@ #define SYMBIAN_NETWORKING_UPS +#include "ss_corepractivities.h" + + #include #include "ss_internal_activities.h" -#include "ss_coreprstates.h" -#include "ss_corepractivities.h" +#include #include -#include "ss_mcprnodemessages.h" +#include #include #include @@ -40,10 +42,10 @@ #include #include "ss_nodemessages_dataclient.h" #include "ss_nodemessages_serviceprovider.h" -#include "ss_nodemessages_rejoiningprovider.h" -#include "ss_nodemessages_flow.h" +#include +#include #include "ss_nodemessages_factory.h" -#include "ss_nodemessages_internal_esock.h" +#include #ifdef _DEBUG @@ -70,6 +72,7 @@ using namespace MeshMachine; using namespace Factories; + #ifdef _DEBUG _LIT (KCorePrPanic,"CorePrPanic"); #endif @@ -651,6 +654,16 @@ static_cast(iNode).DeleteMeNow(); } +TBool CDestroyActivity::Next(TNodeContextBase& aContext) + { + if (aContext.iMessage.IsMessage()) + { + return ETrue; + } + else + return CNodeActivityBase::Next(aContext); + } + EXPORT_DEFINE_SMELEMENT(CDestroyActivity::TNoTagOrNoTagBackwards, NetStateMachine::MStateFork, PRStates::TContext) EXPORT_C TInt CDestroyActivity::TNoTagOrNoTagBackwards::TransitionTag() { @@ -840,8 +853,6 @@ ACTIVITY_MAP_ENTRY(PRClientLeaveActivity, PRClientLeave) ACTIVITY_MAP_ENTRY(PRForwardStateChangeActivity, PRForwardStateChange) ACTIVITY_MAP_ENTRY(PRBindToActivity, PRBindTo) - ACTIVITY_MAP_ENTRY(PRDataClientStartActivity, PRDataClientStart) - ACTIVITY_MAP_ENTRY(PRDataClientStopActivity, PRDataClientStop) ACTIVITY_MAP_END_BASE(CoreActivities,coreActivitiesAll) //Activity Map provided by CorePr to be used by SCprs. @@ -850,6 +861,8 @@ ACTIVITY_MAP_ENTRY(PRProvisionActivity, PrProvision) ACTIVITY_MAP_ENTRY(PRStartActivity, PRStart) ACTIVITY_MAP_ENTRY(PRStopActivity, PRStop) + ACTIVITY_MAP_ENTRY(PRDataClientStartActivity, PRDataClientStart) + ACTIVITY_MAP_ENTRY(PRDataClientStopActivity, PRDataClientStop) ACTIVITY_MAP_ENTRY(PRDataClientIdleActivity, PRDataClientIdle) ACTIVITY_MAP_ENTRY(PRDataClientActiveActivity, PRDataClientActive) ACTIVITY_MAP_ENTRY(PRDestroyActivity, PRDestroy) @@ -868,6 +881,8 @@ ACTIVITY_MAP_ENTRY(PRProvisionActivity, PrProvision) ACTIVITY_MAP_ENTRY(PRStartActivity, PRStart) ACTIVITY_MAP_ENTRY(PRStopActivity, PRStop) + ACTIVITY_MAP_ENTRY(PRDataClientStartActivity, PRDataClientStart) + ACTIVITY_MAP_ENTRY(PRDataClientStopActivity, PRDataClientStop) ACTIVITY_MAP_ENTRY(PRDataClientIdleActivity, PRDataClientIdle) ACTIVITY_MAP_ENTRY(PRDataClientActiveActivity, PRDataClientActive) ACTIVITY_MAP_ENTRY(PRDestroyActivity, PRDestroy) @@ -982,11 +997,13 @@ const TCFDataClient::TBindTo& bindToMsg(message_cast(iContext.iMessage)); __ASSERT_DEBUG(!bindToMsg.iNodeId.IsNull(), User::Panic(KCorePrPanic, KPanicNoServiceProvider)); - activity.iNewServiceProvider = iContext.Node().AddClientL(bindToMsg.iNodeId, - TClientType(TCFClientType::EServProvider, TCFClientType::EActivating)); - //Join the new service provider - iContext.iNodeActivity->PostRequestTo(*activity.iNewServiceProvider, - TCFControlClient::TJoinRequest(iContext.NodeId(), TClientType(TCFClientType::ECtrl)).CRef()); + RNodeInterface* newServiceProvider = iContext.Node().AddClientL(bindToMsg.iNodeId, + TClientType(TCFClientType::EServProvider, TCFClientType::EActivating)); + __ASSERT_DEBUG(newServiceProvider, User::Panic(KCorePrPanic, KPanicNoServiceProvider)); + activity.iNewServiceProvider = bindToMsg.iNodeId; + //Join the new service provider + iContext.Activity()->PostRequestTo(*newServiceProvider, + TCFControlClient::TJoinRequest(iContext.NodeId(), TClientType(TCFClientType::ECtrl)).CRef()); } EXPORT_DEFINE_SMELEMENT(CBindToActivity::TAwaitingBindToCompleteOrError, NetStateMachine::MState, CRejoinDataClientActivity::TContext) @@ -1037,8 +1054,9 @@ CBindToActivity& activity = static_cast(*iContext.iNodeActivity); //The service provider has been joined already and must be found here - __ASSERT_DEBUG(activity.iNewServiceProvider , User::Panic(KCorePrPanic, KPanicNoServiceProvider)); - + __ASSERT_DEBUG(!activity.iNewServiceProvider.IsNull(), User::Panic(KCorePrPanic, KPanicNoServiceProvider)); + RNodeInterface* newServiceProvider = iContext.Node().FindClient(activity.iNewServiceProvider); + __ASSERT_DEBUG(newServiceProvider, User::Panic(KCorePrPanic, KPanicNoServiceProvider)); //We must not be in this transition if dc was not found __ASSERT_DEBUG(activity.CurrentDataClient(), User::Panic(KCorePrPanic, KPanicDataClient)); @@ -1071,7 +1089,7 @@ // Send "TCommsBinderRequest" to the Current ServiceProvider activity.PostRequestTo( - *activity.iNewServiceProvider, + *newServiceProvider, TCFServiceProvider::TCommsBinderRequest(subConnOpenType).CRef() ); } @@ -1152,24 +1170,29 @@ return KBearerReady; } - if (iContext.Node().ServiceProvider() - && bindToReq.iNodeId == iContext.Node().ServiceProvider()->RecipientId()) - { - //received the same service provider, it's already bound to. - bindToActivity.iNewServiceProvider = iContext.Node().ServiceProvider(); + RNodeInterface* sp = iContext.Node().ServiceProvider(); + if (sp && bindToReq.iNodeId == sp->RecipientId()) + { + //received the same service provider, it's already bound to. + bindToActivity.iNewServiceProvider = sp->RecipientId(); return KBearerReady; } - bindToActivity.iNewServiceProvider = iContext.Node().FindClient(bindToReq.iNodeId); - if (bindToActivity.iNewServiceProvider) + RNodeInterface* newServiceProvider = iContext.Node().FindClient(bindToReq.iNodeId); + if (newServiceProvider) { - __ASSERT_DEBUG(bindToActivity.iNewServiceProvider->Type() == TCFClientType::EServProvider, User::Panic(KCorePrPanic, KPanicIncorrectState)); + __ASSERT_DEBUG(newServiceProvider->Type() == TCFClientType::EServProvider, User::Panic(KCorePrPanic, KPanicIncorrectState)); //Ok, we've received a TBindTo holding a service provider that we already know of and that is not //our current service provider. We're going to assume this node tolerates multiple service providers (like MCPRs do). //the current service provider will be swapped, but won't be dropped. - bindToActivity.iNewServiceProvider->SetFlags(TCFClientType::EActivating); + bindToActivity.iNewServiceProvider = bindToReq.iNodeId; + newServiceProvider->SetFlags(TCFClientType::EActivating); bindToActivity.SetDontLeaveServiceProvider(); return KBearerReady; } + else + { + bindToActivity.iNewServiceProvider = TNodeId::NullId(); + } //The node received a new service provider... return KNoTag; } @@ -1187,7 +1210,7 @@ return KBindToComplete; } - if (!bindToActivity.iNewServiceProvider) + if (bindToActivity.iNewServiceProvider.IsNull()) { //There is no service provider (new or old) below us. return KBearerReady; @@ -1209,7 +1232,8 @@ }; bindToActivity.iSuccessfulDataClients.Reset(); RNodeInterface* sp = iContext.Node().ServiceProvider(); - if (sp && sp != bindToActivity.iNewServiceProvider) + + if (sp && sp->RecipientId() != bindToActivity.iNewServiceProvider) { if (bindToActivity.ShouldLeaveServiceProvider()) { @@ -1229,14 +1253,19 @@ bindToActivity.SetIdle(); } - if (bindToActivity.iNewServiceProvider && sp != bindToActivity.iNewServiceProvider) - { - __ASSERT_DEBUG(bindToActivity.iNewServiceProvider->Flags() & TCFClientType::EActivating, User::Panic(KCorePrPanic, KPanicIncorrectState)); - bindToActivity.iNewServiceProvider->ClearFlags(TCFClientType::EActivating); - bindToActivity.iNewServiceProvider->SetFlags(TCFClientType::EActive); - __ASSERT_DEBUG(iContext.Node().ServiceProvider() == bindToActivity.iNewServiceProvider, User::Panic(KCorePrPanic, KPanicIncorrectState)); - } - bindToActivity.iNewServiceProvider = NULL; + if (!bindToActivity.iNewServiceProvider.IsNull() && (sp == NULL || sp->RecipientId() != bindToActivity.iNewServiceProvider)) + { + RNodeInterface* newServiceProvider = iContext.Node().FindClient(bindToActivity.iNewServiceProvider); + if (newServiceProvider) + { + __ASSERT_DEBUG(newServiceProvider->Flags() & TCFClientType::EActivating, User::Panic(KCorePrPanic, KPanicIncorrectState)); + newServiceProvider->ClearFlags(TCFClientType::EActivating); + newServiceProvider->SetFlags(TCFClientType::EActive); + // Note: iContext.Node().ServiceProvider() must be re-evaluated in the ASSERT below (i.e. don't use any previously cached value). + __ASSERT_DEBUG(iContext.Node().ServiceProvider() == newServiceProvider, User::Panic(KCorePrPanic, KPanicIncorrectState)); + } + } + bindToActivity.iNewServiceProvider = TNodeId::NullId(); } EXPORT_DEFINE_SMELEMENT(CBindToActivity::TCancel, NetStateMachine::MStateTransition, CBindToActivity::TContext) @@ -1251,25 +1280,28 @@ }; bindToActivity.iSuccessfulDataClients.Reset(); - if (bindToActivity.iNewServiceProvider && bindToActivity.iNewServiceProvider != iContext.Node().ServiceProvider()) - { - __ASSERT_DEBUG(bindToActivity.iNewServiceProvider->Flags() & TCFClientType::EActivating, User::Panic(KCorePrPanic, KPanicIncorrectState)); - bindToActivity.iNewServiceProvider->ClearFlags(TCFClientType::EActivating); - if (bindToActivity.ShouldLeaveServiceProvider()) - { - bindToActivity.PostRequestTo(*bindToActivity.iNewServiceProvider, TEPeer::TLeaveRequest().CRef()); - bindToActivity.iNewServiceProvider->SetFlags(TCFClientType::ELeaving); - } - else - { - bindToActivity.SetIdle(); - } - } - else - { - bindToActivity.SetIdle(); - } - bindToActivity.iNewServiceProvider = NULL; + TBool setIdle = ETrue; + if (!bindToActivity.iNewServiceProvider.IsNull()) + { + RNodeInterface* newServiceProvider = iContext.Node().FindClient(bindToActivity.iNewServiceProvider); + if (newServiceProvider && newServiceProvider != iContext.Node().ServiceProvider()) + { + __ASSERT_DEBUG(newServiceProvider->Flags() & TCFClientType::EActivating, User::Panic(KCorePrPanic, KPanicIncorrectState)); + newServiceProvider->ClearFlags(TCFClientType::EActivating); + if (bindToActivity.ShouldLeaveServiceProvider()) + { + bindToActivity.PostRequestTo(*newServiceProvider, TEPeer::TLeaveRequest().CRef()); + newServiceProvider->SetFlags(TCFClientType::ELeaving); + setIdle = EFalse; + } + } + } + + if (setIdle) + { + bindToActivity.SetIdle(); + } + bindToActivity.iNewServiceProvider = TNodeId::NullId(); } diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/core_states/ss_corepractivities.cpp.orig --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/datacommsserver/esockserver/core_states/ss_corepractivities.cpp.orig Thu Jan 07 13:34:53 2010 +0200 @@ -0,0 +1,2041 @@ +// 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: +// COREPRACTIVITIES.CPP +// Core PR Activities +// THIS API IS INTERNAL TO NETWORKING AND IS SUBJECT TO CHANGE AND NOT FOR EXTERNAL USE +// +// + +/** + @file + @internalComponent +*/ + +#define SYMBIAN_NETWORKING_UPS + +#include "ss_corepractivities.h" + + +#include +#include "ss_internal_activities.h" +#include +#include +#include + +#include +#include + + +#include +#include +#include +#include "ss_nodemessages_dataclient.h" +#include "ss_nodemessages_serviceprovider.h" +#include +#include +#include "ss_nodemessages_factory.h" +#include + + +#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_ESockCrStaCPRAC, "ESockCrStaCPRAC"); +#endif + +#if defined __CFLOG_ACTIVE || defined ESOCK_EXTLOG_ACTIVE + #define KCoreProviderStatesTag KESockCoreProviderTag + _LIT8(KCoreProviderStatesSubTag, "coreprovstate"); +#endif + +using namespace NetStateMachine; +using namespace CoreStates; +using namespace CoreNetStates; +using namespace PRStates; +using namespace PRActivities; +using namespace CoreActivities; +using namespace ESock; +using namespace CorePanics; +using namespace Elements; +using namespace Messages; +using namespace MeshMachine; +using namespace Factories; + + +#ifdef _DEBUG +_LIT (KCorePrPanic,"CorePrPanic"); +#endif + +namespace CoreErrorActivity +{ //Special parallel activity, must be started as the last one +DEFINE_EXPORT_CUSTOM_NODEACTIVITY(ECFActivityError, CoreError, TEBase::TError, CErrorActivity::NewL) + FIRST_NODEACTIVITY_ENTRY(CErrorActivity::TCFAwaitingError, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, CErrorActivity::TSendErrorRecoveryReq, MeshMachine::TAwaitingMessageState, MeshMachine::TNoTag) + LAST_NODEACTIVITY_ENTRY(KNoTag, CErrorActivity::TDoErrorRecovery) +NODEACTIVITY_END() +} + +namespace PRProvisionActivity +{ +DECLARE_DEFINE_NODEACTIVITY(ECFActivityStoreProvision, PrProvision, TCFDataClient::TProvisionConfig) + NODEACTIVITY_ENTRY(KNoTag, PRStates::TStoreProvision, CoreNetStates::TAwaitingProvision, MeshMachine::TNoTag) +NODEACTIVITY_END() +} + +namespace PRControlClientJoinActivity +{ +DEFINE_EXPORT_NODEACTIVITY(ECFActivityClientJoin, PRControlClientJoin, TNodeSignal::TNullMessageId) //May be waiting for both messages + NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TAddControlClientAndSendJoinCompleteIfRequest, CoreNetStates::TAwaitingControlClientJoin, MeshMachine::TNoTag) +NODEACTIVITY_END() +} + +namespace PRDataClientJoinActivity +{ //This activity needs the activity object (& it can fail on AddClientL, so no point converting) +DEFINE_EXPORT_NODEACTIVITY(ECFActivityDataClientJoin, PRDataClientJoin, TCFPeer::TJoinRequest) + FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingDataClientJoinRequest, MeshMachine::TNoTag) + LAST_NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TAddDataClientAndRespond) +NODEACTIVITY_END() +} + +namespace PRClientLeaveActivity +{//This activity will wait for ECFActivityBinderRequest to complete +DEFINE_EXPORT_NODEACTIVITY(ECFActivityClientLeave, PRClientLeave, TNodeSignal::TNullMessageId) //May be waiting for both messages +NODEACTIVITY_ENTRY(KNoTag, PRStates::TProcessClientLeave, CoreStates::TAwaitingClientLeave, MeshMachine::TNoTag) +NODEACTIVITY_END() +} + +namespace PRDataClientIdleActivity +{ +DEFINE_EXPORT_NODEACTIVITY(ECFActivityDataClientIdle, PRDataClientIdle, TCFControlProvider::TIdle) + NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::THandleDataClientIdle, CoreNetStates::TAwaitingDataClientIdle, MeshMachine::TNoTag) +NODEACTIVITY_END() +} + +namespace PRDataClientActiveActivity +{ +DEFINE_EXPORT_NODEACTIVITY(ECFActivityDataClientActive, PRDataClientActive, TCFControlProvider::TActive) + NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing, CoreNetStates::TAwaitingDataClientActive, MeshMachine::TNoTag) +NODEACTIVITY_END() +} + +namespace PRDestroyActivity +{ +//The generic Destroy activity. Carries out the node's goodbye handshake. +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityDestroy, PRDestroy, TEChild::TDestroy, CoreActivities::CDestroyActivity::New) + FIRST_NODEACTIVITY_ENTRY(MeshMachine::TAwaitingDestroy, CoreActivities::CDestroyActivity::TNoTagBlockedByActivitiesOrLeavingDataClient) + + //Stop self first + NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TStopSelf, CoreNetStates::TAwaitingDataClientStopped, CoreStates::TNoTagOrNoClients) + + //The node mustn't go out of scope with clients present. The node must get rid of them first. + NODEACTIVITY_ENTRY(KNoTag, CoreActivities::CDestroyActivity::TMakeClientsLeaveOrProcessClientLeave, CoreStates::TAwaitingClientLeave, CDestroyActivity::TNoTagOrNoTagBackwards) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, CoreActivities::CDestroyActivity::TProcessClientLeave, TTag) + + THROUGH_NODEACTIVITY_ENTRY(KNoClients, PRStates::TProcessDestroy, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing, MeshMachine::TAwaitingLeaveComplete, CoreActivities::CDestroyActivity::TNoTagOrNoTagBackwards) + LAST_NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendClientLeavingAndRemoveControlProvider) +NODEACTIVITY_END() +} + +namespace PRSetParamsRequest +{ +#ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW +DEFINE_EXPORT_NODEACTIVITY(ECFActivityParamRequest, PRSetParams, TCFScpr::TSetParamsRequest) + FIRST_NODEACTIVITY_ENTRY(PRStates::TAwaitingParamRequest, CoreNetStates::TNoTagOrBearerPresent) + NODEACTIVITY_ENTRY(CoreNetStates::KBearerPresent, PRStates::TPassToServiceProvider, CoreNetStates::TAwaitingParamResponse, MeshMachine::TTag) + LAST_NODEACTIVITY_ENTRY(CoreNetStates::KBearerPresent, PRStates::TStoreParamsAndPostToOriginators) + LAST_NODEACTIVITY_ENTRY(KNoTag, PRStates::TStoreAndRespondWithCurrentParams) +NODEACTIVITY_END() +#else +DEFINE_EXPORT_NODEACTIVITY(ECFActivityParamRequest, PRSetParams, TNodeSignal::TNullMessageId) +NODEACTIVITY_END() +#endif +} + +// no Store in case of GetParamsRequest +namespace PRGetParamsRequest +{ +#ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW +DEFINE_EXPORT_NODEACTIVITY(ECFActivityParamRequest, PRGetParams, TCFScpr::TGetParamsRequest) + FIRST_NODEACTIVITY_ENTRY(PRStates::TAwaitingParamRequest, CoreNetStates::TNoTagOrBearerPresent) + NODEACTIVITY_ENTRY(CoreNetStates::KBearerPresent, PRStates::TPassToServiceProvider, CoreNetStates::TAwaitingParamResponse, MeshMachine::TTag) + LAST_NODEACTIVITY_ENTRY(CoreNetStates::KBearerPresent, CoreStates::TPostToOriginators) + LAST_NODEACTIVITY_ENTRY(KNoTag, PRStates::TRespondWithRetrievedParams) +NODEACTIVITY_END() +#else +DEFINE_EXPORT_NODEACTIVITY(ECFActivityParamRequest, PRGetParams, TNodeSignal::TNullMessageId) +NODEACTIVITY_END() +#endif +} + +namespace PRBindToActivity +{ +//PRBindToActivity is responsible for handling TCFDataClient::TBindTo; +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityBindTo, PRBindTo, TCFDataClient::TBindTo, CBindToActivity::NewL) + FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingBindTo, CBindToActivity::TNoTagOrBearerReady) + //TBindTo can hold: + //[KNoTag] - a valid serviceProvider cookie that this node isn't bound to; + //[KBearerReady] - a valid serviceProvider cookie that this node is already bound to; + //[KBearerReady] - a NULL serviceProvider (this node is at the stack's bottom); + + //{ JOINING NEW SERVICE PROVIDER + //a valid serviceProvider supplied, new to this node, let's join it; + NODEACTIVITY_ENTRY(KNoTag, CBindToActivity::TSendControlClientJoinRequest, CoreStates::TAwaitingJoinComplete, TTag) + //} + + //serviceProvider provisionally joined. Now the activity needs to propagate iteslf (TBindTo) to its dataclients. + //The dataclients are either present or not. If not this activity will assume this is the layer construction phase + //and will attempt to construct a default dataclient. + THROUGH_NODEACTIVITY_ENTRY(KBearerReady, MeshMachine::TDoNothing, CBindToActivity::TNoTagOrDataClientReady) + + //{ DATA CLIENT CREATION + //No dataclients present, assume this is the layer creation phase. Attempt to create a dataclient. + NODEACTIVITY_ENTRY(KNoTag, CBindToActivity::TCreateDataClient, TAcceptErrorState, MeshMachine::TErrorTagOr) + //BindTo activity is the pre-start layer builder, hence it always requests the dataclient from the factory. + //The factory (being aware of the phase) may decide to: + //1. create a new dataclient -> process dataclient creation [KNoTag] + //2. return a preexisting dataclient -> bind the client [KDataClientReady] + //3. not to create a dataclient -> send TBindToComplete to the originator [KBindToComplete] + THROUGH_NODEACTIVITY_ENTRY(KNoTag, PRStates::TProcessDataClientCreation, TTag) + //} + + THROUGH_NODEACTIVITY_ENTRY(KDataClientReady, MeshMachine::TDoNothing, CBindToActivity::TNoTagOrBearerReadyOrBindToComplete) + //{ BINDING DATACLIENTS LOOP + //Dataclient(s) is/are ready. Depending on whether the node has the lower layer or not, + //we will [KNoTag] or will not [KNoBearer] need to request a binder for the dataclient. + + //{SERVICE PROVIDER PRESENT + NODEACTIVITY_ENTRY(KNoTag, CBindToActivity::TRequestCommsBinder, TAcceptErrorState, TErrorTagOr >) + //} + NODEACTIVITY_ENTRY(KBearerReady, PRActivities::CBindToActivity::TSendBindTo, CBindToActivity::TAwaitingBindToCompleteOrError, + TErrorTagOr >) + //} + + //Binding is finished. If this is not autocommit (see TCFDataClient::TBindTo), the activity will reply TCFDataClient::TBindToComplete + //to the sender await for the confirmation (TCFDataClient::TCommitBindTo) or cancelation (TBase::TCancel) from the sender. + //If this is autommit, the activity will skip awaiting for TCFDataClient::TCommitBindTo and commit itself. + THROUGH_NODEACTIVITY_ENTRY(KBindToComplete, CBindToActivity::TSendBindToComplete, CBindToActivity::TNoTagOrCommit) + NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing, MeshMachine::TAwaitingMessageState, TErrorTagOr >) + + //commiting (either implicit or explicit). + NODEACTIVITY_ENTRY(KCommit, CBindToActivity::TCommit, MeshMachine::TAwaitingLeaveComplete, MeshMachine::TNoTag) + + //This is not autocommit and the sender has just explicitly cancelled. Alternativelly this is an error path. + //Cancelling/processing error entiles sending TCancel to all dataclients awaiting confirmation + //as well as it entiles leaving the new service provider. + NODEACTIVITY_ENTRY(KErrorTag, CBindToActivity::TCancel, MeshMachine::TAwaitingLeaveComplete, MeshMachine::TNoTag) + + LAST_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing) +NODEACTIVITY_END() +} + +namespace PRStartActivity +{ +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityStart, PRStart, TCFServiceProvider::TStart, PRActivities::CStartActivity::NewL) + FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingStart, CoreNetStates::TNoTagOrBearerPresentBlockedByStop) + NODEACTIVITY_ENTRY(KBearerPresent, CoreNetStates::TBindSelfToPresentBearer, CoreNetStates::TAwaitingBindToComplete, TTag) + NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendNoBearer, MeshMachine::TAwaitingMessageState, CoreNetStates::TNoTagOrBearerPresentOrErrorTag) + + //Start the service provider, use the default cancellation. + //Forward TCancel to the service provider, wait for TStarted or TError (via the Error Activity) + //When TStarted arrives after TCancel the activity will move to the nearest KErrorTag + NODEACTIVITY_ENTRY(KBearerPresent, CoreNetStates::TStartServiceProviderRetry, CoreNetStates::TAwaitingStarted, MeshMachine::TNoTagOrErrorTag) + LAST_NODEACTIVITY_ENTRY(KErrorTag, MeshMachine::TDoNothing) + //Start data clients, use the default cancellation. + //Forward TCancel to the self, wait for TCFDataClient::TStarted or TError (via the Error Activity) + //When TCFDataClient::TStarted arrives after TCancel the activity will move to the nearest KErrorTag + NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TStartSelf, CoreNetStates::TAwaitingDataClientStarted, MeshMachine::TNoTagOrErrorTag) + NODEACTIVITY_ENTRY(KErrorTag, CoreNetStates::TStopSelf, CoreNetStates::TAwaitingDataClientStopped, MeshMachine::TErrorTag) + LAST_NODEACTIVITY_ENTRY(KErrorTag, MeshMachine::TRaiseAndClearActivityError) + LAST_NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendStarted) +NODEACTIVITY_END() +} + +namespace PRStopActivity +{ +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityStop, PRStop, TCFServiceProvider::TStop, MeshMachine::CNodeRetryActivity::NewL) + FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingStop, TActiveOrNoTagBlockedByBindTo) + THROUGH_NODEACTIVITY_ENTRY(KActiveTag, CoreNetStates::TCancelDataClientStart, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TStopSelf, CoreNetStates::TAwaitingDataClientStopped, CoreNetStates::TNoTagOrNoBearer) + NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendStop, CoreNetStates::TAwaitingStopped, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendClientLeavingRequestToServiceProvider, MeshMachine::TAwaitingLeaveComplete, TTag) + LAST_NODEACTIVITY_ENTRY(CoreNetStates::KNoBearer, PRStates::TSendStoppedAndGoneDown) +NODEACTIVITY_END() +} + +namespace PRDataClientStartActivity +{ +DECLARE_DEFINE_NODEACTIVITY(ECFActivityStartDataClient, PRDataClientStart, TCFDataClient::TStart) + FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingDataClientStart, CoreNetStates::TNoTagOrNoDataClients) + NODEACTIVITY_ENTRY(KNoTag, PRStates::TStartDataClients, TAcceptErrorState, MeshMachine::TErrorTagOr >) + LAST_NODEACTIVITY_ENTRY(CoreNetStates::KNoDataClients, PRStates::TSendDataClientStarted) + + NODEACTIVITY_ENTRY(KErrorTag, CoreNetStates::TStopSelf, CoreNetStates::TAwaitingDataClientsStopped, MeshMachine::TErrorTag) + LAST_NODEACTIVITY_ENTRY(KErrorTag, MeshMachine::TRaiseAndClearActivityError) +NODEACTIVITY_END() +} + +namespace PRDataClientStopActivity +{ +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityStopDataClient, PRDataClientStop, TCFDataClient::TStop, MeshMachine::CNodeRetryActivity::NewL) + FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingDataClientStop, MeshMachine::TNoTag) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, PRStates::TProcessDataClientStop, CoreNetStates::TNoTagOrDataClientsToStopBlockedByStarting) + + NODEACTIVITY_ENTRY(CoreNetStates::KDataClientsToStop, CoreNetStates::TStopDataClients, CoreNetStates::TAwaitingDataClientsStopped, MeshMachine::TNoTag) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing, CoreNetStates::TNoTagOrUnbindOnStop) + + NODEACTIVITY_ENTRY(CoreNetStates::KUnbind, CoreNetStates::TSendClientLeavingRequestToServiceProvider, MeshMachine::TAwaitingLeaveComplete, MeshMachine::TNoTag) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, PRStates::TDestroyOrphanedDataClients, MeshMachine::TNoTag) + LAST_NODEACTIVITY_ENTRY(KNoTag, PRStates::TSendDataClientStopped) +NODEACTIVITY_END() +} + + +namespace PRForwardStateChangeActivity +{ +DECLARE_DEFINE_NODEACTIVITY(ECFActivityForwardStateChange, PRForwardStateChange, TCFMessage::TStateChange) + NODEACTIVITY_ENTRY(KNoTag, PRStates::TForwardStateChange, MeshMachine::TAwaitingMessageState, MeshMachine::TNoTag) +NODEACTIVITY_END() +} + +namespace PRDataClientStatusChangeActivity +{ +DECLARE_DEFINE_NODEACTIVITY(ECFActivityDataClientStatusChange, PRDataClientStatusChange, TCFControlProvider::TDataClientStatusChange) + NODEACTIVITY_ENTRY(KNoTag, PRStates::THandleDataClientStatusChangeAndDestroyOrphans, CoreNetStates::TAwaitingDataClientStatusChange, MeshMachine::TNoTag) +NODEACTIVITY_END() +} + +namespace PRGoneDownActivity +{ +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityGoneDown, PRGoneDown, TCFControlClient::TGoneDown, CGoneDownActivity::NewL) + // Our Service Provider has gone down unexpectedly (we haven't issued a TStop) + FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingGoneDown, MeshMachine::TNoTag) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TCancelAndCloseZone0ClientExtIfaces, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendClientLeavingRequestToServiceProvider, MeshMachine::TAwaitingLeaveComplete, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, CGoneDownActivity::TSendErrorRecoveryReq, MeshMachine::TAwaitingErrorRecoveryResponseOrError, CoreStates::TRetryOrIgnoreOrPropagate) + THROUGH_NODEACTIVITY_ENTRY(CoreStates::KRetry, MeshMachine::TDoNothing, CGoneDownActivity::TIgnoreOrPropagate) + LAST_NODEACTIVITY_ENTRY(CoreStates::KIgnore, MeshMachine::TDoNothing) + NODEACTIVITY_ENTRY(CoreStates::KPropagate, CoreNetStates::TCancelStartAndStopSelf, CoreNetStates::TAwaitingDataClientStopped, MeshMachine::TNoTag) + LAST_NODEACTIVITY_ENTRY(KNoTag, PRStates::TSendGoneDown) +NODEACTIVITY_END() +} + + +namespace PRGoneUpActivity +{ +// This Activity forward the TGoneUp event to the Control Clients nodes that are +// not in the originator lis + +DECLARE_DEFINE_NODEACTIVITY(ECFActivityGoneUp, PRGoneUp, TCFControlClient::TGoneUp) + FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingGoneUp, MeshMachine::TNoTag) + LAST_NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendGoneUp) +NODEACTIVITY_END() +} + +namespace PRLegacyRMessage2HandlerActivity +{ +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityLegacyRMessage2Handler, PRLegacyRMessage2Handler, TNodeSignal::TNullMessageId, MeshMachine::CNodeParallelMessageStoreActivityBase::NewL) + FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingLegacyRMessage2Ext, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TProcessOrForwardRMessage2Ext, CoreNetStates::TAwaitingRMessage2Processed, MeshMachine::TNoTag) + LAST_NODEACTIVITY_ENTRY(KNoTag, CoreStates::TPostToOriginators) +NODEACTIVITY_END() +} + + +namespace CoreActivities +{ +DECLARE_DEFINE_ACTIVITY_MAP(coreActivitiesAll) + ACTIVITY_MAP_ENTRY(CoreErrorActivity, CoreError) //Must be first in the table +ACTIVITY_MAP_END() + +//-========================================================= +// +//Error Activity +// +//-========================================================= +MeshMachine::CNodeActivityBase* CErrorActivity::NewL( const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode ) + { + TUint c = GetNextActivityCountL(aActivitySig,aNode); + return new(ELeave)CErrorActivity(aActivitySig, aNode, c); + } + +CErrorActivity::CErrorActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode, TUint aActivitiesCount) + : MeshMachine::CNodeParallelActivityBase(aActivitySig, aNode, aActivitiesCount), iErroredActivityId(MeshMachine::KActivityNull) + { + } + +CErrorActivity::~CErrorActivity() + { + if (Error() != KErrNone) + { + CNodeActivityBase* a = iNode.FindActivityById(iErroredActivityId); + if (a) + { + a->SetError(Error()); + a->SetIdle(); + } + } + SetError(KErrNone); + } + +TBool CErrorActivity::IsIdle() const + { + return NetStateMachine::ACore::IsIdle(); + } + +void CErrorActivity::StartL(TNodeContextBase& aContext, const Messages::XNodePeerId& /*aOriginator*/, const TStateTriple& aFirst) + { + __ASSERT_DEBUG(IsIdle(), User::Panic(KSpecAssert_ESockCrStaCPRAC, 1)); + MESH_LOG_ACTIVITY_EXT(KESockMeshMachine, this, &aContext, (_L8("CErrorActivity %08x:\tStartL->starting activity"), this)); + + NetStateMachine::ACore::Start(&aContext, aFirst); + + MESH_LOG_ACTIVITY_EXT(KESockMeshMachine, this, &aContext, (_L8("CErrorActivity %08x:\tStartL->activity started"),this)); + } + +TBool CErrorActivity::Next(TNodeContextBase& aContext) + { + TBool ret = EFalse; + + + if (aContext.iMessage.IsMessage()) + { + CNodeActivityBase* a = iNode.FindActivityById(iErroredActivityId); + //Special handling for TCancel. + if (a && a->FindOriginator(aContext.iSender) != KErrNotFound) + { + ret = ETrue; + //iActiviy could have handled it, but chose not to. + Cancel(aContext); + //consume the message, otherwise the iActivity will get idled and iActivity reference + //will become invalid. + aContext.iMessage.ClearMessageId(); + } + } + else + { + //If we have sent TErrorRecoveryRequest, we had to have set PostedToId() to the recipient (ControlProvider) + //as otherwise there would be no path for propagating the potential TCancel. + //The response however (TErrorRecoveryResponse or TError) will not necesserily come from that recipient (CP) + //(for example it could be coming from the MCpr and we could be the SCpr). + //Normally this would be a problem because any unrelated TError message arriving to the node + //and presented to the awaiting state would easily be confused with the response (TError == no recovery on the MCpr == EPropagate). + //We avoid the problem by checking all arriving messages if they are adressed to our activity (but we don't + //check the sender. + const TNodeCtxId* recipient = address_cast(&aContext.iRecipient); + if (recipient && (ActivityId() == recipient->NodeCtx())) + { + ret = ACore::Next(&aContext); + if(ret) + { + MESH_LOG_ACTIVITY_EXT(KMeshMachineSubTag, this, &aContext, (_L8("CNodeActivityBase %08x:\tNext->transition"), this)); + } + } + } + return ret; + } + +EXPORT_DEFINE_SMELEMENT(CErrorActivity::TAwaitingError, NetStateMachine::MState, CErrorActivity::TContext) +EXPORT_C TBool CErrorActivity::TAwaitingError::Accept() + { + if (! iContext.iMessage.IsMessage()) + { + return EFalse; + } + + TEBase::TError& errorMessage = message_cast(iContext.iMessage); + + //Diagnostic panic only. TError message should not be travelling around with KErrNone. + //If you see this panic, please send a proper error code. + __ASSERT_DEBUG(errorMessage.iValue != KErrNone, User::Panic(KSpecAssert_ESockCrStaCPRAC, 2)); + + MeshMachine::CNodeActivityBase* aa = iContext.Node().FindAddressedActivity(iContext); + + //TError is always a response. If there is no activity addressed by the TError, + //then we assume the activity hasn't bothered waiting for the result. + //We hence ignore the error. + if (aa) + { + aa->SetError(errorMessage.iValue); + aa->SetIdle(); + } + errorMessage.ClearMessageId(); + return EFalse; + } + +DEFINE_SMELEMENT(CErrorActivity::TCFAwaitingError, NetStateMachine::MState, CErrorActivity::TContext) +EXPORT_C TBool CErrorActivity::TCFAwaitingError::Accept() + { + if (! iContext.iMessage.IsMessage()) + { + return EFalse; + } + + TEBase::TError& errorMessage = message_cast(iContext.iMessage); + + //Diagnostic panic only. TError message should not be travelling around with KErrNone. + //If you see this panic, please send a proper error code. + __ASSERT_DEBUG(errorMessage.iValue != KErrNone, User::Panic(KSpecAssert_ESockCrStaCPRAC, 3)); + + RNodeInterface* client = iContext.Node().FindClient(iContext.iSender); + if (client && + client->Type() & TCFClientType::EServProvider && + iContext.Node().ControlProvider() != NULL && + iContext.Node().CountActivities(ECFActivityDestroy) == 0) + { + //this is the only way out into the activity and into error recovery steps + //that error activity is responsible for doing. + return ETrue; + } + + return CErrorActivity::TAwaitingError::Accept(); + } + +//Simply leaving from this DoL will NOT have the effect of sending TError to originators +//of the Errored activity! iContext.iNodeActivity is the Error activity. +//Reassign iContext.iNodeActivity before leaving or handle the error. +EXPORT_DEFINE_SMELEMENT(CErrorActivity::TSendErrorRecoveryReq, NetStateMachine::MStateTransition, CErrorActivity::TContext) +EXPORT_C void CErrorActivity::TSendErrorRecoveryReq::DoL() + { + //Find matching activity, if any + MeshMachine::CNodeActivityBase* aa = iContext.Node().FindAddressedActivity(iContext); + //we are started based on the fact the the last message iContext.Node()'s received is TError + TEBase::TError& errmsg = message_cast(iContext.iMessage); + + //The error comes from someone else than our Data Client (or we wouldn't be here). + //It may be our Service Provider or it can be some other node which has originated + //an activity on us (in which case the errored activity must be present). + if (aa==NULL) + { + __CFLOG_VAR((KCoreProviderStatesTag, KCoreProviderStatesSubTag, _L8("ASendErrorRecoveryReq::DoL - TError but no addressed activity - ignoring"))); +#ifdef SYMBIAN_NETWORKING_UPS + // Terminate the error activity (not UPS specific). + iContext.iNodeActivity->SetIdle(); +#endif //SYMBIAN_NETWORKING_UPS + return; + } + + AContextStore* intf = NULL; + if (aa->SupportsExtInterface(AContextStore::KInterfaceId)) + { + //FetchExtInterfaceL below can never leave because it is being checked few lines above in the "if" + intf = reinterpret_cast(aa->FetchExtInterfaceL(AContextStore::KInterfaceId)); + } + + //Check if there is any point in sending Error Recovery Request + if (intf==NULL || !intf->IsStored() || !iContext.Node().ControlProvider()) + { + __CFLOG_VAR((KCoreProviderStatesTag, KCoreProviderStatesSubTag, _L8("ERROR: ASendErrorRecoveryReq::DoL - KErrNotSupported"))); + iContext.iNodeActivity->SetIdle(); + aa->SetError(errmsg.iValue); + aa->SetIdle(); + return; + } + + //Determine who TErrorRecoveryRequest should be sent to. + //If there is no ControlProvider we send a RecoveryRequest to ourselves to recover from the error, + //otherwise we sned the RecoveryRequest up to our ControlProvider. + //MCPrs typically put all of the error recovery function in a single error recovery activity therefore + //it makes sense even for MCPrs to send TErrorRecoveryRequest to their error recovery function. By + //posting a TErrorRecoveryRequest sub-classes of the MCPrs get a chance to override the default error + //recovery. + RNodeInterface* errorRecoverer = iContext.Node().ControlProvider() ? iContext.Node().ControlProvider() : &iContext.Node().SelfInterface(); + + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + CoreActivities::CErrorActivity& activity = static_cast(*iContext.iNodeActivity); + __ASSERT_DEBUG(activity.iErroredActivityId==MeshMachine::KActivityNull, User::Panic(KSpecAssert_ESockCrStaCPRAC, 4)); + // Save a reference to the activity and a point + // Each time we use the activity, query it from the node, because the activity may have gone away (originator left node etc) + activity.iErroredActivityId = aa->ActivityId(); + + activity.SetError(errmsg.iValue); + activity.iMessageId = errmsg.iMsgId; + + TErrContext ctx(iContext.NodeId(), errmsg.iMsgId, aa->ActivitySigId(), TStateChange(0, errmsg.iValue)); + TEErrorRecovery::TErrorRecoveryRequest msg(ctx); + + activity.PostRequestTo( + *errorRecoverer,//ControlProvider() verified above + TCFSafeMessage::TRequestCarrierEast(msg).CRef() + ); + + //The original activiy might have set 'sent to', but that's surely + //not meaningful anymore (we've just received a response from that 'sent to'). + //We could have pretended that the orginal activity knows it's sent + //error recovery to the control provider but it's best just to clear + //'sent to' (and handle TCancel from here (CErrorActivity::Next()). + aa->ClearPostedTo(); + } + +EXPORT_DEFINE_SMELEMENT(CErrorActivity::TDoErrorRecovery, NetStateMachine::MStateTransition, CErrorActivity::TContext) +EXPORT_C void CErrorActivity::TDoErrorRecovery::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + CoreActivities::CErrorActivity* act = static_cast(iContext.iNodeActivity); + CNodeActivityBase* a = iContext.Node().FindActivityById(act->iErroredActivityId); + if (a == NULL) + { + iContext.iNodeActivity->SetIdle(); + return; + } + + if (iContext.iMessage.IsMessage()) + { + TErrResponse& resp = message_cast(iContext.iMessage).iErrResponse; + if (resp.iAction == TErrResponse::ERetry) + { //rerun current transition + __CFLOG_VAR((KCoreProviderStatesTag, KCoreProviderStatesSubTag, _L8("ADoErrorRecovery::DoL - instructed to retry"))); + __ASSERT_DEBUG(a->SupportsExtInterface(AContextStore::KInterfaceId), User::Panic(KCorePrPanic, KPanicExtInterfaceNotSupported)); + + AContextStore* intf = reinterpret_cast(a->FetchExtInterfaceL(AContextStore::KInterfaceId)); + __ASSERT_DEBUG(intf->IsStored(), User::Panic(KSpecAssert_ESockCrStaCPRAC, 5)); + intf->Retry(*a,iContext); + if (iContext.iReturn == KErrNone) + { //retry succeded + act->SetError(KErrNone); + } + //if Retry had failed, then the d'tor of act will raise the error on + //and terminate act->iActivity, + } + else if (resp.iAction == TErrResponse::EPropagate) + { //set new error values and fall through + __CFLOG_VAR((KCoreProviderStatesTag, KCoreProviderStatesSubTag, _L8("ADoErrorRecovery::DoL - instructed to propagate the error"))); + act->iMessageId = resp.iMessageId; + a->SetError(resp.iError); + } + else //if (resp.iAction == TErrResponse::EIgnore) + { + __CFLOG_VAR((KCoreProviderStatesTag, KCoreProviderStatesSubTag, + _L8("WARNING: ADoErrorRecovery::DoL() - instructed to ignore the error!"))); + } + } + } + + +//-========================================================= +// +//Destroy Activity - will delete the node when destructed +// +//-========================================================= + +EXPORT_C MeshMachine::CNodeActivityBase* CDestroyActivity::New(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) + { + TAny* space = BorrowPreallocatedSpace(aNode, sizeof(CDestroyActivity)); + CDestroyActivity* self = new (space) CDestroyActivity(aActivitySig, aNode); + self->InsertPreallocatedDestroyActivity(); //Destructing preallocated activity + return self; + } + +CDestroyActivity::CDestroyActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) +: CNodeRetryActivity(aActivitySig, aNode), + APreallocatedOriginators<1>(iOriginators) + { + //Mark the provider for deletion, so that it's not served by the factory from now on. + static_cast(iNode).MarkMeForDeletion(); + } + +void CDestroyActivity::Destroy() + { + ReturnPreallocatedSpace(this); + this->~CDestroyActivity(); //Run the destructor + + //Delete the provider. + static_cast(iNode).DeleteMeNow(); + } + +TBool CDestroyActivity::Next(TNodeContextBase& aContext) + { + if (aContext.iMessage.IsMessage()) + { + return ETrue; + } + else + return CNodeActivityBase::Next(aContext); + } + +EXPORT_DEFINE_SMELEMENT(CDestroyActivity::TNoTagOrNoTagBackwards, NetStateMachine::MStateFork, PRStates::TContext) +EXPORT_C TInt CDestroyActivity::TNoTagOrNoTagBackwards::TransitionTag() + { + if (iContext.iMessage.IsMessage()) + { + TClientIter iter = iContext.Node().GetClientIter(TClientType(TCFClientType::EData|TCFClientType::ECtrl)); + __ASSERT_DEBUG(iter[0], User::Panic(KSpecAssert_ESockCrStaCPRAC, 7)); //One leaving client must still be there. + return iter[1] == NULL ? MeshMachine::KNoTag : MeshMachine::KNoTag | NetStateMachine::EBackward; + } + else if (iContext.iMessage.IsMessage()) + { + __ASSERT_DEBUG(iContext.Node().GetFirstClient(TClientType(TCFClientType::ECtrl|TCFClientType::EData))==NULL, + User::Panic(KCorePrPanic, KPanicClientsStillPresent)); + if (iContext.Node().GetFirstClient(TClientType(TCFClientType::EServProvider))==NULL) + { + return NetStateMachine::EForward | MeshMachine::KNoTag; + } + return NetStateMachine::EBackward | MeshMachine::KNoTag; //Loop back to the same triple (& remove the peer) + } + __ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockCrStaCPRAC, 8)); + return KNoTag; + } + +EXPORT_DEFINE_SMELEMENT(CDestroyActivity::TMakeClientsLeaveOrProcessClientLeave, NetStateMachine::MStateTransition, PRStates::TContext) +EXPORT_C void CDestroyActivity::TMakeClientsLeaveOrProcessClientLeave::DoL() + { + if (iContext.iMessage.IsMessage()) + { + ProcessClientLeaveL(); + } + else + { + MakeClientsLeaveL(); + } + } + +void CDestroyActivity::TMakeClientsLeaveOrProcessClientLeave::MakeClientsLeaveL() + { + __ASSERT_DEBUG(iContext.Node().GetFirstClient(TClientType(TCFClientType::ECtrl))==NULL, + User::Panic(KCorePrPanic, KPanicClientsStillPresent)); + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + iContext.iNodeActivity->ClearPostedTo(); + + //MZTODO: this asserion may need to be changed since TDestroy can + //come while data client is active etc. + __ASSERT_DEBUG(iContext.Node().GetFirstClient(TClientType(TCFClientType::EData, TCFClientType::EActive|TCFClientType::EActivating|TCFClientType::EStarting|TCFClientType::EStarted))==NULL, + User::Panic(KCorePrPanic, KPanicClientsStillPresent)); + + TClientIter dciter = iContext.Node().GetClientIter(TClientType(TCFClientType::EData), TClientType(0, TCFClientType::ELeaving)); + RNodeInterface* dc = NULL; + while ((dc = dciter[0]) != NULL) //always inspect the first elem as we're invalidating the iterator with each hit. + { + dc->PostMessage(iContext.NodeId(), TEChild::TDestroy().CRef()); + dc->SetFlags(TCFClientType::ELeaving); + } + } + +void CDestroyActivity::TMakeClientsLeaveOrProcessClientLeave::ProcessClientLeaveL() + { + CDestroyActivity::TProcessClientLeave processClientLeave(iContext); + processClientLeave.DoL(); + } + + +//-========================================================= +// +//Loppin Activity +// +//-========================================================= +EXPORT_C ACountLoopActivity::~ACountLoopActivity() + { + } + + +EXPORT_C MeshMachine::CNodeActivityBase* CCountLoopActivityBase::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) + { + return new (ELeave) CCountLoopActivityBase(aActivitySig, aNode); + } + +EXPORT_C CCountLoopActivityBase::CCountLoopActivityBase(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) +: MeshMachine::CNodeActivityBase(aActivitySig, aNode), + TIfStaticFetcherNearestInHierarchy(this) + { + } + +EXPORT_C CCountLoopActivityBase::~CCountLoopActivityBase() + { + } + +EXPORT_DEFINE_SMELEMENT(ACountLoopActivity::TNoTagOrNoTagBackwards, NetStateMachine::MStateFork, PRStates::TContext) +EXPORT_C TInt ACountLoopActivity::TNoTagOrNoTagBackwards::TransitionTag() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + __ASSERT_DEBUG(iContext.iNodeActivity->SupportsExtInterface(ACountLoopActivity::KInterfaceId),User::Panic(KCorePrPanic, KPanicInterfaceNotSupported)); + ACountLoopActivity* countLoopActivity = static_cast(iContext.iNodeActivity->FetchExtInterface(ACountLoopActivity::KInterfaceId)); + if (countLoopActivity->DecCount() > 0) + { + return KNoTag | NetStateMachine::EBackward; + } + return KNoTag | NetStateMachine::EForward; + } + + + + + +//-========================================================= +// +// +//Binding Activity +// +// +//-========================================================= +EXPORT_C ABindingActivity::~ABindingActivity() + { + //Handle premature termination of the ABindingActivity object + //by responding to the originator + //If the originator has not been replied to yet, reply now with an error code + if (IsBinding()) + { + ReplyToOriginator(KErrAbort); + } + } + +EXPORT_C void ABindingActivity::StoreOriginator(const TRuntimeCtxId& aNodeCtxId) + { + //Check if the originator wasn't set before. If it was, it must be replied to before storing ths new one. + __ASSERT_DEBUG(iOriginator.IsNull(), User::Panic(KSpecAssert_ESockCrStaCPRAC, 9)); + iOriginator = aNodeCtxId; + } + +EXPORT_C void ABindingActivity::ReplyToOriginator(TInt aError) + { + //NOTE: Please do not make this diagnostic panic conditional. + //Please allow it to server everyone equally. + //Please handle the error conditions properly so that you obey this API's semantics. + //If you are not providing a clean error handling solution for your activity, + //please use IsBinding() before calling this API! + __ASSERT_DEBUG(!iOriginator.IsNull(), User::Panic(KSpecAssert_ESockCrStaCPRAC, 10)); //The iOriginator must be set. + RClientInterface::OpenPostMessageClose(iOurNode, iOriginator, TCFDataClient::TBindToComplete(aError).CRef()); + iOriginator.SetNull(); + } + +EXPORT_DEFINE_SMELEMENT(ABindingActivity::TSendBindToComplete, NetStateMachine::MStateTransition, CoreStates::TContext) +EXPORT_C void ABindingActivity::TSendBindToComplete::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + __ASSERT_DEBUG(iContext.iNodeActivity->SupportsExtInterface(ABindingActivity::KInterfaceId), User::Panic(KSpecAssert_ESockCrStaCPRAC, 11)); + ABindingActivity* bindingActivity = reinterpret_cast(iContext.iNodeActivity->FetchExtInterfaceL(ABindingActivity::KInterfaceId)); + bindingActivity->ReplyToOriginator(iContext.iNodeActivity->Error()); + } + +EXPORT_DEFINE_SMELEMENT(ABindingActivity::TSendBindToCompleteIfExpected, NetStateMachine::MStateTransition, CoreStates::TContext) +EXPORT_C void ABindingActivity::TSendBindToCompleteIfExpected::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + __ASSERT_DEBUG(iContext.iNodeActivity->SupportsExtInterface(ABindingActivity::KInterfaceId), User::Panic(KSpecAssert_ESockCrStaCPRAC, 12)); + ABindingActivity* bindingActivity = reinterpret_cast(iContext.iNodeActivity->FetchExtInterfaceL(ABindingActivity::KInterfaceId)); + if (bindingActivity->IsBinding()) + { + bindingActivity->ReplyToOriginator(iContext.iNodeActivity->Error()); + } + } + +void ABindingActivity::FinalReplyToOriginator(TInt aError) +/** +Intended to be called from derived class destructors to arrange for a TBindToComplete reply to be sent +before any other messages in those derived class destructors (for example TDestroy). +*/ + { + if (IsBinding()) + { + ReplyToOriginator(aError); + // Ensure that we don't send another reply in ~ABindingActivity. + iOriginator = Messages::TNodeCtxId(); + } + } + +} // CoreActivities + + +namespace PRActivities +{ +DECLARE_DEFINE_ACTIVITY_MAP(coreActivitiesPR) + ACTIVITY_MAP_ENTRY(PRDataClientJoinActivity, PRDataClientJoin) + ACTIVITY_MAP_ENTRY(PRControlClientJoinActivity, PRControlClientJoin) + ACTIVITY_MAP_ENTRY(PRClientLeaveActivity, PRClientLeave) + ACTIVITY_MAP_ENTRY(PRForwardStateChangeActivity, PRForwardStateChange) + ACTIVITY_MAP_ENTRY(PRBindToActivity, PRBindTo) + ACTIVITY_MAP_ENTRY(PRDataClientStartActivity, PRDataClientStart) + ACTIVITY_MAP_ENTRY(PRDataClientStopActivity, PRDataClientStop) +ACTIVITY_MAP_END_BASE(CoreActivities,coreActivitiesAll) + +//Activity Map provided by CorePr to be used by SCprs. +//(it is further extended in CoreSCpr). +DEFINE_EXPORT_ACTIVITY_MAP(coreActivitiesSCpr) + ACTIVITY_MAP_ENTRY(PRProvisionActivity, PrProvision) + ACTIVITY_MAP_ENTRY(PRStartActivity, PRStart) + ACTIVITY_MAP_ENTRY(PRStopActivity, PRStop) + ACTIVITY_MAP_ENTRY(PRDataClientIdleActivity, PRDataClientIdle) + ACTIVITY_MAP_ENTRY(PRDataClientActiveActivity, PRDataClientActive) + ACTIVITY_MAP_ENTRY(PRDestroyActivity, PRDestroy) + ACTIVITY_MAP_ENTRY(PRGoneDownActivity, PRGoneDown) + ACTIVITY_MAP_ENTRY(PRGoneUpActivity, PRGoneUp) //robertomaro +#ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW + ACTIVITY_MAP_ENTRY(PRSetParamsRequest, PRSetParams) + ACTIVITY_MAP_ENTRY(PRGetParamsRequest, PRGetParams) +#endif // SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW + ACTIVITY_MAP_ENTRY(PRLegacyRMessage2HandlerActivity, PRLegacyRMessage2Handler) +ACTIVITY_MAP_END_BASE(PRActivities,coreActivitiesPR) + +//Activity Map provided by CorePr to be used by Cprs. +//(it is further extended in CoreCpr). +DEFINE_EXPORT_ACTIVITY_MAP(coreActivitiesCpr) + ACTIVITY_MAP_ENTRY(PRProvisionActivity, PrProvision) + ACTIVITY_MAP_ENTRY(PRStartActivity, PRStart) + ACTIVITY_MAP_ENTRY(PRStopActivity, PRStop) + ACTIVITY_MAP_ENTRY(PRDataClientIdleActivity, PRDataClientIdle) + ACTIVITY_MAP_ENTRY(PRDataClientActiveActivity, PRDataClientActive) + ACTIVITY_MAP_ENTRY(PRDestroyActivity, PRDestroy) + ACTIVITY_MAP_ENTRY(PRGoneDownActivity, PRGoneDown) + ACTIVITY_MAP_ENTRY(PRGoneUpActivity, PRGoneUp) //robertomaro + ACTIVITY_MAP_ENTRY(PRDataClientStatusChangeActivity, PRDataClientStatusChange) +#ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW + ACTIVITY_MAP_ENTRY(PRSetParamsRequest, PRSetParams) + ACTIVITY_MAP_ENTRY(PRGetParamsRequest, PRGetParams) +#endif // SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW + ACTIVITY_MAP_ENTRY(PRLegacyRMessage2HandlerActivity, PRLegacyRMessage2Handler) +ACTIVITY_MAP_END_BASE(PRActivities,coreActivitiesPR) + +//Activity Map provided by CorePr to be used by MCprs. +//(it is further extended in CoreMCpr). +DEFINE_EXPORT_ACTIVITY_MAP(coreActivitiesMCpr) + ACTIVITY_MAP_ENTRY(PRDataClientIdleActivity, PRDataClientIdle) + ACTIVITY_MAP_ENTRY(PRDataClientActiveActivity, PRDataClientActive) + ACTIVITY_MAP_ENTRY(PRDataClientStatusChangeActivity, PRDataClientStatusChange) + ACTIVITY_MAP_ENTRY(PRLegacyRMessage2HandlerActivity, PRLegacyRMessage2Handler) +ACTIVITY_MAP_END_BASE(PRActivities,coreActivitiesPR) + +//Activity Map provided by CorePr to be used by TMs. +//(it is further extended in CoreTM). +DEFINE_EXPORT_ACTIVITY_MAP(coreActivitiesTM) +ACTIVITY_MAP_END_BASE(PRActivities,coreActivitiesPR) + + + + +//-========================================================= +// +//CBindToActivity +// +//-========================================================= +EXPORT_C CBindToActivity::CBindToActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode, TInt aNextActivityCount) + : MeshMachine::CNodeParallelActivityBase(aActivitySig, aNode, aNextActivityCount), + CoreActivities::ABindingActivity(aNode.Id()), + TIfStaticFetcherNearestInHierarchy(this) + { + } + +EXPORT_C MeshMachine::CNodeActivityBase* CBindToActivity::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) + { + //there can be only one BindTo activity running at a time. + TUint c = GetNextActivityCountL(aActivitySig,aNode); + __ASSERT_DEBUG(c == 1,User::Panic(KCorePrPanic, KPanicPeerMisbehaving)); + if (c > 1) + { + User::Leave(KErrInUse); + } + return new (ELeave) CBindToActivity(aActivitySig, aNode, c); + } + +EXPORT_C CBindToActivity::~CBindToActivity() + { + //If the activity is aborted then no cleanup will be performed (the destroy activity will do + //that for us) so we should not assert that iSuccessfulDataClients is empty or iNewServiceProvider + //is null. + + //CBindToActivity::TCommit or CBindToActivity::TCancel should have been executed + //and rendered iSuccessfulDataClients empty. + //__ASSERT_DEBUG(iSuccessfulDataClients.Count() == 0, User::Panic(KCorePrPanic, KPanicIncorrectState)); + + //CBindToActivity::iNewServiceProvider should have been cleared by CBindToActivity::TCommit or CBindToActivity::TCancel + //__ASSERT_DEBUG(iNewServiceProvider == NULL, User::Panic(KCorePrPanic, KPanicIncorrectState)); + + iSuccessfulDataClients.Close(); + } + +Messages::RNodeInterface* CBindToActivity::NextDataClient() + { + TClientIter iter = iNode.GetClientIter( + /*include*/TClientType(TCFClientType::EData), + /*exclude*/TClientType(0, TCFClientType::ELeaving | TCFClientType::EConfigAccessPoint)); + iCurrentDataClient = iter++; + while (iCurrentDataClient && (iSuccessfulDataClients.Find(iCurrentDataClient) != KErrNotFound)) + { + iCurrentDataClient = iter++; + }; + return iCurrentDataClient; + } + +TBool CBindToActivity::DataClientsAutocommit() + { + TInt nonLeavingDataClients = iNode.CountClients( + /*include*/TClientType(TCFClientType::EData), + /*exclude*/TClientType(0, TCFClientType::ELeaving | TCFClientType::EConfigAccessPoint)); + return nonLeavingDataClients <=1 && IsAutocommit(); + } + + +void CBindToActivity::AddClientAsSuccessfulL(Messages::RNodeInterface* aDataClient) + { + __ASSERT_DEBUG(aDataClient, User::Panic(KCorePrPanic, KPanicDataClient)); + __ASSERT_DEBUG(iSuccessfulDataClients.Find(aDataClient) == KErrNotFound, User::Panic(KCorePrPanic, KPanicIncorrectState)); + iSuccessfulDataClients.Append(aDataClient); + } + +void CBindToActivity::RemoveClientFromSuccessful(Messages::RNodeInterface* aDataClient) + { + TInt index = iSuccessfulDataClients.Find(aDataClient); + __ASSERT_DEBUG(index >= 0, User::Panic(KCorePrPanic, KPanicDataClient)); + iSuccessfulDataClients.Remove(index); + } + +EXPORT_DEFINE_SMELEMENT(CBindToActivity::TSendControlClientJoinRequest, NetStateMachine::MStateTransition, CBindToActivity::TContext) +void CBindToActivity::TSendControlClientJoinRequest::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + CBindToActivity& activity = static_cast(*iContext.iNodeActivity); + const TCFDataClient::TBindTo& bindToMsg(message_cast(iContext.iMessage)); + + __ASSERT_DEBUG(!bindToMsg.iNodeId.IsNull(), User::Panic(KCorePrPanic, KPanicNoServiceProvider)); + RNodeInterface* newServiceProvider = iContext.Node().AddClientL(bindToMsg.iNodeId, + TClientType(TCFClientType::EServProvider, TCFClientType::EActivating)); + __ASSERT_DEBUG(newServiceProvider, User::Panic(KCorePrPanic, KPanicNoServiceProvider)); + activity.iNewServiceProvider = bindToMsg.iNodeId; + //Join the new service provider + iContext.Activity()->PostRequestTo(*newServiceProvider, + TCFControlClient::TJoinRequest(iContext.NodeId(), TClientType(TCFClientType::ECtrl)).CRef()); + } + +EXPORT_DEFINE_SMELEMENT(CBindToActivity::TAwaitingBindToCompleteOrError, NetStateMachine::MState, CRejoinDataClientActivity::TContext) +TBool CBindToActivity::TAwaitingBindToCompleteOrError::Accept() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + CBindToActivity& activity = static_cast(*iContext.iNodeActivity); + if (CoreNetStates::TAwaitingBindToComplete(iContext).Accept()) + { + if (activity.IsBinding()) + { + //Activity is binding (i.e.: we havent received TBindToComplete as a response + //to null-carrying TBindTo. + activity.ReplyToOriginator(KErrNone); + } + activity.ResetCurrentDataClient(); + return ETrue; + } + else if (iContext.iMessage.IsMessage()) + { + activity.ReplyToOriginator(message_cast(iContext.iMessage).iValue); + activity.RemoveClientFromSuccessful(activity.CurrentDataClient()); + activity.ResetCurrentDataClient(); + return ETrue; + } + return EFalse; + } + +EXPORT_DEFINE_SMELEMENT(CBindToActivity::TNoTagOrDataClientReady, NetStateMachine::MStateFork, CBindToActivity::TContext) +TInt CBindToActivity::TNoTagOrDataClientReady::TransitionTag() + { + //Any non-leaving dataclients already present? + if (iContext.Node().CountClients( + /*include*/TClientType(TCFClientType::EData), + /*exclude*/TClientType(0, TCFClientType::ELeaving | TCFClientType::EConfigAccessPoint))) + { + return KDataClientReady; + } + return KNoTag; + } + + +EXPORT_DEFINE_SMELEMENT(CBindToActivity::TRequestCommsBinder, NetStateMachine::MStateTransition, CBindToActivity::TContext) +void CBindToActivity::TRequestCommsBinder::DoL() + { + __ASSERT_DEBUG(iContext.Node().CountClients(TClientType(TCFClientType::EData)),User::Panic(KCorePrPanic, KPanicDataClient)); + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + CBindToActivity& activity = static_cast(*iContext.iNodeActivity); + + //The service provider has been joined already and must be found here + __ASSERT_DEBUG(!activity.iNewServiceProvider.IsNull(), User::Panic(KCorePrPanic, KPanicNoServiceProvider)); + RNodeInterface* newServiceProvider = iContext.Node().FindClient(activity.iNewServiceProvider); + __ASSERT_DEBUG(newServiceProvider, User::Panic(KCorePrPanic, KPanicNoServiceProvider)); + //We must not be in this transition if dc was not found + __ASSERT_DEBUG(activity.CurrentDataClient(), User::Panic(KCorePrPanic, KPanicDataClient)); + + // Also if it is not so common to have multiple DataClient (except + // for the relation "SCPR<-CPR"), there are situation where it happens + // and where only one of them is marked as Default. + // So, we check if this is the case and, in case the + // Originator of this activity is NOT a Default one, send ECreateNew. + + // If the Current DC is marked as Default, we ask to the lower layer + // to "AttachToDefault". If it is not, we ask "CreateNew". + TInt subConnOpenType = (activity.CurrentDataClient()->Flags() & TCFClientType::EDefault) ? + TSubConnOpen::EAttachToDefault : TSubConnOpen::ECreateNew; + + // --- WORKAROUND START --- + // [399TODO] There are situation were we don't have any DataClient marked + // as Default, but, asking for ECreateNew, the lower layer doesn't + // manage the request very well. + // This is a WORKAROUND and need fixing (see DEF113154). + // In the meanwhile, we count the number of "DefaultDataClient" and, + // if the result is "0", we ask the lower layer "AttachToDefault" + TInt numberOfDefaultDataClient = iContext.Node().CountClients( + TClientType(TCFClientType::EData, TCFClientType::EDefault) + ); + if (numberOfDefaultDataClient == 0) + { + subConnOpenType = TSubConnOpen::EAttachToDefault; + } + // --- WORKAROUND END --- + + // Send "TCommsBinderRequest" to the Current ServiceProvider + activity.PostRequestTo( + *newServiceProvider, + TCFServiceProvider::TCommsBinderRequest(subConnOpenType).CRef() + ); + } + + +EXPORT_DEFINE_SMELEMENT(CBindToActivity::TCreateDataClient, NetStateMachine::MStateTransition, CBindToActivity::TContext) +void CBindToActivity::TCreateDataClient::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + + IssuePeerCreationRequestL (); + } + +EXPORT_DEFINE_SMELEMENT(CBindToActivity::TSendBindTo, NetStateMachine::MStateTransition, CBindToActivity::TContext) +void CBindToActivity::TSendBindTo::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + CBindToActivity& bindToActivity = static_cast(*iContext.iNodeActivity); + + //Provisionally stash the current dataclient as successful. If it fails to bind, we'll unstash it + //We're doing this now, as stashing may fail and we don't want that to be the sole reason for + //unrolling. + bindToActivity.AddClientAsSuccessfulL(bindToActivity.CurrentDataClient()); + + TCFServiceProvider::TCommsBinderResponse* commsBinderResponse = message_cast(&iContext.iMessage); + Messages::TNodeId commsBinder = commsBinderResponse ? commsBinderResponse->iNodeId : Messages::TNodeId::NullId(); + + bindToActivity.PostRequestTo(*bindToActivity.CurrentDataClient(), + TCFDataClient::TBindTo(commsBinder, !bindToActivity.DataClientsAutocommit()).CRef()); + } + +EXPORT_DEFINE_SMELEMENT(CBindToActivity::TSendBindToComplete, NetStateMachine::MStateTransition, CBindToActivity::TContext) +void CBindToActivity::TSendBindToComplete::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + iContext.iNodeActivity->PostToOriginators(TCFDataClient::TBindToComplete().CRef()); + } + +EXPORT_DEFINE_SMELEMENT(CBindToActivity::TNoTagOrCommit, NetStateMachine::MStateFork, CBindToActivity::TContext) +TInt CBindToActivity::TNoTagOrCommit::TransitionTag() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + CBindToActivity& bindToActivity = static_cast(*iContext.iNodeActivity); + if (bindToActivity.IsAutocommit()) + { + return KCommit; + } + return KNoTag; + } + +EXPORT_DEFINE_SMELEMENT(CBindToActivity::TNoTagOrBindToComplete, NetStateMachine::MStateFork, CBindToActivity::TContext) +EXPORT_C TInt CBindToActivity::TNoTagOrBindToComplete::TransitionTag() + { + TCFFactory::TPeerFoundOrCreated& dcJoined = message_cast(iContext.iMessage); + + if (dcJoined.iNodeId.IsNull()) + { + //Factory decided not to create a dataclient; + return KBindToComplete; + } + + //factory created a new citizen. + return KNoTag; + } + + +EXPORT_DEFINE_SMELEMENT(CBindToActivity::TNoTagOrBearerReady, NetStateMachine::MStateFork, CBindToActivity::TContext) +TInt CBindToActivity::TNoTagOrBearerReady::TransitionTag() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + CBindToActivity& bindToActivity = static_cast(*iContext.iNodeActivity); + TCFDataClient::TBindTo& bindToReq = message_cast(iContext.iMessage); + bindToActivity.SetAutocommit(!bindToReq.iValue); + + if (bindToReq.iNodeId.IsNull()) + //received a null service provider, the node is at the stack's bottom. + { + return KBearerReady; + } + + RNodeInterface* sp = iContext.Node().ServiceProvider(); + if (sp && bindToReq.iNodeId == sp->RecipientId()) + { + //received the same service provider, it's already bound to. + bindToActivity.iNewServiceProvider = sp->RecipientId(); + return KBearerReady; + } + RNodeInterface* newServiceProvider = iContext.Node().FindClient(bindToReq.iNodeId); + if (newServiceProvider) + { + __ASSERT_DEBUG(newServiceProvider->Type() == TCFClientType::EServProvider, User::Panic(KCorePrPanic, KPanicIncorrectState)); + //Ok, we've received a TBindTo holding a service provider that we already know of and that is not + //our current service provider. We're going to assume this node tolerates multiple service providers (like MCPRs do). + //the current service provider will be swapped, but won't be dropped. + bindToActivity.iNewServiceProvider = bindToReq.iNodeId; + newServiceProvider->SetFlags(TCFClientType::EActivating); + bindToActivity.SetDontLeaveServiceProvider(); + return KBearerReady; + } + else + { + bindToActivity.iNewServiceProvider = TNodeId::NullId(); + } + //The node received a new service provider... + return KNoTag; + } + + +EXPORT_DEFINE_SMELEMENT(CBindToActivity::TNoTagOrBearerReadyOrBindToComplete, NetStateMachine::MStateFork, CBindToActivity::TContext) +TInt CBindToActivity::TNoTagOrBearerReadyOrBindToComplete::TransitionTag() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + CBindToActivity& bindToActivity = static_cast(*iContext.iNodeActivity); + + if (!bindToActivity.NextDataClient()) + { + //No more dataclients to bind + return KBindToComplete; + } + + if (bindToActivity.iNewServiceProvider.IsNull()) + { + //There is no service provider (new or old) below us. + return KBearerReady; + } + + return KNoTag; + } + +EXPORT_DEFINE_SMELEMENT(CBindToActivity::TCommit, NetStateMachine::MStateTransition, CBindToActivity::TContext) +void CBindToActivity::TCommit::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + CBindToActivity& bindToActivity = static_cast(*iContext.iNodeActivity); + + TInt count = bindToActivity.DataClientsAutocommit() ? 0 : bindToActivity.iSuccessfulDataClients.Count(); + while (count ) + { + bindToActivity.PostRequestTo(*bindToActivity.iSuccessfulDataClients[--count], TCFDataClient::TCommitBindTo().CRef()); + }; + bindToActivity.iSuccessfulDataClients.Reset(); + RNodeInterface* sp = iContext.Node().ServiceProvider(); + + if (sp && sp->RecipientId() != bindToActivity.iNewServiceProvider) + { + if (bindToActivity.ShouldLeaveServiceProvider()) + { + bindToActivity.PostRequestTo(*sp, TEPeer::TLeaveRequest().CRef()); + sp->SetFlags(TCFClientType::ELeaving); + } + else + { + //Didn't leave, no need for waiting for TLeaveComplete; + bindToActivity.SetIdle(); + } + sp->ClearFlags(TCFClientType::EActive); + } + else + { + //Didn't leave, no need for waiting for TLeaveComplete; + bindToActivity.SetIdle(); + } + + if (!bindToActivity.iNewServiceProvider.IsNull() && (sp == NULL || sp->RecipientId() != bindToActivity.iNewServiceProvider)) + { + RNodeInterface* newServiceProvider = iContext.Node().FindClient(bindToActivity.iNewServiceProvider); + if (newServiceProvider) + { + __ASSERT_DEBUG(newServiceProvider->Flags() & TCFClientType::EActivating, User::Panic(KCorePrPanic, KPanicIncorrectState)); + newServiceProvider->ClearFlags(TCFClientType::EActivating); + newServiceProvider->SetFlags(TCFClientType::EActive); + // Note: iContext.Node().ServiceProvider() must be re-evaluated in the ASSERT below (i.e. don't use any previously cached value). + __ASSERT_DEBUG(iContext.Node().ServiceProvider() == newServiceProvider, User::Panic(KCorePrPanic, KPanicIncorrectState)); + } + } + bindToActivity.iNewServiceProvider = TNodeId::NullId(); + } + +EXPORT_DEFINE_SMELEMENT(CBindToActivity::TCancel, NetStateMachine::MStateTransition, CBindToActivity::TContext) +void CBindToActivity::TCancel::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + CBindToActivity& bindToActivity = static_cast(*iContext.iNodeActivity); + TInt count = bindToActivity.iSuccessfulDataClients.Count(); + while (count ) + { + bindToActivity.PostRequestTo(*bindToActivity.iSuccessfulDataClients[--count], TEBase::TCancel().CRef()); + }; + bindToActivity.iSuccessfulDataClients.Reset(); + + TBool setIdle = ETrue; + if (!bindToActivity.iNewServiceProvider.IsNull()) + { + RNodeInterface* newServiceProvider = iContext.Node().FindClient(bindToActivity.iNewServiceProvider); + if (newServiceProvider && newServiceProvider != iContext.Node().ServiceProvider()) + { + __ASSERT_DEBUG(newServiceProvider->Flags() & TCFClientType::EActivating, User::Panic(KCorePrPanic, KPanicIncorrectState)); + newServiceProvider->ClearFlags(TCFClientType::EActivating); + if (bindToActivity.ShouldLeaveServiceProvider()) + { + bindToActivity.PostRequestTo(*newServiceProvider, TEPeer::TLeaveRequest().CRef()); + newServiceProvider->SetFlags(TCFClientType::ELeaving); + setIdle = EFalse; + } + } + } + + if (setIdle) + { + bindToActivity.SetIdle(); + } + bindToActivity.iNewServiceProvider = TNodeId::NullId(); + } + + +//-========================================================= +// +//Rejoin DataClient Activity +// +//-========================================================= +EXPORT_C MeshMachine::CNodeActivityBase* CRejoinDataClientActivity::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) + { + TUint c = GetNextActivityCountL(aActivitySig,aNode); + return new(ELeave)CRejoinDataClientActivity(aActivitySig, c, aNode); + } + +CRejoinDataClientActivity::~CRejoinDataClientActivity() + { + if ( iDataClients.Count() ) + { + if (Error() != KErrNone) + { + //An error has occured when processing rejoin as the activity hasn't been properly wrapped + //up. This error must have happened before any of the clients have been added to the new + //owner as such addition must either collectively succeed or collectively fail. Reinstall + //clients in at the current owner. + for (TInt i = 0; i < iDataClients.Count(); i++) + { + if (!(iDataClients[i].iDataClient.Flags() & TCFClientType::EActive)) + { +#ifndef __GCCXML__ + //If the dataclient managed to report idle in the mean time, have him destroyed + RClientInterface::OpenPostMessageClose(iNode.Id(), iDataClients[i].iDataClient.RecipientId(), TEChild::TDestroy().CRef()); +#endif + } + iDataClients[i].iDataClient.ClearFlags(TCFClientType::EActivating); +#ifndef __GCCXML__ + //Simulate client leaving on the new owner. + RClientInterface::OpenPostMessageClose(iDataClients[i].iDataClient.RecipientId(), iDataClients[i].iNewOwner, + TEChild::TLeft().CRef()); +#endif + } + } + else + { + //All clear. Remove the clients for good. + for (TInt i = 0; i < iDataClients.Count(); i++) + { + iNode.RemoveClient(iDataClients[i].iDataClient.RecipientId()); + } + } + } + iDataClients.Reset(); + } + + +void CRejoinDataClientActivity::TCFDataClientJoiningRequest::DispatchL(const TRuntimeCtxId& aSender, const TRuntimeCtxId& aRecipient) + { + const TNodeId& nodeId = address_cast(aRecipient); //This message type operates on nodes + MeshMachine::AMMNodeBase* nodeBase = reinterpret_cast(nodeId.Node().FetchNodeInterfaceL(AMMNodeBase::KInterfaceId)); + RNodeInterface* client = NULL; + client = nodeBase->AddClientL(iDataClient, iDataClientType); + client->SetFlags(TCFClientType::EJoining|TCFClientType::EStarted); + RClientInterface::OpenPostMessageClose(nodeId, aSender, TCFPeer::TJoinComplete().CRef()); + } + + +EXPORT_DEFINE_SMELEMENT(CRejoinDataClientActivity::TAwaitingJoinComplete, NetStateMachine::MState, CRejoinDataClientActivity::TContext) +TBool CRejoinDataClientActivity::TAwaitingJoinComplete::Accept() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KSpecAssert_ESockCrStaCPRAC, 13)); + if (iContext.iMessage.IsMessage()) + { + return ETrue; + } + else if (iContext.iMessage.IsMessage()) + { + iContext.iNodeActivity->SetError(message_cast(iContext.iMessage).iValue); + iContext.iNodeActivity->SetIdle(); + iContext.iMessage.ClearMessageId(); + } + return EFalse; + } + + +EXPORT_DEFINE_SMELEMENT(CRejoinDataClientActivity::TRejoinDataClient, NetStateMachine::MStateTransition, CRejoinDataClientActivity::TContext) +EXPORT_C void CRejoinDataClientActivity::TRejoinDataClient::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KSpecAssert_ESockCrStaCPRAC, 14)); + CRejoinDataClientActivity* rejoinActivity = static_cast(iContext.iNodeActivity); + + TCFRejoiningProvider::TRejoinDataClientRequest& rejoinDCMsg = message_cast(iContext.iMessage); + RNodeInterface* subject = iContext.Node().FindClient(rejoinDCMsg.iNodeId1); + if (NULL == subject //client not found + || subject->Flags() & TCFClientType::ELeaving //client leaving/gone + || !(subject->Flags() & TCFClientType::EActive)) //client reported idle or never bound to + { + User::Leave(KErrNotFound); + } + if (subject->Flags() & TCFClientType::EActivating) //client requested by someone + { + User::Leave(KErrInUse); + } + + rejoinActivity->iDataClients.AppendL(TMigrationPairs(*subject, rejoinDCMsg.iNodeId2)); + + CRejoinDataClientActivity::TCFDataClientJoiningRequest msg(subject->RecipientId(), subject->ClientType()); + + RClientInterface::OpenPostMessageClose( + iContext.NodeId(), + rejoinDCMsg.iNodeId2, + msg); + + //Set Client being migrated to a new owner.. reference handed over. secure lifetime. + subject->SetFlags(TCFClientType::EActivating); + } + +EXPORT_DEFINE_SMELEMENT(CRejoinDataClientActivity::TApplyRejoin, NetStateMachine::MStateTransition, CRejoinDataClientActivity::TContext) +void CRejoinDataClientActivity::TApplyRejoin::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KSpecAssert_ESockCrStaCPRAC, 15)); + CRejoinDataClientActivity* rejoinActivity = static_cast(iContext.iNodeActivity); + __ASSERT_DEBUG(rejoinActivity->iDataClients.Count(), User::Panic(KSpecAssert_ESockCrStaCPRAC, 16)); + for (TInt i = 0; i < rejoinActivity->iDataClients.Count(); i++) + { + RClientInterface::OpenPostMessageClose(iContext.NodeId(), rejoinActivity->iDataClients[i].iDataClient.RecipientId(), + TCFFlow::TRejoin(rejoinActivity->iDataClients[i].iNewOwner).CRef()); + rejoinActivity->iDataClients[i].iDataClient.SetFlags(TCFClientType::ELeaving); + } + rejoinActivity->PostRequestTo(iContext.NodeId(), TCFScpr::TApplyRequest().CRef()); + } + +EXPORT_DEFINE_SMELEMENT(CRejoinDataClientActivity::TRejoinLoopTag,NetStateMachine::MStateFork, CRejoinDataClientActivity::TContext) +EXPORT_C TInt CRejoinDataClientActivity::TRejoinLoopTag::TransitionTag() + { + if (iContext.iMessage.IsMessage()) + { + return CoreStates::KLoopTag | NetStateMachine::EBackward; + } + return MeshMachine::KNoTag | NetStateMachine::EForward; + } + +//-========================================================= +// +// CommsBinderActivity (parallel) +// +//-========================================================= + +EXPORT_C MeshMachine::CNodeActivityBase* CCommsBinderActivity::NewL( const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode ) + { + TUint c = GetNextActivityCountL(aActivitySig,aNode); + return new(ELeave)CCommsBinderActivity(aActivitySig, aNode, c); + } + +EXPORT_C CCommsBinderActivity::CCommsBinderActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode, TUint aNextActivityCount) +: MeshMachine::CNodeRetryParallelActivity(aActivitySig, aNode, aNextActivityCount), + TIfStaticFetcherNearestInHierarchy(this) + { + } + +//-========================================================= +// +// CCommsBinderActivity +// +// Aggregate class containing common functionality for +// CommsBinderActivity and CCommsBinderCombiningActivity. +// +//-========================================================= + +EXPORT_C TBool CCommsBinderActivity::TDataClientMutex::IsBlocked(MeshMachine::TNodeContextBase& aContext) + { + TInt c = aContext.Node().CountActivities(aContext.iNodeActivity->ActivitySigId()); + __ASSERT_DEBUG(c>0, User::Panic(KSpecAssert_ESockCrStaCPRAC, 17)); //Diagnostic + if (c == 1 || CCommsBinderActivity::IsDataClientPresent(aContext)) + { + return EFalse; + } + return ETrue; + } + +EXPORT_C TBool CCommsBinderActivity::TDefaultDataClientMutex::IsBlocked(MeshMachine::TNodeContextBase& aContext) + { + TInt c = aContext.Node().CountActivities(aContext.iNodeActivity->ActivitySigId()); + __ASSERT_DEBUG(c>0, User::Panic(KSpecAssert_ESockCrStaCPRAC, 18)); //Diagnostic + if (c == 1 || CCommsBinderActivity::IsDataClientPresent(aContext, TCFClientType::EDefault)) + { + return EFalse; + } + return ETrue; + } + +EXPORT_C /*virtual*/ CCommsBinderActivity::~CCommsBinderActivity() + { + if(!iBinderRequestParameters.IsNull()) + { + iBinderRequestParameters.Close(); + } + } + +EXPORT_C void CCommsBinderActivity::StoreBinder(RNodeInterface* aDataClient) + { + __ASSERT_DEBUG(iPendingBinder == aDataClient || iPendingBinder == NULL, User::Panic(KSpecAssert_ESockCrStaCPRAC, 19)); + iPendingBinder = aDataClient; + } + +EXPORT_C RNodeInterface* CCommsBinderActivity::Binder() const + { + return iPendingBinder; + } + +EXPORT_C void CCommsBinderActivity::StoreBinderRequestParameters(const RCFParameterFamilyBundleC& aBinderRequestParameters) + { + __ASSERT_DEBUG(iBinderRequestParameters.IsNull(), User::Panic(KSpecAssert_ESockCrStaCPRAC, 20)); + if(! aBinderRequestParameters.IsNull()) + { + iBinderRequestParameters.Open(aBinderRequestParameters); + } + } + +void CCommsBinderActivity::SendCustomFlowProvision() +/** +Send a custom message that provisions a flow with flow parameters +*/ + { + __ASSERT_DEBUG(iPendingBinder, User::Panic(KSpecAssert_ESockCrStaCPRAC, 21)); + + // Only send the message if we have parameters to send + if(!iBinderRequestParameters.IsNull()) + { + RParameterFamily parameterFamily = + iBinderRequestParameters.FindFamily(KFlowParametersFamily); + + if(!parameterFamily.IsNull()) + { + STypeId typeId = STypeId::CreateSTypeId(CFlowRequestParameters::EUid, CFlowRequestParameters::EType); + CFlowRequestParameters* flowParams = static_cast(parameterFamily.FindParameterSet(typeId, RParameterFamily::ERequested)); + + iPendingBinder->PostMessage( + iNode.Id(), + TCFInternalEsock::TFlowProvision( + flowParams->GetFlowParams() + ).CRef() + ); + } + } + } + + +void CCommsBinderActivity::SendBinderResponseToOriginator() +/** +Send out CommsBinderResponse to all originators. + +We send to all originators that have joined up until this point, and store this count +in iOriginatorsCountSnapshot. See comment in ProcessBindToComplete(). +*/ + { + __ASSERT_DEBUG(iPendingBinder, User::Panic(KSpecAssert_ESockCrStaCPRAC, 22)); + + PostRequestTo( + address_cast(FirstOriginator().RecipientId()), + TCFServiceProvider::TCommsBinderResponse(iPendingBinder->RecipientId()).CRef()); + + iPendingBinder->SetFlags(TCFClientType::EActivating); + } + +void CCommsBinderActivity::BindToComplete() + { + __ASSERT_DEBUG(iPendingBinder, User::Panic(KSpecAssert_ESockCrStaCPRAC, 23)); + TUint c = iNode.CountActivities(ActivitySigId()); + // Note: this routine can be used with parallel and non-parallel binder activities. In the + // former case we start with multiple activities and eventually end up with a single one. In + // the latter case we have a single activity throughout. + if(c == 1) + { + iPendingBinder->ClearFlags(TCFClientType::EActivating); + } + iPendingBinder = NULL; + } + +// +// CCommsBinderActivity methods that are embedded transitions/states/stateforks +// + +EXPORT_C RNodeInterface* CCommsBinderActivity::IsDataClientPresent(TNodeContextBase& aContext, TUint aClientFlags) +/** +Check if we have a data client and, if so, store it as the binder for this activity. + +@param aContext Node context +@param aClientFlags client flags to use in iterator check +@return ETrue if data client present, else EFalse. +*/ + { + // Be careful not to use a client to which we have already sent TDestroy previously. + // Find the first data client that does not have the ELeaving flag set. If all are + // marked ELeaving then return EFalse - they are on the way out and will disappear + // eventually. The effect will be that a new data client will be created. + RNodeInterface* dataClient = aContext.Node().GetFirstClient(TClientType(TCFClientType::EData, aClientFlags), TClientType(0, TCFClientType::ELeaving)); + return dataClient; + } + +EXPORT_DEFINE_SMELEMENT(CCommsBinderActivity::TNoTagOrUseExisting, NetStateMachine::MStateFork, CCommsBinderActivity::TContext) +EXPORT_C TInt CCommsBinderActivity::TNoTagOrUseExisting::TransitionTag() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KSpecAssert_ESockCrStaCPRAC, 24)); + TCFServiceProvider::TCommsBinderRequest& msg = message_cast(iContext.iMessage); + + // Save away the parameters sent to us so that they are accessible during the activity + __ASSERT_DEBUG(iContext.iNodeActivity->SupportsExtInterface(CCommsBinderActivity::KInterfaceId), User::Panic(KCorePrPanic, KPanicExtInterfaceNotSupported)); + CCommsBinderActivity* intf = reinterpret_cast(iContext.iNodeActivity->FetchExtInterface(CCommsBinderActivity::KInterfaceId)); + intf->StoreBinderRequestParameters(msg.iFamilyBundle); + + if(msg.iValue == TSubConnOpen::EAttachToDefault) + { + RNodeInterface* dc = CCommsBinderActivity::IsDataClientPresent(iContext); + if (dc) + { + __ASSERT_DEBUG(iContext.iNodeActivity->SupportsExtInterface(CCommsBinderActivity::KInterfaceId), User::Panic(KCorePrPanic, KPanicExtInterfaceNotSupported)); + CCommsBinderActivity* intf = reinterpret_cast(iContext.iNodeActivity->FetchExtInterface(CCommsBinderActivity::KInterfaceId)); + + intf->StoreBinder(dc); + return CoreStates::KUseExisting; + } + } + return MeshMachine::KNoTag; + } + +//MZTODO - logic of: +//TNoTagOrWaitForIncomingOrUseExisting +//& +//TNoTagOrWaitForIncomingOrUseExistingDefault +//has been copied but does not seem right, as both use EDefault? +//Why? + +//[401TODO] DL : Only one of TNoTagOrWaitForIncomingOrUseExisting(Default) is used, is it ok to nuke one? + +EXPORT_DEFINE_SMELEMENT(CCommsBinderActivity::TNoTagOrWaitForIncomingOrUseExisting, NetStateMachine::MStateFork, CCommsBinderActivity::TContext) +EXPORT_C TInt CCommsBinderActivity::TNoTagOrWaitForIncomingOrUseExisting::TransitionTag() + { + TCFServiceProvider::TCommsBinderRequest& msg = message_cast(iContext.iMessage); + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KSpecAssert_ESockCrStaCPRAC, 25)); + + if (msg.iValue == TSubConnOpen::EWaitForIncoming) + { + return CoreNetStates::KWaitForIncoming; + } + + else + { + RNodeInterface* dc = CCommsBinderActivity::IsDataClientPresent(iContext, TCFClientType::EDefault); + if (dc) + { + __ASSERT_DEBUG(iContext.iNodeActivity->SupportsExtInterface(CCommsBinderActivity::KInterfaceId), User::Panic(KCorePrPanic, KPanicExtInterfaceNotSupported)); + CCommsBinderActivity* intf = reinterpret_cast(iContext.iNodeActivity->FetchExtInterface(CCommsBinderActivity::KInterfaceId)); + + intf->StoreBinder(dc); + return CoreStates::KUseExisting; + } + } + + return MeshMachine::KNoTag; + } + +EXPORT_DEFINE_SMELEMENT(CCommsBinderActivity::TNoTagOrWaitForIncomingOrUseExistingDefault, NetStateMachine::MStateFork, CCommsBinderActivity::TContext) +EXPORT_C TInt CCommsBinderActivity::TNoTagOrWaitForIncomingOrUseExistingDefault::TransitionTag() + { + TCFServiceProvider::TCommsBinderRequest& msg = message_cast(iContext.iMessage); + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KSpecAssert_ESockCrStaCPRAC, 26)); + + if(msg.iValue == TSubConnOpen::EAttachToDefault) + { + RNodeInterface* dc = CCommsBinderActivity::IsDataClientPresent(iContext, TCFClientType::EDefault); + if (dc) + { + __ASSERT_DEBUG(iContext.iNodeActivity->SupportsExtInterface(CCommsBinderActivity::KInterfaceId), User::Panic(KCorePrPanic, KPanicExtInterfaceNotSupported)); + CCommsBinderActivity* intf = reinterpret_cast(iContext.iNodeActivity->FetchExtInterface(CCommsBinderActivity::KInterfaceId)); + + intf->StoreBinder(dc); + return CoreStates::KUseExisting; + } + } + else if (msg.iValue == TSubConnOpen::EWaitForIncoming) + { + return CoreNetStates::KWaitForIncoming; + } + return MeshMachine::KNoTag; + } + +EXPORT_DEFINE_SMELEMENT(CCommsBinderActivity::TStorePendingBinder, NetStateMachine::MStateTransition, CCommsBinderActivity::TContext) +EXPORT_C void CCommsBinderActivity::TStorePendingBinder::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KSpecAssert_ESockCrStaCPRAC, 27)); + message_cast(iContext.iMessage); + + __ASSERT_DEBUG(iContext.iNodeActivity->SupportsExtInterface(CCommsBinderActivity::KInterfaceId), User::Panic(KCorePrPanic, KPanicExtInterfaceNotSupported)); + CCommsBinderActivity* intf = reinterpret_cast(iContext.iNodeActivity->FetchExtInterface(CCommsBinderActivity::KInterfaceId)); + + intf->StoreBinder(iContext.iPeer); + } + +EXPORT_DEFINE_SMELEMENT(CCommsBinderActivity::TSendBinderResponse, NetStateMachine::MStateTransition, CCommsBinderActivity::TContext) +EXPORT_C void CCommsBinderActivity::TSendBinderResponse::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KSpecAssert_ESockCrStaCPRAC, 28)); + + __ASSERT_DEBUG(iContext.iNodeActivity->SupportsExtInterface(CCommsBinderActivity::KInterfaceId), User::Panic(KCorePrPanic, KPanicExtInterfaceNotSupported)); + CCommsBinderActivity* intf = reinterpret_cast(iContext.iNodeActivity->FetchExtInterface(CCommsBinderActivity::KInterfaceId)); + + intf->SendBinderResponseToOriginator(); + } + +EXPORT_DEFINE_SMELEMENT(CCommsBinderActivity::TSendCustomFlowProvision, NetStateMachine::MStateTransition, CCommsBinderActivity::TContext) +EXPORT_C void CCommsBinderActivity::TSendCustomFlowProvision::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KSpecAssert_ESockCrStaCPRAC, 29)); + + __ASSERT_DEBUG(iContext.iNodeActivity->SupportsExtInterface(CCommsBinderActivity::KInterfaceId), User::Panic(KCorePrPanic, KPanicExtInterfaceNotSupported)); + CCommsBinderActivity* intf = reinterpret_cast(iContext.iNodeActivity->FetchExtInterface(CCommsBinderActivity::KInterfaceId)); + + intf->SendCustomFlowProvision(); + } + +EXPORT_DEFINE_SMELEMENT(CCommsBinderActivity::TAwaitingBindToComplete, NetStateMachine::MState, PRStates::TContext) +EXPORT_C TBool CCommsBinderActivity::TAwaitingBindToComplete::Accept() + { + CoreNetStates::TAwaitingBindToComplete awaitingBindToComplete(iContext); + if (awaitingBindToComplete.Accept()) + { + CCommsBinderActivity* binderActivity = reinterpret_cast(iContext.iNodeActivity->FetchExtInterface(CCommsBinderActivity::KInterfaceId)); + __ASSERT_DEBUG(binderActivity, User::Panic(KSpecAssert_ESockCrStaCPRAC, 30)); + binderActivity->BindToComplete(); + iContext.Node().DestroyOrphanedDataClients(); + return ETrue; + } + return EFalse; + } + +//-========================================================= +// +//CNoBearer Activity +// +//-========================================================= + +CNoBearer::CNoBearer(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode, TUint aActivitiesCount) +: MeshMachine::CNodeRetryParallelActivity(aActivitySig, aNode, aActivitiesCount), + ABindingActivity(aNode.Id()), + TIfStaticFetcherNearestInHierarchy(this) + { + } + +/*virtual*/ CNoBearer::~CNoBearer() + { + iNoBearerParameters.Close(); + } + +EXPORT_C MeshMachine::CNodeActivityBase* CNoBearer::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) + { + TUint c = GetNextActivityCountL(aActivitySig,aNode); + return new(ELeave)CNoBearer(aActivitySig, aNode, c); + } + +EXPORT_C TNodePeerId& CNoBearer::GetOriginator() + { + __ASSERT_DEBUG(iOriginators.Count() == 1, User::Panic(KSpecAssert_ESockCrStaCPRAC, 31)); + return iOriginators[0]; + } + +EXPORT_C void CNoBearer::ReturnInterfacePtrL(CoreActivities::ABindingActivity*& aInterface) + { + aInterface = this; + } + +EXPORT_C TBool CNoBearer::TServiceProviderMutex::IsBlocked(MeshMachine::TNodeContextBase& aContext) + { + TInt c = aContext.Node().CountActivities(aContext.iNodeActivity->ActivitySigId()); + __ASSERT_DEBUG(c>0, User::Panic(KSpecAssert_ESockCrStaCPRAC, 32)); //Diagnostic + if (c == 1 || aContext.Node().CountClients(TClientType(TCFClientType::EServProvider)) != 0) + { + return EFalse; + } + return ETrue; + } + +EXPORT_DEFINE_SMELEMENT(CNoBearer::TRequestCommsBinder, NetStateMachine::MStateTransition, CNoBearer::TContext) +EXPORT_C void CNoBearer::TRequestCommsBinder::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + CNoBearer& noBearer = static_cast(*iContext.iNodeActivity); + + RNodeInterface* sp = iContext.Node().ServiceProvider(); + __ASSERT_DEBUG(sp, User::Panic(KCorePrPanic, KPanicNoServiceProvider)); + + TSubConnOpen::TSubConnType type = TSubConnOpen::EAttachToDefault; + if (!(noBearer.GetOriginator().Flags() & TCFClientType::EDefault)) + { + type = TSubConnOpen::ECreateNew; + } + + noBearer.PostRequestTo( + *sp, + TCFServiceProvider::TCommsBinderRequest( + type, noBearer.iNoBearerParameters + ).CRef() + ); + } + +EXPORT_DEFINE_SMELEMENT(CNoBearer::TStoreRequestParameters, NetStateMachine::MStateTransition, CNoBearer::TContext) +EXPORT_C void CNoBearer::TStoreRequestParameters::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + CNoBearer& noBearer = static_cast(*iContext.iNodeActivity); + const TCFControlProvider::TNoBearer& noBearerMessage = message_cast(iContext.iMessage); + __ASSERT_DEBUG(noBearer.iNoBearerParameters.IsNull(), User::Panic(KSpecAssert_ESockCrStaCPRAC, 33)); // handle should be empty when this fn is called + if(noBearerMessage.iFamilyBundle.IsNull()) + { + noBearer.iNoBearerParameters.Open(); + } + else + { + noBearer.iNoBearerParameters.Open(noBearerMessage.iFamilyBundle); + } + } + +EXPORT_DEFINE_SMELEMENT(CNoBearer::TNoTagOrDataClientsToStart, NetStateMachine::MStateFork, CNoBearer::TContext) +TInt CNoBearer::TNoTagOrDataClientsToStart::TransitionTag() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + CNoBearer& activity = static_cast(*iContext.iNodeActivity); + + const TNodePeerId& originator = activity.GetOriginator(); + __ASSERT_DEBUG(originator.Type() & TCFClientType::EData, User::Panic(KSpecAssert_ESockCrStaCPRAC, 34)); + + if (activity.Error() == KErrNone && (originator.Flags() & (TCFClientType::EStarting|TCFClientType::EStarted|TCFClientType::ELeaving)) == 0) + { + //Start dc + return CoreNetStates::KDataClientsToStart; + } + //Finish the activity + return MeshMachine::KNoTag; + } + +EXPORT_DEFINE_SMELEMENT(CNoBearer::TStartOriginatingDataClient, NetStateMachine::MStateTransition, CNoBearer::TContext) +void CNoBearer::TStartOriginatingDataClient::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + CNoBearer& activity = static_cast(*iContext.iNodeActivity); + TNodePeerId& originator = activity.GetOriginator(); + __ASSERT_DEBUG(originator.Type() & TCFClientType::EData, User::Panic(KSpecAssert_ESockCrStaCPRAC, 35)); + activity.PostRequestTo(originator.Peer(), TCFDataClient::TStart().CRef()); + originator.SetFlags(TCFClientType::EStarting); + } + +EXPORT_DEFINE_SMELEMENT(CNoBearer::TNoTagOrBearerPresent, NetStateMachine::MStateFork, CNoBearer::TContext) +EXPORT_C TInt CNoBearer::TNoTagOrBearerPresent::TransitionTag() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + CNoBearer& noBearer = static_cast(*iContext.iNodeActivity); + const TCFControlProvider::TNoBearer& noBearerMessage = message_cast(iContext.iMessage); + __ASSERT_DEBUG(noBearer.iNoBearerParameters.IsNull(), User::Panic(KSpecAssert_ESockCrStaCPRAC, 36)); // should not yet be set when this fn is called + noBearer.iNoBearerParameters.Open(noBearerMessage.iFamilyBundle); + + CoreNetStates::TNoTagOrBearerPresent fork(iContext); + return fork.TransitionTag(); + } + +EXPORT_DEFINE_SMELEMENT(CNoBearer::TNoTagOrBearerPresentForAutostart, NetStateMachine::MStateFork, CNoBearer::TContext) +EXPORT_C TInt CNoBearer::TNoTagOrBearerPresentForAutostart::TransitionTag() + { + TInt cntrlClients = iContext.Node().CountClients( + /*include*/TClientType(TCFClientType::ECtrl)); + if (cntrlClients > 0 && + iContext.Node().ServiceProvider() && + !(iContext.Node().ServiceProvider()->Flags() & TCFClientType::EStarted)) + { + //This fork calculates if the NoBearer activity (which this fork has been implemented for) + //should attempt to autostart the service provider when returning it to the sender of TNoBearer. + //The philosphy here is that if the local node doesn't have a control client, then there's noone + //that could posibly start it. It will hence decide to autostart as the top layer of what looks + //like an implicit connection. In the future this autostart behaviour should become a specialty + //of someone more concrete (rather than generic function). We are speculating about the implicit + //top layer that could acquire this function if it ever comes into being. + return CoreNetStates::KBearerPresent; + } + return KNoTag; + } + + +//-========================================================= +// +//CStartActivity Activity +// +//-========================================================= +CStartActivity::CStartActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) + : MeshMachine::CNodeRetryActivity(aActivitySig, aNode), + CoreActivities::ABindingActivity(aNode.Id()), + TIfStaticFetcherNearestInHierarchy(this) + { + } + +EXPORT_C CStartActivity::~CStartActivity() + { + } + +EXPORT_C MeshMachine::CNodeActivityBase* CStartActivity::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) + { + return new (ELeave) CStartActivity(aActivitySig, aNode); + } + +//-========================================================= +// +//Gone Down Activity +// +//-========================================================= +MeshMachine::CNodeActivityBase* CGoneDownActivity::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) + { + CGoneDownActivity* self = new (ELeave) CGoneDownActivity(aActivitySig,aNode); + return self; + } + +CGoneDownActivity::CGoneDownActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) +: MeshMachine::CNodeRetryActivity(aActivitySig, aNode) + { + } + +CGoneDownActivity::~CGoneDownActivity() + { + //This is a gone down activity. Error mode is its only/natural state + //CGoneDownActivity inherits ultimatelly from CNodeActivityBase, which + //will attempt to interpret the error mode as a failure to execute (and + //auto respond to orignators), which we don't want. Hence clearing + //the error and allowing 'this' to die peacefully. + SetError(KErrNone); + } + +void CGoneDownActivity::StartL(TNodeContextBase& aContext, const Messages::XNodePeerId& aOriginator, const TStateTriple& aFirst) + { + //399TODO: for the moment ignore duplicated TGoneDown messages + //but this needs to be fixed (someone is sending TGoneDown from TSendDataClientStopped + //hence the problem) + + //ASSERT(IsIdle()); + if (!IsIdle()) + { + return; + } + + //This activity provides service for only one single requestor at a time. + __ASSERT_DEBUG(iOriginators.Count()==0, User::Panic(KSpecAssert_ESockCrStaCPRAC, 37)); //Diagnostic panic + + TCFControlClient::TGoneDown& msg = message_cast(aContext.iMessage); + SetError(msg.iValue1); + iGoneDownApId = msg.iValue2; + + MESH_LOG_ACTIVITY_EXT(KMeshMachineSubTag, this, &aContext, (_L8("CGoneDownActivity %08x:\tStartL->starting activity"), this)); + NetStateMachine::ACore::Start(&aContext, aFirst); + + MESH_LOG_ACTIVITY_EXT(KMeshMachineSubTag, this, &aContext, (_L8("CGoneDownActivity %08x:\tStartL->activity started"), this)); + (void)aOriginator; + } + +//Find next DC to rebind +TBool CGoneDownActivity::IsIdle() const + { + return NetStateMachine::ACore::IsIdle(); + } + +DEFINE_SMELEMENT(CGoneDownActivity::TSendErrorRecoveryReq, NetStateMachine::MStateTransition, CGoneDownActivity::TContext) +void CGoneDownActivity::TSendErrorRecoveryReq::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + CGoneDownActivity& activity = static_cast(*iContext.iNodeActivity); + + //TInt error = ExtractErrorCode(iContext.iMessage); + TErrContext ctx(iContext.NodeId(), TCFControlClient::TGoneDown::Id(), activity.ActivitySigId(), TStateChange(0, activity.Error())); + ctx.iInfo = (TAny*)activity.iGoneDownApId; + TEErrorRecovery::TErrorRecoveryRequest msg(ctx); + + //We can not set SetSentTo() to Control Provider, because the response may not be coming from it + //(for example it could be coming from the MCpr and we could be the SCpr). + //Normally this would be a problem because any unrelated TError message arriving to the node + //and presented to the awaiting state would easily be confused with the response (TError == + //no recovery on the MCpr == EPropagate). + //We avoid the problem by checking all arriving TError messages if they are adressed to our activity. + __ASSERT_DEBUG(iContext.Node().ControlProvider(), User::Panic(KCorePrPanic, KPanicNoControlProvider)); + activity.PostRequestTo(*iContext.Node().ControlProvider(), + TCFSafeMessage::TRequestCarrierEast(msg).CRef()); + activity.ClearPostedTo(); + } + +DEFINE_SMELEMENT(CGoneDownActivity::TIgnoreOrPropagate, NetStateMachine::MStateFork, CGoneDownActivity::TContext) +TInt CGoneDownActivity::TIgnoreOrPropagate::TransitionTag() + { + __ASSERT_DEBUG(iContext.iMessage.IsMessage(), User::Panic(KSpecAssert_ESockCrStaCPRAC, 38)); + RNodeInterface* sp = iContext.Node().GetFirstClient(TClientType(TCFClientType::EServProvider, TCFClientType::EStarted)); + if (sp) + { + return CoreStates::KIgnore | NetStateMachine::EForward; + } + //There is no started service provider, the reconnection, mobility, etc must have failed, + //continue with tearing this layer down. + CGoneDownActivity& activity = static_cast(*iContext.iNodeActivity); + TErrResponse& resp = message_cast(iContext.iMessage).iErrResponse; + resp.iAction=TErrResponse::EPropagate; + __ASSERT_DEBUG(activity.Error()!=KErrNone, User::Panic(KSpecAssert_ESockCrStaCPRAC, 39)); + resp.iError = activity.Error(); + return CoreStates::KPropagate | NetStateMachine::EForward; + } + + +EXPORT_DEFINE_SMELEMENT(CStartActivity::TAwaitingBindToCompleteOrCancel, NetStateMachine::MState, CStartActivity::TContext) +TBool CStartActivity::TAwaitingBindToCompleteOrCancel::Accept() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + if (iContext.iMessage.IsMessage()) + { + iContext.iNodeActivity->SetError(KErrCancel); + iContext.iMessage.ClearMessageId(); + return EFalse; + } + else + { + CoreNetStates::TAwaitingBindToComplete state(iContext); + return state.Accept(); + } + } +} //PRActivities + +EXPORT_DEFINE_SMELEMENT(PRDataClientStopActivity::TNoTagOrProviderStopped, NetStateMachine::MStateFork, PRDataClientStopActivity::TContext) +EXPORT_C TInt PRDataClientStopActivity::TNoTagOrProviderStopped::TransitionTag() + { + iContext.iNodeActivity->SetError(message_cast(iContext.iMessage).iValue); + if (iContext.Node().GetFirstClient( + TClientType(TCFClientType::EData, TCFClientType::EStarted)) != NULL) + { + // At least one started data client + return MeshMachine::KNoTag; + } + return CoreNetStates::KProviderStopped; + } + + + diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/core_states/ss_corepractivities.cpp~ --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/datacommsserver/esockserver/core_states/ss_corepractivities.cpp~ Thu Jan 07 13:34:53 2010 +0200 @@ -0,0 +1,2034 @@ +// 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: +// COREPRACTIVITIES.CPP +// Core PR Activities +// THIS API IS INTERNAL TO NETWORKING AND IS SUBJECT TO CHANGE AND NOT FOR EXTERNAL USE +// +// + +/** + @file + @internalComponent +*/ + +#define SYMBIAN_NETWORKING_UPS + +#include "ss_corepractivities.h" + + +#include +#include "ss_internal_activities.h" +#include +#include +#include + +#include +#include + + +#include +#include +#include +#include "ss_nodemessages_dataclient.h" +#include "ss_nodemessages_serviceprovider.h" +#include +#include +#include "ss_nodemessages_factory.h" +#include + + +#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_ESockCrStaCPRAC, "ESockCrStaCPRAC"); +#endif + +#if defined __CFLOG_ACTIVE || defined ESOCK_EXTLOG_ACTIVE + #define KCoreProviderStatesTag KESockCoreProviderTag + _LIT8(KCoreProviderStatesSubTag, "coreprovstate"); +#endif + +using namespace NetStateMachine; +using namespace CoreStates; +using namespace CoreNetStates; +using namespace PRStates; +using namespace PRActivities; +using namespace CoreActivities; +using namespace ESock; +using namespace CorePanics; +using namespace Elements; +using namespace Messages; +using namespace MeshMachine; +using namespace Factories; + + +#ifdef _DEBUG +_LIT (KCorePrPanic,"CorePrPanic"); +#endif + +namespace CoreErrorActivity +{ //Special parallel activity, must be started as the last one +DEFINE_EXPORT_CUSTOM_NODEACTIVITY(ECFActivityError, CoreError, TEBase::TError, CErrorActivity::NewL) + FIRST_NODEACTIVITY_ENTRY(CErrorActivity::TCFAwaitingError, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, CErrorActivity::TSendErrorRecoveryReq, MeshMachine::TAwaitingMessageState, MeshMachine::TNoTag) + LAST_NODEACTIVITY_ENTRY(KNoTag, CErrorActivity::TDoErrorRecovery) +NODEACTIVITY_END() +} + +namespace PRProvisionActivity +{ +DECLARE_DEFINE_NODEACTIVITY(ECFActivityStoreProvision, PrProvision, TCFDataClient::TProvisionConfig) + NODEACTIVITY_ENTRY(KNoTag, PRStates::TStoreProvision, CoreNetStates::TAwaitingProvision, MeshMachine::TNoTag) +NODEACTIVITY_END() +} + +namespace PRControlClientJoinActivity +{ +DEFINE_EXPORT_NODEACTIVITY(ECFActivityClientJoin, PRControlClientJoin, TNodeSignal::TNullMessageId) //May be waiting for both messages + NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TAddControlClientAndSendJoinCompleteIfRequest, CoreNetStates::TAwaitingControlClientJoin, MeshMachine::TNoTag) +NODEACTIVITY_END() +} + +namespace PRDataClientJoinActivity +{ //This activity needs the activity object (& it can fail on AddClientL, so no point converting) +DEFINE_EXPORT_NODEACTIVITY(ECFActivityDataClientJoin, PRDataClientJoin, TCFPeer::TJoinRequest) + FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingDataClientJoinRequest, MeshMachine::TNoTag) + LAST_NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TAddDataClientAndRespond) +NODEACTIVITY_END() +} + +namespace PRClientLeaveActivity +{//This activity will wait for ECFActivityBinderRequest to complete +DEFINE_EXPORT_NODEACTIVITY(ECFActivityClientLeave, PRClientLeave, TNodeSignal::TNullMessageId) //May be waiting for both messages +NODEACTIVITY_ENTRY(KNoTag, PRStates::TProcessClientLeave, CoreStates::TAwaitingClientLeave, MeshMachine::TNoTag) +NODEACTIVITY_END() +} + +namespace PRDataClientIdleActivity +{ +DEFINE_EXPORT_NODEACTIVITY(ECFActivityDataClientIdle, PRDataClientIdle, TCFControlProvider::TIdle) + NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::THandleDataClientIdle, CoreNetStates::TAwaitingDataClientIdle, MeshMachine::TNoTag) +NODEACTIVITY_END() +} + +namespace PRDataClientActiveActivity +{ +DEFINE_EXPORT_NODEACTIVITY(ECFActivityDataClientActive, PRDataClientActive, TCFControlProvider::TActive) + NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing, CoreNetStates::TAwaitingDataClientActive, MeshMachine::TNoTag) +NODEACTIVITY_END() +} + +namespace PRDestroyActivity +{ +//The generic Destroy activity. Carries out the node's goodbye handshake. +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityDestroy, PRDestroy, TEChild::TDestroy, CoreActivities::CDestroyActivity::New) + FIRST_NODEACTIVITY_ENTRY(MeshMachine::TAwaitingDestroy, CoreActivities::CDestroyActivity::TNoTagBlockedByActivitiesOrLeavingDataClient) + + //Stop self first + NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TStopSelf, CoreNetStates::TAwaitingDataClientStopped, CoreStates::TNoTagOrNoClients) + + //The node mustn't go out of scope with clients present. The node must get rid of them first. + NODEACTIVITY_ENTRY(KNoTag, CoreActivities::CDestroyActivity::TMakeClientsLeaveOrProcessClientLeave, CoreStates::TAwaitingClientLeave, CDestroyActivity::TNoTagOrNoTagBackwards) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, CoreActivities::CDestroyActivity::TProcessClientLeave, TTag) + + THROUGH_NODEACTIVITY_ENTRY(KNoClients, PRStates::TProcessDestroy, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing, MeshMachine::TAwaitingLeaveComplete, CoreActivities::CDestroyActivity::TNoTagOrNoTagBackwards) + LAST_NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendClientLeavingAndRemoveControlProvider) +NODEACTIVITY_END() +} + +namespace PRSetParamsRequest +{ +#ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW +DEFINE_EXPORT_NODEACTIVITY(ECFActivityParamRequest, PRSetParams, TCFScpr::TSetParamsRequest) + FIRST_NODEACTIVITY_ENTRY(PRStates::TAwaitingParamRequest, CoreNetStates::TNoTagOrBearerPresent) + NODEACTIVITY_ENTRY(CoreNetStates::KBearerPresent, PRStates::TPassToServiceProvider, CoreNetStates::TAwaitingParamResponse, MeshMachine::TTag) + LAST_NODEACTIVITY_ENTRY(CoreNetStates::KBearerPresent, PRStates::TStoreParamsAndPostToOriginators) + LAST_NODEACTIVITY_ENTRY(KNoTag, PRStates::TStoreAndRespondWithCurrentParams) +NODEACTIVITY_END() +#else +DEFINE_EXPORT_NODEACTIVITY(ECFActivityParamRequest, PRSetParams, TNodeSignal::TNullMessageId) +NODEACTIVITY_END() +#endif +} + +// no Store in case of GetParamsRequest +namespace PRGetParamsRequest +{ +#ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW +DEFINE_EXPORT_NODEACTIVITY(ECFActivityParamRequest, PRGetParams, TCFScpr::TGetParamsRequest) + FIRST_NODEACTIVITY_ENTRY(PRStates::TAwaitingParamRequest, CoreNetStates::TNoTagOrBearerPresent) + NODEACTIVITY_ENTRY(CoreNetStates::KBearerPresent, PRStates::TPassToServiceProvider, CoreNetStates::TAwaitingParamResponse, MeshMachine::TTag) + LAST_NODEACTIVITY_ENTRY(CoreNetStates::KBearerPresent, CoreStates::TPostToOriginators) + LAST_NODEACTIVITY_ENTRY(KNoTag, PRStates::TRespondWithRetrievedParams) +NODEACTIVITY_END() +#else +DEFINE_EXPORT_NODEACTIVITY(ECFActivityParamRequest, PRGetParams, TNodeSignal::TNullMessageId) +NODEACTIVITY_END() +#endif +} + +namespace PRBindToActivity +{ +//PRBindToActivity is responsible for handling TCFDataClient::TBindTo; +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityBindTo, PRBindTo, TCFDataClient::TBindTo, CBindToActivity::NewL) + FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingBindTo, CBindToActivity::TNoTagOrBearerReady) + //TBindTo can hold: + //[KNoTag] - a valid serviceProvider cookie that this node isn't bound to; + //[KBearerReady] - a valid serviceProvider cookie that this node is already bound to; + //[KBearerReady] - a NULL serviceProvider (this node is at the stack's bottom); + + //{ JOINING NEW SERVICE PROVIDER + //a valid serviceProvider supplied, new to this node, let's join it; + NODEACTIVITY_ENTRY(KNoTag, CBindToActivity::TSendControlClientJoinRequest, CoreStates::TAwaitingJoinComplete, TTag) + //} + + //serviceProvider provisionally joined. Now the activity needs to propagate iteslf (TBindTo) to its dataclients. + //The dataclients are either present or not. If not this activity will assume this is the layer construction phase + //and will attempt to construct a default dataclient. + THROUGH_NODEACTIVITY_ENTRY(KBearerReady, MeshMachine::TDoNothing, CBindToActivity::TNoTagOrDataClientReady) + + //{ DATA CLIENT CREATION + //No dataclients present, assume this is the layer creation phase. Attempt to create a dataclient. + NODEACTIVITY_ENTRY(KNoTag, CBindToActivity::TCreateDataClient, TAcceptErrorState, MeshMachine::TErrorTagOr) + //BindTo activity is the pre-start layer builder, hence it always requests the dataclient from the factory. + //The factory (being aware of the phase) may decide to: + //1. create a new dataclient -> process dataclient creation [KNoTag] + //2. return a preexisting dataclient -> bind the client [KDataClientReady] + //3. not to create a dataclient -> send TBindToComplete to the originator [KBindToComplete] + THROUGH_NODEACTIVITY_ENTRY(KNoTag, PRStates::TProcessDataClientCreation, TTag) + //} + + THROUGH_NODEACTIVITY_ENTRY(KDataClientReady, MeshMachine::TDoNothing, CBindToActivity::TNoTagOrBearerReadyOrBindToComplete) + //{ BINDING DATACLIENTS LOOP + //Dataclient(s) is/are ready. Depending on whether the node has the lower layer or not, + //we will [KNoTag] or will not [KNoBearer] need to request a binder for the dataclient. + + //{SERVICE PROVIDER PRESENT + NODEACTIVITY_ENTRY(KNoTag, CBindToActivity::TRequestCommsBinder, TAcceptErrorState, TErrorTagOr >) + //} + NODEACTIVITY_ENTRY(KBearerReady, PRActivities::CBindToActivity::TSendBindTo, CBindToActivity::TAwaitingBindToCompleteOrError, + TErrorTagOr >) + //} + + //Binding is finished. If this is not autocommit (see TCFDataClient::TBindTo), the activity will reply TCFDataClient::TBindToComplete + //to the sender await for the confirmation (TCFDataClient::TCommitBindTo) or cancelation (TBase::TCancel) from the sender. + //If this is autommit, the activity will skip awaiting for TCFDataClient::TCommitBindTo and commit itself. + THROUGH_NODEACTIVITY_ENTRY(KBindToComplete, CBindToActivity::TSendBindToComplete, CBindToActivity::TNoTagOrCommit) + NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing, MeshMachine::TAwaitingMessageState, TErrorTagOr >) + + //commiting (either implicit or explicit). + NODEACTIVITY_ENTRY(KCommit, CBindToActivity::TCommit, MeshMachine::TAwaitingLeaveComplete, MeshMachine::TNoTag) + + //This is not autocommit and the sender has just explicitly cancelled. Alternativelly this is an error path. + //Cancelling/processing error entiles sending TCancel to all dataclients awaiting confirmation + //as well as it entiles leaving the new service provider. + NODEACTIVITY_ENTRY(KErrorTag, CBindToActivity::TCancel, MeshMachine::TAwaitingLeaveComplete, MeshMachine::TNoTag) + + LAST_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing) +NODEACTIVITY_END() +} + +namespace PRStartActivity +{ +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityStart, PRStart, TCFServiceProvider::TStart, PRActivities::CStartActivity::NewL) + FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingStart, CoreNetStates::TNoTagOrBearerPresentBlockedByStop) + NODEACTIVITY_ENTRY(KBearerPresent, CoreNetStates::TBindSelfToPresentBearer, CoreNetStates::TAwaitingBindToComplete, TTag) + NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendNoBearer, MeshMachine::TAwaitingMessageState, CoreNetStates::TNoTagOrBearerPresentOrErrorTag) + + //Start the service provider, use the default cancellation. + //Forward TCancel to the service provider, wait for TStarted or TError (via the Error Activity) + //When TStarted arrives after TCancel the activity will move to the nearest KErrorTag + NODEACTIVITY_ENTRY(KBearerPresent, CoreNetStates::TStartServiceProviderRetry, CoreNetStates::TAwaitingStarted, MeshMachine::TNoTagOrErrorTag) + LAST_NODEACTIVITY_ENTRY(KErrorTag, MeshMachine::TDoNothing) + //Start data clients, use the default cancellation. + //Forward TCancel to the self, wait for TCFDataClient::TStarted or TError (via the Error Activity) + //When TCFDataClient::TStarted arrives after TCancel the activity will move to the nearest KErrorTag + NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TStartSelf, CoreNetStates::TAwaitingDataClientStarted, MeshMachine::TNoTagOrErrorTag) + NODEACTIVITY_ENTRY(KErrorTag, CoreNetStates::TStopSelf, CoreNetStates::TAwaitingDataClientStopped, MeshMachine::TErrorTag) + LAST_NODEACTIVITY_ENTRY(KErrorTag, MeshMachine::TRaiseAndClearActivityError) + LAST_NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendStarted) +NODEACTIVITY_END() +} + +namespace PRStopActivity +{ +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityStop, PRStop, TCFServiceProvider::TStop, MeshMachine::CNodeRetryActivity::NewL) + FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingStop, TActiveOrNoTagBlockedByBindTo) + THROUGH_NODEACTIVITY_ENTRY(KActiveTag, CoreNetStates::TCancelDataClientStart, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TStopSelf, CoreNetStates::TAwaitingDataClientStopped, CoreNetStates::TNoTagOrNoBearer) + NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendStop, CoreNetStates::TAwaitingStopped, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendClientLeavingRequestToServiceProvider, MeshMachine::TAwaitingLeaveComplete, TTag) + LAST_NODEACTIVITY_ENTRY(CoreNetStates::KNoBearer, PRStates::TSendStoppedAndGoneDown) +NODEACTIVITY_END() +} + +namespace PRDataClientStartActivity +{ +DECLARE_DEFINE_NODEACTIVITY(ECFActivityStartDataClient, PRDataClientStart, TCFDataClient::TStart) + FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingDataClientStart, CoreNetStates::TNoTagOrNoDataClients) + NODEACTIVITY_ENTRY(KNoTag, PRStates::TStartDataClients, TAcceptErrorState, MeshMachine::TErrorTagOr >) + LAST_NODEACTIVITY_ENTRY(CoreNetStates::KNoDataClients, PRStates::TSendDataClientStarted) + + NODEACTIVITY_ENTRY(KErrorTag, CoreNetStates::TStopSelf, CoreNetStates::TAwaitingDataClientsStopped, MeshMachine::TErrorTag) + LAST_NODEACTIVITY_ENTRY(KErrorTag, MeshMachine::TRaiseAndClearActivityError) +NODEACTIVITY_END() +} + +namespace PRDataClientStopActivity +{ +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityStopDataClient, PRDataClientStop, TCFDataClient::TStop, MeshMachine::CNodeRetryActivity::NewL) + FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingDataClientStop, MeshMachine::TNoTag) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, PRStates::TProcessDataClientStop, CoreNetStates::TNoTagOrDataClientsToStopBlockedByStarting) + + NODEACTIVITY_ENTRY(CoreNetStates::KDataClientsToStop, CoreNetStates::TStopDataClients, CoreNetStates::TAwaitingDataClientsStopped, MeshMachine::TNoTag) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing, CoreNetStates::TNoTagOrUnbindOnStop) + + NODEACTIVITY_ENTRY(CoreNetStates::KUnbind, CoreNetStates::TSendClientLeavingRequestToServiceProvider, MeshMachine::TAwaitingLeaveComplete, MeshMachine::TNoTag) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, PRStates::TDestroyOrphanedDataClients, MeshMachine::TNoTag) + LAST_NODEACTIVITY_ENTRY(KNoTag, PRStates::TSendDataClientStopped) +NODEACTIVITY_END() +} + + +namespace PRForwardStateChangeActivity +{ +DECLARE_DEFINE_NODEACTIVITY(ECFActivityForwardStateChange, PRForwardStateChange, TCFMessage::TStateChange) + NODEACTIVITY_ENTRY(KNoTag, PRStates::TForwardStateChange, MeshMachine::TAwaitingMessageState, MeshMachine::TNoTag) +NODEACTIVITY_END() +} + +namespace PRDataClientStatusChangeActivity +{ +DECLARE_DEFINE_NODEACTIVITY(ECFActivityDataClientStatusChange, PRDataClientStatusChange, TCFControlProvider::TDataClientStatusChange) + NODEACTIVITY_ENTRY(KNoTag, PRStates::THandleDataClientStatusChangeAndDestroyOrphans, CoreNetStates::TAwaitingDataClientStatusChange, MeshMachine::TNoTag) +NODEACTIVITY_END() +} + +namespace PRGoneDownActivity +{ +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityGoneDown, PRGoneDown, TCFControlClient::TGoneDown, CGoneDownActivity::NewL) + // Our Service Provider has gone down unexpectedly (we haven't issued a TStop) + FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingGoneDown, MeshMachine::TNoTag) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TCancelAndCloseZone0ClientExtIfaces, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendClientLeavingRequestToServiceProvider, MeshMachine::TAwaitingLeaveComplete, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, CGoneDownActivity::TSendErrorRecoveryReq, MeshMachine::TAwaitingErrorRecoveryResponseOrError, CoreStates::TRetryOrIgnoreOrPropagate) + THROUGH_NODEACTIVITY_ENTRY(CoreStates::KRetry, MeshMachine::TDoNothing, CGoneDownActivity::TIgnoreOrPropagate) + LAST_NODEACTIVITY_ENTRY(CoreStates::KIgnore, MeshMachine::TDoNothing) + NODEACTIVITY_ENTRY(CoreStates::KPropagate, CoreNetStates::TCancelStartAndStopSelf, CoreNetStates::TAwaitingDataClientStopped, MeshMachine::TNoTag) + LAST_NODEACTIVITY_ENTRY(KNoTag, PRStates::TSendGoneDown) +NODEACTIVITY_END() +} + + +namespace PRGoneUpActivity +{ +// This Activity forward the TGoneUp event to the Control Clients nodes that are +// not in the originator lis + +DECLARE_DEFINE_NODEACTIVITY(ECFActivityGoneUp, PRGoneUp, TCFControlClient::TGoneUp) + FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingGoneUp, MeshMachine::TNoTag) + LAST_NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendGoneUp) +NODEACTIVITY_END() +} + +namespace PRLegacyRMessage2HandlerActivity +{ +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityLegacyRMessage2Handler, PRLegacyRMessage2Handler, TNodeSignal::TNullMessageId, MeshMachine::CNodeParallelMessageStoreActivityBase::NewL) + FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingLegacyRMessage2Ext, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TProcessOrForwardRMessage2Ext, CoreNetStates::TAwaitingRMessage2Processed, MeshMachine::TNoTag) + LAST_NODEACTIVITY_ENTRY(KNoTag, CoreStates::TPostToOriginators) +NODEACTIVITY_END() +} + + +namespace CoreActivities +{ +DECLARE_DEFINE_ACTIVITY_MAP(coreActivitiesAll) + ACTIVITY_MAP_ENTRY(CoreErrorActivity, CoreError) //Must be first in the table +ACTIVITY_MAP_END() + +//-========================================================= +// +//Error Activity +// +//-========================================================= +MeshMachine::CNodeActivityBase* CErrorActivity::NewL( const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode ) + { + TUint c = GetNextActivityCountL(aActivitySig,aNode); + return new(ELeave)CErrorActivity(aActivitySig, aNode, c); + } + +CErrorActivity::CErrorActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode, TUint aActivitiesCount) + : MeshMachine::CNodeParallelActivityBase(aActivitySig, aNode, aActivitiesCount), iErroredActivityId(MeshMachine::KActivityNull) + { + } + +CErrorActivity::~CErrorActivity() + { + if (Error() != KErrNone) + { + CNodeActivityBase* a = iNode.FindActivityById(iErroredActivityId); + if (a) + { + a->SetError(Error()); + a->SetIdle(); + } + } + SetError(KErrNone); + } + +TBool CErrorActivity::IsIdle() const + { + return NetStateMachine::ACore::IsIdle(); + } + +void CErrorActivity::StartL(TNodeContextBase& aContext, const Messages::XNodePeerId& /*aOriginator*/, const TStateTriple& aFirst) + { + __ASSERT_DEBUG(IsIdle(), User::Panic(KSpecAssert_ESockCrStaCPRAC, 1)); + MESH_LOG_ACTIVITY_EXT(KESockMeshMachine, this, &aContext, (_L8("CErrorActivity %08x:\tStartL->starting activity"), this)); + + NetStateMachine::ACore::Start(&aContext, aFirst); + + MESH_LOG_ACTIVITY_EXT(KESockMeshMachine, this, &aContext, (_L8("CErrorActivity %08x:\tStartL->activity started"),this)); + } + +TBool CErrorActivity::Next(TNodeContextBase& aContext) + { + TBool ret = EFalse; + + + if (aContext.iMessage.IsMessage()) + { + CNodeActivityBase* a = iNode.FindActivityById(iErroredActivityId); + //Special handling for TCancel. + if (a && a->FindOriginator(aContext.iSender) != KErrNotFound) + { + ret = ETrue; + //iActiviy could have handled it, but chose not to. + Cancel(aContext); + //consume the message, otherwise the iActivity will get idled and iActivity reference + //will become invalid. + aContext.iMessage.ClearMessageId(); + } + } + else + { + //If we have sent TErrorRecoveryRequest, we had to have set PostedToId() to the recipient (ControlProvider) + //as otherwise there would be no path for propagating the potential TCancel. + //The response however (TErrorRecoveryResponse or TError) will not necesserily come from that recipient (CP) + //(for example it could be coming from the MCpr and we could be the SCpr). + //Normally this would be a problem because any unrelated TError message arriving to the node + //and presented to the awaiting state would easily be confused with the response (TError == no recovery on the MCpr == EPropagate). + //We avoid the problem by checking all arriving messages if they are adressed to our activity (but we don't + //check the sender. + const TNodeCtxId* recipient = address_cast(&aContext.iRecipient); + if (recipient && (ActivityId() == recipient->NodeCtx())) + { + ret = ACore::Next(&aContext); + if(ret) + { + MESH_LOG_ACTIVITY_EXT(KMeshMachineSubTag, this, &aContext, (_L8("CNodeActivityBase %08x:\tNext->transition"), this)); + } + } + } + return ret; + } + +EXPORT_DEFINE_SMELEMENT(CErrorActivity::TAwaitingError, NetStateMachine::MState, CErrorActivity::TContext) +EXPORT_C TBool CErrorActivity::TAwaitingError::Accept() + { + if (! iContext.iMessage.IsMessage()) + { + return EFalse; + } + + TEBase::TError& errorMessage = message_cast(iContext.iMessage); + + //Diagnostic panic only. TError message should not be travelling around with KErrNone. + //If you see this panic, please send a proper error code. + __ASSERT_DEBUG(errorMessage.iValue != KErrNone, User::Panic(KSpecAssert_ESockCrStaCPRAC, 2)); + + MeshMachine::CNodeActivityBase* aa = iContext.Node().FindAddressedActivity(iContext); + + //TError is always a response. If there is no activity addressed by the TError, + //then we assume the activity hasn't bothered waiting for the result. + //We hence ignore the error. + if (aa) + { + aa->SetError(errorMessage.iValue); + aa->SetIdle(); + } + errorMessage.ClearMessageId(); + return EFalse; + } + +DEFINE_SMELEMENT(CErrorActivity::TCFAwaitingError, NetStateMachine::MState, CErrorActivity::TContext) +EXPORT_C TBool CErrorActivity::TCFAwaitingError::Accept() + { + if (! iContext.iMessage.IsMessage()) + { + return EFalse; + } + + TEBase::TError& errorMessage = message_cast(iContext.iMessage); + + //Diagnostic panic only. TError message should not be travelling around with KErrNone. + //If you see this panic, please send a proper error code. + __ASSERT_DEBUG(errorMessage.iValue != KErrNone, User::Panic(KSpecAssert_ESockCrStaCPRAC, 3)); + + RNodeInterface* client = iContext.Node().FindClient(iContext.iSender); + if (client && + client->Type() & TCFClientType::EServProvider && + iContext.Node().ControlProvider() != NULL && + iContext.Node().CountActivities(ECFActivityDestroy) == 0) + { + //this is the only way out into the activity and into error recovery steps + //that error activity is responsible for doing. + return ETrue; + } + + return CErrorActivity::TAwaitingError::Accept(); + } + +//Simply leaving from this DoL will NOT have the effect of sending TError to originators +//of the Errored activity! iContext.iNodeActivity is the Error activity. +//Reassign iContext.iNodeActivity before leaving or handle the error. +EXPORT_DEFINE_SMELEMENT(CErrorActivity::TSendErrorRecoveryReq, NetStateMachine::MStateTransition, CErrorActivity::TContext) +EXPORT_C void CErrorActivity::TSendErrorRecoveryReq::DoL() + { + //Find matching activity, if any + MeshMachine::CNodeActivityBase* aa = iContext.Node().FindAddressedActivity(iContext); + //we are started based on the fact the the last message iContext.Node()'s received is TError + TEBase::TError& errmsg = message_cast(iContext.iMessage); + + //The error comes from someone else than our Data Client (or we wouldn't be here). + //It may be our Service Provider or it can be some other node which has originated + //an activity on us (in which case the errored activity must be present). + if (aa==NULL) + { + __CFLOG_VAR((KCoreProviderStatesTag, KCoreProviderStatesSubTag, _L8("ASendErrorRecoveryReq::DoL - TError but no addressed activity - ignoring"))); +#ifdef SYMBIAN_NETWORKING_UPS + // Terminate the error activity (not UPS specific). + iContext.iNodeActivity->SetIdle(); +#endif //SYMBIAN_NETWORKING_UPS + return; + } + + AContextStore* intf = NULL; + if (aa->SupportsExtInterface(AContextStore::KInterfaceId)) + { + //FetchExtInterfaceL below can never leave because it is being checked few lines above in the "if" + intf = reinterpret_cast(aa->FetchExtInterfaceL(AContextStore::KInterfaceId)); + } + + //Check if there is any point in sending Error Recovery Request + if (intf==NULL || !intf->IsStored() || !iContext.Node().ControlProvider()) + { + __CFLOG_VAR((KCoreProviderStatesTag, KCoreProviderStatesSubTag, _L8("ERROR: ASendErrorRecoveryReq::DoL - KErrNotSupported"))); + iContext.iNodeActivity->SetIdle(); + aa->SetError(errmsg.iValue); + aa->SetIdle(); + return; + } + + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + CoreActivities::CErrorActivity& activity = static_cast(*iContext.iNodeActivity); + __ASSERT_DEBUG(activity.iErroredActivityId==MeshMachine::KActivityNull, User::Panic(KSpecAssert_ESockCrStaCPRAC, 4)); + // Save a reference to the activity and a point + // Each time we use the activity, query it from the node, because the activity may have gone away (originator left node etc) + activity.iErroredActivityId = aa->ActivityId(); + + activity.SetError(errmsg.iValue); + activity.iMessageId = errmsg.iMsgId; + + TErrContext ctx(iContext.NodeId(), errmsg.iMsgId, aa->ActivitySigId(), TStateChange(0, errmsg.iValue)); + TEErrorRecovery::TErrorRecoveryRequest msg(ctx); + + activity.PostRequestTo( + *iContext.Node().ControlProvider(),//ControlProvider() verified above + TCFSafeMessage::TRequestCarrierEast(msg).CRef() + ); + + //The original activiy might have set 'sent to', but that's surely + //not meaningful anymore (we've just received a response from that 'sent to'). + //We could have pretended that the orginal activity knows it's sent + //error recovery to the control provider but it's best just to clear + //'sent to' (and handle TCancel from here (CErrorActivity::Next()). + aa->ClearPostedTo(); + } + +EXPORT_DEFINE_SMELEMENT(CErrorActivity::TDoErrorRecovery, NetStateMachine::MStateTransition, CErrorActivity::TContext) +EXPORT_C void CErrorActivity::TDoErrorRecovery::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + CoreActivities::CErrorActivity* act = static_cast(iContext.iNodeActivity); + CNodeActivityBase* a = iContext.Node().FindActivityById(act->iErroredActivityId); + if (a == NULL) + { + iContext.iNodeActivity->SetIdle(); + return; + } + + if (iContext.iMessage.IsMessage()) + { + TErrResponse& resp = message_cast(iContext.iMessage).iErrResponse; + if (resp.iAction == TErrResponse::ERetry) + { //rerun current transition + __CFLOG_VAR((KCoreProviderStatesTag, KCoreProviderStatesSubTag, _L8("ADoErrorRecovery::DoL - instructed to retry"))); + __ASSERT_DEBUG(a->SupportsExtInterface(AContextStore::KInterfaceId), User::Panic(KCorePrPanic, KPanicExtInterfaceNotSupported)); + + AContextStore* intf = reinterpret_cast(a->FetchExtInterfaceL(AContextStore::KInterfaceId)); + __ASSERT_DEBUG(intf->IsStored(), User::Panic(KSpecAssert_ESockCrStaCPRAC, 5)); + intf->Retry(*a,iContext); + if (iContext.iReturn == KErrNone) + { //retry succeded + act->SetError(KErrNone); + } + //if Retry had failed, then the d'tor of act will raise the error on + //and terminate act->iActivity, + } + else if (resp.iAction == TErrResponse::EPropagate) + { //set new error values and fall through + __CFLOG_VAR((KCoreProviderStatesTag, KCoreProviderStatesSubTag, _L8("ADoErrorRecovery::DoL - instructed to propagate the error"))); + act->iMessageId = resp.iMessageId; + a->SetError(resp.iError); + } + else //if (resp.iAction == TErrResponse::EIgnore) + { + __CFLOG_VAR((KCoreProviderStatesTag, KCoreProviderStatesSubTag, + _L8("WARNING: ADoErrorRecovery::DoL() - instructed to ignore the error!"))); + } + } + } + + +//-========================================================= +// +//Destroy Activity - will delete the node when destructed +// +//-========================================================= + +EXPORT_C MeshMachine::CNodeActivityBase* CDestroyActivity::New(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) + { + TAny* space = BorrowPreallocatedSpace(aNode, sizeof(CDestroyActivity)); + CDestroyActivity* self = new (space) CDestroyActivity(aActivitySig, aNode); + self->InsertPreallocatedDestroyActivity(); //Destructing preallocated activity + return self; + } + +CDestroyActivity::CDestroyActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) +: CNodeRetryActivity(aActivitySig, aNode), + APreallocatedOriginators<1>(iOriginators) + { + //Mark the provider for deletion, so that it's not served by the factory from now on. + static_cast(iNode).MarkMeForDeletion(); + } + +void CDestroyActivity::Destroy() + { + ReturnPreallocatedSpace(this); + this->~CDestroyActivity(); //Run the destructor + + //Delete the provider. + static_cast(iNode).DeleteMeNow(); + } + +TBool CDestroyActivity::Next(TNodeContextBase& aContext) + { + if (aContext.iMessage.IsMessage()) + { + return ETrue; + } + else + return CNodeActivityBase::Next(aContext); + } + +EXPORT_DEFINE_SMELEMENT(CDestroyActivity::TNoTagOrNoTagBackwards, NetStateMachine::MStateFork, PRStates::TContext) +EXPORT_C TInt CDestroyActivity::TNoTagOrNoTagBackwards::TransitionTag() + { + if (iContext.iMessage.IsMessage()) + { + TClientIter iter = iContext.Node().GetClientIter(TClientType(TCFClientType::EData|TCFClientType::ECtrl)); + __ASSERT_DEBUG(iter[0], User::Panic(KSpecAssert_ESockCrStaCPRAC, 7)); //One leaving client must still be there. + return iter[1] == NULL ? MeshMachine::KNoTag : MeshMachine::KNoTag | NetStateMachine::EBackward; + } + else if (iContext.iMessage.IsMessage()) + { + __ASSERT_DEBUG(iContext.Node().GetFirstClient(TClientType(TCFClientType::ECtrl|TCFClientType::EData))==NULL, + User::Panic(KCorePrPanic, KPanicClientsStillPresent)); + if (iContext.Node().GetFirstClient(TClientType(TCFClientType::EServProvider))==NULL) + { + return NetStateMachine::EForward | MeshMachine::KNoTag; + } + return NetStateMachine::EBackward | MeshMachine::KNoTag; //Loop back to the same triple (& remove the peer) + } + __ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockCrStaCPRAC, 8)); + return KNoTag; + } + +EXPORT_DEFINE_SMELEMENT(CDestroyActivity::TMakeClientsLeaveOrProcessClientLeave, NetStateMachine::MStateTransition, PRStates::TContext) +EXPORT_C void CDestroyActivity::TMakeClientsLeaveOrProcessClientLeave::DoL() + { + if (iContext.iMessage.IsMessage()) + { + ProcessClientLeaveL(); + } + else + { + MakeClientsLeaveL(); + } + } + +void CDestroyActivity::TMakeClientsLeaveOrProcessClientLeave::MakeClientsLeaveL() + { + __ASSERT_DEBUG(iContext.Node().GetFirstClient(TClientType(TCFClientType::ECtrl))==NULL, + User::Panic(KCorePrPanic, KPanicClientsStillPresent)); + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + iContext.iNodeActivity->ClearPostedTo(); + + //MZTODO: this asserion may need to be changed since TDestroy can + //come while data client is active etc. + __ASSERT_DEBUG(iContext.Node().GetFirstClient(TClientType(TCFClientType::EData, TCFClientType::EActive|TCFClientType::EActivating|TCFClientType::EStarting|TCFClientType::EStarted))==NULL, + User::Panic(KCorePrPanic, KPanicClientsStillPresent)); + + TClientIter dciter = iContext.Node().GetClientIter(TClientType(TCFClientType::EData), TClientType(0, TCFClientType::ELeaving)); + RNodeInterface* dc = NULL; + while ((dc = dciter[0]) != NULL) //always inspect the first elem as we're invalidating the iterator with each hit. + { + dc->PostMessage(iContext.NodeId(), TEChild::TDestroy().CRef()); + dc->SetFlags(TCFClientType::ELeaving); + } + } + +void CDestroyActivity::TMakeClientsLeaveOrProcessClientLeave::ProcessClientLeaveL() + { + CDestroyActivity::TProcessClientLeave processClientLeave(iContext); + processClientLeave.DoL(); + } + + +//-========================================================= +// +//Loppin Activity +// +//-========================================================= +EXPORT_C ACountLoopActivity::~ACountLoopActivity() + { + } + + +EXPORT_C MeshMachine::CNodeActivityBase* CCountLoopActivityBase::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) + { + return new (ELeave) CCountLoopActivityBase(aActivitySig, aNode); + } + +EXPORT_C CCountLoopActivityBase::CCountLoopActivityBase(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) +: MeshMachine::CNodeActivityBase(aActivitySig, aNode), + TIfStaticFetcherNearestInHierarchy(this) + { + } + +EXPORT_C CCountLoopActivityBase::~CCountLoopActivityBase() + { + } + +EXPORT_DEFINE_SMELEMENT(ACountLoopActivity::TNoTagOrNoTagBackwards, NetStateMachine::MStateFork, PRStates::TContext) +EXPORT_C TInt ACountLoopActivity::TNoTagOrNoTagBackwards::TransitionTag() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + __ASSERT_DEBUG(iContext.iNodeActivity->SupportsExtInterface(ACountLoopActivity::KInterfaceId),User::Panic(KCorePrPanic, KPanicInterfaceNotSupported)); + ACountLoopActivity* countLoopActivity = static_cast(iContext.iNodeActivity->FetchExtInterface(ACountLoopActivity::KInterfaceId)); + if (countLoopActivity->DecCount() > 0) + { + return KNoTag | NetStateMachine::EBackward; + } + return KNoTag | NetStateMachine::EForward; + } + + + + + +//-========================================================= +// +// +//Binding Activity +// +// +//-========================================================= +EXPORT_C ABindingActivity::~ABindingActivity() + { + //Handle premature termination of the ABindingActivity object + //by responding to the originator + //If the originator has not been replied to yet, reply now with an error code + if (IsBinding()) + { + ReplyToOriginator(KErrAbort); + } + } + +EXPORT_C void ABindingActivity::StoreOriginator(const TRuntimeCtxId& aNodeCtxId) + { + //Check if the originator wasn't set before. If it was, it must be replied to before storing ths new one. + __ASSERT_DEBUG(iOriginator.IsNull(), User::Panic(KSpecAssert_ESockCrStaCPRAC, 9)); + iOriginator = aNodeCtxId; + } + +EXPORT_C void ABindingActivity::ReplyToOriginator(TInt aError) + { + //NOTE: Please do not make this diagnostic panic conditional. + //Please allow it to server everyone equally. + //Please handle the error conditions properly so that you obey this API's semantics. + //If you are not providing a clean error handling solution for your activity, + //please use IsBinding() before calling this API! + __ASSERT_DEBUG(!iOriginator.IsNull(), User::Panic(KSpecAssert_ESockCrStaCPRAC, 10)); //The iOriginator must be set. + RClientInterface::OpenPostMessageClose(iOurNode, iOriginator, TCFDataClient::TBindToComplete(aError).CRef()); + iOriginator.SetNull(); + } + +EXPORT_DEFINE_SMELEMENT(ABindingActivity::TSendBindToComplete, NetStateMachine::MStateTransition, CoreStates::TContext) +EXPORT_C void ABindingActivity::TSendBindToComplete::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + __ASSERT_DEBUG(iContext.iNodeActivity->SupportsExtInterface(ABindingActivity::KInterfaceId), User::Panic(KSpecAssert_ESockCrStaCPRAC, 11)); + ABindingActivity* bindingActivity = reinterpret_cast(iContext.iNodeActivity->FetchExtInterfaceL(ABindingActivity::KInterfaceId)); + bindingActivity->ReplyToOriginator(iContext.iNodeActivity->Error()); + } + +EXPORT_DEFINE_SMELEMENT(ABindingActivity::TSendBindToCompleteIfExpected, NetStateMachine::MStateTransition, CoreStates::TContext) +EXPORT_C void ABindingActivity::TSendBindToCompleteIfExpected::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + __ASSERT_DEBUG(iContext.iNodeActivity->SupportsExtInterface(ABindingActivity::KInterfaceId), User::Panic(KSpecAssert_ESockCrStaCPRAC, 12)); + ABindingActivity* bindingActivity = reinterpret_cast(iContext.iNodeActivity->FetchExtInterfaceL(ABindingActivity::KInterfaceId)); + if (bindingActivity->IsBinding()) + { + bindingActivity->ReplyToOriginator(iContext.iNodeActivity->Error()); + } + } + +void ABindingActivity::FinalReplyToOriginator(TInt aError) +/** +Intended to be called from derived class destructors to arrange for a TBindToComplete reply to be sent +before any other messages in those derived class destructors (for example TDestroy). +*/ + { + if (IsBinding()) + { + ReplyToOriginator(aError); + // Ensure that we don't send another reply in ~ABindingActivity. + iOriginator = Messages::TNodeCtxId(); + } + } + +} // CoreActivities + + +namespace PRActivities +{ +DECLARE_DEFINE_ACTIVITY_MAP(coreActivitiesPR) + ACTIVITY_MAP_ENTRY(PRDataClientJoinActivity, PRDataClientJoin) + ACTIVITY_MAP_ENTRY(PRControlClientJoinActivity, PRControlClientJoin) + ACTIVITY_MAP_ENTRY(PRClientLeaveActivity, PRClientLeave) + ACTIVITY_MAP_ENTRY(PRForwardStateChangeActivity, PRForwardStateChange) + ACTIVITY_MAP_ENTRY(PRBindToActivity, PRBindTo) +ACTIVITY_MAP_END_BASE(CoreActivities,coreActivitiesAll) + +//Activity Map provided by CorePr to be used by SCprs. +//(it is further extended in CoreSCpr). +DEFINE_EXPORT_ACTIVITY_MAP(coreActivitiesSCpr) + ACTIVITY_MAP_ENTRY(PRProvisionActivity, PrProvision) + ACTIVITY_MAP_ENTRY(PRStartActivity, PRStart) + ACTIVITY_MAP_ENTRY(PRStopActivity, PRStop) + ACTIVITY_MAP_ENTRY(PRDataClientStartActivity, PRDataClientStart) + ACTIVITY_MAP_ENTRY(PRDataClientStopActivity, PRDataClientStop) + ACTIVITY_MAP_ENTRY(PRDataClientIdleActivity, PRDataClientIdle) + ACTIVITY_MAP_ENTRY(PRDataClientActiveActivity, PRDataClientActive) + ACTIVITY_MAP_ENTRY(PRDestroyActivity, PRDestroy) + ACTIVITY_MAP_ENTRY(PRGoneDownActivity, PRGoneDown) + ACTIVITY_MAP_ENTRY(PRGoneUpActivity, PRGoneUp) //robertomaro +#ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW + ACTIVITY_MAP_ENTRY(PRSetParamsRequest, PRSetParams) + ACTIVITY_MAP_ENTRY(PRGetParamsRequest, PRGetParams) +#endif // SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW + ACTIVITY_MAP_ENTRY(PRLegacyRMessage2HandlerActivity, PRLegacyRMessage2Handler) +ACTIVITY_MAP_END_BASE(PRActivities,coreActivitiesPR) + +//Activity Map provided by CorePr to be used by Cprs. +//(it is further extended in CoreCpr). +DEFINE_EXPORT_ACTIVITY_MAP(coreActivitiesCpr) + ACTIVITY_MAP_ENTRY(PRProvisionActivity, PrProvision) + ACTIVITY_MAP_ENTRY(PRStartActivity, PRStart) + ACTIVITY_MAP_ENTRY(PRStopActivity, PRStop) + ACTIVITY_MAP_ENTRY(PRDataClientStartActivity, PRDataClientStart) + ACTIVITY_MAP_ENTRY(PRDataClientStopActivity, PRDataClientStop) + ACTIVITY_MAP_ENTRY(PRDataClientIdleActivity, PRDataClientIdle) + ACTIVITY_MAP_ENTRY(PRDataClientActiveActivity, PRDataClientActive) + ACTIVITY_MAP_ENTRY(PRDestroyActivity, PRDestroy) + ACTIVITY_MAP_ENTRY(PRGoneDownActivity, PRGoneDown) + ACTIVITY_MAP_ENTRY(PRGoneUpActivity, PRGoneUp) //robertomaro + ACTIVITY_MAP_ENTRY(PRDataClientStatusChangeActivity, PRDataClientStatusChange) +#ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW + ACTIVITY_MAP_ENTRY(PRSetParamsRequest, PRSetParams) + ACTIVITY_MAP_ENTRY(PRGetParamsRequest, PRGetParams) +#endif // SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW + ACTIVITY_MAP_ENTRY(PRLegacyRMessage2HandlerActivity, PRLegacyRMessage2Handler) +ACTIVITY_MAP_END_BASE(PRActivities,coreActivitiesPR) + +//Activity Map provided by CorePr to be used by MCprs. +//(it is further extended in CoreMCpr). +DEFINE_EXPORT_ACTIVITY_MAP(coreActivitiesMCpr) + ACTIVITY_MAP_ENTRY(PRDataClientIdleActivity, PRDataClientIdle) + ACTIVITY_MAP_ENTRY(PRDataClientActiveActivity, PRDataClientActive) + ACTIVITY_MAP_ENTRY(PRDataClientStatusChangeActivity, PRDataClientStatusChange) + ACTIVITY_MAP_ENTRY(PRLegacyRMessage2HandlerActivity, PRLegacyRMessage2Handler) +ACTIVITY_MAP_END_BASE(PRActivities,coreActivitiesPR) + +//Activity Map provided by CorePr to be used by TMs. +//(it is further extended in CoreTM). +DEFINE_EXPORT_ACTIVITY_MAP(coreActivitiesTM) +ACTIVITY_MAP_END_BASE(PRActivities,coreActivitiesPR) + + + + +//-========================================================= +// +//CBindToActivity +// +//-========================================================= +EXPORT_C CBindToActivity::CBindToActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode, TInt aNextActivityCount) + : MeshMachine::CNodeParallelActivityBase(aActivitySig, aNode, aNextActivityCount), + CoreActivities::ABindingActivity(aNode.Id()), + TIfStaticFetcherNearestInHierarchy(this) + { + } + +EXPORT_C MeshMachine::CNodeActivityBase* CBindToActivity::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) + { + //there can be only one BindTo activity running at a time. + TUint c = GetNextActivityCountL(aActivitySig,aNode); + __ASSERT_DEBUG(c == 1,User::Panic(KCorePrPanic, KPanicPeerMisbehaving)); + if (c > 1) + { + User::Leave(KErrInUse); + } + return new (ELeave) CBindToActivity(aActivitySig, aNode, c); + } + +EXPORT_C CBindToActivity::~CBindToActivity() + { + //If the activity is aborted then no cleanup will be performed (the destroy activity will do + //that for us) so we should not assert that iSuccessfulDataClients is empty or iNewServiceProvider + //is null. + + //CBindToActivity::TCommit or CBindToActivity::TCancel should have been executed + //and rendered iSuccessfulDataClients empty. + //__ASSERT_DEBUG(iSuccessfulDataClients.Count() == 0, User::Panic(KCorePrPanic, KPanicIncorrectState)); + + //CBindToActivity::iNewServiceProvider should have been cleared by CBindToActivity::TCommit or CBindToActivity::TCancel + //__ASSERT_DEBUG(iNewServiceProvider == NULL, User::Panic(KCorePrPanic, KPanicIncorrectState)); + + iSuccessfulDataClients.Close(); + } + +Messages::RNodeInterface* CBindToActivity::NextDataClient() + { + TClientIter iter = iNode.GetClientIter( + /*include*/TClientType(TCFClientType::EData), + /*exclude*/TClientType(0, TCFClientType::ELeaving | TCFClientType::EConfigAccessPoint)); + iCurrentDataClient = iter++; + while (iCurrentDataClient && (iSuccessfulDataClients.Find(iCurrentDataClient) != KErrNotFound)) + { + iCurrentDataClient = iter++; + }; + return iCurrentDataClient; + } + +TBool CBindToActivity::DataClientsAutocommit() + { + TInt nonLeavingDataClients = iNode.CountClients( + /*include*/TClientType(TCFClientType::EData), + /*exclude*/TClientType(0, TCFClientType::ELeaving | TCFClientType::EConfigAccessPoint)); + return nonLeavingDataClients <=1 && IsAutocommit(); + } + + +void CBindToActivity::AddClientAsSuccessfulL(Messages::RNodeInterface* aDataClient) + { + __ASSERT_DEBUG(aDataClient, User::Panic(KCorePrPanic, KPanicDataClient)); + __ASSERT_DEBUG(iSuccessfulDataClients.Find(aDataClient) == KErrNotFound, User::Panic(KCorePrPanic, KPanicIncorrectState)); + iSuccessfulDataClients.Append(aDataClient); + } + +void CBindToActivity::RemoveClientFromSuccessful(Messages::RNodeInterface* aDataClient) + { + TInt index = iSuccessfulDataClients.Find(aDataClient); + __ASSERT_DEBUG(index >= 0, User::Panic(KCorePrPanic, KPanicDataClient)); + iSuccessfulDataClients.Remove(index); + } + +EXPORT_DEFINE_SMELEMENT(CBindToActivity::TSendControlClientJoinRequest, NetStateMachine::MStateTransition, CBindToActivity::TContext) +void CBindToActivity::TSendControlClientJoinRequest::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + CBindToActivity& activity = static_cast(*iContext.iNodeActivity); + const TCFDataClient::TBindTo& bindToMsg(message_cast(iContext.iMessage)); + + __ASSERT_DEBUG(!bindToMsg.iNodeId.IsNull(), User::Panic(KCorePrPanic, KPanicNoServiceProvider)); + RNodeInterface* newServiceProvider = iContext.Node().AddClientL(bindToMsg.iNodeId, + TClientType(TCFClientType::EServProvider, TCFClientType::EActivating)); + __ASSERT_DEBUG(newServiceProvider, User::Panic(KCorePrPanic, KPanicNoServiceProvider)); + activity.iNewServiceProvider = bindToMsg.iNodeId; + //Join the new service provider + iContext.Activity()->PostRequestTo(*newServiceProvider, + TCFControlClient::TJoinRequest(iContext.NodeId(), TClientType(TCFClientType::ECtrl)).CRef()); + } + +EXPORT_DEFINE_SMELEMENT(CBindToActivity::TAwaitingBindToCompleteOrError, NetStateMachine::MState, CRejoinDataClientActivity::TContext) +TBool CBindToActivity::TAwaitingBindToCompleteOrError::Accept() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + CBindToActivity& activity = static_cast(*iContext.iNodeActivity); + if (CoreNetStates::TAwaitingBindToComplete(iContext).Accept()) + { + if (activity.IsBinding()) + { + //Activity is binding (i.e.: we havent received TBindToComplete as a response + //to null-carrying TBindTo. + activity.ReplyToOriginator(KErrNone); + } + activity.ResetCurrentDataClient(); + return ETrue; + } + else if (iContext.iMessage.IsMessage()) + { + activity.ReplyToOriginator(message_cast(iContext.iMessage).iValue); + activity.RemoveClientFromSuccessful(activity.CurrentDataClient()); + activity.ResetCurrentDataClient(); + return ETrue; + } + return EFalse; + } + +EXPORT_DEFINE_SMELEMENT(CBindToActivity::TNoTagOrDataClientReady, NetStateMachine::MStateFork, CBindToActivity::TContext) +TInt CBindToActivity::TNoTagOrDataClientReady::TransitionTag() + { + //Any non-leaving dataclients already present? + if (iContext.Node().CountClients( + /*include*/TClientType(TCFClientType::EData), + /*exclude*/TClientType(0, TCFClientType::ELeaving | TCFClientType::EConfigAccessPoint))) + { + return KDataClientReady; + } + return KNoTag; + } + + +EXPORT_DEFINE_SMELEMENT(CBindToActivity::TRequestCommsBinder, NetStateMachine::MStateTransition, CBindToActivity::TContext) +void CBindToActivity::TRequestCommsBinder::DoL() + { + __ASSERT_DEBUG(iContext.Node().CountClients(TClientType(TCFClientType::EData)),User::Panic(KCorePrPanic, KPanicDataClient)); + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + CBindToActivity& activity = static_cast(*iContext.iNodeActivity); + + //The service provider has been joined already and must be found here + __ASSERT_DEBUG(!activity.iNewServiceProvider.IsNull(), User::Panic(KCorePrPanic, KPanicNoServiceProvider)); + RNodeInterface* newServiceProvider = iContext.Node().FindClient(activity.iNewServiceProvider); + __ASSERT_DEBUG(newServiceProvider, User::Panic(KCorePrPanic, KPanicNoServiceProvider)); + //We must not be in this transition if dc was not found + __ASSERT_DEBUG(activity.CurrentDataClient(), User::Panic(KCorePrPanic, KPanicDataClient)); + + // Also if it is not so common to have multiple DataClient (except + // for the relation "SCPR<-CPR"), there are situation where it happens + // and where only one of them is marked as Default. + // So, we check if this is the case and, in case the + // Originator of this activity is NOT a Default one, send ECreateNew. + + // If the Current DC is marked as Default, we ask to the lower layer + // to "AttachToDefault". If it is not, we ask "CreateNew". + TInt subConnOpenType = (activity.CurrentDataClient()->Flags() & TCFClientType::EDefault) ? + TSubConnOpen::EAttachToDefault : TSubConnOpen::ECreateNew; + + // --- WORKAROUND START --- + // [399TODO] There are situation were we don't have any DataClient marked + // as Default, but, asking for ECreateNew, the lower layer doesn't + // manage the request very well. + // This is a WORKAROUND and need fixing (see DEF113154). + // In the meanwhile, we count the number of "DefaultDataClient" and, + // if the result is "0", we ask the lower layer "AttachToDefault" + TInt numberOfDefaultDataClient = iContext.Node().CountClients( + TClientType(TCFClientType::EData, TCFClientType::EDefault) + ); + if (numberOfDefaultDataClient == 0) + { + subConnOpenType = TSubConnOpen::EAttachToDefault; + } + // --- WORKAROUND END --- + + // Send "TCommsBinderRequest" to the Current ServiceProvider + activity.PostRequestTo( + *newServiceProvider, + TCFServiceProvider::TCommsBinderRequest(subConnOpenType).CRef() + ); + } + + +EXPORT_DEFINE_SMELEMENT(CBindToActivity::TCreateDataClient, NetStateMachine::MStateTransition, CBindToActivity::TContext) +void CBindToActivity::TCreateDataClient::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + + IssuePeerCreationRequestL (); + } + +EXPORT_DEFINE_SMELEMENT(CBindToActivity::TSendBindTo, NetStateMachine::MStateTransition, CBindToActivity::TContext) +void CBindToActivity::TSendBindTo::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + CBindToActivity& bindToActivity = static_cast(*iContext.iNodeActivity); + + //Provisionally stash the current dataclient as successful. If it fails to bind, we'll unstash it + //We're doing this now, as stashing may fail and we don't want that to be the sole reason for + //unrolling. + bindToActivity.AddClientAsSuccessfulL(bindToActivity.CurrentDataClient()); + + TCFServiceProvider::TCommsBinderResponse* commsBinderResponse = message_cast(&iContext.iMessage); + Messages::TNodeId commsBinder = commsBinderResponse ? commsBinderResponse->iNodeId : Messages::TNodeId::NullId(); + + bindToActivity.PostRequestTo(*bindToActivity.CurrentDataClient(), + TCFDataClient::TBindTo(commsBinder, !bindToActivity.DataClientsAutocommit()).CRef()); + } + +EXPORT_DEFINE_SMELEMENT(CBindToActivity::TSendBindToComplete, NetStateMachine::MStateTransition, CBindToActivity::TContext) +void CBindToActivity::TSendBindToComplete::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + iContext.iNodeActivity->PostToOriginators(TCFDataClient::TBindToComplete().CRef()); + } + +EXPORT_DEFINE_SMELEMENT(CBindToActivity::TNoTagOrCommit, NetStateMachine::MStateFork, CBindToActivity::TContext) +TInt CBindToActivity::TNoTagOrCommit::TransitionTag() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + CBindToActivity& bindToActivity = static_cast(*iContext.iNodeActivity); + if (bindToActivity.IsAutocommit()) + { + return KCommit; + } + return KNoTag; + } + +EXPORT_DEFINE_SMELEMENT(CBindToActivity::TNoTagOrBindToComplete, NetStateMachine::MStateFork, CBindToActivity::TContext) +EXPORT_C TInt CBindToActivity::TNoTagOrBindToComplete::TransitionTag() + { + TCFFactory::TPeerFoundOrCreated& dcJoined = message_cast(iContext.iMessage); + + if (dcJoined.iNodeId.IsNull()) + { + //Factory decided not to create a dataclient; + return KBindToComplete; + } + + //factory created a new citizen. + return KNoTag; + } + + +EXPORT_DEFINE_SMELEMENT(CBindToActivity::TNoTagOrBearerReady, NetStateMachine::MStateFork, CBindToActivity::TContext) +TInt CBindToActivity::TNoTagOrBearerReady::TransitionTag() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + CBindToActivity& bindToActivity = static_cast(*iContext.iNodeActivity); + TCFDataClient::TBindTo& bindToReq = message_cast(iContext.iMessage); + bindToActivity.SetAutocommit(!bindToReq.iValue); + + if (bindToReq.iNodeId.IsNull()) + //received a null service provider, the node is at the stack's bottom. + { + return KBearerReady; + } + + RNodeInterface* sp = iContext.Node().ServiceProvider(); + if (sp && bindToReq.iNodeId == sp->RecipientId()) + { + //received the same service provider, it's already bound to. + bindToActivity.iNewServiceProvider = sp->RecipientId(); + return KBearerReady; + } + RNodeInterface* newServiceProvider = iContext.Node().FindClient(bindToReq.iNodeId); + if (newServiceProvider) + { + __ASSERT_DEBUG(newServiceProvider->Type() == TCFClientType::EServProvider, User::Panic(KCorePrPanic, KPanicIncorrectState)); + //Ok, we've received a TBindTo holding a service provider that we already know of and that is not + //our current service provider. We're going to assume this node tolerates multiple service providers (like MCPRs do). + //the current service provider will be swapped, but won't be dropped. + bindToActivity.iNewServiceProvider = bindToReq.iNodeId; + newServiceProvider->SetFlags(TCFClientType::EActivating); + bindToActivity.SetDontLeaveServiceProvider(); + return KBearerReady; + } + else + { + bindToActivity.iNewServiceProvider = TNodeId::NullId(); + } + //The node received a new service provider... + return KNoTag; + } + + +EXPORT_DEFINE_SMELEMENT(CBindToActivity::TNoTagOrBearerReadyOrBindToComplete, NetStateMachine::MStateFork, CBindToActivity::TContext) +TInt CBindToActivity::TNoTagOrBearerReadyOrBindToComplete::TransitionTag() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + CBindToActivity& bindToActivity = static_cast(*iContext.iNodeActivity); + + if (!bindToActivity.NextDataClient()) + { + //No more dataclients to bind + return KBindToComplete; + } + + if (bindToActivity.iNewServiceProvider.IsNull()) + { + //There is no service provider (new or old) below us. + return KBearerReady; + } + + return KNoTag; + } + +EXPORT_DEFINE_SMELEMENT(CBindToActivity::TCommit, NetStateMachine::MStateTransition, CBindToActivity::TContext) +void CBindToActivity::TCommit::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + CBindToActivity& bindToActivity = static_cast(*iContext.iNodeActivity); + + TInt count = bindToActivity.DataClientsAutocommit() ? 0 : bindToActivity.iSuccessfulDataClients.Count(); + while (count ) + { + bindToActivity.PostRequestTo(*bindToActivity.iSuccessfulDataClients[--count], TCFDataClient::TCommitBindTo().CRef()); + }; + bindToActivity.iSuccessfulDataClients.Reset(); + RNodeInterface* sp = iContext.Node().ServiceProvider(); + + if (sp && sp->RecipientId() != bindToActivity.iNewServiceProvider) + { + if (bindToActivity.ShouldLeaveServiceProvider()) + { + bindToActivity.PostRequestTo(*sp, TEPeer::TLeaveRequest().CRef()); + sp->SetFlags(TCFClientType::ELeaving); + } + else + { + //Didn't leave, no need for waiting for TLeaveComplete; + bindToActivity.SetIdle(); + } + sp->ClearFlags(TCFClientType::EActive); + } + else + { + //Didn't leave, no need for waiting for TLeaveComplete; + bindToActivity.SetIdle(); + } + + if (!bindToActivity.iNewServiceProvider.IsNull() && (sp == NULL || sp->RecipientId() != bindToActivity.iNewServiceProvider)) + { + RNodeInterface* newServiceProvider = iContext.Node().FindClient(bindToActivity.iNewServiceProvider); + if (newServiceProvider) + { + __ASSERT_DEBUG(newServiceProvider->Flags() & TCFClientType::EActivating, User::Panic(KCorePrPanic, KPanicIncorrectState)); + newServiceProvider->ClearFlags(TCFClientType::EActivating); + newServiceProvider->SetFlags(TCFClientType::EActive); + // Note: iContext.Node().ServiceProvider() must be re-evaluated in the ASSERT below (i.e. don't use any previously cached value). + __ASSERT_DEBUG(iContext.Node().ServiceProvider() == newServiceProvider, User::Panic(KCorePrPanic, KPanicIncorrectState)); + } + } + bindToActivity.iNewServiceProvider = TNodeId::NullId(); + } + +EXPORT_DEFINE_SMELEMENT(CBindToActivity::TCancel, NetStateMachine::MStateTransition, CBindToActivity::TContext) +void CBindToActivity::TCancel::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + CBindToActivity& bindToActivity = static_cast(*iContext.iNodeActivity); + TInt count = bindToActivity.iSuccessfulDataClients.Count(); + while (count ) + { + bindToActivity.PostRequestTo(*bindToActivity.iSuccessfulDataClients[--count], TEBase::TCancel().CRef()); + }; + bindToActivity.iSuccessfulDataClients.Reset(); + + TBool setIdle = ETrue; + if (!bindToActivity.iNewServiceProvider.IsNull()) + { + RNodeInterface* newServiceProvider = iContext.Node().FindClient(bindToActivity.iNewServiceProvider); + if (newServiceProvider && newServiceProvider != iContext.Node().ServiceProvider()) + { + __ASSERT_DEBUG(newServiceProvider->Flags() & TCFClientType::EActivating, User::Panic(KCorePrPanic, KPanicIncorrectState)); + newServiceProvider->ClearFlags(TCFClientType::EActivating); + if (bindToActivity.ShouldLeaveServiceProvider()) + { + bindToActivity.PostRequestTo(*newServiceProvider, TEPeer::TLeaveRequest().CRef()); + newServiceProvider->SetFlags(TCFClientType::ELeaving); + setIdle = EFalse; + } + } + } + + if (setIdle) + { + bindToActivity.SetIdle(); + } + bindToActivity.iNewServiceProvider = TNodeId::NullId(); + } + + +//-========================================================= +// +//Rejoin DataClient Activity +// +//-========================================================= +EXPORT_C MeshMachine::CNodeActivityBase* CRejoinDataClientActivity::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) + { + TUint c = GetNextActivityCountL(aActivitySig,aNode); + return new(ELeave)CRejoinDataClientActivity(aActivitySig, c, aNode); + } + +CRejoinDataClientActivity::~CRejoinDataClientActivity() + { + if ( iDataClients.Count() ) + { + if (Error() != KErrNone) + { + //An error has occured when processing rejoin as the activity hasn't been properly wrapped + //up. This error must have happened before any of the clients have been added to the new + //owner as such addition must either collectively succeed or collectively fail. Reinstall + //clients in at the current owner. + for (TInt i = 0; i < iDataClients.Count(); i++) + { + if (!(iDataClients[i].iDataClient.Flags() & TCFClientType::EActive)) + { +#ifndef __GCCXML__ + //If the dataclient managed to report idle in the mean time, have him destroyed + RClientInterface::OpenPostMessageClose(iNode.Id(), iDataClients[i].iDataClient.RecipientId(), TEChild::TDestroy().CRef()); +#endif + } + iDataClients[i].iDataClient.ClearFlags(TCFClientType::EActivating); +#ifndef __GCCXML__ + //Simulate client leaving on the new owner. + RClientInterface::OpenPostMessageClose(iDataClients[i].iDataClient.RecipientId(), iDataClients[i].iNewOwner, + TEChild::TLeft().CRef()); +#endif + } + } + else + { + //All clear. Remove the clients for good. + for (TInt i = 0; i < iDataClients.Count(); i++) + { + iNode.RemoveClient(iDataClients[i].iDataClient.RecipientId()); + } + } + } + iDataClients.Reset(); + } + + +void CRejoinDataClientActivity::TCFDataClientJoiningRequest::DispatchL(const TRuntimeCtxId& aSender, const TRuntimeCtxId& aRecipient) + { + const TNodeId& nodeId = address_cast(aRecipient); //This message type operates on nodes + MeshMachine::AMMNodeBase* nodeBase = reinterpret_cast(nodeId.Node().FetchNodeInterfaceL(AMMNodeBase::KInterfaceId)); + RNodeInterface* client = NULL; + client = nodeBase->AddClientL(iDataClient, iDataClientType); + client->SetFlags(TCFClientType::EJoining|TCFClientType::EStarted); + RClientInterface::OpenPostMessageClose(nodeId, aSender, TCFPeer::TJoinComplete().CRef()); + } + + +EXPORT_DEFINE_SMELEMENT(CRejoinDataClientActivity::TAwaitingJoinComplete, NetStateMachine::MState, CRejoinDataClientActivity::TContext) +TBool CRejoinDataClientActivity::TAwaitingJoinComplete::Accept() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KSpecAssert_ESockCrStaCPRAC, 13)); + if (iContext.iMessage.IsMessage()) + { + return ETrue; + } + else if (iContext.iMessage.IsMessage()) + { + iContext.iNodeActivity->SetError(message_cast(iContext.iMessage).iValue); + iContext.iNodeActivity->SetIdle(); + iContext.iMessage.ClearMessageId(); + } + return EFalse; + } + + +EXPORT_DEFINE_SMELEMENT(CRejoinDataClientActivity::TRejoinDataClient, NetStateMachine::MStateTransition, CRejoinDataClientActivity::TContext) +EXPORT_C void CRejoinDataClientActivity::TRejoinDataClient::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KSpecAssert_ESockCrStaCPRAC, 14)); + CRejoinDataClientActivity* rejoinActivity = static_cast(iContext.iNodeActivity); + + TCFRejoiningProvider::TRejoinDataClientRequest& rejoinDCMsg = message_cast(iContext.iMessage); + RNodeInterface* subject = iContext.Node().FindClient(rejoinDCMsg.iNodeId1); + if (NULL == subject //client not found + || subject->Flags() & TCFClientType::ELeaving //client leaving/gone + || !(subject->Flags() & TCFClientType::EActive)) //client reported idle or never bound to + { + User::Leave(KErrNotFound); + } + if (subject->Flags() & TCFClientType::EActivating) //client requested by someone + { + User::Leave(KErrInUse); + } + + rejoinActivity->iDataClients.AppendL(TMigrationPairs(*subject, rejoinDCMsg.iNodeId2)); + + CRejoinDataClientActivity::TCFDataClientJoiningRequest msg(subject->RecipientId(), subject->ClientType()); + + RClientInterface::OpenPostMessageClose( + iContext.NodeId(), + rejoinDCMsg.iNodeId2, + msg); + + //Set Client being migrated to a new owner.. reference handed over. secure lifetime. + subject->SetFlags(TCFClientType::EActivating); + } + +EXPORT_DEFINE_SMELEMENT(CRejoinDataClientActivity::TApplyRejoin, NetStateMachine::MStateTransition, CRejoinDataClientActivity::TContext) +void CRejoinDataClientActivity::TApplyRejoin::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KSpecAssert_ESockCrStaCPRAC, 15)); + CRejoinDataClientActivity* rejoinActivity = static_cast(iContext.iNodeActivity); + __ASSERT_DEBUG(rejoinActivity->iDataClients.Count(), User::Panic(KSpecAssert_ESockCrStaCPRAC, 16)); + for (TInt i = 0; i < rejoinActivity->iDataClients.Count(); i++) + { + RClientInterface::OpenPostMessageClose(iContext.NodeId(), rejoinActivity->iDataClients[i].iDataClient.RecipientId(), + TCFFlow::TRejoin(rejoinActivity->iDataClients[i].iNewOwner).CRef()); + rejoinActivity->iDataClients[i].iDataClient.SetFlags(TCFClientType::ELeaving); + } + rejoinActivity->PostRequestTo(iContext.NodeId(), TCFScpr::TApplyRequest().CRef()); + } + +EXPORT_DEFINE_SMELEMENT(CRejoinDataClientActivity::TRejoinLoopTag,NetStateMachine::MStateFork, CRejoinDataClientActivity::TContext) +EXPORT_C TInt CRejoinDataClientActivity::TRejoinLoopTag::TransitionTag() + { + if (iContext.iMessage.IsMessage()) + { + return CoreStates::KLoopTag | NetStateMachine::EBackward; + } + return MeshMachine::KNoTag | NetStateMachine::EForward; + } + +//-========================================================= +// +// CommsBinderActivity (parallel) +// +//-========================================================= + +EXPORT_C MeshMachine::CNodeActivityBase* CCommsBinderActivity::NewL( const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode ) + { + TUint c = GetNextActivityCountL(aActivitySig,aNode); + return new(ELeave)CCommsBinderActivity(aActivitySig, aNode, c); + } + +EXPORT_C CCommsBinderActivity::CCommsBinderActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode, TUint aNextActivityCount) +: MeshMachine::CNodeRetryParallelActivity(aActivitySig, aNode, aNextActivityCount), + TIfStaticFetcherNearestInHierarchy(this) + { + } + +//-========================================================= +// +// CCommsBinderActivity +// +// Aggregate class containing common functionality for +// CommsBinderActivity and CCommsBinderCombiningActivity. +// +//-========================================================= + +EXPORT_C TBool CCommsBinderActivity::TDataClientMutex::IsBlocked(MeshMachine::TNodeContextBase& aContext) + { + TInt c = aContext.Node().CountActivities(aContext.iNodeActivity->ActivitySigId()); + __ASSERT_DEBUG(c>0, User::Panic(KSpecAssert_ESockCrStaCPRAC, 17)); //Diagnostic + if (c == 1 || CCommsBinderActivity::IsDataClientPresent(aContext)) + { + return EFalse; + } + return ETrue; + } + +EXPORT_C TBool CCommsBinderActivity::TDefaultDataClientMutex::IsBlocked(MeshMachine::TNodeContextBase& aContext) + { + TInt c = aContext.Node().CountActivities(aContext.iNodeActivity->ActivitySigId()); + __ASSERT_DEBUG(c>0, User::Panic(KSpecAssert_ESockCrStaCPRAC, 18)); //Diagnostic + if (c == 1 || CCommsBinderActivity::IsDataClientPresent(aContext, TCFClientType::EDefault)) + { + return EFalse; + } + return ETrue; + } + +EXPORT_C /*virtual*/ CCommsBinderActivity::~CCommsBinderActivity() + { + if(!iBinderRequestParameters.IsNull()) + { + iBinderRequestParameters.Close(); + } + } + +EXPORT_C void CCommsBinderActivity::StoreBinder(RNodeInterface* aDataClient) + { + __ASSERT_DEBUG(iPendingBinder == aDataClient || iPendingBinder == NULL, User::Panic(KSpecAssert_ESockCrStaCPRAC, 19)); + iPendingBinder = aDataClient; + } + +EXPORT_C RNodeInterface* CCommsBinderActivity::Binder() const + { + return iPendingBinder; + } + +EXPORT_C void CCommsBinderActivity::StoreBinderRequestParameters(const RCFParameterFamilyBundleC& aBinderRequestParameters) + { + __ASSERT_DEBUG(iBinderRequestParameters.IsNull(), User::Panic(KSpecAssert_ESockCrStaCPRAC, 20)); + if(! aBinderRequestParameters.IsNull()) + { + iBinderRequestParameters.Open(aBinderRequestParameters); + } + } + +void CCommsBinderActivity::SendCustomFlowProvision() +/** +Send a custom message that provisions a flow with flow parameters +*/ + { + __ASSERT_DEBUG(iPendingBinder, User::Panic(KSpecAssert_ESockCrStaCPRAC, 21)); + + // Only send the message if we have parameters to send + if(!iBinderRequestParameters.IsNull()) + { + RParameterFamily parameterFamily = + iBinderRequestParameters.FindFamily(KFlowParametersFamily); + + if(!parameterFamily.IsNull()) + { + STypeId typeId = STypeId::CreateSTypeId(CFlowRequestParameters::EUid, CFlowRequestParameters::EType); + CFlowRequestParameters* flowParams = static_cast(parameterFamily.FindParameterSet(typeId, RParameterFamily::ERequested)); + + iPendingBinder->PostMessage( + iNode.Id(), + TCFInternalEsock::TFlowProvision( + flowParams->GetFlowParams() + ).CRef() + ); + } + } + } + + +void CCommsBinderActivity::SendBinderResponseToOriginator() +/** +Send out CommsBinderResponse to all originators. + +We send to all originators that have joined up until this point, and store this count +in iOriginatorsCountSnapshot. See comment in ProcessBindToComplete(). +*/ + { + __ASSERT_DEBUG(iPendingBinder, User::Panic(KSpecAssert_ESockCrStaCPRAC, 22)); + + PostRequestTo( + address_cast(FirstOriginator().RecipientId()), + TCFServiceProvider::TCommsBinderResponse(iPendingBinder->RecipientId()).CRef()); + + iPendingBinder->SetFlags(TCFClientType::EActivating); + } + +void CCommsBinderActivity::BindToComplete() + { + __ASSERT_DEBUG(iPendingBinder, User::Panic(KSpecAssert_ESockCrStaCPRAC, 23)); + TUint c = iNode.CountActivities(ActivitySigId()); + // Note: this routine can be used with parallel and non-parallel binder activities. In the + // former case we start with multiple activities and eventually end up with a single one. In + // the latter case we have a single activity throughout. + if(c == 1) + { + iPendingBinder->ClearFlags(TCFClientType::EActivating); + } + iPendingBinder = NULL; + } + +// +// CCommsBinderActivity methods that are embedded transitions/states/stateforks +// + +EXPORT_C RNodeInterface* CCommsBinderActivity::IsDataClientPresent(TNodeContextBase& aContext, TUint aClientFlags) +/** +Check if we have a data client and, if so, store it as the binder for this activity. + +@param aContext Node context +@param aClientFlags client flags to use in iterator check +@return ETrue if data client present, else EFalse. +*/ + { + // Be careful not to use a client to which we have already sent TDestroy previously. + // Find the first data client that does not have the ELeaving flag set. If all are + // marked ELeaving then return EFalse - they are on the way out and will disappear + // eventually. The effect will be that a new data client will be created. + RNodeInterface* dataClient = aContext.Node().GetFirstClient(TClientType(TCFClientType::EData, aClientFlags), TClientType(0, TCFClientType::ELeaving)); + return dataClient; + } + +EXPORT_DEFINE_SMELEMENT(CCommsBinderActivity::TNoTagOrUseExisting, NetStateMachine::MStateFork, CCommsBinderActivity::TContext) +EXPORT_C TInt CCommsBinderActivity::TNoTagOrUseExisting::TransitionTag() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KSpecAssert_ESockCrStaCPRAC, 24)); + TCFServiceProvider::TCommsBinderRequest& msg = message_cast(iContext.iMessage); + + // Save away the parameters sent to us so that they are accessible during the activity + __ASSERT_DEBUG(iContext.iNodeActivity->SupportsExtInterface(CCommsBinderActivity::KInterfaceId), User::Panic(KCorePrPanic, KPanicExtInterfaceNotSupported)); + CCommsBinderActivity* intf = reinterpret_cast(iContext.iNodeActivity->FetchExtInterface(CCommsBinderActivity::KInterfaceId)); + intf->StoreBinderRequestParameters(msg.iFamilyBundle); + + if(msg.iValue == TSubConnOpen::EAttachToDefault) + { + RNodeInterface* dc = CCommsBinderActivity::IsDataClientPresent(iContext); + if (dc) + { + __ASSERT_DEBUG(iContext.iNodeActivity->SupportsExtInterface(CCommsBinderActivity::KInterfaceId), User::Panic(KCorePrPanic, KPanicExtInterfaceNotSupported)); + CCommsBinderActivity* intf = reinterpret_cast(iContext.iNodeActivity->FetchExtInterface(CCommsBinderActivity::KInterfaceId)); + + intf->StoreBinder(dc); + return CoreStates::KUseExisting; + } + } + return MeshMachine::KNoTag; + } + +//MZTODO - logic of: +//TNoTagOrWaitForIncomingOrUseExisting +//& +//TNoTagOrWaitForIncomingOrUseExistingDefault +//has been copied but does not seem right, as both use EDefault? +//Why? + +//[401TODO] DL : Only one of TNoTagOrWaitForIncomingOrUseExisting(Default) is used, is it ok to nuke one? + +EXPORT_DEFINE_SMELEMENT(CCommsBinderActivity::TNoTagOrWaitForIncomingOrUseExisting, NetStateMachine::MStateFork, CCommsBinderActivity::TContext) +EXPORT_C TInt CCommsBinderActivity::TNoTagOrWaitForIncomingOrUseExisting::TransitionTag() + { + TCFServiceProvider::TCommsBinderRequest& msg = message_cast(iContext.iMessage); + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KSpecAssert_ESockCrStaCPRAC, 25)); + + if (msg.iValue == TSubConnOpen::EWaitForIncoming) + { + return CoreNetStates::KWaitForIncoming; + } + + else + { + RNodeInterface* dc = CCommsBinderActivity::IsDataClientPresent(iContext, TCFClientType::EDefault); + if (dc) + { + __ASSERT_DEBUG(iContext.iNodeActivity->SupportsExtInterface(CCommsBinderActivity::KInterfaceId), User::Panic(KCorePrPanic, KPanicExtInterfaceNotSupported)); + CCommsBinderActivity* intf = reinterpret_cast(iContext.iNodeActivity->FetchExtInterface(CCommsBinderActivity::KInterfaceId)); + + intf->StoreBinder(dc); + return CoreStates::KUseExisting; + } + } + + return MeshMachine::KNoTag; + } + +EXPORT_DEFINE_SMELEMENT(CCommsBinderActivity::TNoTagOrWaitForIncomingOrUseExistingDefault, NetStateMachine::MStateFork, CCommsBinderActivity::TContext) +EXPORT_C TInt CCommsBinderActivity::TNoTagOrWaitForIncomingOrUseExistingDefault::TransitionTag() + { + TCFServiceProvider::TCommsBinderRequest& msg = message_cast(iContext.iMessage); + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KSpecAssert_ESockCrStaCPRAC, 26)); + + if(msg.iValue == TSubConnOpen::EAttachToDefault) + { + RNodeInterface* dc = CCommsBinderActivity::IsDataClientPresent(iContext, TCFClientType::EDefault); + if (dc) + { + __ASSERT_DEBUG(iContext.iNodeActivity->SupportsExtInterface(CCommsBinderActivity::KInterfaceId), User::Panic(KCorePrPanic, KPanicExtInterfaceNotSupported)); + CCommsBinderActivity* intf = reinterpret_cast(iContext.iNodeActivity->FetchExtInterface(CCommsBinderActivity::KInterfaceId)); + + intf->StoreBinder(dc); + return CoreStates::KUseExisting; + } + } + else if (msg.iValue == TSubConnOpen::EWaitForIncoming) + { + return CoreNetStates::KWaitForIncoming; + } + return MeshMachine::KNoTag; + } + +EXPORT_DEFINE_SMELEMENT(CCommsBinderActivity::TStorePendingBinder, NetStateMachine::MStateTransition, CCommsBinderActivity::TContext) +EXPORT_C void CCommsBinderActivity::TStorePendingBinder::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KSpecAssert_ESockCrStaCPRAC, 27)); + message_cast(iContext.iMessage); + + __ASSERT_DEBUG(iContext.iNodeActivity->SupportsExtInterface(CCommsBinderActivity::KInterfaceId), User::Panic(KCorePrPanic, KPanicExtInterfaceNotSupported)); + CCommsBinderActivity* intf = reinterpret_cast(iContext.iNodeActivity->FetchExtInterface(CCommsBinderActivity::KInterfaceId)); + + intf->StoreBinder(iContext.iPeer); + } + +EXPORT_DEFINE_SMELEMENT(CCommsBinderActivity::TSendBinderResponse, NetStateMachine::MStateTransition, CCommsBinderActivity::TContext) +EXPORT_C void CCommsBinderActivity::TSendBinderResponse::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KSpecAssert_ESockCrStaCPRAC, 28)); + + __ASSERT_DEBUG(iContext.iNodeActivity->SupportsExtInterface(CCommsBinderActivity::KInterfaceId), User::Panic(KCorePrPanic, KPanicExtInterfaceNotSupported)); + CCommsBinderActivity* intf = reinterpret_cast(iContext.iNodeActivity->FetchExtInterface(CCommsBinderActivity::KInterfaceId)); + + intf->SendBinderResponseToOriginator(); + } + +EXPORT_DEFINE_SMELEMENT(CCommsBinderActivity::TSendCustomFlowProvision, NetStateMachine::MStateTransition, CCommsBinderActivity::TContext) +EXPORT_C void CCommsBinderActivity::TSendCustomFlowProvision::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KSpecAssert_ESockCrStaCPRAC, 29)); + + __ASSERT_DEBUG(iContext.iNodeActivity->SupportsExtInterface(CCommsBinderActivity::KInterfaceId), User::Panic(KCorePrPanic, KPanicExtInterfaceNotSupported)); + CCommsBinderActivity* intf = reinterpret_cast(iContext.iNodeActivity->FetchExtInterface(CCommsBinderActivity::KInterfaceId)); + + intf->SendCustomFlowProvision(); + } + +EXPORT_DEFINE_SMELEMENT(CCommsBinderActivity::TAwaitingBindToComplete, NetStateMachine::MState, PRStates::TContext) +EXPORT_C TBool CCommsBinderActivity::TAwaitingBindToComplete::Accept() + { + CoreNetStates::TAwaitingBindToComplete awaitingBindToComplete(iContext); + if (awaitingBindToComplete.Accept()) + { + CCommsBinderActivity* binderActivity = reinterpret_cast(iContext.iNodeActivity->FetchExtInterface(CCommsBinderActivity::KInterfaceId)); + __ASSERT_DEBUG(binderActivity, User::Panic(KSpecAssert_ESockCrStaCPRAC, 30)); + binderActivity->BindToComplete(); + iContext.Node().DestroyOrphanedDataClients(); + return ETrue; + } + return EFalse; + } + +//-========================================================= +// +//CNoBearer Activity +// +//-========================================================= + +CNoBearer::CNoBearer(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode, TUint aActivitiesCount) +: MeshMachine::CNodeRetryParallelActivity(aActivitySig, aNode, aActivitiesCount), + ABindingActivity(aNode.Id()), + TIfStaticFetcherNearestInHierarchy(this) + { + } + +/*virtual*/ CNoBearer::~CNoBearer() + { + iNoBearerParameters.Close(); + } + +EXPORT_C MeshMachine::CNodeActivityBase* CNoBearer::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) + { + TUint c = GetNextActivityCountL(aActivitySig,aNode); + return new(ELeave)CNoBearer(aActivitySig, aNode, c); + } + +EXPORT_C TNodePeerId& CNoBearer::GetOriginator() + { + __ASSERT_DEBUG(iOriginators.Count() == 1, User::Panic(KSpecAssert_ESockCrStaCPRAC, 31)); + return iOriginators[0]; + } + +EXPORT_C void CNoBearer::ReturnInterfacePtrL(CoreActivities::ABindingActivity*& aInterface) + { + aInterface = this; + } + +EXPORT_C TBool CNoBearer::TServiceProviderMutex::IsBlocked(MeshMachine::TNodeContextBase& aContext) + { + TInt c = aContext.Node().CountActivities(aContext.iNodeActivity->ActivitySigId()); + __ASSERT_DEBUG(c>0, User::Panic(KSpecAssert_ESockCrStaCPRAC, 32)); //Diagnostic + if (c == 1 || aContext.Node().CountClients(TClientType(TCFClientType::EServProvider)) != 0) + { + return EFalse; + } + return ETrue; + } + +EXPORT_DEFINE_SMELEMENT(CNoBearer::TRequestCommsBinder, NetStateMachine::MStateTransition, CNoBearer::TContext) +EXPORT_C void CNoBearer::TRequestCommsBinder::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + CNoBearer& noBearer = static_cast(*iContext.iNodeActivity); + + RNodeInterface* sp = iContext.Node().ServiceProvider(); + __ASSERT_DEBUG(sp, User::Panic(KCorePrPanic, KPanicNoServiceProvider)); + + TSubConnOpen::TSubConnType type = TSubConnOpen::EAttachToDefault; + if (!(noBearer.GetOriginator().Flags() & TCFClientType::EDefault)) + { + type = TSubConnOpen::ECreateNew; + } + + noBearer.PostRequestTo( + *sp, + TCFServiceProvider::TCommsBinderRequest( + type, noBearer.iNoBearerParameters + ).CRef() + ); + } + +EXPORT_DEFINE_SMELEMENT(CNoBearer::TStoreRequestParameters, NetStateMachine::MStateTransition, CNoBearer::TContext) +EXPORT_C void CNoBearer::TStoreRequestParameters::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + CNoBearer& noBearer = static_cast(*iContext.iNodeActivity); + const TCFControlProvider::TNoBearer& noBearerMessage = message_cast(iContext.iMessage); + __ASSERT_DEBUG(noBearer.iNoBearerParameters.IsNull(), User::Panic(KSpecAssert_ESockCrStaCPRAC, 33)); // handle should be empty when this fn is called + if(noBearerMessage.iFamilyBundle.IsNull()) + { + noBearer.iNoBearerParameters.Open(); + } + else + { + noBearer.iNoBearerParameters.Open(noBearerMessage.iFamilyBundle); + } + } + +EXPORT_DEFINE_SMELEMENT(CNoBearer::TNoTagOrDataClientsToStart, NetStateMachine::MStateFork, CNoBearer::TContext) +TInt CNoBearer::TNoTagOrDataClientsToStart::TransitionTag() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + CNoBearer& activity = static_cast(*iContext.iNodeActivity); + + const TNodePeerId& originator = activity.GetOriginator(); + __ASSERT_DEBUG(originator.Type() & TCFClientType::EData, User::Panic(KSpecAssert_ESockCrStaCPRAC, 34)); + + if (activity.Error() == KErrNone && (originator.Flags() & (TCFClientType::EStarting|TCFClientType::EStarted|TCFClientType::ELeaving)) == 0) + { + //Start dc + return CoreNetStates::KDataClientsToStart; + } + //Finish the activity + return MeshMachine::KNoTag; + } + +EXPORT_DEFINE_SMELEMENT(CNoBearer::TStartOriginatingDataClient, NetStateMachine::MStateTransition, CNoBearer::TContext) +void CNoBearer::TStartOriginatingDataClient::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + CNoBearer& activity = static_cast(*iContext.iNodeActivity); + TNodePeerId& originator = activity.GetOriginator(); + __ASSERT_DEBUG(originator.Type() & TCFClientType::EData, User::Panic(KSpecAssert_ESockCrStaCPRAC, 35)); + activity.PostRequestTo(originator.Peer(), TCFDataClient::TStart().CRef()); + originator.SetFlags(TCFClientType::EStarting); + } + +EXPORT_DEFINE_SMELEMENT(CNoBearer::TNoTagOrBearerPresent, NetStateMachine::MStateFork, CNoBearer::TContext) +EXPORT_C TInt CNoBearer::TNoTagOrBearerPresent::TransitionTag() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + CNoBearer& noBearer = static_cast(*iContext.iNodeActivity); + const TCFControlProvider::TNoBearer& noBearerMessage = message_cast(iContext.iMessage); + __ASSERT_DEBUG(noBearer.iNoBearerParameters.IsNull(), User::Panic(KSpecAssert_ESockCrStaCPRAC, 36)); // should not yet be set when this fn is called + noBearer.iNoBearerParameters.Open(noBearerMessage.iFamilyBundle); + + CoreNetStates::TNoTagOrBearerPresent fork(iContext); + return fork.TransitionTag(); + } + +EXPORT_DEFINE_SMELEMENT(CNoBearer::TNoTagOrBearerPresentForAutostart, NetStateMachine::MStateFork, CNoBearer::TContext) +EXPORT_C TInt CNoBearer::TNoTagOrBearerPresentForAutostart::TransitionTag() + { + TInt cntrlClients = iContext.Node().CountClients( + /*include*/TClientType(TCFClientType::ECtrl)); + if (cntrlClients > 0 && + iContext.Node().ServiceProvider() && + !(iContext.Node().ServiceProvider()->Flags() & TCFClientType::EStarted)) + { + //This fork calculates if the NoBearer activity (which this fork has been implemented for) + //should attempt to autostart the service provider when returning it to the sender of TNoBearer. + //The philosphy here is that if the local node doesn't have a control client, then there's noone + //that could posibly start it. It will hence decide to autostart as the top layer of what looks + //like an implicit connection. In the future this autostart behaviour should become a specialty + //of someone more concrete (rather than generic function). We are speculating about the implicit + //top layer that could acquire this function if it ever comes into being. + return CoreNetStates::KBearerPresent; + } + return KNoTag; + } + + +//-========================================================= +// +//CStartActivity Activity +// +//-========================================================= +CStartActivity::CStartActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) + : MeshMachine::CNodeRetryActivity(aActivitySig, aNode), + CoreActivities::ABindingActivity(aNode.Id()), + TIfStaticFetcherNearestInHierarchy(this) + { + } + +EXPORT_C CStartActivity::~CStartActivity() + { + } + +EXPORT_C MeshMachine::CNodeActivityBase* CStartActivity::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) + { + return new (ELeave) CStartActivity(aActivitySig, aNode); + } + +//-========================================================= +// +//Gone Down Activity +// +//-========================================================= +MeshMachine::CNodeActivityBase* CGoneDownActivity::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) + { + CGoneDownActivity* self = new (ELeave) CGoneDownActivity(aActivitySig,aNode); + return self; + } + +CGoneDownActivity::CGoneDownActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) +: MeshMachine::CNodeRetryActivity(aActivitySig, aNode) + { + } + +CGoneDownActivity::~CGoneDownActivity() + { + //This is a gone down activity. Error mode is its only/natural state + //CGoneDownActivity inherits ultimatelly from CNodeActivityBase, which + //will attempt to interpret the error mode as a failure to execute (and + //auto respond to orignators), which we don't want. Hence clearing + //the error and allowing 'this' to die peacefully. + SetError(KErrNone); + } + +void CGoneDownActivity::StartL(TNodeContextBase& aContext, const Messages::XNodePeerId& aOriginator, const TStateTriple& aFirst) + { + //399TODO: for the moment ignore duplicated TGoneDown messages + //but this needs to be fixed (someone is sending TGoneDown from TSendDataClientStopped + //hence the problem) + + //ASSERT(IsIdle()); + if (!IsIdle()) + { + return; + } + + //This activity provides service for only one single requestor at a time. + __ASSERT_DEBUG(iOriginators.Count()==0, User::Panic(KSpecAssert_ESockCrStaCPRAC, 37)); //Diagnostic panic + + TCFControlClient::TGoneDown& msg = message_cast(aContext.iMessage); + SetError(msg.iValue1); + iGoneDownApId = msg.iValue2; + + MESH_LOG_ACTIVITY_EXT(KMeshMachineSubTag, this, &aContext, (_L8("CGoneDownActivity %08x:\tStartL->starting activity"), this)); + NetStateMachine::ACore::Start(&aContext, aFirst); + + MESH_LOG_ACTIVITY_EXT(KMeshMachineSubTag, this, &aContext, (_L8("CGoneDownActivity %08x:\tStartL->activity started"), this)); + (void)aOriginator; + } + +//Find next DC to rebind +TBool CGoneDownActivity::IsIdle() const + { + return NetStateMachine::ACore::IsIdle(); + } + +DEFINE_SMELEMENT(CGoneDownActivity::TSendErrorRecoveryReq, NetStateMachine::MStateTransition, CGoneDownActivity::TContext) +void CGoneDownActivity::TSendErrorRecoveryReq::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + CGoneDownActivity& activity = static_cast(*iContext.iNodeActivity); + + //TInt error = ExtractErrorCode(iContext.iMessage); + TErrContext ctx(iContext.NodeId(), TCFControlClient::TGoneDown::Id(), activity.ActivitySigId(), TStateChange(0, activity.Error())); + ctx.iInfo = (TAny*)activity.iGoneDownApId; + TEErrorRecovery::TErrorRecoveryRequest msg(ctx); + + //We can not set SetSentTo() to Control Provider, because the response may not be coming from it + //(for example it could be coming from the MCpr and we could be the SCpr). + //Normally this would be a problem because any unrelated TError message arriving to the node + //and presented to the awaiting state would easily be confused with the response (TError == + //no recovery on the MCpr == EPropagate). + //We avoid the problem by checking all arriving TError messages if they are adressed to our activity. + __ASSERT_DEBUG(iContext.Node().ControlProvider(), User::Panic(KCorePrPanic, KPanicNoControlProvider)); + activity.PostRequestTo(*iContext.Node().ControlProvider(), + TCFSafeMessage::TRequestCarrierEast(msg).CRef()); + activity.ClearPostedTo(); + } + +DEFINE_SMELEMENT(CGoneDownActivity::TIgnoreOrPropagate, NetStateMachine::MStateFork, CGoneDownActivity::TContext) +TInt CGoneDownActivity::TIgnoreOrPropagate::TransitionTag() + { + __ASSERT_DEBUG(iContext.iMessage.IsMessage(), User::Panic(KSpecAssert_ESockCrStaCPRAC, 38)); + RNodeInterface* sp = iContext.Node().GetFirstClient(TClientType(TCFClientType::EServProvider, TCFClientType::EStarted)); + if (sp) + { + return CoreStates::KIgnore | NetStateMachine::EForward; + } + //There is no started service provider, the reconnection, mobility, etc must have failed, + //continue with tearing this layer down. + CGoneDownActivity& activity = static_cast(*iContext.iNodeActivity); + TErrResponse& resp = message_cast(iContext.iMessage).iErrResponse; + resp.iAction=TErrResponse::EPropagate; + __ASSERT_DEBUG(activity.Error()!=KErrNone, User::Panic(KSpecAssert_ESockCrStaCPRAC, 39)); + resp.iError = activity.Error(); + return CoreStates::KPropagate | NetStateMachine::EForward; + } + + +EXPORT_DEFINE_SMELEMENT(CStartActivity::TAwaitingBindToCompleteOrCancel, NetStateMachine::MState, CStartActivity::TContext) +TBool CStartActivity::TAwaitingBindToCompleteOrCancel::Accept() + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); + if (iContext.iMessage.IsMessage()) + { + iContext.iNodeActivity->SetError(KErrCancel); + iContext.iMessage.ClearMessageId(); + return EFalse; + } + else + { + CoreNetStates::TAwaitingBindToComplete state(iContext); + return state.Accept(); + } + } +} //PRActivities + +EXPORT_DEFINE_SMELEMENT(PRDataClientStopActivity::TNoTagOrProviderStopped, NetStateMachine::MStateFork, PRDataClientStopActivity::TContext) +EXPORT_C TInt PRDataClientStopActivity::TNoTagOrProviderStopped::TransitionTag() + { + iContext.iNodeActivity->SetError(message_cast(iContext.iMessage).iValue); + if (iContext.Node().GetFirstClient( + TClientType(TCFClientType::EData, TCFClientType::EStarted)) != NULL) + { + // At least one started data client + return MeshMachine::KNoTag; + } + return CoreNetStates::KProviderStopped; + } + + + diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/core_states/ss_corepractivities.h --- a/datacommsserver/esockserver/core_states/ss_corepractivities.h Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/core_states/ss_corepractivities.h Thu Jan 07 13:34:53 2010 +0200 @@ -174,6 +174,7 @@ protected: CDestroyActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode); virtual void Destroy(); + virtual TBool Next(MeshMachine::TNodeContextBase& aContext); //States, StateForks & StateTransitions protected: @@ -435,7 +436,9 @@ IMPORT_C CBindToActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode, TInt aNextActivityCount); protected: - Messages::RNodeInterface* iNewServiceProvider; + // We cannot store iNewServiceProvider as an RNodeInterface* in case an activity (like GoneDown) executes simultaneously and removes + // the client we hold a reference to. Hence use the NodeId and lookup the corresponding RNodeInterface* as and when required. + Messages::TNodeId iNewServiceProvider; private: Messages::RNodeInterface* iCurrentDataClient; RPointerArray iSuccessfulDataClients; diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/debug/documentation/DISTRIBUTION.POLICY --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/datacommsserver/esockserver/debug/documentation/DISTRIBUTION.POLICY Thu Jan 07 13:34:53 2010 +0200 @@ -0,0 +1,2 @@ +Category T +OSD: Reference/Test Tools diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/group/BLD.INF --- a/datacommsserver/esockserver/group/BLD.INF Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/group/BLD.INF Thu Jan 07 13:34:53 2010 +0200 @@ -234,5 +234,5 @@ #endif PRJ_TESTMMPFILES -#include "../test/bld.inf" +//#include "../test/bld.inf" diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/group/BLD.INF~ --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/datacommsserver/esockserver/group/BLD.INF~ Thu Jan 07 13:34:53 2010 +0200 @@ -0,0 +1,238 @@ +// Copyright (c) 1999-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: +// Sockets/Networking Server +// +// + +/** + @file +*/ + +#define SYMBIAN_NETWORKING_UPS + + +PRJ_PLATFORMS + +DEFAULT + +PRJ_EXPORTS + +../core_states/ss_esockstates.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_esockstates.h) +../core_states/ss_esockactivities.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_esockactivities.h) +../core_states/ss_coreprstates.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_coreprstates.h) +../core_states/ss_corepractivities.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_corepractivities.h) + +../csock/SOCKMES.H SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/sockmes.h) + +../inc/es_connectionservermessages.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/es_connectionservermessages.h) + +../eintsock/eintsock.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/eintsock.h) +../inc/ss_intsock.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_intsock.h) + +../group/esock.iby /epoc32/rom/include/esock.iby +../group/esock_core.iby /epoc32/rom/include/esock_core.iby + +../inc/ss_DataMonitoringProvider.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_datamonitoringprovider.h) +../inc/ConnPref.h SYMBIAN_OS_LAYER_PUBLIC_EXPORT_PATH(connpref.h) +../inc/es_commsdataobject.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/es_commsdataobject.h) +../inc/es_accesspointstatus.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/es_accesspointstatus.h) +../inc/es_availability.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/es_availability.h) +../inc/es_config.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/es_config.h) +../inc/es_connectionserv.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/es_connectionserv.h) +../inc/es_connectionservparameterbundle.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/es_connectionservparameterbundle.h) +../inc/es_connectionservparameterbundletrace.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/es_connectionservparameterbundletrace.h) +../inc/es_connectionservparameterbundletraceimpl.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/es_connectionservparameterbundletraceimpl.h) +../inc/es_connPref.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(es_connpref.h) +../inc/es_enum.h SYMBIAN_OS_LAYER_PUBLIC_EXPORT_PATH(es_enum.h) +../inc/es_enum.inl SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(es_enum.inl) +../inc/ES_INI.H SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(es_ini.h) +../inc/es_mbufif.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(es_mbufif.h) +../inc/es_notq.inl SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(es_notq.inl) +../inc/es_panic.h SYMBIAN_OS_LAYER_PUBLIC_EXPORT_PATH(es_panic.h) +../inc/es_parameterset.h SYMBIAN_OS_LAYER_PUBLIC_EXPORT_PATH(comms-infras/es_parameterset.h) +../inc/es_event.h SYMBIAN_OS_LAYER_PUBLIC_EXPORT_PATH(comms-infras/es_event.h) +../inc/ss_protopt.h SYMBIAN_OS_LAYER_PUBLIC_EXPORT_PATH(comms-infras/ss_protopt.h) +../inc/es_parameterbundle.h SYMBIAN_OS_LAYER_PUBLIC_EXPORT_PATH(comms-infras/es_parameterbundle.h) +../inc/es_parameterfamily.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/es_parameterfamily.h) +../inc/es_parameterfamily.inl SYMBIAN_OS_LAYER_PUBLIC_EXPORT_PATH(comms-infras/es_parameterfamily.inl) +../inc/ES_PROT.H SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(es_prot.h) +../inc/ES_PROT.INL SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(es_prot.inl) +../inc/es_protbinder.h SYMBIAN_OS_LAYER_PUBLIC_EXPORT_PATH(comms-infras/es_protbinder.h) +../inc/es_prov.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(es_prov.h) +../inc/es_sap.h SYMBIAN_OS_LAYER_PUBLIC_EXPORT_PATH(comms-infras/es_sap.h) +../inc/ES_SOCK.H SYMBIAN_OS_LAYER_PUBLIC_EXPORT_PATH(es_sock.h) +../inc/ES_SOCK.INL SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(es_sock.inl) +../inc/ES_VER.H SYMBIAN_OS_LAYER_PUBLIC_EXPORT_PATH(es_ver.h) +../inc/ss_activities.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_activities.h) +../inc/ss_common.h SYMBIAN_OS_LAYER_PUBLIC_EXPORT_PATH(comms-infras/ss_common.h) +../inc/ss_commsprov.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_commsprov.h) +../inc/ss_commsprov_internal.h SYMBIAN_OS_LAYER_PUBLIC_EXPORT_PATH(comms-infras/ss_commsprov_internal.h) +../inc/ss_api_ext.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_api_ext.h) +../inc/ss_apiext_register.h SYMBIAN_OS_LAYER_PUBLIC_EXPORT_PATH(comms-infras/ss_apiext_register.h) +../inc/ss_connLegacy.h SYMBIAN_OS_LAYER_PUBLIC_EXPORT_PATH(comms-infras/ss_connlegacy.h) +../inc/ss_connprov.h SYMBIAN_OS_LAYER_PUBLIC_EXPORT_PATH(comms-infras/ss_connprov.h) +../inc/ss_connselect.h SYMBIAN_OS_LAYER_PUBLIC_EXPORT_PATH(comms-infras/ss_connselect.h) +../inc/ss_connsettings.h SYMBIAN_OS_LAYER_PUBLIC_EXPORT_PATH(comms-infras/ss_connsettings.h) +../inc/ss_cprnodeinterfaces.h SYMBIAN_OS_LAYER_PUBLIC_EXPORT_PATH(comms-infras/ss_cprnodeinterfaces.h) +../inc/ss_datatransfer.h SYMBIAN_OS_LAYER_PUBLIC_EXPORT_PATH(comms-infras/ss_datatransfer.h) +../inc/ss_fact.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(ss_fact.h) +../inc/ss_fact_internal.h SYMBIAN_OS_LAYER_PUBLIC_EXPORT_PATH(comms-infras/ss_fact_internal.h) +../inc/ss_factorycontainermap.h SYMBIAN_OS_LAYER_PUBLIC_EXPORT_PATH(comms-infras/ss_factorycontainermap.h) +../inc/ss_flowbinders.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_flowbinders.h) +../inc/ss_flowbinders_internal.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_flowbinders_internal.h) +../inc/SS_GLOB.H SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(ss_glob.h) +../inc/ss_log.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_log.h) +../inc/ss_logext.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_logext.h) +../inc/ss_mcprnodemessages.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_mcprnodemessages.h) +../inc/ss_metaconnprov.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_metaconnprov.h) +../inc/ss_metaconnprov_internal.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_metaconnprov_internal.h) +../inc/ss_mmcommsprov.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_mmcommsprov.h) +../inc/ss_mmnode.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_mmnode.h) +../inc/ss_mmnode_subsess.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_mmnode_subsess.h) +../inc/ss_nodeinterfaces.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_nodeinterfaces.h) +../inc/ss_dispatchers.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_dispatchers.h) +../inc/ss_nodemessages.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_nodemessages.h) +../inc/ss_nodemessages_internal.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_nodemessages_internal.h) +../inc/ss_nodemessages_legacy.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_nodemessages_legacy.h) +../inc/ss_nodemessages_legacy_internal.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_nodemessages_legacy_internal.h) +../inc/ss_nodemessages_dataclient.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_nodemessages_dataclient.h) +../inc/ss_nodemessages_peer.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_nodemessages_peer.h) +../inc/ss_nodemessages_mobility.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_nodemessages_mobility.h) +../inc/ss_nodemessages_availability.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_nodemessages_availability.h) +../inc/ss_nodemessages_serviceprovider.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_nodemessages_serviceprovider.h) +../inc/ss_nodemessages_subconn.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_nodemessages_subconn.h) +../inc/ss_nodemessages_rejoiningprovider.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_nodemessages_rejoiningprovider.h) +../inc/ss_nodemessages_selector.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_nodemessages_selector.h) +../inc/ss_nodemessages_ipmessages.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_nodemessages_ipmessages.h) +../inc/ss_nodemessages_flow.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_nodemessages_flow.h) +../inc/ss_nodemessages_internal_esock.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_nodemessages_internal_esock.h) +../inc/ss_nodemessages_parameters.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_nodemessages_parameters.h) +../inc/ss_nodemessages_factory.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_nodemessages_factory.h) +../inc/ss_nodemessages_tiermanagerfactory.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_nodemessages_tiermanagerfactory.h) +../inc/ss_nodemessages_tiermanager.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_nodemessages_tiermanager.h) +../inc/ss_nodemessages_mcpr.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_nodemessages_mcpr.h) +../inc/ss_nodemessages_cpr.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_nodemessages_cpr.h) +../inc/ss_nodemessages_scpr.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_nodemessages_scpr.h) +../inc/ss_commsdataobject.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_commsdataobject.h) +../inc/ss_parameterfamilybundle.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_parameterfamilybundle.h) +../inc/SS_PMAN.H SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(ss_pman.h) +../inc/SS_PMAN.INL SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(ss_pman.inl) +../inc/ss_protflow.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_protflow.h) +../inc/ss_protprov.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(ss_protprov.h) +../inc/ss_protcfgldr.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_protcfgldr.h) +../inc/ss_roles.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_roles.h) +../inc/ss_roles.inl SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_roles.inl) +../inc/ss_sapshim.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_sapshim.h) +../inc/ss_select.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(ss_select.h) +../inc/SS_sock.H SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(ss_sock.h) +../inc/SS_STD.H SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(ss_std.h) +../inc/SS_STD.INL SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(ss_std.inl) +../inc/ss_subconnflow.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_subconnflow.h) +../inc/ss_subconnprov.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_subconnprov.h) +../inc/ss_thread.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_thread.h) +../inc/ss_threadtransport.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_threadtransport.h) +../inc/ss_threadtransport.inl SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_threadtransport.inl) +../inc/ss_tiermanager.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_tiermanager.h) +../inc/ss_tiermanager_internal.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_tiermanager_internal.h) +../inc/ss_tiermanagerutils.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_tiermanagerutils.h) +../inc/ss_rmetaextensioncontainer.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_rmetaextensioncontainer.h) + +// Would rather not export these headers, but they are needed by BT Avctp for the time being +../inc/ss_legacyinterfaces.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_legacyinterfaces.h) + +../subcon_params/group/SUBCONPARAMS.iby /epoc32/rom/include/subconparams.iby +../subcon_params/inc/cs_subconevents.h SYMBIAN_OS_LAYER_PUBLIC_EXPORT_PATH(cs_subconevents.h) +../subcon_params/inc/cs_subconevents.inl SYMBIAN_OS_LAYER_PUBLIC_EXPORT_PATH(cs_subconevents.inl) +../subcon_params/inc/cs_subconparams.h SYMBIAN_OS_LAYER_PUBLIC_EXPORT_PATH(cs_subconparams.h) +../subcon_params/inc/cs_subconparams.inl SYMBIAN_OS_LAYER_PUBLIC_EXPORT_PATH(cs_subconparams.inl) + +#ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW +../subcon_params/inc/cs_genevent.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(cs_genevent.h) +../subcon_params/inc/cs_genevent.inl SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(cs_genevent.inl) +#endif // SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW + +../esock_params/group/esock_params.iby /epoc32/rom/include/esock_params.iby +../esock_params/inc/esock_params.h SYMBIAN_OS_LAYER_PUBLIC_EXPORT_PATH(comms-infras/esock_params.h) +../esock_params/inc/esock_params.inl SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/esock_params.inl) +../esock_params/inc/esock_params_internal.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/esock_params_internal.h) +../esock_params/inc/esock_params_internal.inl SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/esock_params_internal.inl) + +../connserv_params/group/CONNSERVPARAMS.iby /epoc32/rom/include/connservparams.iby +../connserv_params/inc/cs_connservparams.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/cs_connservparams.h) +../connserv_params/inc/cs_connservparams_internal.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/cs_connservparams_internal.h) + +../inc/es_api_ext.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/es_api_ext.h) +../inc/es_datamon_apiext.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/es_datamon_apiext.h) +../inc/es_mobility_apiext.h SYMBIAN_OS_LAYER_PUBLIC_EXPORT_PATH(comms-infras/es_mobility_apiext.h) + +../inc/ss_datamon_apiext.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_datamon_apiext.h) +../inc/ss_mobility_apiext.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_mobility_apiext.h) +../inc/ss_platsec_apiext.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_platsec_apiext.h) +../inc/ss_msgintercept.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_msgintercept.h) + +../inc/ss_protocolparameterset.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_protocolparameterset.h) +../inc/ss_protocolparameterset.inl SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_protocolparameterset.inl) + +#ifdef SYMBIAN_NETWORKING_UPS +../inc/ss_upsaccesspointconfigext.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_upsaccesspointconfigext.h) +#endif + + +../inc/addressupdate.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(addressupdate.h) +../inc/es_enum_partner.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(es_enum_partner.h) +../inc/es_enum_partner.inl SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(es_enum_partner.inl) +../inc/es_enum_internal.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(es_enum_internal.h) +../inc/es_enum_internal.inl SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(es_enum_internal.inl) +../inc/es_panic_partner.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(es_panic_partner.h) +../inc/es_panic_internal.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(es_panic_internal.h) +../inc/es_sock_internal.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(es_sock_internal.h) +../inc/es_sock_internal.inl SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(es_sock_internal.inl) +../inc/es_sock_partner.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(es_sock_partner.h) +../inc/es_prot_internal.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(es_prot_internal.h) + + +../inc/ss_mobility_apiext_internal.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_mobility_apiext_internal.h) +../inc/ss_refcountowner.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(comms-infras/ss_refcountowner.h) + +#include "../etc/BLD.INF" +#include "../compatibility_headers/group/bld.inf" + +//Backup and restore exports +../group/backup_registration.xml z:/private/101f7989/backup_registration.xml + +PRJ_MMPFILES + +../group/ESOCK.MMP +../group/ESockSvr.MMP +../eintsock_transport/group/eintsock_transport.mmp +../subcon_params/group/subconparams.mmp +../esock_params/group/esock_params.mmp +../connserv_params/group/connservparams.mmp + +#include "../debug/MessageInterceptRegister/group/bld.inf" +#include "../commsdataobjects/group/bld.inf" +#include "../api_ext/group/bld.inf" +#include "../esock_messages/group/bld.inf" +#include "../esock_internal_messages/group/bld.inf" +#include "../CoreProviders/group/bld.inf" +#include "../MobilityCoreProviders/group/bld.inf" +#include "../simpleselectorbase/group/bld.inf" + +#ifdef SYMBIAN_NETWORKING_UPS +#include "../UpsCoreProviders/group/bld.inf" +#endif + +PRJ_TESTMMPFILES +#include "../test/bld.inf" + diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/group/ESockSvr.MMP --- a/datacommsserver/esockserver/group/ESockSvr.MMP Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/group/ESockSvr.MMP Thu Jan 07 13:34:53 2010 +0200 @@ -124,7 +124,6 @@ USERINCLUDE ../inc USERINCLUDE ../eintsock -USERINCLUDE ../../../commsfwsupport/commselements/serverden/inc OS_LAYER_SYSTEMINCLUDE_SYMBIAN diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/inc/SS_conn.H --- a/datacommsserver/esockserver/inc/SS_conn.H Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/inc/SS_conn.H Thu Jan 07 13:34:53 2010 +0200 @@ -152,6 +152,7 @@ friend class EnumerateConnectionsActivity::TCacheConnectionInfo; friend class EnumerateConnectionsActivity::TCompleteClient; friend class AllInterfaceNotificationActivity::TEnqueueNotification; + friend class AllInterfaceNotificationActivity::TSendErrorToConnection; friend class ConnSubConnEventsActivity::TProcessSubConnEvent; friend class ConnStates::TGenerateConnectionUpProgress; diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/inc/ss_connLegacy.h --- a/datacommsserver/esockserver/inc/ss_connLegacy.h Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/inc/ss_connLegacy.h Thu Jan 07 13:34:53 2010 +0200 @@ -46,6 +46,7 @@ namespace AllInterfaceNotificationActivity { class TEnqueueNotification; +class TSendErrorToConnection; } namespace EnumerateConnectionsActivity @@ -82,6 +83,7 @@ friend class EnumerateConnectionsActivity::TCacheConnectionInfo; friend class EnumerateConnectionsActivity::TCompleteClient; friend class AllInterfaceNotificationActivity::TEnqueueNotification; + friend class AllInterfaceNotificationActivity::TSendErrorToConnection; friend class ConnStates::TNoTagOrCancelAllInterfaceWorker; friend class ConnStates::TCancelAllInterfaceNotificationWorker; diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/inc/ss_connprov.h --- a/datacommsserver/esockserver/inc/ss_connprov.h Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/inc/ss_connprov.h Thu Jan 07 13:34:53 2010 +0200 @@ -61,10 +61,15 @@ : iProviderInfo(aProviderInfo) { } + explicit XConnectionProviderInfoQuery(const TUint32 aAPid) + : iAPid(aAPid) + { + } IMPORT_C virtual TMatchResult Match(Factories::TFactoryObjectInfo& aProviderInfo); TProviderInfo iProviderInfo; + TUint32 iAPid; protected: explicit XConnectionProviderInfoQuery() diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/inc/ss_connstates.h --- a/datacommsserver/esockserver/inc/ss_connstates.h Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/inc/ss_connstates.h Thu Jan 07 13:34:53 2010 +0200 @@ -388,7 +388,8 @@ TConnPrefList* iConnPrefList; TConnCSRPref* iCSRPreferences; TBool iIsAutoStartPresent; - + TBool iStartReceived; // Indicates that ECNStart has been received + protected: typedef MeshMachine::TNodeContext TContext; diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/inc/ss_nodemessages_selector.h~ --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/datacommsserver/esockserver/inc/ss_nodemessages_selector.h~ Thu Jan 07 13:34:53 2010 +0200 @@ -0,0 +1,693 @@ +// 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 the License "Symbian Foundation License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +/** + @file + @publishedPartner + @released +*/ + +#ifndef SYMBIAN_NODEMESSAGES_SELECTOR_H +#define SYMBIAN_NODEMESSAGES_SELECTOR_H + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +namespace ConnStates +{ + class TSelectMetaPlane; +} + +class TConnProviderInfo; + +namespace ESock +{ + +/** +TConnProviderInfo based preferences. Can be passed into RConnection::Start +to specify what connection should be started. The handling of this preference +is implementation specific. + +@publishedPartner +@released +*/ + +class TConnProviderInfoPref : public TConnPref + { +public: + IMPORT_C explicit TConnProviderInfoPref(const TConnProviderInfo& aProviderInfo); + + IMPORT_C const TConnProviderInfo& Info() const; + }; + +/** +Selection preferences object used internally by the 3 plane comms implementation. + +@publishedPartner +@released +*/ +class TSelectionPrefs : public Meta::SMetaData + { +public: + /** + Uid and TypeId for SMetaData + */ + enum {EUid = 0x10272C79, ETypeId = 1}; + + /** + Scopes for which the selection can take place. + + Each of the flags may be set, alone, all or in any combinations + */ + enum TSelectionScope + { + /** + For initialisation only + */ + ENone = 0x00, + /** + Select only from preexisting providers. Do not create new ones. + */ + ESelectFromExisting = 0x01, + /** + Select only the top provider. + */ + EExplicitConnection = 0x02, + /** + Do not request a comms binder. + */ + ERequestCommsBinder = 0x04 + }; + + /** + Flags to indicate what type of selection is taking place. + */ + enum TSelectionFlags + { + /** + Selecting for a monitor access point. This access point does not affect the idleness + of a node. + */ + EMonitor = 0x01, + /** + Selecting for an access point wishing to attach to a specified access point which + already exists + */ + EAttach = 0x02 + }; + +public: + IMPORT_C TSelectionPrefs(); + /** + @param aSelectionScope Scope for which the selection will take place + */ + IMPORT_C TSelectionPrefs(TSelectionScope aSelectionScope); + /** + @param aPref Preferences used to decide which access point to select + */ + IMPORT_C TSelectionPrefs(const TConnPref& aPref); + + /** + @param aPref Preferences used to decide which access point to select + */ + inline void SetPrefs(const TConnPref& aPref); + + /** + @return Mutable connection preferences of this selection preference. + */ + inline TConnPref& Prefs(); + + /** + @return Immutable connection preferences of this selection preference. + */ + inline const TConnPref& Prefs() const; + + /** + @return ETrue if no preferences has been set in the selection preferences object + */ + inline TBool IsEmpty() const; + + /** + @return the scope of the selection preferences + */ + inline TUint Scope() const; + + /** + @param aScope a new scope for the selection preferences + */ + inline void SetScope(TUint aScope); + + /** + @return The flags which have been set for the selection preferences + */ + inline TUint Flags() const; + + /** + @param aFlags New flags for set for the selection preferences. Overwrites the old flags + */ + inline void SetFlags(TUint aFlags); + + /** + @return The subsession unique id of the subsession which initiated this selection + */ + inline TSubSessionUniqueId SubSessionUniqueId() const; + + /** + @param aSubSessionUniqueId The subsession unique id of the subsession initiated this selection + */ + inline void SetSubSessionUniqueId(TSubSessionUniqueId aSubSessionUniqueId); + + EXPORT_DATA_VTABLE_AND_FN + +private: + TConnPref iPrefs; + union + { + TUint iSelectionParams; //used by meta data offset + struct //used by node + { + TUint iScope : 16; + TUint iFlags : 16; + } iS; + } iU; + TSubSessionUniqueId iSubSessionUniqueId; + }; + +void TSelectionPrefs::SetPrefs(const TConnPref& aPref) + { + iPrefs = aPref; + } + +TConnPref& TSelectionPrefs::Prefs() + { + return iPrefs; + } + +const TConnPref& TSelectionPrefs::Prefs() const + { + return iPrefs; + } + +TBool TSelectionPrefs::IsEmpty() const + { + return iPrefs.ExtensionId() == TConnPref::EConnPrefUnknown; + } + +TUint TSelectionPrefs::Scope() const + { + return iU.iS.iScope; + } + +void TSelectionPrefs::SetScope(TUint aScope) + { + iU.iS.iScope = aScope; + } + +TUint TSelectionPrefs::Flags() const + { + return iU.iS.iFlags; + } + +void TSelectionPrefs::SetFlags(TUint aFlags) + { + iU.iS.iFlags = aFlags; + } + +TSubSessionUniqueId TSelectionPrefs::SubSessionUniqueId() const + { + return iSubSessionUniqueId; + } + +void TSelectionPrefs::SetSubSessionUniqueId(TSubSessionUniqueId aSubSessionUniqueId) + { + iSubSessionUniqueId = aSubSessionUniqueId; + } + +/** +Selection preferences override. By default a mcpr will select using the selection prefs +which were used to create it. The selection preferences override can be used to make them use +something else. + +@publishedPartner +@released +*/ +class TOverridenSelectionPrefsExt : public Meta::SMetaData + { +public: + enum {EUid = 0x10272C79, ETypeId = 2}; + +public: + /** + @param aTierId The tier on which the preferences will be used + @param aPrefs The preferences which will override the default preferences + */ + IMPORT_C explicit TOverridenSelectionPrefsExt(TUid aTierId, const TSelectionPrefs& aPrefs); + + EXPORT_DATA_VTABLE_AND_FN + + TSelectionPrefs iPrefs; + TUid iTierId; + }; + +/** +Panic catagory for RConnPrefList panics +*/ +_LIT (RConnPrefListPanic,"RConnPrefListPanic"); + +/** +Null element panic code. An attempt was made to access an element in the +preferences list that didn't exist +*/ +const TInt ENullElement = 1; + +/** +This class will be used as a handle to TConnPrefList. During construction of +the stack this class will be sent in messages as TConnPrefList cannot be sent +in every message. The overhead of this would be too great (as it would have to +be serialized and deserialized every time the message was sent). A reference +cannot be sent as this would not work across processes. + + +@publishedPartner +@released +*/ +class RConnPrefList + { + friend class ConnStates::TSelectMetaPlane; +public: + /** + Base class for RConnPrefList iterators + */ + class TIterBase + { + protected: + /** + @param aConnPrefList Connection preference list to iterate over + */ + TIterBase(RConnPrefList &aConnPrefList) + : iConnPrefList(aConnPrefList), iMasterIndex(0) + { + + } + + /** + @param aType Only return preferences of this type + @param aIndex Index of preference requested + @return The requested connection preference, or NULL if no preference of the specified type was found at aIndex + */ + IMPORT_C Meta::SMetaData* AtIndex(const Meta::STypeId& aType, TInt aIndex); + + protected: + RConnPrefList& iConnPrefList; + TInt iMasterIndex; + }; + + template + /** + This iterator will return objects of the templated class. It will only + return objects from the list that are of the type passed in as the template parameter + */ + class TIter : public TIterBase + { + public: + /** + @param aConnPrefList Connection preferences to iterate over + */ + TIter(RConnPrefList &aConnPrefList) + : TIterBase(aConnPrefList) + { + iIndex = 0; + } + + /** + This will return the instance of the given type in the list at the + point specified by aIndex + + @param aIndex index of item to return + @return The item found at the index, or NULL if not found + */ + TYPE* operator[](TInt aIndex) + { + return static_cast(AtIndex(Meta::STypeId::CreateSTypeId(TYPE::EUid,TYPE::ETypeId) , aIndex)); + } + + /** + @return the next instance of the given tpye in the list or NULL if no more instances remain + */ + TYPE* operator++(TInt) + { + return static_cast((*this)[iIndex++]); + } + + /** + @return a reference to the current object pointed to by the iterator + */ + TYPE& operator*() + { + TYPE* ptr = static_cast(iConnPrefList[iMasterIndex]); + __ASSERT_ALWAYS(ptr != NULL,User::Panic(RConnPrefListPanic, ENullElement)); + return *ptr; + } + + /** + @return a pointer to the current object pointed to by the iterator + */ + TYPE* operator->() + { + TYPE* ptr = static_cast(iConnPrefList[iMasterIndex]); + return ptr; + } + + /** + @return ETrue if there are no more elements to iterate over. EFalse, otherwise + */ + TBool IsEnd() + { + if((*this)[iIndex] == NULL) + { + return ETrue; + } + else + { + return EFalse; + } + } + + /** + Remove the current object from the iterators associated RConnPrefList + @return a pointer to the removed object + */ + TYPE* Remove() + { + TYPE* ptr = static_cast(iConnPrefList[iMasterIndex]); + iConnPrefList.Remove(iMasterIndex); + (*this)[iIndex]; + return ptr; + } + + private: + TInt iIndex; + }; + +public: + IMPORT_C RConnPrefList(); + + /** + Open and initialise with data from passed in RConnPrefList + @param aPrefList RConnPrefList to copy data from. The copy is shallow. + */ + IMPORT_C void Open(RConnPrefList& aPrefList); + + /** + Close the RConnPrefList object + */ + IMPORT_C void Close(); + + /** + Create an iterator for template parameter TYPE. The iterator will be able to + iterate over all the members of the RConnPrefList which match the type specified. + @return A new iterator object for this connection preferences list + */ + template + RConnPrefList::TIter getIter() + { + return RConnPrefList::TIter(*this); + } + + /** + Append a preference to connection preferences list + @param aFamily Preference to append + @leave System wide error code. + */ + IMPORT_C void AppendL(SMetaDataECom* aFamily); + + /** + @param aIndex index of requested object + @return The object at aIndex + */ + IMPORT_C SMetaData* operator[](TInt aIndex); + + /** + Remove an object from the RConnPrefList + @param aIndex the index of the object to remove + */ + IMPORT_C void Remove(TInt aIndex); + + /** + @return the number of preferences in the list + */ + IMPORT_C TInt Count(); + +private: + TInt Open(TConnPrefList* aObject); + TConnPrefList* iObject; + }; + + +/** +Signature for a message which can carry selection preferences +*/ +struct TSigSelectionPrefs : public Messages::TSignatureBase + { +protected: + inline TSigSelectionPrefs() {} + + /** + @param aMessageId Id of the message this signature is being created for. + */ + TSigSelectionPrefs(const Messages::TNodeSignal::TMessageId& aMessageId) + : Messages::TSignatureBase(aMessageId) + {} + + /** + @param aMessageId Id of the message this signature is being created for. + @param aSelectionPrefs Selection preferences object to be passed in the message + */ + TSigSelectionPrefs(const Messages::TNodeSignal::TMessageId& aMessageId, const Meta::SMetaData& aSelectionPrefs) + : Messages::TSignatureBase(aMessageId) + { + //TODO: the copy can be optimised out when SMetaDataNetCtr handlers supported. + iSelectionPrefs.Copy(aSelectionPrefs); + } +public: + DECLARE_MVIP_CTR(TSigSelectionPrefs) + EXPORT_DATA_VTABLE_AND_FN + + /** + Selection preferences object passed in the message + */ + TSelectionPrefs iSelectionPrefs; + }; + +/** +Signature for a message which can carry a list of connection preferences +*/ +struct TSigConnPrefList : public Messages::TSignatureBase + { +protected: + inline TSigConnPrefList() {} + + /** + @param aMessageId Id of the message this signature is being created for. + */ + TSigConnPrefList(const Messages::TNodeSignal::TMessageId& aMessageId) + : Messages::TSignatureBase(aMessageId) + {} + + /** + @param aMessageId Id of the message this signature is being created for. + @param aConnPrefList List of connection preferences to be passed in this message + */ + TSigConnPrefList(const Messages::TNodeSignal::TMessageId& aMessageId, RConnPrefList& aConnPrefList) + : Messages::TSignatureBase(aMessageId) + { + iConnPrefList = aConnPrefList; + } +public: + DECLARE_MVIP_CTR(TSigConnPrefList) + EXPORT_DATA_VTABLE_AND_FN + + /** + List of connection preferences passed in this message + */ + RConnPrefList iConnPrefList; + }; + + +/** +Message signature template for a message which can carry selection preferences + +@see TSigSelectionPrefs +*/ +template +struct TMessageSigSelectionPrefs : public TSigSelectionPrefs, public Messages::TSignatureBase::TTypeToMessageId + { + explicit TMessageSigSelectionPrefs() : + TSigSelectionPrefs(Messages::TNodeSignal::TMessageId(id, realm)) + { } + + explicit TMessageSigSelectionPrefs(const Meta::SMetaData& aSelectionPrefs) + : TSigSelectionPrefs(Messages::TNodeSignal::TMessageId(id, realm), aSelectionPrefs) + { + } + }; + +/** +Message signature template for a message which can carry a list of connection preferences + +@see TSigConnPrefList +*/ +template + struct TMessageSigConnPrefList : public TSigConnPrefList, public Messages::TSignatureBase::TTypeToMessageId + { + explicit TMessageSigConnPrefList() + : TSigConnPrefList(Messages::TNodeSignal::TMessageId(id, realm)) + {} + + explicit TMessageSigConnPrefList(RConnPrefList& aCustomPrefs) + : TSigConnPrefList(Messages::TNodeSignal::TMessageId(id, realm), aCustomPrefs) + {} + }; + +/** +Signature for a select complete message. +*/ +struct TSigSelectComplete : public Messages::TSignatureBase + { +protected: + inline TSigSelectComplete() {} + + /** + @param aMessageId Id of the message this signature is being created for. + @param aNodeId Node id of node which has been created + @param aProviderInfo Provider info of access point which has been created. + */ + TSigSelectComplete(const Messages::TNodeSignal::TMessageId& aMessageId, const Messages::TNodeId& aNodeId, const TProviderInfo& aProviderInfo) + : Messages::TSignatureBase(aMessageId), + iNodeId(aNodeId), + iProviderInfo(aProviderInfo) + { + } +public: + DECLARE_MVIP_CTR(TSigSelectComplete) + EXPORT_DATA_VTABLE_AND_FN + /** + Node id of node which has been created + */ + Messages::TNodeId iNodeId; + /** + Provider info of the access point which has been created + */ + TProviderInfo iProviderInfo; + }; + +/** +Message signature template for a select complete message + +@see TSigSelectComplete + */ +template +struct TMessageSigSelectComplete : public TSigSelectComplete, public Messages::TSignatureBase::TTypeToMessageId + { + explicit TMessageSigSelectComplete(const Messages::TNodeId& aNodeId, const TProviderInfo aProviderInfo) + : TSigSelectComplete(Messages::TNodeSignal::TMessageId(id, realm), aNodeId, aProviderInfo) + { + } + }; + +/** +Message signature template for availability subscription message + */ +DECLARE_MESSAGE_SIG_1(SigAvailabilitySubscriptionOptions, TAvailabilitySubscriptionOptions, AvailabilitySubscriptionOptions) +/** +Message signature for availability status message +*/ +DECLARE_MESSAGE_SIG_1(SigAvailabilityStatus, TAvailabilityStatus, AvailabilityStatus) + +/** +Message interface for selector nodes +Nodes wishing to implement this interface must implement all message protocols in the interface. + +@publishedPartner +@released +*/ +class TCFSelector + { + private: + enum + { + ECFSimpleSelect = 1, + ECFSelect = 2, + ECFSelectComplete = 3 + }; + +public: + enum { ERealmId = 0x10285F4E }; //UID allocated on 4/6/08 from KUidNodeMessageRealms + + /** + Selection request sent to TierManagers (usually by MCPRs). Can only carry one type of selection preferences at a time, and for this + reason, using TSelect is preferred. It should be noted however, that multiple nodes may be returned in exchange for this single + preference, for example in the case of SNAP preferences. + + This request is completed only after TSelectComplete with a NULL address has been received by the requestor. + + @li Type: Request + @li Fallible: Yes + + @param iSelectionPrefs preferences used by the selection process to choose nodes + */ + typedef TMessageSigSelectionPrefs TSimpleSelect; + + + /** + Selection request sent to Tier Managers (usually by MCPRs or CSR). Carries an RConnPrefList instance, the objects in the list are used + during the construction of the stack. Multiple nodes may be returned by the selection activity. This request is completed only after + TSelectComplete with a NULL address has been received by the requestor. + + @li Type: Request + @li Fallible: Yes + + @param aConnPrefList an instance of RConnPrefList + */ + typedef TMessageSigConnPrefList TSelect; + + /** + Response to TSelect or TSelectNextLayer. Carries address to selected providers (MCPRs). A selection request is completed only after + TSelectComplete with a NULL address has been received by the requestor. This response also carries some additional information about + the selected provider. + + @li Type: Response to TSimpleSelect or TSelect + @li Fallible: No + + @param iNodeId node id of the node which has been selected + @param iProviderInfo additional information about the created node + */ + typedef TMessageSigSelectComplete TSelectComplete; + }; + +} //namespace esock + +#endif +//SYMBIAN_NODEMESSAGES_SELECTOR_H + diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/ssock/ss_conn.cpp --- a/datacommsserver/esockserver/ssock/ss_conn.cpp Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/ssock/ss_conn.cpp Thu Jan 07 13:34:53 2010 +0200 @@ -303,7 +303,6 @@ } - namespace ConnectionGoingDownActivity { DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityGoneDown, ConnectionGoingDown, TCFControlClient::TGoneDown, PRActivities::CGoneDownActivity::NewL) @@ -311,9 +310,10 @@ THROUGH_NODEACTIVITY_ENTRY(KNoTag, ConnectionGoingDownActivity::TStoreGoneDownError, MeshMachine::TNoTag) THROUGH_NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TCancelAndCloseZone0ClientExtIfaces, MeshMachine::TNoTag) THROUGH_NODEACTIVITY_ENTRY(KNoTag, ConnStates::TCancelAllLegacyRMessage2Activities, ConnStates::TNoTagBlockedByLegacyRMessage2Activities) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, ConnStates::TGenerateConnectionDownProgress, MeshMachine::TNoTag) NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendClientLeavingRequestToServiceProviders, MeshMachine::TAwaitingLeaveComplete, MeshMachine::TNoTag) NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSetIdleIfNoServiceProviders, MeshMachine::TAwaitingLeaveComplete, ConnectionCleanupActivities::TNoTagOrNoTagBackwards) - LAST_NODEACTIVITY_ENTRY(KNoTag, ConnStates::TGenerateConnectionDownProgress) + LAST_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing) NODEACTIVITY_END() } @@ -402,6 +402,8 @@ : CMMSockSubSession(ConnectionActivities::connectionActivities::Self(), aSession, aPlayer, aSubSessionUniqueId), ASubSessionPlatsecApiExt(UniqueId()), TIfStaticFetcherNearestInHierarchy(this), + iLastProgress(KConnectionUninitialised, KErrNone), + iLastProgressError(KConnectionUninitialised, KErrNone), iTierId(aTierId), iLegacyConnection(*this) { @@ -516,6 +518,18 @@ Main body of CConnection::NewL(CSockSession* aSession, const CConnection& aExistingConnection) */ { + // will need to be brought over + iLastProgress = aExistingConnection.iLastProgress; + iLastProgressError = aExistingConnection.iLastProgressError; + iProgressQueue = aExistingConnection.iProgressQueue; + + /** + The first commented in section of code here is incorrect. It only clones one of the service providers and not them + all. This means that certain calls, GetIntSetting being one, does not work on cloned connections. Unfortunately, + some code now relies on this being broken (browser). This code needs to be fixed before the first section of code + is removed and the proper code reinstated. + */ +#if 1 // BAD CODE RNodeInterface* sp = aExistingConnection.ServiceProvider(); if (sp) { @@ -529,6 +543,59 @@ LOG( ESockLog::Printf(KESockConnectionTag, _L8("CConnection %08x CloneL KErrNotReady"), this) ); User::Leave(KErrNotReady); } + +#else // PROPER CODE + /* + This function looks like it'd be better to do in one loop. dont do this though. All fallible parts need to be done before + sending the messages to ourselves, otherwise the mesh machine will panic. + */ + TInt numSP = 0; + TClientIter iter = aExistingConnection.GetClientIter(TClientType(TCFClientType::EServProvider), + Messages::TClientType(TCFClientType::EServProvider, Messages::TClientType::ELeaving)); + + /** + Add clients to client list. If this fails at any point, remove anything we've added. + Makes assumption that we are the only thing adding service providers. + */ + RNodeInterface* sp = iter++; + while (sp) + { + TRAPD(err, AddClientL(sp->RecipientId(), sp->ClientType())); + if (err != KErrNone) + { + sp = GetFirstClient(TClientType(TCFClientType::EServProvider)); + while (sp) + { + RemoveClient(sp->RecipientId()); + sp = GetFirstClient(TClientType(TCFClientType::EServProvider)); + } + User::Leave(err); + } + + sp = iter++; + numSP++; + } + + /** + If we managed to add anything, post messages to them so that we get added as control clients + */ + if (numSP == 0) + { + LOG( ESockLog::Printf(KESockConnectionTag, _L8("CConnection %08x CloneL KErrNotReady"), this) ); + User::Leave(KErrNotReady); + } + else + { + TClientIter iter = GetClientIter(TClientType(TCFClientType::EServProvider)); + sp = iter++; + while (sp) + { + // TODO IK: This is the wrong message to be using here, should use JoinRequest/Complete handshake + sp->PostMessage(Id(), TCFFactory::TPeerFoundOrCreated(Id(), 0).CRef()); + sp = iter++; + } + } +#endif } @@ -791,7 +858,9 @@ void CConnection::ProgressL() { - if (iLastProgress.iStage != KConnectionUp && iLastProgress.iStage != KConnectionDown) + if (iLastProgress.iStage != KConnectionUp + && iLastProgress.iStage != KConnectionDown + && iLastProgress.iStage != KConnectionUninitialised) { RNodeInterface* sp = ServiceProvider(); User::LeaveIfError(sp? KErrNone : KErrNotReady); @@ -812,7 +881,9 @@ void CConnection::LastProgressErrorL() { - if (iLastProgress.iStage != KConnectionUp && iLastProgress.iStage != KConnectionDown) + if (iLastProgress.iStage != KConnectionUp + && iLastProgress.iStage != KConnectionDown + && iLastProgress.iStage != KConnectionUninitialised) { RNodeInterface* sp = ServiceProvider(); User::LeaveIfError(sp? KErrNone : KErrNotReady); @@ -997,10 +1068,9 @@ // Enqueue the notification and wait for the next one - we loop here forever NODEACTIVITY_ENTRY(KNoTag, TEnqueueNotification, TAwaitingLinkNotification, CoreStates::TCancelOrErrorOrTag) - THROUGH_TRIPLE_ENTRY(KErrorTag, MeshMachine::TStoreError, MeshMachine::TTag) // If we received a TCancel from CConnection, reply with TError to complete shutdown handshake. - THROUGH_NODEACTIVITY_ENTRY(KCancelTag, TSendErrorToConnection, MeshMachine::TTag) - NODEACTIVITY_ENTRY(KCancelTag, TCancelLinkNotification, TAwaitingLinkNotificationError, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KCancelTag, TCancelLinkNotification, TAwaitingLinkNotificationError, MeshMachine::TTag) + THROUGH_TRIPLE_ENTRY(KErrorTag, TSendErrorToConnection, MeshMachine::TNoTag) LAST_NODEACTIVITY_ENTRY(KNoTag, TLeaveTierManager) // no other sessions with tier so can safely fire & forget this NODEACTIVITY_END() } diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/ssock/ss_connprov.cpp --- a/datacommsserver/esockserver/ssock/ss_connprov.cpp Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/ssock/ss_connprov.cpp Thu Jan 07 13:34:53 2010 +0200 @@ -59,7 +59,9 @@ CConnectionProviderBase* prov = static_cast(aProviderInfo.iInfo.iFactoryObject); const TProviderInfo& thePI = static_cast(prov->AccessPointConfig().FindExtensionL( STypeId::CreateSTypeId(TProviderInfoExt::EUid, TProviderInfoExt::ETypeId))).iProviderInfo; - TBool isMatch = (thePI.TierId() == iProviderInfo.TierId()) && (thePI.APId() == iProviderInfo.APId()); + TBool isMatch = (thePI.APId() == iAPid); + LOG(ESockLog::Printf(KESockCtrlFactTag, _L("XConnectionProviderInfoQuery::Match %08x:\tiAPid is = %08x THePI.APId = %08x"), + this, iAPid, thePI.APId())); return (isMatch ? MFactoryQuery::EMatch : MFactoryQuery::EContinue); } diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/ssock/ss_connstates.cpp --- a/datacommsserver/esockserver/ssock/ss_connstates.cpp Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/ssock/ss_connstates.cpp Thu Jan 07 13:34:53 2010 +0200 @@ -168,6 +168,7 @@ } else { + ac.iStartReceived = ETrue; ac.SetSelectionScope(TSelectionPrefs::EExplicitConnection); } } @@ -845,10 +846,18 @@ // activity Id and so will never give a match. Here we ensure that our second IPC is matched and accepted. TCFInternalEsock::TSubSess* msg = message_cast(&aContext.iMessage); - if (!msg || msg->iMessage.Function() != ECNStart) + if (!msg || (msg->iMessage.Function() != ECNStart && msg->iMessage.Function() != ECNSetStartPrefs)) { return CNodeActivityBase::Next(aContext); } + else if (iStartReceived) + { + // ECNSetStartPrefs should only ever be seen as the IPC in the TSubSess kick off message + // ECNStart should only be seen once after an ECNSetStartPrefs or as the kick off message + PanicClient(ETwice); + aContext.iReturn = KErrInUse; + return ETrue; + } MESH_LOG((KESockConnectionTag, _L8("CStartAttachActivity::Next:\tAccepted ECNStart IPC after ECNSetStartPrefs"))); TBool nextRet = ACore::Next(&aContext); @@ -1440,8 +1449,12 @@ DEFINE_SMELEMENT(AllInterfaceNotificationActivity::TSendErrorToConnection, NetStateMachine::MStateTransition, TContext) void AllInterfaceNotificationActivity::TSendErrorToConnection::DoL() { - // Send a TError to the CConnection to complete the shutdown handshake. - RNodeInterface::OpenPostMessageClose(TNodeCtxId(iContext.ActivityId(), iContext.NodeId()), iContext.Node().iConnection.Id(), TEBase::TError(iContext.Activity()->KickOffMessageId(), KErrCancel).CRef()); + iContext.Node().iConnection.iLegacyConnection.CompleteAllInterfaceNotificationL(iContext.Activity()->Error()); + + TEBase::TError msg(iContext.Activity()->KickOffMessageId(), iContext.Activity()->Error()); + iContext.Activity()->PostToOriginators(msg); + + iContext.Activity()->SetError(KErrNone); } DEFINE_SMELEMENT(TNoTagOrCancelAllInterfaceWorker, NetStateMachine::MStateFork, TContext) diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/ssock/ss_thread.cpp --- a/datacommsserver/esockserver/ssock/ss_thread.cpp Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/ssock/ss_thread.cpp Thu Jan 07 13:34:53 2010 +0200 @@ -32,7 +32,7 @@ #include #include #include -#include "sd_rootserverchannelhandler.h" +#include #include "ss_connectionserver.h" #include #include diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/test/TE_EsockTestSteps/inc/EsockTestBase.h --- a/datacommsserver/esockserver/test/TE_EsockTestSteps/inc/EsockTestBase.h Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/test/TE_EsockTestSteps/inc/EsockTestBase.h Thu Jan 07 13:34:53 2010 +0200 @@ -139,6 +139,19 @@ TBool iValueExpected; }; +struct TRSocketSetOptParams + { + void Reset(); + + TPtrC iSocketName; + TInt iOptionName; + TInt iOptionLevel; + TPtrC iOptionToSetText; + TInt iOptionToSetValue; + TBool iTextSet; + TBool iValueSet; + }; + struct TProtocolDescriptionParams { void Reset(); @@ -482,6 +495,8 @@ TProtocolDesc& aProtocolDescriptionOutput); TInt GetOptSocket(const TRSocketGetOptParams& aParams, TDes8& aGetOptOutput); TInt GetOptSocket(const TRSocketGetOptParams& aParams, TInt& aGetOptOutput); + TInt SetOptSocket(const TRSocketSetOptParams& aParams, TDes8& aSetOptOutput); + TInt SetOptSocket(const TRSocketSetOptParams& aParams, TInt& aSetOptOutput); //connection functions library RConnection* FindConnection(const TDesC& aConnectionName); diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/test/TE_EsockTestSteps/inc/Sockets.TestSteps.h --- a/datacommsserver/esockserver/test/TE_EsockTestSteps/inc/Sockets.TestSteps.h Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/test/TE_EsockTestSteps/inc/Sockets.TestSteps.h Thu Jan 07 13:34:53 2010 +0200 @@ -375,6 +375,23 @@ _LIT(KSocketGetOptionStep, "SocketGetOptionStep"); +/** +Class implementing control and confirmation of RSocket::SetOpt() calls + +@internalComponent +*/ +class CSocketSetOptionStep : public CTe_EsockStepBase + { +public: + CSocketSetOptionStep(CCEsockTestBase*& aEsockTest); + TVerdict doSingleTestStep(); + TInt ConfigureFromIni(); + +private: + TRSocketSetOptParams iParams; + }; + +_LIT(KSocketSetOptionStep, "SocketSetOptionStep"); /** Class implementing confirmation of protocol description retrieved from a socket with: diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/test/TE_EsockTestSteps/src/EsockTestBase.cpp --- a/datacommsserver/esockserver/test/TE_EsockTestSteps/src/EsockTestBase.cpp Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/test/TE_EsockTestSteps/src/EsockTestBase.cpp Thu Jan 07 13:34:53 2010 +0200 @@ -195,6 +195,16 @@ iValueExpected = EFalse; } +void TRSocketSetOptParams::Reset() + { + iSocketName.Set(KNullDesC); + iOptionName = 0; + iOptionLevel = 0; + iOptionToSetText.Set(KNullDesC); + iTextSet = EFalse; + iValueSet = EFalse; + } + void TRSocketIoctlParams::Reset() { iSocketName.Set(KNullDesC); @@ -1061,6 +1071,24 @@ return s->GetOpt(aParams.iOptionName, aParams.iOptionLevel, aGetOptOutput); } +TInt CCEsockTestBase::SetOptSocket(const TRSocketSetOptParams& aParams, TDes8& aSetOptInput) + { + RSocket* s = iSocks.Find(aParams.iSocketName); + if (s == NULL) + return KErrNotFound; + + return s->SetOpt(aParams.iOptionName, aParams.iOptionLevel, aSetOptInput); + } + +TInt CCEsockTestBase::SetOptSocket(const TRSocketSetOptParams& aParams, TInt& aSetOptInput) + { + RSocket* s = iSocks.Find(aParams.iSocketName); + if (s == NULL) + return KErrNotFound; + + return s->SetOpt(aParams.iOptionName, aParams.iOptionLevel, aSetOptInput); + } + TInt CCEsockTestBase::ProtocolDescription( const TSocketProtocolDescriptionParams& aParams, TProtocolDesc& aProtocolDescriptionOutput) diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/test/TE_EsockTestSteps/src/Sockets.TestSteps.cpp --- a/datacommsserver/esockserver/test/TE_EsockTestSteps/src/Sockets.TestSteps.cpp Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/test/TE_EsockTestSteps/src/Sockets.TestSteps.cpp Thu Jan 07 13:34:53 2010 +0200 @@ -1019,6 +1019,8 @@ // Get options //------------ +_LIT(KOptionName, "OptionName"); +_LIT(KOptionLevel, "OptionLevel"); CSocketGetOptionStep::CSocketGetOptionStep(CCEsockTestBase*& aEsockTest) : CTe_EsockStepBase(aEsockTest) @@ -1026,8 +1028,6 @@ SetTestStepName(KSocketGetOptionStep); } -_LIT(KOptionName, "OptionName"); -_LIT(KOptionLevel, "OptionLevel"); _LIT(KExpectedOptionText, "ExpectedOptionText"); _LIT(KExpectedOptionValue, "ExpectedOptionValue"); @@ -1073,7 +1073,7 @@ // Checks on config values if(iParams.iValueExpected && iParams.iTextExpected) { - INFO_PRINTF1(_L("Can be only value of text expected. Not both")); + INFO_PRINTF1(_L("Can be only value or text expected. Not both")); return KErrCorrupt; } @@ -1140,7 +1140,127 @@ return TestStepResult(); } +// Set options +//------------ +CSocketSetOptionStep::CSocketSetOptionStep(CCEsockTestBase*& aEsockTest) +: CTe_EsockStepBase(aEsockTest) + { + SetTestStepName(KSocketSetOptionStep); + } + +_LIT(KOptionToSetText, "OptionToSetText"); +_LIT(KOptionToSetValue, "OptionToSetValue"); + +TInt CSocketSetOptionStep::ConfigureFromIni() + { + // Reset the parameters and read in necessary fields + iParams.Reset(); + + // Socket to apply it to + if((GetStringFromConfig(iSection, KTe_SocketName, iParams.iSocketName) != 1) + || (iParams.iSocketName.Length() == 0)) + { + INFO_PRINTF3(KErrString_MissingConfigFileField, &iSection, &KTe_SocketName); + return KErrNotFound; + } + + // Option "name" + if (GetIntFromConfig(iSection, KOptionName, iParams.iOptionName) != 1) + { + INFO_PRINTF3(KErrString_MissingConfigFileField, &iSection, &KOptionName); + return KErrNotFound; + } + + // Option level + if (GetIntFromConfig(iSection, KOptionLevel, iParams.iOptionLevel) != 1) + { + INFO_PRINTF1(_L("Option level not specified: defaulting to KLevelUnspecified")); + iParams.iOptionLevel = KLevelUnspecified; + } + + // Input text to be set + if(GetStringFromConfig(iSection, KOptionToSetText, iParams.iOptionToSetText) == 1) + { + iParams.iTextSet = ETrue; + } + + // Input value to be set + if(GetIntFromConfig(iSection, KOptionToSetValue, iParams.iOptionToSetValue) == 1) + { + iParams.iValueSet = ETrue; + } + + // Checks on config values + if(iParams.iValueSet && iParams.iTextSet) + { + INFO_PRINTF1(_L("Can be only value or text expected. Not both")); + return KErrCorrupt; + } + + if(!iParams.iValueSet && !iParams.iTextSet) + { + INFO_PRINTF1(_L("Must have value or text expected.")); + return KErrCorrupt; + } + + // All ok if we got this far + return KErrNone; + } + +TVerdict CSocketSetOptionStep::doSingleTestStep() + { + TRequestStatus requestStatus; + + TBuf8<256> inputBuffer; + inputBuffer.Copy(iParams.iOptionToSetText); + TInt inputValue = iParams.iOptionToSetValue; + TInt error; + + if(iParams.iTextSet) + { + error = iEsockTest->SetOptSocket(iParams, inputBuffer); + } + else + { + error = iEsockTest->SetOptSocket(iParams, inputValue); + } + + if (error != KErrNone) + { + INFO_PRINTF3(_L("Socket set option error. socket:%S, error:%d"), &iParams.iSocketName, error); + SetTestStepError(error); + return EFail; + } + + if(iParams.iTextSet) + { + // Convert the output to wide chars + TBuf<256> inputConvertedToWideChars; + CnvUtfConverter::ConvertToUnicodeFromUtf8(inputConvertedToWideChars, inputBuffer); + + // Log what was returned + INFO_PRINTF2(_L("Socket set with opt text. value:%S"), &inputConvertedToWideChars); + INFO_PRINTF2(_L("Text set by user. value:%S"), &iParams.iOptionToSetText); + + // Validate the output with that expected + TVerdict verdict = (inputConvertedToWideChars == iParams.iOptionToSetText) ? EPass : EFail; + SetTestStepResult(verdict); + } + else + { + // Log what was returned + INFO_PRINTF2(_L("Socket returned get opt value. value:%d"), inputValue); + INFO_PRINTF2(_L("Value set by user. value:%d"), iParams.iOptionToSetValue); + + // Validate the output with that expected + TVerdict verdict = (inputValue == iParams.iOptionToSetValue) ? EPass : EFail; + SetTestStepResult(verdict); + } + + // Return the result + return TestStepResult(); + } // Socket protocol description //---------------------------- diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/test/TE_EsockTestSteps/src/Te_esockteststepsSuiteServer.cpp --- a/datacommsserver/esockserver/test/TE_EsockTestSteps/src/Te_esockteststepsSuiteServer.cpp Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/test/TE_EsockTestSteps/src/Te_esockteststepsSuiteServer.cpp Thu Jan 07 13:34:53 2010 +0200 @@ -406,6 +406,7 @@ NEW_ESOCK_TESTSTEP(SendReceiveIoctlStep) NEW_ESOCK_TESTSTEP(SocketProtocolDescriptionStep) NEW_ESOCK_TESTSTEP(SocketGetOptionStep) + NEW_ESOCK_TESTSTEP(SocketSetOptionStep) // Socket server NEW_ESOCK_TESTSTEP(SocketServerNumProtocolsStep) diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/test/TE_RConnection/configs/ContentionManagement/CM_GT0429_00.txt --- a/datacommsserver/esockserver/test/TE_RConnection/configs/ContentionManagement/CM_GT0429_00.txt Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/test/TE_RConnection/configs/ContentionManagement/CM_GT0429_00.txt Thu Jan 07 13:34:53 2010 +0200 @@ -15,7 +15,7 @@ # ContextConfigGPRS = , , , , , # ProtocolConfigOption = , , , , # , , , -SetContextConfigGPRS= 0,Test,,0, 2, 0, 0,RasUser,,,,,,0 +SetContextConfigGPRS = 0,Test,,0,2,0,1,RasUser,,,,,,1 # TRel99ContextConfig = , , , , # , , diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/test/TE_RConnection/configs/ContentionManagement/CM_GT0429_01.txt --- a/datacommsserver/esockserver/test/TE_RConnection/configs/ContentionManagement/CM_GT0429_01.txt Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/test/TE_RConnection/configs/ContentionManagement/CM_GT0429_01.txt Thu Jan 07 13:34:53 2010 +0200 @@ -15,7 +15,7 @@ # ContextConfigGPRS = , , , , , # ProtocolConfigOption = , , , , # , , , -SetContextConfigGPRS= 0,Test,,0, 2, 0, 0,RasUser,,,,,,0 +SetContextConfigGPRS = 0,Test,,0,2,0,1,RasUser,,,,,,1 # TRel99ContextConfig = , , , , # , , diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/test/TE_RConnection/configs/ContentionManagement/CM_GT0429_05.txt --- a/datacommsserver/esockserver/test/TE_RConnection/configs/ContentionManagement/CM_GT0429_05.txt Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/test/TE_RConnection/configs/ContentionManagement/CM_GT0429_05.txt Thu Jan 07 13:34:53 2010 +0200 @@ -15,7 +15,7 @@ # ContextConfigGPRS = , , , , , # ProtocolConfigOption = , , , , # , , , -SetContextConfigGPRS= 0,Test,,0, 2, 0, 0,RasUser,,,,,,0 +SetContextConfigGPRS = 0,Test,,0,2,0,1,RasUser,,,,,,1 # TRel99ContextConfig = , , , , # , , diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/test/TE_RConnection/configs/ContentionManagement/config_001.txt --- a/datacommsserver/esockserver/test/TE_RConnection/configs/ContentionManagement/config_001.txt Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/test/TE_RConnection/configs/ContentionManagement/config_001.txt Thu Jan 07 13:34:53 2010 +0200 @@ -15,7 +15,7 @@ # ContextConfigGPRS = , , , , , # ProtocolConfigOption = , , , , # , , , -SetContextConfigGPRS= 0,Test,,0, 2, 0, 0,RasUser,,,,,,0 +SetContextConfigGPRS = 0,Test,,0,2,0,1,RasUser,,,,,,1 # TRel99ContextConfig = , , , , # , , diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/test/TE_RConnection/configs/ContentionManagement/config_004.txt --- a/datacommsserver/esockserver/test/TE_RConnection/configs/ContentionManagement/config_004.txt Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/test/TE_RConnection/configs/ContentionManagement/config_004.txt Thu Jan 07 13:34:53 2010 +0200 @@ -15,7 +15,7 @@ # ContextConfigGPRS = , , , , , # ProtocolConfigOption = , , , , # , , , -SetContextConfigGPRS= 0,Test,,0, 2, 0, 0,RasUser,,,,,,0 +SetContextConfigGPRS = 0,Test,,0,2,0,1,RasUser,,,,,,1 # TRel99ContextConfig = , , , , # , , diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/test/TE_RConnection/configs/ContentionManagement/config_015.txt --- a/datacommsserver/esockserver/test/TE_RConnection/configs/ContentionManagement/config_015.txt Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/test/TE_RConnection/configs/ContentionManagement/config_015.txt Thu Jan 07 13:34:53 2010 +0200 @@ -15,7 +15,7 @@ # ContextConfigGPRS = , , , , , # ProtocolConfigOption = , , , , # , , , -SetContextConfigGPRS= 0,Test,,0, 2, 0, 0,RasUser,,,,,,0 +SetContextConfigGPRS = 0,Test,,0,2,0,1,RasUser,,,,,,1 # TRel99ContextConfig = , , , , # , , diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/test/TE_RConnectionServ/configs/CIT_mixedap_config.txt --- a/datacommsserver/esockserver/test/TE_RConnectionServ/configs/CIT_mixedap_config.txt Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/test/TE_RConnectionServ/configs/CIT_mixedap_config.txt Thu Jan 07 13:34:53 2010 +0200 @@ -14,7 +14,8 @@ # ContextConfigGPRS = , , , , , # ProtocolConfigOption = , , , , # , , , -SetContextConfigGPRS= 0,Test,,0, 2, 0, 0,RasUser,,,,,,0 +SetContextConfigGPRS = 0,Test,,0,2,0,1,RasUser,,,,,,1 + # TRel99ContextConfig = , , , , # , , diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/test/TE_RConnectionServ/configs/CIT_pppavail_config.txt --- a/datacommsserver/esockserver/test/TE_RConnectionServ/configs/CIT_pppavail_config.txt Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/test/TE_RConnectionServ/configs/CIT_pppavail_config.txt Thu Jan 07 13:34:53 2010 +0200 @@ -14,7 +14,7 @@ # ContextConfigGPRS = , , , , , # ProtocolConfigOption = , , , , # , , , -SetContextConfigGPRS= 0,Test,,0, 2, 0, 0,RasUser,,,,,,0 +SetContextConfigGPRS = 0,Test,,0,2,0,1,RasUser,,,,,,1 # TRel99ContextConfig = , , , , # , , diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/test/TE_RConnectionSuite/config/rconnectioncmm_test456_config.txt --- a/datacommsserver/esockserver/test/TE_RConnectionSuite/config/rconnectioncmm_test456_config.txt Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/test/TE_RConnectionSuite/config/rconnectioncmm_test456_config.txt Thu Jan 07 13:34:53 2010 +0200 @@ -14,7 +14,7 @@ # ContextConfigGPRS = , , , , , # ProtocolConfigOption = , , , , # , , , -SetContextConfigGPRS= 0,Test,,0, 2, 0, 0,RasUser,,,,,,0 +SetContextConfigGPRS= 0,Test,,0, 2, 0, 1,RasUser,,,,,,1 # TRel99ContextConfig = , , , , # , , diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/test/TE_RConnectionSuite/config/te_rconnectionallinterfacenot_Connection_Tests.script --- a/datacommsserver/esockserver/test/TE_RConnectionSuite/config/te_rconnectionallinterfacenot_Connection_Tests.script Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/test/TE_RConnectionSuite/config/te_rconnectionallinterfacenot_Connection_Tests.script Thu Jan 07 13:34:53 2010 +0200 @@ -111,3 +111,11 @@ END_TESTCASE COMINF-ESOCK-RConnectionSuite-AllInterfaceNot-0109 +START_TESTCASE COMINF-ESOCK-RConnectionSuite-AllInterfaceNot-0111 +//! @SYMTestCaseID COMINF-ESOCK-RConnectionSuite-AllInterfaceNot-0111 + +heap_mark +run_test_step 500, TE_RConnectionSuite Test319 c:\rconnectiontest.ini +heap_markend +test_complete +END_TESTCASE COMINF-ESOCK-RConnectionSuite-AllInterfaceNot-0111 diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/test/TE_RConnectionSuite/config/te_rconnectioncmmtests_NonConnection.script --- a/datacommsserver/esockserver/test/TE_RConnectionSuite/config/te_rconnectioncmmtests_NonConnection.script Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/test/TE_RConnectionSuite/config/te_rconnectioncmmtests_NonConnection.script Thu Jan 07 13:34:53 2010 +0200 @@ -241,6 +241,38 @@ #test_complete //END_TESTCASE COMINF-ESOCK-RConnectionSuite-CMM-0621 +START_TESTCASE COMINF-ESOCK-RConnectionSuite-CMM-0622 +//! @SYMTestCaseID COMINF-ESOCK-RConnectionSuite-CMM-0622 +//!@SYMTestCaseDesc Test correct progresses arrive at the correct times +//!@SYMPREQ PREQ399 +//!@SYMAPI +//RConnection::Progress() +//RConnection::ProgressNotification() +//!@SYMTestPriority Critical +//!@SYMTestActions +// Open conn1 +// Request progress on conn1 +// Check progress (Should be KConnectionUninitialised) +// Request progress notification on conn1 +// Start conn1 +// Check progress (Should be KStartingSelection) +// Stop conn1 +// Open conn1 +// Request progress on conn1 +// Check progress (Should be KConnectionUninitialised) +// Request progress notification on conn1 for when conn1 gets KFinishedSelection progress +// Start conn1 +// Check progress (Should be KFinishedSelection) +// Stop conn1 +// +//!@SYMTestType CIT +//!@SYMTestExpectedResults All progresses are as expected + +heap_mark +run_test_step 100, TE_RConnectionSuite Test319 c:\rconnectiontest.ini +heap_markend +test_complete +END_TESTCASE COMINF-ESOCK-RConnectionSuite-CMM-0622 run_script z:\TestData\scripts\te_esock_test_unloadesockForced.script diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/test/TE_RConnectionSuite/inc/TE_AllInterfaceNotification.h --- a/datacommsserver/esockserver/test/TE_RConnectionSuite/inc/TE_AllInterfaceNotification.h Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/test/TE_RConnectionSuite/inc/TE_AllInterfaceNotification.h Thu Jan 07 13:34:53 2010 +0200 @@ -153,11 +153,5 @@ }; -class TE_RConnectionTest319 : public TE_RConnectionStep -{ -public: - virtual enum TVerdict doTestStepL(); - -}; #endif // TS_ALLINTERFACENOTIFICATION_H diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/test/TE_RConnectionSuite/inc/TE_RConnectionCMM.h --- a/datacommsserver/esockserver/test/TE_RConnectionSuite/inc/TE_RConnectionCMM.h Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/test/TE_RConnectionSuite/inc/TE_RConnectionCMM.h Thu Jan 07 13:34:53 2010 +0200 @@ -861,5 +861,12 @@ virtual enum TVerdict doTestStepL (); }; +class TE_RConnectionTest319 : public TE_RConnectionStep +{ +public: + virtual enum TVerdict doTestStepL(); + +}; + #endif // TE_RConnectionCMM_H diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/test/TE_RConnectionSuite/src/TE_AllInterfaceNotification.cpp --- a/datacommsserver/esockserver/test/TE_RConnectionSuite/src/TE_AllInterfaceNotification.cpp Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/test/TE_RConnectionSuite/src/TE_AllInterfaceNotification.cpp Thu Jan 07 13:34:53 2010 +0200 @@ -1628,66 +1628,3 @@ return TestStepResult(); } // TE_RConnectionTest318 -/****************************************************************************** - * - * Test 319 - * - * To test progress - * - *****************************************************************************/ - -// To test progress -enum TVerdict TE_RConnectionTest319::doTestStepL(void) -{ - RSocketServ ss; - RConnection conn1; - - TRequestStatus tStartConn; - - TInt nErr = OpenSocketServer( ss ); - TESTEL(KErrNone == nErr, nErr); - CleanupClosePushL(ss); - - nErr = conn1.Open( ss ); - TESTEL( nErr == KErrNone, nErr ); - CleanupClosePushL(conn1); - - TNifProgress tProg; - conn1.Progress( tProg ); - TESTEL( tProg.iError == KErrNone && tProg.iStage == 0, tProg.iError ); - - TNifProgressBuf tNifProgressBuf; - conn1.ProgressNotification( tNifProgressBuf, tStartConn, KConnProgressDefault ); - nErr = conn1.Start(); - TESTEL( nErr == KErrNone, nErr ); - User::WaitForRequest( tStartConn ); - TESTEL( tStartConn.Int() == KErrNone, tStartConn.Int() ); - TESTEL( tNifProgressBuf().iStage == KStartingSelection, tNifProgressBuf().iStage ); - - //close conn1 - conn1.Stop(); - CleanupStack::PopAndDestroy(); - - nErr = conn1.Open( ss ); - TESTEL( nErr == KErrNone, nErr ); - CleanupClosePushL(conn1); - - conn1.Progress( tProg ); - TESTEL( tProg.iError == KErrNone && tProg.iStage == 0, tProg.iError ); - //wait for particular guy - conn1.ProgressNotification( tNifProgressBuf, tStartConn, KFinishedSelection ); - nErr = conn1.Start(); - TESTEL( nErr == KErrNone, nErr ); - User::WaitForRequest( tStartConn ); - TESTEL( tStartConn.Int() == KErrNone, tStartConn.Int() ); - TESTEL( tNifProgressBuf().iStage == KFinishedSelection, tNifProgressBuf().iStage ); - - //close conn1 - conn1.Stop(); - CleanupStack::PopAndDestroy(); - - //close ss - CleanupStack::PopAndDestroy(); - return TestStepResult(); -} // TE_RConnectionTest319 - diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/test/TE_RConnectionSuite/src/TE_RConnectionCMM.cpp --- a/datacommsserver/esockserver/test/TE_RConnectionSuite/src/TE_RConnectionCMM.cpp Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/test/TE_RConnectionSuite/src/TE_RConnectionCMM.cpp Thu Jan 07 13:34:53 2010 +0200 @@ -7202,5 +7202,72 @@ } // TE_RConnectionTest480 +/****************************************************************************** + * + * Test 319 + * + * To test progress + * + *****************************************************************************/ + +// To test progress +enum TVerdict TE_RConnectionTest319::doTestStepL(void) +{ + RSocketServ ss; + RConnection conn1; + + TRequestStatus tStartConn; + + TInt nErr = OpenSocketServer( ss ); + TESTEL(KErrNone == nErr, nErr); + CleanupClosePushL(ss); + + nErr = conn1.Open( ss ); + TESTEL( nErr == KErrNone, nErr ); + CleanupClosePushL(conn1); + + TNifProgress tProg; + conn1.Progress( tProg ); + TESTEL( tProg.iError == KErrNone && tProg.iStage == 0, tProg.iError ); + + TNifProgressBuf tNifProgressBuf; + conn1.ProgressNotification( tNifProgressBuf, tStartConn, KConnProgressDefault ); + + nErr = StartConnectionWithOverrides(conn1, iDummyNifIap); + + TESTEL( nErr == KErrNone, nErr ); + User::WaitForRequest( tStartConn ); + TESTEL( tStartConn.Int() == KErrNone, tStartConn.Int() ); + TESTEL( tNifProgressBuf().iStage == KStartingSelection, tNifProgressBuf().iStage ); + + //close conn1 + conn1.Stop(); + CleanupStack::PopAndDestroy(); + + nErr = conn1.Open( ss ); + TESTEL( nErr == KErrNone, nErr ); + CleanupClosePushL(conn1); + + conn1.Progress( tProg ); + TESTEL( tProg.iError == KErrNone && tProg.iStage == 0, tProg.iError ); + //wait for particular guy + conn1.ProgressNotification( tNifProgressBuf, tStartConn, KFinishedSelection ); + nErr = StartConnectionWithOverrides(conn1, iDummyNifIap); + + TESTEL( nErr == KErrNone, nErr ); + User::WaitForRequest( tStartConn ); + TESTEL( tStartConn.Int() == KErrNone, tStartConn.Int() ); + TESTEL( tNifProgressBuf().iStage == KFinishedSelection, tNifProgressBuf().iStage ); + + //close conn1 + conn1.Stop(); + CleanupStack::PopAndDestroy(); + + //close ss + CleanupStack::PopAndDestroy(); + return TestStepResult(); +} // TE_RConnectionTest319 + + // EOF TE_RConnectionCMM.cpp diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/test/TE_RSubconnection/configs/te_RSubConnectionCase28.txt --- a/datacommsserver/esockserver/test/TE_RSubconnection/configs/te_RSubConnectionCase28.txt Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/test/TE_RSubconnection/configs/te_RSubConnectionCase28.txt Thu Jan 07 13:34:53 2010 +0200 @@ -14,7 +14,7 @@ # ContextConfigGPRS = , , , , , # ProtocolConfigOption = , , , , # , , , -SetContextConfigGPRS= 0,Test,,0, 2, 0, 0,RasUser,,,,,,0 +SetContextConfigGPRS = 0,Test,,0,2,0,1,RasUser,,,,,,1 # TRel99ContextConfig = , , , , # , , diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/test/TE_RSubconnection/configs/te_RSubConnection_simtsy.txt --- a/datacommsserver/esockserver/test/TE_RSubconnection/configs/te_RSubConnection_simtsy.txt Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/test/TE_RSubconnection/configs/te_RSubConnection_simtsy.txt Thu Jan 07 13:34:53 2010 +0200 @@ -12,7 +12,8 @@ # ContextConfigGPRS = , , , , , # ProtocolConfigOption = , , , , # , , , -SetContextConfigGPRS= 0,Test,,0, 2, 0, 0,RasUser,,,,,,0 +SetContextConfigGPRS = 0,Test,,0,2,0,1,RasUser,,,,,,1 + # TRel99ContextConfig = , , , , # , , diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/test/providers/dummy/inc/dummypr_mcprpubsubsubscriber.h --- a/datacommsserver/esockserver/test/providers/dummy/inc/dummypr_mcprpubsubsubscriber.h Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/test/providers/dummy/inc/dummypr_mcprpubsubsubscriber.h Thu Jan 07 13:34:53 2010 +0200 @@ -1,9 +1,9 @@ // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). // All rights reserved. // This component and the accompanying materials are made available -// under the terms of the License "Symbian Foundation License v1.0" +// under the terms of "Eclipse Public License v1.0" // which accompanies this distribution, and is available -// at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html". +// at the URL "http://www.eclipse.org/legal/epl-v10.html". // // Initial Contributors: // Nokia Corporation - initial contribution. diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/test/providers/dummy/inc/dummypr_metaconnprov.h --- a/datacommsserver/esockserver/test/providers/dummy/inc/dummypr_metaconnprov.h Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/test/providers/dummy/inc/dummypr_metaconnprov.h Thu Jan 07 13:34:53 2010 +0200 @@ -1,9 +1,9 @@ // 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 the License "Symbian Foundation License v1.0" +// under the terms of "Eclipse Public License v1.0" // which accompanies this distribution, and is available -// at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html". +// at the URL "http://www.eclipse.org/legal/epl-v10.html". // // Initial Contributors: // Nokia Corporation - initial contribution. diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/test/providers/dummy/src/dummypr_mcprpubsubsubscriber.cpp --- a/datacommsserver/esockserver/test/providers/dummy/src/dummypr_mcprpubsubsubscriber.cpp Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/test/providers/dummy/src/dummypr_mcprpubsubsubscriber.cpp Thu Jan 07 13:34:53 2010 +0200 @@ -1,9 +1,9 @@ // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). // All rights reserved. // This component and the accompanying materials are made available -// under the terms of the License "Symbian Foundation License v1.0" +// under the terms of "Eclipse Public License v1.0" // which accompanies this distribution, and is available -// at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html". +// at the URL "http://www.eclipse.org/legal/epl-v10.html". // // Initial Contributors: // Nokia Corporation - initial contribution. @@ -70,7 +70,7 @@ iProperty.Close(); } -/////////////////////////////////////////////////////////////////////////////// +// CMCPrPubSubAvailability* CMCPrPubSubAvailability::NewL(const ESock::CMetaConnectionProviderBase& aProvBase, TUint aStopCode) { @@ -134,9 +134,11 @@ __CFLOG_VAR((KDummyMCprTag, KDummyMCprSubTag, _L8("CMCPrPubSubAvailability subscribed value now %d"),value)); __ASSERT_DEBUG(!iAvailabilityActivity.IsNull(), User::Panic(KSpecAssert_DummyPrStopSubsc, 1)); //maybe a bit defensive, but this is test code after all. The test changes availability when nobody is listenning; Surely test is wrong? + RClientInterface::OpenPostMessageClose(Id(), iAvailabilityActivity, + TCFAvailabilityControlClient::TAvailabilityNotification(value).CRef()); } -/////////////////////////////////////////////////////////////////////////////// +// CMCPrPubSubStopTrigger* CMCPrPubSubStopTrigger::NewL(const ESock::CMetaConnectionProviderBase& aProvBase, TUint aStopCode) { diff -r dfb7c4ff071f -r 21d2ab05f085 datacommsserver/esockserver/test/providers/dummy/src/dummypr_metaconnprov.cpp --- a/datacommsserver/esockserver/test/providers/dummy/src/dummypr_metaconnprov.cpp Thu Dec 17 09:22:25 2009 +0200 +++ b/datacommsserver/esockserver/test/providers/dummy/src/dummypr_metaconnprov.cpp Thu Jan 07 13:34:53 2010 +0200 @@ -1,9 +1,9 @@ // 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 the License "Symbian Foundation License v1.0" +// under the terms of "Eclipse Public License v1.0" // which accompanies this distribution, and is available -// at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html". +// at the URL "http://www.eclipse.org/legal/epl-v10.html". // // Initial Contributors: // Nokia Corporation - initial contribution.