diff -r 000000000000 -r 1bce908db942 multimediacommsengine/mmcesrv/mmceserver/src/mcesipsession.cpp --- /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 +#include +#include +#include +#include +#include +#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( 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( 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( aEvent.Code() ), *msg ); + } + else + { + DoServiceL( *ids, static_cast( 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( 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