multimediacommsengine/mmcesrv/mmceserver/src/mcestateconfirming.cpp
changeset 0 1bce908db942
child 5 5e57de868bc0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multimediacommsengine/mmcesrv/mmceserver/src/mcestateconfirming.cpp	Tue Feb 02 01:04:58 2010 +0200
@@ -0,0 +1,461 @@
+/*
+* Copyright (c) 2005 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:  
+*
+*/
+
+
+
+
+
+#include "mcestateconfirming.h"
+#include "mcesipsession.h"
+#include "mceactionset.h"
+#include "mcefcactionset.h"
+#include "mceclientserver.h"
+#include "mcesipextensions.h"
+#include "mcenatmacros.h"
+#include <sipdialogassocbase.h>
+#include <sipdialog.h>
+
+
+// -----------------------------------------------------------------------------
+// CMceStateConfirming::CMceStateConfirming
+// -----------------------------------------------------------------------------
+//
+CMceStateConfirming::CMceStateConfirming()
+    : CMceState( KMceStateConfirming )
+	{
+	}
+
+
+// -----------------------------------------------------------------------------
+// CMceStateConfirming::~CMceStateConfirming
+// -----------------------------------------------------------------------------
+//
+CMceStateConfirming::~CMceStateConfirming()
+	{
+	}
+
+
+// -----------------------------------------------------------------------------
+// CMceStateConfirming::DoAcceptL
+// -----------------------------------------------------------------------------
+//
+TBool CMceStateConfirming::DoAcceptL( TMceStateTransitionEvent& aEvent )
+	{
+	User::LeaveIfError( 	                 
+       aEvent.Code() == EMceResponse ||
+       aEvent.Code() == EMceProvisionalResponse ||
+       aEvent.Code() == EMceRedirectionResponse ||
+       aEvent.Code() == EMceErrorResponse ||
+       aEvent.Code() == EMceItcCancel ||
+       aEvent.Code() == EMceMediaUpdated ||      
+       aEvent.Code() == EMceItcEnable ||
+       aEvent.Code() == EMceItcDisable ||
+       IsExtensionRequestEvent( aEvent )
+       
+       ? KErrNone : KErrTotalLossOfPrecision );
+    
+	return ETrue;
+	}
+
+// -----------------------------------------------------------------------------
+// CMceStateConfirming::EntryL
+// -----------------------------------------------------------------------------
+//
+void CMceStateConfirming::EntryL( TMceStateTransitionEvent& aEvent )
+	{
+
+	if ( IsExtensionRequestEvent( aEvent ))
+		{
+		HandleExtensionRequestEventL( aEvent );	
+		}
+	else
+		{
+		CMceSipSession& session = aEvent.Session();
+	    switch ( aEvent.Code() )
+	        {
+	        case EMceResponse:
+	            {
+	            EntryResponseL( aEvent );
+	            break;
+	            }
+	        case EMceProvisionalResponse:
+	            {
+	            EntryProvisionalResponseL( aEvent );
+	            break;
+	            }
+	        case EMceRedirectionResponse:
+	        case EMceErrorResponse:
+	            {
+	            EntryErrorResponseL( aEvent );
+	            break;
+	            }
+	        case EMceItcCancel:
+	            {
+	            EntryCancelL( aEvent );
+	            break;
+	            }
+	        case EMceMediaUpdated:
+	            {
+	            EntryMediaUpdatedL( aEvent );
+	            break;
+	            }
+	        case EMceItcEnable:
+	        case EMceItcDisable:
+	            {
+	            session.Actions().ControlMediaL( aEvent.ParamIDs(), 
+	                                             (TMceItcFunctions)aEvent.Code() );
+	            break;
+	            }  
+	        default:
+	            {
+	            // NOP
+	            break;
+	            }
+	        }
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CMceStateConfirming::ExitL
+// -----------------------------------------------------------------------------
+//
+void CMceStateConfirming::ExitL( TMceStateTransitionEvent& aEvent )
+	{
+	
+	if ( IsExtensionRequestEvent( aEvent ))
+		{
+		//Do Nothing;
+		}
+
+	else
+		{
+	    CMceSipSession& session = aEvent.Session();
+	    switch ( aEvent.Code() )
+	        {
+	        case EMceMediaUpdated:
+	            {
+	            ExitMediaUpdatedL( aEvent );
+	            break;
+	            }
+	        case EMceItcCancel:
+	            {
+	            session.Actions().StateChanged( KMceStateCanceled );
+	            session.Actions().ClientStateChanged( aEvent.ParamIDs(), 
+	                                                  CMceSession::ECancelling );
+	            break;
+	            }
+	        case EMceErrorResponse:
+	        case EMceRedirectionResponse:
+	            {
+	            // session canceled
+	            session.Actions().StateChanged( KMceStateCanceled );
+	            session.Actions().ClientStateChangedL( CMceSession::ECancelling,
+	                                                   session.Response() );
+	                                                          
+	            break;                                                   
+	            }
+	        default:
+	            {
+	            break;
+	            }
+	        }
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CMceStateConfirming::EntryResponseL
+// -----------------------------------------------------------------------------
+//
+void CMceStateConfirming::EntryResponseL( TMceStateTransitionEvent& aEvent )
+    {
+    CMceSipSession& session = aEvent.Session();
+    RStringF trx = session.Response().Type();
+    
+    TMceReturnStatus status = KMceReady;
+    CSIPClientTransaction& response = session.Response(); 
+    TBool hasContent = MceSip::HasContent( response );
+        
+    if ( trx == SIPStrings::StringF( SipStrConsts::EInvite ) )
+        {
+        // 2xx to INVITE already, send ACK
+        session.Actions().SendACKL( response );
+        
+        if ( hasContent )
+            {
+            // since the answer is already received, 
+            // seize resending UPDATE/PRACK
+            TBool interrupted = session.Actions().InterruptConfirming();
+            User::LeaveIfError( interrupted ? 
+                KErrNone : KErrTotalLossOfPrecision );
+            
+            // there is SDP, treat it as answer
+            User::LeaveIfError( session.Actions().CreateSDP( response ) );
+            session.Actions().DecodeL();
+            status = session.Actions().UpdateL();
+            if ( status == KMceReady )
+                {
+                if ( MCE_NEED_TO_SEND( session, NULL ) )
+                    {
+                    // send re-INVITE
+                    session.Actions().EncodeL();
+                    session.Actions().SendInviteL();
+                    }
+                aEvent.Code() = EMceMediaUpdated;
+                }
+            else if ( MCE_IS_ERROR( status ) )
+                {
+                User::Leave( status );
+                }
+            else // KMceAsync
+                {
+                // NOP
+                }                
+            }
+        else
+            {
+            // TODO: IF ( answerNeeded ) 
+            //       THEN wait until the PRACK/UPDATE generates a response.
+            //       ELSE consider session established
+            }
+        }
+    else if ( trx == SIPStrings::StringF( SipStrConsts::EUpdate ) ||
+              trx == SIPStrings::StringF( SipStrConsts::EPrack ) )
+        {
+        // 2xx to PRACK/UPDATE
+        
+        if ( hasContent )
+            {
+            NAT_WAIT_NO_EXEC( session, (status = session.Actions().CreateSDP( response )));
+            if ( !MCE_IS_ERROR( status ) && MCE_NEED_TO_SEND( session, NULL ) )
+                {
+                if ( session.ActiveBody().SecureSession() )
+                	{
+                	session.ActiveBody().SecureSession()->iLSReadyToBind = ETrue;
+                	}
+                status = session.Actions().DecodeL();
+                if ( status == KMceSipPreconditionFailure )
+                	{
+                	User::Leave( status );
+                	}
+                else
+                	{
+                	status = session.Actions().UpdateL();
+                	}
+                }
+            }
+        
+        if ( status == KMceReady )
+            {
+            if ( ( MCE_NEED_TO_SEND( session, NULL ) || 
+               ( trx == SIPStrings::StringF( SipStrConsts::EPrack ) &&
+                 session.Extensions().RemoteIMSRel5() )  )&&
+                 session.ActiveBody().Modifier( KMceSecPreconditions )!=
+                 	 KMcePreconditionsE2ESupported )
+                 
+                {
+                
+                if (!hasContent)
+                    {
+                        // Do nothing.
+                    }
+                else
+                    {
+                    status = session.Actions().UpdateL();
+                    __ASSERT_ALWAYS( status == KMceReady, User::Leave( KErrArgument ) );
+                    if ( session.ActiveBody().SecureSession() )
+                    	{
+                    	session.ActiveBody().SecureSession()->iLSReadyToBind = ETrue;
+                    	}
+                    NAT_WAIT_NO_EXEC( session, session.Actions().EncodeL() );
+                    session.Actions().SendUpdateRequestL();
+                    }
+                }
+            aEvent.Code() = EMceMediaUpdated;
+            }
+        else if ( MCE_IS_ERROR( status ) )
+            {
+            User::Leave( status );
+            }
+        else // KMceAsync
+            {
+            // NOP
+            }
+        aEvent.ParamStatus() = status;
+        }
+    else
+        {
+        User::Leave( KErrTotalLossOfPrecision );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMceStateConfirming::EntryProvisionalResponseL
+// -----------------------------------------------------------------------------
+//
+void CMceStateConfirming::EntryProvisionalResponseL( 
+                                        TMceStateTransitionEvent& /*aEvent*/ )
+    {
+    // IF retransmission THEN ignore
+    // ELSE IF sent reliably THEN send PRACK
+    // 
+    // IF 180 ringing THEN give to application
+    // TBD: What if 180 Ringing comes here?
+    }
+
+// -----------------------------------------------------------------------------
+// CMceStateConfirming::EntryErrorResponseL
+// -----------------------------------------------------------------------------
+//    
+void CMceStateConfirming::EntryErrorResponseL( 
+                                        TMceStateTransitionEvent& aEvent )
+    {
+    CMceSipSession& session = aEvent.Session();
+    RStringF trx = session.Response().Type();
+    TUint code = MceSip::ResponseCode( session.Response() );
+    
+    if ( trx == SIPStrings::StringF( SipStrConsts::EInvite ) )
+        {
+        if ( session.SubState() == CMceSipSession::EOffering )
+            {
+            session.Actions().StateChanged( KMceStateTerminated );
+            session.Actions().ClientStateChangedL( CMceSession::ETerminated,
+                                                   session.Response() );
+            
+            }
+          
+        else if ( session.SubState() == CMceSipSession::EUpdating ||
+              session.SubState() == CMceSipSession::ERefreshing )
+        	{
+      		if ( code == KMceSipCallOrTransactionDoesNotExist ||
+                 code == KMceSipRequestTimeout ) 
+	            { 
+    	        session.Actions().UpdateFailed();
+	            session.Actions().SendBYEL();
+                session.Actions().StopMedia();
+                session.FCActions().ReleaseFC();
+                session.Actions().StateChanged( KMceStateTerminated );
+            	session.Actions().ClientStateChangedL( CMceSession::ETerminated,
+                                               session.Response() );
+                }
+         	else
+                {
+    	        session.Actions().UpdateFailed(); 
+  	        	session.Actions().StateChanged( KMceStateEstablished );
+				session.Actions().ClientStateChangedL( CMceSession::EEstablished, 
+                                               *session.Body(),
+                                               session.Response(),
+                                               KErrCancel );
+                }
+        	}
+                
+        }
+    
+    else if ( trx == SIPStrings::StringF( SipStrConsts::EUpdate ) ||
+              trx == SIPStrings::StringF( SipStrConsts::EPrack ) )
+        {
+        EntryCancelL( aEvent );
+        }
+    else
+        {
+        User::Leave( KErrTotalLossOfPrecision );
+        }
+    }
+    
+// -----------------------------------------------------------------------------
+// CMceStateConfirming::EntryCancelL
+// -----------------------------------------------------------------------------
+//    
+void CMceStateConfirming::EntryCancelL( TMceStateTransitionEvent& aEvent )
+    {
+    CMceSipSession& session = aEvent.Session();
+    CMceSipSession::TSubState subState = session.SubState();
+
+    //(try) send CANCEL
+    session.Actions().SendCancelL();
+
+    if ( subState == CMceSipSession::EOffering )
+        {
+        session.Actions().StopMedia();
+        session.FCActions().ReleaseFC();
+        }
+    else if ( subState == CMceSipSession::EUpdating )
+        {
+        session.Actions().UpdateFailed();
+        }    
+    }
+
+// -----------------------------------------------------------------------------
+// CMceStateConfirming::EntryMediaUpdatedL
+// -----------------------------------------------------------------------------
+//    
+void CMceStateConfirming::EntryMediaUpdatedL( TMceStateTransitionEvent& aEvent )
+    {
+    CMceSipSession& session = aEvent.Session();
+    
+    if ( MCE_NEED_TO_SEND( session, NULL ) )
+        {
+        NAT_WAIT_NO_EXEC( session, session.Actions().EncodeL() );
+        
+        if ( session.Dialog()->Dialog().State() == CSIPDialog::EEarly )
+            {
+            session.Actions().SendUpdateRequestL();    
+            }
+        else
+            {
+            session.Actions().SendInviteL();
+            }
+        }    
+    }
+
+// -----------------------------------------------------------------------------
+// CMceStateConfirming::ExitMediaUpdatedL
+// -----------------------------------------------------------------------------
+//    
+void CMceStateConfirming::ExitMediaUpdatedL( TMceStateTransitionEvent& aEvent )
+    {
+    CMceSipSession& session = aEvent.Session();
+    CSIPClientTransaction* update = session.PendingTransaction(
+        SIPStrings::StringF( SipStrConsts::EUpdate ) );
+    if ( update && !MceSip::TrxCompleted( *update ) )
+        {
+        // just sent UPDATE
+        session.Actions().StateChanged( KMceStateConfirming );
+        }
+    else
+        {
+        CSIPClientTransaction* invite = session.PendingTransaction( 
+                    SIPStrings::StringF( SipStrConsts::EInvite ) );
+        User::LeaveIfError( invite ? KErrNone : 
+            KErrTotalLossOfPrecision );
+
+        if ( invite->StateL() == CSIPTransactionBase::ETerminated )
+            {
+            // Just go to established state
+            session.Actions().ClientStateChangedL( 
+                                    CMceSession::EEstablished,
+                                    *session.Body(),
+                                    session.Response() );
+            session.Actions().StateChanged( KMceStateEstablished );
+            }
+        else
+            {
+            session.Actions().StateChanged( KMceStateOffering );
+            }
+        }    
+    }
+    
+// End of file