sipvoipprovider/svphold/src/svpholdoutestablishingstate.cpp
branchRCL_3
changeset 22 d38647835c2e
parent 0 a4daefaec16c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sipvoipprovider/svphold/src/svpholdoutestablishingstate.cpp	Wed Sep 01 12:29:57 2010 +0100
@@ -0,0 +1,477 @@
+/*
+* Copyright (c) 2006-2008 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:  Outgoing request establishing state for hold state machine.
+*
+*/
+
+
+#include    <badesca.h>
+#include    "mcesession.h"
+#include    "mcemediastream.h"
+#include    "mceaudiostream.h"
+#include    "svpholdoutestablishingstate.h"
+#include    "svpholdcontext.h"
+#include    "svpholdcontroller.h"
+#include    "svpholdattributehandler.h"
+#include    "svpholdobserver.h"
+#include    "svplogger.h"
+
+
+// ---------------------------------------------------------------------------
+// CSVPHoldOutEstablishingState::CSVPHoldOutEstablishingState
+// ---------------------------------------------------------------------------
+CSVPHoldOutEstablishingState::CSVPHoldOutEstablishingState()
+    {
+    }
+
+// ---------------------------------------------------------------------------
+// CSVPHoldOutEstablishingState::NewLC
+// ---------------------------------------------------------------------------
+CSVPHoldOutEstablishingState* CSVPHoldOutEstablishingState::NewLC()
+    {
+    CSVPHoldOutEstablishingState* self = 
+        new ( ELeave ) CSVPHoldOutEstablishingState;
+    CleanupStack::PushL( self );
+    return self;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CSVPHoldOutEstablishingState::~CSVPHoldOutEstablishingState
+// ---------------------------------------------------------------------------
+CSVPHoldOutEstablishingState::~CSVPHoldOutEstablishingState()
+    {
+    }
+
+// ---------------------------------------------------------------------------
+// CSVPHoldOutEstablishingState::DoApplyL
+// ---------------------------------------------------------------------------
+//
+void CSVPHoldOutEstablishingState::DoApplyL( CSVPHoldContext& aContext )
+    {
+    SVPDEBUG1( "CSVPHoldOutEstablishingState::DoApply" );
+    
+    TSVPHoldStateIndex nextState = KSVPHoldEstablishingStateIndex; 
+    CMceSession* session = aContext.SessionObject();
+    const RPointerArray< CMceMediaStream >& streams = session->Streams();
+    TInt streamCount = streams.Count();
+    
+    // Hold / Resume handling depends on the response received from network and
+    // timers; any differences from normal handled in SpecialResponseHandling:
+    if ( !aContext.SpecialResponseHandling( nextState ) )
+        {
+        for ( TInt i = 0; i < streamCount; i++ )
+            {
+            CMceMediaStream* mediaStream = streams[ i ];
+            TMceMediaType mediaType = mediaStream->Type();
+            if ( KMceAudio == mediaType )
+                {
+                // This media is audio stream. Handling depends on the request
+                switch ( aContext.HoldRequest() )
+                    {
+                    case ESVPLocalHold:
+                    case ESVPLocalResume:
+                    case ESVPLocalDoubleHold:
+                    case ESVPLocalDoubleHoldResume:
+                        {
+                        HandleLocalHoldL( aContext, mediaStream, nextState );
+                        break;
+                        }
+                    
+                    case ESVPRemoteHold:
+                    case ESVPRemoteResume:
+                    case ESVPRemoteDoubleHold:
+                    case ESVPRemoteDoubleHoldResume:
+                        {
+                        SVPDEBUG1(
+                        "CSVPHoldOutEstablishingState::DoApply\
+                         - Remote action - State Error" );                   
+                        User::Leave( KErrSVPHoldStateError );
+                        }
+                        
+                    default:
+                        {
+                        // Error in request solving
+                        SVPDEBUG2(
+                        "CSVPHoldOutEstablishingState::CSVPHoldOutEstablishingState\
+                         - Error, request %i",
+                        aContext.HoldRequest() );
+                        break;
+                        }
+                    }
+                }
+            }    
+        }
+    
+    aContext.SetCurrentStateL( aContext, nextState );
+    SVPDEBUG1( "CSVPHoldOutEstablishingState::DoApply - Handled" );
+    }
+    
+// ---------------------------------------------------------------------------
+// CSVPHoldOutEstablishingState::DoEnter
+// ---------------------------------------------------------------------------
+//
+void CSVPHoldOutEstablishingState::DoEnter( CSVPHoldContext& /*aContext*/ )
+    {
+    SVPDEBUG1( "CSVPHoldOutEstablishingState::DoEnter" );
+    }
+
+// ---------------------------------------------------------------------------
+// CSVPHoldOutEstablishingState::IsOutEstablishingStateActive
+// ---------------------------------------------------------------------------
+//
+TBool CSVPHoldOutEstablishingState::IsOutEstablishingStateActive()
+    {
+    return ETrue;
+    }
+    
+// ---------------------------------------------------------------------------
+// CSVPHoldOutEstablishingState::HandleLocalHoldL
+// ---------------------------------------------------------------------------
+//
+void CSVPHoldOutEstablishingState::
+HandleLocalHoldL( CSVPHoldContext& aContext,
+                  CMceMediaStream* aMediaStream,
+                  TSVPHoldStateIndex& aNextState )
+    {
+    switch ( aContext.HoldRequest() )
+        {
+        case ESVPLocalHold:
+            {
+            // From Connected state
+            HandleLocalHoldingL( aContext,
+                                 aMediaStream,
+                                 aNextState );
+            break;
+            }
+            
+        case ESVPLocalResume:
+            {
+            // From Out state
+            HandleLocalResumingL( aContext,
+                                  aMediaStream,
+                                  aNextState );
+            break;
+            }
+
+        case ESVPLocalDoubleHold:
+            {
+            // From In state
+            HandleLocalHoldingL( aContext,
+                                 aMediaStream,
+                                 aNextState,
+                                 KSVPHoldDHStateIndex );
+            break;
+            }
+
+         case ESVPLocalDoubleHoldResume:
+            {
+            // From Doublehold state
+            HandleLocalResumingL( aContext,
+                                  aMediaStream,
+                                  aNextState,
+                                  KSVPHoldInStateIndex );
+            break;
+            }       
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CSVPHoldOutEstablishingState::HandleLocalHoldingL
+// ---------------------------------------------------------------------------
+//
+void CSVPHoldOutEstablishingState::
+HandleLocalHoldingL( CSVPHoldContext& aContext,
+                     CMceMediaStream* mediaStream,
+                     TSVPHoldStateIndex& aNextState,
+                     TSVPHoldStateIndex aState )
+    {
+    SVPDEBUG1(
+    "CSVPHoldOutEstablishingState::HandleLocalHoldingL" );
+    
+    MDesC8Array* attributeLines = mediaStream->MediaAttributeLinesL();
+    CleanupDeletePushL( attributeLines );
+
+    if ( KSVPHoldDHStateIndex == aState )
+        {
+        SVPDEBUG1(
+        "CSVPHoldOutEstablishingState::HandleLocalHoldingL\
+         - Next KSVPHoldDHStateIndex" );
+        //aNextState = KSVPHoldDHStateIndex;
+        KSVPHoldAttributeIndex neededAttribute = KSVPHoldInactiveIndex;
+        CheckAttributeL( attributeLines,
+                         neededAttribute,
+                         aNextState,
+                         aContext );
+        }
+    else
+        {
+        SVPDEBUG1(
+        "CSVPHoldOutEstablishingState::HandleLocalHoldingL\
+         - Next KSVPHoldOutStateIndex" );
+        //aNextState = KSVPHoldOutStateIndex;
+        KSVPHoldAttributeIndex neededAttribute = KSVPHoldRecvonlyIndex;
+        CheckAttributeL( attributeLines,
+                         neededAttribute,
+                         aNextState,
+                         aContext );
+        }
+
+    CleanupStack::PopAndDestroy( attributeLines );
+    
+    SVPDEBUG1( "CSVPHoldOutEstablishingState::HandleLocalHoldingL - Done" );
+    }
+
+// ---------------------------------------------------------------------------
+// CSVPHoldOutEstablishingState::HandleLocalResumingL
+// ---------------------------------------------------------------------------
+//
+void CSVPHoldOutEstablishingState::
+HandleLocalResumingL( CSVPHoldContext& aContext,
+                      CMceMediaStream* mediaStream,
+                      TSVPHoldStateIndex& aNextState,
+                      TSVPHoldStateIndex aState )
+    {
+    SVPDEBUG1(
+    "CSVPHoldOutEstablishingState::HandleLocalResumingL" );
+    
+    MDesC8Array* attributeLines = mediaStream->MediaAttributeLinesL();
+    CleanupDeletePushL( attributeLines );
+    
+    if ( KSVPHoldInStateIndex == aState )
+        {
+        // Resume from doublehold:
+        SVPDEBUG1(
+        "CSVPHoldOutEstablishingState::HandleLocalResumingL\
+         - Next KSVPHoldInStateIndex" );
+        //aNextState = KSVPHoldInStateIndex;
+        KSVPHoldAttributeIndex neededAttribute = KSVPHoldSendonlyIndex;
+        CheckAttributeL( attributeLines,
+                         neededAttribute,
+                         aNextState,
+                         aContext );    
+        }
+        
+    else
+        {
+        // Basic resume:
+        SVPDEBUG1(
+        "CSVPHoldOutEstablishingState::HandleLocalResumingL\
+         - Next KSVPHoldConnectedStateIndex" );
+        //aNextState = KSVPHoldConnectedStateIndex;
+        KSVPHoldAttributeIndex neededAttribute = KSVPHoldSendrecvIndex;
+        CheckAttributeL( attributeLines,
+                         neededAttribute,
+                         aNextState,
+                         aContext );                                  
+        }
+        
+    CleanupStack::PopAndDestroy( attributeLines );
+
+    SVPDEBUG1(
+    "CSVPHoldOutEstablishingState::HandleLocalResumingL - Done" );
+    }
+    
+// ---------------------------------------------------------------------------
+// CSVPHoldOutEstablishingState::CheckAttributeL
+// ---------------------------------------------------------------------------
+//
+TInt CSVPHoldOutEstablishingState::
+CheckAttributeL( MDesC8Array* aAttributeLines,
+                KSVPHoldAttributeIndex aNeededAttribute,
+                TSVPHoldStateIndex& aNextState,
+                CSVPHoldContext& aContext )
+    {
+    SVPDEBUG1( "CSVPHoldOutEstablishingState::CheckAttributeL" );
+
+    KSVPHoldAttributeIndex responseAttribute =
+        aContext.AttributeHandler().FindDirectionAttribute( aAttributeLines );
+
+    if ( KErrNotFound == responseAttribute )
+        {
+        SVPDEBUG1( "CSVPHoldOutEstablishingState::CheckAttributeL - Session level" );
+        
+        MDesC8Array* sessionAttributeLines =
+            aContext.SessionObject()->SessionSDPLinesL();
+        
+        responseAttribute =
+            aContext.AttributeHandler().FindDirectionAttribute(
+                sessionAttributeLines );
+        
+        aContext.SessionObject()->SetSessionSDPLinesL(
+            static_cast<CDesC8Array*>( sessionAttributeLines ) );
+        
+        SVPDEBUG1( "CSVPHoldOutEstablishingState::CheckAttributeL - Session level done" );
+        }
+        
+    if ( aNeededAttribute == responseAttribute || 
+         KErrNotFound == responseAttribute )
+        {
+        // If there is no attributes in response; but 200Ok is received;
+        // state change is done based to default cases.
+        return DefineDefaultCaseStateChange( aContext, aNextState );
+        }
+        
+    else if ( KSVPHoldSendrecvIndex == aNeededAttribute &&
+              KErrNotFound == responseAttribute )
+        {
+        // If there is no direction attribute at all, default is sendrecv
+        SVPDEBUG1(
+        "CSVPHoldOutEstablishingState::CheckAttributeL - No attribute" );
+        aNextState = KSVPHoldConnectedStateIndex;
+        return KErrNone;
+        }
+
+    else if ( KSVPHoldSendrecvIndex == aNeededAttribute &&
+              KSVPHoldRecvonlyIndex == responseAttribute )
+        {
+        // Radvision client fix (it responds to resume with recvonly)
+        SVPDEBUG1(
+        "CSVPHoldOutEstablishingState::CheckAttributeL - recvonly to resume.." );
+        aNextState = KSVPHoldConnectedStateIndex;
+        return KErrNone;
+        }
+    
+    else if ( KSVPHoldRecvonlyIndex == aNeededAttribute &&
+              KSVPHoldInactiveIndex == responseAttribute )
+        {
+        // Inactive response to local hold is allowed
+        SVPDEBUG1(
+        "CSVPHoldOutEstablishingState::CheckAttributeL - No attribute" );
+        aNextState = KSVPHoldOutStateIndex;
+        return KErrNone;
+        }
+        
+    else if( KSVPHoldSendonlyIndex == responseAttribute &&
+             KSVPHoldInactiveIndex == aNeededAttribute )
+        {
+        // Sendonly response to local DH (accept for IOP)
+        SVPDEBUG1(
+        "CSVPHoldOutEstablishingState::CheckAttributeL - Sendonly to Inactive request" );
+        aNextState = KSVPHoldDHStateIndex;
+        return KErrNone;        
+        }
+
+    else if( KSVPHoldSendonlyIndex == aNeededAttribute &&
+             KSVPHoldInactiveIndex == responseAttribute )
+        {
+        // Inactive response to local DH resume (accept for IOP)
+        SVPDEBUG1(
+        "CSVPHoldOutEstablishingState::CheckAttributeL - Inactive to DH resume request" );
+        aNextState = KSVPHoldInStateIndex;
+        return KErrNone;        
+        }   
+    
+    else if ( KSVPHoldSendrecvIndex == responseAttribute )
+        {
+        // Response has sendrecv -attribute
+        return ResolveStateFromSendRecvIndex( aNeededAttribute, aNextState );
+        }
+
+    else
+        {
+        SVPDEBUG1(
+        "CSVPHoldOutEstablishingState::CheckAttributeL - else" );
+        return KErrNone;
+        }        
+    }
+    
+// ---------------------------------------------------------------------------
+// CSVPHoldOutEstablishingState::DefineDefaultCaseStateChange
+// ---------------------------------------------------------------------------
+//
+TInt CSVPHoldOutEstablishingState::
+DefineDefaultCaseStateChange( CSVPHoldContext& aContext,
+                              TSVPHoldStateIndex& aNextState )
+    {
+    SVPDEBUG1( "CSVPHoldOutEstablishingState::DefineDefaultCaseStateChange" );
+    // Basic cases (e.g for holding "sendonly" answer has "recvonly")
+    switch ( aContext.HoldRequest() )
+        {
+        case ESVPLocalHold:
+            {
+            SVPDEBUG1( "    ESVPLocalHold" );
+            aNextState = KSVPHoldOutStateIndex;
+            return KErrNone;
+            }
+             
+        case ESVPLocalResume:
+            {
+            SVPDEBUG1( "    ESVPLocalResume" );
+            aNextState = KSVPHoldConnectedStateIndex;
+            return KErrNone;
+            }
+            
+        case ESVPLocalDoubleHold:
+            {
+            SVPDEBUG1( "    ESVPLocalDoubleHold" );
+            aNextState = KSVPHoldDHStateIndex;
+            return KErrNone;
+            }
+            
+        case ESVPLocalDoubleHoldResume:
+            {
+            SVPDEBUG1( "    ESVPLocalDoubleHoldResume" );
+            aNextState = KSVPHoldInStateIndex;
+            return KErrNone;
+            }
+            
+        default:
+            {
+            SVPDEBUG1(
+            "CSVPHoldOutEstablishingState::DefineDefaultCaseStateChange" );
+             return KErrNone;
+            }
+        }    
+    }
+
+// ---------------------------------------------------------------------------
+// CSVPHoldOutEstablishingState::ResolveStateFromSendRecvIndex
+// ---------------------------------------------------------------------------
+//
+TInt CSVPHoldOutEstablishingState::
+ResolveStateFromSendRecvIndex( KSVPHoldAttributeIndex aNeededAttribute,
+                               TSVPHoldStateIndex& aNextState )
+    {
+    SVPDEBUG1( "CSVPHoldOutEstablishingState::ResolveStateFromSendRecvIndex" );
+    switch ( aNeededAttribute )
+        {
+        case KSVPHoldRecvonlyIndex:
+            {
+            aNextState = KSVPHoldOutStateIndex;
+            return KErrNone;
+            }
+
+        case KSVPHoldInactiveIndex:
+            {
+            aNextState = KSVPHoldDHStateIndex;
+            return KErrNone;
+            }
+
+        case KSVPHoldSendonlyIndex:
+            {
+            aNextState = KSVPHoldInStateIndex;
+            return KErrNone;
+            }
+        
+        default:
+            {
+            SVPDEBUG1(
+            "CSVPHoldOutEstablishingState::CheckAttributeL - Last default" );
+            return KErrNone;
+            }
+        }
+    }    
+
+