diff -r 000000000000 -r 1bce908db942 multimediacommsengine/mmcesrv/mmceserver/src/mcestateacknowledgementrequired.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/multimediacommsengine/mmcesrv/mmceserver/src/mcestateacknowledgementrequired.cpp Tue Feb 02 01:04:58 2010 +0200 @@ -0,0 +1,474 @@ +/* +* Copyright (c) 2008 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 "mcestateacknowledgementrequired.h" +#include "mcesipsession.h" +#include "mceactionset.h" +#include "mcefcactionset.h" +#include "mcenatmacros.h" +#include "mcereliablesender.h" + +// ----------------------------------------------------------------------------- +// CMceStateAcknowledgementRequired::CMceStateAcknowledgementRequired +// ----------------------------------------------------------------------------- +// +CMceStateAcknowledgementRequired::CMceStateAcknowledgementRequired() + : CMceState( KMceStateAcknowledgementRequired ) + { + } + + +// ----------------------------------------------------------------------------- +// CMceStateAcknowledgementRequired::~CMceStateAcknowledgementRequired +// ----------------------------------------------------------------------------- +// +CMceStateAcknowledgementRequired::~CMceStateAcknowledgementRequired() + { + } + + +// ----------------------------------------------------------------------------- +// CMceStateAcknowledgementRequired::DoAcceptL +// ----------------------------------------------------------------------------- +// +TBool CMceStateAcknowledgementRequired::DoAcceptL( + TMceStateTransitionEvent& aEvent ) + { + User::LeaveIfError( + aEvent.Code() == EMcePrack || + aEvent.Code() == EMceMediaUpdated || + aEvent.Code() == EMceNoPrackReceived || + aEvent.Code() == EMceReliableFailed || + aEvent.Code() == EMceAck || + aEvent.Code() == EMceItcEnable || + aEvent.Code() == EMceItcDisable || + aEvent.Code() == EMceItcAcceptSession || + aEvent.Code() == EMceItcRejectSession || + IsExtensionRequestEvent( aEvent ) + + ? KErrNone : KErrTotalLossOfPrecision ); + + return ETrue; + } + +// ----------------------------------------------------------------------------- +// CMceStateAcknowledgementRequired::EntryL +// ----------------------------------------------------------------------------- +// +void CMceStateAcknowledgementRequired::EntryL( + TMceStateTransitionEvent& aEvent ) + { + + if ( IsExtensionRequestEvent( aEvent )) + { + HandleExtensionRequestEventL( aEvent ); + } + + else + { + switch ( aEvent.Code() ) + { + case EMcePrack: + { + EntryPrackL( aEvent ); + break; + } + case EMceMediaUpdated: + { + EntryMediaUpdatedL( aEvent ); + break; + } + case EMceNoPrackReceived: + { + EntryNoPrackReceivedL( aEvent ); + break; + } + case EMceReliableFailed: + { + EntryReliableFailedL ( aEvent ); + break; + } + case EMceItcEnable: + case EMceItcDisable: + { + aEvent.Session().Actions().ControlMediaL( aEvent.ParamIDs(), + (TMceItcFunctions)aEvent.Code() ); + break; + } + case EMceItcAcceptSession: + { + EntryEarlyAcceptL( aEvent ); + break; + } + + case EMceItcRejectSession: + { + CMceSipSession& session = aEvent.Session(); + CSIPServerTransaction& request = session.Request(); + + aEvent.Session().Actions().SendDeclineL( request, + aEvent.ParamClientMessage() ); + + aEvent.Session().Actions().StopMedia(); + aEvent.Session().FCActions().ReleaseFC(); + break; + } + + + default: + { + // NOP + break; + } + } + } + } + +// ----------------------------------------------------------------------------- +// CMceStateAcknowledgementRequired::ExitL +// ----------------------------------------------------------------------------- +// +void CMceStateAcknowledgementRequired::ExitL( TMceStateTransitionEvent& aEvent ) + { + + if ( IsExtensionRequestEvent( aEvent )) + { + //Do Nothing; + } + + else + { + CMceSipSession& session = aEvent.Session(); + TInt status = aEvent.ParamStatus(); + switch ( aEvent.Code() ) + { + case EMcePrack: + { + if ( MCE_IS_ERROR( status ) ) + { + session.Actions().StateChanged( KMceStateTerminated ); + session.Actions().ClientStateChangedL( CMceSession::ETerminated ); + } + else + { + //NOTE this is only for media reservation, not for resource + //reservation + if ( status == KMceAsync ) + { + //PRACK caused media to be ready asynchronously + } + else if ( status == KMceReady && + MCE_NEED_TO_RECEIVE( session ) ) + { + //media is ready, but preconditions are not met + session.Actions().StateChanged( KMceStateConfirmationRequired ); + } + + else + { + // media is ready and preconditions are met + ProceedToUpdatedL( aEvent ); + } + } + break; + } + case EMceMediaUpdated: + { + if ( MCE_IS_ERROR( status ) ) + { + session.Actions().StateChanged( KMceStateTerminated ); + session.Actions().ClientStateChangedL( CMceSession::ETerminated ); + } + else if ( status == KMceReady ) + { + // Other possible state changes handle in entry + session.Actions().StateChanged( KMceStateConfirmationRequired ); + } + else // KMceAsync + { + session.Actions().StateChanged( KMceStateServerReserving ); + } + break; + } + + case EMceNoPrackReceived: + { + session.Actions().StateChanged( KMceStateTerminated ); + session.Actions().ClientStateChangedL( CMceSession::ETerminated, + KErrTimedOut ); + break; + } + + case EMceReliableFailed: + { + session.Actions().StateChanged( KMceStateTerminated ); + session.Actions().ClientStateChangedL( CMceSession::ETerminated, + aEvent.ParamStatus()); + break; + } + + case EMceItcRejectSession: + { + session.Actions().StateChanged( KMceStateTerminated ); + session.Actions().ClientStateChanged( aEvent.ParamIDs(), + CMceSession::ETerminated ); + break; + } + + + default: + { + // NOP + break; + } + } + } + } + +// ----------------------------------------------------------------------------- +// CMceStateAcknowledgementRequired::EntryPrackL +// ----------------------------------------------------------------------------- +// +void CMceStateAcknowledgementRequired::EntryPrackL( + TMceStateTransitionEvent& aEvent ) + { + CMceSipSession& session = aEvent.Session(); + // validate PRACK + TBool match = session.ReliableSender().PrackReceived( session.Request() ); + TMceSipWarningCode warning = KErrNone; + if ( match ) + { + if ( MceSip::HasContent( session.Request() ) ) + { + // PRACK carries SDP + User::LeaveIfError( session.Actions().CreateSDP( session.Request() ) ); + + session.Actions().CreateBodyCandidateL( CMceComSession::EInSession ); + + warning = session.Actions().DecodeL(); + + session.ActiveBody().iCodecSelection = KMceCodecSelectionMerge; + + aEvent.ParamStatus() = !warning ? KErrNone : KErrAbort; + if ( !warning ) + { + TMceReturnStatus status = session.Actions().UpdateL(); + //Second update is needed. + status = session.Actions().UpdateL(); + aEvent.ParamStatus() = status; + if ( status == KMceReady ) + { + aEvent.Code() = EMceMediaUpdated; + EntryMediaUpdatedL( aEvent ); + } + } + } + else + { + // Empty PRACK + // Send 200 OK + session.Actions().Send200OKL( session.Request() ); + TMceReturnStatus status = KMceReady; + status = session.Actions().ReserveL(); + + aEvent.ParamStatus() = status; + if ( status == KMceAsync ) + { + // reservation ongoind + session.Actions().StateChanged( KMceStateServerReserving ); + } + } + + if ( aEvent.Code() != EMceMediaUpdated && + MCE_IS_ERROR( aEvent.ParamStatus() ) ) + { + if ( warning ) //if error, reject offer (4XX out) + { + session.Actions().SendRejectOfferWithWarningL( warning, session.Request() ); + } + else + { + MceSip::DiscardRequest( session.Request() ); + } + + //reject also invite + session.DiscardInvite(); + } + } + else // not match + { + // Reject the PRACK + // Suitable Error code can be defined when PRACK is not mached + // to handle state transition + aEvent.ParamStatus() = KErrNotFound; + MceSip::DiscardRequest( session.Request(), + KMceSipCallOrTransactionDoesNotExist ); + + } + } + +// ----------------------------------------------------------------------------- +// CMceStateAcknowledgementRequired::EntryMediaUpdatedL +// ----------------------------------------------------------------------------- +// +void CMceStateAcknowledgementRequired::EntryMediaUpdatedL( + TMceStateTransitionEvent& aEvent ) + { + CMceSipSession& session = aEvent.Session(); + CSIPServerTransaction& prack = session.Request(); + // verify, that PRACK really is the previous request + __ASSERT_ALWAYS( prack.Type() == SIPStrings::StringF( SipStrConsts::EPrack ), + User::Leave( KErrTotalLossOfPrecision ) ); + + TMceReturnStatus status = session.Actions().ReserveL(); + aEvent.ParamStatus() = status; + if ( MCE_IS_ERROR( aEvent.ParamStatus() ) ) + { + MceSip::DiscardRequest( session.Request() ); + + //reject also invite + session.DiscardInvite(); + } + else + { + // send 2xx to PRACK + if ( session.ActiveBody().SecureSession() ) + { + session.ActiveBody().SecureSession()->iLSReadyToBind = ETrue; + } + + // In KMceNatStateDecodeOffer state, answer is available. + // Pull mode is not used with long signalling. + if ( !( session.NatSession() && + ( ( session.NatState() == KMceNatStateCreateOffer ) || + ( session.NatState() == KMceNatStateCreateAnswer ) || + ( session.NatState() == KMceNatStateWait ) || + ( session.NatState() == KMceNatStateConnected ) ) ) ) + { + session.Actions().EncodeL(); + } + session.FCActions().UpdateFCAnswerL( *session.Offer() ); + session.Actions().SendAnswerL( prack ); + + session.Actions().UpdateSucceed(); + + if ( !MCE_NEED_TO_RECEIVE( session ) && !MCE_FORCED_TO_RECEIVE( session ) ) + { + ProceedToUpdatedL( aEvent ); + } + } + } + +// ----------------------------------------------------------------------------- +// CMceStateAcknowledgementRequired::EntryNoPrackReveivedL +// ----------------------------------------------------------------------------- +// +void CMceStateAcknowledgementRequired::EntryNoPrackReceivedL( + TMceStateTransitionEvent& aEvent ) + { + CMceSipSession& session = aEvent.Session(); + CSIPServerTransaction& serverTransaction = session.Request(); + MceSip::DiscardRequest( serverTransaction, + KMceSipServerTimeOut, + KMceNoRetryAfter ); + + if ( session.SubState() == CMceSipSession::EOffering || + session.SubState() == CMceSipSession::EAnswering ) + { + session.Actions().StopMedia(); + session.FCActions().ReleaseFC(); + } + else if ( session.SubState() == CMceSipSession::EUpdating ) + { + session.Actions().UpdateFailed(); + } + else + { + // NOP + } + } + +// ----------------------------------------------------------------------------- +// CMceStateAcknowledgementRequired::EntryReliableFailedL +// ----------------------------------------------------------------------------- +// +void CMceStateAcknowledgementRequired::EntryReliableFailedL( + TMceStateTransitionEvent& aEvent ) + { + + CMceSipSession& session = aEvent.Session(); + CSIPServerTransaction& serverTransaction = session.Request(); + MceSip::DiscardRequest( serverTransaction, + KMceSipServerInternalError, + KMceNoRetryAfter ); + + if ( session.SubState() == CMceSipSession::EOffering || + session.SubState() == CMceSipSession::EAnswering ) + { + session.Actions().StopMedia(); + session.FCActions().ReleaseFC(); + } + else if ( session.SubState() == CMceSipSession::EUpdating ) + { + session.Actions().UpdateFailed(); + } + else + { + // NOP + } + } + +// ----------------------------------------------------------------------------- +// CMceStateAcknowledgementRequired::EntryEarlyAcceptL +// ----------------------------------------------------------------------------- +// +void CMceStateAcknowledgementRequired::EntryEarlyAcceptL( + TMceStateTransitionEvent& aEvent ) + { + // Client accepted the session before prack was received, remember that + // 200 OK for invite is sent when possible. + CMceSipSession& session = aEvent.Session(); + session.StoreAutoEventL( &aEvent, &session.InitialRequest() ); + } + +// ----------------------------------------------------------------------------- +// CMceStateAcknowledgementRequired::ProceedToUpdatedL +// ----------------------------------------------------------------------------- +// +void CMceStateAcknowledgementRequired::ProceedToUpdatedL( + TMceStateTransitionEvent& aEvent ) + { + CMceSipSession& session = aEvent.Session(); + + TMceStateTransitionEvent* acceptEvent = session.StoredAutoEvent(); + if ( acceptEvent && acceptEvent->Code() == EMceItcAcceptSession ) + { + // Session was accepted before really possible and now accepting is + // possible, enable automatic event generation to occur at state change + session.SetAutoEvent( ETrue ); + } + + session.Actions().StateChanged( KMceStateUpdated ); + session.Actions().ClientStateChangedL( CMceSession::EProceeding, + *session.Body(), + KErrNone ); + } + +// End of file