--- a/datacommsserver/esockserver/MobilityCoreProviders/src/mobilitymcpractivities.cpp Mon Mar 15 12:45:15 2010 +0200
+++ b/datacommsserver/esockserver/MobilityCoreProviders/src/mobilitymcpractivities.cpp Wed Mar 31 23:27:09 2010 +0300
@@ -15,7 +15,7 @@
#include <elements/nm_messages_errorrecovery.h>
#include <comms-infras/ss_coreprstates.h>
-#include "mobilitymcpractivities.h"
+#include <comms-infras/mobilitymcpractivities.h>
#include <comms-infras/mobilitymcprstates.h>
#include <comms-infras/ss_nodemessages_selector.h>
#include <comms-infras/ss_nodemessages_mobility.h>
@@ -87,7 +87,7 @@
//if it sees that the availability notification has influcenced what the currently preffered bearer should be.
THROUGH_NODEACTIVITY_ENTRY(KNoTag, CMobilityActivity::TSendAvailabilityRequest, MeshMachine::TTag<MobilityMCprStates::KStartMobilityHandshake>)
- //<BEGIN> MAIN LOOP ****************
+ //<BEGIN> MAIN LOOP ****************
//The main mobility handshake loop. The loop is executed when performing migration from one service provider to another.
//The entry condition for the loop is that:
//- upgrade: a better then current access point is now available (a better access point reported available)
@@ -97,23 +97,25 @@
// NOTE: if the current bearer ceases to be available completely (goes down), then this will be assisted by an error recovery request;
// NOTE: This tuple doesn't actually do (b), i.e.: assumes the threshold of '1' (in 0..100 availability score range)
//Before awaitng for availability change or rejection by the client (TAwaitingCurrentCarrierRejectedOrAvailabilityChange), the activity
- //first checks (TNoTagOrAwaitMobilityBlockedByErrorRecovery) if the availability has changed since it last checked
- //(availability could have been reported amidst the previous handshake loop)
+ //first checks (TNoTagOrAwaitMobilityBlockedByErrorRecovery) if the availability has changed since it last checked
+ //(availability could have been reported amidst the previous handshake loop)
THROUGH_NODEACTIVITY_ENTRY(MobilityMCprStates::KStartMobilityHandshake, CMobilityActivity::TClearHandshakingFlag, CMobilityActivity::TNoTagOrAwaitMobilityBlockedByErrorRecovery)
NODEACTIVITY_ENTRY(MobilityMCprStates::KAwaitMobility, MeshMachine::TDoNothing, CMobilityActivity::TAwaitingCurrentCarrierRejectedOrAvailabilityChange, CMobilityActivity::TNoTagOrAwaitMobilityBackwardsOnMobilityTriggerBlockedByErrorRecovery)
- //Mobility has been triggered ((a) or (b)). Start mobility handshake (set handshaking flag and inform the client about the preferred bearer)
- NODEACTIVITY_ENTRY(KNoTag, CMobilityActivity::TInformMigrationAvailableAndSetHandshakingFlag, MobilityMCprStates::TAwaitingMigrationRequestedOrRejected, CMobilityActivity::TNoTagOrStartMobilityHandshakeBackwards)
+ //Mobility has been triggered ((a) or (b)). Start mobility handshake (set handshaking flag and inform the client about the preferred bearer)
+ //ReConnect only needs to be done if the bearer is different from the curret bearer.
+ NODEACTIVITY_ENTRY(KNoTag, CMobilityActivity::TInformMigrationAvailableAndSetHandshakingFlag, MobilityMCprStates::TAwaitingMigrationRequestedOrRejected, CMobilityActivity::TNoTagOrReConnectOrStartMobilityHandshakeBackwards)
+ //The client accepts the new access point.
//The client accepts the new access point.
//For the moment it is sufficient to use the re-connect activity, in the future we may want to
//customise the behavior, for example start the new layer before rebinding it, etc.
//Should rebinding fail, the mobility activity will be set to an error mode. The error mode will be cleared if
//there are other bearers this activity can offer. If there aren't the data client will be errored.
- NODEACTIVITY_ENTRY(KNoTag, CMobilityActivity::TRequestReConnect, MCprStates::TAwaitingReConnectCompleteOrError, CMobilityActivity::TNoTagOrStartMobilityHandshakeBackwards)
+ NODEACTIVITY_ENTRY(MobilityMCprStates::KReConnect, CMobilityActivity::TRequestReConnect, MCprStates::TAwaitingReConnectCompleteOrError, CMobilityActivity::TNoTagOrStartMobilityHandshakeBackwards)
//Rebinding has been successful. As far as MCPR is concerned, the mobility is finished, but the MCPR must await
- //for the handshake (accept|reject) before it can offer another bearer.
- NODEACTIVITY_ENTRY(KNoTag, CMobilityActivity::TInformMigrationCompleted, MobilityMCprStates::TAwaitingMigrationAcceptedOrRejected, CMobilityActivity::TRejectedOrStartMobilityHandshakeBackwards)
- NODEACTIVITY_ENTRY(MobilityMCprStates::KRejected, CoreNetStates::TStopDataClients, CoreNetStates::TAwaitingDataClientsStopped, MeshMachine::TTag<MobilityMCprStates::KStartMobilityHandshake|NetStateMachine::EBackward>)
+ //for the handshake (accept|reject) before it can offer another bearer.
+ NODEACTIVITY_ENTRY(KNoTag, CMobilityActivity::TInformMigrationCompleted, MobilityMCprStates::TAwaitingMigrationAcceptedOrRejected, CMobilityActivity::TRejectedOrStartMobilityHandshakeBackwards)
+ NODEACTIVITY_ENTRY(MobilityMCprStates::KRejected, CoreNetStates::TStopDataClients, CoreNetStates::TAwaitingDataClientsStopped, MeshMachine::TTag<MobilityMCprStates::KStartMobilityHandshake|NetStateMachine::EBackward>)
NODEACTIVITY_END()
}
@@ -211,11 +213,12 @@
// - current bearer rejected;
// - proposed bearer rejected;
// - failure to migrate to the proposed bearer;
- lastRejected = iPreferred ? iPreferred :
- static_cast<RMetaServiceProviderInterface*>(aContext.Node().ServiceProvider());
+ lastRejected = iAvailable ? iAvailable :
+ static_cast<RMetaServiceProviderInterface*>(aContext.Node().ServiceProvider());
}
-
- iPreferred = NULL; //Do not remember rejected candidate any longer
+
+ iCandidate = iAvailable;
+ iAvailable = NULL; //Do not remember rejected candidate any longer
while ((candidate = static_cast<RMetaServiceProviderInterface*>(iter++)) != NULL)
{
const TAvailabilityStatus& status = candidate->AvailabilityStatus();
@@ -230,7 +233,8 @@
if (status.Score() > iAvailabilityScoreTreshold
&& candidate!=lastRejected)
{
- if (candidate->Flags() & TCFClientType::EStarted)
+ if (candidate==aContext.Node().ServiceProvider()
+ && Error() == KErrNone )
{
//The preferred one is the current one, is still available and was not just rejected.
//No need to do anything more.
@@ -238,7 +242,7 @@
}
//A new match found
- iPreferred = candidate;
+ iAvailable = candidate;
return ETrue;
}
}
@@ -257,6 +261,22 @@
static_cast<CMobilityMetaConnectionProvider&>(iNode).iIsHandshakingNow = EFalse;
}
+DEFINE_SMELEMENT(CMobilityActivity::TNoTagOrReConnectOrStartMobilityHandshakeBackwards, NetStateMachine::MStateFork, CMobilityActivity::TContext)
+TInt CMobilityActivity::TNoTagOrReConnectOrStartMobilityHandshakeBackwards::TransitionTag()
+ {
+ if (iContext.Activity()->Error() == KErrNone &&
+ (message_cast<TCFMobilityProvider::TMigrationRequested>(&iContext.iMessage) ||
+ message_cast<TCFMcpr::TReConnectComplete>(&iContext.iMessage)))
+ {
+ CMobilityActivity& activity = static_cast<CMobilityActivity&>(*iContext.iNodeActivity);
+ if( activity.iCurrent!=activity.iAvailable )
+ return MobilityMCprStates::KReConnect | NetStateMachine::EForward;
+ else
+ return MeshMachine::KNoTag | NetStateMachine::EForward;
+ }
+ return MobilityMCprStates::KStartMobilityHandshake | NetStateMachine::EBackward;
+ }
+
DEFINE_SMELEMENT(CMobilityActivity::TNoTagOrStartMobilityHandshakeBackwards, NetStateMachine::MStateFork, CMobilityActivity::TContext)
TInt CMobilityActivity::TNoTagOrStartMobilityHandshakeBackwards::TransitionTag()
{
@@ -273,13 +293,13 @@
TInt CMobilityActivity::TNoTagOrAwaitMobilityBackwardsOnMobilityTrigger::TransitionTag()
{
//This is where the judgement is made on whether to trigger mobility (offer the client another bearer)
- //or ignore and come back waiting.
+ //or ignore and come back waiting.
__ASSERT_DEBUG(iContext.iMessage.IsMessage<TCFMobilityProvider::TMigrationRejected>() ||
- iContext.iMessage.IsMessage<TCFAvailabilityControlClient::TAvailabilityNotification>(),
+ iContext.iMessage.IsMessage<TCFAvailabilityControlClient::TAvailabilityNotification>(),
User::Panic(KCoreMobileMCprPanic, KPanicIncorrectMessage));
- __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity));
+ __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity));
CMobilityActivity& activity = static_cast<CMobilityActivity&>(*iContext.iNodeActivity);
-
+
if (activity.EvaluatePreference(iContext))
{
activity.SetError(KErrNone);
@@ -296,9 +316,9 @@
DEFINE_SMELEMENT(CMobilityActivity::TNoTagOrAwaitMobility, NetStateMachine::MStateFork, CMobilityActivity::TContext)
TInt CMobilityActivity::TNoTagOrAwaitMobility::TransitionTag()
{
- __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity));
+ __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity));
CMobilityActivity& activity = static_cast<CMobilityActivity&>(*iContext.iNodeActivity);
-
+
if (activity.EvaluatePreference(iContext))
{
activity.SetError(KErrNone);
@@ -323,20 +343,20 @@
if (iContext.iMessage.IsMessage<TCFMobilityProvider::TMigrationRejected>())
{
TBool otherSP = EFalse;
-
+
// Find if there anymore available non rejected service providers
TClientIter<TDefaultClientMatchPolicy> iter = iContext.Node().GetClientIter<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EServProvider));
__ASSERT_DEBUG(iter[0], User::Panic(KCoreMobileMCprPanic, KPanicNoServiceProvider)); //A Service Provider must exist!
RMetaServiceProviderInterface* rejected = static_cast<RMetaServiceProviderInterface*>(iContext.Node().ServiceProvider());
RMetaServiceProviderInterface* candidate = NULL;
-
+
while ((candidate = static_cast<RMetaServiceProviderInterface*>(iter++)) != NULL)
{
if (candidate == rejected)
{
continue;
}
-
+
const TAvailabilityStatus& status = candidate->AvailabilityStatus();
if (!status.IsKnown())
{
@@ -380,31 +400,45 @@
//Inform the CPR that a potential migration is available. We only support a single data client
//in this implementation.
- __ASSERT_DEBUG(activity.iPreferred, User::Panic(KCoreMobileMCprPanic, KPanicNoServiceProvider));
+ __ASSERT_DEBUG(activity.iAvailable, User::Panic(KCoreMobileMCprPanic, KPanicNoServiceProvider));
//Compute all this here to keep EvaluatePreference() as fast as possible
- activity.iCurrent = static_cast<RMetaServiceProviderInterface*>(iContext.Node().GetFirstClient<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EServProvider, TCFClientType::EStarted)));
+ activity.iCurrent = static_cast<RMetaServiceProviderInterface*>(iContext.Node().ServiceProvider());
__ASSERT_DEBUG(activity.iCurrent, User::Panic(KCoreMobileMCprPanic, KPanicNoServiceProvider));
//Perform a simple check if this is an upgrade or not
TClientIter<TDefaultClientMatchPolicy> iter = iContext.Node().GetClientIter<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EServProvider));
RNodeInterface* sp = iter++;
- while (sp && sp!=activity.iCurrent && sp!=activity.iPreferred)
+ while (sp && sp!=activity.iCurrent && sp!=activity.iAvailable)
{
sp = iter++;
}
TBool isUpgrade = (sp != activity.iCurrent); //If current was found first -> this is not an upgrade
- TCFMobilityControlClient::TMigrationNotification msg(activity.iCurrent->ProviderInfo().APId(),
- activity.iPreferred->ProviderInfo().APId(),
- isUpgrade, EFalse);
+ if( activity.iCurrent == activity.iAvailable && activity.iCandidate )
+ {
+ // The available client is the same as the current and a candidate exists, this indicates that
+ // an error has occured when trying to start the candidate bearer and the control as reverted to
+ // the current bearer. In this situation the notification needs to look as if the bearer has
+ // migrated from the failed candidate to the current bearer.
+ TCFMobilityControlClient::TMigrationNotification msg(activity.iCandidate->ProviderInfo().APId(),
+ activity.iAvailable->ProviderInfo().APId(),
+ isUpgrade, EFalse);
+ activity.PostToOriginators(msg);
+ }
+ else
+ {
+ // Standard case where migration is going from current to available.
+ TCFMobilityControlClient::TMigrationNotification msg(activity.iCurrent->ProviderInfo().APId(),
+ activity.iAvailable->ProviderInfo().APId(),
+ isUpgrade, EFalse);
+ activity.PostToOriginators(msg);
+ }
- activity.PostToOriginators(msg);
activity.ClearPostedTo();
activity.SetHandshakingFlag();
}
-
DEFINE_SMELEMENT(CMobilityActivity::TAwaitingCurrentCarrierRejectedOrAvailabilityChange, NetStateMachine::MState, CMobilityActivity::TContext)
TBool CMobilityActivity::TAwaitingCurrentCarrierRejectedOrAvailabilityChange::Accept()
{
@@ -423,13 +457,13 @@
__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity));
CMobilityActivity& activity = static_cast<CMobilityActivity&>(*iContext.iNodeActivity);
- __ASSERT_DEBUG(activity.iPreferred, User::Panic(KCoreMobileMCprPanic, KPanicNoServiceProvider));
+ __ASSERT_DEBUG(activity.iAvailable, User::Panic(KCoreMobileMCprPanic, KPanicNoServiceProvider));
__ASSERT_DEBUG(activity.iCurrent, User::Panic(KCoreMobileMCprPanic, KPanicNoServiceProvider));
- __ASSERT_DEBUG(activity.iCurrent!=activity.iPreferred, User::Panic(KSpecAssert_ESockMbCrMCPRAct, 1));
+ __ASSERT_DEBUG(activity.iCurrent!=activity.iAvailable, User::Panic(KSpecAssert_ESockMbCrMCPRAct, 1));
// For the moment it is sufficient to use the re-connect activity, in the future we may want to
// customise the behavior, for example start the new layer before rebinding it, etc.
- TCFMcpr::TReConnect msg(activity.iCurrent->RecipientId(), activity.iPreferred->RecipientId());
+ TCFMcpr::TReConnect msg(activity.iCurrent->RecipientId(), activity.iAvailable->RecipientId());
activity.PostRequestTo(iContext.NodeId(), msg);
}
@@ -516,27 +550,26 @@
void CConnectionRecoveryActivity::TProcessConnectionStartRecoveryRequest::DoL()
{
__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity));
- RNodeInterface* startingSP = NULL;
- RNodeInterface* stoppingSP = NULL;
+ RNodeInterface* newSP = NULL;
+ RNodeInterface* curSP = iContext.Node().ServiceProvider(); //Our current started Service Provider.
//Choose Service Providers to work on
TClientIter<TDefaultClientMatchPolicy> iter = iContext.Node().GetClientIter<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EServProvider));
RNodeInterface* itf = NULL;
- for (itf = iter++; itf!=NULL && stoppingSP==NULL; itf = iter++)
+ for (itf = iter++; itf!=NULL && newSP==NULL; itf = iter++)
{
- if (itf->Flags() & TCFClientType::EStarted)
+ if (itf==curSP)
{
- stoppingSP = itf; //Our current started Service Provider.
- startingSP = iter++; //And the new one to try next
+ newSP = iter++; //And the new one to try next
}
}
//Sanity check.
//The new provider must not be started, there can be only one started at a time.
- __ASSERT_DEBUG(startingSP==NULL || (startingSP->Flags() & TCFClientType::EStarted)==0, User::Panic(KSpecAssert_ESockMbCrMCPRAct, 3));
+ __ASSERT_DEBUG(newSP==NULL || (newSP->Flags() & TCFClientType::EStarted)==0, User::Panic(KSpecAssert_ESockMbCrMCPRAct, 3));
//If there is no other Service Provider to try, return KErrNotFound
- if (startingSP==NULL || stoppingSP == NULL)
+ if (newSP==NULL || curSP == NULL)
{
#ifdef __CFLOG_ACTIVE
__CFLOG_VAR((KCoreMCprStatesTag, KCoreMCprStatesSubTag, _L8("WARNING: CConnectionRecoveryActivity::TProcessConnectionStartRecoveryRequest::DoL() - no more choices, abandoning recovery.")));
@@ -547,7 +580,7 @@
//Diagnostinc - there must be a data client or we cannot be here
__ASSERT_DEBUG(iContext.Node().GetFirstClient<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EData)), User::Panic(KCoreMobileMCprPanic, KPanicNoDataClient));
iContext.iNodeActivity->PostRequestTo(iContext.NodeId(),
- TCFMcpr::TReConnect(stoppingSP->RecipientId(), startingSP->RecipientId()).CRef());
+ TCFMcpr::TReConnect(curSP->RecipientId(), newSP->RecipientId()).CRef());
}
DEFINE_SMELEMENT(CConnectionRecoveryActivity::TProcessConnectionGoneDownRecoveryRequest, NetStateMachine::MStateTransition, CConnectionRecoveryActivity::TContext)
@@ -556,7 +589,7 @@
__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileMCprPanic, KPanicNoActivity));
CConnectionRecoveryActivity& activity = static_cast<CConnectionRecoveryActivity&>(*iContext.iNodeActivity);
- RNodeInterface* started = iContext.Node().GetFirstClient<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EServProvider, TCFClientType::EStarted));
+ RNodeInterface* started = iContext.Node().ServiceProvider();
TUint apId = (TUint)activity.iOriginalErrContext.iInfo;
RNodeInterface* gonedownsp = iContext.Node().FindServiceProvider(apId);
if (started && started != gonedownsp)