datacommsserver/esockserver/MobilityCoreProviders/src/mobilitymcpractivities.cpp
changeset 1 21d2ab05f085
parent 0 dfb7c4ff071f
child 2 dee179edb159
equal deleted inserted replaced
0:dfb7c4ff071f 1:21d2ab05f085
     1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
     1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Symbian Foundation License v1.0"
     4 // under the terms of "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html".
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     7 //
     8 // Initial Contributors:
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
     9 // Nokia Corporation - initial contribution.
    10 //
    10 //
    11 // Contributors:
    11 // Contributors:
    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 "mobilitymcpractivities.h"
    19 #include "mobilitymcprstates.h"
    19 #include <comms-infras/mobilitymcprstates.h>
    20 #include "ss_nodemessages_selector.h"
    20 #include <comms-infras/ss_nodemessages_selector.h>
    21 #include "ss_nodemessages_mobility.h"
    21 #include <comms-infras/ss_nodemessages_mobility.h>
    22 #include "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>
    24 
    24 
    25 
    25 
    26 #ifdef _DEBUG
    26 #ifdef _DEBUG
    27 // Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module
    27 // Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module
    41 using namespace MCprActivities;
    41 using namespace MCprActivities;
    42 using namespace MobilityMCprActivities;
    42 using namespace MobilityMCprActivities;
    43 using namespace Messages;
    43 using namespace Messages;
    44 using namespace MeshMachine;
    44 using namespace MeshMachine;
    45 
    45 
    46 ///////////////////////////////////////////////////////////////////////////////
    46 //
    47 //Panics
    47 //Panics
    48 #ifdef _DEBUG
    48 #ifdef _DEBUG
    49 _LIT (KCoreMobileMCprPanic,"CoreMobileMCprPanic");
    49 _LIT (KCoreMobileMCprPanic,"CoreMobileMCprPanic");
    50 #endif
    50 #endif
    51 
    51 
    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::TNoTagOrReConnectOrStartMobilityHandshakeBackwards)
   106 		NODEACTIVITY_ENTRY(KNoTag, CMobilityActivity::TInformMigrationAvailableAndSetHandshakingFlag, MobilityMCprStates::TAwaitingMigrationRequestedOrRejected, CMobilityActivity::TNoTagOrStartMobilityHandshakeBackwards)
   107 		//The client accepts the new access point.
   107 		//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
   108 		//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.
   109 		//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
   110 		//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.
   111 		//there are other bearers this activity can offer. If there aren't the data client will be errored.
   112 		NODEACTIVITY_ENTRY(MobilityMCprStates::KReConnect, CMobilityActivity::TRequestReConnect, MCprStates::TAwaitingReConnectCompleteOrError, CMobilityActivity::TNoTagOrStartMobilityHandshakeBackwards)
   112 		NODEACTIVITY_ENTRY(KNoTag, 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
   113 		//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.
   114 		//for the handshake (accept|reject) before it can offer another bearer. 
   115 		NODEACTIVITY_ENTRY(KNoTag, CMobilityActivity::TInformMigrationCompleted, MobilityMCprStates::TAwaitingMigrationAcceptedOrRejected, MeshMachine::TTag<MobilityMCprStates::KStartMobilityHandshake|EBackward>)
   115 		NODEACTIVITY_ENTRY(KNoTag, CMobilityActivity::TInformMigrationCompleted, MobilityMCprStates::TAwaitingMigrationAcceptedOrRejected, MeshMachine::TTag<MobilityMCprStates::KStartMobilityHandshake|EBackward>)
   116 NODEACTIVITY_END()
   116 NODEACTIVITY_END()
   117 }
   117 }
   118 
   118 
   119 namespace MCprConnectionStartRecoveryActivity
   119 namespace MCprConnectionStartRecoveryActivity
   162 	ACTIVITY_MAP_ENTRY(MCprConnectionStartRecoveryActivity,MCprConnectionStartRecovery)
   162 	ACTIVITY_MAP_ENTRY(MCprConnectionStartRecoveryActivity,MCprConnectionStartRecovery)
   163 	ACTIVITY_MAP_ENTRY(MCprConnectionGoneDownRecoveryActivity,MCprConnectionGoneDownRecovery)
   163 	ACTIVITY_MAP_ENTRY(MCprConnectionGoneDownRecoveryActivity,MCprConnectionGoneDownRecovery)
   164 ACTIVITY_MAP_END_BASE(MCprActivities, coreMCprActivities)
   164 ACTIVITY_MAP_END_BASE(MCprActivities, coreMCprActivities)
   165 }
   165 }
   166 
   166 
   167 ///////////////////////////////////////////////////////////////////////////////
   167 //
   168 // CMobilityActivity
   168 // CMobilityActivity
   169 MeshMachine::CNodeActivityBase* MobilityMCprActivities::CMobilityActivity::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode)
   169 MeshMachine::CNodeActivityBase* MobilityMCprActivities::CMobilityActivity::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode)
   170 	{
   170 	{
   171 	return new (ELeave) CMobilityActivity(aActivitySig, aNode);
   171 	return new (ELeave) CMobilityActivity(aActivitySig, aNode);
   172 	}
   172 	}
   208 	    //There's a couple of reasons why the activity may be in an error mode:
   208 	    //There's a couple of reasons why the activity may be in an error mode:
   209 	    //- rejection
   209 	    //- rejection
   210 	    //  - current bearer rejected;
   210 	    //  - current bearer rejected;
   211 	    //  - proposed bearer rejected;
   211 	    //  - proposed bearer rejected;
   212 	    //  - failure to migrate to the proposed bearer;
   212 	    //  - failure to migrate to the proposed bearer;
   213         lastRejected = iAvailable ? iAvailable :
   213         lastRejected = iPreferred ? iPreferred : 
   214                                     static_cast<RMetaServiceProviderInterface*>(aContext.Node().ServiceProvider());
   214                                     static_cast<RMetaServiceProviderInterface*>(aContext.Node().ServiceProvider()); 
   215 	    }
   215 	    }
   216 
   216 	
   217     iCandidate = iAvailable;
   217 	iPreferred = NULL; //Do not remember rejected candidate any longer
   218 	iAvailable = NULL; //Do not remember rejected candidate any longer
       
   219 	while ((candidate = static_cast<RMetaServiceProviderInterface*>(iter++)) != NULL)
   218 	while ((candidate = static_cast<RMetaServiceProviderInterface*>(iter++)) != NULL)
   220 		{
   219 		{
   221 		const TAvailabilityStatus& status = candidate->AvailabilityStatus();
   220 		const TAvailabilityStatus& status = candidate->AvailabilityStatus();
   222 		if (!status.IsKnown())
   221 		if (!status.IsKnown())
   223 			{
   222 			{
   228 			}
   227 			}
   229 
   228 
   230 		if (status.Score() > iAvailabilityScoreTreshold
   229 		if (status.Score() > iAvailabilityScoreTreshold
   231 			&& candidate!=lastRejected)
   230 			&& candidate!=lastRejected)
   232 			{
   231 			{
   233 			if (candidate==aContext.Node().ServiceProvider()
   232 			if (candidate->Flags() & TCFClientType::EStarted)
   234 			    && Error() == KErrNone )
       
   235 				{
   233 				{
   236 				//The preferred one is the current one, is still available and was not just rejected.
   234 				//The preferred one is the current one, is still available and was not just rejected.
   237 				//No need to do anything more.
   235 				//No need to do anything more.
   238 				return EFalse;
   236 				return EFalse;
   239 				}
   237 				}
   240 
   238 
   241 			//A new match found
   239 			//A new match found
   242 			iAvailable = candidate;
   240 			iPreferred = candidate;
   243 			return ETrue;
   241 			return ETrue;
   244 			}
   242 			}
   245 		}
   243 		}
   246 
   244 
   247 	//There is no choice for migration
   245 	//There is no choice for migration
   256 void CMobilityActivity::ClearHandshakingFlag()
   254 void CMobilityActivity::ClearHandshakingFlag()
   257 	{
   255 	{
   258 	static_cast<CMobilityMetaConnectionProvider&>(iNode).iIsHandshakingNow = EFalse;
   256 	static_cast<CMobilityMetaConnectionProvider&>(iNode).iIsHandshakingNow = EFalse;
   259 	}
   257 	}
   260 
   258 
   261 DEFINE_SMELEMENT(CMobilityActivity::TNoTagOrReConnectOrStartMobilityHandshakeBackwards, NetStateMachine::MStateFork, CMobilityActivity::TContext)
   259 DEFINE_SMELEMENT(CMobilityActivity::TNoTagOrStartMobilityHandshakeBackwards, NetStateMachine::MStateFork, CMobilityActivity::TContext)
   262 TInt CMobilityActivity::TNoTagOrReConnectOrStartMobilityHandshakeBackwards::TransitionTag()
   260 TInt CMobilityActivity::TNoTagOrStartMobilityHandshakeBackwards::TransitionTag()
   263 	{
   261 	{
   264 	if (iContext.Activity()->Error() == KErrNone &&
   262 	if (iContext.Activity()->Error() == KErrNone &&
   265 	    (message_cast<TCFMobilityProvider::TMigrationRequested>(&iContext.iMessage) ||
   263 	    (message_cast<TCFMobilityProvider::TMigrationRequested>(&iContext.iMessage) ||
   266 	     message_cast<TCFMcpr::TReConnectComplete>(&iContext.iMessage)))
   264 	     message_cast<TCFMcpr::TReConnectComplete>(&iContext.iMessage)))
   267 		{
   265 		{
   268 	        CMobilityActivity& activity = static_cast<CMobilityActivity&>(*iContext.iNodeActivity);
   266 		return MeshMachine::KNoTag | NetStateMachine::EForward;
   269 			if( activity.iCurrent!=activity.iAvailable )
       
   270 			    return MobilityMCprStates::KReConnect | NetStateMachine::EForward;
       
   271 			else
       
   272 		        return MeshMachine::KNoTag | NetStateMachine::EForward;
       
   273 		}
       
   274 	return MobilityMCprStates::KStartMobilityHandshake | NetStateMachine::EBackward;
       
   275 	}
       
   276 
       
   277 DEFINE_SMELEMENT(CMobilityActivity::TNoTagOrStartMobilityHandshakeBackwards, NetStateMachine::MStateFork, CMobilityActivity::TContext)
       
   278 TInt CMobilityActivity::TNoTagOrStartMobilityHandshakeBackwards::TransitionTag()
       
   279 	{
       
   280 	if (iContext.Activity()->Error() == KErrNone &&
       
   281 	    (message_cast<TCFMobilityProvider::TMigrationRequested>(&iContext.iMessage) ||
       
   282 	     message_cast<TCFMcpr::TReConnectComplete>(&iContext.iMessage)))
       
   283 		{
       
   284 			return MeshMachine::KNoTag | NetStateMachine::EForward;
       
   285 		}
   267 		}
   286 	return MobilityMCprStates::KStartMobilityHandshake | NetStateMachine::EBackward;
   268 	return MobilityMCprStates::KStartMobilityHandshake | NetStateMachine::EBackward;
   287 	}
   269 	}
   288 
   270 
   289 DEFINE_SMELEMENT(CMobilityActivity::TNoTagOrAwaitMobilityBackwardsOnMobilityTrigger, NetStateMachine::MStateFork, CMobilityActivity::TContext)
   271 DEFINE_SMELEMENT(CMobilityActivity::TNoTagOrAwaitMobilityBackwardsOnMobilityTrigger, NetStateMachine::MStateFork, CMobilityActivity::TContext)
   290 TInt CMobilityActivity::TNoTagOrAwaitMobilityBackwardsOnMobilityTrigger::TransitionTag()
   272 TInt CMobilityActivity::TNoTagOrAwaitMobilityBackwardsOnMobilityTrigger::TransitionTag()
   291 	{
   273 	{
   292 	//This is where the judgement is made on whether to trigger mobility (offer the client another bearer)
   274 	//This is where the judgement is made on whether to trigger mobility (offer the client another bearer)
   293 	//or ignore and come back waiting.
   275 	//or ignore and come back waiting. 
   294 	__ASSERT_DEBUG(iContext.iMessage.IsMessage<TCFMobilityProvider::TMigrationRejected>() ||
   276 	__ASSERT_DEBUG(iContext.iMessage.IsMessage<TCFMobilityProvider::TMigrationRejected>() ||
   295 			iContext.iMessage.IsMessage<TCFAvailabilityControlClient::TAvailabilityNotification>(),
   277 			iContext.iMessage.IsMessage<TCFAvailabilityControlClient::TAvailabilityNotification>(), 
   296 			User::Panic(KCoreMobileMCprPanic, KPanicIncorrectMessage));
   278 			User::Panic(KCoreMobileMCprPanic, KPanicIncorrectMessage));
   297 	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity));
   279 	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity));	
   298 	CMobilityActivity& activity = static_cast<CMobilityActivity&>(*iContext.iNodeActivity);
   280 	CMobilityActivity& activity = static_cast<CMobilityActivity&>(*iContext.iNodeActivity);
   299 
   281 	
   300 	if (activity.EvaluatePreference(iContext))
   282 	if (activity.EvaluatePreference(iContext))
   301 		{
   283 		{
   302         activity.SetError(KErrNone);
   284         activity.SetError(KErrNone);
   303 		return KNoTag;
   285 		return KNoTag;
   304 		}
   286 		}
   311 	}
   293 	}
   312 
   294 
   313 DEFINE_SMELEMENT(CMobilityActivity::TNoTagOrAwaitMobility, NetStateMachine::MStateFork, CMobilityActivity::TContext)
   295 DEFINE_SMELEMENT(CMobilityActivity::TNoTagOrAwaitMobility, NetStateMachine::MStateFork, CMobilityActivity::TContext)
   314 TInt CMobilityActivity::TNoTagOrAwaitMobility::TransitionTag()
   296 TInt CMobilityActivity::TNoTagOrAwaitMobility::TransitionTag()
   315 	{
   297 	{
   316 	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity));
   298 	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity));	
   317 	CMobilityActivity& activity = static_cast<CMobilityActivity&>(*iContext.iNodeActivity);
   299 	CMobilityActivity& activity = static_cast<CMobilityActivity&>(*iContext.iNodeActivity);
   318 
   300 	
   319 	if (activity.EvaluatePreference(iContext))
   301 	if (activity.EvaluatePreference(iContext))
   320 		{
   302 		{
   321 		activity.SetError(KErrNone);
   303 		activity.SetError(KErrNone);
   322 		return KNoTag;
   304 		return KNoTag;
   323 		}
   305 		}
   348 	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity));
   330 	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity));
   349 	CMobilityActivity& activity = static_cast<CMobilityActivity&>(*iContext.iNodeActivity);
   331 	CMobilityActivity& activity = static_cast<CMobilityActivity&>(*iContext.iNodeActivity);
   350 
   332 
   351 	//Inform the CPR that a potential migration is available. We only support a single data client
   333 	//Inform the CPR that a potential migration is available. We only support a single data client
   352 	//in this implementation.
   334 	//in this implementation.
   353 	__ASSERT_DEBUG(activity.iAvailable, User::Panic(KCoreMobileMCprPanic, KPanicNoServiceProvider));
   335 	__ASSERT_DEBUG(activity.iPreferred, User::Panic(KCoreMobileMCprPanic, KPanicNoServiceProvider));
   354 
   336 
   355 	//Compute all this here to keep EvaluatePreference() as fast as possible
   337 	//Compute all this here to keep EvaluatePreference() as fast as possible
   356 	activity.iCurrent = static_cast<RMetaServiceProviderInterface*>(iContext.Node().ServiceProvider());
   338 	activity.iCurrent = static_cast<RMetaServiceProviderInterface*>(iContext.Node().GetFirstClient<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EServProvider, TCFClientType::EStarted)));
   357 	__ASSERT_DEBUG(activity.iCurrent, User::Panic(KCoreMobileMCprPanic, KPanicNoServiceProvider));
   339 	__ASSERT_DEBUG(activity.iCurrent, User::Panic(KCoreMobileMCprPanic, KPanicNoServiceProvider));
   358 
   340 
   359 	//Perform a simple check if this is an upgrade or not
   341 	//Perform a simple check if this is an upgrade or not
   360 	TClientIter<TDefaultClientMatchPolicy> iter = iContext.Node().GetClientIter<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EServProvider));
   342 	TClientIter<TDefaultClientMatchPolicy> iter = iContext.Node().GetClientIter<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EServProvider));
   361 	RNodeInterface* sp = iter++;
   343 	RNodeInterface* sp = iter++;
   362 	while (sp && sp!=activity.iCurrent && sp!=activity.iAvailable)
   344 	while (sp && sp!=activity.iCurrent && sp!=activity.iPreferred)
   363 		{
   345 		{
   364 		sp = iter++;
   346 		sp = iter++;
   365 		}
   347 		}
   366 
   348 
   367 	TBool isUpgrade = (sp != activity.iCurrent); //If current was found first -> this is not an upgrade
   349 	TBool isUpgrade = (sp != activity.iCurrent); //If current was found first -> this is not an upgrade
   368 	if( activity.iCurrent == activity.iAvailable && activity.iCandidate )
   350 	TCFMobilityControlClient::TMigrationNotification msg(activity.iCurrent->ProviderInfo().APId(),
   369 	    {
   351 	                                       activity.iPreferred->ProviderInfo().APId(),
   370 		// The available client is the same as the current and a candidate exists, this indicates that
   352 	                                       isUpgrade, EFalse);
   371 		// an error has occured when trying to start the candidate bearer and the control as reverted to
   353 
   372 		// the current bearer. In this situation the notification needs to look as if the bearer has
   354 	activity.PostToOriginators(msg);
   373 		// migrated from the failed candidate to the current bearer.
       
   374 		TCFMobilityControlClient::TMigrationNotification msg(activity.iCandidate->ProviderInfo().APId(),
       
   375 											   activity.iAvailable->ProviderInfo().APId(),
       
   376 											   isUpgrade, EFalse);
       
   377 		activity.PostToOriginators(msg);
       
   378 	    }
       
   379 	else
       
   380 	    {
       
   381 		// Standard case where migration is going from current to available.
       
   382 		TCFMobilityControlClient::TMigrationNotification msg(activity.iCurrent->ProviderInfo().APId(),
       
   383 											   activity.iAvailable->ProviderInfo().APId(),
       
   384 											   isUpgrade, EFalse);
       
   385 		activity.PostToOriginators(msg);
       
   386 	    }
       
   387 
       
   388 	activity.ClearPostedTo();
   355 	activity.ClearPostedTo();
   389 	activity.SetHandshakingFlag();
   356 	activity.SetHandshakingFlag();
   390 	}
   357 	}
   391 
   358 
   392 
   359 
   406 void CMobilityActivity::TRequestReConnect::DoL()
   373 void CMobilityActivity::TRequestReConnect::DoL()
   407 	{
   374 	{
   408 	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity));
   375 	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity));
   409 	CMobilityActivity& activity = static_cast<CMobilityActivity&>(*iContext.iNodeActivity);
   376 	CMobilityActivity& activity = static_cast<CMobilityActivity&>(*iContext.iNodeActivity);
   410 
   377 
   411 	__ASSERT_DEBUG(activity.iAvailable, User::Panic(KCoreMobileMCprPanic, KPanicNoServiceProvider));
   378 	__ASSERT_DEBUG(activity.iPreferred, User::Panic(KCoreMobileMCprPanic, KPanicNoServiceProvider));
   412 	__ASSERT_DEBUG(activity.iCurrent, User::Panic(KCoreMobileMCprPanic, KPanicNoServiceProvider));
   379 	__ASSERT_DEBUG(activity.iCurrent, User::Panic(KCoreMobileMCprPanic, KPanicNoServiceProvider));
   413 	__ASSERT_DEBUG(activity.iCurrent!=activity.iAvailable, User::Panic(KSpecAssert_ESockMbCrMCPRAct, 1));
   380 	__ASSERT_DEBUG(activity.iCurrent!=activity.iPreferred, User::Panic(KSpecAssert_ESockMbCrMCPRAct, 1));
   414 
   381 
   415 	// For the moment it is sufficient to use the re-connect activity, in the future we may want to
   382 	// For the moment it is sufficient to use the re-connect activity, in the future we may want to
   416 	// customise the behavior, for example start the new layer before rebinding it, etc.
   383 	// customise the behavior, for example start the new layer before rebinding it, etc.
   417 	TCFMcpr::TReConnect msg(activity.iCurrent->RecipientId(), activity.iAvailable->RecipientId());
   384 	TCFMcpr::TReConnect msg(activity.iCurrent->RecipientId(), activity.iPreferred->RecipientId());
   418 	activity.PostRequestTo(iContext.NodeId(), msg);
   385 	activity.PostRequestTo(iContext.NodeId(), msg);
   419 	}
   386 	}
   420 
   387 
   421 DEFINE_SMELEMENT(CMobilityActivity::TInformMigrationCompleted, NetStateMachine::MStateTransition, CMobilityActivity::TContext)
   388 DEFINE_SMELEMENT(CMobilityActivity::TInformMigrationCompleted, NetStateMachine::MStateTransition, CMobilityActivity::TContext)
   422 void CMobilityActivity::TInformMigrationCompleted::DoL()
   389 void CMobilityActivity::TInformMigrationCompleted::DoL()
   433 	CMobilityActivity& activity = static_cast<CMobilityActivity&>(*iContext.iNodeActivity);
   400 	CMobilityActivity& activity = static_cast<CMobilityActivity&>(*iContext.iNodeActivity);
   434 	activity.ClearHandshakingFlag();
   401 	activity.ClearHandshakingFlag();
   435 	}
   402 	}
   436 
   403 
   437 
   404 
   438 ///////////////////////////////////////////////////////////////////////////////
   405 //
   439 //CConnectionRecoveryActivity
   406 //CConnectionRecoveryActivity
   440 MeshMachine::CNodeActivityBase* CConnectionRecoveryActivity::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode)
   407 MeshMachine::CNodeActivityBase* CConnectionRecoveryActivity::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode)
   441 	{
   408 	{
   442 	return new (ELeave) CConnectionRecoveryActivity(aActivitySig, aNode);
   409 	return new (ELeave) CConnectionRecoveryActivity(aActivitySig, aNode);
   443 	}
   410 	}
   499 
   466 
   500 DEFINE_SMELEMENT(CConnectionRecoveryActivity::TProcessConnectionStartRecoveryRequest, NetStateMachine::MStateTransition, CConnectionRecoveryActivity::TContext)
   467 DEFINE_SMELEMENT(CConnectionRecoveryActivity::TProcessConnectionStartRecoveryRequest, NetStateMachine::MStateTransition, CConnectionRecoveryActivity::TContext)
   501 void CConnectionRecoveryActivity::TProcessConnectionStartRecoveryRequest::DoL()
   468 void CConnectionRecoveryActivity::TProcessConnectionStartRecoveryRequest::DoL()
   502 	{
   469 	{
   503 	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity));
   470 	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity));
   504 	RNodeInterface* newSP = NULL;
   471 	RNodeInterface* startingSP = NULL;
   505 	RNodeInterface* curSP = iContext.Node().ServiceProvider(); //Our current started Service Provider.
   472 	RNodeInterface* stoppingSP = NULL;
   506 
   473 
   507 	//Choose Service Providers to work on
   474 	//Choose Service Providers to work on
   508 	TClientIter<TDefaultClientMatchPolicy> iter = iContext.Node().GetClientIter<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EServProvider));
   475 	TClientIter<TDefaultClientMatchPolicy> iter = iContext.Node().GetClientIter<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EServProvider));
   509 	RNodeInterface* itf = NULL;
   476 	RNodeInterface* itf = NULL;
   510 	for (itf = iter++; itf!=NULL && newSP==NULL; itf = iter++)
   477 	for (itf = iter++; itf!=NULL && stoppingSP==NULL; itf = iter++)
   511 		{
   478 		{
   512 		if (itf==curSP)
   479 		if (itf->Flags() & TCFClientType::EStarted)
   513 			{
   480 			{
   514 			newSP = iter++; //And the new one to try next
   481 			stoppingSP = itf; //Our current started Service Provider.
       
   482 			startingSP = iter++; //And the new one to try next
   515 			}
   483 			}
   516 		}
   484 		}
   517 
   485 
   518 	//Sanity check.
   486 	//Sanity check.
   519 	//The new provider must not be started, there can be only one started at a time.
   487 	//The new provider must not be started, there can be only one started at a time.
   520 	__ASSERT_DEBUG(newSP==NULL || (newSP->Flags() & TCFClientType::EStarted)==0, User::Panic(KSpecAssert_ESockMbCrMCPRAct, 3));
   488 	__ASSERT_DEBUG(startingSP==NULL || (startingSP->Flags() & TCFClientType::EStarted)==0, User::Panic(KSpecAssert_ESockMbCrMCPRAct, 3));
   521 
   489 
   522 	//If there is no other Service Provider to try, return KErrNotFound
   490 	//If there is no other Service Provider to try, return KErrNotFound
   523 	if (newSP==NULL || curSP == NULL)
   491 	if (startingSP==NULL || stoppingSP == NULL)
   524 		{
   492 		{
   525 #ifdef __CFLOG_ACTIVE
   493 #ifdef __CFLOG_ACTIVE
   526 		__CFLOG_VAR((KCoreMCprStatesTag, KCoreMCprStatesSubTag, _L8("WARNING: CConnectionRecoveryActivity::TProcessConnectionStartRecoveryRequest::DoL() - no more choices, abandoning recovery.")));
   494 		__CFLOG_VAR((KCoreMCprStatesTag, KCoreMCprStatesSubTag, _L8("WARNING: CConnectionRecoveryActivity::TProcessConnectionStartRecoveryRequest::DoL() - no more choices, abandoning recovery.")));
   527 #endif
   495 #endif
   528 		User::Leave(KErrNotFound);
   496 		User::Leave(KErrNotFound);
   529 		}
   497 		}
   530 
   498 
   531 	//Diagnostinc - there must be a data client or we cannot be here
   499 	//Diagnostinc - there must be a data client or we cannot be here
   532 	__ASSERT_DEBUG(iContext.Node().GetFirstClient<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EData)), User::Panic(KCoreMobileMCprPanic, KPanicNoDataClient));
   500 	__ASSERT_DEBUG(iContext.Node().GetFirstClient<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EData)), User::Panic(KCoreMobileMCprPanic, KPanicNoDataClient));
   533 	iContext.iNodeActivity->PostRequestTo(iContext.NodeId(),
   501 	iContext.iNodeActivity->PostRequestTo(iContext.NodeId(),
   534 			TCFMcpr::TReConnect(curSP->RecipientId(), newSP->RecipientId()).CRef());
   502 			TCFMcpr::TReConnect(stoppingSP->RecipientId(), startingSP->RecipientId()).CRef());
   535 	}
   503 	}
   536 
   504 
   537 DEFINE_SMELEMENT(CConnectionRecoveryActivity::TProcessConnectionGoneDownRecoveryRequest, NetStateMachine::MStateTransition, CConnectionRecoveryActivity::TContext)
   505 DEFINE_SMELEMENT(CConnectionRecoveryActivity::TProcessConnectionGoneDownRecoveryRequest, NetStateMachine::MStateTransition, CConnectionRecoveryActivity::TContext)
   538 void CConnectionRecoveryActivity::TProcessConnectionGoneDownRecoveryRequest::DoL()
   506 void CConnectionRecoveryActivity::TProcessConnectionGoneDownRecoveryRequest::DoL()
   539 	{
   507 	{
   540 	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity));
   508 	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity));
   541 	CConnectionRecoveryActivity& activity = static_cast<CConnectionRecoveryActivity&>(*iContext.iNodeActivity);
   509 	CConnectionRecoveryActivity& activity = static_cast<CConnectionRecoveryActivity&>(*iContext.iNodeActivity);
   542 
   510 
   543 	RNodeInterface* started = iContext.Node().ServiceProvider();
   511 	RNodeInterface* started = iContext.Node().GetFirstClient<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EServProvider, TCFClientType::EStarted));
   544 	TUint apId = (TUint)activity.iOriginalErrContext.iInfo;
   512 	TUint apId = (TUint)activity.iOriginalErrContext.iInfo;
   545 	RNodeInterface* gonedownsp = iContext.Node().FindServiceProvider(apId);
   513 	RNodeInterface* gonedownsp = iContext.Node().FindServiceProvider(apId);
   546 	if (started && started != gonedownsp)
   514 	if (started && started != gonedownsp)
   547 		{
   515 		{
   548 		CConnectionRecoveryActivity::TSendRetryRecoveryResponse tr(iContext);
   516 		CConnectionRecoveryActivity::TSendRetryRecoveryResponse tr(iContext);