multimediacommsengine/mmcesrv/mmceserver/src/mcestateacknowledgementrequired.cpp
changeset 0 1bce908db942
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multimediacommsengine/mmcesrv/mmceserver/src/mcestateacknowledgementrequired.cpp	Tue Feb 02 01:04:58 2010 +0200
@@ -0,0 +1,474 @@
+/*
+* Copyright (c) 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:  
+*
+*/
+
+
+
+
+#include "mcestateacknowledgementrequired.h"
+#include "mcesipsession.h"
+#include "mceactionset.h"
+#include "mcefcactionset.h"
+#include "mcenatmacros.h"
+#include "mcereliablesender.h"
+
+// -----------------------------------------------------------------------------
+// CMceStateAcknowledgementRequired::CMceStateAcknowledgementRequired
+// -----------------------------------------------------------------------------
+//
+CMceStateAcknowledgementRequired::CMceStateAcknowledgementRequired()
+    : CMceState( KMceStateAcknowledgementRequired )
+	{
+	}
+
+
+// -----------------------------------------------------------------------------
+// CMceStateAcknowledgementRequired::~CMceStateAcknowledgementRequired
+// -----------------------------------------------------------------------------
+//
+CMceStateAcknowledgementRequired::~CMceStateAcknowledgementRequired()
+	{
+	}
+
+
+// -----------------------------------------------------------------------------
+// CMceStateAcknowledgementRequired::DoAcceptL
+// -----------------------------------------------------------------------------
+//
+TBool CMceStateAcknowledgementRequired::DoAcceptL( 
+                                        TMceStateTransitionEvent& aEvent )
+	{
+	User::LeaveIfError(
+       aEvent.Code() == EMcePrack ||
+       aEvent.Code() == EMceMediaUpdated ||
+       aEvent.Code() == EMceNoPrackReceived ||
+       aEvent.Code() == EMceReliableFailed ||
+       aEvent.Code() == EMceAck  ||      
+       aEvent.Code() == EMceItcEnable ||
+       aEvent.Code() == EMceItcDisable ||
+       aEvent.Code() == EMceItcAcceptSession ||
+       aEvent.Code() == EMceItcRejectSession ||
+       IsExtensionRequestEvent( aEvent )
+       
+       ? KErrNone : KErrTotalLossOfPrecision );
+    
+	return ETrue;
+	}
+
+// -----------------------------------------------------------------------------
+// CMceStateAcknowledgementRequired::EntryL
+// -----------------------------------------------------------------------------
+//
+void CMceStateAcknowledgementRequired::EntryL( 
+                                        TMceStateTransitionEvent& aEvent )
+	{
+	
+	if ( IsExtensionRequestEvent( aEvent ))
+		{
+		HandleExtensionRequestEventL( aEvent );	
+		}
+	
+	else
+		{
+	    switch ( aEvent.Code() )
+	        {
+	        case EMcePrack:
+	            {
+	            EntryPrackL( aEvent );
+	            break;
+	            }
+	        case EMceMediaUpdated:
+	            {
+	            EntryMediaUpdatedL( aEvent );
+	            break;
+	            }
+	        case EMceNoPrackReceived:
+	            {
+	            EntryNoPrackReceivedL( aEvent );
+	            break;             
+	            }
+	        case EMceReliableFailed:
+	            {
+	            EntryReliableFailedL ( aEvent ); 
+	            break;       
+	            }
+	        case EMceItcEnable:
+	        case EMceItcDisable:
+	            {
+	            aEvent.Session().Actions().ControlMediaL( aEvent.ParamIDs(), 
+	                                             (TMceItcFunctions)aEvent.Code() );
+	            break;
+	            }  
+	        case EMceItcAcceptSession:
+	            {
+	            EntryEarlyAcceptL( aEvent );
+	            break;
+	            }
+	        
+			case EMceItcRejectSession:
+	            {
+	            CMceSipSession& session = aEvent.Session();
+				CSIPServerTransaction& request = session.Request();
+				
+	            aEvent.Session().Actions().SendDeclineL( request, 
+	                                            aEvent.ParamClientMessage() );
+				                                            
+	            aEvent.Session().Actions().StopMedia();
+	            aEvent.Session().FCActions().ReleaseFC();
+	            break;
+	            }
+	            
+
+	        default: 
+	            {
+	            // NOP
+	            break;
+	            }
+	        }
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CMceStateAcknowledgementRequired::ExitL
+// -----------------------------------------------------------------------------
+//
+void CMceStateAcknowledgementRequired::ExitL( TMceStateTransitionEvent& aEvent )
+	{
+	
+	if ( IsExtensionRequestEvent( aEvent ))
+		{
+		//Do Nothing;
+		}
+	
+	else 
+		{
+		CMceSipSession& session = aEvent.Session();
+		TInt status = aEvent.ParamStatus();
+		switch ( aEvent.Code() )
+	        {
+	        case EMcePrack:
+	            {
+	            if ( MCE_IS_ERROR( status ) )
+	                {
+	                session.Actions().StateChanged( KMceStateTerminated );
+	                session.Actions().ClientStateChangedL( CMceSession::ETerminated );
+	                }
+	            else
+	                {
+	                //NOTE this is only for media reservation, not for resource
+	                //reservation
+	                if ( status == KMceAsync )
+	                    {
+						//PRACK caused media to be ready asynchronously
+	                    }
+	                else if ( status == KMceReady && 
+	                	    MCE_NEED_TO_RECEIVE( session ) )
+	                    {
+	                    //media is ready, but preconditions are not met
+	                    session.Actions().StateChanged( KMceStateConfirmationRequired );
+	                    }
+	                                                                       
+	                else 
+	                    {
+	                    // media is ready and preconditions are met
+	                    ProceedToUpdatedL( aEvent );
+	                    }
+	                }
+	            break;
+	            }
+	        case EMceMediaUpdated:
+	            {
+	            if ( MCE_IS_ERROR( status ) )
+	                {
+	                session.Actions().StateChanged( KMceStateTerminated );
+	                session.Actions().ClientStateChangedL( CMceSession::ETerminated );
+	                }
+	            else if ( status == KMceReady )
+	                {
+	                // Other possible state changes handle in entry
+	                session.Actions().StateChanged( KMceStateConfirmationRequired );
+	                }
+	            else // KMceAsync
+	                {
+	                session.Actions().StateChanged( KMceStateServerReserving );
+	                }
+	            break;
+	            }
+	         
+	        case EMceNoPrackReceived:
+	            {
+	            session.Actions().StateChanged( KMceStateTerminated );
+	            session.Actions().ClientStateChangedL( CMceSession::ETerminated,
+	                                                   KErrTimedOut );
+	            break;             
+	            }
+	            
+	        case EMceReliableFailed:
+	            {
+	            session.Actions().StateChanged( KMceStateTerminated );
+	            session.Actions().ClientStateChangedL( CMceSession::ETerminated,
+	                                                   aEvent.ParamStatus());
+	            break;
+	            }
+		
+			case EMceItcRejectSession:
+	            {
+	            session.Actions().StateChanged( KMceStateTerminated );
+	            session.Actions().ClientStateChanged( aEvent.ParamIDs(), 
+	                                                  CMceSession::ETerminated );
+	            break;
+	            }
+	            
+	                    
+	        default: 
+	            {
+	            // NOP
+	            break;
+	            }
+	        }
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CMceStateAcknowledgementRequired::EntryPrackL
+// -----------------------------------------------------------------------------
+//
+void CMceStateAcknowledgementRequired::EntryPrackL( 
+                                            TMceStateTransitionEvent& aEvent )
+    {
+    CMceSipSession& session = aEvent.Session();
+    // validate PRACK
+    TBool match = session.ReliableSender().PrackReceived( session.Request() );
+    TMceSipWarningCode warning = KErrNone;
+    if ( match )
+        {
+        if ( MceSip::HasContent( session.Request() ) )
+            {
+            // PRACK carries SDP
+            User::LeaveIfError( session.Actions().CreateSDP( session.Request() ) );
+          	
+            session.Actions().CreateBodyCandidateL( CMceComSession::EInSession );
+          	
+          	warning = session.Actions().DecodeL();
+          	
+          	session.ActiveBody().iCodecSelection = KMceCodecSelectionMerge;
+          	
+            aEvent.ParamStatus() = !warning ? KErrNone : KErrAbort;
+            if ( !warning )
+                {
+                TMceReturnStatus status = session.Actions().UpdateL();
+                //Second update is needed.
+                status = session.Actions().UpdateL();
+                aEvent.ParamStatus() = status;
+                if ( status == KMceReady )
+                    {
+                    aEvent.Code() = EMceMediaUpdated;
+                    EntryMediaUpdatedL( aEvent );
+                    }
+                }
+            }
+        else
+            {
+            // Empty PRACK
+            // Send 200 OK
+            session.Actions().Send200OKL( session.Request() );
+            TMceReturnStatus status = KMceReady;
+            status = session.Actions().ReserveL();
+            
+            aEvent.ParamStatus() = status;
+            if ( status == KMceAsync )
+                {
+                // reservation ongoind
+                session.Actions().StateChanged( KMceStateServerReserving );
+                }
+            }
+            
+        if ( aEvent.Code() != EMceMediaUpdated && 
+             MCE_IS_ERROR( aEvent.ParamStatus() ) )
+            {
+            if ( warning ) //if error, reject offer (4XX out)
+                {
+                session.Actions().SendRejectOfferWithWarningL( warning, session.Request() );
+                }
+            else
+                {
+                MceSip::DiscardRequest( session.Request() );
+                }
+                
+            //reject also invite
+            session.DiscardInvite();
+            }
+        }            
+    else // not match
+        {
+        // Reject the PRACK
+        // Suitable Error code can be defined when PRACK is not mached
+        // to handle state transition
+        aEvent.ParamStatus() = KErrNotFound; 
+        MceSip::DiscardRequest( session.Request(), 
+                                KMceSipCallOrTransactionDoesNotExist ); 
+                                                                          
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMceStateAcknowledgementRequired::EntryMediaUpdatedL
+// -----------------------------------------------------------------------------
+//
+void CMceStateAcknowledgementRequired::EntryMediaUpdatedL( 
+                                            TMceStateTransitionEvent& aEvent )
+    {
+    CMceSipSession& session = aEvent.Session();
+    CSIPServerTransaction& prack = session.Request();
+    // verify, that PRACK really is the previous request
+    __ASSERT_ALWAYS( prack.Type() == SIPStrings::StringF( SipStrConsts::EPrack ), 
+         User::Leave( KErrTotalLossOfPrecision ) );
+    
+    TMceReturnStatus status = session.Actions().ReserveL();
+    aEvent.ParamStatus() = status;
+    if ( MCE_IS_ERROR( aEvent.ParamStatus() ) )
+        {
+        MceSip::DiscardRequest( session.Request() );
+            
+        //reject also invite
+        session.DiscardInvite();
+        }
+    else 
+        {
+        // send 2xx to PRACK
+        if ( session.ActiveBody().SecureSession() )
+        	{
+        	session.ActiveBody().SecureSession()->iLSReadyToBind = ETrue;
+        	}
+
+		// In KMceNatStateDecodeOffer state, answer is available.
+		// Pull mode is not used with long signalling.
+		if ( !( session.NatSession() &&
+			  ( ( session.NatState() == KMceNatStateCreateOffer )  ||
+			    ( session.NatState() == KMceNatStateCreateAnswer ) ||
+			    ( session.NatState() == KMceNatStateWait )         ||
+			    ( session.NatState() == KMceNatStateConnected ) ) ) )
+			{
+			session.Actions().EncodeL();
+			}
+		session.FCActions().UpdateFCAnswerL( *session.Offer() );
+        session.Actions().SendAnswerL( prack );
+
+	    session.Actions().UpdateSucceed();
+        	
+        if ( !MCE_NEED_TO_RECEIVE( session ) &&  !MCE_FORCED_TO_RECEIVE( session ) )
+            {
+            ProceedToUpdatedL( aEvent );
+            } 
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMceStateAcknowledgementRequired::EntryNoPrackReveivedL
+// -----------------------------------------------------------------------------
+//
+void CMceStateAcknowledgementRequired::EntryNoPrackReceivedL( 
+    TMceStateTransitionEvent& aEvent )
+    {
+    CMceSipSession& session = aEvent.Session();
+    CSIPServerTransaction& serverTransaction = session.Request();
+    MceSip::DiscardRequest( serverTransaction, 
+                           KMceSipServerTimeOut, 
+                           KMceNoRetryAfter );
+    
+    if ( session.SubState() == CMceSipSession::EOffering ||
+         session.SubState() == CMceSipSession::EAnswering )
+        {
+        session.Actions().StopMedia();
+        session.FCActions().ReleaseFC();
+        }
+    else if ( session.SubState() == CMceSipSession::EUpdating )
+        {
+        session.Actions().UpdateFailed();
+        }
+    else
+        {
+        // NOP
+        }
+    }
+    
+// -----------------------------------------------------------------------------
+// CMceStateAcknowledgementRequired::EntryReliableFailedL
+// -----------------------------------------------------------------------------
+//
+void CMceStateAcknowledgementRequired::EntryReliableFailedL( 
+    TMceStateTransitionEvent& aEvent )
+    {
+
+    CMceSipSession& session = aEvent.Session();
+    CSIPServerTransaction& serverTransaction = session.Request();
+    MceSip::DiscardRequest( serverTransaction, 
+                           KMceSipServerInternalError, 
+                           KMceNoRetryAfter );
+                   
+    if ( session.SubState() == CMceSipSession::EOffering ||
+         session.SubState() == CMceSipSession::EAnswering )
+        {
+        session.Actions().StopMedia();
+        session.FCActions().ReleaseFC();
+        }
+    else if ( session.SubState() == CMceSipSession::EUpdating )
+        {
+        session.Actions().UpdateFailed();
+        }
+    else
+        {
+        // NOP 
+        }                           
+    }
+
+// -----------------------------------------------------------------------------
+// CMceStateAcknowledgementRequired::EntryEarlyAcceptL
+// -----------------------------------------------------------------------------
+//    
+void CMceStateAcknowledgementRequired::EntryEarlyAcceptL( 
+    TMceStateTransitionEvent& aEvent )
+    {
+    // Client accepted the session before prack was received, remember that
+    // 200 OK for invite is sent when possible.
+    CMceSipSession& session = aEvent.Session();
+    session.StoreAutoEventL( &aEvent, &session.InitialRequest() );
+    }
+
+// -----------------------------------------------------------------------------
+// CMceStateAcknowledgementRequired::ProceedToUpdatedL
+// -----------------------------------------------------------------------------
+//
+void CMceStateAcknowledgementRequired::ProceedToUpdatedL(
+    TMceStateTransitionEvent& aEvent )
+    {
+    CMceSipSession& session = aEvent.Session();
+    
+    TMceStateTransitionEvent* acceptEvent = session.StoredAutoEvent();                                          
+    if ( acceptEvent && acceptEvent->Code() == EMceItcAcceptSession )
+        {
+        // Session was accepted before really possible and now accepting is
+        // possible, enable automatic event generation to occur at state change
+        session.SetAutoEvent( ETrue );
+        }
+    
+    session.Actions().StateChanged( KMceStateUpdated );
+    session.Actions().ClientStateChangedL( CMceSession::EProceeding,
+                                           *session.Body(),
+                                           KErrNone );
+    }
+    
+// End of file