diff -r 000000000000 -r 1bce908db942 multimediacommsengine/mmcesrv/mmceserver/src/mcestateoffering.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/multimediacommsengine/mmcesrv/mmceserver/src/mcestateoffering.cpp Tue Feb 02 01:04:58 2010 +0200 @@ -0,0 +1,956 @@ +/* +* 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 "mcestateoffering.h" +#include "mcesipsession.h" +#include "mcesipextensions.h" +#include "mceactionset.h" +#include "mcefcactionset.h" +#include "mceclientserver.h" +#include "mcesip.h" +#include "mcesipsession.h" +#include "mcenatmacros.h" +#include "mcesdpsession.h" +#include "mcesrvlogs.h" + +// ----------------------------------------------------------------------------- +// CMceStateOffering::CMceStateOffering +// ----------------------------------------------------------------------------- +// +CMceStateOffering::CMceStateOffering () + : CMceState( KMceStateOffering ) + { + } + + +// ----------------------------------------------------------------------------- +// CMceStateOffering::~CMceStateOffering +// ----------------------------------------------------------------------------- +// +CMceStateOffering::~CMceStateOffering() + { + } + + +// ----------------------------------------------------------------------------- +// CMceStateOffering::DoAcceptL +// ----------------------------------------------------------------------------- +// +TBool CMceStateOffering::DoAcceptL( TMceStateTransitionEvent& aEvent ) + { + + User::LeaveIfError( + aEvent.Code() == EMceUpdate || + aEvent.Code() == EMceResponse || + aEvent.Code() == EMceProvisionalResponse || + aEvent.Code() == EMceRedirectionResponse || + aEvent.Code() == EMceErrorResponse || + aEvent.Code() == EMceMediaUpdated || + aEvent.Code() == EMceItcCancel || + aEvent.Code() == EMceBye || + aEvent.Code() == EMceItcEnable || + aEvent.Code() == EMceItcDisable || + IsExtensionRequestEvent( aEvent ) + + ? KErrNone : KErrTotalLossOfPrecision ); + + return ETrue; + + } + +// ----------------------------------------------------------------------------- +// CMceStateOffering::EntryL +// ----------------------------------------------------------------------------- +// +void CMceStateOffering::EntryL( TMceStateTransitionEvent& aEvent ) + { + + if ( IsExtensionRequestEvent( aEvent )) + { + HandleExtensionRequestEventL( aEvent ); + } + + else + { + switch( aEvent.Code() ) + { + case EMceUpdate: + { + EntryUpdateL( aEvent ); + break; + } + case EMceProvisionalResponse: + { + EntryProvisionalResponseL( aEvent ); + break; + } + //200 OK + case EMceResponse: + { + EntryResponseL( aEvent ); + break; + } + //error + case EMceRedirectionResponse: + { + EntryRedirectionResponseL( aEvent ); + break; + } + case EMceErrorResponse: + { + EntryErrorResponseL( aEvent ); + break; + } + //if client cancels, send CANCEL + case EMceItcCancel: + { + EntryCancelL( aEvent ); + break; + } + case EMceMediaUpdated: + { + CMceSipSession& session = aEvent.Session(); + CSIPServerTransaction* update = &session.Request(); + + if ( update && update->Type() == + SIPStrings::StringF( SipStrConsts::EUpdate ) ) + { + EntryMediaUpdatedL( aEvent ); + } + else + { + if ( aEvent.Session().SubState() == CMceSipSession::EUpdating ) + { + EntryAnswerToUpdateDecodedL( aEvent ); + } + else + { + EntryAnswerToOfferDecodedL( aEvent ); + } + } + break; + } + + case EMceItcEnable: + case EMceItcDisable: + { + aEvent.Session().Actions().ControlMediaL( aEvent.ParamIDs(), + (TMceItcFunctions)aEvent.Code() ); + break; + } + case EMceBye: + { + EntryByeL( aEvent ); + break; + } + default: + { + //NOP + break; + } + } + } + } + +// ----------------------------------------------------------------------------- +// CMceStateOffering::EntryUpdateL +// ----------------------------------------------------------------------------- +// +void CMceStateOffering::EntryUpdateL( TMceStateTransitionEvent& aEvent ) + { + CMceSipSession& session = aEvent.Session(); + if ( MceSip::HasContent( session.Request() ) ) + { + // UPDATE carries SDP + User::LeaveIfError( session.Actions().CreateSDP( session.Request() ) ); + + session.Actions().DecodeL(); + TMceReturnStatus status = session.Actions().UpdateL(); + aEvent.ParamStatus() = status; + if ( MCE_IS_ERROR( status ) ) + { + // TBD: update failed, reject + } + else if ( status == KMceAsync ) + { + // NOP + } + else // ready + { + aEvent.Code() = EMceMediaUpdated; + EntryMediaUpdatedL( aEvent ); + } + } + else + { + // TBD: handle UPDATE without content + } + + } + +// ----------------------------------------------------------------------------- +// CMceStateOffering::EntryProvisionalResponseL +// ----------------------------------------------------------------------------- +// +void CMceStateOffering::EntryMediaUpdatedL( TMceStateTransitionEvent& aEvent ) + { + CMceSipSession& session = aEvent.Session(); + + TMceReturnStatus status = session.Actions().ReserveL(); + aEvent.ParamStatus() = status; + if ( MCE_IS_ERROR( status )) + { + // TBD: reservation failed + } + else + if (status == KMceAsync) + { + // NOP + } + else // ready, send 2xx to update + { + CSIPServerTransaction* update= NULL; + RStringF trx = session.Request().Type(); + if (trx == SIPStrings::StringF(SipStrConsts::EUpdate) ) + { + update = &session.Request(); + } + + if (update) + { + session.Actions().EncodeL(); + session.FCActions().UpdateFCAnswerL( *session.Offer() ); + session.Actions().SendAnswerL( *update); + } + else + { + User::Leave(KErrTotalLossOfPrecision); + } + } + } + +// ----------------------------------------------------------------------------- +// CMceStateOffering::EntryProvisionalResponseL +// ----------------------------------------------------------------------------- +// +void CMceStateOffering::EntryProvisionalResponseL( + TMceStateTransitionEvent& aEvent ) + { + TInt status = KErrNone; + CMceSipSession& session = aEvent.Session(); + CSIPClientTransaction& response = session.Response(); + + session.Extensions().UpdateL( response ); + session.Actions().CheckContactIsSecureL( response ); + + session.ActiveBody().AnswerType() = KMceNegotiationAnswerTypeIntermediate; + + TBool IsFork = EFalse; + if ( MceSip::ResponseCode( session.Response() ) == KMceSipSessionProgress && + session.ForkedDialogsCount() ) + { + IsFork = ETrue; + } + if ( session.Actions().NeedToProcessL( aEvent ) || IsFork ) + { + if ( MCE_NEED_TO_SEND( session, NULL ) || IsFork ) + { + if ( MceSip::HasContent( response ) ) + { + // create SDP answer + //status = session.Actions().CreateSDP( response ); + NAT_WAIT_NO_EXEC( session, (status = session.Actions().CreateSDP( response ))); + + // handle SDP content + if ( !MCE_IS_ERROR( status ) ) + { + // process session timer + session.Actions().ProcessSessionTimerClientL( response ); + // update FC + session.FCActions().PeekFCDocumentL( *session.Offer() ); + + //decode answer, ignore warning code + if ( session.ActiveBody().SecureSession()) + { + session.ActiveBody().SecureSession()->iLSReadyToBind = EFalse; + } + session.Actions().DecodeL(); + + + // update media + status = session.Actions().UpdateL(); + } + } + + //if there was an error + if ( MCE_IS_ERROR( status ) ) + { + EntryCancelL( aEvent ); + //transition exit is performed here + session.Actions().StateChanged( KMceStateCanceled ); + session.Actions().ClientStateChangedL( CMceSession::ECancelling, + aEvent.ParamStatus() ); + } + else if ( status == KMceAsync ) + { + aEvent.Session().SetWaitingMediaCallback( ETrue ); + } + else // KMceReady + { + EntryAnswerToOfferDecodedL( aEvent ); + } + } + else + { + EntryAnswerToOfferDecodedL( aEvent ); + } + } + aEvent.ParamStatus() = status; + } + +// ----------------------------------------------------------------------------- +// CMceStateOffering::EntryRedirectionResponseL +// ----------------------------------------------------------------------------- +// +void CMceStateOffering::EntryRedirectionResponseL( + TMceStateTransitionEvent& aEvent ) + { + MCESRV_DEBUG("CMceStateOffering::EntryRedirectionResponseL, Entry"); + + CMceSipSession& session = aEvent.Session(); + + session.ResetSdpCounts(); + + switch ( MceSip::ResponseCode( session.Response() ) ) + { + case KMceSipMovedTemporarily: + { + // any 3xx response for updating will be handled as + // a error situation + if ( session.SubState() != CMceSipSession::EUpdating ) + { + // get remoteUri information from response + session.AddRemoteUriFromResponseL( + *const_cast(session.Response().ResponseElements()) ); + // create a new inviteAssociationDialog + session.CreateDialogFrom3XXResponseL(); + // send the invite again + session.Actions().SendInviteL(); + } + break; + } + // include KMceSipUseProxy, KMceSipAlternativeService, + // KMceSipMultipleChoices, KMceSipMovedPermanently + default: + { + // error situation + break; + } + } + + MCESRV_DEBUG("CMceStateOffering::EntryRedirectionResponseL, Exit"); + } + +// ----------------------------------------------------------------------------- +// CMceStateOffering::ExitRedirectionEventL +// ----------------------------------------------------------------------------- +// +void CMceStateOffering::ExitRedirectionEventL( + TMceStateTransitionEvent& aEvent ) + { + MCESRV_DEBUG("CMceStateOffering::RedirectionErrorResponseL, Entry"); + + CMceSipSession& session = aEvent.Session(); + CMceSipSession::TSubState subState = session.SubState(); + TUint responseCode = MceSip::ResponseCode( session.Response() ); + + if ( subState == CMceSipSession::EOffering ) + { + if ( responseCode == KMceSipMovedTemporarily ) + { + session.Actions().ClientStateChangedL( + CMceSession::EOffering, *session.Body(), session.Response() ); + } + else + { + session.Actions().StopMedia(); + session.FCActions().ReleaseFC(); + session.Actions().StateChanged( KMceStateTerminated ); + session.Actions().ClientStateChangedL( + CMceSession::ETerminated, *session.Body(), session.Response() ); + } + } + else if ( session.SubState() == CMceSipSession::EUpdating ) + { + session.Actions().StopUpdatingMedia(); + session.Actions().UpdateFailed(); + session.Actions().StateChanged( CMceSession::EEstablished ); + session.Actions().ClientStateChangedL( + CMceSession::EEstablished, *session.Body(), + session.Response(), KErrGeneral ); + } + else + { + // do nothing + } + + MCESRV_DEBUG("CMceStateOffering::RedirectionErrorResponseL, Exit"); + } + +// ----------------------------------------------------------------------------- +// CMceStateOffering::EntryResponseL +// ----------------------------------------------------------------------------- +// +void CMceStateOffering::EntryResponseL( TMceStateTransitionEvent& aEvent ) + { + TInt status = KErrNone; + CMceSipSession& session = aEvent.Session(); + CMceSipSession::TSubState subState = session.SubState(); + + //send ACK + session.Actions().SendACKL( session.Response() ); + session.Actions().CheckContactIsSecureL( session.Response() ); + session.ActiveBody().AnswerType() = KMceNegotiationAnswerTypeFinal; + + // Handle the answer only if the media processing is not + // already ongoing + if ( !session.WaitingMediaCallback() ) + { + if ( MceSip::HasContent( session.Response() ) ) + { + //process session timer + session.Actions().ProcessSessionTimerClientL( session.Response() ); + + if ( subState != CMceSipSession::ERefreshing ) + { + //create SDP answer + NAT_WAIT_NO_EXEC( session, (status = session.Actions().CreateSDP( session.Response() ) )); + + if ( !MCE_IS_ERROR( status ) ) + { + //update FC + session.FCActions().PeekFCDocumentL( *session.Offer() ); + + //decode answer, ignore warning code + if ( session.ActiveBody().SecureSession()) + { + session.ActiveBody().SecureSession()->iLSReadyToBind = ETrue; + } + status = session.Actions().Decode(); + + // update media and start waiting EMceMediaUpdated (if needed) + if ( !MCE_IS_ERROR( status ) ) + { + status = session.Actions().UpdateL(); + //if everything OK, starts floor control + if ( !MCE_IS_ERROR( status ) ) + { + //check should wait EMceMediaUpdated + aEvent.Code() = status == KMceReady ? + EMceMediaUpdated : EMceResponse; + if ( subState == CMceSipSession::EOffering ) + { + // start floor control only for the initial INVITE + session.FCActions().StartFCL(); + } + } + } + } + } + } + else // no content + { + if ( !MCE_NEED_TO_RECEIVE( session ) ) + { + status = session.Actions().UpdateL(); + // SDP answer was received before + // go to established state + session.Actions().StateChanged( KMceStateEstablished ); + //session.Actions().ClientStateChangedL( CMceSession::EEstablished, + // session.Response() ); + session.Actions().ClientStateChangedL( CMceSession::EEstablished, + *session.Body(), + session.Response(), + status ); + } + else + { + // SDP answer is not received + User::Leave( KErrNotReady ); + } + } + + aEvent.ParamStatus() = status; + + //if there was an error + if ( MCE_IS_ERROR( status ) ) + { + //if first invite + if ( subState == CMceSipSession::EOffering ) + { + //send BYE and stop media + session.Actions().SendBYEL(); + session.Actions().StopMedia(); + } + //if updating + else if ( subState == CMceSipSession::EUpdating ) + { + //do rollback + session.Actions().UpdateFailed(); + if ( session.Body() && &session.Body()->SdpSession() && + session.Body()->SdpSession().iOOldSchoolCompleted ) + { + session.Actions().ClientStateChangedL( + CMceSession::EEstablished, *( session.Body() ), status ); + } + } + else + { + //NOP + } + } + else if ( status == KMceAsync ) + { + // set session waiting for media callback + aEvent.Session().SetWaitingMediaCallback( ETrue ); + } + else if ( status == KMceReady && subState == CMceSipSession::EUpdating ) + { + session.Actions().UpdateSucceed(); + } + else + { + // NOP + } + } + } + + +// ----------------------------------------------------------------------------- +// CMceStateOffering::EntryErrorResponseL +// ----------------------------------------------------------------------------- +// +void CMceStateOffering::EntryErrorResponseL( TMceStateTransitionEvent& aEvent ) + { + CMceSipSession& session = aEvent.Session(); + + session.ResetSdpCounts(); + + CMceSipSession::TSubState subState = session.SubState(); + + TUint code = MceSip::ResponseCode( session.Response() ); + TInt errorCode = KErrNone; + + if ( code == KMceSipSessionIntervalTooSmall ) + { + if ( session.Dialog()->Dialog().State() == CSIPDialog::EConfirmed ) + { + //sending re-INVITE after 422 for re-INVITE + session.Actions().ProcessSessionTimerClientL( session.Response() ); + //send again + session.Actions().SendSessionRefreshL(); + } + + else if ( session.Dialog()->Dialog().State() == CSIPDialog::ETerminated ) + { + //sending re-INVITE after 422 for INVITE + errorCode = session.ReUseDialog(); + if ( errorCode == KErrNone ) + { + session.Actions().ProcessSessionTimerClientL( session.Response() ); + session.Actions().SendInviteL(); + } + } + } + else if ( code == KMceSipExtensionRequired ) + { + session.Extensions().UpdateL( session.Response() ); + session.ReCreateOutgoingDialogL(); + session.Actions().SendInviteL(); + } + //if first invite, stop media and FC + else if ( subState == CMceSipSession::EOffering ) + { + session.Actions().StopMedia(); + session.FCActions().ReleaseFC(); + } + //if update, reject update + else if ( subState == CMceSipSession::EUpdating || + subState == CMceSipSession::ERefreshing ) + { + if ( code == KMceSipCallOrTransactionDoesNotExist || + code == KMceSipRequestTimeout ) + { + session.Actions().UpdateFailed(); + session.Actions().SendBYEL(); + session.Actions().StopMedia(); + session.FCActions().ReleaseFC(); + session.Actions().StateChanged( KMceStateTerminated ); + session.Actions().ClientStateChangedL( CMceSession::ETerminated, + session.Response() ); + } + else + { + session.Actions().UpdateFailed(); + session.Actions().StateChanged( KMceStateEstablished ); + session.Actions().ClientStateChangedL( CMceSession::EEstablished, + *session.Body(), + session.Response(), + KErrCancel ); + } + } + else + { + //NOP + } + } + +// ----------------------------------------------------------------------------- +// CMceStateOffering::EntryCancelL +// ----------------------------------------------------------------------------- +// +void CMceStateOffering::EntryCancelL( TMceStateTransitionEvent& aEvent ) + { + CMceSipSession& session = aEvent.Session(); + CMceSipSession::TSubState subState = session.SubState(); + + //(try) send CANCEL + session.Actions().SendCancelL(); + + if ( subState == CMceSipSession::EOffering ) + { + session.Actions().StopMedia(); + session.FCActions().ReleaseFC(); + } + else if ( subState == CMceSipSession::EUpdating ) + { + session.Actions().UpdateFailed(); + } + + } + +// ----------------------------------------------------------------------------- +// CMceStateOffering::EntryAnswerToUpdateDecodedL +// ----------------------------------------------------------------------------- +// +void CMceStateOffering::EntryAnswerToUpdateDecodedL( TMceStateTransitionEvent& aEvent ) + { + CMceSipSession& session = aEvent.Session(); + + //if media error, media unusable -> send BYE, stop media and FC + if ( aEvent.ParamStatus() == KErrNone ) + { + session.Actions().UpdateSucceed(); + } + else + { + session.Actions().UpdateFailed(); + } + + } + +// ----------------------------------------------------------------------------- +// CMceStateOffering::EntryAnswerToOfferDecodedL +// ----------------------------------------------------------------------------- +// +void CMceStateOffering::EntryAnswerToOfferDecodedL( TMceStateTransitionEvent& aEvent ) + { + CMceSipSession& session = aEvent.Session(); + CSIPClientTransaction* response = &session.Response(); + + TInt status = KErrNone; + + if ( MceSip::ResponseType( *response ) == E1XX && + session.Extensions().LevelL( *response, CMceSipExtensions::E100rel ) + == CMceSipExtensions::ERequired ) + + { + TBool hasContent = MceSip::HasContent( *response ); + + // TBD: Quick Fix: Need to have Support in MediaManager to ask do we need + // to send SDP or not, decision must be based on conf line, and 2ndly + // based on weither negotiation has completed or not. + TBool sendSdp = hasContent && + ( MCE_NEED_TO_SEND( session, NULL ) || + session.Extensions().RemoteIMSRel5() || + session.ActiveBody().Modifier( KMceSecPreconditions ) == + KMcePreconditionsE2ESupported ); + //if there is required header for precodition but no precondition + //Prack should indicate precondition failure + if ( MceSip::ResponseType( *response ) == E1XX && + session.Extensions().LevelL( *response, CMceSipExtensions::ESecPreconds ) + == CMceSipExtensions::ERequired ) + { + session.ActiveBody().iRemoteSecPreconditionsRequired = ETrue; + } + if ( sendSdp ) + { + status = session.Actions().UpdateL(); + __ASSERT_ALWAYS( status == KMceReady, User::Leave( KErrArgument ) ); + //need not to change secure keys + if ( session.ActiveBody().SecureSession() && + MceSip:: ResponseCode( *response ) == KMceSipSessionProgress) + { + session.ActiveBody().SecureSession()->iKeyNeedUpdated = EFalse; + } + NAT_WAIT_NO_EXEC( session, session.Actions().EncodeL() ) + //session, session.Actions().EncodeL(); + } + + + session.Actions().SendPrackL( sendSdp ); + + aEvent.Code() = EMceProvisionalResponse; + } + + } + + +// ----------------------------------------------------------------------------- +// CMceStateOffering::EntryByeL +// ----------------------------------------------------------------------------- +// +void CMceStateOffering::EntryByeL( TMceStateTransitionEvent& aEvent ) + { + CMceSipSession& session = aEvent.Session(); + + //send 200OK and stop media and FC + session.Actions().Send200OKL( session.Request() ); + session.Actions().StopMedia(); + session.FCActions().ReleaseFC(); + + } + +// ----------------------------------------------------------------------------- +// CMceStateOffering::ExitL +// ----------------------------------------------------------------------------- +// +void CMceStateOffering::ExitL( TMceStateTransitionEvent& aEvent ) + { + + if ( IsExtensionRequestEvent( aEvent )) + { + //Do Nothing; + } + + + else + { + CMceSipSession& session = aEvent.Session(); + CSIPClientTransaction* response = &session.Response(); + TInt status = aEvent.ParamStatus(); + + switch( aEvent.Code() ) + { + //received BYE causes server & client to terminated state + case EMceBye: + { + session.Actions().StateChanged( KMceStateTerminated ); + session.Actions().ClientStateChangedL( + CMceSession::ETerminated, session.Request() ); + break; + } + case EMceMediaUpdated: + { + if ( MceSip::ResponseType( *response ) == E2XX && + response->ResponseElements()->CSeqHeader()->Method() == + SIPStrings::StringF( SipStrConsts::EInvite ) ) + { + //server and client state established, + //if update was successful Body() returns previous BodyCandidate(), + //if update was failed Body() returns original body + session.Actions().ClientStateChangedL( CMceSession::EEstablished, + *session.Body(), + session.Response(), + status ); + session.Actions().StateChanged( KMceStateEstablished ); + } + break; + } + case EMceResponse: + case EMceErrorResponse: + case EMceProvisionalResponse: + case EMceRedirectionResponse: + { + ExitSIPEventL( aEvent ); + break; + } + + case EMceItcCancel: + { + session.Actions().StateChanged( KMceStateCanceled ); + session.Actions().ClientStateChanged( aEvent.ParamIDs(), + CMceSession::ECancelling ); + break; + } + + default: + { + //NOP + } + + } + } + + } + + +// ----------------------------------------------------------------------------- +// CMceStateOffering::ExitSIPEventL +// ----------------------------------------------------------------------------- +// +void CMceStateOffering::ExitSIPEventL( TMceStateTransitionEvent& aEvent ) + { + + CMceSipSession& session = aEvent.Session(); + TInt status = aEvent.ParamStatus(); + CMceSipSession::TSubState subState = session.SubState(); + + if ( aEvent.Code() == EMceResponse ) + { + //error in response handling + if ( status < KErrNone && subState == CMceSipSession::EOffering )//failed + { + //no need to update body to client + session.Actions().StateChanged( KMceStateTerminating ); + session.Actions().ClientStateChangedL( CMceSession::ETerminating, + session.Response(), + status ); + } + else if ( status < KErrNone && subState == CMceSipSession::EUpdating )//failed + { + //original body is updated to client + session.Actions().ClientStateChangedL( CMceSession::EEstablished, + *session.Body(), + session.Response(), + status ); + session.Actions().StateChanged( KMceStateEstablished ); + } + else if ( subState == CMceSipSession::ERefreshing ) + { + session.Actions().StateChanged( KMceStateEstablished ); + session.Actions().ClientStateChangedL( CMceSession::EEstablished, + session.Response() ); + } + else + { + // SDP Answer was received previously, ignore the contents if any + // Get into established state. + if ( !session.WaitingMediaCallback() && + !MCE_NEED_TO_RECEIVE( session ) ) + { + session.Actions().StateChanged( KMceStateEstablished ); + session.Actions().ClientStateChangedL( CMceSession::EEstablished, + session.Response() ); + } + else + { + //wait EMceAnswerDecoded or EMceAnswerToUpdateDecoded + } + } + } + else if ( aEvent.Code() == EMceErrorResponse ) + { + if ( subState == CMceSipSession::EOffering ) + { + TUint code = MceSip::ResponseCode( session.Response() ); + if ( code != KMceSipExtensionRequired && code != KMceSipSessionIntervalTooSmall ) + { + session.Actions().StateChanged( KMceStateTerminated ); + session.Actions().ClientStateChangedL( CMceSession::ETerminated, + session.Response() ); + } + } + else if ( subState == CMceSipSession::EUpdating ) + { + if ( MceSip::ResponseCode( + session.Response() ) == KMceSipCallOrTransactionDoesNotExist || + MceSip::ResponseCode( + session.Response() ) == KMceSipRequestTimeout ) + { + session.Actions().StateChanged( KMceStateTerminating ); + session.Actions().ClientStateChangedL( CMceSession::ETerminating, + session.Response() ); + } + else + { + session.Actions().ClientStateChangedL( CMceSession::EEstablished, + *session.Body(), + session.Response(), + KErrCancel ); + session.Actions().StateChanged( KMceStateEstablished ); + } + } + else + {//MediaUpdated + if ( session.PendingTransaction( SIPStrings::StringF( SipStrConsts::EPrack ) ) ) + { + session.Actions().StateChanged( KMceStateConfirming ); + } + else + { + session.Actions().ClientStateChangedL( CMceSession::EEstablished, + session.Response() ); + session.Actions().StateChanged( KMceStateEstablished ); + } + } + } + else if ( aEvent.Code() == EMceRedirectionResponse ) + { + ExitRedirectionEventL( aEvent ); + } + + + else//EMceProvisionalResponse + { + if ( MceSip::ResponseCode( session.Response() ) > KMceSipTrying && + session.Actions().NeedToProcessL( aEvent ) ) + { + // update RSeq of a handled response to the session if it contains + TInt rseqValueOfLatestResponse = KErrNotFound; + + rseqValueOfLatestResponse = MceSip::RSeq( *session.Response().ResponseElements() ); + + if ( rseqValueOfLatestResponse != KErrNotFound ) + { + session.SetRSeq( rseqValueOfLatestResponse ); + } + + session.Actions().ClientStateChangedL( CMceSession::EOffering, + *session.Body(), session.Response() ); + } + + if ( session.PendingTransaction( SIPStrings::StringF( SipStrConsts::EPrack ) ) ) + { + session.Actions().StateChanged( KMceStateConfirming ); + } + } + + } + + + +// End of File +