diff -r 000000000000 -r 1bce908db942 multimediacommsengine/mmcesrv/mmceserver/src/mcestateconfirming.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/multimediacommsengine/mmcesrv/mmceserver/src/mcestateconfirming.cpp Tue Feb 02 01:04:58 2010 +0200 @@ -0,0 +1,461 @@ +/* +* 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 "mcestateconfirming.h" +#include "mcesipsession.h" +#include "mceactionset.h" +#include "mcefcactionset.h" +#include "mceclientserver.h" +#include "mcesipextensions.h" +#include "mcenatmacros.h" +#include +#include + + +// ----------------------------------------------------------------------------- +// CMceStateConfirming::CMceStateConfirming +// ----------------------------------------------------------------------------- +// +CMceStateConfirming::CMceStateConfirming() + : CMceState( KMceStateConfirming ) + { + } + + +// ----------------------------------------------------------------------------- +// CMceStateConfirming::~CMceStateConfirming +// ----------------------------------------------------------------------------- +// +CMceStateConfirming::~CMceStateConfirming() + { + } + + +// ----------------------------------------------------------------------------- +// CMceStateConfirming::DoAcceptL +// ----------------------------------------------------------------------------- +// +TBool CMceStateConfirming::DoAcceptL( TMceStateTransitionEvent& aEvent ) + { + User::LeaveIfError( + aEvent.Code() == EMceResponse || + aEvent.Code() == EMceProvisionalResponse || + aEvent.Code() == EMceRedirectionResponse || + aEvent.Code() == EMceErrorResponse || + aEvent.Code() == EMceItcCancel || + aEvent.Code() == EMceMediaUpdated || + aEvent.Code() == EMceItcEnable || + aEvent.Code() == EMceItcDisable || + IsExtensionRequestEvent( aEvent ) + + ? KErrNone : KErrTotalLossOfPrecision ); + + return ETrue; + } + +// ----------------------------------------------------------------------------- +// CMceStateConfirming::EntryL +// ----------------------------------------------------------------------------- +// +void CMceStateConfirming::EntryL( TMceStateTransitionEvent& aEvent ) + { + + if ( IsExtensionRequestEvent( aEvent )) + { + HandleExtensionRequestEventL( aEvent ); + } + else + { + CMceSipSession& session = aEvent.Session(); + switch ( aEvent.Code() ) + { + case EMceResponse: + { + EntryResponseL( aEvent ); + break; + } + case EMceProvisionalResponse: + { + EntryProvisionalResponseL( aEvent ); + break; + } + case EMceRedirectionResponse: + case EMceErrorResponse: + { + EntryErrorResponseL( aEvent ); + break; + } + case EMceItcCancel: + { + EntryCancelL( aEvent ); + break; + } + case EMceMediaUpdated: + { + EntryMediaUpdatedL( aEvent ); + break; + } + case EMceItcEnable: + case EMceItcDisable: + { + session.Actions().ControlMediaL( aEvent.ParamIDs(), + (TMceItcFunctions)aEvent.Code() ); + break; + } + default: + { + // NOP + break; + } + } + } + } + +// ----------------------------------------------------------------------------- +// CMceStateConfirming::ExitL +// ----------------------------------------------------------------------------- +// +void CMceStateConfirming::ExitL( TMceStateTransitionEvent& aEvent ) + { + + if ( IsExtensionRequestEvent( aEvent )) + { + //Do Nothing; + } + + else + { + CMceSipSession& session = aEvent.Session(); + switch ( aEvent.Code() ) + { + case EMceMediaUpdated: + { + ExitMediaUpdatedL( aEvent ); + break; + } + case EMceItcCancel: + { + session.Actions().StateChanged( KMceStateCanceled ); + session.Actions().ClientStateChanged( aEvent.ParamIDs(), + CMceSession::ECancelling ); + break; + } + case EMceErrorResponse: + case EMceRedirectionResponse: + { + // session canceled + session.Actions().StateChanged( KMceStateCanceled ); + session.Actions().ClientStateChangedL( CMceSession::ECancelling, + session.Response() ); + + break; + } + default: + { + break; + } + } + } + } + +// ----------------------------------------------------------------------------- +// CMceStateConfirming::EntryResponseL +// ----------------------------------------------------------------------------- +// +void CMceStateConfirming::EntryResponseL( TMceStateTransitionEvent& aEvent ) + { + CMceSipSession& session = aEvent.Session(); + RStringF trx = session.Response().Type(); + + TMceReturnStatus status = KMceReady; + CSIPClientTransaction& response = session.Response(); + TBool hasContent = MceSip::HasContent( response ); + + if ( trx == SIPStrings::StringF( SipStrConsts::EInvite ) ) + { + // 2xx to INVITE already, send ACK + session.Actions().SendACKL( response ); + + if ( hasContent ) + { + // since the answer is already received, + // seize resending UPDATE/PRACK + TBool interrupted = session.Actions().InterruptConfirming(); + User::LeaveIfError( interrupted ? + KErrNone : KErrTotalLossOfPrecision ); + + // there is SDP, treat it as answer + User::LeaveIfError( session.Actions().CreateSDP( response ) ); + session.Actions().DecodeL(); + status = session.Actions().UpdateL(); + if ( status == KMceReady ) + { + if ( MCE_NEED_TO_SEND( session, NULL ) ) + { + // send re-INVITE + session.Actions().EncodeL(); + session.Actions().SendInviteL(); + } + aEvent.Code() = EMceMediaUpdated; + } + else if ( MCE_IS_ERROR( status ) ) + { + User::Leave( status ); + } + else // KMceAsync + { + // NOP + } + } + else + { + // TODO: IF ( answerNeeded ) + // THEN wait until the PRACK/UPDATE generates a response. + // ELSE consider session established + } + } + else if ( trx == SIPStrings::StringF( SipStrConsts::EUpdate ) || + trx == SIPStrings::StringF( SipStrConsts::EPrack ) ) + { + // 2xx to PRACK/UPDATE + + if ( hasContent ) + { + NAT_WAIT_NO_EXEC( session, (status = session.Actions().CreateSDP( response ))); + if ( !MCE_IS_ERROR( status ) && MCE_NEED_TO_SEND( session, NULL ) ) + { + if ( session.ActiveBody().SecureSession() ) + { + session.ActiveBody().SecureSession()->iLSReadyToBind = ETrue; + } + status = session.Actions().DecodeL(); + if ( status == KMceSipPreconditionFailure ) + { + User::Leave( status ); + } + else + { + status = session.Actions().UpdateL(); + } + } + } + + if ( status == KMceReady ) + { + if ( ( MCE_NEED_TO_SEND( session, NULL ) || + ( trx == SIPStrings::StringF( SipStrConsts::EPrack ) && + session.Extensions().RemoteIMSRel5() ) )&& + session.ActiveBody().Modifier( KMceSecPreconditions )!= + KMcePreconditionsE2ESupported ) + + { + + if (!hasContent) + { + // Do nothing. + } + else + { + status = session.Actions().UpdateL(); + __ASSERT_ALWAYS( status == KMceReady, User::Leave( KErrArgument ) ); + if ( session.ActiveBody().SecureSession() ) + { + session.ActiveBody().SecureSession()->iLSReadyToBind = ETrue; + } + NAT_WAIT_NO_EXEC( session, session.Actions().EncodeL() ); + session.Actions().SendUpdateRequestL(); + } + } + aEvent.Code() = EMceMediaUpdated; + } + else if ( MCE_IS_ERROR( status ) ) + { + User::Leave( status ); + } + else // KMceAsync + { + // NOP + } + aEvent.ParamStatus() = status; + } + else + { + User::Leave( KErrTotalLossOfPrecision ); + } + } + +// ----------------------------------------------------------------------------- +// CMceStateConfirming::EntryProvisionalResponseL +// ----------------------------------------------------------------------------- +// +void CMceStateConfirming::EntryProvisionalResponseL( + TMceStateTransitionEvent& /*aEvent*/ ) + { + // IF retransmission THEN ignore + // ELSE IF sent reliably THEN send PRACK + // + // IF 180 ringing THEN give to application + // TBD: What if 180 Ringing comes here? + } + +// ----------------------------------------------------------------------------- +// CMceStateConfirming::EntryErrorResponseL +// ----------------------------------------------------------------------------- +// +void CMceStateConfirming::EntryErrorResponseL( + TMceStateTransitionEvent& aEvent ) + { + CMceSipSession& session = aEvent.Session(); + RStringF trx = session.Response().Type(); + TUint code = MceSip::ResponseCode( session.Response() ); + + if ( trx == SIPStrings::StringF( SipStrConsts::EInvite ) ) + { + if ( session.SubState() == CMceSipSession::EOffering ) + { + session.Actions().StateChanged( KMceStateTerminated ); + session.Actions().ClientStateChangedL( CMceSession::ETerminated, + session.Response() ); + + } + + else if ( session.SubState() == CMceSipSession::EUpdating || + session.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 if ( trx == SIPStrings::StringF( SipStrConsts::EUpdate ) || + trx == SIPStrings::StringF( SipStrConsts::EPrack ) ) + { + EntryCancelL( aEvent ); + } + else + { + User::Leave( KErrTotalLossOfPrecision ); + } + } + +// ----------------------------------------------------------------------------- +// CMceStateConfirming::EntryCancelL +// ----------------------------------------------------------------------------- +// +void CMceStateConfirming::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(); + } + } + +// ----------------------------------------------------------------------------- +// CMceStateConfirming::EntryMediaUpdatedL +// ----------------------------------------------------------------------------- +// +void CMceStateConfirming::EntryMediaUpdatedL( TMceStateTransitionEvent& aEvent ) + { + CMceSipSession& session = aEvent.Session(); + + if ( MCE_NEED_TO_SEND( session, NULL ) ) + { + NAT_WAIT_NO_EXEC( session, session.Actions().EncodeL() ); + + if ( session.Dialog()->Dialog().State() == CSIPDialog::EEarly ) + { + session.Actions().SendUpdateRequestL(); + } + else + { + session.Actions().SendInviteL(); + } + } + } + +// ----------------------------------------------------------------------------- +// CMceStateConfirming::ExitMediaUpdatedL +// ----------------------------------------------------------------------------- +// +void CMceStateConfirming::ExitMediaUpdatedL( TMceStateTransitionEvent& aEvent ) + { + CMceSipSession& session = aEvent.Session(); + CSIPClientTransaction* update = session.PendingTransaction( + SIPStrings::StringF( SipStrConsts::EUpdate ) ); + if ( update && !MceSip::TrxCompleted( *update ) ) + { + // just sent UPDATE + session.Actions().StateChanged( KMceStateConfirming ); + } + else + { + CSIPClientTransaction* invite = session.PendingTransaction( + SIPStrings::StringF( SipStrConsts::EInvite ) ); + User::LeaveIfError( invite ? KErrNone : + KErrTotalLossOfPrecision ); + + if ( invite->StateL() == CSIPTransactionBase::ETerminated ) + { + // Just go to established state + session.Actions().ClientStateChangedL( + CMceSession::EEstablished, + *session.Body(), + session.Response() ); + session.Actions().StateChanged( KMceStateEstablished ); + } + else + { + session.Actions().StateChanged( KMceStateOffering ); + } + } + } + +// End of file