datacommsserver/esockserver/MobilityCoreProviders/src/mobilitycpractivities.cpp
changeset 0 dfb7c4ff071f
child 2 dee179edb159
equal deleted inserted replaced
-1:000000000000 0:dfb7c4ff071f
       
     1 // Copyright (c) 2007-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 // mobilityactivities.cpp
       
    15 // Mobility Connection Provider activity definitions.
       
    16 //
       
    17 //
       
    18 //
       
    19 
       
    20 /**
       
    21  @file
       
    22  @internalComponent
       
    23 */
       
    24 
       
    25 #include <comms-infras/mobilitycpr.h>
       
    26 #include "mobilitycpractivities.h"
       
    27 #include <comms-infras/mobilitycprstates.h>
       
    28 #include <comms-infras/ss_coreprstates.h>
       
    29 
       
    30 #include <comms-infras/ss_nodemessages.h>
       
    31 #include <comms-infras/corecpractivities.h>
       
    32 #include <elements/nm_messages_errorrecovery.h>
       
    33 
       
    34 
       
    35 #ifdef _DEBUG
       
    36 // Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module
       
    37 // (if it could happen through user error then you should give it an explicit, documented, category + code)
       
    38 _LIT(KSpecAssert_ESockMbCrCPRAct, "ESockMbCrCPRAct");
       
    39 #endif
       
    40 
       
    41 
       
    42 using namespace ESock;
       
    43 using namespace Messages;
       
    44 using namespace MeshMachine;
       
    45 using namespace NetStateMachine;
       
    46 using namespace MobilityCprActivities;
       
    47 using namespace MobilityCprStates;
       
    48 using namespace CorePanics;
       
    49 
       
    50 //
       
    51 //Panics
       
    52 #ifdef _DEBUG
       
    53 _LIT (KCoreMobileCprPanic,"CoreMobileCprPanic");
       
    54 #endif
       
    55 
       
    56 namespace CprMobilityActivity
       
    57 {
       
    58 /**
       
    59 	Activity responsible for interacting with the ESock client mobility extension
       
    60 	API and with the MCPR for the acceptance or rejection of requests to migrate
       
    61 	bearer.
       
    62 */
       
    63 DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityCprMobility, MobilityCprMobility, TCFMobilityProvider::TStartMobility, CMobilityActivity::NewL)
       
    64 	FIRST_NODEACTIVITY_ENTRY(MobilityCprStates::TAwaitingStartMobility, MeshMachine::TNoTag)
       
    65 
       
    66 	// Attempt to start mobility activity on the meta plane
       
    67 	NODEACTIVITY_ENTRY(KNoTag, MobilityCprStates::TSendStartMobility, MobilityCprStates::TAwaitingMobilityStartedOrError, MeshMachine::TNoTagOrErrorTag)
       
    68 
       
    69 	// Success - complete the IPC client
       
    70 	THROUGH_NODEACTIVITY_ENTRY(KNoTag, CMobilityActivity::TCompleteMobilityClient, TTag<CMobilityActivity::KWaitForMobility>)
       
    71 
       
    72 	//<BEGIN> MAIN LOOP ****************
       
    73 	//Awaiting mobility triggers, which can either be:
       
    74 	//(1) TMigrationNotification (PreferredCarrierAvailable) coming from the control provider (presumably as a response to changing availability)
       
    75 	//(2) TMigrationRejected (NewCarrierRejected) coming from the control client (who's presumably not content with the currently offered carrier).
       
    76 	//(3) TError coming from the control provider in response to the previous rejection. The client rejected the current bearer, but there are no more bearers to offer.
       
    77 	NODEACTIVITY_ENTRY(CMobilityActivity::KWaitForMobility, MeshMachine::TDoNothing, MobilityCprStates::TAwaitingNewCarrierOrErrorOrRelayAndConsumeCurrentCarrierRejected, CMobilityActivity::TStartHandshakeOrErrorTagBlockedByClientNotReady)
       
    78 
       
    79 		// Notify the ESock client that a preferred carrier is available and await the client to respond
       
    80 		// The response may be:
       
    81 		// (1) TCFMobilityProvider::TMigrationRequested - proceed with the migration - the tuple will jump (with KNoTag) to await for the control provider to supply the new bearer.
       
    82  		// (2) TCFMobilityProvider::TMigrationRejected - abort the migration - the tuple will jump (with KWaitForMobility | EBackaward) back to awaiting for the preferred bearer.
       
    83  		// Note that TAwaitAndRelayMigrationRequestedOrMigrationRejected does the job of forwarding both messages to the control provider.
       
    84 		NODEACTIVITY_ENTRY(CMobilityActivity::KStartHandshake, CMobilityActivity::TNotifyClientPreferredCarrierAvailable, MobilityCprStates::TAwaitAndRelayMigrationRequestedOrMigrationRejected, CMobilityActivity::TNoTagOrWaitForMobilityBackwards)
       
    85 
       
    86 		//We've just told the control provider (see above: TAwaitAndRelayMigrationRequested...) that the offered carrier has been accepted - the client is requesting migration.
       
    87 		//The control provider may respond threefold:
       
    88 		//(1) TMigrationComplete - Proceed with the migration - the tuple will jump (with KNoTag) to starting of the bearer;
       
    89 		//(2) TMigrationNotification - offer another bearer (if the current one became out of date) - the tuple will jump back to the processing of the new bearer
       
    90 		//(3) TError - abort mobility if the current bearer is out of date and there are no more bearers to offer - the tuple will jump to the KErrorTag tuple who will decide what kind of error it is.
       
    91 		NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing, MobilityCprStates::TAwaitingMigrationCompleteOrNewCarrierOrError, MobilityCprStates::TNoTagOrStartHandshakeBackwardsOrError)
       
    92 		THROUGH_NODEACTIVITY_ENTRY(KErrorTag, CMobilityActivity::TCompleteMobilityClient, MeshMachine::TTag<CMobilityActivity::KWaitForMobility|EBackward>)
       
    93 
       
    94 		// Start the new connection
       
    95 		NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TStartServiceProvider, MobilityCprStates::TAwaitingStartedOrError, CMobilityActivity::TNoTagOrErrorTagBlockedByClientNotReady)
       
    96 		NODEACTIVITY_ENTRY(KErrorTag, TSendErrorRecoveryReq, MeshMachine::TAwaitingErrorRecoveryResponseOrError, CMobilityActivity::TNoTagBackwardsOrRecoverableErrorOrErrorBlockedByClientNotReady)
       
    97 
       
    98         //If the bearer fails to start, the can be another bearer available, so we need to notify the control provider in case it can offer one.
       
    99 		//This node does that by rejecting the current bearer.
       
   100 		THROUGH_NODEACTIVITY_ENTRY(CoreStates::KRecoverableErrorTag, MobilityCprStates::TSendMigrationRejected, TTag<CMobilityActivity::KWaitForMobility|EBackward>)
       
   101 		THROUGH_NODEACTIVITY_ENTRY(KErrorTag, CMobilityActivity::TCompleteMobilityClient, MeshMachine::TTag<CMobilityActivity::KWaitForMobility|EBackward>)
       
   102 
       
   103 		NODEACTIVITY_ENTRY(KNoTag, CMobilityActivity::TNotifyClientNewCarrierActive, MobilityCprStates::TAwaitAndRelayMigrationAcceptedOrMigrationRejected, MeshMachine::TTag<CMobilityActivity::KWaitForMobility|EBackward>)
       
   104 		//<END> MAIN LOOP **************
       
   105 
       
   106 NODEACTIVITY_END()
       
   107 } // namespace CprMobilityActivity
       
   108 
       
   109 namespace MobilityCprActivities
       
   110 {
       
   111 DEFINE_EXPORT_ACTIVITY_MAP(mobilityCprActivities)
       
   112 	ACTIVITY_MAP_ENTRY(CprMobilityActivity, MobilityCprMobility)
       
   113 ACTIVITY_MAP_END_BASE(CprActivities, coreCprActivities)
       
   114 }
       
   115 
       
   116 //
       
   117 // CMobilityActivity
       
   118 CMobilityActivity::CMobilityActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode)
       
   119 :	MeshMachine::CNodeRetryActivity(aActivitySig, aNode)
       
   120 	{
       
   121 	__ASSERT_DEBUG(static_cast<CMobilityConnectionProvider&>(iNode).iMobilityActivity == NULL, User::Panic(KCoreMobileCprPanic, KPanicActivity));
       
   122 	}
       
   123 
       
   124 CMobilityActivity::~CMobilityActivity()
       
   125 	{
       
   126 	//This pointer becomes invalid now, clear if still set.
       
   127 	static_cast<CMobilityConnectionProvider&>(iNode).iMobilityActivity = NULL;
       
   128 	CCommsApiExtResponder::Complete(iResponder, Error() ? Error() : KErrAbort); //Safe if NULL
       
   129 	SetError(KErrNone);
       
   130 	}
       
   131 
       
   132 MeshMachine::CNodeActivityBase* CMobilityActivity::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode)
       
   133 	{
       
   134 	CMobilityActivity* self = new(ELeave) CMobilityActivity(aActivitySig, aNode);
       
   135 	return self;
       
   136 	}
       
   137 
       
   138 void CMobilityActivity::SetResponder(ESock::CCommsApiExtResponder& aResponder)
       
   139 	{
       
   140 	__ASSERT_DEBUG(iResponder==NULL, User::Panic(KSpecAssert_ESockMbCrCPRAct, 7));
       
   141 	__ASSERT_DEBUG(&aResponder, User::Panic(KSpecAssert_ESockMbCrCPRAct, 8));
       
   142 	iResponder = &aResponder;
       
   143 
       
   144 	//CMobilityActivity::TMobilityClientNotReadyMutex may have CMobilityActivity await for
       
   145 	//iResponder to pop up and if it is waiting, we need to signal it.
       
   146 	TNodeNullContext context(iNode, this);
       
   147 	Signal(context);
       
   148 	}
       
   149 
       
   150 TBool CMobilityActivity::TMobilityClientNotReadyMutex::IsBlocked(MeshMachine::TNodeContextBase& aContext)
       
   151 	{
       
   152 	__ASSERT_DEBUG(aContext.iNodeActivity, User::Panic(KCoreMobileCprPanic, KPanicNoActivity));
       
   153 	CMobilityActivity& activity = static_cast<CMobilityActivity&>(*aContext.iNodeActivity);
       
   154 	return activity.iResponder? EFalse : ETrue;
       
   155 	}
       
   156 
       
   157 //Cpr::CMobilityActivity has no originators
       
   158 void CMobilityActivity::StartL(TNodeContextBase& aContext, const Messages::XNodePeerId& aOriginator, const TStateTriple& aFirst)
       
   159 	{
       
   160 	//This activity does not support multiple clients. Any subsequent client should be completed with KErrNotSupported
       
   161 	//from CMobilityConnectionProvider::OpenExtensionInterface().
       
   162 	__ASSERT_DEBUG(iOriginators.Count()==0, User::Panic(KSpecAssert_ESockMbCrCPRAct, 1));
       
   163 
       
   164 	MeshMachine::CNodeRetryActivity::StartL(aContext, aOriginator, aFirst);
       
   165 
       
   166 	TCFMobilityProvider::TStartMobility& msg = message_cast<TCFMobilityProvider::TStartMobility>(aContext.iMessage);
       
   167 	iResponder = static_cast<CCommsApiExtResponder*>(msg.iPtr);
       
   168 	iClientId = msg.iValue;
       
   169 	__ASSERT_DEBUG(msg.iValue != 0, User::Panic(KSpecAssert_ESockMbCrCPRAct, 2)); //Client id must be valid here.
       
   170 
       
   171 	//Set a pointer to the mobility activity in the node on which it's running
       
   172 	__ASSERT_DEBUG(static_cast<CMobilityConnectionProvider&>(iNode).iMobilityActivity == NULL, User::Panic(KSpecAssert_ESockMbCrCPRAct, 3));
       
   173 	static_cast<CMobilityConnectionProvider&>(iNode).iMobilityActivity = this;
       
   174 	}
       
   175 
       
   176 void CMobilityActivity::Cancel(TNodeContextBase& aContext)
       
   177 	{
       
   178 	RNodeInterface* cp = iNode.GetFirstClient<TDefaultClientMatchPolicy>(TClientType(TCFClientType::ECtrlProvider));
       
   179 	__ASSERT_DEBUG(cp, User::Panic(KSpecAssert_ESockMbCrCPRAct, 4)); //We are a Cpr, must exist.
       
   180 
       
   181 	//PostedTo() could be our service provider or possibly other peer
       
   182 	if (PostedToId() != cp->RecipientId())
       
   183 		{
       
   184 		cp->PostMessage(TNodeCtxId(ActivityId(), iNode.Id()),
       
   185 			TEBase::TCancel().CRef());
       
   186 		}
       
   187 
       
   188 	MeshMachine::CNodeRetryActivity::Cancel(aContext); //Send TCancel to iPostedTo
       
   189 	}
       
   190 
       
   191 
       
   192 DEFINE_SMELEMENT(CMobilityActivity::TNoTagBackwardsOrRecoverableErrorOrError, NetStateMachine::MStateFork, CMobilityActivity::TContext)
       
   193 TInt CMobilityActivity::TNoTagBackwardsOrRecoverableErrorOrError::TransitionTag()
       
   194 	{
       
   195 	if (iContext.iMessage.IsMessage<TEErrorRecovery::TErrorRecoveryResponse>())
       
   196 		{
       
   197 		TErrResponse& resp = message_cast<TEErrorRecovery::TErrorRecoveryResponse>(iContext.iMessage).iErrResponse;
       
   198 		if (resp.iAction == TErrResponse::ERetry)
       
   199 			{
       
   200 		    return KNoTag | NetStateMachine::EBackward;
       
   201 			}
       
   202 		else if  (resp.iAction == TErrResponse::EPropagate || resp.iError == KErrCancel)
       
   203 			{
       
   204 			return KErrorTag;
       
   205 			}
       
   206 		else if (resp.iAction == TErrResponse::EIgnore) // and or iError is KErrCancel
       
   207 			{
       
   208 			//TODO RZ: This looks inappropriate. EIgnore and EPropagate flags are not 
       
   209 			//really complimentary. They're simply invalid in soem scenarios.
       
   210 			//Here we use ignore to an activity that attempted error recovery,
       
   211 			//it technically cannot ignore the error. It will propagate it back
       
   212 			//to the MCPR (and not to the client) by rejecting the current bearer.
       
   213 			//It feels thought clearing the error doesn't belong here. It probably
       
   214 			//belongs to the error activity. 
       
   215 			iContext.Activity()->SetError(KErrNone);
       
   216 			return CoreStates::KRecoverableErrorTag;
       
   217 			}
       
   218 		}
       
   219 	return KNoTag;
       
   220 	}
       
   221 
       
   222 
       
   223 DEFINE_SMELEMENT(CMobilityActivity::TNoTagOrWaitForMobilityBackwards, NetStateMachine::MStateFork, CMobilityActivity::TContext)
       
   224 TInt CMobilityActivity::TNoTagOrWaitForMobilityBackwards::TransitionTag()
       
   225 	{
       
   226 	if(iContext.iMessage.IsMessage<TCFMobilityProvider::TMigrationRequested>())
       
   227 		{
       
   228 		return KNoTag;
       
   229 		}
       
   230 	else
       
   231 		{
       
   232 		__ASSERT_DEBUG(iContext.iMessage.IsMessage<TCFMobilityProvider::TMigrationRejected>(), User::Panic(KSpecAssert_ESockMbCrCPRAct, 6));
       
   233 		return CMobilityActivity::KWaitForMobility|EBackward;
       
   234 		}
       
   235 	}
       
   236 
       
   237 
       
   238 //Transitions
       
   239 
       
   240 DEFINE_SMELEMENT(CMobilityActivity::TCompleteMobilityClient, NetStateMachine::MStateTransition, CMobilityActivity::TContext)
       
   241 void CMobilityActivity::TCompleteMobilityClient::DoL()
       
   242 	{
       
   243 	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileCprPanic, KPanicNoActivity));
       
   244 	CMobilityActivity& activity = static_cast<CMobilityActivity&>(*iContext.iNodeActivity);
       
   245 	CCommsApiExtResponder::Complete(activity.iResponder, activity.Error());
       
   246 	
       
   247 	//There is only one way to kill the mobility activity and it is by the client closing the API extension.
       
   248 	//This will be manifested with KErrCancel.
       
   249 	if (activity.Error() == KErrCancel)
       
   250 	    {
       
   251 	    activity.SetIdle();
       
   252 	    }
       
   253 	activity.SetError(KErrNone); //The error has been handled
       
   254 	activity.ClearPostedTo();
       
   255 	}
       
   256 
       
   257 DEFINE_SMELEMENT(CMobilityActivity::TNotifyClientPreferredCarrierAvailable, NetStateMachine::MStateTransition, CMobilityActivity::TContext)
       
   258 void CMobilityActivity::TNotifyClientPreferredCarrierAvailable::DoL()
       
   259 	{
       
   260 	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileCprPanic, KPanicNoActivity));
       
   261 	CMobilityActivity& activity = static_cast<CMobilityActivity&>(*iContext.iNodeActivity);
       
   262 	TCFMobilityControlClient::TMigrationNotification& msg = message_cast<TCFMobilityControlClient::TMigrationNotification>(iContext.iMessage);
       
   263 
       
   264 	activity.iCurrentAp = msg.iValue1;
       
   265 	activity.iPreferredAp = msg.iValue2;
       
   266 	activity.iIsUpgrade = msg.iValue3;
       
   267 
       
   268 	CCommsMobilitySrvResp* responder = static_cast<CCommsMobilitySrvResp*>(activity.iResponder);
       
   269 	activity.iResponder = NULL;
       
   270 	CCommsMobilitySrvResp::PreferredCarrierAvailable(responder, TAccessPointInfo(activity.iCurrentAp), TAccessPointInfo(activity.iPreferredAp), activity.iIsUpgrade, EFalse);
       
   271 	activity.ClearPostedTo();
       
   272 	}
       
   273 
       
   274 DEFINE_SMELEMENT(CMobilityActivity::TNotifyClientNewCarrierActive, NetStateMachine::MStateTransition, CMobilityActivity::TContext)
       
   275 void CMobilityActivity::TNotifyClientNewCarrierActive::DoL()
       
   276 	{
       
   277 	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCoreMobileCprPanic, KPanicNoActivity));
       
   278 	CMobilityActivity& activity = static_cast<CMobilityActivity&>(*iContext.iNodeActivity);
       
   279 	CCommsMobilitySrvResp* responder = static_cast<CCommsMobilitySrvResp*>(activity.iResponder);
       
   280 	activity.iResponder = NULL;
       
   281 	CCommsMobilitySrvResp::NewCarrierActive(responder, TAccessPointInfo(activity.iPreferredAp), EFalse);
       
   282 	activity.ClearPostedTo();
       
   283 	}
       
   284 
       
   285