natplugins/natpnatfwsdpprovider/src/nspstatemachine.cpp
changeset 0 1bce908db942
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/natplugins/natpnatfwsdpprovider/src/nspstatemachine.cpp	Tue Feb 02 01:04:58 2010 +0200
@@ -0,0 +1,386 @@
+/*
+* Copyright (c) 2007 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:  State machine implementation.
+*
+*/
+
+#include "nspstatemachine.h"
+#include "nspstatebase.h"
+#include "nspsessiondata.h"
+#include "nspevents.h"
+#include "nspstateinitializing.h"
+#include "nspstateidle.h"
+#include "nspstatelocalcand.h"
+#include "nspstatenegotiating.h"
+#include "nspstateresolving.h"
+#include "nspstateactivating.h"
+#include "nspstateconnected.h"
+#include "nspstatedeactivating.h"
+#include "nspdefs.h"
+
+#define STATE_ID_L( statearray, state ) \
+        User::LeaveIfError( statearray.Find( state ) )
+
+#define LOGSTATE( aState ) \
+    switch( aState )\
+        {\
+        case KStateIndexInitializing:{ NSPLOG_STR( "state:Initializing" ); break; }\
+        case KStateIndexIdle:{ NSPLOG_STR( "state:Idle" ); break; }\
+        case KStateIndexLocalCand:{ NSPLOG_STR( "state:LocalCand" ); break; }\
+        case KStateIndexNegotiating:{ NSPLOG_STR( "state:Negotiating" ); break; }\
+        case KStateIndexResolving:{ NSPLOG_STR( "state:Resolving" ); break; }\
+        case KStateIndexActivating:{ NSPLOG_STR( "state:Activating" ); break; }\
+        case KStateIndexConnected:{ NSPLOG_STR( "state:Connected" ); break; }\
+        case KStateIndexDeActivating:{ NSPLOG_STR( "state:DeActivating" ); break; }\
+        default:{ NSPLOG_STR( "state:Unknown" ); break; }\
+        }
+
+#define LOGOLDSTATE( aState ) \
+    switch( aState )\
+        {\
+        case KStateIndexInitializing:{ NSPLOG_STR( "    old state:Initializing" ); break; }\
+        case KStateIndexIdle:{ NSPLOG_STR( "    old state:Idle" ); break; }\
+        case KStateIndexLocalCand:{ NSPLOG_STR( "    old state:LocalCand" ); break; }\
+        case KStateIndexNegotiating:{ NSPLOG_STR( "    old state:Negotiating" ); break; }\
+        case KStateIndexResolving:{ NSPLOG_STR( "    old state:Resolving" ); break; }\
+        case KStateIndexActivating:{ NSPLOG_STR( "    old state:Activating" ); break; }\
+        case KStateIndexConnected:{ NSPLOG_STR( "    old state:Connected" ); break; }\
+        case KStateIndexDeActivating:{ NSPLOG_STR( "    old state:DeActivating" ); break; }\
+        default:{ NSPLOG_STR( "    old state:Unknown" ); break; }\
+        }
+
+#define LOGSNEWTATE( aState ) \
+    switch( aState )\
+        {\
+        case KStateIndexInitializing:{ NSPLOG_STR( "    new state:Initializing" ); break; }\
+        case KStateIndexIdle:{ NSPLOG_STR( "    new state:Idle" ); break; }\
+        case KStateIndexLocalCand:{ NSPLOG_STR( "    new state:LocalCand" ); break; }\
+        case KStateIndexNegotiating:{ NSPLOG_STR( "    new state:Negotiating" ); break; }\
+        case KStateIndexResolving:{ NSPLOG_STR( "    new state:Resolving" ); break; }\
+        case KStateIndexActivating:{ NSPLOG_STR( "    new state:Activating" ); break; }\
+        case KStateIndexConnected:{ NSPLOG_STR( "    new state:Connected" ); break; }\
+        case KStateIndexDeActivating:{ NSPLOG_STR( "    new state:DeActivating" ); break; }\
+        default:{ NSPLOG_STR( "    new state:Unknown" ); break; }\
+        }
+
+
+#define LOGEVENT( aEvent ) \
+    switch( (TNSPStateMachineEvent::TRequest) aEvent.Request() )\
+        {\
+        case TNSPStateMachineEvent::ENat:{ NSPLOG_STR( "event:ENat" ); break; }\
+        case TNSPStateMachineEvent::ECreateOffer:{ NSPLOG_STR( "event:ECreateOffer" ); break; }\
+        case TNSPStateMachineEvent::EResolve:{ NSPLOG_STR( "event:EResolve" ); break; }\
+        case TNSPStateMachineEvent::EDecodeAnswer:{ NSPLOG_STR( "event:EDecodeAnswer" ); break; }\
+        case TNSPStateMachineEvent::EUpdate:{ NSPLOG_STR( "event:EUpdate" ); break; }\
+        case TNSPStateMachineEvent::EReservationStatus:{ NSPLOG_STR( "event:EReservationStatus" ); break; }\
+        case TNSPStateMachineEvent::ECloseSession:{ NSPLOG_STR( "event:ECloseSession" ); break; }\
+        default:{ NSPLOG_STR( "event:Unknown" ); break; }\
+        }
+
+// ======== MEMBER FUNCTIONS ========
+// ---------------------------------------------------------------------------
+// CNSPStateMachine::CNSPStateMachine
+// ---------------------------------------------------------------------------
+//
+CNSPStateMachine::CNSPStateMachine()
+    {
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPStateMachine::ConstructL
+// ---------------------------------------------------------------------------
+//
+void CNSPStateMachine::ConstructL()
+    {
+    InitializeStateArrayL();
+    iCurrentState = iStateArray[KStateIndexInitializing];
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPStateMachine::InitializeStateArrayL
+// ---------------------------------------------------------------------------
+//
+void CNSPStateMachine::InitializeStateArrayL()
+    {
+    CNSPStateBase* state = NULL;
+    
+    state = CNSPStateInitializing::NewLC();
+    User::LeaveIfError( iStateArray.Insert( state, KStateIndexInitializing ) );
+    CleanupStack::Pop( state );
+    
+    state = CNSPStateIdle::NewLC();
+    User::LeaveIfError( iStateArray.Insert( state, KStateIndexIdle ) );
+    CleanupStack::Pop( state );
+    
+    state = CNSPStateLocalCand::NewLC();
+    User::LeaveIfError( iStateArray.Insert( state, KStateIndexLocalCand ) );
+    CleanupStack::Pop( state );
+    
+    state = CNSPStateNegotiating::NewLC();
+    User::LeaveIfError( iStateArray.Insert( state, KStateIndexNegotiating ) );
+    CleanupStack::Pop( state );
+    
+    state = CNSPStateResolving::NewLC();
+    User::LeaveIfError( iStateArray.Insert( state, KStateIndexResolving ) );
+    CleanupStack::Pop( state );
+    
+    state = CNSPStateActivating::NewLC();
+    User::LeaveIfError( iStateArray.Insert( state, KStateIndexActivating ) );
+    CleanupStack::Pop( state );
+    
+    state = CNSPStateConnected::NewLC();
+    User::LeaveIfError( iStateArray.Insert( state, KStateIndexConnected ) );
+    CleanupStack::Pop( state );
+
+    state = CNSPStateDeActivating::NewLC();
+    User::LeaveIfError( iStateArray.Insert( state, KStateIndexDeActivating ) );
+    CleanupStack::Pop( state );
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPStateMachine::NewL
+// ---------------------------------------------------------------------------
+//
+CNSPStateMachine* CNSPStateMachine::NewL()
+    {
+    CNSPStateMachine* self = CNSPStateMachine::NewLC();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPStateMachine::NewLC
+// ---------------------------------------------------------------------------
+//
+CNSPStateMachine* CNSPStateMachine::NewLC()
+    {
+    CNSPStateMachine* self = new ( ELeave ) CNSPStateMachine();
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    return self;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPStateMachine::~CNSPStateMachine
+// ---------------------------------------------------------------------------
+//
+CNSPStateMachine::~CNSPStateMachine()
+    {
+    iStateArray.ResetAndDestroy();
+    iStateArray.Close();
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPStateMachine::ProcessL
+// ---------------------------------------------------------------------------
+//
+void CNSPStateMachine::ProcessL( TNSPStateMachineEvent& aEvent )
+    {
+    __ASSERT_ALWAYS( iCurrentState, User::Leave( KErrTotalLossOfPrecision ) );
+    
+    NSPLOG_STR( "CNSPStateMachine::ProcessL, Entry" )
+    
+    TBool accept = iCurrentState->AcceptL( aEvent );
+    
+    if ( accept )
+        {
+        TNSPStateIndex currState = STATE_ID_L( iStateArray, iCurrentState );
+        aEvent.NextState() = currState;
+        
+        LOGSTATE( currState );
+        LOGEVENT( aEvent );
+        
+        iCurrentState->ApplyL( aEvent );
+        
+        if ( currState != aEvent.NextState() )
+            {
+            NSPLOG_STR( "CNSPStateMachine::ProcessL, Changing session state." )
+            LOGOLDSTATE( currState )
+            
+            IsAcceptableStateTransitionL( aEvent.NextState() );
+            
+            LOGSNEWTATE( aEvent.NextState() )
+            
+            iCurrentState->ExitL( aEvent );
+            CNSPStateBase* newState = iStateArray[aEvent.NextState()];
+            TRAPD( error, newState->StateEntryL( aEvent ) );
+            
+            if ( KErrNone != error )
+                {
+                NSPLOG_STR( "CNSPStateMachine::ProcessL, StateEntryL leave!" )
+                NSPLOG_INT( "CNSPStateMachine::ProcessL, With leave code", error )
+                NSPLOG_STR( "CNSPStateMachine::ProcessL, Reversing.." )
+                iCurrentState->Reverse( aEvent );
+                User::Leave( error );
+                }
+            else
+                {
+                iCurrentState = newState;
+                }
+            }
+        }
+    else
+    	{
+    	NSPLOG_STR( "CNSPStateMachine::ProcessL, Ignoring event." )
+    	}
+    
+    NSPLOG_STR( "CNSPStateMachine::ProcessL, Exit" )
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPStateMachine::IsAcceptableStateTransitionL
+// ---------------------------------------------------------------------------
+//
+void CNSPStateMachine::IsAcceptableStateTransitionL( 
+        TNSPStateIndex aStateIndex ) const
+    {
+    User::LeaveIfError( IsAcceptableStateTransition( aStateIndex ) ?
+            KErrNone : KErrArgument );
+    }
+
+
+// ---------------------------------------------------------------------------
+// CNSPStateMachine::IsAcceptableStateTransition
+// ---------------------------------------------------------------------------
+//
+TBool CNSPStateMachine::IsAcceptableStateTransition(
+        TNSPStateIndex aStateIndex ) const
+    {
+    const TNSPStateIndex currstate = iStateArray.Find( iCurrentState );
+    
+    switch( currstate )
+        {
+        case KErrNotFound:
+            {
+            NSPLOG_STR(
+            "CNSPStateMachine::IsAcceptableStateTransition(), Not found" )
+            return EFalse;
+            }
+        
+        case KStateIndexInitializing:
+        	{
+        	if ( KStateIndexIdle == aStateIndex )
+        		{
+        		return ETrue;
+        		}
+        	else
+        		{
+        		return EFalse;
+        		}
+        	}
+        
+        case KStateIndexIdle:
+            {
+            if ( KStateIndexLocalCand == aStateIndex )
+                {
+                return ETrue;
+                }
+            else
+                {
+                return EFalse;
+                }
+            }
+        
+        case KStateIndexLocalCand:
+            {
+            if ( KStateIndexNegotiating == aStateIndex ||
+                 KStateIndexResolving == aStateIndex ||
+                 KStateIndexActivating == aStateIndex )
+                {
+                return ETrue;
+                }
+            else
+                {
+                return EFalse;
+                }
+            }
+        
+        case KStateIndexNegotiating:
+            {
+            if ( KStateIndexResolving == aStateIndex ||
+                 KStateIndexActivating == aStateIndex )
+                {
+                return ETrue;
+                }
+            else
+                {
+                return EFalse;
+                }
+            }
+        
+        case KStateIndexResolving:
+            {
+            if ( KStateIndexActivating == aStateIndex )
+                {
+                return ETrue;
+                }
+            else
+                {
+                return EFalse;
+                }
+            }
+        
+        case KStateIndexActivating:
+            {
+            if ( KStateIndexConnected == aStateIndex ||
+                 KStateIndexDeActivating == aStateIndex )
+                {
+                return ETrue;
+                }
+            else
+                {
+                return EFalse;
+                }
+            }
+        
+        case KStateIndexConnected:
+            {
+            if ( KStateIndexLocalCand == aStateIndex ||
+                 KStateIndexActivating == aStateIndex ||
+                 KStateIndexResolving == aStateIndex ||
+                 KStateIndexDeActivating == aStateIndex )
+                {
+                return ETrue;
+                }
+            else
+                {
+                return EFalse;
+                }
+            }
+        
+        case KStateIndexDeActivating:
+            {
+            return EFalse; // end state, no transitions allowed
+            }
+        
+        default:
+            {
+            // never should come here,
+            // since all state transitions are handled above
+            NSPLOG_STR(
+            "CNSPStateMachine::IsAcceptableStateTransition(), DEFAULT" )
+            return EFalse;
+            }
+        }
+    }
+
+
+// end of file