--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/multimediacommsengine/mmcesrv/mmceserver/src/mcesipsession.cpp Tue Feb 02 01:04:58 2010 +0200
@@ -0,0 +1,2615 @@
+/*
+* 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 <sipinvitedialogassoc.h>
+#include <sipprofile.h>
+#include <sdpdocument.h>
+#include <siptoheader.h>
+#include <sipdialog.h>
+#include <sipcontactheader.h>
+#include "mcesipsession.h"
+#include "mcecssession.h"
+#include "mceservercore.h"
+#include "fcpluginengine.h"
+#include "mcesipconnection.h"
+#include "mcesipstatemachine.h"
+#include "mcestate.h"
+#include "mceactionset.h"
+#include "mcefcactionset.h"
+#include "mceclient.pan"
+#include "mcesrvlogs.h"
+#include "mcecomsession.h"
+#include "mcecomaudiocodec.h"
+#include "mcesipextensions.h"
+#include "mcereliablesender.h"
+#include "mcemediamanager.h"
+#include "mcesdpsession.h"
+#include "mcetimermanager.h"
+#include "mcemediastate.h"
+
+#define MCE_IGNORE_MEDIA_ERROR ( ( defined __WINSCW__ ) || ( defined __WINS__ ) )\
+ && ( !defined MCESRV_UNIT_TESTING )
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::NewL
+// -----------------------------------------------------------------------------
+//
+CMceSipSession* CMceSipSession::NewL( CMceCsSession& aClientSession,
+ CMceSipConnection& aSIPConnection,
+ CMceSipStateMachine& aStateMachine,
+ CSIPProfile& aProfile )
+ {
+ CMceSipSession* self = CMceSipSession::NewLC( aClientSession,
+ aSIPConnection,
+ aStateMachine,
+ aProfile );
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::NewLC
+// -----------------------------------------------------------------------------
+//
+CMceSipSession* CMceSipSession::NewLC ( CMceCsSession& aClientSession,
+ CMceSipConnection& aSIPConnection,
+ CMceSipStateMachine& aStateMachine,
+ CSIPProfile& aProfile )
+ {
+ CMceSipSession* self = new (ELeave) CMceSipSession( aClientSession,
+ aSIPConnection,
+ aStateMachine,
+ aProfile );
+ CleanupStack::PushL(self);
+ self->ConstructL( aClientSession );
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::NewLC
+// -----------------------------------------------------------------------------
+//
+CMceSipSession* CMceSipSession::NewLC ( CMceCsSession& aClientSession,
+ CMceSipConnection& aSIPConnection,
+ CMceSipStateMachine& aStateMachine )
+ {
+ CMceSipSession* self = new (ELeave) CMceSipSession( aClientSession,
+ aSIPConnection,
+ aStateMachine );
+ CleanupStack::PushL(self);
+ self->ConstructL( aClientSession );
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::CMceSipSession
+// -----------------------------------------------------------------------------
+//
+CMceSipSession::CMceSipSession ( CMceCsSession& aClientSession,
+ CMceSipConnection& aSIPConnection,
+ CMceSipStateMachine& aStateMachine,
+ CSIPProfile& aProfile )
+: CMceCsSubSession( KMceCSSIPSession, aClientSession, aSIPConnection, \
+ aProfile ),
+ iStateMachine( &aStateMachine ),
+ iSubState( ENone ),
+ iUseFC( EFalse )
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::CMceSipSession
+// -----------------------------------------------------------------------------
+//
+CMceSipSession::CMceSipSession ( CMceCsSession& aClientSession,
+ CMceSipConnection& aSIPConnection,
+ CMceSipStateMachine& aStateMachine )
+: CMceCsSubSession( KMceCSSIPSession, aClientSession, aSIPConnection ),
+ iStateMachine( &aStateMachine ),
+ iSubState( ENone ),
+ iUseFC( EFalse )
+ {
+ }
+
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::ConstructL
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::ConstructL ( CMceCsSession& aClientSession )
+ {
+ MCESRV_DEBUG("CMceSipSession::ConstructL, Entry");
+
+ CMceCsSubSession::ConstructL( aClientSession );
+
+ iTimer = CMceTimerManager::KNoSuchTimer;
+
+ iPendingTimer = CMceTimerManager::KNoSuchTimer;
+
+ iCurrentState = &iStateMachine->State( KMceStateIdle );
+
+ iExtensions= CMceSipExtensions::NewL();
+
+ iReliableSender = CMceReliableSender::NewL( *this );
+
+ iRSeq = KErrNone;
+
+ iPreviousState = KMceStateIdle;
+
+ iForceSDPSending = EFalse;
+
+ iNatSession = EFalse;
+
+ MCESRV_DEBUG("CMceSipSession::ConstructL, Exit");
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::~CMceSipSession
+// -----------------------------------------------------------------------------
+//
+CMceSipSession::~CMceSipSession()
+ {
+ MCESRV_DEBUG("CMceSipSession::~CMceSipSession, Entry");
+
+ CloseMedia( ETrue );
+ CMceComSession::Delete( iNewBodyCandidate, Manager().MediaManager() );
+
+ PrevOfferSafeDelete();
+
+ delete iOffer;
+ Manager().TimerManager().Stop( iTimer );
+
+ if ( iFCSession )
+ {
+ ServerCore().DeregisterFCSession( *this, *iFCSession );
+ ServerCore().FCPluginEngine().ReleaseSession( *iFCSession);
+ }
+ iForkedDialogs.ResetAndDestroy();
+ delete iMediaAuthorizationToken;
+ delete iExtensions;
+ delete iReliableSender;
+ iRemoteUri.ResetAndDestroy();
+
+ MCESRV_DEBUG("CMceSipSession::~CMceSipSession, Exit");
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::CloseMedia
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::CloseMedia( TBool aDelete )
+ {
+ MCESRV_DEBUG("CMceSipSession::CloseMedia, Entry");
+
+ if ( aDelete )
+ {
+ CMceComSession::Delete( iBody, Manager().MediaManager() );
+ }
+ else
+ {
+ Manager().MediaManager().CloseSession( *iBody );
+ }
+
+ CloseBodyBucket();
+
+ MCESRV_DEBUG("CMceSipSession::CloseMedia, Exit");
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::CloseBodyBucket
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::CloseBodyBucket()
+ {
+ MCESRV_DEBUG("CMceSipSession::CloseBodyBucket, Entry");
+
+ while( iBodyBucket.Count() > 0 )
+ {
+ CMceComSession* body = iBodyBucket[ 0 ];
+ if ( &body->SdpSession() )
+ {
+ body->SdpSession().AttachContext( NULL );
+ }
+ CMceComSession::Delete( body, Manager().MediaManager() );
+ iBodyBucket.Remove( 0 );
+ }
+
+ iBodyBucket.ResetAndDestroy();
+
+ MCESRV_DEBUG("CMceSipSession::CloseBodyBucket, Exit");
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::ReliableSender
+// -----------------------------------------------------------------------------
+//
+CMceReliableSender& CMceSipSession::ReliableSender()
+ {
+ return *iReliableSender;
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::DoInitializeIncomingDialogL
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::DoInitializeIncomingDialogL(
+ CSIPServerTransaction& /*aTransaction*/ )
+ {
+ MCESRV_DEBUG("CMceSipSession::DoInitializeIncomingDialogL, Entry");
+
+ FCActions().InitializeFCL();
+
+ SetBodyL();
+
+ MCESRV_DEBUG("DoInitializeIncomingDialogL: new session body:");
+ MCESRV_DEBUG_COMSESSION( iBody );
+
+ MCESRV_DEBUG("CMceSipSession::DoInitializeIncomingDialogL, Exit");
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::CanDispose
+// -----------------------------------------------------------------------------
+//
+TBool CMceSipSession::CanDispose()
+ {
+ return ( CurrentState().Id() == KMceStateTerminated &&
+ HasInitialInviteTransactionBeenCompleted() );
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::Actions
+// -----------------------------------------------------------------------------
+//
+TMceActionSet CMceSipSession::Actions()
+ {
+ return TMceActionSet( *this );
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::FCActions
+// -----------------------------------------------------------------------------
+//
+TMceFCActionSet CMceSipSession::FCActions()
+ {
+ return TMceFCActionSet( *this );
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::CurrentState
+// -----------------------------------------------------------------------------
+//
+CMceState& CMceSipSession::CurrentState( TBool aMarkExit )
+ {
+ if ( aMarkExit )
+ {
+ iExitState = iCurrentState;
+ }
+ return *iCurrentState;
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::Body
+// -----------------------------------------------------------------------------
+//
+CMceComSession* CMceSipSession::Body()
+ {
+ CMceComSession* body = iBody;
+
+ if ( iBodyBucket.Count() > 0 )
+ {
+ body = &iBody->SdpSession() && iBody->SdpSession().Context() == Dialog() ?
+ iBody : NULL;
+ TInt index = 0;
+ while( !body && index < iBodyBucket.Count() )
+ {
+ body = iBodyBucket[ index++ ];
+ body = &body->SdpSession() && body->SdpSession().Context() == Dialog() ? body : NULL;
+ }
+
+ body = !body ? iBody : body;
+
+ }
+
+ return body;
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::BodyCandidate
+// -----------------------------------------------------------------------------
+//
+CMceComSession* CMceSipSession::BodyCandidate()
+ {
+ return iNewBodyCandidate;
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::SetOffer
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::SetOffer( CSdpDocument* aSdpDocument )
+ {
+ if ( aSdpDocument != iOffer )
+ {
+ delete iOffer;
+ iOffer = aSdpDocument;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::Offer
+// -----------------------------------------------------------------------------
+//
+CSdpDocument* CMceSipSession::Offer()
+ {
+ return iOffer;
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::SetPrevOffer
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::SetPrevOffer( CSdpDocument* aSdpDocument )
+ {
+ if ( aSdpDocument != iPrevOffer )
+ {
+ PrevOfferSafeDelete();
+ iPrevOffer = aSdpDocument;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::PrevOffer
+// -----------------------------------------------------------------------------
+//
+CSdpDocument* CMceSipSession::PrevOffer()
+ {
+ return iPrevOffer;
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::StorePrevOffer
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::StorePrevOffer()
+ {
+ MCESRV_DEBUG( "*** CMceSipSession::StorePrevOfferL, Entry" );
+
+ // If refreshing, existing prev offer is going to be taken in use and
+ // we don't want to override it with offer.
+ if ( iOffer && SubState() != ERefreshing )
+ {
+ MCESRV_DEBUG( "*** CMceSipSession::StorePrevOfferL, Copy" );
+ CSdpDocument* clonedOffer = NULL;
+ TRAP_IGNORE( ( clonedOffer = iOffer->CloneL() ) );
+ SetPrevOffer( clonedOffer );
+ }
+
+ MCESRV_DEBUG( "*** CMceSipSession::StorePrevOfferL, Exit" );
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::IncrementSentSdpCount
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::IncrementSentSdpCount()
+ {
+ iSentSdpCount++;
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::IncrementReceivedSdpCount
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::IncrementReceivedSdpCount()
+ {
+ iReceivedSdpCount++;
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::ResetSdpCounts
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::ResetSdpCounts()
+ {
+ iSentSdpCount = 0;
+ iReceivedSdpCount = 0;
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::DoesMediaManagerNeedToNegotiate
+// -----------------------------------------------------------------------------
+//
+TBool CMceSipSession::DoesMediaManagerNeedToNegotiate(
+ CSdpDocument* aSdpDocument )
+ {
+ CMceMediaManager& mediaManager = Manager().MediaManager();
+ return mediaManager.NeedToNegotiate( ActiveBody(), aSdpDocument );
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::NatSession
+// -----------------------------------------------------------------------------
+//
+TBool CMceSipSession::NatSession() const
+ {
+ return EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::NatState
+// -----------------------------------------------------------------------------
+//
+TInt CMceSipSession::NatState() const
+ {
+ return KErrNotFound;
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::IsNatDisabled
+// -----------------------------------------------------------------------------
+//
+TBool CMceSipSession::IsNatDisabled() const
+ {
+ return EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::StartSessionTimerL
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::StartSessionTimerL()
+ {
+ MCESRV_DEBUG("CMceSipSession::StartSessionTimerL, Entry");
+
+ const TUint KTwo = 2;
+
+ CMceTimerManager& timerManager = Manager().TimerManager();
+
+ if( iBody->iTimeout > 0 )
+ {
+ TUint32 interval;
+
+ if( iBody->iRefresh )
+ {
+ // if this end should perform refreshes then the reccommended
+ // time is half the session interval
+ interval = ( iBody->iTimeout * KMceSecToMillisec ) / KTwo;
+ }
+ else
+ {
+ // the other end is performing refreshes, so set the timeout
+ // to full session interval and send bye in case of no refresh
+ interval = iBody->iTimeout * KMceSecToMillisec;
+ }
+
+ if ( timerManager.IsRunning( iTimer ) )
+ {
+ timerManager.Stop( iTimer );
+ }
+
+ iTimer = timerManager.StartL( this, interval );
+ }
+ MCESRV_DEBUG("CMceSipSession::StartSessionTimerL, Exit");
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::StartPendingTimerL
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::StartPendingTimerL( TUint aInterval )
+ {
+ MCESRV_DEBUG("CMceSipSession::StartPendingTimerL, Entry");
+
+ CMceTimerManager& timerManager = Manager().TimerManager();
+
+ iPendingTimer = timerManager.StartL( this, aInterval );
+
+ MCESRV_DEBUG("CMceSipSession::StartPendingTimerL, Exit");
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::NextState
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::NextState( TUint aNextStateId )
+ {
+ MCESRV_DEBUG("CMceSipSession::NextState, Entry");
+
+ iPreviousState = iCurrentState->Id();
+
+ MCESRV_DEBUG_STATE("old state", iPreviousState );
+ MCESRV_DEBUG_STATE("new state", aNextStateId );
+
+ ClearRemoteUri( aNextStateId );
+ iCurrentState = &iStateMachine->State( aNextStateId );
+
+ // Automatic event generation
+ //
+ TMceStateTransitionEvent* autoEvent = StoredAutoEvent();
+ if ( AutoEvent() && autoEvent && iCurrentlyProcessedAutoEvent != autoEvent )
+ {
+ // Remember what event is processed at the moment in order to avoid
+ // multiple generations of same event if nested state changes occur.
+ iCurrentlyProcessedAutoEvent = autoEvent;
+
+ TRAPD( err, DoAutoEventL( *autoEvent ) );
+ if ( err )
+ {
+ MCESRV_DEBUG("CMceSipSession::NextState, automatic event failed");
+ err++;
+ }
+
+ // Do it just once
+ SetAutoEvent( EFalse );
+ iCurrentlyProcessedAutoEvent = NULL;
+ }
+
+ MCESRV_DEBUG("CMceSipSession::NextState, Exit");
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::MethodCode
+// -----------------------------------------------------------------------------
+//
+TMceSipEventCode CMceSipSession::MethodCode( RStringF method )
+ {
+ TMceSipEventCode eventCode = (TMceSipEventCode)KErrNotFound;
+
+ if ( method == SIPStrings::StringF( SipStrConsts::EInvite ) )
+ {
+ eventCode = EMceInvite;
+ }
+ else if ( method == SIPStrings::StringF( SipStrConsts::ECancel ) )
+ {
+ eventCode = EMceCancel;
+ }
+ else if ( method == SIPStrings::StringF( SipStrConsts::EAck ) )
+ {
+ eventCode = EMceAck;
+ }
+ else if ( method == SIPStrings::StringF( SipStrConsts::EBye ) )
+ {
+ eventCode = EMceBye;
+ }
+ else if ( method == SIPStrings::StringF( SipStrConsts::EPrack ) )
+ {
+ eventCode = EMcePrack;
+ }
+ else if ( method == SIPStrings::StringF( SipStrConsts::EUpdate ) )
+ {
+ eventCode = EMceUpdate;
+ }
+ else if ( Actions().IsExtensionRequest( method ))
+ {
+ eventCode = EMceRequest;
+ }
+ return eventCode;
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::ActiveBody
+// -----------------------------------------------------------------------------
+//
+CMceComSession& CMceSipSession::ActiveBody()
+ {
+ TSubState subState = SubState();
+
+ CMceComSession* body = NULL;
+
+ if ( subState != EUpdating )
+ {
+ body = Body();
+ }
+ else
+ {
+ // If session is already accepted/rejected, body candidate does not
+ // exist anymore but the session is still in updating substate.
+ body = BodyCandidate() ? BodyCandidate() : Body();
+ }
+
+ return *body;
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::UpdateMediaL
+// -----------------------------------------------------------------------------
+//
+TMceReturnStatus CMceSipSession::UpdateMediaL()
+ {
+ MCESRV_DEBUG("CMceSipSession::UpdateMediaL, Entry");
+
+ TMceReturnStatus status = Manager().MediaManager().UpdateL( ActiveBody() );
+
+ TUint signallingTos = ActiveBody().Modifier( KMceSignallingTypeOfService );
+ if ( signallingTos != KMaxTUint16 )
+ {
+ SIPConnection().UpdateConnectionL( signallingTos );
+ }
+
+ MCESRV_DEBUG("CMceSipSession::UpdateMediaL, Exit");
+
+ return status;
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::ReserveL
+// -----------------------------------------------------------------------------
+//
+TMceReturnStatus CMceSipSession::ReserveL()
+ {
+ MCESRV_DEBUG("CMceSipSession::ReserveL, Entry");
+
+ TMceReturnStatus status = KMceReady;
+ HBufC8* token = MediaAuthorizationToken();
+ if ( token )
+ {
+ // session has received a media authorization token
+ CMceMediaManager& mediaManager = Manager().MediaManager();
+ status = mediaManager.ReserveL( ActiveBody(), *token );
+ }
+
+ MCESRV_DEBUG_DVALUE( "ReserveL: status", status);
+
+ MCESRV_DEBUG("CMceSipSession::ReserveL, Exit");
+
+ return status;
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::NeedToSend
+// -----------------------------------------------------------------------------
+//
+TBool CMceSipSession::NeedToSend( CSdpDocument* aSdpDocument )
+ {
+ MCESRV_DEBUG( "CMceSipSession::NeedToSend, Entry" )
+
+ CMceMediaManager& mediaManager = Manager().MediaManager();
+
+ TBool needToSend =
+ ( DoesMediaManagerNeedToNegotiate( aSdpDocument ) ||
+ (( iSentSdpCount < iReceivedSdpCount ) &&
+ ( mediaManager.GetRole( ActiveBody()) == EMceRoleAnswerer )));
+
+ MCESRV_DEBUG_DVALUE( "CMceSipSession::NeedToSend, Exit", needToSend )
+
+ return needToSend;
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::NeedToReceive
+// -----------------------------------------------------------------------------
+//
+TBool CMceSipSession::NeedToReceive()
+ {
+ MCESRV_DEBUG( "CMceSipSession::NeedToReceive, Entry" );
+
+ CMceMediaManager& mediaManager = Manager().MediaManager();
+ TBool confirmationNeeded = mediaManager.ConfirmationNeeded( ActiveBody() );
+
+ MCESRV_DEBUG( "CMceSipSession::NeedToReceive, Exit" );
+
+ return confirmationNeeded;
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::AcceptMethod
+// -----------------------------------------------------------------------------
+//
+TBool CMceSipSession::AcceptMethod( RStringF aMethod )
+ {
+ return MethodCode( aMethod ) != (TMceSipEventCode)KErrNotFound;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::RequestReceived
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::RequestReceived( TBool aInsideDialog, CSIPDialog& aDialog )
+ {
+ MCESRV_DEBUG("CMceSipSession::RequestReceived, Entry");
+
+ if ( Request().Type() == SIPStrings::StringF( SipStrConsts::EInvite ) )
+ {
+ MCESRV_DEBUG("CMceSipSession::RequestReceived, invite");
+ if ( aInsideDialog && iCurrentState->Id() == KMceStateAnswering )
+ {
+ MCESRV_DEBUG("CMceSipSession::RequestReceived, ack missing, fake it");
+
+ HandleSIPEvent( EMceAck, aDialog );
+ }
+ else if ( iCurrentState->Id() != KMceStateEstablished &&
+ iCurrentState->Id() != KMceStateIdle )
+ {
+
+ MCESRV_DEBUG("there is pending request");
+ // Send 491
+ MceSip::DiscardRequest( Request(), KMceSipRequestPending );
+ delete PopRequest();
+ return;
+ }
+ else
+ {
+ // NOP
+ }
+ }
+
+ MCESRV_DEBUG("Handle new request");
+ TMceSipEventCode eventCode = MethodCode( MceSip::Method( Request() ) );
+
+ HandleSIPEvent( eventCode, aDialog );
+
+ MCESRV_DEBUG("CMceSipSession::RequestReceived, Exit");
+ }
+
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::HandleSIPEvent
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::HandleSIPEvent( TMceSipEventCode aEventCode, CSIPDialog& aDialog )
+ {
+ MCESRV_DEBUG("CMceSipSession::HandleSIPEvent, Entry");
+
+ if ( Body() && &Body()->SdpSession() )
+ {
+ Body()->SdpSession().AttachContext( Dialog() );
+ }
+
+ TMceStateTransitionEvent event( *this, aEventCode, aDialog );
+
+ if ( iStateMachine->Consumes( event ) )
+ {
+ TRAPD( error, iStateMachine->ProcessL( event ) );
+ if ( error != KErrNone )
+ {
+ MCESRV_DEBUG_DVALUE(
+ "HandleSIPEvent: state machine causes ERROR", error );
+
+ TRAPD( handleError, HandleSIPEventErrorL( aEventCode, error ) );
+ if ( handleError != KErrNone )
+ {
+ LocalErrorOccured( KMceStateError, error );
+ }
+ }
+ }
+ else
+ {
+ MceSip::DiscardRequest( Request(), KMceSipNotImplemented );
+ }
+
+ MCESRV_DEBUG("CMceSipSession::HandleSIPEvent, Exit");
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::HandleSIPEventErrorL
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::HandleSIPEventErrorL( TMceSipEventCode aEventCode,
+ TInt aError )
+ {
+ switch( aEventCode )
+ {
+ case EMceProvisionalResponse:
+ case EMceRedirectionResponse:
+ case EMceResponse:
+ case EMceErrorResponse:
+ {
+ if ( SubState() == EUpdating )
+ {
+ Actions().StopUpdatingMedia();
+ Actions().UpdateFailed();
+ Actions().StateChanged( KMceStateEstablished );
+ Actions().ClientStateChangedL( CMceSession::EEstablished, *iBody, aError );
+ }
+ else
+ {
+ Actions().StopMedia();
+ FCActions().ReleaseFC();
+ CSIPDialog::TState dialogState = Dialog()->Dialog().State();
+ if ( dialogState == CSIPDialog::EConfirmed )
+ {
+ // ACK is already sent, terminate session with BYE
+ Actions().SendBYEL();
+ Actions().StateChanged( KMceStateTerminating );
+ Actions().ClientStateChangedL( CMceSession::ETerminating );
+ }
+ else if ( dialogState == CSIPDialog::EEarly )
+ {
+ Actions().SendCancelL();
+ Actions().StateChanged( KMceStateCanceled );
+ Actions().ClientStateChangedL( CMceSession::ECancelling );
+ }
+ // for 3xx response error situation
+ else if ( dialogState == CSIPDialog::ETerminated )
+ {
+ Actions().StateChanged( KMceStateTerminated );
+ Actions().ClientStateChangedL(
+ CMceSession::ETerminated, *Body(), Response() );
+ }
+ else
+ {
+ // NOP
+ }
+ }
+
+ break;
+ }
+ default:
+ {
+ if ( aError == KErrTotalLossOfPrecision )
+ {
+ // unexpected request is rejected, but does not
+ // affect on session.
+ if ( Request().Type() == SIPStrings::StringF(
+ SipStrConsts::EPrack ) )
+ {
+ // unexpected PRACK
+ MceSip::DiscardRequest( Request(),
+ KMceSipCallOrTransactionDoesNotExist );
+ }
+ else
+ {
+ // Default handling for other methods
+ MceSip::DiscardRequest( Request() );
+ }
+ }
+ else
+ {
+ Actions().StopMedia();
+ FCActions().ReleaseFC();
+
+ // other errors cause session to be terminated
+ MceSip::DiscardRequest( Request(), aError );
+ if ( aEventCode == EMcePrack ||
+ aEventCode == EMceUpdate )
+ {
+ //reject also invite
+ DiscardInvite();
+ }
+ CSIPDialog::TState dialogState = Dialog()->Dialog().State();
+ if ( dialogState == CSIPDialog::EConfirmed )
+ {
+ // terminate established session with BYE
+ Actions().SendBYEL();
+ Actions().StateChanged( KMceStateTerminating );
+ Actions().ClientStateChangedL( CMceSession::ETerminating );
+ }
+ else
+ {
+ Actions().StateChanged( KMceStateTerminated );
+ Actions().ClientStateChangedL( CMceSession::ETerminated );
+ }
+ }
+ break;
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::SdpCleanup
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::SdpCleanup( CSdpDocument* aPrevious, CSdpDocument* aReplacement )
+ {
+ if ( iBody )
+ {
+ iBody->SdpCleanup( aPrevious, aReplacement );
+ }
+
+ if ( iNewBodyCandidate )
+ {
+ iNewBodyCandidate->SdpCleanup( aPrevious, aReplacement );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::CreateIncomingDialogL
+// -----------------------------------------------------------------------------
+//
+CSIPDialogAssocBase* CMceSipSession::CreateIncomingDialogL(
+ CSIPServerTransaction& aInitialRequest )
+ {
+ MCESRV_DEBUG("CMceSipSession::CreateIncomingDialogL, Entry");
+ __ASSERT_ALWAYS( ProfileConfigured(), User::Leave( KErrArgument ) );
+
+ CSIPInviteDialogAssoc* dialog =
+ CSIPInviteDialogAssoc::NewL( aInitialRequest, Profile() );
+
+ MCESRV_DEBUG("CMceSipSession::CreateIncomingDialogL, Exit");
+
+ return dialog;
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::CreateOutgoingDialogL
+// -----------------------------------------------------------------------------
+//
+CSIPDialogAssocBase* CMceSipSession::CreateOutgoingDialogL(
+ TMceDialogType aDialogType,
+ CDesC8Array& /*aParams*/,
+ CSIPDialog& aExistingDialog )
+ {
+ MCESRV_DEBUG("CMceSipSession::CreateOutgoingDialogL( existing dlg ), Entry");
+
+ __ASSERT_ALWAYS( aDialogType == KMceDlgTypeInvite, User::Leave( KErrArgument ) );
+
+
+ CSIPInviteDialogAssoc* dialog =
+ CSIPInviteDialogAssoc::NewL( aExistingDialog );
+
+ MCESRV_DEBUG("CMceSipSession::CreateOutgoingDialogL( existing dlg ), Exit");
+
+ return dialog;
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::CreateOutgoingDialogL
+// -----------------------------------------------------------------------------
+//
+CSIPDialogAssocBase* CMceSipSession::CreateOutgoingDialogL(
+ TMceDialogType aDialogType,
+ CDesC8Array& aParams )
+ {
+ MCESRV_DEBUG("CMceSipSession::CreateOutgoingDialogL( new dlg ), Entry");
+
+ __ASSERT_ALWAYS( aDialogType == KMceDlgTypeInvite,
+ User::Leave( KErrArgument ) );
+
+ CSIPInviteDialogAssoc* inviteDialog = NULL;
+ CSIPConnection& connection = SIPConnection().Connection();
+ if ( ProfileConfigured() )
+ {
+ const CSIPProfile& profile = Profile();
+ TPtrC8 originator = aParams.MdcaPoint( KMceArrayIndexOriginator );
+ TPtrC8 recipient = aParams.MdcaPoint( KMceArrayIndexRecipient );
+ CSIPToHeader* toHeader = CSIPToHeader::DecodeL( recipient );
+ CleanupStack::PushL( toHeader );
+ CUri8* remoteUri = CUri8::NewLC( toHeader->SIPAddress().Uri8().Uri() );
+
+ // create targetset with remoteUri of the request
+ AddRemoteUriL( *remoteUri );
+ CSIPFromHeader* fromHeader = NULL;
+ if ( originator.Length() > 0 )
+ {
+ fromHeader = MceSip::ToFromHeaderL( originator );
+ CleanupStack::PushL( fromHeader );
+ }
+
+ //create dialog
+ MCESRV_DEBUG_SVALUE("CreateOutgoingDialogL: originator",originator);
+ MCESRV_DEBUG_SVALUE("CreateOutgoingDialogL: recipient",recipient);
+ MCESRV_DEBUG_SVALUE("CreateOutgoingDialogL: remote uri",
+ remoteUri->Uri().UriDes() );
+
+ inviteDialog =
+ CSIPInviteDialogAssoc::NewL( connection,
+ remoteUri,
+ profile,
+ fromHeader,
+ toHeader );
+ if ( fromHeader )
+ {
+ CleanupStack::Pop( fromHeader );
+ }
+ CleanupStack::Pop( remoteUri );
+ CleanupStack::Pop( toHeader );
+ }
+ else
+ {
+ TPtrC8 originator = aParams.MdcaPoint( KMceArrayIndexOriginator );
+ TPtrC8 recipient = aParams.MdcaPoint( KMceArrayIndexRecipient );
+ CSIPToHeader* toHeader = CSIPToHeader::DecodeL( recipient );
+ CleanupStack::PushL( toHeader );
+ CUri8* remoteUri = CUri8::NewLC( toHeader->SIPAddress().Uri8().Uri() );
+
+ // Add remote uri of the request to an array
+ AddRemoteUriL( *remoteUri );
+
+ CSIPFromHeader* fromHeader = NULL;
+ if ( originator.Length() > 0 )
+ {
+ fromHeader = MceSip::ToFromHeaderL( originator );
+ CleanupStack::PushL( fromHeader );
+ }
+
+ //create dialog
+ MCESRV_DEBUG_SVALUE("CreateOutgoingDialogL: originator",originator);
+ MCESRV_DEBUG_SVALUE("CreateOutgoingDialogL: recipient",recipient);
+ MCESRV_DEBUG_SVALUE("CreateOutgoingDialogL: remote uri",
+ remoteUri->Uri().UriDes() );
+
+ inviteDialog =
+ CSIPInviteDialogAssoc::NewL( connection,
+ fromHeader,
+ remoteUri,
+ toHeader );
+ if ( fromHeader )
+ {
+ CleanupStack::Pop( fromHeader );
+ }
+ CleanupStack::Pop( remoteUri );
+ CleanupStack::Pop( toHeader );
+
+ }
+ MCESRV_DEBUG("CMceSipSession::CreateOutgoingDialogL( new dlg ), Exit");
+ return inviteDialog;
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::ReCreateOutgoingDialogL
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::ReCreateOutgoingDialogL()
+ {
+ RStringF tagT = SIPStrings::StringF( SipStrConsts::ETag );
+ MCESRV_DEBUG("CMceSipSession::ReCreateOutgoingDialogL, Entry");
+ CSIPClientTransaction& response = Response();
+
+ const CSIPResponseElements* respElements = response.ResponseElements();
+
+ const CSIPToHeader* toHdr = respElements->ToHeader();
+
+ CSIPToHeader* newToHdr = static_cast<CSIPToHeader *>( toHdr->CloneL() );
+
+ newToHdr->DeleteParam( tagT );
+
+ CleanupStack::PushL( newToHdr );
+
+ CUri8* remoteUri = CUri8::NewLC( toHdr->SIPAddress().Uri8().Uri() );
+
+ CSIPInviteDialogAssoc* newSipBaseDialog =
+ DoCreateOutgoingDialogL( remoteUri, newToHdr );
+
+ CleanupStack::Pop( remoteUri );
+ CleanupStack::Pop( newToHdr );
+
+ TUint32 oldDialogId = DialogId();
+
+ MCE_DELETE( iDialog );
+ SetDialog( CMceCsSubSession::EOutSession, newSipBaseDialog, oldDialogId );
+
+ ResetInitialInvite();
+ MCESRV_DEBUG("CMceSipSession::ReCreateOutgoingDialogL, Exit");
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::CreateDialogFrom3XXResponseL
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::CreateDialogFrom3XXResponseL()
+ {
+ MCESRV_DEBUG("CMceSipSession::CreateDialogFrom3XXResponseL, Entry");
+ TInt count = iRemoteUri.Count();
+ RDebug::Print( _L("CMceSipSession::CreateDialogFrom3XXResponseL, iRemoteUri.Count()= %d"), count );
+ __ASSERT_ALWAYS( count > 0, User::Leave( KErrArgument ) );
+
+ const CUri8* nextUri = iRemoteUri[count-1];
+
+ // create CSIPToHeader
+ CSIPToHeader* newToHdr = CSIPToHeader::DecodeL( nextUri->Uri().UriDes() );
+ // remove tag
+ RStringF tagT = SIPStrings::StringF( SipStrConsts::ETag );
+ newToHdr->DeleteParam( tagT );
+ CleanupStack::PushL( newToHdr );
+
+ // create new remote uri
+ TUriParser8 uri8Parser;
+ User::LeaveIfError( uri8Parser.Parse( nextUri->Uri().UriDes() ) );
+
+ CUri8* remoteUri = CUri8::NewLC( uri8Parser );
+
+ // create new dialog association
+ CSIPInviteDialogAssoc* newSipBaseDialog =
+ DoCreateOutgoingDialogL( remoteUri, newToHdr );
+
+ CleanupStack::Pop( remoteUri );
+ CleanupStack::Pop( newToHdr );
+
+ TUint32 oldDialogId = DialogId();
+
+ MCE_DELETE( iDialog );
+ SetDialog( CMceCsSubSession::EOutSession, newSipBaseDialog, oldDialogId );
+
+ ResetInitialInvite();
+
+ if ( Body() && &Body()->SdpSession() )
+ {
+ Body()->SdpSession().AttachContext( NULL ); // Clear first
+ Body()->SdpSession().AttachContext( Dialog() );
+ }
+
+ MCESRV_DEBUG("CMceSipSession::CreateDialogFrom3XXResponseL, Exit");
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::ReUseDialog
+// -----------------------------------------------------------------------------
+//
+TInt CMceSipSession::ReUseDialog()
+ {
+ return iDialog->Dialog().ReuseInitialRequestData();
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::DoCreateOutgoingDialogL
+// -----------------------------------------------------------------------------
+//
+CSIPInviteDialogAssoc* CMceSipSession::DoCreateOutgoingDialogL(
+ CUri8* remoteURI,
+ CSIPToHeader* to )
+ {
+ __ASSERT_ALWAYS( ProfileConfigured(), User::Leave( KErrArgument ) );
+
+ CSIPConnection& connection = SIPConnection().Connection();
+ const CSIPProfile& profile = Profile();
+
+ return CSIPInviteDialogAssoc::NewL( connection, remoteURI, profile,
+ NULL, to );
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::Dialog
+// -----------------------------------------------------------------------------
+//
+CSIPDialogAssocBase* CMceSipSession::Dialog() const
+ {
+ CSIPDialogAssocBase* dialog = NULL;
+ if ( iForkedDialogs.Count() == 0 )
+ {
+ dialog = CMceCsSubSession::Dialog();
+ }
+ else
+ {
+ dialog = iCurrentDialog;
+ }
+
+ return dialog;
+ }
+
+
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::Consumes
+// -----------------------------------------------------------------------------
+//
+
+TBool CMceSipSession::Consumes( CSIPDialog& aDialog,
+ CSIPServerTransaction& aTransaction,
+ TBool& aAssociatesWithDialog )
+
+ {
+
+ TBool consumes = CMceCsSubSession::Consumes( aDialog, aTransaction,
+ aAssociatesWithDialog );
+
+ if ( !aAssociatesWithDialog &&
+ CMceCsSubSession::Dialog()->Dialog() == aDialog )
+ //dialog might be forked and current dialog is the forked one
+ {
+ aAssociatesWithDialog = ETrue;
+ consumes = AcceptMethod( MceSip::Method( aTransaction ) );
+ }
+ else if ( !aAssociatesWithDialog )
+ {
+ //dialog might be forked and current dialog is the original one
+ CSIPInviteDialogAssoc* forkedDlg = NULL;
+ TInt index = 0;
+ while( !aAssociatesWithDialog && index < iForkedDialogs.Count() )
+ {
+ forkedDlg = iForkedDialogs[ index++ ];
+ if ( forkedDlg->Dialog() == aDialog )
+ {
+ aAssociatesWithDialog = ETrue;
+ consumes = AcceptMethod( MceSip::Method( aTransaction ) );
+ }
+ }
+ }
+ else
+ {
+ //NOP
+ }
+
+ return consumes;
+
+ }
+
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::InviteCompleted
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::InviteCompleted( CSIPClientTransaction& aTransaction )
+ {
+ CMceCsSubSession::InviteCompleted( aTransaction );
+ iForkedDialogs.ResetAndDestroy();
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::ResponseReceived
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::ResponseReceived()
+ {
+ MCESRV_DEBUG("CMceSipSession::ResponseReceived, Entry");
+
+ if ( iCurrentState->Id() == KMceStateEstablished &&
+ Response().Type() == SIPStrings::StringF( SipStrConsts::EInvite ) )
+ {
+ //Send ACK for signaling integrality
+ TRAP_IGNORE( Actions().SendACKL( Response() ) );
+ // If the 2xx response in the same dialog that established current session
+ // Just reply ACK for it, otherwise, send bye to terminate the dialog
+ if ( iDialog != iCurrentDialog )
+ {
+ // Send BYE to end forked dialog
+ TRAP_IGNORE( Actions().SendBYEL() );
+ // Set the original dialog back as the current dialog
+ iCurrentDialog = iDialog;
+ }
+ }
+ else
+ {
+ if ( Response().Type() == SIPStrings::StringF( SipStrConsts::EInvite ) )
+ {
+ // If one of the forked dialogs generated 200 OK response
+ // for a session that is not in established state,
+ // replace the actual dialog with that
+ HandleForkedDialogs();
+ }
+ else
+ {
+ iCurrentDialog = iDialog;
+ }
+ HandleSIPEvent( EMceResponse, Dialog()->Dialog() );
+ }
+
+ MCESRV_DEBUG("CMceSipSession::ResponseReceived, Exit");
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::ProvisionalResponseReceived
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::ProvisionalResponseReceived()
+ {
+ MCESRV_DEBUG("CMceSipSession::ProvisionalResponseReceived, Entry");
+
+ HandleSIPEvent( EMceProvisionalResponse, Dialog()->Dialog() );
+
+ MCESRV_DEBUG("CMceSipSession::ProvisionalResponseReceived, Exit");
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::RedirectionResponseReceived
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::RedirectionResponseReceived()
+ {
+ MCESRV_DEBUG("CMceSipSession::RedirectionResponseReceived, Entry");
+
+ HandleForkedDialogs();
+
+ HandleSIPEvent( EMceRedirectionResponse, Dialog()->Dialog());
+
+ iForkedDialogs.ResetAndDestroy();
+
+ MCESRV_DEBUG("CMceSipSession::RedirectionResponseReceived, Exit");
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::ErrorResponseReceived
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::ErrorResponseReceived()
+ {
+ MCESRV_DEBUG("CMceSipSession::ErrorResponseReceived, Entry");
+
+ HandleForkedDialogs();
+
+ HandleSIPEvent( EMceErrorResponse, Dialog()->Dialog() );
+
+ iForkedDialogs.ResetAndDestroy();
+
+ MCESRV_DEBUG("CMceSipSession::ErrorResponseReceived, Exit");
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::StandAloneRequestReceived
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::StandAloneRequestReceived()
+ {
+ MCESRV_DEBUG("CMceSipSession::StandAloneRequestReceived, Entry");
+ // Method is acceptable for session, but receiving them outside session
+ // is not acceptable.
+ MceSip::DiscardRequest( Request() );
+
+ MCESRV_DEBUG("CMceSipSession::StandAloneRequestReceived, Exit");
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::SubState
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::SetSubState( CMceSipSession::TSubState aSubState )
+ {
+ MCESRV_DEBUG("CMceSipSession::SetSubState, Entry");
+ MCESRV_DEBUG_SUBSTATE("SetSubState: old sub state", iSubState );
+
+ iSubState = aSubState;
+
+ MCESRV_DEBUG_SUBSTATE("SetSubState: new sub state", iSubState );
+ MCESRV_DEBUG("CMceSipSession::SetSubState, Exit");
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::SubState
+// -----------------------------------------------------------------------------
+//
+CMceSipSession::TSubState CMceSipSession::SubState()
+ {
+ return iSubState;
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::UpdateAccepted
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::UpdateAccepted()
+ {
+ CMceComSession::Delete( iBody, Manager().MediaManager() );
+ iBody = BodyCandidate();
+ iBody->iCloneOrigin = NULL;
+ iNewBodyCandidate = NULL;
+ iBody->iFcSignallingRequired = EFalse;
+ iBody->iRequireSignalling = EFalse;
+ iBody->iPullModeUpdate = EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::UpdateRejected
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::UpdateRejected()
+ {
+ if ( iBody && &iBody->SdpSession() && iBody->SdpSession().iOOldSchool )
+ {
+ if ( iBody->SdpSession().iOOldSchoolProceeding )
+ {
+ iBody->SdpSession().iOOldSchool = 0;
+ iBody->SdpSession().iOOldSchoolProceeding = 0;
+ iBody->SdpSession().iOOldSchoolCompleted = 1;
+ }
+ else
+ {
+ iBody->SdpSession().iOOldSchoolProceeding = 1;
+ iBody->SdpSession().iOOldSchoolCompleted = 0;
+ }
+ }
+ // reset the remoteUri Array if updated failed
+ iRemoteUri.ResetAndDestroy();
+
+ CMceComSession::Delete( iNewBodyCandidate, Manager().MediaManager() );
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::SetBodyL
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::SetBodyL( CMceComSession* aSession )
+ {
+ __ASSERT_ALWAYS( !iBody, User::Leave( KErrArgument ) );
+ TInetAddr nextHop;
+
+ TInetAddr localIpAddress = SIPConnection().LocalIPAddressL( NextHopL( nextHop ) );
+
+ if ( !aSession )
+ {
+ iBody = CMceComSession::NewL( CMceComSession::EInSession );
+ SetSubState( EAnswering );
+ }
+ else
+ {
+ __ASSERT_ALWAYS( aSession->iType == CMceComSession::EOutSession,
+ User::Leave( KErrArgument ) );
+ iBody = aSession;
+ SetSubState( EOffering );
+
+ }
+
+ iBody->SetObserver( *this );
+ MCE_SET_LOCAL_IP_ADDR( iBody, localIpAddress );
+ iBody->iIapId = SIPConnection().AccessPointId();
+ iBody->iDialogId = DialogId();
+
+ iExtensions->Update( *iBody );
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::PrepareIdsL
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::PrepareIdsL( TMceIds& aIds ) const
+ {
+ aIds.iMsgType = EMceItcMsgTypeSession;
+ aIds.iManagerType = KMceCSSIPSession;
+ aIds.iDialogType = KMceDlgTypeInvite;
+ aIds.iDialogID = DialogId();
+
+ if ( ProfileConfigured() )
+ {
+ TUint32 profileId;
+ User::LeaveIfError( Profile().GetParameter( KSIPProfileId, profileId ) );
+
+ aIds.iProfileID = profileId;
+ }
+
+ aIds.iSecureFlag = iBody->iIsSecureSession;
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::InviteTransaction
+// -----------------------------------------------------------------------------
+//
+CSIPClientTransaction* CMceSipSession::InviteTransaction()
+ {
+ CSIPClientTransaction* trx = NULL;
+ TInt index = 0;
+
+ while( !trx && index < PendingTransactions().Count() )
+ {
+ trx = PendingTransactions()[ index++ ];
+ TBool isInvite =
+ trx->Type() == SIPStrings::StringF( SipStrConsts::EInvite );
+ TBool isCompleted = MceSip::TrxCompleted( *trx );
+
+ trx = isInvite && !isCompleted ? trx : NULL;
+ }
+
+ return trx;
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::StandAloneResponseReceived
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::StandAloneResponseReceived(
+ TMceSipResponseType /*aResponseType*/ )
+ {
+ MCESRV_DEBUG("CMceSipSession::StandAloneResponseReceived, Entry");
+
+ //if response to CANCEL
+ if ( MceSip::IsResponseTo( Response(),
+ SIPStrings::StringF( SipStrConsts::ECancel ) ) )
+ {
+ ResponseReceived();
+ }
+ else
+ {
+ MCESRV_DEBUG("StandAloneResponseReceived: NOT CANCEL. IGNORED");
+ //NOP
+ }
+
+ MCESRV_DEBUG("CMceSipSession::StandAloneResponseReceived, Exit");
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::ErrorOccured
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::ErrorOccured( TInt aError )
+ {
+ MCESRV_DEBUG("CMceSipSession::ErrorOccured, Entry")
+
+ TUint newState( KMceStateError );
+ CMceSession::TState newClientState( CMceSession::ETerminated );
+
+ if ( CurrentState().Id() == KMceStateTerminating )
+ {
+ // Failed to send BYE. ignore and set the state to terminated.
+ newState = KMceStateTerminated;
+ }
+ else if ( ( aError == KErrSIPNoAckReceived && ( SubState() == EAnswering || SubState() == EUpdating ) ) ||
+ ( CurrentState().Id() == KMceStateOffering ) ||
+ ( CurrentState().Id() == KMceStateConfirming ) )
+ {
+ if ( Dialog() )
+ {
+ CSIPDialog::TState dialogState = Dialog()->Dialog().State();
+ switch ( dialogState )
+ {
+ case CSIPDialog::EEarly:
+ {
+ TRAP_IGNORE( Actions().SendCancelL() )
+ newState = KMceStateCanceled;
+ newClientState = CMceSession::ECancelling;
+ break;
+ }
+ case CSIPDialog::EConfirmed:
+ {
+ TRAP_IGNORE( Actions().SendBYEL() )
+ newState = KMceStateTerminating;
+ newClientState = CMceSession::ETerminating;
+ break;
+ }
+ default:
+ {
+ newState = KMceStateTerminated;
+ break;
+ }
+ }
+ }
+ }
+
+ if ( CurrentState().Id() != KMceStateTerminating )
+ {
+ Actions().StopMedia();
+ FCActions().ReleaseFC();
+ }
+
+ Actions().StateChanged( newState );
+ TRAP_IGNORE( Actions().ClientStateChangedL( newClientState, aError ) )
+ MCESRV_DEBUG("CMceSipSession::ErrorOccured, Exit")
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::DoErrorOccured
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::DoErrorOccured( TInt aError,
+ CSIPTransactionBase& aTransaction )
+ {
+ // If Error is for Extension Request
+ if ( Actions().IsExtensionRequest( aTransaction.Type()) )
+ {
+ Actions().ReceiveExtensionError( aTransaction, aError );
+ }
+ else
+ {
+ ErrorOccured( aError );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::ErrorOccured
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::LocalErrorOccured( TMceStateIndex aNewState, TInt aWithError )
+ {
+ MCESRV_DEBUG("CMceSipSession::LocalErrorOccured( state, error), Entry");
+ MCESRV_DEBUG_DVALUE("ERROR", aWithError );
+
+ if ( aNewState == KMceStateError )
+ {
+ Actions().StopMedia();
+ FCActions().ReleaseFC();
+ }
+
+ Actions().StateChanged( aNewState );
+ Actions().ClientErrorOccured( aWithError );
+
+ MCESRV_DEBUG("CMceSipSession::LocalErrorOccured( state, error), Exit");
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::Terminate
+// -----------------------------------------------------------------------------
+//
+TBool CMceSipSession::Terminate()
+ {
+ MCESRV_DEBUG( "CMceSipSession::Terminate, Entry" );
+ TRAPD( error, DoTerminateL() );
+ if ( error )
+ {
+ MCESRV_DEBUG_DVALUE( "CMceSipSession::Terminate, ERROR:", error );
+ Actions().StateChanged( KMceStateTerminated );
+ }
+ MCESRV_DEBUG( "CMceSipSession::Terminate, Exit" );
+ return CanDispose();
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::DiscardInvite
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::DiscardInvite()
+ {
+ CSIPServerTransaction* invite = FIRST_REQUEST();
+ if ( MceSip::TrxType( *invite ) == SipStrConsts::EInvite )
+ {
+ MceSip::DiscardRequest( *invite );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::DoTerminateL
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::DoTerminateL()
+ {
+ TMceStateIndex currentState = CurrentState().Id();
+
+ MCESRV_DEBUG_STATE("DoTerminateL: current state", currentState );
+
+ Actions().StopMedia();
+ FCActions().ReleaseFC();
+
+ switch( currentState )
+ {
+ case KMceStateAnswering:
+ {
+ MCESRV_DEBUG("DoTerminateL: KMceStateAnswering -> BYE");
+ Actions().SendBYEL();
+ //going to still wait ACK or error that ACK not received
+ break;
+ }
+ case KMceStateEstablished:
+ {
+ MCESRV_DEBUG("DoTerminateL: KMceStateEstablished -> BYE");
+ Actions().SendBYEL();
+ Actions().StateChanged( KMceStateTerminating );
+ break;
+ }
+ case KMceStateError:
+ {
+ MCESRV_DEBUG("DoTerminateL: KMceStateError:");
+
+ TMceStateIndex nextState = KMceStateTerminated;
+ if ( iExitState )
+ {
+ TMceStateIndex exitStateId = iExitState->Id();
+ MCESRV_DEBUG_STATE("from state", exitStateId );
+
+ if ( iExitState->Id() == KMceStateEstablished ||
+ iExitState->Id() == KMceStateAnswering )
+ {
+ MCESRV_DEBUG("DoTerminateL: KMceStateError -> BYE");
+ Actions().SendBYEL();
+ nextState = KMceStateTerminating;
+ }
+ }
+ Actions().StateChanged( nextState );
+ break;
+ }
+ case KMceStateUpdated:
+ {
+ MCESRV_DEBUG("DoTerminateL: KMceStateUpdated -> DECLINE");
+ if ( &Request() )
+ {
+ CMceMsgSIPData msg;
+ Actions().SendDeclineL(Request(), msg );
+ }
+ Actions().StateChanged( KMceStateTerminated );
+ break;
+ }
+ case KMceStateIdle:
+ case KMceStateServerInitializing:
+ case KMceStateTerminating:
+ {
+ MCESRV_DEBUG("DoTerminateL: KMceStateUpdated, KMceStateIdle");
+ Actions().StateChanged( KMceStateTerminated );
+ break;
+ }
+ case KMceStateOffering:
+ {
+ MCESRV_DEBUG("DoTerminateL: KMceStateOffering");
+ if ( SubState() == EOffering )
+ {
+ CSIPClientTransaction* lastResponse = &Response();
+
+ if ( lastResponse && MceSip::TrxCompleted( *lastResponse )
+ && ( PendingTransaction(SIPStrings::StringF(
+ SipStrConsts::EInvite )) == NULL ))
+ {
+ // 200 OK already received and waiting for media, bye can be sent
+ MCESRV_DEBUG("DoTerminateL: KMceStateOffering -> BYE");
+ Actions().SendBYEL();
+ Actions().StateChanged( KMceStateTerminating );
+ }
+ else
+ {
+ MCESRV_DEBUG("DoTerminateL: KMceStateOffering -> CANCEL");
+ Actions().SendCancelL();
+ Actions().StateChanged( KMceStateCanceled );
+ }
+ }
+ break;
+ }
+ case KMceStateServerEstablishing:
+ {
+ MCESRV_DEBUG("DoTerminateL: KMceStateServerEstablishing -> DECLINE");
+ if ( &Request() && Dialog() )
+ {
+ MceSip::DiscardRequest( Request(), KMceSipDecline );
+ if ( Dialog()->Dialog().State() == CSIPDialog::EConfirmed )
+ {
+ Actions().SendBYEL();
+ Actions().StateChanged( KMceStateTerminating );
+ }
+ else
+ {
+ Actions().StateChanged( KMceStateTerminated );
+ }
+ }
+ else
+ {
+ Actions().StateChanged( KMceStateTerminated );
+ }
+ break;
+ }
+ default:
+ {
+ //NOP
+ }
+
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::DoConnectionStateChanged
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::DoConnectionStateChanged( TBool aIsActive )
+ {
+ MCESRV_DEBUG("CMceSipSession::ConnectionStateChanged, Entry");
+
+ if ( iBody )
+ {
+ iBody->iIsConnectionActive = aIsActive;
+ }
+
+ MCESRV_DEBUG("CMceSipSession::ConnectionStateChanged, Exit");
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::Canceled
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::Canceled()
+ {
+ MCESRV_DEBUG("CMceSipSession::Canceled, Entry");
+
+ if ( IsSipDialogConfirmed() )
+ {
+ // cancel the reinvite shouldn't terminate original session.
+ Actions().StopUpdatingMedia();
+ Actions().UpdateFailed();
+ Actions().StateChanged( KMceStateEstablished );
+ TRAP_IGNORE( Actions().ClientStateChangedL(
+ CMceSession::EEstablished, *Body(), KErrCancel ) );
+ }
+ else
+ {
+ Actions().StopMedia();
+ FCActions().ReleaseFC();
+ Actions().StateChanged( KMceStateTerminated );
+ TRAP_IGNORE( Actions().ClientStateChangedL( CMceSession::ETerminated ) );
+ }
+
+ MCESRV_DEBUG("CMceSipSession::Canceled, Exit");
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::DoServiceL
+// -----------------------------------------------------------------------------
+//
+HBufC8* CMceSipSession::DoServiceL( TMceIds& aIds,
+ TMceItcFunctions aFunction )
+ {
+ MCESRV_DEBUG("CMceSipSession::DoServiceL( no message ), Entry");
+ MCESRV_DEBUG_EVENT("ITC function", aFunction );
+
+ HBufC8* returnMessage = NULL;
+
+ TMceStateTransitionEvent event( *this, aFunction, aIds );
+ if ( iStateMachine->Consumes( event ) )
+ {
+ MCESRV_DEBUG("handler: state machine");
+ iStateMachine->ProcessL( event );
+ }
+ else
+ {
+ switch ( aFunction )
+ {
+ case EMceItcFCGetMediaLines:
+ {
+ MCESRV_DEBUG("handler: floor control");
+ returnMessage = FCActions().FCGetMediaLinesL();
+ break;
+ }
+ case EMceItcGetSession:
+ {
+ MCESRV_DEBUG("handler: session");
+ returnMessage = Actions().BodyToTextL();
+ break;
+ }
+ //rtp sink
+ case EMceItcSendSR:
+ case EMceItcSendRR:
+ case EMceItcSetFastForward:
+ case EMceItcSetFastRewind:
+ case EMceItcDisableInactivityTimer:
+ //dtmf
+ case EMceItcIsDtmfActive:
+ case EMceItcStartDtmfTone:
+ case EMceItcStopDtmfTone:
+ case EMceItcSendDtmfTone:
+ case EMceItcCancelSendDtmfToneSequence:
+ {
+ MCESRV_DEBUG("handler: media");
+ returnMessage = Actions().ControlMediaL( aIds, aFunction );
+ break;
+ }
+ default:
+ {
+ MCESRV_DEBUG("NOT SUPPORTED");
+ User::Leave( KErrNotSupported );
+ break;
+ }
+ }
+ }
+
+ MCESRV_DEBUG("CMceSipSession::DoServiceL( no message ), Exit");
+
+ return returnMessage;
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::DoServiceL
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::DoServiceL( TMceIds& aIds,
+ TMceItcFunctions aFunction,
+ const TDesC8& aMessage )
+ {
+ MCESRV_DEBUG("CMceSipSession::DoServiceL( write data ), Entry");
+ MCESRV_DEBUG_EVENT("ITC function", aFunction );
+
+ switch ( aFunction )
+ {
+ case EMceItcInitFC:
+ {
+ MCESRV_DEBUG("handler: floor control");
+ iUseFC = ETrue;
+ FCActions().InitializeFCL ( aIds, aMessage );
+ break;
+ }
+ case EMceItcUpdateFC:
+ {
+ MCESRV_DEBUG("handler: floor control");
+ iUseFC = ETrue;
+ FCActions().UpdateFCL( aIds, aMessage );
+ break;
+ }
+ case EMceItcSendFCMsg:
+ {
+ MCESRV_DEBUG("handler: floor control");
+ FCActions().SendFCMsgL ( aMessage );
+ break;
+ }
+ //speaker sink
+ case EMceItcSetVolume:
+ case EMceItcSetAudioRouting:
+ //mic source
+ case EMceItcSetGain:
+ //rtp source
+ case EMceItcEnableInactivityTimer:
+ //camera source
+ case EMceItcSetZoomFactor:
+ case EMceItcSetDigitalZoomFactor:
+ case EMceItcSetContrast:
+ case EMceItcSetBrightness:
+ case EMceItcSetExposure:
+ case EMceItcSetWhiteBalance:
+ //display sink
+ case EMceItcSetDisplayIndex:
+ case EMceItcSetDisplayPriority:
+ case EMceItcSetDisplayRect:
+ case EMceItcSetDisplayRotation:
+ //file source
+ case EMceItcSetFilePosition:
+ case EMceItcSetFileInfo:
+ //dtmf
+ case EMceItcSendDtmfToneSequence:
+ {
+ MCESRV_DEBUG("handler: media");
+ Actions().ControlMediaL( aIds, aFunction, aMessage );
+ break;
+ }
+ default:
+ {
+ MCESRV_DEBUG("NOT SUPPORTED");
+ User::Leave( KErrNotSupported );
+ break;
+ }
+ }
+
+ MCESRV_DEBUG("CMceSipSession::DoServiceL( write data ), Exit");
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::DoServiceL
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::DoServiceL( TMceIds& aIds,
+ TMceItcFunctions aFunction,
+ TPtr8& aMessage )
+ {
+ MCESRV_DEBUG("CMceSipSession::DoServiceL( read data ), Entry");
+ MCESRV_DEBUG_EVENT("ITC function", aFunction );
+
+ switch ( aFunction )
+ {
+ case EMceItcVolume:
+ case EMceItcAudioRouting:
+ case EMceItcGain:
+ case EMceItcZoomFactor:
+ case EMceItcDigitalZoomFactor:
+ case EMceItcContrast:
+ case EMceItcBrightness:
+ case EMceItcExposure:
+ case EMceItcWhiteBalance:
+ case EMceItcDisplayRect:
+ case EMceItcDisplayPriority:
+ case EMceItcDisplayRotation:
+ case EMceItcFileInfo:
+ case EMceItcFilePosition:
+ case EMceItcSetCameraIndex:
+ {
+ MCESRV_DEBUG("handler: media");
+ Actions().ControlMediaL( aIds, aFunction, aMessage );
+ break;
+ }
+ default:
+ {
+ MCESRV_DEBUG("NOT SUPPORTED");
+ User::Leave( KErrNotSupported );
+ break;
+ }
+ }
+
+ MCESRV_DEBUG("CMceSipSession::DoServiceL( read data ), Exit");
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::DoServiceL
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::DoServiceL( TMceIds& aIds,
+ TMceItcFunctions aFunction,
+ CMceMsgBase& aMessage )
+ {
+ MCESRV_DEBUG("CMceSipSession::DoServiceL( message ), Entry");
+ MCESRV_DEBUG_EVENT("ITC function", aFunction );
+
+
+ TMceStateTransitionEvent event( *this, aFunction, aIds, aMessage );
+ if ( iStateMachine->Consumes( event ) )
+ {
+ MCESRV_DEBUG("handler: state machine");
+ iStateMachine->ProcessL( event );
+ }
+ else
+ {
+ switch ( aFunction )
+ {
+ case EMceItcFCSetMediaLines:
+ {
+ MCESRV_DEBUG("handler: floor control");
+ FCActions().FCSetMediaLinesL ( aMessage );
+ break;
+ }
+ default:
+ {
+ MCESRV_DEBUG("NOT SUPPORTED");
+ User::Leave( KErrNotSupported );
+ break;
+ }
+ }
+ }
+
+ MCESRV_DEBUG("CMceSipSession::DoServiceL( message ), Exit");
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::Updated
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::Updated( CMceComSession& aSession )
+ {
+ MCESRV_DEBUG("CMceSipSession::Updated, Entry");
+
+ __ASSERT_ALWAYS( &aSession == iBody || &aSession == iNewBodyCandidate,
+ User::Panic( KMceServerPanic, KErrArgument ) );
+
+ TMceStateTransitionEvent event( *this, EMceMediaUpdated );
+ TRAPD( error, iStateMachine->ProcessL( event ) );
+ if ( error != KErrNone )
+ {
+ MCESRV_DEBUG_DVALUE("Updated: state machine causes ERROR", error );
+ LocalErrorOccured( KMceStateError, error );
+ }
+
+ MCESRV_DEBUG("CMceSipSession::Updated, Exit");
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::Reserved
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::Reserved( CMceComSession& aSession )
+ {
+ MCESRV_DEBUG("CMceSipSession::Reserved, Entry");
+
+ __ASSERT_ALWAYS( &aSession == iBody || &aSession == iNewBodyCandidate,
+ User::Panic( KMceServerPanic, KErrArgument ) );
+
+ TMceStateTransitionEvent event( *this, EMceMediaReserved );
+ TRAPD( error, iStateMachine->ProcessL( event ) );
+ if ( error != KErrNone )
+ {
+ MCESRV_DEBUG_DVALUE("Reserved: state machine causes ERROR", error );
+ LocalErrorOccured( KMceStateError, error );
+ }
+
+ MCESRV_DEBUG("CMceSipSession::Reserved, Exit");
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::SessionClosed
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::SessionClosed( CMceComSession& aSession )
+ {
+ MCESRV_DEBUG("CMceSipSession::SessionClosed, Entry");
+
+ __ASSERT_ALWAYS( &aSession == iBody || &aSession == iNewBodyCandidate,
+ User::Panic( KMceServerPanic, KErrArgument ) );
+
+ TMceStateTransitionEvent event( *this, EMceMediaSessionStopped );
+ TRAPD( error, iStateMachine->ProcessL( event ) );
+ if ( error != KErrNone )
+ {
+ MCESRV_DEBUG_DVALUE(
+ "SessionClosed: state machine causes ERROR", error );
+ LocalErrorOccured( KMceStateTerminated, error );
+ }
+
+ MCESRV_DEBUG("CMceSipSession::SessionClosed, Exit");
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::EventReceived
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::EventReceived( TMceMccComEvent& aEvent )
+ {
+ MCESRV_DEBUG("CMceSipSession::EventReceived, Entry");
+
+ if ( aEvent.iItcEvent == EMceItcFCMsgReceived &&
+ FCSession() &&
+ aEvent.iItcDataDesC )
+ {
+ HBufC8* data = NULL;
+ TRAPD( err, data = aEvent.iItcDataDesC->AllocL() );
+ if( err == KErrNone )
+ {
+ FCReceivedData( data, FCSession() );
+ }
+ else
+ {
+ MCESRV_DEBUG("RtcpSignalReceived, Alloc failed");
+ }
+ }
+ else
+ {
+ TRAPD( err, Actions().ClientMediaStateChangedL( &aEvent ) );
+ if( err != KErrNone )
+ {
+ MCESRV_DEBUG("RtcpSignalReceived, ClientMediaStateChanged failed");
+ }
+ }
+
+ MCESRV_DEBUG("CMceSipSession::EventReceived, Exit");
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::MediaError
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::MediaError( TMceMccComEvent& aEvent )
+ {
+#if MCE_IGNORE_MEDIA_ERROR
+
+ if ( aEvent.iError < 0 )
+ {
+ MCESRV_DEBUG_DVALUE("error", aEvent.iError );
+ MCESRV_DEBUG("CMceSipSession::MediaError, Exit");
+ return;
+ }
+
+#else
+
+ TMceStateTransitionEvent event( *this, aEvent, EMceMediaError );
+ CMceState& currentState = CurrentState();
+ currentState.MediaErrorOccured( event );
+
+#endif
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::SessionCreatedL
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::SessionCreatedL( CMceComSession* aSession )
+ {
+ MCESRV_DEBUG("CMceSipSession::SessionCreated, Entry");
+
+ __ASSERT_ALWAYS( iBody, User::Leave( KErrArgument ) );
+ __ASSERT_ALWAYS( aSession, User::Leave( KErrArgument ) );
+ aSession->SdpSession().AttachContext( Dialog() );
+
+ iBodyBucket.AppendL( iBody );
+ iBody = aSession;
+
+ MCESRV_DEBUG("CMceSipSession::SessionCreated, Exit");
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::TimerExpiredL
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::TimerExpiredL( TMceTimerId aTimerId, TAny* /*aTimerParam*/ )
+ {
+ MCESRV_DEBUG("CMceSipSession::TimerExpiredL, Entry");
+ TMceStateIndex currentState = CurrentState().Id();
+
+ if( aTimerId == iTimer && iBody->iRefresh )
+ {
+ TMceStateTransitionEvent event( *this, EMceSessionRefresh );
+ TRAPD( error, iStateMachine->ProcessL( event ) );
+ if ( error != KErrNone )
+ {
+ MCESRV_DEBUG_DVALUE(
+ "TimerExpiredL: state machine causes ERROR", error );
+ LocalErrorOccured( currentState, error );
+ }
+ }
+ else if( aTimerId == iPendingTimer )
+ {
+ TMceStateTransitionEvent event( *this, EMceSessionPending );
+ TRAPD( error, iStateMachine->ProcessL( event ) );
+ if ( error != KErrNone )
+ {
+ MCESRV_DEBUG_DVALUE(
+ "TimerExpiredL: state machine causes ERROR", error );
+ LocalErrorOccured( currentState, error );
+ }
+ }
+ else
+ {
+ // session has expired, terminate
+ TMceStateTransitionEvent event( *this, EMceSessionExpired );
+ TRAPD( error, iStateMachine->ProcessL( event ) );
+ if ( error != KErrNone )
+ {
+ MCESRV_DEBUG_DVALUE(
+ "TimerExpiredL: state machine causes ERROR", error );
+ LocalErrorOccured( KMceStateTerminated, error );
+ }
+ }
+
+ if ( aTimerId == iTimer )
+ {
+ iTimer = CMceTimerManager::KNoSuchTimer;
+ }
+
+ MCESRV_DEBUG("CMceSipSession::TimerExpiredL, Exit");
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::UseFC
+// -----------------------------------------------------------------------------
+//
+TBool CMceSipSession::UseFC()
+ {
+ return iUseFC;
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::FCReceivedData
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::FCReceivedData( HBufC8* aData,
+ const CFCSession* /*aFCSession*/ )
+ {
+
+ MCESRV_DEBUG("CMceSipSession::FCReceivedData, Entry");
+
+ TMceIds ids;
+ ids.iCallbackID = EMceItcFCMsgReceived;
+
+ TRAPD( error, SendToClientL( ids, aData, NULL ) );
+ if ( error != KErrNone )
+ {
+ delete aData;
+ }
+
+ MCESRV_DEBUG("CMceSipSession::FCReceivedData, Exit");
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::FCErrorNotify
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::FCErrorNotify( TInt aErrCode,
+ const CFCSession* /*aFCSession*/ )
+ {
+ TMceIds ids;
+ ids.iCallbackID = EMceItcFCErrorReceived;
+ ids.iStatus = aErrCode;
+ SendToClient( ids );
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::InviteForkedL
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::InviteForkedL( CSIPClientTransaction& aTransaction,
+ CSIPInviteDialogAssoc* aDialogAssoc )
+ {
+ __ASSERT_ALWAYS( aDialogAssoc, User::Leave( KErrArgument ) );
+ iForkedDialogs.AppendL( aDialogAssoc );
+ ResponseReceivedWithinDialog( aTransaction, *aDialogAssoc );
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::HandleForkedDialogs
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::HandleForkedDialogs()
+ {
+
+ // If one of the forked dialogs generated final response,
+ // replace the actual dialog with that
+ CSIPInviteDialogAssoc* forkedDlg = NULL;
+ CSIPDialog::TState forkedDlgState = ( CSIPDialog::TState )( KErrNotFound );
+ for ( TInt ind = 0; ind < iForkedDialogs.Count(); ind++ )
+ {
+ forkedDlg = iForkedDialogs[ ind ];
+ forkedDlgState = forkedDlg->Dialog().State();
+ if ( forkedDlgState == CSIPDialog::EConfirmed ||
+ forkedDlgState == CSIPDialog::ETerminated )
+ {
+ CSIPInviteDialogAssoc* origDlg = static_cast<CSIPInviteDialogAssoc*>( iDialog );
+ iDialog = forkedDlg;
+ iForkedDialogs.Remove( ind );
+ iForkedDialogs.Insert( origDlg,ind );
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::WaitingMediaCallback
+// -----------------------------------------------------------------------------
+//
+TBool CMceSipSession::WaitingMediaCallback() const
+ {
+ return iWaitingMediaCallback;
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::SetWaitingMediaCallback
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::SetWaitingMediaCallback( TBool aWaiting )
+ {
+ iWaitingMediaCallback = aWaiting;
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::SetMediaAuthorizationToken
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::SetMediaAuthorizationToken( HBufC8* aToken )
+ {
+ delete iMediaAuthorizationToken;
+ iMediaAuthorizationToken = aToken;
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::Extensions
+// -----------------------------------------------------------------------------
+//
+CMceSipExtensions& CMceSipSession::Extensions()
+ {
+ return *iExtensions;
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::MediaAuthorizationToken
+// -----------------------------------------------------------------------------
+//
+HBufC8* CMceSipSession::MediaAuthorizationToken() const
+ {
+ return iMediaAuthorizationToken;
+ }
+
+// -------------------------------------------------------------------------------
+// CMceSipSession::NoPrackReceived
+// -------------------------------------------------------------------------------
+//
+void CMceSipSession::NoPrackReceived( CSIPServerTransaction& aTransaction )
+ {
+ if ( Request() == aTransaction )
+ {
+ MCESRV_DEBUG("CMceSipSession::NoPrackReceived");
+ TMceStateTransitionEvent event( *this, EMceNoPrackReceived );
+
+ TRAPD( error, iStateMachine->ProcessL( event ) );
+ if ( error != KErrNone )
+ {
+ MCESRV_DEBUG_DVALUE(
+ "SessionClosed: state machine causes ERROR", error );
+ LocalErrorOccured( KMceStateError, error );
+ }
+ MCESRV_DEBUG("CMceSipSession::NoPrackReceived, Exit");
+ }
+ }
+
+// -------------------------------------------------------------------------------
+// CMceSipSession::ReliableFailed
+// -------------------------------------------------------------------------------
+//
+void CMceSipSession::ReliableFailed( CSIPServerTransaction& aTransaction,
+ TInt aError )
+ {
+ MCESRV_DEBUG("CMceSipSession::ReliableFailed, Entry");
+ MCESRV_DEBUG_DVALUE("error", aError );
+
+ if ( Request() == aTransaction )
+ {
+ TMceStateTransitionEvent event( *this, EMceReliableFailed, aError );
+
+ TRAPD( error, iStateMachine->ProcessL( event ) );
+ if ( error != KErrNone )
+ {
+ MCESRV_DEBUG_DVALUE(
+ "SessionClosed: state machine causes ERROR", error );
+ LocalErrorOccured( KMceStateError, error );
+ }
+ MCESRV_DEBUG("CMceSipSession::ReliableFailed, Exit");
+ }
+ }
+
+// -------------------------------------------------------------------------------
+// CMceSipSession::SetRSeq
+// -------------------------------------------------------------------------------
+//
+void CMceSipSession::SetRSeq( TUint aRSeq )
+ {
+ if ( aRSeq )
+ {
+ iRSeq = aRSeq;
+ }
+ }
+
+// -------------------------------------------------------------------------------
+// CMceSipSession::RSeq
+// -------------------------------------------------------------------------------
+//
+TInt CMceSipSession::RSeq()
+ {
+ return iRSeq;
+ }
+
+// -------------------------------------------------------------------------------
+// CMceSipSession::DoAutoEventL
+// -------------------------------------------------------------------------------
+//
+void CMceSipSession::DoAutoEventL( TMceStateTransitionEvent& aEvent )
+ {
+ CMceMsgBase* msg = &aEvent.ParamClientMessage();
+ TMceIds emptyIds;
+ TMceIds* ids = &aEvent.ParamIDs();
+ ids = ids != NULL ? ids : &emptyIds;
+ if ( msg )
+ {
+ DoServiceL( *ids, static_cast<TMceItcFunctions>( aEvent.Code() ), *msg );
+ }
+ else
+ {
+ DoServiceL( *ids, static_cast<TMceItcFunctions>( aEvent.Code() ) );
+ }
+ }
+
+// -------------------------------------------------------------------------------
+// CMceSipSession::AddRemoteUriL
+// -------------------------------------------------------------------------------
+//
+void CMceSipSession::AddRemoteUriL( const CUri8& aRemoteUri )
+ {
+ MCESRV_DEBUG("CMceSipSession::AddRemoveUriL, Entry");
+
+ TInt uriFound = FindRemoteUri( aRemoteUri );
+
+ User::LeaveIfError( uriFound == KErrNotFound ? KErrNone : KErrAlreadyExists );
+
+ CUri8* remoteUri = CUri8::NewLC( aRemoteUri.Uri() );
+ iRemoteUri.AppendL( remoteUri );
+ CleanupStack::Pop();
+ RDebug::Print(_L("CMceSipSession::AddRemoveUriL, iRemoteUri.Count()=%d"),iRemoteUri.Count() );
+ MCESRV_DEBUG("CMceSipSession::AddRemoveUriL, Exit");
+ }
+
+// -------------------------------------------------------------------------------
+// CMceSipSession::FindRemoteUri
+// -------------------------------------------------------------------------------
+//
+TInt CMceSipSession::FindRemoteUri( const CUri8& aRemoteUri )
+ {
+ MCESRV_DEBUG("CMceSipSession::FindRemoteUri, Entry");
+
+ TInt ret = KErrNotFound;
+
+ for( TInt i=0; ( i<iRemoteUri.Count() ) && ( ret==KErrNotFound ); i++ )
+ {
+ if( MceSip::CompareUri( aRemoteUri, *iRemoteUri[i] ) == KErrNone )
+ {
+ ret = i;
+ RDebug::Print(_L("CMceSipSession::FindRemoteUri,i=%d"), i);
+ }
+ }
+
+ MCESRV_DEBUG("CMceSipSession::FindRemoteUri, Exit");
+
+ return ret;
+ }
+
+// -------------------------------------------------------------------------------
+// CMceSipSession::AddRemoteUriFromResponseL
+// -------------------------------------------------------------------------------
+//
+void CMceSipSession::AddRemoteUriFromResponseL(
+ CSIPResponseElements& aResponseElements )
+ {
+ MCESRV_DEBUG("CMceSipSession::AddRemoteUriFromResponseL, Entry");
+
+ CSIPHeaderBase* contact = MceSip::FindHeader(
+ aResponseElements.MessageElements(),
+ SIPStrings::StringF( SipStrConsts::EContactHeader ) );
+
+ User::LeaveIfError( contact ? KErrNone : KErrNotFound );
+
+ const CUri8& uri = static_cast< CSIPContactHeader* >( contact )->
+ SIPAddress()->Uri8();
+
+ AddRemoteUriL( uri );
+
+ MCESRV_DEBUG("CMceSipSession::AddRemoteUriFromResponseL, Exit");
+ }
+
+// -------------------------------------------------------------------------------
+// CMceSipSession::ClearRemoteUri
+// -------------------------------------------------------------------------------
+//
+void CMceSipSession::ClearRemoteUri( const TMceStateIndex aState )
+ {
+ MCESRV_DEBUG("CMceSipSession::ClearRemoteUri, Entry");
+
+ if ( aState == KMceStateEstablished ||
+ aState == KMceStateTerminated ||
+ aState == KMceStateUpdated )
+ {
+ RDebug::Print(_L("CMceSipSession::ClearRemoteUri, aState=%d"), aState);
+ RDebug::Print(_L("CMceSipSession::ClearRemoteUri, iRemoteUri.Count=%d"),
+ iRemoteUri.Count());
+
+ iRemoteUri.ResetAndDestroy();
+ }
+ MCESRV_DEBUG("CMceSipSession::ClearRemoteUri, Exit");
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::ForceSDPSendingStatus
+// -----------------------------------------------------------------------------
+//
+TBool CMceSipSession::ForceSDPSendingStatus()
+ {
+ return iForceSDPSending;
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::PrevOfferSafeDelete
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::PrevOfferSafeDelete()
+ {
+ if ( iPrevOffer && iPrevOffer != iOffer )
+ {
+ MCE_DELETE( iPrevOffer );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::PreviousState
+// -----------------------------------------------------------------------------
+//
+TUint CMceSipSession::PreviousState()
+ {
+ return iPreviousState;
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::ServerInitializedL
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::ServerInitializedL()
+ {
+ TMceStateTransitionEvent event( *this, EMceServerInitialized );
+ TRAPD( error, iStateMachine->ProcessL( event ) );
+ if ( error != KErrNone )
+ {
+ MCESRV_DEBUG_DVALUE( "ServerInitializedL: state machine causes ERROR",
+ error );
+ LocalErrorOccured( KMceStateError, error );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::ContinueHandlingIncomingSessionL
+// -----------------------------------------------------------------------------
+//
+void CMceSipSession::ContinueHandlingIncomingSessionL()
+ {
+ FCActions().PeekFCDocumentL( *Offer() );
+ Actions().ClientUpdateIncomingSessionL( Request() );
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::IsSipDialogConfirmed
+// -----------------------------------------------------------------------------
+//
+TBool CMceSipSession::IsSipDialogConfirmed() const
+ {
+ TBool confirmed( EFalse );
+ if ( Dialog() )
+ {
+ confirmed = ( Dialog()->Dialog().State() == CSIPDialog::EConfirmed );
+ }
+ return confirmed;
+ }
+
+// -----------------------------------------------------------------------------
+// CMceSipSession::IsNatSession
+// -----------------------------------------------------------------------------
+//
+TBool CMceSipSession::IsNatSession()
+ {
+ return iNatSession;
+ }
+
+TInt CMceSipSession::ForkedDialogsCount()
+ {
+ return iForkedDialogs.Count();
+ }
+// End of File