bearermanagement/S60MCPR/src/s60mcprstates.cpp
changeset 0 5a93021fdf25
child 1 40cb640ef159
--- /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 <cdblen.h>
+
+#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<TCFControlProvider::TDataClientStatusChange>(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<TDefaultClientMatchPolicy> iter = 
+        iContext.Node().GetClientIter<TDefaultClientMatchPolicy>(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<TDefaultClientMatchPolicy>(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<Messages::TEBase::TError>() )
+        {
+        S60MCPRLOGSTRING1("S60MCPR<%x>::TProcessError::DoL() Using iMessage as error source",(TInt*)&iContext.Node())
+        error = message_cast<TEBase::TError>(&iContext.iMessage)->iValue;
+        }
+    else
+        {
+        S60MCPRLOGSTRING1("S60MCPR<%x>::TProcessError::DoL() Using CS60ErrorRecoveryActivity as error source",(TInt*)&iContext.Node())
+        // Get the activity.
+        CS60ErrorRecoveryActivity& activity = 
+            static_cast<CS60ErrorRecoveryActivity&>(*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<TEBase::TError>(&iContext.iMessage);
+    if( msg )
+        {
+        S60MCPRLOGSTRING1("S60MCPR<%x>::TAwaitingSelectNextLayerCompletedOrError::Accept() TError",(TInt*)&iContext.Node())
+        iContext.iNodeActivity->SetError(msg->iValue);
+        return ETrue;
+        }
+    if (iContext.iMessage.IsMessage<TCFSelector::TSelectComplete>())
+        {
+        if (message_cast<TCFSelector::TSelectComplete>(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<TCFS60MCPRMessage::TMPMReselectBestIAPCompletedMsg>() )
+        {
+        S60MCPRLOGSTRING1("S60MCPR<%x>::TAwaitingReselectBestIAPCompleteOrError::Accept() TMPMReselectBestIAPCompletedMsg Accepted",(TInt*)&iContext.Node())
+        
+        // Reselect completed.
+        return ETrue;
+        }
+    else if ( iContext.iMessage.IsMessage<Messages::TEBase::TError>() )
+        {
+        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<TEBase::TError>(&iContext.iMessage);
+        iContext.iNodeActivity->SetError(msg->iValue);
+        return ETrue;
+        }
+    else if ( iContext.iMessage.IsMessage<Messages::TEBase::TCancel>() )
+        {
+        // 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<TCFS60MCPRMessage::TMPMProcessErrorCompletedMsg>() )
+        {
+        S60MCPRLOGSTRING1("S60MCPR<%x>::TAwaitingProcessErrorCompleteOrError::Accept() TMPMProcessErrorCompletedMsg or Error", (TInt*)&iContext.Node())
+        // ProcessErrorComplete completed.
+        return ETrue;
+        }
+    else if ( iContext.iMessage.IsMessage<TEBase::TError>() )
+        {
+        // Processing continue in error transition.
+        TEBase::TError* msg = message_cast<TEBase::TError>( &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<TEBase::TCancel>() )
+        {
+        // 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<ESock::TMCprGetConnectionSetting>() )  
+        {
+        S60MCPRLOGSTRING1("S60MCPR<%x>::TAwaitingServiceIdRequest::Accept() TMCprGetConnectionSetting", 
+            (TInt*)&iContext.Node())
+        msg = message_cast<ESock::TMCprGetConnectionSetting>(&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<TUint32> pckg( serviceId );
+
+    S60MCPRLOGSTRING1("S60MCPR<%x>::TRetrieveServiceId::DoL() Write ServiceId to ResponseMsg", 
+            (TInt*)&iContext.Node())
+    TCFSigLegacyRMessage2Ext& msg = static_cast<TCFSigLegacyRMessage2Ext&>( 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
+