multimediacommsengine/mmcesrv/mmceserver/src/mcestateestablished.cpp
changeset 0 1bce908db942
child 17 a5ac35ca6d81
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multimediacommsengine/mmcesrv/mmceserver/src/mcestateestablished.cpp	Tue Feb 02 01:04:58 2010 +0200
@@ -0,0 +1,656 @@
+/*
+* 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 <sipdialogassocbase.h> 
+#include <sipdialog.h>			
+#include "mcestateestablished.h"
+#include "mcesipsession.h"
+#include "mceactionset.h"
+#include "mcefcactionset.h"
+#include "mcenatmacros.h"
+#include "mcesdpsession.h"
+#include "mcesrvlogs.h"
+
+
+// -----------------------------------------------------------------------------
+// CMceStateEstablished::CMceStateEstablished
+// -----------------------------------------------------------------------------
+//
+CMceStateEstablished::CMceStateEstablished ()
+    : CMceState( KMceStateEstablished )
+	{
+	}
+
+// -----------------------------------------------------------------------------
+// CMceStateEstablished::~CMceStateEstablished
+// -----------------------------------------------------------------------------
+//
+CMceStateEstablished::~CMceStateEstablished()
+	{
+	}
+
+// -----------------------------------------------------------------------------
+// CMceStateEstablished::DoAcceptL
+// -----------------------------------------------------------------------------
+//
+TBool CMceStateEstablished::DoAcceptL( TMceStateTransitionEvent& aEvent )
+	{
+	if ( !IsExtensionRequestEvent( aEvent ) &&
+		 aEvent.Code() == EMceResponse && 
+	     MceSip::ResponseCode( aEvent.Session().Response() ) == KMceSipOK )
+		{
+	    return EFalse;		
+		}
+
+    User::LeaveIfError( 	                 
+       aEvent.Code() == EMceItcTerminateSession  ||
+       aEvent.Code() == EMceItcUpdate  ||
+       aEvent.Code() == EMceItcEnable  ||
+       aEvent.Code() == EMceItcDisable  ||
+       aEvent.Code() == EMceMediaSessionStopped  ||
+       aEvent.Code() == EMceInvite  ||
+       aEvent.Code() == EMceUpdate ||
+       aEvent.Code() == EMceBye ||
+       aEvent.Code() == EMceSessionExpired ||
+       aEvent.Code() == EMceSessionRefresh ||
+       aEvent.Code() == EMceSessionPending ||
+       aEvent.Code() == EMceErrorResponse || // 487 for CANCEL
+       IsExtensionRequestEvent( aEvent )
+       
+       ? KErrNone : KErrTotalLossOfPrecision );
+           
+	return ETrue;
+	}
+
+// -----------------------------------------------------------------------------
+// CMceStateEstablished::StateEntry
+// -----------------------------------------------------------------------------
+//
+void CMceStateEstablished::StateEntry( TMceStateTransitionEvent& aEvent )
+    {
+    CMceState::StateEntry( aEvent );
+    
+	CMceSipSession& session = aEvent.Session();
+    
+    TBool clearSubState = ETrue;
+    
+    if ( &session.Response() )
+        {
+        TUint code = MceSip::ResponseCode( session.Response() );
+        if ( code != KMceSipRequestPending )
+            {
+            session.Actions().StopPendingTimer();
+            }
+        else
+            {
+            clearSubState = EFalse;
+            }
+        }
+    if ( clearSubState )
+        {
+        session.SetSubState( CMceSipSession::ENone );
+        }
+        
+    session.CloseBodyBucket();
+
+    session.RemoveCompletedRequests( ETrue );
+    
+    session.ResetSdpCounts();
+    
+    }
+
+// -----------------------------------------------------------------------------
+// CMceStateEstablished::EntryL
+// -----------------------------------------------------------------------------
+//
+void CMceStateEstablished::EntryL( TMceStateTransitionEvent& aEvent )
+	{
+
+	if ( IsExtensionRequestEvent( aEvent ))
+		{
+		HandleExtensionRequestEventL( aEvent );	
+		}
+	
+	else 
+		{
+
+		CMceSipSession& session = aEvent.Session();
+
+	    switch ( aEvent.Code() )
+	        {
+	        //client has been asked to update session
+	        case EMceItcUpdate:
+	            {
+	            EntryUpdateL( aEvent );
+	            break;
+	            }
+	        //INVITE has been received due session update or refresh
+	        case EMceInvite:
+	            {
+	            EntryInviteL( aEvent );
+	            break;
+	            }
+	        //UPDATE has been received for instance for session expires
+	        // or media update
+	        case EMceUpdate:
+	            {
+                EntryInUpdateL( aEvent );
+                break;
+	            }
+	        //client terminates session or session timer expires, 
+	        //when session is not refresher BYE is sent and media 
+	        //and FC are stopped
+	        case EMceSessionExpired:
+	        case EMceItcTerminateSession:
+	            {
+	            EntryTerminateSessionL( aEvent );
+	            break;
+	            }
+	        //BYE has been received
+	        case EMceBye:
+	            {
+	            EntryByeL( aEvent );
+	            break;
+	            }
+	        //media conrol
+	        case EMceItcEnable:
+	        case EMceItcDisable:
+	            {
+	            EntryMediaL( aEvent );
+	            break;
+	            }
+	        //refresher's session timer fired
+	        //and thus, refresh is launched (INVITE)
+	        case EMceSessionRefresh:
+	            {
+	            session.Actions().EncodeL();
+	            session.FCActions().UpdateFCOfferL( *session.Offer() );
+	            session.Actions().SendSessionRefreshL();
+	            break;
+	            }
+	        //pending timer fired, re-send re-INVITE
+	        case EMceSessionPending:
+	            {
+	            session.Actions().SendInviteL();
+	            break;
+	            }
+	        //media has beed stopped or there is media error
+	        //session state is not affected, client is only informed
+	        case EMceMediaSessionStopped:
+	           	{
+	           	MediaErrorOccured( aEvent );
+	           	break;
+	           	}
+	              
+	        default:
+	            {
+	            //NOP
+	            break;
+	            }
+	        }
+		}
+	         
+	}
+
+// -----------------------------------------------------------------------------
+// CMceStateEstablished::EntryUpdateL
+// -----------------------------------------------------------------------------
+//
+void CMceStateEstablished::EntryUpdateL( TMceStateTransitionEvent& aEvent )
+    {
+	CMceSipSession& session = aEvent.Session();
+    
+    // create body candidate
+    session.Actions().CreateBodyCandidateL( CMceComSession::EOutSession );
+    // update body candidate
+    session.Actions().UpdateBodyL( aEvent.ParamIDs(), 
+                                   aEvent.ParamClientMessage() );
+    session.BodyCandidate()->iFcSignallingRequired = 
+                                    session.FCActions().NeedToSendOffer();
+
+    if ( &session.Body()->SdpSession() &&
+    	 session.Body()->SdpSession().iOOldSchoolCompleted )
+        {
+        session.BodyCandidate()->iRequireSignalling = ETrue;
+        session.Body()->SdpSession().iOOldSchoolCompleted = 0;
+        }
+        
+    //create updated session (body) candidate
+    TMceReturnStatus status = session.Actions().UpdateL();
+                              
+    aEvent.ParamStatus() = status;
+    //if creation fails candidate is rolled back to original
+    if ( MCE_IS_ERROR( status ) )
+        {
+        session.Actions().UpdateFailed();
+        }
+    else if ( status == KMceReady )
+        {
+        if ( MCE_NEED_TO_SEND( session, NULL ) )
+            {
+            NAT_WAIT_NO_EXEC( session, session.Actions().EncodeL() );
+            session.FCActions().UpdateFCOfferL( *session.Offer() );
+            session.Actions().SendInviteL();
+            
+            session.Actions().StateChanged( KMceStateOffering );
+            session.Actions().ClientStateChanged( aEvent.ParamIDs(), 
+                                                  CMceSession::EOffering );
+            }
+        else
+            {
+            session.Actions().UpdateSucceed();
+            }
+        }
+    else
+        {
+        // NOP
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMceStateEstablished::EntryInUpdateL
+// -----------------------------------------------------------------------------
+//
+void CMceStateEstablished::EntryInUpdateL(TMceStateTransitionEvent& aEvent)
+    {
+    CMceSipSession& session = aEvent.Session();
+    CSIPServerTransaction& request = session.Request();
+    CSIPServerTransaction* requestPtr = &request;
+    TBool isRefreshing = EFalse;
+
+    session.Actions().CheckContactIsSecureL(request);
+
+    if ( (requestPtr!=NULL) && !MceSip::HasContent(request) )
+        {
+        isRefreshing = ETrue;
+        }
+    else
+        {
+        // update extension information
+        session.Extensions().UpdateL(session.Request() );
+        // create SDP
+        User::LeaveIfError(session.Actions().CreateSDP(session.Request() ) );
+
+        if ( !session.DoesMediaManagerNeedToNegotiate( session.Offer() ) )
+            {
+            // SDP not changed
+            isRefreshing = ETrue;
+            }
+        }
+    
+    if (isRefreshing)
+        {
+        //set substate to refreshing
+        session.SetSubState(CMceSipSession::ERefreshing);
+        //update timer data in body
+        session.Actions().ProcessSessionTimerServerL(session.Request() );
+
+        // Use previous offer
+        session.SdpCleanup(session.Offer(), session.PrevOffer() );
+
+        // encode
+        session.Actions().EncodeL();
+
+        //update FC in answer
+        session.FCActions().UpdateFCAnswerL( *session.Offer() );
+
+        //reset session timer if session is not refresher
+        session.Actions().ResetSessionTimerL();
+        session.Actions().SendAnswerL(session.Request() );
+        
+        session.Actions().StateChanged( KMceStateEstablished );
+        session.Actions().ClientStateChangedL( CMceSession::EEstablished, session.Request() );  
+        }
+    else
+        {
+        // create body candidate
+        session.Actions().CreateBodyCandidateL(CMceComSession::EInSession);
+
+        TMceReturnStatus status = KErrNone;
+
+        // decode 
+        TMceSipWarningCode warning = session.Actions().DecodeL();
+
+        if ( !warning)
+            {
+            status = session.Actions().Update();
+            if (status == KErrNotSupported)
+                {
+                warning = KMceSipWarnSessionDescriptionParameterNotUnderstood;
+                }
+            }
+
+        aEvent.ParamStatus() = status;
+
+        if (warning)
+            {
+            session.Actions().UpdateFailed();
+            session.Actions().SendRejectOfferWithWarningL(warning, session.Request() );
+            aEvent.ParamStatus() = warning;
+            }
+        else
+            if ( MCE_IS_ERROR( status ))
+                {
+                session.Actions().UpdateFailed();
+                User::Leave(status);
+                }
+            else
+                {
+                session.Actions().ClientUpdateSessionL(session.Request() );
+                }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMceStateEstablished::EntryInviteL
+// -----------------------------------------------------------------------------
+//
+void CMceStateEstablished::EntryInviteL( TMceStateTransitionEvent& aEvent )
+    {
+	CMceSipSession& session = aEvent.Session();
+	CSIPServerTransaction& request = session.Request();
+	CSIPServerTransaction* requestPtr = &request;
+
+    session.Actions().CheckContactIsSecureL( request );
+     
+	if ( (requestPtr!=NULL) && !MceSip::HasContent( request ) )
+        {
+        // Pull Mode
+        session.Extensions().UpdateL( request );
+        if ( MCE_NEED_TO_SEND( session, session.Offer() ) ) // is session update
+            {
+            // create body candidate for Pull mode
+            session.Actions().CreateBodyCandidateL( 
+                CMceComSession::EInSession );
+            }
+        session.Actions().ProcessSessionTimerServerL( session.Request() );
+        session.Actions().ClientUpdateSessionL( request );	  
+        }
+	else
+	    {
+	    // update extension information
+	    session.Extensions().UpdateL( session.Request() );
+        // create SDP
+        User::LeaveIfError( session.Actions().CreateSDP( session.Request() ) );
+
+        if ( session.DoesMediaManagerNeedToNegotiate( session.Offer() ) )
+            {
+            // create body candidate
+            session.Actions().CreateBodyCandidateL( CMceComSession::EInSession );
+            
+            TMceReturnStatus status = KErrNone;
+            
+            // decode 
+            TMceSipWarningCode warning = session.Actions().DecodeL();
+            
+            if ( !warning )
+                {
+                status = session.Actions().Update();
+                if ( status == KErrNotSupported )
+                    {
+                    warning = KMceSipWarnSessionDescriptionParameterNotUnderstood;
+                    }
+                }
+            
+            aEvent.ParamStatus() = status;
+
+            if ( warning )
+                {
+                session.Actions().UpdateFailed();
+                session.Actions().SendRejectOfferWithWarningL( warning, 
+                                                               session.Request() );
+                aEvent.ParamStatus() = warning;
+                }
+            else if ( MCE_IS_ERROR( status ) )
+                {
+                session.Actions().UpdateFailed();
+                User::Leave( status );
+                }
+            else
+                {
+                session.Actions().ClientUpdateSessionL( session.Request() );
+                }
+            }
+        else // SDP not changed
+            {
+            //set substate to refreshing
+            session.SetSubState( CMceSipSession::ERefreshing );
+            //update timer data in body
+            session.Actions().ProcessSessionTimerServerL( session.Request() );
+            
+            // Use previous offer
+            session.SdpCleanup( session.Offer(), session.PrevOffer() );
+           
+            // encode
+            session.Actions().EncodeL();
+            
+            //update FC in answer
+            session.FCActions().UpdateFCAnswerL( *session.Offer() );
+            
+            session.Actions().SendAnswerL( session.Request() );
+            
+            session.Actions().StateChanged( KMceStateAnswering );
+            session.Actions().ClientStateChangedL( CMceSession::EAnswering,
+                                                   session.Request() );
+            }
+	    }
+	//reset session timer
+	session.Actions().ResetSessionTimerL();
+    }
+
+// -----------------------------------------------------------------------------
+// CMceStateEstablished::EntryTerminateSessionL
+// -----------------------------------------------------------------------------
+//
+void CMceStateEstablished::EntryTerminateSessionL( 
+                                            TMceStateTransitionEvent& aEvent )
+    {
+	CMceSipSession& session = aEvent.Session();
+
+    session.Actions().SendBYEL( aEvent.ParamClientMessage() );
+    session.Actions().StopMedia();
+    session.FCActions().ReleaseFC();
+    }
+
+// -----------------------------------------------------------------------------
+// CMceStateEstablished::EntryByeL
+// -----------------------------------------------------------------------------
+//
+void CMceStateEstablished::EntryByeL( TMceStateTransitionEvent& aEvent )
+    {
+	CMceSipSession& session = aEvent.Session();
+	
+    //send 200OK and stop media and FC
+    session.Actions().Send200OKL( session.Request() );
+    session.Actions().StopMedia();
+    session.FCActions().ReleaseFC();
+    }
+
+// -----------------------------------------------------------------------------
+// CMceStateEstablished::EntryMediaL
+// -----------------------------------------------------------------------------
+//
+void CMceStateEstablished::EntryMediaL( TMceStateTransitionEvent& aEvent )
+    {
+	CMceSipSession& session = aEvent.Session();
+
+    session.Actions().ControlMediaL( aEvent.ParamIDs(), 
+                                    (TMceItcFunctions)aEvent.Code() );
+    }
+    
+    
+    
+// -----------------------------------------------------------------------------
+// CMceStateEstablished::MediaErrorOccured
+// -----------------------------------------------------------------------------
+//
+void CMceStateEstablished::MediaErrorOccured( TMceStateTransitionEvent& aEvent )
+	{
+	MCESRV_DEBUG( "CMceStateEstablished::MediaErrorOccured, Entry" );                           	
+	CMceSipSession& session = aEvent.Session();
+	
+	// If ClientMediaStateChangedL leaves while trying to pause the RTP sink,
+	// just trap and log it.
+	TRAPD( err, session.Actions().ClientMediaStateChangedL( 
+                           aEvent.ParamMccEvent(),
+                           static_cast<TMceMediaEventCode>( aEvent.Code() ) ) );
+	
+	if ( err != KErrNone )
+		{
+		MCESRV_DEBUG_DVALUE( "ClientMediaStateChangedL leaves with error code", err );
+		}
+	
+	MCESRV_DEBUG( "CMceStateEstablished::MediaErrorOccured, Exit" );                           
+	}
+
+
+// -----------------------------------------------------------------------------
+// CMceStateEstablished::ExitL
+// -----------------------------------------------------------------------------
+//
+void CMceStateEstablished::ExitL( TMceStateTransitionEvent& aEvent )
+	{
+	
+	if ( IsExtensionRequestEvent( aEvent ))
+		{
+		//Do Nothing;
+		}
+
+	else 
+		{
+		CMceSipSession& session = aEvent.Session();
+		TInt status = aEvent.ParamStatus();
+
+	    switch ( aEvent.Code() )
+	        {
+	        //received BYE causes server & client to terminated state
+	        case EMceBye:
+	            {
+	            session.Actions().StateChanged( KMceStateTerminated );
+	            session.Actions().ClientStateChangedL( 
+	                CMceSession::ETerminated, session.Request() );
+	            break;
+	            }
+	        //client's session termination causes 
+	        //server & client to terminating state
+	        case EMceItcTerminateSession:
+	            {
+	            session.Actions().StateChanged( KMceStateTerminating );
+	            session.Actions().ClientStateChanged( 
+	                aEvent.ParamIDs(), CMceSession::ETerminating );
+	            break;
+	            }
+	        //timer expiration causes server & client to terminating state
+	        case EMceSessionExpired:
+	            {
+	            session.Actions().StateChanged( KMceStateTerminating );
+	            session.Actions().ClientStateChangedL( CMceSession::ETerminating );
+	            break;
+	            }
+	        //session refresh causes server & client to terminating state
+	        case EMceSessionRefresh:
+	            {
+	            session.Actions().StateChanged( KMceStateOffering );
+	            session.Actions().ClientStateChangedL( CMceSession::EOffering );
+	            break;
+	            }
+	        case EMceSessionPending:
+	            {
+	            session.Actions().StateChanged( KMceStateOffering );
+	            session.Actions().ClientStateChangedL( CMceSession::EOffering );
+	            break;
+	            }
+	       
+	        case EMceItcUpdate:
+	            {
+	            //client's update,if decoding has been failed 
+	            //or update is not deeded, does not affect 
+	            if ( MCE_IS_ERROR( status ) )
+	                {
+	                //Client will fetch original session with ITC
+	                session.Actions().StateChanged( KMceStateEstablished );
+	                session.Actions().ClientStateChanged( aEvent.ParamIDs(), 
+	                                                      CMceSession::EEstablished, 
+	                                                      status );
+	                }
+	            else if ( status == KMceAsync )
+	                {
+	                session.Actions().StateChanged( KMceStateClientEstablishing );
+	                session.Actions().ClientStateChanged( aEvent.ParamIDs(), 
+	                                                      CMceSession::EOffering );
+	                }
+	            else if ( status == KMceReady )
+	                {
+	                session.Actions().StateChanged( KMceStateEstablished );
+	                session.Actions().ClientStateChanged( 
+	                                                aEvent.ParamIDs(), 
+	                                                CMceSession::EEstablished );
+	                }
+	            else
+	                {
+	                // NOP
+	                }
+	            break;
+	            }
+            case EMceUpdate:
+                {
+                if ( session.SubState() == CMceSipSession::ERefreshing )
+                    {
+                    session.Actions().StateChanged(KMceStateEstablished);
+
+                    // If warning occurred, client is not informed
+                    if ( MCE_IS_ERROR( status ))
+                        {
+                        session.Actions().ClientStateChangedL(CMceSession::EEstablished, status);
+                        }
+                    }
+                else
+                    {
+                    session.Actions().StateChanged( KMceStateServerEstablishing );
+	                }
+	            break;
+	            }
+	        case EMceInvite:
+	            {
+	            if ( status == KErrNone )
+	    	        {
+	                session.Actions().StateChanged( KMceStateServerEstablishing );
+	    	        }
+	            else
+	                {
+	                session.Actions().StateChanged( KMceStateEstablished );
+	                
+	                // If warning occurred, client is not informed
+	                if ( MCE_IS_ERROR( status ) )
+	                    {
+	                    session.Actions().ClientStateChangedL( 
+	                                    CMceSession::EEstablished, status );
+	                    }
+	                }
+	            break;
+	            }
+	        default:
+	            {
+	            }
+	        }
+		}
+	}
+
+// End of File