datacommsserver/esockserver/CoreProviders/src/coremcpractivities.cpp.orig
changeset 1 21d2ab05f085
equal deleted inserted replaced
0:dfb7c4ff071f 1:21d2ab05f085
       
     1 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include "coremcpractivities.h"
       
    17 
       
    18 
       
    19 #include <comms-infras/ss_log.h>
       
    20 #include <comms-infras/ss_coreprstates.h>
       
    21 #include <comms-infras/coremcprstates.h>
       
    22 #include <comms-infras/esock_params.h>
       
    23 #include <comms-infras/ss_nodemessages_selector.h>
       
    24 #include <comms-infras/ss_nodemessages_dataclient.h>
       
    25 #include <comms-infras/ss_nodemessages_serviceprovider.h>
       
    26 #include <comms-infras/ss_nodemessages_availability.h>
       
    27 #include <comms-infras/ss_nodemessages_factory.h>
       
    28 #include <comms-infras/ss_nodemessages_tiermanagerfactory.h>
       
    29 #include <comms-infras/ss_nodemessages_mcpr.h>
       
    30 
       
    31 #include <elements/nm_messages_peer.h>
       
    32 #include <elements/nm_messages_errorrecovery.h>
       
    33 #include <elements/nm_messages_child.h>
       
    34 #include <comms-infras/ss_tiermanagerutils.h>
       
    35 #include <ss_glob.h>
       
    36 #include "ss_internal_activities.h"
       
    37 #include <commsdattypesv1_1.h>
       
    38 
       
    39 #ifdef _DEBUG
       
    40 // Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module
       
    41 // (if it could happen through user error then you should give it an explicit, documented, category + code)
       
    42 _LIT(KSpecAssert_ESockCoreProvcprac, "ESockCrPrvcprac");
       
    43 #endif
       
    44 
       
    45 #ifdef __CFLOG_ACTIVE
       
    46 	#define KCoreMCprStatesTag KESockMetaConnectionTag
       
    47 	_LIT8(KCoreMCprStatesSubTag, "coremcprstate");
       
    48 #endif
       
    49 
       
    50 using namespace ESock;
       
    51 using namespace MCprActivities;
       
    52 using namespace NetStateMachine;
       
    53 using namespace PRActivities;
       
    54 using namespace CorePanics;
       
    55 using namespace Messages;
       
    56 using namespace MeshMachine;
       
    57 
       
    58 
       
    59 //
       
    60 //Panics
       
    61 void CoreMCprPanic(TInt aCode)
       
    62 	{
       
    63 	_LIT(KCoreMCprPanic, "CoreMCprPanic");
       
    64 	User::Panic(KCoreMCprPanic, aCode);
       
    65 	}
       
    66 
       
    67 
       
    68 namespace MCprControlClientJoinActivity
       
    69 { //This activity needs the activity object (& it can fail on AddClientL, so no point converting)
       
    70 DECLARE_DEFINE_NODEACTIVITY(ECFActivityClientJoin, MCprControlClientJoin, Messages::TNodeSignal::TNullMessageId) //May be waiting for both messages
       
    71 	FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingControlClientJoin, MeshMachine::TNoTag)
       
    72 	LAST_NODEACTIVITY_ENTRY(KNoTag, MCprStates::TDecrementBlockingDestroyAndAddControlClientAndSendJoinCompleteIfRequest)
       
    73 NODEACTIVITY_END()
       
    74 }
       
    75 
       
    76 namespace MCprDataClientJoinActivity
       
    77 { //This activity needs the activity object (& it can fail on AddClientL, so no point converting)
       
    78 DECLARE_DEFINE_NODEACTIVITY(ECFActivityDataClientJoin, MCprDataClientJoin, TCFControlProvider::TJoinRequest)
       
    79 	FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingDataClientJoinRequest, MCprStates::TNoTagOrRejoinTag)
       
    80 	LAST_NODEACTIVITY_ENTRY(MCprStates::KRejoinTag, MCprStates::TProcessDataClientRejoin)
       
    81 	LAST_NODEACTIVITY_ENTRY(KNoTag, MCprStates::TDecrementBlockingDestroyAndAddDataClientAndRespond)
       
    82 NODEACTIVITY_END()
       
    83 }
       
    84 
       
    85 namespace MCprDestroyActivity
       
    86 {
       
    87 DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityDestroy, MCprDestroy, Messages::TNodeSignal::TNullMessageId, CoreActivities::CDestroyActivity::New) //May be waiting for both messages
       
    88 	FIRST_NODEACTIVITY_ENTRY(MCprStates::TAwaitingClientLeaveAndNoClients, MeshMachine::TNoTag)
       
    89     //MCprStates::TProcessClientLeave removes the client and marks the node for deletion.
       
    90 	//If there are no servce providers it also terminates the activity.
       
    91 	//If there are service providers it continues to following triples.
       
    92  	THROUGH_NODEACTIVITY_ENTRY(KNoTag, MCprStates::TProcessClientLeave, MeshMachine::TNoTag)
       
    93  	NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing, MeshMachine::TAwaitingLeaveComplete, CoreActivities::CDestroyActivity::TNoTagOrNoTagBackwards)
       
    94  	LAST_NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendClientLeavingAndRemoveControlProvider)
       
    95 NODEACTIVITY_END()
       
    96 }
       
    97 
       
    98 namespace MCprSimpleSelectActivity
       
    99 {
       
   100 DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivitySelect, MCprSimpleSelect, TCFSelector::TSimpleSelect, CSelectNextLayerActivity::NewL)
       
   101 	//Reply from TAwaitingSelectNextLayer if no choices, otherwise accept
       
   102 	FIRST_NODEACTIVITY_ENTRY(MCprStates::TAwaitingSelectNextLayer, MeshMachine::TNoTag)
       
   103 	THROUGH_NODEACTIVITY_ENTRY(KNoTag, CSelectNextLayerActivity::TProcessSimpleSelectionPolicy, MCprStates::TSelectedProvider)
       
   104 	//Start the selection main loop
       
   105 	NODEACTIVITY_ENTRY(MCprStates::KSelectedProvider, CSelectNextLayerActivity::TFindOrCreateTierManager, MCprStates::TAwaitingTierManagerCreated, MeshMachine::TNoTag)
       
   106 	NODEACTIVITY_ENTRY(KNoTag, CSelectNextLayerActivity::TJoinTierManager, CoreStates::TAwaitingJoinComplete, MeshMachine::TNoTag)
       
   107 	//Select next provider and enter the selection internal loop if provider received. Break if SelectComplete(NULL).
       
   108 	NODEACTIVITY_ENTRY(KNoTag, CSelectNextLayerActivity::TSelectNextLayer, MCprStates::TAwaitingSelectComplete, CSelectNextLayerActivity::TNoTagOrSelectedProviderIsNull)
       
   109     NODEACTIVITY_ENTRY(KNoTag, CSelectNextLayerActivity::TAddProviderInfo, MCprStates::TAwaitingSelectComplete, CSelectNextLayerActivity::TNoTagBackwardsOrJoinServiceProvider)
       
   110     //Break the selection internal loop if SelectComplete(NULL), otherwise stay in this tripple
       
   111     NODEACTIVITY_ENTRY(MCprStates::KJoinServiceProvider, CSelectNextLayerActivity::TJoinServiceProvider, CoreStates::TAwaitingJoinComplete, MeshMachine::TNoTag)
       
   112     THROUGH_NODEACTIVITY_ENTRY(KNoTag, CSelectNextLayerActivity::TSendSelectComplete, CSelectNextLayerActivity::TSelectedProviderIsNullOrJoinServiceProviderBackward)
       
   113 	//Break the selection main loop if no more choices, otherwise go back again
       
   114 	THROUGH_NODEACTIVITY_ENTRY(MCprStates::KSelectedProviderIsNull, CSelectNextLayerActivity::TLeaveTierManager, CSelectNextLayerActivity::TNoTagOrSelectedProviderBackward)
       
   115 	//Finish the activity
       
   116 	LAST_NODEACTIVITY_ENTRY(KNoTag, MCprStates::TSendFinalSelectComplete)
       
   117 NODEACTIVITY_END()
       
   118 }
       
   119 
       
   120 namespace MCprSimpleSelectActivitySuper
       
   121 {
       
   122 DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivitySelect, MCprSimpleSelect, TCFSelector::TSelect, CSelectNextLayerActivity::NewL)
       
   123 	//Reply from TAwaitingSelectNextLayer if no choices, otherwise accept
       
   124 	FIRST_NODEACTIVITY_ENTRY(MCprStates::TAwaitingSelectNextLayerSuper, MeshMachine::TNoTag)
       
   125 	THROUGH_NODEACTIVITY_ENTRY(KNoTag, CSelectNextLayerActivity::TProcessPrioritisedSelectionPolicySuper, MCprStates::TSelectedProvider)
       
   126 	//Start the selection main loop
       
   127 	NODEACTIVITY_ENTRY(MCprStates::KSelectedProvider, CSelectNextLayerActivity::TFindOrCreateTierManagerSuper, MCprStates::TAwaitingTierManagerCreated, MeshMachine::TNoTag)
       
   128 	NODEACTIVITY_ENTRY(KNoTag, CSelectNextLayerActivity::TJoinTierManager, CoreStates::TAwaitingJoinComplete, MeshMachine::TNoTag)
       
   129 	//Select next provider and enter the selection internal loop if provider received. Break if SelectComplete(NULL).
       
   130 	NODEACTIVITY_ENTRY(KNoTag, CSelectNextLayerActivity::TSelectNextLayerSuper, MCprStates::TAwaitingSelectComplete, CSelectNextLayerActivity::TNoTagOrSelectedProviderIsNull)
       
   131     NODEACTIVITY_ENTRY(KNoTag, CSelectNextLayerActivity::TAddProviderInfo, MCprStates::TAwaitingSelectComplete, CSelectNextLayerActivity::TNoTagBackwardsOrJoinServiceProvider)
       
   132     //Break the selection internal loop if SelectComplete(NULL), otherwise stay in this tripple
       
   133     NODEACTIVITY_ENTRY(MCprStates::KJoinServiceProvider, CSelectNextLayerActivity::TJoinServiceProvider, CoreStates::TAwaitingJoinComplete, MeshMachine::TNoTag)
       
   134     THROUGH_NODEACTIVITY_ENTRY(KNoTag, CSelectNextLayerActivity::TSendSelectComplete, CSelectNextLayerActivity::TSelectedProviderIsNullOrJoinServiceProviderBackward)
       
   135 	//Break the selection main loop if no more choices, otherwise go back again
       
   136 	THROUGH_NODEACTIVITY_ENTRY(MCprStates::KSelectedProviderIsNull, CSelectNextLayerActivity::TLeaveTierManager, CSelectNextLayerActivity::TNoTagOrSelectedProviderBackwardSuper)
       
   137 	//Finish the activity
       
   138 	LAST_NODEACTIVITY_ENTRY(KNoTag, MCprStates::TSendFinalSelectComplete)
       
   139 NODEACTIVITY_END()
       
   140 }
       
   141 
       
   142 namespace MCprNoBearerActivity
       
   143 {
       
   144 DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityNoBearer, MCprNoBearer, TCFControlProvider::TNoBearer, PRActivities::CNoBearer::NewL)
       
   145 	FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingNoBearer, CNoBearer::TNoTagOrBearerPresentBlockedByNoBearer)
       
   146 	NODEACTIVITY_ENTRY(KNoTag, MCprStates::TSelectNextLayer, MCprStates::TAwaitingSelectNextLayerCompleted, CoreNetStates::TNoTagOrBearerPresent)
       
   147 
       
   148 	//Special for the Meta Plane (don't just copy & paste)
       
   149 //	NODEACTIVITY_ENTRY(CoreNetStates::KBearerPresent, CoreNetStates::TStartServiceProvider, CoreNetStates::TAwaitingStarted, TTag<CoreNetStates::KBearerPresent>)
       
   150 	NODEACTIVITY_ENTRY(CoreNetStates::KBearerPresent, CoreNetStates::TRequestCommsBinderRetry, CoreNetStates::TAwaitingBinderResponse, TTag<CoreNetStates::KBearerPresent>)
       
   151 	NODEACTIVITY_ENTRY(CoreNetStates::KBearerPresent, CoreNetStates::TSendBindTo, CoreNetStates::TAwaitingBindToComplete, TTag<CoreNetStates::KBearerPresent>)
       
   152 	THROUGH_NODEACTIVITY_ENTRY(CoreNetStates::KBearerPresent, CoreActivities::ABindingActivity::TSendBindToComplete, MeshMachine::TNoTag)
       
   153 
       
   154 	LAST_NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendBearer)
       
   155 NODEACTIVITY_END()
       
   156 }
       
   157 
       
   158 namespace MCprReConnectActivity
       
   159 {
       
   160 //MCprConnectionStartRecovery activity belongs to a group of Error Recovery Activities.
       
   161 //Error Recovery Activities need to handle their own errors (generated as well as returned).
       
   162 DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityReConnect, MCprReConnect, TCFMcpr::TReConnect, CReConnectActivity::NewL)
       
   163 	FIRST_NODEACTIVITY_ENTRY(MCprStates::TAwaitingReConnectRequest, MeshMachine::TNoTag)
       
   164 	THROUGH_NODEACTIVITY_ENTRY(KNoTag, CReConnectActivity::TProcessReConnectRequest, MeshMachine::TNoTag)
       
   165 
       
   166 	//Build lower layer
       
   167 	NODEACTIVITY_ENTRY(KNoTag, CReConnectActivity::TBuildLowerLayer, CoreNetStates::TAwaitingBindToComplete, MeshMachine::TNoTag)
       
   168 
       
   169 	//Respond
       
   170 	LAST_NODEACTIVITY_ENTRY(KNoTag, CReConnectActivity::TSendReConnectResponse)
       
   171 NODEACTIVITY_END()
       
   172 }
       
   173 
       
   174 namespace MCprErrorRecoveryDefaultActivity
       
   175 {
       
   176 //This is a default error recovery activity.
       
   177 //It always replies with TErrorRecoveryResponse(EPropagate).
       
   178 DECLARE_DEFINE_NODEACTIVITY(ECFActivityErrorRecovery, DefaultErrorRecovery, TEErrorRecovery::TErrorRecoveryRequest)
       
   179 	NODEACTIVITY_ENTRY(KNoTag, MCprStates::TSendPropagateRecoveryResponse, MCprStates::TAwaitingErrorRecoveryRequest, MeshMachine::TNoTag)
       
   180 NODEACTIVITY_END()
       
   181 }
       
   182 
       
   183 namespace MCprBinderRequestActivity
       
   184 {
       
   185 // MCPRs can only have one data client, hence the use of CoreNetStates::TNoTagOrDataClientPresent.
       
   186 DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityBinderRequest, MCprBinderRequest, TCFServiceProvider::TCommsBinderRequest, CCommsBinderActivity::NewL)
       
   187 	FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingBinderRequest, CCommsBinderActivity::TNoTagOrUseExistingBlockedByBinderRequest)
       
   188 	NODEACTIVITY_ENTRY(KNoTag, PRStates::TCreateDataClient, CoreNetStates::TAwaitingDataClientJoin, MeshMachine::TNoTag)
       
   189 
       
   190 	// Below this point we need to modify the error handling approach. If we're getting a TError on TBinderResponse,
       
   191 	// this means the client requesting the binder couldn't bind to it. As far as the client is concerned, this
       
   192 	// activity is finished (it has flagged an error). The standard error handling will result in erroring
       
   193 	// the originator. In this case we shouoldn't error the originator, instead, wrap up quietly.
       
   194 	THROUGH_NODEACTIVITY_ENTRY(KNoTag, CCommsBinderActivity::TProcessDataClientCreation, TTag<CoreStates::KUseExisting>)
       
   195 
       
   196 	NODEACTIVITY_ENTRY(CoreStates::KUseExisting, CCommsBinderActivity::TSendBinderResponse, CCommsBinderActivity::TAwaitingBindToComplete, MeshMachine::TNoTagOrErrorTag)
       
   197     LAST_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing)
       
   198 	LAST_NODEACTIVITY_ENTRY(KErrorTag, MeshMachine::TClearError)
       
   199 NODEACTIVITY_END()
       
   200 }
       
   201 
       
   202 namespace MCprReportProviderStatusActivity
       
   203 {
       
   204 DECLARE_DEFINE_NODEACTIVITY(ECFActivityReportProviderStatus, MCprReportProviderStatus, TCFMcpr::TProviderStatusChangeRegistration)
       
   205 	// for other requests "joining in"
       
   206 	NODEACTIVITY_ENTRY(KNoTag, MCprStates::TProcessProviderStatusChangeRegistration, MeshMachine::TAwaitingAny, MeshMachine::TNoTag)
       
   207 	NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing, CoreNetStates::TAwaitingProviderStatusChangeOrDataClientStatusChange, MCprStates::TDataClientStatusChangeOrNoTag)
       
   208 	// Process the provider status change notification sent from provider on left
       
   209     THROUGH_NODEACTIVITY_ENTRY(MCprStates::KDataClientStatusChange, PRStates::THandleDataClientStatusChangeAndDestroyOrphans, MeshMachine::TNoTag)
       
   210     NODEACTIVITY_ENTRY(KNoTag, MCprStates::TPostStatusChangeToOriginators, CoreNetStates::TAwaitingProviderStatusChangeOrDataClientStatusChange, MCprStates::TDataClientStatusChangeBackwardsOrNoTagBackwards)
       
   211 	// Never get past this point
       
   212 NODEACTIVITY_END()
       
   213 }
       
   214 
       
   215 namespace MCprAvailabilityNotificationActivity
       
   216 {
       
   217 // Reference availability notification activity.
       
   218 // Forwards availability registrations down to lower MCPRs
       
   219 // Then combines their responses into a single TAvailability object and sends the notification upwards if anything has changed
       
   220 DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityAvailabilityNotification, MCprAvailability, TCFAvailabilityProvider::TAvailabilityNotificationRegistration, CAvailabilityActivity::NewL)
       
   221 	FIRST_NODEACTIVITY_ENTRY(MeshMachine::TAwaitingMessageState<TCFAvailabilityProvider::TAvailabilityNotificationRegistration>, MeshMachine::TNoTag)
       
   222 
       
   223 	//Select Service Providers (availability sources - if any)
       
   224 	NODEACTIVITY_ENTRY(KNoTag, MCprStates::TSelectNextLayer, MCprStates::TAwaitingSelectNextLayerCompleted, MeshMachine::TNoTagOrErrorTag)
       
   225 
       
   226 	//Register for notifications with all Service Providers (if any)
       
   227 	NODEACTIVITY_ENTRY(KNoTag, CAvailabilityActivity::TRegisterForNotifications, MCprStates::TAwaitingAvailabilityNotificationOrError, TErrorTagOr<TTag<MCprStates::KProcessAvailability> >)
       
   228 
       
   229 	//Process the availability notification and loop (if success, or finish on failure)
       
   230 	NODEACTIVITY_ENTRY(MCprStates::KProcessAvailability, CAvailabilityActivity::TProcessNotification, MCprStates::TAwaitingAvailabilityNotificationOrError, TErrorTagOr<TTag<MCprStates::KProcessAvailability|EBackward> >)
       
   231 
       
   232 	LAST_NODEACTIVITY_ENTRY(KErrorTag, MeshMachine::TRaiseAndClearActivityError)
       
   233 NODEACTIVITY_END()
       
   234 }
       
   235 
       
   236 // Also if this Message is not expected to be received from the MCpr, we
       
   237 //	manage it.
       
   238 namespace MCprDataClientGoneDownActivity
       
   239 {
       
   240 DECLARE_DEFINE_NODEACTIVITY(ECFActivityDataClientGoneDown, MCprDataClientGoneDown, TCFControlProvider::TDataClientGoneDown)
       
   241 	// The only thing we do is to clear(unset) the "Flags" of
       
   242 	//	the relative DataClient from "EStart": this is done
       
   243 	//	in "TAwaitingDataClientGoneDown".
       
   244 	FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingDataClientGoneDown, MeshMachine::TNoTag)
       
   245 	LAST_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing)
       
   246 NODEACTIVITY_END()
       
   247 }
       
   248 
       
   249 namespace MCprStartActivity
       
   250 {
       
   251 DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityStart, MCprStart, TCFServiceProvider::TStart, PRActivities::CStartActivity::NewL)
       
   252     FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingStart, CoreNetStates::TNoTagOrBearerPresentBlockedByStop)
       
   253 	NODEACTIVITY_ENTRY(KNoTag, MCprStates::TSelectNextLayer, MCprStates::TAwaitingSelectNextLayerCompleted, CoreNetStates::TNoTagOrBearerPresent)
       
   254 	NODEACTIVITY_ENTRY(CoreNetStates::KBearerPresent, CoreNetStates::TBindSelfToPresentBearer, CoreNetStates::TAwaitingBindToComplete, TTag<CoreNetStates::KBearerPresent>)
       
   255 
       
   256 	//Start the service provider, use the default cancellation.
       
   257 	//Forward TCancel to the service provider, wait for TStarted or TError (via the Error Activity)
       
   258 	//When TStarted arrives after TCancel the activity will move to the nearest KErrorTag
       
   259 	NODEACTIVITY_ENTRY(CoreNetStates::KBearerPresent, CoreNetStates::TStartServiceProviderRetry, CoreNetStates::TAwaitingStarted, MeshMachine::TNoTagOrErrorTag)
       
   260 	LAST_NODEACTIVITY_ENTRY(KErrorTag, MeshMachine::TDoNothing)
       
   261 	//Start data clients, use the default cancellation.
       
   262 	//Forward TCancel to the self, wait for TCFDataClient::TStarted or TError (via the Error Activity)
       
   263 	//When TCFDataClient::TStarted arrives after TCancel the activity will move to the nearest KErrorTag
       
   264 	NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TStartSelf, CoreNetStates::TAwaitingDataClientStarted, MeshMachine::TNoTagOrErrorTag)
       
   265 	NODEACTIVITY_ENTRY(KErrorTag, CoreNetStates::TStopSelf, CoreNetStates::TAwaitingDataClientStopped, MeshMachine::TErrorTag)
       
   266 	LAST_NODEACTIVITY_ENTRY(KErrorTag, MeshMachine::TDoNothing)
       
   267 	LAST_NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendStarted)
       
   268 NODEACTIVITY_END()
       
   269 }
       
   270 
       
   271 namespace MCprStopActivity
       
   272 {
       
   273 DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityStop, MCprStop, TCFServiceProvider::TStop, MeshMachine::CNodeRetryActivity::NewL)
       
   274 	FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingStop, CoreNetStates::TActiveOrNoTagBlockedByBindTo)
       
   275 	THROUGH_NODEACTIVITY_ENTRY(KActiveTag, CoreNetStates::TCancelDataClientStart, MeshMachine::TNoTag)
       
   276 	NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TStopSelf, CoreNetStates::TAwaitingDataClientStopped, CoreNetStates::TNoTagOrNoBearer)
       
   277 	NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendStop, CoreNetStates::TAwaitingStopped, TTag<CoreNetStates::KNoBearer>)
       
   278 	LAST_NODEACTIVITY_ENTRY(CoreNetStates::KNoBearer, PRStates::TSendStoppedAndGoneDown)
       
   279 NODEACTIVITY_END()
       
   280 }
       
   281 
       
   282 namespace MCprActivities
       
   283 {
       
   284 //This activity map should be used if the MCPR only supports the
       
   285 //selection message TSelectNextLayerConnPrefList. Nodes using this activity
       
   286 //map will not support legacy selection
       
   287 DEFINE_EXPORT_ACTIVITY_MAP(coreMCprActivitiesSuper)
       
   288 	ACTIVITY_MAP_ENTRY(MCprDestroyActivity, MCprDestroy)
       
   289 	ACTIVITY_MAP_ENTRY(MCprSimpleSelectActivitySuper, MCprSimpleSelect)
       
   290 	ACTIVITY_MAP_ENTRY(MCprNoBearerActivity, MCprNoBearer)
       
   291 	ACTIVITY_MAP_ENTRY(MCprReConnectActivity, MCprReConnect)
       
   292 	ACTIVITY_MAP_ENTRY(MCprAvailabilityNotificationActivity, MCprAvailability)
       
   293 	ACTIVITY_MAP_ENTRY(MCprBinderRequestActivity, MCprBinderRequest)
       
   294 	ACTIVITY_MAP_ENTRY(MCprReportProviderStatusActivity, MCprReportProviderStatus)
       
   295 	ACTIVITY_MAP_ENTRY(MCprDataClientJoinActivity, MCprDataClientJoin)
       
   296 	ACTIVITY_MAP_ENTRY(MCprControlClientJoinActivity, MCprControlClientJoin)
       
   297 	ACTIVITY_MAP_ENTRY(MCprErrorRecoveryDefaultActivity, DefaultErrorRecovery)
       
   298 	ACTIVITY_MAP_ENTRY(MCprDataClientGoneDownActivity, MCprDataClientGoneDown)
       
   299 	ACTIVITY_MAP_ENTRY(MCprStopActivity, MCprStop)
       
   300 	ACTIVITY_MAP_ENTRY(MCprStartActivity, MCprStart)
       
   301 ACTIVITY_MAP_END_BASE(PRActivities, coreActivitiesMCpr)
       
   302 
       
   303 //This activiy map supports legacy selection and the additional activity
       
   304 //is that support. It should be used where tier managers need to support
       
   305 //selection message TSelectNextLayer
       
   306 DEFINE_EXPORT_ACTIVITY_MAP(coreMCprActivities)
       
   307 	ACTIVITY_MAP_ENTRY(MCprSimpleSelectActivity, MCprSimpleSelect)
       
   308 ACTIVITY_MAP_END_BASE(MCprActivities, coreMCprActivitiesSuper)
       
   309 }
       
   310 
       
   311 //
       
   312 //CSelectNextLayerActivity
       
   313 EXPORT_C MeshMachine::CNodeActivityBase* CSelectNextLayerActivity::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode)
       
   314 	{
       
   315 	CSelectNextLayerActivity* self = new (ELeave) CSelectNextLayerActivity(aActivitySig, aNode);
       
   316 	CleanupStack::PushL(self);
       
   317 	self->ConstructL();
       
   318 	CleanupStack::Pop(self);
       
   319 	return self;
       
   320 	}
       
   321 
       
   322 EXPORT_C void CSelectNextLayerActivity::ConstructL()
       
   323 	{
       
   324 	iDbs = CommsDat::CMDBSession::NewL(KCDVersion1_2);
       
   325 
       
   326 	}
       
   327 
       
   328 EXPORT_C CSelectNextLayerActivity::~CSelectNextLayerActivity()
       
   329 	{
       
   330 	if (!iTierManager.IsNull())
       
   331 		{
       
   332 		// Only leave if the iTierManager is still a client - only happens in some
       
   333 		// error cases for example if the Join fails the generic TError handling
       
   334 		// does not call iTierManager.SetNull(), also if AddClientL() leaves.
       
   335 		// TierManager is always a special case because the relationship with
       
   336 		// MCPR is always temporary.
       
   337 		RNodeInterface* client = iNode.FindClient(iTierManager);
       
   338 		if (client)
       
   339 			{
       
   340 			RClientInterface::OpenPostMessageClose(iNode.Id(), iTierManager, TEChild::TLeft().CRef());
       
   341 			iNode.RemoveClient(iTierManager);
       
   342 			}
       
   343 		iTierManager.SetNull();
       
   344 		}
       
   345 	delete iDbs;
       
   346 	iSelectCompleteMessages.Close();
       
   347 	}
       
   348 
       
   349 EXPORT_C TConnIdList& CSelectNextLayerActivity::SelectionChoices()
       
   350 	{
       
   351 	return iSelectionChoices;
       
   352 	}
       
   353 
       
   354 EXPORT_C ESock::RConnPrefList& CSelectNextLayerActivity::SelectionConnPrefList()
       
   355 	{
       
   356 	return iSelectionConnPrefList;
       
   357 	}
       
   358 
       
   359 EXPORT_DEFINE_SMELEMENT(CSelectNextLayerActivity::TNoTagOrSelectedProviderIsNull, NetStateMachine::MStateFork, CSelectNextLayerActivity::TContext)
       
   360 TInt CSelectNextLayerActivity::TNoTagOrSelectedProviderIsNull::TransitionTag()
       
   361 	{
       
   362 	//We proceede forward through a transision that will process our concrete message received (NULL or not NULL).
       
   363 	TInt tag = MeshMachine::KNoTag | NetStateMachine::EForward;
       
   364 	if (message_cast<TCFSelector::TSelectComplete>(iContext.iMessage).iNodeId.IsNull())
       
   365 		{
       
   366 		tag = MCprStates::KSelectedProviderIsNull | NetStateMachine::EForward;
       
   367 		}
       
   368 	return tag;
       
   369 	}
       
   370 
       
   371 EXPORT_DEFINE_SMELEMENT(CSelectNextLayerActivity::TNoTagBackwardsOrJoinServiceProvider, NetStateMachine::MStateFork, CSelectNextLayerActivity::TContext)
       
   372 TInt CSelectNextLayerActivity::TNoTagBackwardsOrJoinServiceProvider::TransitionTag()
       
   373 	{
       
   374 	TInt tag = MeshMachine::KNoTag | NetStateMachine::EBackward;
       
   375 	if (message_cast<TCFSelector::TSelectComplete>(iContext.iMessage).iNodeId.IsNull())
       
   376 		{
       
   377 		//This is the final select complete that we have received from the selector.
       
   378 		tag = MCprStates::KJoinServiceProvider | NetStateMachine::EForward;
       
   379 		}
       
   380 	return tag;
       
   381 	}
       
   382 
       
   383 EXPORT_DEFINE_SMELEMENT(CSelectNextLayerActivity::TSelectedProviderIsNullOrJoinServiceProviderBackward, NetStateMachine::MStateFork, CSelectNextLayerActivity::TContext)
       
   384 TInt CSelectNextLayerActivity::TSelectedProviderIsNullOrJoinServiceProviderBackward::TransitionTag()
       
   385 	{
       
   386 	__ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity));
       
   387 	CSelectNextLayerActivity& ac = static_cast<CSelectNextLayerActivity&>(*iContext.iNodeActivity);
       
   388 	if (ac.iSelectCompleteMessages.Count() > 0)
       
   389 		{
       
   390 		return MCprStates::KJoinServiceProvider | NetStateMachine::EBackward;
       
   391 		}
       
   392 
       
   393 	return MCprStates::KSelectedProviderIsNull | NetStateMachine::EForward;
       
   394 	}
       
   395 
       
   396 EXPORT_DEFINE_SMELEMENT(CSelectNextLayerActivity::TNoTagOrSelectedProviderBackward, NetStateMachine::MStateFork, CSelectNextLayerActivity::TContext)
       
   397 TInt CSelectNextLayerActivity::TNoTagOrSelectedProviderBackward::TransitionTag()
       
   398 	{
       
   399 	__ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity));
       
   400 	CSelectNextLayerActivity& ac = static_cast<CSelectNextLayerActivity&>(*iContext.iNodeActivity);
       
   401 	if (ac.SelectionChoices().Count() > (ac.iCurrentIndex + 1))
       
   402 		{
       
   403 		return MCprStates::KSelectedProvider | NetStateMachine::EBackward;
       
   404 		}
       
   405 
       
   406 	return MeshMachine::KNoTag | NetStateMachine::EForward;
       
   407 	}
       
   408 
       
   409 EXPORT_DEFINE_SMELEMENT(CSelectNextLayerActivity::TProcessSimpleSelectionPolicy, NetStateMachine::MStateTransition, CSelectNextLayerActivity::TContext)
       
   410 void CSelectNextLayerActivity::TProcessSimpleSelectionPolicy::DoL()
       
   411 	{
       
   412 	__ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity));
       
   413 	CSelectNextLayerActivity& ac = static_cast<CSelectNextLayerActivity&>(*iContext.iNodeActivity);
       
   414 	__ASSERT_DEBUG(ac.SelectionChoices().Count() == 0, User::Panic(KSpecAssert_ESockCoreProvcprac, 1)); //It should be empty
       
   415 
       
   416 	//We are going to process our own selection policy to determine choices
       
   417 	//for selection of the next layer.
       
   418 
       
   419 	//This simple transition interprets the selection policy id
       
   420 	//directly as a next layer access point id.
       
   421 
       
   422 	//This transition is an entry point to the main selection loop which
       
   423 	//will process all the inforamtion gathered in this transition.
       
   424 	//We initialise the current index to start from the beginning of the list
       
   425 	//(next step preincrements).
       
   426 	ac.iCurrentIndex = -1;
       
   427 
       
   428 	if (iContext.Node().AccessPointConfig().FindExtension(TOverridenSelectionPrefsExt::TypeId()))
       
   429 		{
       
   430 		//Our selection has been overriden by special preferences (so called pass-through
       
   431 		//preference) given to us by our control client.
       
   432 		__CFLOG_VAR((KCoreMCprStatesTag, KCoreMCprStatesSubTag, _L8("TProcessSimpleSelectionPolicy::DoL() - Selection policy overriden!.")));
       
   433 		return;
       
   434 		}
       
   435 
       
   436 	//Now we can interpret the selection policy and store the results for further
       
   437 	//processing
       
   438 	const TLayerSelectionInfo* selectInfo = static_cast<const TLayerSelectionInfo*>(iContext.Node().AccessPointConfig().FindExtension(
       
   439 			STypeId::CreateSTypeId(TLayerSelectionInfo::EUid, TLayerSelectionInfo::ETypeId)));
       
   440 	__ASSERT_ALWAYS(selectInfo, CoreMCprPanic(KPanicUnexpectedExecutionPath));
       
   441 
       
   442 	TUint selectionPolicyId = selectInfo->CustomSelectionPolicy();
       
   443 
       
   444 	//Running this transition, we can't be at the bottom of the stack!
       
   445 	__ASSERT_DEBUG(selectionPolicyId, User::Panic(KSpecAssert_ESockCoreProvcprac, 2));
       
   446 
       
   447 	//And, of course, for nodes using this transition, it is only one single
       
   448 	//access point below.
       
   449 	ac.SelectionChoices().Append(selectionPolicyId);
       
   450 	}
       
   451 
       
   452 EXPORT_DEFINE_SMELEMENT(CSelectNextLayerActivity::TProcessPrioritisedSelectionPolicy, NetStateMachine::MStateTransition, CSelectNextLayerActivity::TContext)
       
   453 void CSelectNextLayerActivity::TProcessPrioritisedSelectionPolicy::DoL()
       
   454 	{
       
   455 	__ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity));
       
   456 	CSelectNextLayerActivity& ac = static_cast<CSelectNextLayerActivity&>(*iContext.iNodeActivity);
       
   457 	__ASSERT_DEBUG(ac.SelectionChoices().Count() == 0, User::Panic(KSpecAssert_ESockCoreProvcprac, 3)); //It should be empty
       
   458 
       
   459 	//We are going to process our own selection policy to determine choices
       
   460 	//for selection of the next layer.
       
   461 
       
   462 	//This simple transition interprets the selection policy id
       
   463 	//directly as a next layer access point id.
       
   464 
       
   465 	//This transition is an entry point to the main selection loop which
       
   466 	//will process all the inforamtion gathered in this transition.
       
   467 	//We initialise the current index to start from the beginning of the list
       
   468 	//(next step preincrements).
       
   469 	ac.iCurrentIndex = -1;
       
   470 
       
   471 	if (iContext.Node().AccessPointConfig().FindExtension(TOverridenSelectionPrefsExt::TypeId()))
       
   472 		{
       
   473 		//Our selection has been overriden by special preferences (so called pass-through
       
   474 		//preference) given to us by our control client.
       
   475 		__CFLOG_VAR((KCoreMCprStatesTag, KCoreMCprStatesSubTag, _L8("TProcessPrioritisedSelectionPolicy::DoL() - Selection policy overriden!.")));
       
   476 		return;
       
   477 		}
       
   478 
       
   479 	//Now we can interpret the selection policy and store the results for further
       
   480 	//processing
       
   481 	const TLayerSelectionInfo* selectInfo = static_cast<const TLayerSelectionInfo*>(iContext.Node().AccessPointConfig().FindExtension(
       
   482 			STypeId::CreateSTypeId(TLayerSelectionInfo::EUid, TLayerSelectionInfo::ETypeId)));
       
   483 	__ASSERT_ALWAYS(selectInfo, CoreMCprPanic(KPanicUnexpectedExecutionPath));
       
   484 
       
   485 	TUint selectionPolicyId = selectInfo->SelectionPolicy();
       
   486 
       
   487 	//Running this transition, we can't be at the bottom of the stack!
       
   488 	__ASSERT_DEBUG(selectionPolicyId, User::Panic(KSpecAssert_ESockCoreProvcprac, 4));
       
   489 
       
   490 	//And, of course, for nodes using this transition, all of the choices come
       
   491 	//from the simple prioritised selection policy
       
   492 	TierManagerUtils::FillListL(ac.SelectionChoices(),selectionPolicyId,ac.Dbs());
       
   493 	}
       
   494 
       
   495 EXPORT_DEFINE_SMELEMENT(CSelectNextLayerActivity::TFindOrCreateTierManager, NetStateMachine::MStateTransition, CSelectNextLayerActivity::TContext)
       
   496 void CSelectNextLayerActivity::TFindOrCreateTierManager::DoL()
       
   497 	{
       
   498 	__ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity));
       
   499 	CSelectNextLayerActivity& ac = static_cast<CSelectNextLayerActivity&>(*iContext.iNodeActivity);
       
   500 
       
   501 	//Preincrement the current index
       
   502 	++ac.iCurrentIndex;
       
   503 
       
   504 	//If we do not have our choices now, this may only mean that our selection
       
   505 	//policy has been overriden by our control client.
       
   506 	TUid tierId;
       
   507 	if (ac.SelectionChoices().Count())
       
   508 		{
       
   509 		__ASSERT_DEBUG(ac.SelectionChoices().Count() > ac.iCurrentIndex, User::Panic(KSpecAssert_ESockCoreProvcprac, 5)); //Specified choice must be present
       
   510 		__ASSERT_DEBUG(iContext.Node().AccessPointConfig().FindExtension(TOverridenSelectionPrefsExt::TypeId()) == NULL, User::Panic(KSpecAssert_ESockCoreProvcprac, 6));
       
   511 		tierId = TierManagerUtils::ReadTierIdL(ac.SelectionChoices().Get(ac.iCurrentIndex), ac.Dbs()) ;
       
   512 		}
       
   513 	else
       
   514 		{
       
   515 		//Our policy has been overriden
       
   516 		const TOverridenSelectionPrefsExt& override = static_cast<const TOverridenSelectionPrefsExt&>(iContext.Node().AccessPointConfig().FindExtensionL(TOverridenSelectionPrefsExt::TypeId()));
       
   517 		tierId = override.iTierId;
       
   518 		}
       
   519 
       
   520 	//The tier id must be set now!
       
   521 	__ASSERT_DEBUG(tierId.iUid!=0, User::Panic(KSpecAssert_ESockCoreProvcprac, 7));
       
   522 	User::LeaveIfError(tierId.iUid!=0? KErrNone : KErrCorrupt); //Check your configuration!
       
   523 	TAlwaysFindFactoryQuery query;
       
   524 	iContext.iNodeActivity->PostRequestTo(SockManGlobals::Get()->GetPlaneFC(TCFPlayerRole(TCFPlayerRole::ETierMgrPlane)), TCFFactory::TFindOrCreatePeer(TCFPlayerRole::ETierMgrPlane, tierId, &query).CRef(), EFalse);
       
   525 	}
       
   526 
       
   527 //This is a default implementation of the TSelectNextLayer transition,
       
   528 //Other mcprs, especially those with custom selection policies may want
       
   529 //to use their own logic to populate the selection preferences for the next layer.
       
   530 EXPORT_DEFINE_SMELEMENT(CSelectNextLayerActivity::TSelectNextLayer, NetStateMachine::MStateTransition, CSelectNextLayerActivity::TContext)
       
   531 void CSelectNextLayerActivity::TSelectNextLayer::DoL()
       
   532 	{
       
   533 	__ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity));
       
   534 	CSelectNextLayerActivity& ac = static_cast<CSelectNextLayerActivity&>(*iContext.iNodeActivity);
       
   535 
       
   536 	if (ac.SelectionChoices().Count())
       
   537 		{
       
   538 		//We use choices derived from our own selection policy
       
   539 		__ASSERT_DEBUG(ac.SelectionChoices().Count() > ac.iCurrentIndex, User::Panic(KSpecAssert_ESockCoreProvcprac, 8)); //Specified choice must be present
       
   540 		__ASSERT_DEBUG(iContext.Node().AccessPointConfig().FindExtension(TOverridenSelectionPrefsExt::TypeId())==NULL, User::Panic(KSpecAssert_ESockCoreProvcprac, 9));
       
   541 
       
   542 		TConnIdList list;
       
   543 		list.Append(ac.SelectionChoices().Get(ac.iCurrentIndex));
       
   544 
       
   545 		TSelectionPrefs newPrefs;
       
   546 		newPrefs.SetPrefs(list);
       
   547 
       
   548 		iContext.iNodeActivity->PostRequestTo(ac.iTierManager, TCFSelector::TSimpleSelect(newPrefs).CRef());
       
   549 		}
       
   550 	else
       
   551 		{
       
   552 		//We have been given preferences for the next layer and we use them here
       
   553 		const TOverridenSelectionPrefsExt& override = static_cast<const TOverridenSelectionPrefsExt&>(iContext.Node().AccessPointConfig().FindExtensionL(TOverridenSelectionPrefsExt::TypeId()));
       
   554 
       
   555 		iContext.iNodeActivity->PostRequestTo(ac.iTierManager, TCFSelector::TSimpleSelect(override.iPrefs).CRef());
       
   556 		}
       
   557 	}
       
   558 EXPORT_DEFINE_SMELEMENT(CSelectNextLayerActivity::TProcessSimpleSelectionPolicySuper, NetStateMachine::MStateTransition, CSelectNextLayerActivity::TContext)
       
   559 void CSelectNextLayerActivity::TProcessSimpleSelectionPolicySuper::DoL()
       
   560 	{
       
   561 	__ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity));
       
   562 	CSelectNextLayerActivity& ac = static_cast<CSelectNextLayerActivity&>(*iContext.iNodeActivity);
       
   563 
       
   564 	//We are going to process our own selection policy to determine choices
       
   565 	//for selection of the next layer.
       
   566 
       
   567 	//This simple transition interprets the selection policy id
       
   568 	//directly as a next layer access point id.
       
   569 
       
   570 	//This transition is an entry point to the main selection loop which
       
   571 	//will process all the inforamtion gathered in this transition.
       
   572 
       
   573 	//Now we can interpret the selection policy and store the results for further
       
   574 	//processing
       
   575 	const TLayerSelectionInfo* selectInfo = static_cast<const TLayerSelectionInfo*>(iContext.Node().AccessPointConfig().FindExtension(
       
   576 			STypeId::CreateSTypeId(TLayerSelectionInfo::EUid, TLayerSelectionInfo::ETypeId)));
       
   577 	__ASSERT_ALWAYS(selectInfo, CoreMCprPanic(KPanicUnexpectedExecutionPath));
       
   578 
       
   579 	TUint selectionPolicyId = selectInfo->CustomSelectionPolicy();
       
   580 
       
   581 	//Running this transition, we can't be at the bottom of the stack!
       
   582 	__ASSERT_DEBUG(selectionPolicyId, User::Panic(KSpecAssert_ESockCoreProvcprac, 10));
       
   583 
       
   584 	//And, of course, for nodes using this transition, it is only one single
       
   585 	//access point below.
       
   586 
       
   587 	//This constructs a TConnAPPref to represent the access point to be created
       
   588  	ac.SelectionConnPrefList() = message_cast<TCFSelector::TSelect>(iContext.iMessage).iConnPrefList;
       
   589 
       
   590 	if (selectionPolicyId != (TUint)CommsDat::CCDAccessPointRecord::KNoPolicy)
       
   591 		{
       
   592 		TConnAPPref* nextAP = TConnAPPref::NewL(selectionPolicyId);
       
   593 		CleanupStack::PushL(nextAP);
       
   594 		ac.SelectionConnPrefList().AppendL(nextAP);
       
   595 		CleanupStack::Pop();
       
   596 		}
       
   597 
       
   598 	//The current index is set to the length of the list, this is decremented
       
   599 	//in the next step so the correct tier manager is created (the one
       
   600 	//relating to this access point
       
   601 	}
       
   602 
       
   603 EXPORT_DEFINE_SMELEMENT(CSelectNextLayerActivity::TProcessPrioritisedSelectionPolicySuper, NetStateMachine::MStateTransition, CSelectNextLayerActivity::TContext)
       
   604 void CSelectNextLayerActivity::TProcessPrioritisedSelectionPolicySuper::DoL()
       
   605 	{
       
   606 	__ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity));
       
   607 	CSelectNextLayerActivity& ac = static_cast<CSelectNextLayerActivity&>(*iContext.iNodeActivity);
       
   608 
       
   609 	ac.SelectionConnPrefList() = message_cast<TCFSelector::TSelect>(iContext.iMessage).iConnPrefList;
       
   610 
       
   611 	//We are going to process our own selection policy to determine choices
       
   612 	//for selection of the next layer.
       
   613 
       
   614 	//This simple transition interprets the selection policy id
       
   615 	//directly as a next layer access point id.
       
   616 
       
   617 	//Now we can interpret the selection policy and store the results for further
       
   618 	//processing
       
   619 	const TLayerSelectionInfo* selectInfo = static_cast<const TLayerSelectionInfo*>(iContext.Node().AccessPointConfig().FindExtension(
       
   620 			STypeId::CreateSTypeId(TLayerSelectionInfo::EUid, TLayerSelectionInfo::ETypeId)));
       
   621 	__ASSERT_ALWAYS(selectInfo, CoreMCprPanic(KPanicUnexpectedExecutionPath));
       
   622 	TUint selectionPolicyId = selectInfo->SelectionPolicy();
       
   623 
       
   624 	//Running this transition, we can't be at the bottom of the stack!
       
   625 	__ASSERT_DEBUG(selectionPolicyId, User::Panic(KSpecAssert_ESockCoreProvcprac, 11));
       
   626 
       
   627 	//And, of course, for nodes using this transition, all of the choices come
       
   628 	//from the simple prioritised selection policy
       
   629 
       
   630 	TierManagerUtils::FillListL(ac.SelectionConnPrefList(),selectionPolicyId,ac.Dbs());
       
   631 	}
       
   632 
       
   633 EXPORT_DEFINE_SMELEMENT(CSelectNextLayerActivity::TFindOrCreateTierManagerSuper, NetStateMachine::MStateTransition, CSelectNextLayerActivity::TContext)
       
   634 void CSelectNextLayerActivity::TFindOrCreateTierManagerSuper::DoL()
       
   635 	{
       
   636 	__ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity));
       
   637 	CSelectNextLayerActivity& ac = static_cast<CSelectNextLayerActivity&>(*iContext.iNodeActivity);
       
   638 
       
   639 	//This takes the first TConnAPPref from the list and creates the tier manager it
       
   640 	//is associated with.
       
   641 	ESock::RConnPrefList::TIter<TConnAPPref> iterAP = ac.SelectionConnPrefList().getIter<TConnAPPref>();
       
   642 
       
   643 	__ASSERT_DEBUG(!iterAP.IsEnd(), User::Panic(KSpecAssert_ESockCoreProvcprac, 12));
       
   644 
       
   645 	TUid tierId = TierManagerUtils::ReadTierIdL(iterAP->GetAP(), ac.Dbs()) ;
       
   646 
       
   647 	//The tier id must be set now!
       
   648 	__ASSERT_DEBUG(tierId.iUid!=0, User::Panic(KSpecAssert_ESockCoreProvcprac, 13));
       
   649 	User::LeaveIfError(tierId.iUid!=0? KErrNone : KErrCorrupt); //Check your configuration!
       
   650 	TAlwaysFindFactoryQuery query;
       
   651 	iContext.iNodeActivity->PostRequestTo(SockManGlobals::Get()->GetPlaneFC(
       
   652 		TCFPlayerRole(TCFPlayerRole::ETierMgrPlane)),
       
   653 		TCFFactory::TFindOrCreatePeer(TCFPlayerRole::ETierMgrPlane, tierId, &query).CRef(), EFalse);
       
   654 	}
       
   655 
       
   656 
       
   657 EXPORT_DEFINE_SMELEMENT(CSelectNextLayerActivity::TSelectNextLayerSuper, NetStateMachine::MStateTransition, CSelectNextLayerActivity::TContext)
       
   658 void CSelectNextLayerActivity::TSelectNextLayerSuper::DoL()
       
   659 	{
       
   660 	__ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity));
       
   661 	CSelectNextLayerActivity& ac = static_cast<CSelectNextLayerActivity&>(*iContext.iNodeActivity);
       
   662 
       
   663 	// We should not have got here if the list is empty
       
   664 	__ASSERT_DEBUG(ac.SelectionConnPrefList().Count() != 0, User::Panic(KSpecAssert_ESockCoreProvcprac, 14));
       
   665 
       
   666 	// The handle to the complete list is passed to the tier manager
       
   667 	iContext.iNodeActivity->PostRequestTo(ac.iTierManager, TCFSelector::TSelect(ac.SelectionConnPrefList()).CRef());
       
   668 	}
       
   669 
       
   670 EXPORT_DEFINE_SMELEMENT(CSelectNextLayerActivity::TNoTagOrSelectedProviderBackwardSuper, NetStateMachine::MStateFork, CSelectNextLayerActivity::TContext)
       
   671 EXPORT_C TInt CSelectNextLayerActivity::TNoTagOrSelectedProviderBackwardSuper::TransitionTag()
       
   672 	{
       
   673 	__ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity));
       
   674 	CSelectNextLayerActivity& ac = static_cast<CSelectNextLayerActivity&>(*iContext.iNodeActivity);
       
   675 	ESock::RConnPrefList::TIter<TConnAPPref> iterAP = ac.SelectionConnPrefList().getIter<TConnAPPref>();
       
   676 
       
   677 	if (!iterAP.IsEnd())
       
   678 		{
       
   679 		return MCprStates::KSelectedProvider | NetStateMachine::EBackward;
       
   680 		}
       
   681 
       
   682 	return MeshMachine::KNoTag | NetStateMachine::EForward;
       
   683 	}
       
   684 
       
   685 EXPORT_DEFINE_SMELEMENT(CSelectNextLayerActivity::TAddProviderInfo, NetStateMachine::MStateTransition, CSelectNextLayerActivity::TContext)
       
   686 void CSelectNextLayerActivity::TAddProviderInfo::DoL()
       
   687 	{
       
   688 	__ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity));
       
   689 	CSelectNextLayerActivity& ac = static_cast<CSelectNextLayerActivity&>(*iContext.iNodeActivity);
       
   690 
       
   691 	TCFSelector::TSelectComplete& msg = message_cast<TCFSelector::TSelectComplete>(iContext.iMessage);
       
   692 	ac.iSelectCompleteMessages.Append(msg);
       
   693 	}
       
   694 
       
   695 EXPORT_DEFINE_SMELEMENT(CSelectNextLayerActivity::TJoinTierManager, NetStateMachine::MStateTransition, CSelectNextLayerActivity::TContext)
       
   696 void CSelectNextLayerActivity::TJoinTierManager::DoL()
       
   697 	{
       
   698 	__ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity));
       
   699 	CSelectNextLayerActivity& ac = static_cast<CSelectNextLayerActivity&>(*iContext.iNodeActivity);
       
   700 
       
   701 	ac.iTierManager = message_cast<TCFFactory::TPeerFoundOrCreated>(iContext.iMessage).iNodeId;
       
   702     __ASSERT_DEBUG(!ac.iTierManager.IsNull(), User::Panic(KSpecAssert_ESockCoreProvcprac, 15)); //Must always be valid.
       
   703 
       
   704 	//Ensure that the MCPR remains active by adding the lower TierManager as an
       
   705 	//auxiliary client.  This is only a temporary association with the TierManager
       
   706     //in the layer below and is only active for the duration of the select.
       
   707     //Note that this might leave resulting in ac.iTierManager non-Null in destructor
       
   708     iContext.Node().AddClientL(ac.iTierManager, TClientType(TCFClientType::EAux));
       
   709     ac.PostRequestTo(ac.iTierManager, TCFPeer::TJoinRequest(iContext.NodeId(), TClientType(TCFClientType::ECtrl)).CRef());
       
   710 	}
       
   711 
       
   712 EXPORT_DEFINE_SMELEMENT(CSelectNextLayerActivity::TJoinServiceProvider, NetStateMachine::MStateTransition, MCprStates::TContext)
       
   713 void CSelectNextLayerActivity::TJoinServiceProvider::DoL()
       
   714 	{
       
   715 	__ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity));
       
   716 	CSelectNextLayerActivity& ac = static_cast<CSelectNextLayerActivity&>(*iContext.iNodeActivity);
       
   717 
       
   718 	__ASSERT_DEBUG(ac.iSelectCompleteMessages.Count() > 0, User::Panic(KSpecAssert_ESockCoreProvcprac, 16));
       
   719 	ESock::TSigSelectComplete& msg = ac.iSelectCompleteMessages[0];
       
   720 
       
   721 	//This transition assumes that the first service provider supplied will be the chosen one (EActive denotes 'the' service provider).
       
   722 	TInt flags = 0;
       
   723 	if (iContext.Node().ServiceProvider() == NULL)
       
   724 		{
       
   725 		flags = TCFClientType::EActive;
       
   726 		}
       
   727 
       
   728 	RNodeInterface* client = iContext.Node().AddClientL(msg.iNodeId, TClientType(TCFClientType::EServProvider, flags), &msg.iProviderInfo);
       
   729 
       
   730 	iContext.iNodeActivity->PostRequestTo(*client, TCFServiceProvider::TJoinRequest(iContext.NodeId(), TCFClientType::ECtrl).CRef());
       
   731 	}
       
   732 
       
   733 EXPORT_DEFINE_SMELEMENT(CSelectNextLayerActivity::TSendSelectComplete, NetStateMachine::MStateTransition, MCprStates::TContext)
       
   734 void CSelectNextLayerActivity::TSendSelectComplete::DoL()
       
   735 	{
       
   736 	__ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity));
       
   737 	CSelectNextLayerActivity& ac = static_cast<CSelectNextLayerActivity&>(*iContext.iNodeActivity);
       
   738 
       
   739 	__ASSERT_DEBUG(ac.iSelectCompleteMessages.Count() > 0, User::Panic(KSpecAssert_ESockCoreProvcprac, 17));
       
   740 	ESock::TSigSelectComplete& selectcompletemsg = ac.iSelectCompleteMessages[0];
       
   741 	iContext.iNodeActivity->PostToOriginators(TCFSelector::TSelectComplete(iContext.iPeer->RecipientId(), selectcompletemsg.iProviderInfo).CRef());
       
   742 	ac.iSelectCompleteMessages.Remove(0);
       
   743 	}
       
   744 
       
   745 EXPORT_DEFINE_SMELEMENT(CSelectNextLayerActivity::TLeaveTierManager, NetStateMachine::MStateTransition, CSelectNextLayerActivity::TContext)
       
   746 void CSelectNextLayerActivity::TLeaveTierManager::DoL()
       
   747 	{
       
   748 	__ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity));
       
   749 	CSelectNextLayerActivity& ac = static_cast<CSelectNextLayerActivity&>(*iContext.iNodeActivity);
       
   750     __ASSERT_DEBUG(!ac.iTierManager.IsNull(), User::Panic(KSpecAssert_ESockCoreProvcprac, 18)); //Must always be valid.
       
   751     ac.PostRequestTo(ac.iTierManager, TEChild::TLeft().CRef());
       
   752     iContext.Node().RemoveClient(ac.iTierManager);
       
   753     ac.iTierManager.SetNull();
       
   754 
       
   755 	}
       
   756 //
       
   757 //CReConnectActivity
       
   758 CReConnectActivity::CReConnectActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode)
       
   759 :	MeshMachine::CNodeActivityBase(aActivitySig, aNode)
       
   760 	{
       
   761 	}
       
   762 
       
   763 MeshMachine::CNodeActivityBase* CReConnectActivity::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode)
       
   764 	{
       
   765 	return new(ELeave)CReConnectActivity(aActivitySig, aNode);
       
   766 	}
       
   767 
       
   768 void CReConnectActivity::StartL(TNodeContextBase& aContext, const Messages::XNodePeerId& aOriginator, const TStateTriple& aFirst)
       
   769 	{
       
   770 	//This activity provides service for only one single requestor at a time.
       
   771 	__ASSERT_DEBUG(iOriginators.Count()==0, User::Panic(KSpecAssert_ESockCoreProvcprac, 19)); //Diagnostic panic
       
   772 	User::LeaveIfError(iOriginators.Count()? KErrInUse : KErrNone);
       
   773   	iOriginators.AppendL(aOriginator);
       
   774   	MESH_LOG_CONTEXT_EXT(KESockMeshMachine, aContext, (_L8("CReConnectActivity %08x:\tStartL->starting activity"), this));
       
   775 	__ASSERT_DEBUG(IsIdle(), User::Panic(KSpecAssert_ESockCoreProvcprac, 20));
       
   776 	NetStateMachine::ACore::Start(&aContext, aFirst);
       
   777   	MESH_LOG((KESockMeshMachine, _L8("CReConnectActivity %08x:\tStartL->activity started"), this));
       
   778 	}
       
   779 
       
   780 DEFINE_SMELEMENT(CReConnectActivity::TProcessReConnectRequest, NetStateMachine::MStateTransition, CReConnectActivity::TContext)
       
   781 void CReConnectActivity::TProcessReConnectRequest::DoL()
       
   782 	{
       
   783 	__ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity));
       
   784 	CReConnectActivity& activity = static_cast<CReConnectActivity&>(*iContext.iNodeActivity);
       
   785 	TCFMcpr::TReConnect& msg = message_cast<TCFMcpr::TReConnect>(iContext.iMessage);
       
   786 
       
   787 	activity.iStoppingSP = iContext.Node().FindClientL(msg.iNodeId1);
       
   788 	__ASSERT_DEBUG(activity.iStoppingSP->Type()&TCFClientType::EServProvider, User::Panic(KSpecAssert_ESockCoreProvcprac, 21));
       
   789 
       
   790 	activity.iStartingSP = iContext.Node().FindClientL(msg.iNodeId2);
       
   791 	__ASSERT_DEBUG(activity.iStartingSP->Type()&TCFClientType::EServProvider, User::Panic(KSpecAssert_ESockCoreProvcprac, 22));
       
   792 	}
       
   793 
       
   794 DEFINE_SMELEMENT(CReConnectActivity::TBuildLowerLayer, NetStateMachine::MStateTransition, CReConnectActivity::TContext)
       
   795 void CReConnectActivity::TBuildLowerLayer::DoL()
       
   796 	{
       
   797 	__ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity));
       
   798 	CReConnectActivity& activity = static_cast<CReConnectActivity&>(*iContext.iNodeActivity);
       
   799 
       
   800 	//Post a TBuildLowerLayer to self, initiating building of the new layer below
       
   801 	//Use the new service provider to prime the new layer
       
   802 	__ASSERT_DEBUG(activity.iStartingSP, User::Panic(KSpecAssert_ESockCoreProvcprac, 25));
       
   803 	iContext.iNodeActivity->PostRequestTo(iContext.NodeId(), TCFDataClient::TBindTo(activity.iStartingSP->RecipientId()).CRef());
       
   804 	}
       
   805 
       
   806 
       
   807 DEFINE_SMELEMENT(CReConnectActivity::TSendReConnectResponse, NetStateMachine::MStateTransition, CReConnectActivity::TContext)
       
   808 void CReConnectActivity::TSendReConnectResponse::DoL()
       
   809 	{
       
   810 	__ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity));
       
   811 	iContext.iNodeActivity->PostToOriginators(TCFMcpr::TReConnectComplete().CRef());
       
   812 	}
       
   813 
       
   814 
       
   815 //
       
   816 //CAvailabilityActivity
       
   817 MeshMachine::CNodeActivityBase* CAvailabilityActivity::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode)
       
   818     {
       
   819     return new (ELeave) CAvailabilityActivity(aActivitySig, aNode);
       
   820     }
       
   821 
       
   822 CAvailabilityActivity::~CAvailabilityActivity()
       
   823 	{
       
   824 	static_cast<CCoreMetaConnectionProvider&>(iNode).CancelAvailabilityMonitoring();
       
   825 
       
   826 	//Unmark all remaining availability providers
       
   827 	TClientIter<TFlagsOnlyClientMatchPolicy> iter = iNode.GetClientIter<TFlagsOnlyClientMatchPolicy>(TClientType(0, TCFClientType::EAvailabilityProvider));
       
   828 	RNodeInterface* provider = iter++;
       
   829 	while (provider)
       
   830 		{
       
   831 		provider->ClearFlags(TCFClientType::EAvailabilityProvider);
       
   832 		provider = static_cast<RNodeAvailabilityProviderInterface*>(iter++);
       
   833 		}
       
   834 	}
       
   835 
       
   836 void CAvailabilityActivity::StartL(TNodeContextBase& aContext, const Messages::XNodePeerId& aOriginator, const TStateTriple& aFirst)
       
   837 	{
       
   838 	TCFAvailabilityProvider::TAvailabilityNotificationRegistration& msg =
       
   839 		message_cast<TCFAvailabilityProvider::TAvailabilityNotificationRegistration>(aContext.iMessage);
       
   840 
       
   841 	CSubscriberInfo* info = new (ELeave) CSubscriberInfo;
       
   842 	const_cast<Messages::XNodePeerId&>(aOriginator).iInfo = info;
       
   843 	info->SetSubscriptionOptions(msg.iAvailabilitySubscriptionOptions);
       
   844 	CleanupStack::PushL(info);
       
   845 	MeshMachine::CNodeActivityBase::StartL(aContext, aOriginator, aFirst);
       
   846 	CleanupStack::Pop(info);
       
   847 
       
   848 	if (IsAvailabilityKnown())
       
   849 		{
       
   850 		info->SetReportedStatus(iCurrentAvailabilityStatus);
       
   851 		aContext.PostToSender(TCFAvailabilityControlClient::TAvailabilityNotification(iCurrentAvailabilityStatus).CRef());
       
   852 		}
       
   853 	}
       
   854 
       
   855 void CAvailabilityActivity::Cancel(TNodeContextBase& aContext)
       
   856 	{
       
   857 	//Post TCancel to all availability providers
       
   858 	iNode.PostToClients<TFlagsOnlyClientMatchPolicy>(TNodeCtxId(ActivityId(), iNode.Id()), TEBase::TCancel().CRef(),
       
   859 		TClientType(0, TCFClientType::EAvailabilityProvider));
       
   860 	MeshMachine::CNodeActivityBase::Cancel(aContext);
       
   861 	}
       
   862 
       
   863 void CAvailabilityActivity::CalculateCurrentAvailabilityStatus()
       
   864 	{
       
   865 	iCurrentAvailabilityStatus.SetUnknown();
       
   866 	TClientIter<TFlagsOnlyClientMatchPolicy> iter = iNode.GetClientIter<TFlagsOnlyClientMatchPolicy>(TClientType(0, TCFClientType::EAvailabilityProvider));
       
   867 	RNodeAvailabilityProviderInterface* provider = static_cast<RNodeAvailabilityProviderInterface*>(iter++);
       
   868 	__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)
       
   869 	while (provider)
       
   870 		{
       
   871 		__ASSERT_DEBUG(provider->Type()&(TCFClientType::EServProvider|TClientType::ERegistrar), User::Panic(KSpecAssert_ESockCoreProvcprac, 27));
       
   872 		const TAvailabilityStatus& availabilityStatus = provider->AvailabilityStatus();
       
   873 		if (!availabilityStatus.IsKnown())
       
   874 			{
       
   875 			//If the immediate response from any of the remaining providers is still in transport,
       
   876 			//set the whole as unknown.
       
   877 			iCurrentAvailabilityStatus.SetUnknown();
       
   878 			return;
       
   879 			}
       
   880 		else if (availabilityStatus.Score() > iCurrentAvailabilityStatus.Score())
       
   881 			{
       
   882 			iCurrentAvailabilityStatus.SetScore(availabilityStatus.Score());
       
   883 			}
       
   884 		provider = static_cast<RNodeAvailabilityProviderInterface*>(iter++);
       
   885 		}
       
   886 	}
       
   887 
       
   888 TBool CAvailabilityActivity::IsAvailabilityKnown() const
       
   889 	{
       
   890 	return iCurrentAvailabilityStatus.IsKnown();
       
   891 	}
       
   892 
       
   893 void CAvailabilityActivity::NotifyInterestedSubscribers()
       
   894 	{
       
   895 	__ASSERT_DEBUG(IsAvailabilityKnown(), User::Panic(KSpecAssert_ESockCoreProvcprac, 28)); //Use only with known availability!
       
   896 	TCFAvailabilityControlClient::TAvailabilityNotification msg(iCurrentAvailabilityStatus); //KActivityNull will be overriden
       
   897 
       
   898 	for (TInt i = iOriginators.Count() - 1; i >= 0; --i)
       
   899 		{
       
   900 		XNodePeerId& originator = iOriginators[i];
       
   901 		CSubscriberInfo* info = static_cast<CSubscriberInfo*>(originator.iInfo);
       
   902 		__ASSERT_DEBUG(info, User::Panic(KSpecAssert_ESockCoreProvcprac, 29));
       
   903 
       
   904 		if (!info->ReportedStatus().IsKnown()
       
   905 			|| info->SubscriptionOptions().IsChangeSignificant(info->ReportedStatus(), iCurrentAvailabilityStatus))
       
   906 			{
       
   907 			info->SetReportedStatus(iCurrentAvailabilityStatus);
       
   908 			originator.PostMessage(TNodeCtxId(ActivityId(), iNode.Id()), msg);
       
   909 			}
       
   910 		}
       
   911 	}
       
   912 
       
   913 void CAvailabilityActivity::RegisterForNotifications(TClientIterBase& aClientIter) const
       
   914 	{
       
   915 	RNodeAvailabilityProviderInterface* provider = static_cast<RNodeAvailabilityProviderInterface*>(aClientIter++);
       
   916 
       
   917 	//We can ignore the fact that tere is no service providers we can register with, provided
       
   918 	//the node has ensured there are some other availability providers!
       
   919 	//If there are no service nor other availability providers the condition is serious.
       
   920 	//__ASSERT_ALWAYS is required as the verified conditions are of a run time nature
       
   921 	__ASSERT_ALWAYS(provider!=NULL || iNode.CountClients<TFlagsOnlyClientMatchPolicy>(TClientType(0, TCFClientType::EAvailabilityProvider))>0,
       
   922 		CoreMCprPanic(KPanicNoAvailabilityProvider));
       
   923 
       
   924 	TAvailabilitySubscriptionOptions subscriptionOptions; //By default register for all notifications - may need to be modified in the future
       
   925 	TCFAvailabilityProvider::TAvailabilityNotificationRegistration msg(subscriptionOptions);
       
   926 
       
   927 	//Iterate through service providers if any, setting EAvailabilityProvider flags
       
   928 	while (provider)
       
   929 		{
       
   930 		provider->SetFlags(TCFClientType::EAvailabilityProvider);
       
   931 		provider->PostMessage(TNodeCtxId(ActivityId(), iNode.Id()), msg);
       
   932 		provider = static_cast<RNodeAvailabilityProviderInterface*>(aClientIter++);
       
   933 		}
       
   934 	}
       
   935 
       
   936 DEFINE_SMELEMENT(CAvailabilityActivity::TRegisterForNotifications, NetStateMachine::MStateTransition, CAvailabilityActivity::TContext)
       
   937 void CAvailabilityActivity::TRegisterForNotifications::DoL()
       
   938 	{
       
   939 	__ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity));
       
   940 	CAvailabilityActivity& activity = static_cast<CAvailabilityActivity&>(*iContext.iNodeActivity);
       
   941 
       
   942 	//Start monitoring on the node if necessary
       
   943 	iContext.Node().StartAvailabilityMonitoringL(TNodeCtxId(iContext.ActivityId(), iContext.NodeId()));
       
   944 
       
   945 	TClientIter<TDefaultClientMatchPolicy> iter = iContext.Node().GetClientIter<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EServProvider));
       
   946 	activity.RegisterForNotifications(iter);
       
   947 	}
       
   948 
       
   949 DEFINE_SMELEMENT(CAvailabilityActivity::TProcessNotification, NetStateMachine::MStateTransition, CAvailabilityActivity::TContext)
       
   950 void CAvailabilityActivity::TProcessNotification::DoL()
       
   951 	{
       
   952 	__ASSERT_DEBUG(iContext.iNodeActivity, CoreMCprPanic(KPanicNoActivity));
       
   953 	CAvailabilityActivity& activity = static_cast<CAvailabilityActivity&>(*iContext.iNodeActivity);
       
   954 
       
   955 	//Register with any new service providers (if any) == not with EAvailabilityProvider(s)
       
   956 	TClientIter<TDefaultClientMatchPolicy> iter = iContext.Node().GetClientIter<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EServProvider), TClientType(0, TCFClientType::EAvailabilityProvider));
       
   957 	activity.RegisterForNotifications(iter);
       
   958 
       
   959 	//Now the iPeer must be set (and we need to have the RNodeAvailabilityProviderInterface behind it)
       
   960 	__ASSERT_DEBUG(iContext.iPeer, User::Panic(KSpecAssert_ESockCoreProvcprac, 30));
       
   961 	TCFAvailabilityControlClient::TAvailabilityNotification& msg = message_cast<TCFAvailabilityControlClient::TAvailabilityNotification>(iContext.iMessage);
       
   962 
       
   963 	//RNodeAvailabilityProviderInterface stores information (on this node) about the availability provider
       
   964 	RNodeAvailabilityProviderInterface* provider = static_cast<RNodeAvailabilityProviderInterface*>(iContext.iPeer);
       
   965 	__ASSERT_DEBUG(provider->Flags()&TCFClientType::EAvailabilityProvider, User::Panic(KSpecAssert_ESockCoreProvcprac, 31));
       
   966 	provider->SetAvailabilityStatus(msg.iAvailabilityStatus);
       
   967 
       
   968 	//Compute the overal availability and report if known already
       
   969 	activity.CalculateCurrentAvailabilityStatus();
       
   970 	if (activity.IsAvailabilityKnown())
       
   971 		{
       
   972 		activity.NotifyInterestedSubscribers();
       
   973 		}
       
   974 	}
       
   975