diff -r 000000000000 -r 5a93021fdf25 bearermanagement/S60MCPR/src/s60mcprstates.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bearermanagement/S60MCPR/src/s60mcprstates.cpp Thu Dec 17 08:55:21 2009 +0200 @@ -0,0 +1,486 @@ +/* +* Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: S60 MCPR states implementation +* +*/ + +/** +@file s60mcprstates.cpp +S60 MCPR states implementation +*/ + +#include + +#include "s60mcprstates.h" + +using namespace S60MCprStates; +using namespace ESock; +using namespace Messages; +using namespace MeshMachine; + +// ----------------------------------------------------------------------------- +// THandleMPMStatusChange::DoL +// ----------------------------------------------------------------------------- +// +DEFINE_SMELEMENT(THandleMPMStatusChange, NetStateMachine::MStateTransition, TContext) +void THandleMPMStatusChange::DoL() + { + TCFControlProvider::TDataClientStatusChange& msg = + Messages::message_cast(iContext.iMessage); + + // Get MCPR + CS60MetaConnectionProvider& node = iContext.Node(); + + // Get the policy server's selection result + TInt iapid = node.PolicyPrefs().IapId(); + + if ( iapid == 0 ) + { + // Filter zeros out. + // We don't need information of IPCPR status, we only care real connections. + } + else if ( msg.iValue == TCFControlProvider::TDataClientStatusChange::EStarted && + node.RequestPermissionToSendStarted() ) + { + S60MCPRLOGSTRING2("S60MCPR<%x>::THandleMPMStatusChange::DoL() calling IAPConnectionStartedL IAP %d",(TInt*)&iContext.Node(),iapid) + // TODO use progress notification KLinkLayerOpen once Symbian provides them. + node.Policy()->IAPConnectionStartedL( iapid ); // codescanner::leave + + /** HACK ALERT + * + * Due to regression in MOBILITY the EStartedFlag for serviceprovider is set here! + * TODO Remove this hack whenever possible!!! + */ + node.ServiceProvider()->SetFlags( TCFClientType::EStarted ); + } + else if ( msg.iValue == TCFControlProvider::TDataClientStatusChange::EStopped && + node.RequestPermissionToSendStopped() ) + { + S60MCPRLOGSTRING2("S60MCPR<%x>::THandleMPMStatusChange::DoL() calling IAPConnectionStoppedL IAP %d",(TInt*)&iContext.Node(),iapid) + // Send request. + // The problem with IAPConnectionStoppedL() is that to MPM it means + // that IAP has gone down but actually the provider has just left. + // policy->IAPConnectionStoppedL( node.iIapId ); + // Hence we mimic the situtation that application leaves the connection. + node.Policy()->ApplicationLeavesConnectionL( iapid ); // codescanner::leave + node.Policy()->ApplicationConnectionEndsL(); // codescanner::leave + } + } + +// ----------------------------------------------------------------------------- +// TReselectBestIAP::DoL +// ----------------------------------------------------------------------------- +// +DEFINE_SMELEMENT(TReselectBestIAP, NetStateMachine::MStateTransition, TContext) +void TReselectBestIAP::DoL() + { + S60MCPRLOGSTRING1("S60MCPR<%x>::TReselectBestIAP::DoL()",(TInt*)&iContext.Node()) + + // Get MCPR + CS60MetaConnectionProvider& node = (CS60MetaConnectionProvider&)iContext.Node(); + + // Build up the PolicyRequest. + TConnPref* polpref = (TConnPref*)new ( ELeave ) TPolicyConnPref(); // codescanner::leave + CleanupStack::PushL( polpref ); // codescanner::leave + + CReselectBestIAPCb* cb = new( ELeave ) CReselectBestIAPCb( node, iContext.iNodeActivity ); // codescanner::leave + CleanupStack::PushL( cb ); // codescanner::leave + + // Send request + node.Policy()->ReselectIAPL( polpref, cb ); // codescanner::leave + + // Pop three objects. + CleanupStack::Pop( cb ); + CleanupStack::Pop( polpref ); + // Pop pref and cb objects. + } + + +// ----------------------------------------------------------------------------- +// TRequestReConnect::DoL +// ----------------------------------------------------------------------------- +// +DEFINE_SMELEMENT( TRequestReConnect, NetStateMachine::MStateTransition, TContext ) +void TRequestReConnect::DoL() // codescanner::leave + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KS60MCprPanic, KPanicNoActivity)); + S60MCPRLOGSTRING1("S60MCPR<%x>::TRequestReConnect::DoL()",(TInt*)&iContext.Node()) + // We have AP that will go down. + // And the other AP that will go up. + RNodeInterface* stoppingSP = NULL; + RNodeInterface* startingSP = NULL; + + // The one that will be started is the one MPM selected. + // Both must be present in the MCPR -plane. + + // Choose Service Providers to work on + TClientIter iter = + iContext.Node().GetClientIter(TClientType(TCFClientType::EServProvider)); + + RNodeInterface* itf = NULL; + for ( itf = iter++; ( itf != NULL && ( stoppingSP == NULL || startingSP == NULL ) ); itf = iter++ ) + { + // Only one of the selected MCPRs can be EStarted. + // + if ( itf->Flags() & TCFClientType::EStarted ) + { + stoppingSP = itf; //Our current started Service Provider. + itf->ClearFlags( TCFClientType::EActive ); + } + // The other which is not EStarted must be EActive. + // + else if ( itf->Flags() & TCFClientType::EActive ) + { + startingSP = itf; //And the new one to try next + } + } + // One must be started since this is already a reconnection + if ( stoppingSP==NULL ) + { + // Indication of a serious problem. + S60MCPRLOGSTRING1("S60MCPR<%x>::TRequestReConnect::DoL() - started service provider not found.",(TInt*)&iContext.Node()) + ASSERT( EFalse ); + User::Leave( KErrCorrupt ); // codescanner::leave + } + + //Sanity check. + //The new provider must not be started, there can be only one started at a time. + ASSERT( startingSP == NULL || ( startingSP->Flags() & TCFClientType::EStarted ) == 0 ); + + //If there is no other Service Provider to try, return KErrNotFound + if ( startingSP == NULL ) + { + S60MCPRLOGSTRING1("S60MCPR<%x>::TRequestReConnect::DoL() - no more choices, abandoning recovery.",(TInt*)&iContext.Node()) + User::Leave( KErrNotFound ); // codescanner::leave + } + + //Diagnostinc - there must be a data client or we cannot be here + __ASSERT_DEBUG(iContext.Node().GetFirstClient(TClientType(TCFClientType::EData)), + User::Panic(KS60MCprPanic, KPanicNoDataClient)); + + iContext.iNodeActivity->PostRequestTo( iContext.NodeId(), + TCFMcpr::TReConnect( stoppingSP->RecipientId(), + startingSP->RecipientId()).CRef() ); + } + + +// ----------------------------------------------------------------------------- +// TProcessError::DoL +// ----------------------------------------------------------------------------- +// +DEFINE_SMELEMENT( TProcessError, NetStateMachine::MStateTransition, TContext ) +void TProcessError::DoL() // codescanner::leave + { + __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KS60MCprPanic, KPanicNoActivity)); + // Get the MCPR + CS60MetaConnectionProvider& node = (CS60MetaConnectionProvider&)iContext.Node(); + + TInt error( KErrNone ); + + // Get the error from the message or from the activity. + // Since this transition could be triggered from almost anywhere, + // give preference to current Message. + if ( iContext.iMessage.IsMessage() ) + { + S60MCPRLOGSTRING1("S60MCPR<%x>::TProcessError::DoL() Using iMessage as error source",(TInt*)&iContext.Node()) + error = message_cast(&iContext.iMessage)->iValue; + } + else + { + S60MCPRLOGSTRING1("S60MCPR<%x>::TProcessError::DoL() Using CS60ErrorRecoveryActivity as error source",(TInt*)&iContext.Node()) + // Get the activity. + CS60ErrorRecoveryActivity& activity = + static_cast(*iContext.iNodeActivity); + Messages::TErrContext err = activity.iOriginalErrContext; + error = err.iStateChange.iError; + } + + ASSERT( error != KErrNone ); + + // Create the callback that will eventually create the message that completes this state. + CProcessErrorCb* cb = new( ELeave ) CProcessErrorCb( node, iContext.iNodeActivity ); // codescanner::leave + CleanupStack::PushL( cb ); // codescanner::leave + // We always need to ask MPM to handle the error. + node.Policy()->ProcessErrorL( error, cb ); // codescanner::leave + CleanupStack::Pop( cb ); + // After this we wait for cancellation/error/completion. + } + + +// ----------------------------------------------------------------------------- +// TAwaitingSelectNextLayerCompletedOrError::Accept +// ----------------------------------------------------------------------------- +// +DEFINE_SMELEMENT( TAwaitingSelectNextLayerCompletedOrError, NetStateMachine::MState, TContext ) +TBool TAwaitingSelectNextLayerCompletedOrError::Accept() + { + TEBase::TError* msg = message_cast(&iContext.iMessage); + if( msg ) + { + S60MCPRLOGSTRING1("S60MCPR<%x>::TAwaitingSelectNextLayerCompletedOrError::Accept() TError",(TInt*)&iContext.Node()) + iContext.iNodeActivity->SetError(msg->iValue); + return ETrue; + } + if (iContext.iMessage.IsMessage()) + { + if (message_cast(iContext.iMessage).iNodeId.IsNull()) + { + S60MCPRLOGSTRING1("S60MCPR<%x>::TAwaitingSelectNextLayerCompletedOrError::Accept() TSelectComplete",(TInt*)&iContext.Node()) + return ETrue; + } + //Consume any other TSelectComplete messages + iContext.iMessage.ClearMessageId(); + } + return EFalse; + } + + + +// ----------------------------------------------------------------------------- +// TAwaitingReselectBestIAPCompleteOrError::Accept +// ----------------------------------------------------------------------------- +// +DEFINE_SMELEMENT( TAwaitingReselectBestIAPCompleteOrError, NetStateMachine::MState, TContext ) +TBool TAwaitingReselectBestIAPCompleteOrError::Accept() + { + if ( iContext.iMessage.IsMessage() ) + { + S60MCPRLOGSTRING1("S60MCPR<%x>::TAwaitingReselectBestIAPCompleteOrError::Accept() TMPMReselectBestIAPCompletedMsg Accepted",(TInt*)&iContext.Node()) + + // Reselect completed. + return ETrue; + } + else if ( iContext.iMessage.IsMessage() ) + { + S60MCPRLOGSTRING1("S60MCPR<%x>::TAwaitingReselectBestIAPCompleteOrError::Accept() TError",(TInt*)&iContext.Node()) + // Some error possibly sent by the MPM. Must be handled by the activity. + Messages::TEBase::TError* msg = message_cast(&iContext.iMessage); + iContext.iNodeActivity->SetError(msg->iValue); + return ETrue; + } + else if ( iContext.iMessage.IsMessage() ) + { + // Cancellation from the RConnection::Start(). + // Cancel MPM asynch. + S60MCPRLOGSTRING1("S60MCPR<%x>::TAwaitingReselectBestIAPCompleteOrError::Accept() NOT Accept TCancel, Cancelling ReselectBestIAPL()",(TInt*)&iContext.Node()) + + // Get the MCPR + CS60MetaConnectionProvider& node = (CS60MetaConnectionProvider&)iContext.Node(); + + node.Policy()->CancelReselectBestIAP(); + + return EFalse; + } + else + { + // else + return EFalse; + } + } + +// ----------------------------------------------------------------------------- +// TAwaitingProcessErrorCompleteOrError::Accept +// ----------------------------------------------------------------------------- +// +DEFINE_SMELEMENT( TAwaitingProcessErrorCompleteOrError, NetStateMachine::MState, TContext ) +TBool TAwaitingProcessErrorCompleteOrError::Accept() + { + if ( iContext.iMessage.IsMessage() ) + { + S60MCPRLOGSTRING1("S60MCPR<%x>::TAwaitingProcessErrorCompleteOrError::Accept() TMPMProcessErrorCompletedMsg or Error", (TInt*)&iContext.Node()) + // ProcessErrorComplete completed. + return ETrue; + } + else if ( iContext.iMessage.IsMessage() ) + { + // Processing continue in error transition. + TEBase::TError* msg = message_cast( &iContext.iMessage ); + iContext.iNodeActivity->SetError( msg->iValue ); + S60MCPRLOGSTRING2("S60MCPR<%x>::TAwaitingProcessErrorCompleteOrError::Accept() Error %d", (TInt*)&iContext.Node(),msg->iValue) + return ETrue; + } + else if ( iContext.iMessage.IsMessage() ) + { + // Get the MCPR + CS60MetaConnectionProvider& node = (CS60MetaConnectionProvider&)iContext.Node(); + + node.Policy()->CancelProcessError(); + // should this be the same as ignore? + S60MCPRLOGSTRING1("S60MCPR<%x>::TAwaitingProcessErrorCompleteOrError::Accept() NOT Accepted TCancel Cancelling ProcessError", (TInt*)&iContext.Node()) + return EFalse; + } + else + { + return EFalse; + } + } + +// ----------------------------------------------------------------------------- +// TAwaitingServiceIdRequest::Accept +// ----------------------------------------------------------------------------- +// +DEFINE_SMELEMENT( TAwaitingServiceIdRequest, NetStateMachine::MState, TContext ) +TBool TAwaitingServiceIdRequest::Accept() + { + ESock::TMCprGetConnectionSetting* msg = NULL; + + S60MCPRLOGSTRING2("TAwaitingServiceIdRequest: iContext.iMessage( %x %x )", + iContext.iMessage.MessageId().MessageId(), + iContext.iMessage.MessageId().Realm()); + S60MCPRLOGSTRING2(" == ( %x %x )?\n", + ESock::TMCprGetConnectionSetting::EId, + ESock::TMCprGetConnectionSetting::ERealm); + + if ( iContext.iMessage.IsMessage() ) + { + S60MCPRLOGSTRING1("S60MCPR<%x>::TAwaitingServiceIdRequest::Accept() TMCprGetConnectionSetting", + (TInt*)&iContext.Node()) + msg = message_cast(&iContext.iMessage); + + // Get MCPR + CS60MetaConnectionProvider& node = (CS60MetaConnectionProvider&)iContext.Node(); + + // Only EIntSetting is supported + // + if ( ( TMCprGetConnectionSetting::TConnectionSettingType)msg->iSettingType == + TMCprGetConnectionSetting::EIntSetting + && node.PolicyPrefs().ServiceId() != 0 ) + { + S60MCPRLOGSTRING1("S60MCPR<%x>::TAwaitingServiceIdRequest::Accept() TMCprGetConnectionSetting EIntSetting", + (TInt*)&iContext.Node()) + return ETrue; + } + else + { + S60MCPRLOGSTRING1("S60MCPR<%x>::TAwaitingServiceIdRequest::Accept() TMCprGetConnectionSetting not processing EIntSetting", + (TInt*)&iContext.Node()) + return EFalse; + } + } + else + { + return EFalse; + } + } + +// ----------------------------------------------------------------------------- +// TRetrieveServiceId::DoL +// ----------------------------------------------------------------------------- +// +DEFINE_SMELEMENT( TRetrieveServiceId, NetStateMachine::MStateTransition, TContext ) +void TRetrieveServiceId::DoL() + { + S60MCPRLOGSTRING1("S60MCPR<%x>::TRetrieveServiceId::DoL()", (TInt*)&iContext.Node()) + + // Get MCPR + CS60MetaConnectionProvider& node = (CS60MetaConnectionProvider&)iContext.Node(); + + // Get the policy server's selection result + TUint32 serviceId = node.PolicyPrefs().ServiceId(); + S60MCPRLOGSTRING2("S60MCPR<%x>::TRetrieveServiceId::DoL() ServiceId = %d", + (TInt*)&iContext.Node(), serviceId ) + + TPckg pckg( serviceId ); + + S60MCPRLOGSTRING1("S60MCPR<%x>::TRetrieveServiceId::DoL() Write ServiceId to ResponseMsg", + (TInt*)&iContext.Node()) + TCFSigLegacyRMessage2Ext& msg = static_cast( iContext.iMessage ); + msg.iMessage.WriteL( 1, pckg ); // codescanner::leave + + S60MCPRLOGSTRING1("S60MCPR<%x>::TRetrieveServiceId::DoL() Complete ResponseMsg", + (TInt*)&iContext.Node()) + RLegacyResponseMsg responseMsg( iContext, msg.iMessage, msg.iMessage.Int0() ); + responseMsg.Complete( KErrNone ); + } + +// ----------------------------------------------------------------------------- +// CReselectBestIAPCb::PolicyResponse +// ----------------------------------------------------------------------------- +// +void CReselectBestIAPCb::PolicyResponse( PolicyRequest& aCompletedRequest ) + { + using namespace ESock; + TPolicyConnPref* policypref = (TPolicyConnPref*)aCompletedRequest.iPolicyPref; + + // Request to MPM failed for some reason + if( aCompletedRequest.iStatus != KErrNone ) + { + S60MCPRLOGSTRING2("S60MCPR<%x>::CReselectBestIAPCb::PolicyResponse() MPM Error %d",(TInt*)&iNode,aCompletedRequest.iStatus) + Messages::TEBase::TError msg( TCFS60MCPRMessage::TMPMReselectBestIAPCompletedMsg::Id(), + aCompletedRequest.iStatus ); + if ( iLastRequestOriginator.IsOpen() ) + { + iLastRequestOriginator.ReplyTo( iNode.Id(), msg ); + iLastRequestOriginator.Close(); + } + return; + } + + S60MCPRLOGSTRING3("S60MCPR<%x>::CReselectBestIAPCb::PolicyResponse() IAP %d NET %d", + (TInt*)&iNode,policypref->IapId(),policypref->NetId()) + + iNode.SetPolicyPrefs( *policypref ); + + TCFS60MCPRMessage::TMPMReselectBestIAPCompletedMsg msg; + if ( iLastRequestOriginator.IsOpen() ) + { + iLastRequestOriginator.ReplyTo( iNode.Id(), msg ); + iLastRequestOriginator.Close(); + } + } + +// ----------------------------------------------------------------------------- +// CProcessErrorCb::PolicyResponse +// ----------------------------------------------------------------------------- +// +void CProcessErrorCb::PolicyResponse( PolicyRequest& aCompletedRequest ) + { + S60MCPRLOGSTRING3("S60MCPR<%x>::CProcessErrorCb::PolicyResponse() status=%d action=%d", + (TInt*)&iNode,aCompletedRequest.iStatus,(TInt)aCompletedRequest.iNeededAction) + // Validate that we can send a response. + // + if ( !iLastRequestOriginator.IsOpen() ) + { + // response can't be sent. + return; + } + // Request ok and valid one + // + if ( aCompletedRequest.iStatus == KErrNone && + ( aCompletedRequest.iNeededAction == EIgnoreError || + aCompletedRequest.iNeededAction == EDoReselection )) + { + TCFS60MCPRMessage::TMPMProcessErrorCompletedMsg msg( (TInt)aCompletedRequest.iNeededAction ); + iLastRequestOriginator.ReplyTo( iNode.Id(), msg ); + iLastRequestOriginator.Close(); + } + // Propagate error + // + else + { + // Initialize + TInt err = aCompletedRequest.iStatus; + if ( err == KErrNone ) + { + ASSERT( aCompletedRequest.iError != KErrNone ); + err = aCompletedRequest.iError != KErrNone ? aCompletedRequest.iError : KErrGeneral; + } + TEBase::TError msg( TCFS60MCPRMessage::TMPMProcessErrorCompletedMsg::Id(), err ); + iLastRequestOriginator.ReplyTo( iNode.Id(), msg ); + iLastRequestOriginator.Close(); + } + } + +// End of File +