datacommsserver/esockserver/MobilityCoreProviders/src/mobilitymcpractivities.cpp
branchRCL_3
changeset 19 0b0e9fce0b58
parent 4 928ed51ddc43
equal deleted inserted replaced
14:8b5d60ce1e94 19:0b0e9fce0b58
    13 // Description:
    13 // Description:
    14 //
    14 //
    15 
    15 
    16 #include <elements/nm_messages_errorrecovery.h>
    16 #include <elements/nm_messages_errorrecovery.h>
    17 #include <comms-infras/ss_coreprstates.h>
    17 #include <comms-infras/ss_coreprstates.h>
    18 #include "mobilitymcpractivities.h"
    18 #include <comms-infras/mobilitymcpractivities.h>
    19 #include <comms-infras/mobilitymcprstates.h>
    19 #include <comms-infras/mobilitymcprstates.h>
    20 #include <comms-infras/ss_nodemessages_selector.h>
    20 #include <comms-infras/ss_nodemessages_selector.h>
    21 #include <comms-infras/ss_nodemessages_mobility.h>
    21 #include <comms-infras/ss_nodemessages_mobility.h>
    22 #include <comms-infras/ss_nodemessages_availability.h>
    22 #include <comms-infras/ss_nodemessages_availability.h>
    23 #include <comms-infras/ss_logext.h>
    23 #include <comms-infras/ss_logext.h>
    85 	//Register with self for availability notifications. Self will report _any_ availabilty change (even available->available) back to
    85 	//Register with self for availability notifications. Self will report _any_ availabilty change (even available->available) back to
    86 	//this activity. This activity can trigger mobility (see CMobilityActivity::TNoTagOrErrorTagOrStartMobilityHandshakeBackwardsOnMobilityTriggerBlockedByErrorRecovery)
    86 	//this activity. This activity can trigger mobility (see CMobilityActivity::TNoTagOrErrorTagOrStartMobilityHandshakeBackwardsOnMobilityTriggerBlockedByErrorRecovery)
    87 	//if it sees that the availability notification has influcenced what the currently preffered bearer should be.
    87 	//if it sees that the availability notification has influcenced what the currently preffered bearer should be.
    88 	THROUGH_NODEACTIVITY_ENTRY(KNoTag, CMobilityActivity::TSendAvailabilityRequest, MeshMachine::TTag<MobilityMCprStates::KStartMobilityHandshake>)
    88 	THROUGH_NODEACTIVITY_ENTRY(KNoTag, CMobilityActivity::TSendAvailabilityRequest, MeshMachine::TTag<MobilityMCprStates::KStartMobilityHandshake>)
    89 
    89 
    90 	//<BEGIN> MAIN LOOP ****************	
    90 	//<BEGIN> MAIN LOOP ****************
    91 	//The main mobility handshake loop. The loop is executed when performing migration from one service provider to another.
    91 	//The main mobility handshake loop. The loop is executed when performing migration from one service provider to another.
    92 	//The entry condition for the loop is that:
    92 	//The entry condition for the loop is that:
    93 	//- upgrade: a better then current access point is now available (a better access point reported available)
    93 	//- upgrade: a better then current access point is now available (a better access point reported available)
    94 	//- downgrade:
    94 	//- downgrade:
    95 	//  (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)
    95 	//  (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)
    96 	//  (b) the current access point ceases to be available (reports availability below reasonable threshold).
    96 	//  (b) the current access point ceases to be available (reports availability below reasonable threshold).
    97 	//      NOTE: if the current bearer ceases to be available completely (goes down), then this will be assisted by an error recovery request;
    97 	//      NOTE: if the current bearer ceases to be available completely (goes down), then this will be assisted by an error recovery request;
    98 	//      NOTE: This tuple doesn't actually do (b), i.e.: assumes the threshold of '1' (in 0..100 availability score range)
    98 	//      NOTE: This tuple doesn't actually do (b), i.e.: assumes the threshold of '1' (in 0..100 availability score range)
    99 	//Before awaitng for availability change or rejection by the client (TAwaitingCurrentCarrierRejectedOrAvailabilityChange), the activity
    99 	//Before awaitng for availability change or rejection by the client (TAwaitingCurrentCarrierRejectedOrAvailabilityChange), the activity
   100 	//first checks (TNoTagOrAwaitMobilityBlockedByErrorRecovery) if the availability has changed since it last checked 
   100 	//first checks (TNoTagOrAwaitMobilityBlockedByErrorRecovery) if the availability has changed since it last checked
   101 	//(availability could have been reported amidst the previous handshake loop) 
   101 	//(availability could have been reported amidst the previous handshake loop)
   102 	THROUGH_NODEACTIVITY_ENTRY(MobilityMCprStates::KStartMobilityHandshake, CMobilityActivity::TClearHandshakingFlag, CMobilityActivity::TNoTagOrAwaitMobilityBlockedByErrorRecovery)
   102 	THROUGH_NODEACTIVITY_ENTRY(MobilityMCprStates::KStartMobilityHandshake, CMobilityActivity::TClearHandshakingFlag, CMobilityActivity::TNoTagOrAwaitMobilityBlockedByErrorRecovery)
   103 	    NODEACTIVITY_ENTRY(MobilityMCprStates::KAwaitMobility, MeshMachine::TDoNothing, CMobilityActivity::TAwaitingCurrentCarrierRejectedOrAvailabilityChange, CMobilityActivity::TNoTagOrAwaitMobilityBackwardsOnMobilityTriggerBlockedByErrorRecovery)
   103 	    NODEACTIVITY_ENTRY(MobilityMCprStates::KAwaitMobility, MeshMachine::TDoNothing, CMobilityActivity::TAwaitingCurrentCarrierRejectedOrAvailabilityChange, CMobilityActivity::TNoTagOrAwaitMobilityBackwardsOnMobilityTriggerBlockedByErrorRecovery)
   104 
   104 
   105 		//Mobility has been triggered ((a) or (b)). Start mobility handshake (set handshaking flag and inform the client about the preferred bearer) 
   105 		//Mobility has been triggered ((a) or (b)). Start mobility handshake (set handshaking flag and inform the client about the preferred bearer)
   106 		NODEACTIVITY_ENTRY(KNoTag, CMobilityActivity::TInformMigrationAvailableAndSetHandshakingFlag, MobilityMCprStates::TAwaitingMigrationRequestedOrRejected, CMobilityActivity::TNoTagOrStartMobilityHandshakeBackwards)
   106 		//ReConnect only needs to be done if the bearer is different from the curret bearer.
       
   107 		NODEACTIVITY_ENTRY(KNoTag, CMobilityActivity::TInformMigrationAvailableAndSetHandshakingFlag, MobilityMCprStates::TAwaitingMigrationRequestedOrRejected, CMobilityActivity::TNoTagOrReConnectOrStartMobilityHandshakeBackwards)
       
   108 		//The client accepts the new access point.
   107 		//The client accepts the new access point. 
   109 		//The client accepts the new access point. 
   108 		//For the moment it is sufficient to use the re-connect activity, in the future we may want to
   110 		//For the moment it is sufficient to use the re-connect activity, in the future we may want to
   109 		//customise the behavior, for example start the new layer before rebinding it, etc.
   111 		//customise the behavior, for example start the new layer before rebinding it, etc.
   110 		//Should rebinding fail, the mobility activity will be set to an error mode. The error mode will be cleared if
   112 		//Should rebinding fail, the mobility activity will be set to an error mode. The error mode will be cleared if
   111 		//there are other bearers this activity can offer. If there aren't the data client will be errored.
   113 		//there are other bearers this activity can offer. If there aren't the data client will be errored.
   112 		NODEACTIVITY_ENTRY(KNoTag, CMobilityActivity::TRequestReConnect, MCprStates::TAwaitingReConnectCompleteOrError, CMobilityActivity::TNoTagOrStartMobilityHandshakeBackwards)
   114 		NODEACTIVITY_ENTRY(MobilityMCprStates::KReConnect, CMobilityActivity::TRequestReConnect, MCprStates::TAwaitingReConnectCompleteOrError, CMobilityActivity::TNoTagOrStartMobilityHandshakeBackwards)
   113 		//Rebinding has been successful. As far as MCPR is concerned, the mobility is finished, but the MCPR must await
   115 		//Rebinding has been successful. As far as MCPR is concerned, the mobility is finished, but the MCPR must await
   114 		//for the handshake (accept|reject) before it can offer another bearer. 
   116 		//for the handshake (accept|reject) before it can offer another bearer.
   115         NODEACTIVITY_ENTRY(KNoTag, CMobilityActivity::TInformMigrationCompleted, MobilityMCprStates::TAwaitingMigrationAcceptedOrRejected, CMobilityActivity::TRejectedOrStartMobilityHandshakeBackwards)
   117 	NODEACTIVITY_ENTRY(KNoTag, CMobilityActivity::TInformMigrationCompleted, MobilityMCprStates::TAwaitingMigrationAcceptedOrRejected, CMobilityActivity::TRejectedOrStartMobilityHandshakeBackwards)
   116         NODEACTIVITY_ENTRY(MobilityMCprStates::KRejected, CoreNetStates::TStopDataClients, CoreNetStates::TAwaitingDataClientsStopped, MeshMachine::TTag<MobilityMCprStates::KStartMobilityHandshake|NetStateMachine::EBackward>)
   118 	NODEACTIVITY_ENTRY(MobilityMCprStates::KRejected, CoreNetStates::TStopDataClients, CoreNetStates::TAwaitingDataClientsStopped, MeshMachine::TTag<MobilityMCprStates::KStartMobilityHandshake|NetStateMachine::EBackward>)
   117 NODEACTIVITY_END()
   119 NODEACTIVITY_END()
   118 }
   120 }
   119 
   121 
   120 namespace MCprConnectionStartRecoveryActivity
   122 namespace MCprConnectionStartRecoveryActivity
   121 {
   123 {
   209 	    //There's a couple of reasons why the activity may be in an error mode:
   211 	    //There's a couple of reasons why the activity may be in an error mode:
   210 	    //- rejection
   212 	    //- rejection
   211 	    //  - current bearer rejected;
   213 	    //  - current bearer rejected;
   212 	    //  - proposed bearer rejected;
   214 	    //  - proposed bearer rejected;
   213 	    //  - failure to migrate to the proposed bearer;
   215 	    //  - failure to migrate to the proposed bearer;
   214         lastRejected = iPreferred ? iPreferred : 
   216         lastRejected = iAvailable ? iAvailable :
   215                                     static_cast<RMetaServiceProviderInterface*>(aContext.Node().ServiceProvider()); 
   217                                     static_cast<RMetaServiceProviderInterface*>(aContext.Node().ServiceProvider());
   216 	    }
   218 	    }
   217 	
   219 
   218 	iPreferred = NULL; //Do not remember rejected candidate any longer
   220 	iCandidate = iAvailable;
       
   221 	iAvailable = NULL; //Do not remember rejected candidate any longer
   219 	while ((candidate = static_cast<RMetaServiceProviderInterface*>(iter++)) != NULL)
   222 	while ((candidate = static_cast<RMetaServiceProviderInterface*>(iter++)) != NULL)
   220 		{
   223 		{
   221 		const TAvailabilityStatus& status = candidate->AvailabilityStatus();
   224 		const TAvailabilityStatus& status = candidate->AvailabilityStatus();
   222 		if (!status.IsKnown())
   225 		if (!status.IsKnown())
   223 			{
   226 			{
   228 			}
   231 			}
   229 
   232 
   230 		if (status.Score() > iAvailabilityScoreTreshold
   233 		if (status.Score() > iAvailabilityScoreTreshold
   231 			&& candidate!=lastRejected)
   234 			&& candidate!=lastRejected)
   232 			{
   235 			{
   233 			if (candidate->Flags() & TCFClientType::EStarted)
   236 			if (candidate==aContext.Node().ServiceProvider()
       
   237 			    && Error() == KErrNone )
   234 				{
   238 				{
   235 				//The preferred one is the current one, is still available and was not just rejected.
   239 				//The preferred one is the current one, is still available and was not just rejected.
   236 				//No need to do anything more.
   240 				//No need to do anything more.
   237 				return EFalse;
   241 				return EFalse;
   238 				}
   242 				}
   239 
   243 
   240 			//A new match found
   244 			//A new match found
   241 			iPreferred = candidate;
   245 			iAvailable = candidate;
   242 			return ETrue;
   246 			return ETrue;
   243 			}
   247 			}
   244 		}
   248 		}
   245 
   249 
   246 	//There is no choice for migration
   250 	//There is no choice for migration
   255 void CMobilityActivity::ClearHandshakingFlag()
   259 void CMobilityActivity::ClearHandshakingFlag()
   256 	{
   260 	{
   257 	static_cast<CMobilityMetaConnectionProvider&>(iNode).iIsHandshakingNow = EFalse;
   261 	static_cast<CMobilityMetaConnectionProvider&>(iNode).iIsHandshakingNow = EFalse;
   258 	}
   262 	}
   259 
   263 
   260 DEFINE_SMELEMENT(CMobilityActivity::TNoTagOrStartMobilityHandshakeBackwards, NetStateMachine::MStateFork, CMobilityActivity::TContext)
   264 DEFINE_SMELEMENT(CMobilityActivity::TNoTagOrReConnectOrStartMobilityHandshakeBackwards, NetStateMachine::MStateFork, CMobilityActivity::TContext)
   261 TInt CMobilityActivity::TNoTagOrStartMobilityHandshakeBackwards::TransitionTag()
   265 TInt CMobilityActivity::TNoTagOrReConnectOrStartMobilityHandshakeBackwards::TransitionTag()
   262 	{
   266 	{
   263 	if (iContext.Activity()->Error() == KErrNone &&
   267 	if (iContext.Activity()->Error() == KErrNone &&
   264 	    (message_cast<TCFMobilityProvider::TMigrationRequested>(&iContext.iMessage) ||
   268 	    (message_cast<TCFMobilityProvider::TMigrationRequested>(&iContext.iMessage) ||
   265 	     message_cast<TCFMcpr::TReConnectComplete>(&iContext.iMessage)))
   269 	     message_cast<TCFMcpr::TReConnectComplete>(&iContext.iMessage)))
   266 		{
   270 		{
       
   271 	        CMobilityActivity& activity = static_cast<CMobilityActivity&>(*iContext.iNodeActivity);
       
   272 			if( activity.iCurrent!=activity.iAvailable )
       
   273 			    return MobilityMCprStates::KReConnect | NetStateMachine::EForward;
       
   274 			else
       
   275 		        return MeshMachine::KNoTag | NetStateMachine::EForward;
       
   276 		}
       
   277 	return MobilityMCprStates::KStartMobilityHandshake | NetStateMachine::EBackward;
       
   278 	}
       
   279 
       
   280 DEFINE_SMELEMENT(CMobilityActivity::TNoTagOrStartMobilityHandshakeBackwards, NetStateMachine::MStateFork, CMobilityActivity::TContext)
       
   281 TInt CMobilityActivity::TNoTagOrStartMobilityHandshakeBackwards::TransitionTag()
       
   282 	{
       
   283 	if (iContext.Activity()->Error() == KErrNone &&
       
   284 	    (message_cast<TCFMobilityProvider::TMigrationRequested>(&iContext.iMessage) ||
       
   285 	     message_cast<TCFMcpr::TReConnectComplete>(&iContext.iMessage)))
       
   286 		{
   267 		return MeshMachine::KNoTag | NetStateMachine::EForward;
   287 		return MeshMachine::KNoTag | NetStateMachine::EForward;
   268 		}
   288 		}
   269 	return MobilityMCprStates::KStartMobilityHandshake | NetStateMachine::EBackward;
   289 	return MobilityMCprStates::KStartMobilityHandshake | NetStateMachine::EBackward;
   270 	}
   290 	}
   271 
   291 
   272 DEFINE_SMELEMENT(CMobilityActivity::TNoTagOrAwaitMobilityBackwardsOnMobilityTrigger, NetStateMachine::MStateFork, CMobilityActivity::TContext)
   292 DEFINE_SMELEMENT(CMobilityActivity::TNoTagOrAwaitMobilityBackwardsOnMobilityTrigger, NetStateMachine::MStateFork, CMobilityActivity::TContext)
   273 TInt CMobilityActivity::TNoTagOrAwaitMobilityBackwardsOnMobilityTrigger::TransitionTag()
   293 TInt CMobilityActivity::TNoTagOrAwaitMobilityBackwardsOnMobilityTrigger::TransitionTag()
   274 	{
   294 	{
   275 	//This is where the judgement is made on whether to trigger mobility (offer the client another bearer)
   295 	//This is where the judgement is made on whether to trigger mobility (offer the client another bearer)
   276 	//or ignore and come back waiting. 
   296 	//or ignore and come back waiting.
   277 	__ASSERT_DEBUG(iContext.iMessage.IsMessage<TCFMobilityProvider::TMigrationRejected>() ||
   297 	__ASSERT_DEBUG(iContext.iMessage.IsMessage<TCFMobilityProvider::TMigrationRejected>() ||
   278 			iContext.iMessage.IsMessage<TCFAvailabilityControlClient::TAvailabilityNotification>(), 
   298 			iContext.iMessage.IsMessage<TCFAvailabilityControlClient::TAvailabilityNotification>(),
   279 			User::Panic(KCoreMobileMCprPanic, KPanicIncorrectMessage));
   299 			User::Panic(KCoreMobileMCprPanic, KPanicIncorrectMessage));
   280 	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity));	
   300 	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity));
   281 	CMobilityActivity& activity = static_cast<CMobilityActivity&>(*iContext.iNodeActivity);
   301 	CMobilityActivity& activity = static_cast<CMobilityActivity&>(*iContext.iNodeActivity);
   282 	
   302 
   283 	if (activity.EvaluatePreference(iContext))
   303 	if (activity.EvaluatePreference(iContext))
   284 		{
   304 		{
   285         activity.SetError(KErrNone);
   305         activity.SetError(KErrNone);
   286 		return KNoTag;
   306 		return KNoTag;
   287 		}
   307 		}
   294 	}
   314 	}
   295 
   315 
   296 DEFINE_SMELEMENT(CMobilityActivity::TNoTagOrAwaitMobility, NetStateMachine::MStateFork, CMobilityActivity::TContext)
   316 DEFINE_SMELEMENT(CMobilityActivity::TNoTagOrAwaitMobility, NetStateMachine::MStateFork, CMobilityActivity::TContext)
   297 TInt CMobilityActivity::TNoTagOrAwaitMobility::TransitionTag()
   317 TInt CMobilityActivity::TNoTagOrAwaitMobility::TransitionTag()
   298 	{
   318 	{
   299 	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity));	
   319 	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity));
   300 	CMobilityActivity& activity = static_cast<CMobilityActivity&>(*iContext.iNodeActivity);
   320 	CMobilityActivity& activity = static_cast<CMobilityActivity&>(*iContext.iNodeActivity);
   301 	
   321 
   302 	if (activity.EvaluatePreference(iContext))
   322 	if (activity.EvaluatePreference(iContext))
   303 		{
   323 		{
   304 		activity.SetError(KErrNone);
   324 		activity.SetError(KErrNone);
   305 		return KNoTag;
   325 		return KNoTag;
   306 		}
   326 		}
   321 
   341 
   322 	// if rejected last ap and there's no more
   342 	// if rejected last ap and there's no more
   323 	if (iContext.iMessage.IsMessage<TCFMobilityProvider::TMigrationRejected>())
   343 	if (iContext.iMessage.IsMessage<TCFMobilityProvider::TMigrationRejected>())
   324 		{
   344 		{
   325 		TBool otherSP = EFalse;
   345 		TBool otherSP = EFalse;
   326 		
   346 
   327 		// Find if there anymore available non rejected service providers
   347 		// Find if there anymore available non rejected service providers
   328 		TClientIter<TDefaultClientMatchPolicy> iter = iContext.Node().GetClientIter<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EServProvider));
   348 		TClientIter<TDefaultClientMatchPolicy> iter = iContext.Node().GetClientIter<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EServProvider));
   329 		__ASSERT_DEBUG(iter[0], User::Panic(KCoreMobileMCprPanic, KPanicNoServiceProvider)); //A Service Provider must exist!
   349 		__ASSERT_DEBUG(iter[0], User::Panic(KCoreMobileMCprPanic, KPanicNoServiceProvider)); //A Service Provider must exist!
   330 		RMetaServiceProviderInterface* rejected = static_cast<RMetaServiceProviderInterface*>(iContext.Node().ServiceProvider());
   350 		RMetaServiceProviderInterface* rejected = static_cast<RMetaServiceProviderInterface*>(iContext.Node().ServiceProvider());
   331 		RMetaServiceProviderInterface* candidate = NULL;
   351 		RMetaServiceProviderInterface* candidate = NULL;
   332 		
   352 
   333 		while ((candidate = static_cast<RMetaServiceProviderInterface*>(iter++)) != NULL)
   353 		while ((candidate = static_cast<RMetaServiceProviderInterface*>(iter++)) != NULL)
   334 			{
   354 			{
   335 			if (candidate == rejected)
   355 			if (candidate == rejected)
   336 				{
   356 				{
   337 				continue;
   357 				continue;
   338 				}
   358 				}
   339 			
   359 
   340 			const TAvailabilityStatus& status = candidate->AvailabilityStatus();
   360 			const TAvailabilityStatus& status = candidate->AvailabilityStatus();
   341 			if (!status.IsKnown())
   361 			if (!status.IsKnown())
   342 				{
   362 				{
   343 				continue;
   363 				continue;
   344 				}
   364 				}
   378 	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity));
   398 	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity));
   379 	CMobilityActivity& activity = static_cast<CMobilityActivity&>(*iContext.iNodeActivity);
   399 	CMobilityActivity& activity = static_cast<CMobilityActivity&>(*iContext.iNodeActivity);
   380 
   400 
   381 	//Inform the CPR that a potential migration is available. We only support a single data client
   401 	//Inform the CPR that a potential migration is available. We only support a single data client
   382 	//in this implementation.
   402 	//in this implementation.
   383 	__ASSERT_DEBUG(activity.iPreferred, User::Panic(KCoreMobileMCprPanic, KPanicNoServiceProvider));
   403 	__ASSERT_DEBUG(activity.iAvailable, User::Panic(KCoreMobileMCprPanic, KPanicNoServiceProvider));
   384 
   404 
   385 	//Compute all this here to keep EvaluatePreference() as fast as possible
   405 	//Compute all this here to keep EvaluatePreference() as fast as possible
   386 	activity.iCurrent = static_cast<RMetaServiceProviderInterface*>(iContext.Node().GetFirstClient<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EServProvider, TCFClientType::EStarted)));
   406 	activity.iCurrent = static_cast<RMetaServiceProviderInterface*>(iContext.Node().ServiceProvider());
   387 	__ASSERT_DEBUG(activity.iCurrent, User::Panic(KCoreMobileMCprPanic, KPanicNoServiceProvider));
   407 	__ASSERT_DEBUG(activity.iCurrent, User::Panic(KCoreMobileMCprPanic, KPanicNoServiceProvider));
   388 
   408 
   389 	//Perform a simple check if this is an upgrade or not
   409 	//Perform a simple check if this is an upgrade or not
   390 	TClientIter<TDefaultClientMatchPolicy> iter = iContext.Node().GetClientIter<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EServProvider));
   410 	TClientIter<TDefaultClientMatchPolicy> iter = iContext.Node().GetClientIter<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EServProvider));
   391 	RNodeInterface* sp = iter++;
   411 	RNodeInterface* sp = iter++;
   392 	while (sp && sp!=activity.iCurrent && sp!=activity.iPreferred)
   412 	while (sp && sp!=activity.iCurrent && sp!=activity.iAvailable)
   393 		{
   413 		{
   394 		sp = iter++;
   414 		sp = iter++;
   395 		}
   415 		}
   396 
   416 
   397 	TBool isUpgrade = (sp != activity.iCurrent); //If current was found first -> this is not an upgrade
   417 	TBool isUpgrade = (sp != activity.iCurrent); //If current was found first -> this is not an upgrade
   398 	TCFMobilityControlClient::TMigrationNotification msg(activity.iCurrent->ProviderInfo().APId(),
   418 	if( activity.iCurrent == activity.iAvailable && activity.iCandidate )
   399 	                                       activity.iPreferred->ProviderInfo().APId(),
   419 	    {
   400 	                                       isUpgrade, EFalse);
   420 		// The available client is the same as the current and a candidate exists, this indicates that
   401 
   421 		// an error has occured when trying to start the candidate bearer and the control as reverted to
   402 	activity.PostToOriginators(msg);
   422 		// the current bearer. In this situation the notification needs to look as if the bearer has
       
   423 		// migrated from the failed candidate to the current bearer.
       
   424 		TCFMobilityControlClient::TMigrationNotification msg(activity.iCandidate->ProviderInfo().APId(),
       
   425 											   activity.iAvailable->ProviderInfo().APId(),
       
   426 											   isUpgrade, EFalse);
       
   427 		activity.PostToOriginators(msg);
       
   428 	    }
       
   429 	else
       
   430 	    {
       
   431 		// Standard case where migration is going from current to available.
       
   432 		TCFMobilityControlClient::TMigrationNotification msg(activity.iCurrent->ProviderInfo().APId(),
       
   433 											   activity.iAvailable->ProviderInfo().APId(),
       
   434 											   isUpgrade, EFalse);
       
   435 		activity.PostToOriginators(msg);
       
   436 	    }
       
   437 
   403 	activity.ClearPostedTo();
   438 	activity.ClearPostedTo();
   404 	activity.SetHandshakingFlag();
   439 	activity.SetHandshakingFlag();
   405 	}
   440 	}
   406 
       
   407 
   441 
   408 DEFINE_SMELEMENT(CMobilityActivity::TAwaitingCurrentCarrierRejectedOrAvailabilityChange, NetStateMachine::MState, CMobilityActivity::TContext)
   442 DEFINE_SMELEMENT(CMobilityActivity::TAwaitingCurrentCarrierRejectedOrAvailabilityChange, NetStateMachine::MState, CMobilityActivity::TContext)
   409 TBool CMobilityActivity::TAwaitingCurrentCarrierRejectedOrAvailabilityChange::Accept()
   443 TBool CMobilityActivity::TAwaitingCurrentCarrierRejectedOrAvailabilityChange::Accept()
   410 	{
   444 	{
   411 	if (iContext.iMessage.IsMessage<TCFMobilityProvider::TMigrationRejected>())
   445 	if (iContext.iMessage.IsMessage<TCFMobilityProvider::TMigrationRejected>())
   421 void CMobilityActivity::TRequestReConnect::DoL()
   455 void CMobilityActivity::TRequestReConnect::DoL()
   422 	{
   456 	{
   423 	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity));
   457 	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity));
   424 	CMobilityActivity& activity = static_cast<CMobilityActivity&>(*iContext.iNodeActivity);
   458 	CMobilityActivity& activity = static_cast<CMobilityActivity&>(*iContext.iNodeActivity);
   425 
   459 
   426 	__ASSERT_DEBUG(activity.iPreferred, User::Panic(KCoreMobileMCprPanic, KPanicNoServiceProvider));
   460 	__ASSERT_DEBUG(activity.iAvailable, User::Panic(KCoreMobileMCprPanic, KPanicNoServiceProvider));
   427 	__ASSERT_DEBUG(activity.iCurrent, User::Panic(KCoreMobileMCprPanic, KPanicNoServiceProvider));
   461 	__ASSERT_DEBUG(activity.iCurrent, User::Panic(KCoreMobileMCprPanic, KPanicNoServiceProvider));
   428 	__ASSERT_DEBUG(activity.iCurrent!=activity.iPreferred, User::Panic(KSpecAssert_ESockMbCrMCPRAct, 1));
   462 	__ASSERT_DEBUG(activity.iCurrent!=activity.iAvailable, User::Panic(KSpecAssert_ESockMbCrMCPRAct, 1));
   429 
   463 
   430 	// For the moment it is sufficient to use the re-connect activity, in the future we may want to
   464 	// For the moment it is sufficient to use the re-connect activity, in the future we may want to
   431 	// customise the behavior, for example start the new layer before rebinding it, etc.
   465 	// customise the behavior, for example start the new layer before rebinding it, etc.
   432 	TCFMcpr::TReConnect msg(activity.iCurrent->RecipientId(), activity.iPreferred->RecipientId());
   466 	TCFMcpr::TReConnect msg(activity.iCurrent->RecipientId(), activity.iAvailable->RecipientId());
   433 	activity.PostRequestTo(iContext.NodeId(), msg);
   467 	activity.PostRequestTo(iContext.NodeId(), msg);
   434 	}
   468 	}
   435 
   469 
   436 DEFINE_SMELEMENT(CMobilityActivity::TInformMigrationCompleted, NetStateMachine::MStateTransition, CMobilityActivity::TContext)
   470 DEFINE_SMELEMENT(CMobilityActivity::TInformMigrationCompleted, NetStateMachine::MStateTransition, CMobilityActivity::TContext)
   437 void CMobilityActivity::TInformMigrationCompleted::DoL()
   471 void CMobilityActivity::TInformMigrationCompleted::DoL()
   514 
   548 
   515 DEFINE_SMELEMENT(CConnectionRecoveryActivity::TProcessConnectionStartRecoveryRequest, NetStateMachine::MStateTransition, CConnectionRecoveryActivity::TContext)
   549 DEFINE_SMELEMENT(CConnectionRecoveryActivity::TProcessConnectionStartRecoveryRequest, NetStateMachine::MStateTransition, CConnectionRecoveryActivity::TContext)
   516 void CConnectionRecoveryActivity::TProcessConnectionStartRecoveryRequest::DoL()
   550 void CConnectionRecoveryActivity::TProcessConnectionStartRecoveryRequest::DoL()
   517 	{
   551 	{
   518 	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity));
   552 	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity));
   519 	RNodeInterface* startingSP = NULL;
   553 	RNodeInterface* newSP = NULL;
   520 	RNodeInterface* stoppingSP = NULL;
   554 	RNodeInterface* curSP = iContext.Node().ServiceProvider(); //Our current started Service Provider.
   521 
   555 
   522 	//Choose Service Providers to work on
   556 	//Choose Service Providers to work on
   523 	TClientIter<TDefaultClientMatchPolicy> iter = iContext.Node().GetClientIter<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EServProvider));
   557 	TClientIter<TDefaultClientMatchPolicy> iter = iContext.Node().GetClientIter<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EServProvider));
   524 	RNodeInterface* itf = NULL;
   558 	RNodeInterface* itf = NULL;
   525 	for (itf = iter++; itf!=NULL && stoppingSP==NULL; itf = iter++)
   559 	for (itf = iter++; itf!=NULL && newSP==NULL; itf = iter++)
   526 		{
   560 		{
   527 		if (itf->Flags() & TCFClientType::EStarted)
   561 		if (itf==curSP)
   528 			{
   562 			{
   529 			stoppingSP = itf; //Our current started Service Provider.
   563 			newSP = iter++; //And the new one to try next
   530 			startingSP = iter++; //And the new one to try next
       
   531 			}
   564 			}
   532 		}
   565 		}
   533 
   566 
   534 	//Sanity check.
   567 	//Sanity check.
   535 	//The new provider must not be started, there can be only one started at a time.
   568 	//The new provider must not be started, there can be only one started at a time.
   536 	__ASSERT_DEBUG(startingSP==NULL || (startingSP->Flags() & TCFClientType::EStarted)==0, User::Panic(KSpecAssert_ESockMbCrMCPRAct, 3));
   569 	__ASSERT_DEBUG(newSP==NULL || (newSP->Flags() & TCFClientType::EStarted)==0, User::Panic(KSpecAssert_ESockMbCrMCPRAct, 3));
   537 
   570 
   538 	//If there is no other Service Provider to try, return KErrNotFound
   571 	//If there is no other Service Provider to try, return KErrNotFound
   539 	if (startingSP==NULL || stoppingSP == NULL)
   572 	if (newSP==NULL || curSP == NULL)
   540 		{
   573 		{
   541 #ifdef __CFLOG_ACTIVE
   574 #ifdef __CFLOG_ACTIVE
   542 		__CFLOG_VAR((KCoreMCprStatesTag, KCoreMCprStatesSubTag, _L8("WARNING: CConnectionRecoveryActivity::TProcessConnectionStartRecoveryRequest::DoL() - no more choices, abandoning recovery.")));
   575 		__CFLOG_VAR((KCoreMCprStatesTag, KCoreMCprStatesSubTag, _L8("WARNING: CConnectionRecoveryActivity::TProcessConnectionStartRecoveryRequest::DoL() - no more choices, abandoning recovery.")));
   543 #endif
   576 #endif
   544 		User::Leave(KErrNotFound);
   577 		User::Leave(KErrNotFound);
   545 		}
   578 		}
   546 
   579 
   547 	//Diagnostinc - there must be a data client or we cannot be here
   580 	//Diagnostinc - there must be a data client or we cannot be here
   548 	__ASSERT_DEBUG(iContext.Node().GetFirstClient<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EData)), User::Panic(KCoreMobileMCprPanic, KPanicNoDataClient));
   581 	__ASSERT_DEBUG(iContext.Node().GetFirstClient<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EData)), User::Panic(KCoreMobileMCprPanic, KPanicNoDataClient));
   549 	iContext.iNodeActivity->PostRequestTo(iContext.NodeId(),
   582 	iContext.iNodeActivity->PostRequestTo(iContext.NodeId(),
   550 			TCFMcpr::TReConnect(stoppingSP->RecipientId(), startingSP->RecipientId()).CRef());
   583 			TCFMcpr::TReConnect(curSP->RecipientId(), newSP->RecipientId()).CRef());
   551 	}
   584 	}
   552 
   585 
   553 DEFINE_SMELEMENT(CConnectionRecoveryActivity::TProcessConnectionGoneDownRecoveryRequest, NetStateMachine::MStateTransition, CConnectionRecoveryActivity::TContext)
   586 DEFINE_SMELEMENT(CConnectionRecoveryActivity::TProcessConnectionGoneDownRecoveryRequest, NetStateMachine::MStateTransition, CConnectionRecoveryActivity::TContext)
   554 void CConnectionRecoveryActivity::TProcessConnectionGoneDownRecoveryRequest::DoL()
   587 void CConnectionRecoveryActivity::TProcessConnectionGoneDownRecoveryRequest::DoL()
   555 	{
   588 	{
   556 	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity));
   589 	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity));
   557 	CConnectionRecoveryActivity& activity = static_cast<CConnectionRecoveryActivity&>(*iContext.iNodeActivity);
   590 	CConnectionRecoveryActivity& activity = static_cast<CConnectionRecoveryActivity&>(*iContext.iNodeActivity);
   558 
   591 
   559 	RNodeInterface* started = iContext.Node().GetFirstClient<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EServProvider, TCFClientType::EStarted));
   592 	RNodeInterface* started = iContext.Node().ServiceProvider();
   560 	TUint apId = (TUint)activity.iOriginalErrContext.iInfo;
   593 	TUint apId = (TUint)activity.iOriginalErrContext.iInfo;
   561 	RNodeInterface* gonedownsp = iContext.Node().FindServiceProvider(apId);
   594 	RNodeInterface* gonedownsp = iContext.Node().FindServiceProvider(apId);
   562 	if (started && started != gonedownsp)
   595 	if (started && started != gonedownsp)
   563 		{
   596 		{
   564 		CConnectionRecoveryActivity::TSendRetryRecoveryResponse tr(iContext);
   597 		CConnectionRecoveryActivity::TSendRetryRecoveryResponse tr(iContext);