diff -r 000000000000 -r 1bce908db942 multimediacommsengine/mmcecli/src/mcesession.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/multimediacommsengine/mmcecli/src/mcesession.cpp Tue Feb 02 01:04:58 2010 +0200 @@ -0,0 +1,1699 @@ +/* +* 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 +#include "mcesession.h" +#include "mceinsession.h" +#include "mcemanager.h" +#include "mceinsessionobserver.h" +#include "mcesessionobserver.h" +#include "mcestreamobserver.h" +#include "mcetransactionobserver.h" +#include "mceintransactionobserver.h" +#include "mcertpobserver.h" +#include "mcefcmsgobserver.h" +#include "mcetransactiondatacontainer.h" +#include "mcefactory.h" +#include "mceitcsender.h" +#include "mcesessionreceiver.h" +#include "mceclientserver.h" +#include "mceevents.h" +#include "mceserial.h" +#include "mceitcsender.h" +#include "mcesessionreceiver.h" +#include "mce.h" +#include "mcecomsession.h" +#include "mcecommediasink.h" +#include "mcecommediasource.h" +#include "mcestreambundle.h" +#include "mceclilogs.h" + +#define _FLAT_DATA static_cast( iFlatData ) +#define FLAT_DATA( data ) _FLAT_DATA->data + + +// ============================ MEMBER FUNCTIONS =============================== + + +// ----------------------------------------------------------------------------- +// CMceSession::~CMceSession +// ----------------------------------------------------------------------------- +// +CMceSession::~CMceSession() + { + MCECLI_DEBUG("CMceSession::~CMceSession, Entry") + + //causes EMceItcClientCancelReceive + delete iReceiver; + iReceiver = NULL; + + if ( iManager && iFlatData ) + { + //causes EMceItcDeleteSession + iManager->UnregisterSession( this ); + } + + delete iFlatData; + delete iSender; + + iMediaStreams.ResetAndDestroy(); + iBundles.ResetAndDestroy(); + + MCECLI_DEBUG("CMceSession::~CMceSession, Exit") + } + +// ----------------------------------------------------------------------------- +// CMceSession::State +// ----------------------------------------------------------------------------- +// +EXPORT_C CMceSession::TState CMceSession::State() const + { + return FLAT_DATA( iState ); + } + +// ----------------------------------------------------------------------------- +// CMceSession::GetSIPParams +// ----------------------------------------------------------------------------- +// +void CMceSession::GetSIPParams( CDesC8Array*& aHeaders, + HBufC8*& aContentType, + CDesC8Array*& aContentHeaders ) + { + CDesC8Array* sipHeaders = FLAT_DATA( iSIPHeaders ); + HBufC8* sipContentType = FLAT_DATA( iSIPContentType ); + CDesC8Array* sipContentHeaders = FLAT_DATA( iSIPContentHeaders ); + FLAT_DATA( iSIPHeaders ) = NULL; + FLAT_DATA( iSIPContentType ) = NULL; + FLAT_DATA( iSIPContentHeaders ) = NULL; + aHeaders = sipHeaders; + aContentType = sipContentType; + aContentHeaders = sipContentHeaders; + } + +// ----------------------------------------------------------------------------- +// CMceSession::SetSIPParams +// ----------------------------------------------------------------------------- +// +void CMceSession::SetSIPParams( CDesC8Array* aHeaders, + HBufC8* aContentType, + CDesC8Array* aContentHeaders ) + { + delete FLAT_DATA( iSIPHeaders ); + FLAT_DATA( iSIPHeaders ) = aHeaders; + delete FLAT_DATA( iSIPContentType ); + FLAT_DATA( iSIPContentType ) = aContentType; + delete FLAT_DATA( iSIPContentHeaders ); + FLAT_DATA( iSIPContentHeaders ) = aContentHeaders; + } + +// ----------------------------------------------------------------------------- +// CMceSession::SIPParamsCleanup +// ----------------------------------------------------------------------------- +// +void CMceSession::SIPParamsCleanup( TAny* aSession ) + { + if ( !aSession ) + { + return; + } + CMceSession* session = reinterpret_cast< CMceSession* >( aSession ); + session->iFlatData->iSIPHeaders = 0; + session->iFlatData->iSIPContentType = 0; + session->iFlatData->iSIPContentHeaders = 0; + } + +// ----------------------------------------------------------------------------- +// CMceSession::ConnectionActive +// ----------------------------------------------------------------------------- +// +EXPORT_C TBool CMceSession::ConnectionActive() const + { + return FLAT_DATA( iIsConnectionActive ); + } + +// ----------------------------------------------------------------------------- +// CMceSession::AddStreamL +// If called from InternalizeL, iManager is NULL and don't initialize stream. +// ----------------------------------------------------------------------------- +// +void CMceSession::AddStreamL( CMceMediaStream* aMediaStream ) + { + __ASSERT_ALWAYS( aMediaStream != NULL, User::Leave( KErrArgument ) ); + __ASSERT_ALWAYS( iMediaStreams.Find( aMediaStream ) == KErrNotFound, + User::Leave( KErrArgument ) ); + __ASSERT_ALWAYS( !aMediaStream->BoundStream() || + aMediaStream->Binder(), User::Leave( KErrArgument ) ); + + aMediaStream->AddedL(); + + if ( iManager && StreamInitializeCondition( *aMediaStream ) ) + { + // Initialize stream to get the supported codecs + aMediaStream->InitializeL( iManager, *this ); + } + + DoAddStreamL( aMediaStream ); + } + +// ----------------------------------------------------------------------------- +// CMceSession::DoAddStreamL +// ----------------------------------------------------------------------------- +// +void CMceSession::DoAddStreamL( CMceMediaStream* aMediaStream ) + { + iMediaStreams.AppendL( aMediaStream ); + } + +// ----------------------------------------------------------------------------- +// CMceSession::RemoveStreamL +// ----------------------------------------------------------------------------- +// +EXPORT_C void CMceSession::RemoveStreamL( CMceMediaStream& aMediaStream ) + { + MCECLI_DEBUG("CMceSession::RemoveStreamL, Entry") + + __ASSERT_ALWAYS( State() == CMceSession::EIdle || + State() == CMceSession::EIncoming || + State() == CMceSession::EEstablished, + User::Leave( KErrNotReady ) ); + + TInt index = iMediaStreams.Find( &aMediaStream ); + if ( index >= 0 ) + { + CMceMediaStream* stream = iMediaStreams[ index ]; + iMediaStreams.Remove( index ); + delete stream; + } + + MCECLI_DEBUG("CMceSession::RemoveStreamL, Exit") + } + +// ----------------------------------------------------------------------------- +// CMceSession::InitializeL +// ----------------------------------------------------------------------------- +// +void CMceSession::InitializeL( + TBool aClientSideMedia, + TBool aDiscardUnusedCodecs ) + { + __ASSERT_ALWAYS( iManager, User::Leave( KErrArgument ) ); + + for( TInt i=0; iInitializeL( iManager, *this ); + } + iMediaStreams[i]->InitializeL( *this, aDiscardUnusedCodecs ); + } + for( TInt i=0; iInitializeL( *this ); + } + } + +// ----------------------------------------------------------------------------- +// CMceSession::UpdateL +// ----------------------------------------------------------------------------- +// +EXPORT_C void CMceSession::UpdateL( + TUint32 aTimeout, + CDesC8Array* aHeaders, + HBufC8* aContentType, + HBufC8* aContent, + CDesC8Array* aContentHeaders ) + { + MCECLI_DEBUG("CMceSession::UpdateL, Entry") + TState state = State(); + MCECLI_DEBUG_CLISTATE( "state", state ) + + User::LeaveIfError( IsZombie() ? KErrArgument : KErrNone ); + User::LeaveIfError( State() != EIdle ? KErrNone : KErrNotReady ); + User::LeaveIfError( + ( aContentType && aContent ) || + !( aContentType || aContent || aContentHeaders ) ? + KErrNone : KErrArgument ); + + // Leave if in incoming state givem too small timeout value + User::LeaveIfError( !( aTimeout > 0 && State() == CMceSession::EIncoming ) || + aTimeout <= SessionTimer() ? KErrNone : KErrArgument ); + + // initialize streams + InitializeL( EFalse ); + + SetSIPParams( aHeaders, aContentType, aContentHeaders ); + + if( !( aTimeout == 0 && State() == CMceSession::EIncoming ) ) + { + FLAT_DATA( iTimeout ) = + ( aTimeout < FLAT_DATA( iMinSE ) ? FLAT_DATA( iMinSE ) : aTimeout ); + } + + SendUpdateL( aContent ); + + MCECLI_DEBUG("CMceSession::UpdateL, Exit") + } + +// ----------------------------------------------------------------------------- +// CMceSession::SendUpdateL +// ----------------------------------------------------------------------------- +// +void CMceSession::SendUpdateL( HBufC8* aContent ) + { + MCECLI_DEBUG("CMceSession::SendUpdateL, Entry") + + TCleanupItem sipParamsCleanup( SIPParamsCleanup, this ); + CleanupStack::PushL( sipParamsCleanup ); + + TMceIds ids; + PrepareForITC( ids ); + ids.iState = State(); + + CMceMsgObject* msg = + new (ELeave) CMceMsgObject( *this, EMceItcMsgTypeSession ); + CleanupStack::PushL( msg ); + + // Don't pass aContent's ownership. Delete it when this function can't leave + // anymore + iSender->SendL( ids, EMceItcUpdate, *msg, aContent, EFalse ); + + CleanupStack::PopAndDestroy( msg ); + + FLAT_DATA( iState ) = static_cast( ids.iState ); + TState state = State(); + MCECLI_DEBUG_CLISTATE( "CMceSession::SendUpdateL, after ITC, state", state ) + + if ( ids.iStatus != KErrNone ) + { + MCECLI_DEBUG("CMceSession::SendUpdateL, update failed. rollback") + + TMceIds ids2; + SynchronizeL( ids2 ); + state = State(); + MCECLI_DEBUG_CLISTATE( "CMceSession::SendUpdateL, after ITC, state", state ) + + CleanupStack::Pop(); // sipParamsCleanup + SetSIPParams( NULL, NULL, NULL ); + + MMceSessionObserver* observer = iManager->SessionObserver(); + TMceTransactionDataContainer* container = iManager->TransactionContainer(); + if ( observer && container ) + { + container->SetStatusCode( ids2.iStatus ); + observer->UpdateFailed( *this, container ); + container->Clear(); + } + + } + else + { + CleanupStack::Pop(); // sipParamsCleanup + SetSIPParams( NULL, NULL, NULL ); + } + + delete aContent; + + MCECLI_DEBUG("CMceSession::SendUpdateL, Exit") + } + +// ----------------------------------------------------------------------------- +// CMceSession::SynchronizeL +// ----------------------------------------------------------------------------- +// +void CMceSession::SynchronizeL( TMceIds& aIds ) + { + MCECLI_DEBUG("CMceSession::SynchronizeL, Entry") + + PrepareForITC( aIds ); + aIds.iState = State(); + + HBufC8* encodedSrvSession = iSender->ReadStringL( aIds, EMceItcGetSession ); + CleanupStack::PushL( encodedSrvSession ); + + CMceMsgObject* srvSession = + new (ELeave) CMceMsgObject(); + CleanupStack::PushL( srvSession ); + srvSession->DecodeL( *encodedSrvSession ); + + srvSession->PushL(); + UpdateL( *srvSession->iObject ); + CleanupStack::PopAndDestroy( srvSession ); + CleanupStack::PopAndDestroy( encodedSrvSession ); + + MCECLI_DEBUG("CMceSession::SynchronizeL, Exit") + } + +// ----------------------------------------------------------------------------- +// CMceSession::TerminateL +// ----------------------------------------------------------------------------- +// +EXPORT_C void CMceSession::TerminateL( CDesC8Array* aHeaders, + HBufC8* aContentType, + HBufC8* aContent ) + { + MCECLI_DEBUG("CMceSession::TerminateL, Entry") + TState state = State(); + MCECLI_DEBUG_CLISTATE( "state", state ) + + User::LeaveIfError( IsZombie() ? KErrArgument : KErrNone ); + User::LeaveIfError( State() != EIdle ? KErrNone : KErrNotReady ); + User::LeaveIfError( + ( aContentType && aContent ) || !( aContentType || aContent ) ? + KErrNone : KErrArgument ); + + + TMceIds ids; + PrepareForITC( ids ); + ids.iState = State(); + + CMceMsgSIPData* sipData = new (ELeave) CMceMsgSIPData( SipStrConsts::EBye, + *aHeaders, *aContentType ); + CleanupStack::PushL( sipData ); + + sipData->OwnershipRollbackPushLC(); + + iSender->SendL( ids, EMceItcTerminateSession, *sipData, aContent ); + + CleanupStack::Pop(); // sipData->OwnershipRollbackPushLC() + + sipData->Close(); + CleanupStack::PopAndDestroy( sipData ); + + FLAT_DATA( iState ) = static_cast( ids.iState ); + + state = State(); + MCECLI_DEBUG_CLISTATE( "CMceSession::TerminateL, after ITC, state", state ) + MCECLI_DEBUG("CMceSession::TerminateL, Exit") + } + +// ----------------------------------------------------------------------------- +// CMceSession::Streams +// ----------------------------------------------------------------------------- +// +EXPORT_C const RPointerArray& CMceSession::Streams() const + { + return iMediaStreams; + } + +// ----------------------------------------------------------------------------- +// CMceSession::Recipient +// ----------------------------------------------------------------------------- +// +EXPORT_C const TDesC8& CMceSession::Recipient() const + { + return *FLAT_DATA( iRecipient ); + } + +// ----------------------------------------------------------------------------- +// CMceSession::Originator +// ----------------------------------------------------------------------------- +// +EXPORT_C const TDesC8& CMceSession::Originator() const + { + return *FLAT_DATA( iOriginator ); + } + +// ----------------------------------------------------------------------------- +// CMceSession::Originator +// ----------------------------------------------------------------------------- +// +EXPORT_C TUint32 CMceSession::SessionTimer() const + { + return FLAT_DATA( iTimeout ); + } + +// ----------------------------------------------------------------------------- +// CMceSession::SetSessionSDPLinesL +// ----------------------------------------------------------------------------- +// +EXPORT_C void CMceSession::SetSessionSDPLinesL( CDesC8Array* aSessionSDPLines ) + { + MCECLI_DEBUG("CMceSession::SetSessionSDPLinesL, Entry") + + User::LeaveIfError( State() == CMceSession::EIdle || + State() == CMceSession::EIncoming || + State() == CMceSession::EEstablished ? + KErrNone : KErrNotReady ); + CDesC8Array* lines = ( aSessionSDPLines ? aSessionSDPLines : + new (ELeave) CDesC8ArrayFlat( KMceArrayGranularity ) ); + delete FLAT_DATA( iLocalSessionSDPLines ); + FLAT_DATA( iLocalSessionSDPLines ) = lines; + MCECLI_DEBUG("CMceSession::SetSessionSDPLinesL, Exit") + } + +// ----------------------------------------------------------------------------- +// CMceSession::SessionSDPLinesL +// ----------------------------------------------------------------------------- +// +EXPORT_C MDesC8Array* CMceSession::SessionSDPLinesL() + { + CDesC8Array* lines = new (ELeave) CDesC8ArrayFlat( KMceArrayGranularity ); + CleanupStack::PushL( lines ); + for ( TInt i=0; i < FLAT_DATA( iRemoteSessionSDPLines )->Count(); i++ ) + { + lines->AppendL( FLAT_DATA( iRemoteSessionSDPLines )->MdcaPoint( i ) ); + } + CleanupStack::Pop( lines ); + return lines; + } + +// ----------------------------------------------------------------------------- +// CMceRefer::AssociatedEvents +// ----------------------------------------------------------------------------- +// +EXPORT_C RPointerArray< CMceEvent >* CMceSession::AssociatedEventsL() const + { + return NULL; + } + +// ----------------------------------------------------------------------------- +// CMceRefer::AssociatedRefers +// ----------------------------------------------------------------------------- +// +EXPORT_C RPointerArray< CMceRefer >* CMceSession::AssociatedRefersL() const + { + return NULL; + } + +// ----------------------------------------------------------------------------- +// CMceSession::GetModifierL +// ----------------------------------------------------------------------------- +// +EXPORT_C void CMceSession::GetModifierL( TMceSessionModifier aModifier, + TUint& aValue ) const + { + __ASSERT_ALWAYS( aModifier < KMceMaxSessionModifiers, + User::Leave( KErrArgument ) ); + TUint value = _FLAT_DATA->Modifier( aModifier ); + aValue = value; + } + +// ----------------------------------------------------------------------------- +// CMceSession::SetModifierL +// ----------------------------------------------------------------------------- +// +EXPORT_C void CMceSession::SetModifierL( TMceSessionModifier aModifier, + TUint aValue ) + { + __ASSERT_ALWAYS( aModifier < KMceMaxSessionModifiers, + User::Leave( KErrArgument ) ); + _FLAT_DATA->Modifier( aModifier ) = aValue; + if ( aModifier == KMceSecPreconditions && aValue == KMcePreconditionsE2ESupported ) + { + _FLAT_DATA->Modifier( KMcePreconditions ) = KMcePreconditionsNotUsed; + } + + if ( aModifier == KMcePreconditions && aValue == KMcePreconditionsSupported && + _FLAT_DATA->Modifier( KMceSecPreconditions ) != KMcePreconditionsE2ESupported ) + { + _FLAT_DATA->Modifier( KMceSecPreconditions ) = KMcePreconditionsNotUsed; + } + + } + + +// ----------------------------------------------------------------------------- +// CMceSession::AddBundleL +// ----------------------------------------------------------------------------- +// +EXPORT_C void CMceSession::AddBundleL( CMceStreamBundle* aBundle ) + { + + aBundle->AddedL(); + iBundles.AppendL( aBundle ); + + + } + +// ----------------------------------------------------------------------------- +// CMceSession::RemoveBundleL +// ----------------------------------------------------------------------------- +// +EXPORT_C void CMceSession::RemoveBundleL( CMceStreamBundle& aBundle ) + { + TInt index = iBundles.Find( &aBundle ); + User::LeaveIfError( index ); + iBundles.Remove( index ); + + } + +// ----------------------------------------------------------------------------- +// CMceSession::Bundles +// ----------------------------------------------------------------------------- +// +EXPORT_C const RPointerArray< CMceStreamBundle >& CMceSession::Bundles() const + { + return iBundles; + } + +// ----------------------------------------------------------------------------- +// CMceSession::Profile +// ----------------------------------------------------------------------------- +// +EXPORT_C TUint32 CMceSession::Profile() const + { + return iProfileId; + } + + +// ----------------------------------------------------------------------------- +// CMceSession::SetServiceTypeL +// ----------------------------------------------------------------------------- +// +EXPORT_C void CMceSession::SetServiceTypeL( TUint32 aServiceType ) + { + MCECLI_DEBUG("CMceSession::SetServiceTypeL, Entry") + + User::LeaveIfError( State() == CMceSession::EIdle || + State() == CMceSession::EIncoming ? + KErrNone : KErrNotReady ); + User::LeaveIfError ( aServiceType >= KMceMaxTypeOfServiceValue ? + KErrArgument : KErrNone ); + + FLAT_DATA( iServiceType ) = aServiceType ; + + MCECLI_DEBUG("CMceSession::SetServiceTypeL, Exit") + } + +// ----------------------------------------------------------------------------- +// CMceSession::ControlPathSecurityLevel() +// ----------------------------------------------------------------------------- +// +EXPORT_C CMceSession::TControlPathSecurityLevel +CMceSession::ControlPathSecurityLevel() const + { + if ( FLAT_DATA( iSipContactAddrSecure ) != CMceSession::EControlPathUnsecure && + FLAT_DATA( iSipContactAddrSecure ) != CMceSession::EControlPathSecure ) + { + FLAT_DATA( iSipContactAddrSecure ) = CMceSession::EControlPathSecurityUnknown; + } + + return FLAT_DATA( iSipContactAddrSecure ); + } + +// ----------------------------------------------------------------------------- +// CMceSession::ServiceType +// ----------------------------------------------------------------------------- +// +EXPORT_C TUint32 CMceSession::ServiceType() const + { + return FLAT_DATA( iServiceType ); + } + +// ----------------------------------------------------------------------------- +// CMceSession::Type +// ----------------------------------------------------------------------------- +// +TMceSessionType CMceSession::Type() const + { + return KMceSessionNormal; + } + +// ----------------------------------------------------------------------------- +// CMceSession::CMceSession +// ----------------------------------------------------------------------------- +// +CMceSession::CMceSession( CMceManager* aManager, TUint32 aProfileId ) + : iManager( aManager ), + iProfileId( aProfileId ) + { + } + +// ----------------------------------------------------------------------------- +// CMceSession::SerializationId +// ----------------------------------------------------------------------------- +// +TUint64 CMceSession::SerializationId() const + { + return FLAT_DATA( SerializationId() ); + } + +// ----------------------------------------------------------------------------- +// CMceSession::InternalizeFlatL +// ----------------------------------------------------------------------------- +// +void CMceSession::InternalizeFlatL( RReadStream& aReadStream ) + { + _FLAT_DATA->InternalizeFlatL( aReadStream ); + } + +// ----------------------------------------------------------------------------- +// CMceSession::ExternalizeFlatL +// ----------------------------------------------------------------------------- +// +void CMceSession::ExternalizeFlatL( RWriteStream& aWriteStream ) + { + _FLAT_DATA->ExternalizeFlatL( aWriteStream ); + } + +// ----------------------------------------------------------------------------- +// CMceSession::InternalizeL +// ----------------------------------------------------------------------------- +// +void CMceSession::InternalizeL( MMceComSerializationContext& aSerCtx ) + { + TMceSessionSerializer serial( *this, _FLAT_DATA ); + serial.InternalizeL( aSerCtx ); + } + +// ----------------------------------------------------------------------------- +// CMceSession::ExternalizeL +// ----------------------------------------------------------------------------- +// +void CMceSession::ExternalizeL( MMceComSerializationContext& aSerCtx ) + { + TMceSessionSerializer serial( *this, _FLAT_DATA ); + serial.ExternalizeL( aSerCtx ); + } + + +// ----------------------------------------------------------------------------- +// CMceSession::BaseFactory +// ----------------------------------------------------------------------------- +// +TMceFactory CMceSession::BaseFactory() + { + return TMceFactory(); + } + +// ----------------------------------------------------------------------------- +// CMceSession::Factory +// ----------------------------------------------------------------------------- +// +TMceFactory CMceSession::Factory() + { + return TMceFactory(); + } + + +// ----------------------------------------------------------------------------- +// CMceSession::Id +// ----------------------------------------------------------------------------- +// +TUint32 CMceSession::Id() const + { + return FLAT_DATA( iID ); + } + + +// ----------------------------------------------------------------------------- +// CMceSession::DialogId +// ----------------------------------------------------------------------------- +// +TUint32 CMceSession::DialogId() const + { + return FLAT_DATA( iDialogId ); + } + +// ----------------------------------------------------------------------------- +// CMceSession::ITCSender +// ----------------------------------------------------------------------------- +// +CMceItcSender& CMceSession::ITCSender() const + { + return *iSender; + } + +// ----------------------------------------------------------------------------- +// CMceSession::Manager +// ----------------------------------------------------------------------------- +// +CMceManager& CMceSession::Manager() const + { + return *iManager; + } + +// ----------------------------------------------------------------------------- +// CMceSession::SetFCObserver +// ----------------------------------------------------------------------------- +// +void CMceSession::SetFCObserver( MMceFcMsgObserver* aPtr) + { + iFCObserver = aPtr; + } + +// ----------------------------------------------------------------------------- +// CMceSession::ConstructL +// ----------------------------------------------------------------------------- +// +void CMceSession::ConstructL( TBool aUpdateSession ) + { + MCECLI_DEBUG("CMceSession::ConstructL, Entry") + + User::LeaveIfNull( iFlatData ); + + if ( iManager && !aUpdateSession ) + { + TBuf8<64> iapId; + iapId.AppendNum( FLAT_DATA( iIapId ) ); + + CDesC8ArrayFlat* params = + new (ELeave) CDesC8ArrayFlat( KMceArrayGranularity ); + CleanupStack::PushL( params ); + params->AppendL( Originator() ); + params->AppendL( Recipient() ); + params->AppendL( iapId ); + + FLAT_DATA( iID ) = iManager->RegisterSessionL( this, + *params, + FLAT_DATA( iDialogId ), + FLAT_DATA( iIsConnectionActive ) ); + + CleanupStack::PopAndDestroy( params ); + + //get server + RMce& server = iManager->ServerSession(); + + //create sender + iSender = CMceItcSender::NewL( server ); + //create receiver + iReceiver = new (ELeave) CMceSessionReceiver( server, *this ); + } + + MCECLI_DEBUG("CMceSession::ConstructL, Exit") + } + +// ----------------------------------------------------------------------------- +// CMceSession::PrepareForITC +// ----------------------------------------------------------------------------- +// +void CMceSession::PrepareForITC( TMceIds& aId ) + { + + aId.iAppUID = Manager().AppUid().iUid; + aId.iSessionID = Id(); + aId.iManagerType = KMceCSSIPSession; + aId.iProfileID = iProfileId; + + } + + +// ----------------------------------------------------------------------------- +// CMceSession::EventReceivedL +// ----------------------------------------------------------------------------- +// +void CMceSession::EventReceivedL( TMceIds& aId ) + { + TMceEvent event( aId, NULL, NULL ); + EventReceivedL( event ); + } + + +// ----------------------------------------------------------------------------- +// CMceSession::EventReceivedL +// ----------------------------------------------------------------------------- +// +void CMceSession::EventReceivedL( TMceIds& aId, CMceMsgBase& aMessage ) + { + TMceEvent event( aId, &aMessage, NULL ); + EventReceivedL( event ); + } + + +// ----------------------------------------------------------------------------- +// CMceSession::IsZombie +// ----------------------------------------------------------------------------- +// +TBool CMceSession::IsZombie() + { + return !iReceiver && !iSender; + } + +// ----------------------------------------------------------------------------- +// CMceSession::IncomingUpdateL +// ----------------------------------------------------------------------------- +// +void CMceSession::IncomingUpdateL( CMceInSession* aInSession, HBufC8* aContent ) + { + MCECLI_DEBUG("CMceSession::IncomingUpdateL, Entry") + TState state = State(); + MCECLI_DEBUG_CLISTATE("state", state ) + state = aInSession->State(); + MCECLI_DEBUG_CLISTATE("update state", state ) + + MMceInSessionObserver* observer = iManager->InSessionObserver(); + if ( !observer ) + { + MCECLI_DEBUG("CMceSession::IncomingUpdateL, no observer. reject") + SendITCEventL( EMceItcRejectSession ); + delete aInSession; + return; + } + + CDesC8Array* headers = NULL; + HBufC8* contentType = NULL; + CDesC8Array* contentHeaders = NULL; + aInSession->GetSIPParams( headers, contentType, contentHeaders ); + + TInt pushs = 0; + + if ( headers ) + { + CleanupStack::PushL( headers );++pushs; + } + + if ( contentType ) + { + CleanupStack::PushL( contentType );++pushs; + } + + if ( contentHeaders ) + { + CleanupStack::PushL( contentHeaders );++pushs; + } + + TMceTransactionDataContainer* container = iManager->TransactionContainer(); + + if ( container ) + { + container->SetHeaders( headers ); + container->SetContentType( contentType ); + container->SetContent( aContent ); + container->SetContentHeaders( contentHeaders ); + CleanupStack::Pop( pushs ); + } + else + { + CleanupStack::PopAndDestroy( pushs ); + } + + iManager->IncomingSessionUpdateL( *aInSession, *this ); + + MCECLI_DEBUG("CMceSession::IncomingUpdateL, this session is now zombie.") + + observer->IncomingUpdate( *this, aInSession, container ); + + if ( container ) + { + container->Clear(); + } + + + MCECLI_DEBUG("CMceSession::IncomingUpdateL, Exit") + + } + + +// ----------------------------------------------------------------------------- +// CMceSession::SetZombie +// ----------------------------------------------------------------------------- +// +void CMceSession::SetZombie( CMceInSession& aInSession ) + { + aInSession.iManager = iManager; + iManager = NULL; + + aInSession.iProfileId = iProfileId; + + aInSession.iSender = iSender; + iSender = NULL; + + aInSession.iReceiver = iReceiver; + iReceiver->ReplaceSession( aInSession ); + iReceiver = NULL; + + aInSession.iFCObserver = iFCObserver; + iFCObserver = NULL; + + } + + +// ----------------------------------------------------------------------------- +// CMceSession::EventReceivedL +// ----------------------------------------------------------------------------- +// +void CMceSession::EventReceivedL( TMceIds& aId, + CMceMsgBase& aMessage, + HBufC8* aContent ) + { + TMceEvent event( aId, &aMessage, aContent ); + EventReceivedL( event ); + } + +// ----------------------------------------------------------------------------- +// CMceSession::ErrorOccuredL +// ----------------------------------------------------------------------------- +// +void CMceSession::ErrorOccuredL( TInt aError ) + { + MCECLI_DEBUG("CMceSession::ErrorOccuredL, Entry") + MCECLI_DEBUG_DVALUE("error", aError ) + + User::LeaveIfError( iManager->SessionObserver() ? KErrNone : KErrArgument ); + FLAT_DATA( iState ) = CMceSession::ETerminated; + + + iManager->SessionObserver()->Failed( *this, aError ); + + TState state = State(); + MCECLI_DEBUG_CLISTATE( "CMceSession::ErrorOccuredL, before exit. state", state ) + MCECLI_DEBUG("CMceSession::ErrorOccuredL, Exit") + } + +// ----------------------------------------------------------------------------- +// CMceSession::FCMessageReceived +// ----------------------------------------------------------------------------- +// +void CMceSession::FCMessageReceived( HBufC8* aMessage ) + { + MCECLI_DEBUG("CMceSession::FCMessageReceived, Entry") + + if ( iFCObserver ) + { + iFCObserver->FCMsgReceived( *this, aMessage ); + } + else + { + delete aMessage; + } + MCECLI_DEBUG("CMceSession::FCMessageReceived, Exit") + } + +// ----------------------------------------------------------------------------- +// CMceSession::FCErrorOccurred +// ----------------------------------------------------------------------------- +// +void CMceSession::FCErrorOccurred( TInt aError ) + { + MCECLI_DEBUG("CMceSession::FCErrorOccurred, Entry") + MCECLI_DEBUG_DVALUE("error", aError ) + + if ( iFCObserver ) + { + iFCObserver->FCMsgErrorOccurred( *this, aError ); + } + + MCECLI_DEBUG("CMceSession::FCErrorOccurred, Exit") + } + +// ----------------------------------------------------------------------------- +// CMceSession::EventReceivedL +// ----------------------------------------------------------------------------- +// +void CMceSession::EventReceivedL( TMceEvent& aEvent ) + { + MCECLI_DEBUG( "CMceSession::EventReceivedL, Entry" ) + TState state = State(); + MCECLI_DEBUG_CLISTATE( "this: state", state ) + MCECLI_DEBUG_DVALUE( "this: id", Id() ) + + User::LeaveIfError( + aEvent.Id().iSessionID == Id() ? KErrNone : KErrGeneral ); + + if ( aEvent.Id().IsSessionId() ) + { + MCECLI_DEBUG("CMceSession::EventReceivedL, for session") + HandleEvent( aEvent ); + } + else + { + MCECLI_DEBUG( "CMceSession::EventReceivedL, for media" ) + TInt j = 0; + TInt status = KMceEventNotConsumed; + while ( status != KMceEventConsumed && j < iMediaStreams.Count() ) + { + CMceMediaStream* stream = iMediaStreams[j]; + status = stream->EventReceivedL( aEvent ); + if ( status == KMceEventUpdate ) + { + MCECLI_DEBUG( "CMceSession::EventReceivedL, \ +update media stream by replacing old version with new one" ) + CMceMsgObject* updateMsg = + static_cast*>( aEvent.Message() ); + CMceMediaStream* updateStream = updateMsg->Object(); + CleanupStack::PushL( updateStream ); + iMediaStreams.Remove( j ); + delete stream; + updateStream->InitializeL( *this, EFalse ); + AddStreamL( updateStream ); + CleanupStack::Pop( updateStream ); + updateStream->Updated(); + status = KMceEventConsumed; + } + j++; + } + + } + MCECLI_DEBUG( "CMceSession::EventReceivedL, Exit" ) + } + +// ----------------------------------------------------------------------------- +// CMceSession::Updated +// ----------------------------------------------------------------------------- +// +void CMceSession::Updated() + { + MMceSessionObserver* observer = iManager->SessionObserver(); + TMceTransactionDataContainer* container = iManager->TransactionContainer(); + + if ( observer ) + { + observer->SessionStateChanged( *this , container); + } + + } + + +// ----------------------------------------------------------------------------- +// CMceSession::SetContainer +// ----------------------------------------------------------------------------- +// +TBool CMceSession::SetContainer( CMceMsgSIPReply& aReply, HBufC8* aContent ) + { + if ( !&aReply ) + { + delete aContent; + return ETrue; + } + TBool contentDeleted( EFalse ); + TMceTransactionDataContainer* container = iManager->TransactionContainer(); + + if ( container ) + { + container->SetStatusCode( aReply.iCode ); + container->SetReasonPhrase( aReply.Reason() ); + container->SetHeaders( aReply.Headers() ); + container->SetContentType( aReply.ContentType() ); + container->SetContent( aContent ); + } + else + { + aReply.Close(); + delete aContent; + contentDeleted = ETrue; + } + return contentDeleted; + } + + +// ----------------------------------------------------------------------------- +// CMceSession::SetContainer +// ----------------------------------------------------------------------------- +// +TBool CMceSession::SetContainer( CMceMsgSIPData& aRequest, HBufC8* aContent ) + { + if ( !&aRequest ) + { + delete aContent; + return ETrue; + } + TBool contentDeleted( EFalse ); + TMceTransactionDataContainer* container = iManager->TransactionContainer(); + + if ( container ) + { + container->SetHeaders( aRequest.Headers() ); + container->SetContentType( aRequest.ContentType() ); + container->SetContent( aContent ); + } + else + { + aRequest.Close(); + delete aContent; + contentDeleted = ETrue; + } + return contentDeleted; + } + + +// ----------------------------------------------------------------------------- +// CMceSession::SetContainer +// ----------------------------------------------------------------------------- +// +void CMceSession::SetContainer( CMceMsgArray& aMsgArray, + HBufC8* aContent ) + { + + if ( !&aMsgArray ) + { + delete aContent; + return; + } + + + for( TInt i = 0; i < aMsgArray.iArray.Count(); i++ ) + { + CMceMsgBase* msg = aMsgArray.iArray[ i ]; + + if ( msg->Type() == EMceItcMsgTypeSIPReply ) + { + if ( SetContainer( static_cast( *msg ), aContent ) ) + { + // Content was deleted + aContent = NULL; + } + } + else if ( msg->Type() == EMceItcMsgTypeSIPData ) + { + if ( SetContainer( static_cast( *msg ), aContent ) ) + { + // Content was deleted + aContent = NULL; + } + } + else if ( msg->Type() == EMceItcMsgTypeSession ) + { + CMceSession* session = + static_cast*>( msg )->Object(); + TRAPD( error, UpdateL( *session ) ); + if ( error != KErrNone ) + { + //TBD + } + delete session; + } + else + { + } + } + } + +// ----------------------------------------------------------------------------- +// CMceSession::HandleEvent +// ----------------------------------------------------------------------------- +// +void CMceSession::HandleEvent( TMceEvent& aEvent ) + { + MCECLI_DEBUG("CMceSession::HandleEvent, Entry") + + if ( aEvent.Action() == EMceItcSessionConnectionStateChanged ) + { + MCECLI_DEBUG("CMceSession::HandleEvent, connection state changed") + FLAT_DATA( iIsConnectionActive ) = + static_cast( aEvent.ActionData() ); + iManager->SessionObserver()->SessionConnectionStateChanged( + *this, + FLAT_DATA( iIsConnectionActive ) ); + return; + } + + if ( aEvent.Action() == EMceItcStateChanged || + aEvent.Action() == EMceItcUpdateFailed ) + { + TMceTransactionDataContainer* container = iManager->TransactionContainer(); + MMceSessionObserver* observer = iManager->SessionObserver(); + HBufC8* content = aEvent.Content(); + + FLAT_DATA( iState ) = + static_cast( aEvent.ActionData() ); + + MCECLI_DEBUG("CMceSession::HandleEvent, session state changed" ) + + if ( aEvent.MessageType() == EMceItcMsgTypeSIPReply ) + { + MCECLI_DEBUG("CMceSession::HandleEvent, caused by sip reply") + CMceMsgSIPReply* reply = + static_cast( aEvent.Message() ); + if ( observer ) + { + SetContainer( *reply, content ); + if ( aEvent.Action() == EMceItcStateChanged ) + { + observer->SessionStateChanged( *this, container ); + } + else + { + MCECLI_DEBUG("CMceSession::HandleEvent, update failed") + observer->UpdateFailed( *this, container ); + } + + if ( container ) + { + container->Clear(); + } + } + else + { + if ( reply ) + { + reply->Close(); + } + delete content; + } + } + else if ( aEvent.MessageType() == EMceItcMsgTypeSIPData ) + { + MCECLI_DEBUG("CMceSession::HandleEvent, caused by sip request") + CMceMsgSIPData* request = + static_cast( aEvent.Message() ); + if ( observer ) + { + SetContainer( *request, content ); + if ( aEvent.Action() == EMceItcStateChanged ) + { + observer->SessionStateChanged( *this, container ); + } + else + { + MCECLI_DEBUG("CMceSession::HandleEvent, update failed") + observer->UpdateFailed( *this, container ); + } + + if ( container ) + { + container->Clear(); + } + } + else + { + if ( request ) + { + request->Close(); + } + delete content; + } + } + else if ( aEvent.MessageType() == EMceItcMsgTypeMessageArray ) + { + MCECLI_DEBUG("CMceSession::HandleEvent, caused by sip request/reply") + + CMceMsgArray* msgArray = + static_cast*>( aEvent.Message() ); + if ( observer ) + { + if ( aEvent.Action() == EMceItcStateChanged ) + { + SetContainer( *msgArray, content ); + observer->SessionStateChanged( *this, container ); + } + else + { + if ( aEvent.Id().iStatus != KMceErrOldSchool ) + { + SetContainer( *msgArray, content ); + } + UpdateFailed( aEvent, container ); + } + + if ( container ) + { + container->Clear(); + } + } + else + { + if ( msgArray ) + { + msgArray->Close(); + } + delete content; + } + } + else + { + if ( aEvent.MessageType() == EMceItcMsgTypeSession ) + { + MCECLI_DEBUG("CMceSession::HandleEvent, caused by session update") + + CMceMsgObject* updateMsg = + static_cast*>( aEvent.Message() ); + CMceSession* session = updateMsg->Object(); + TRAPD( error, UpdateL( *session ) ); + if ( error != KErrNone ) + { + //TBD + } + delete session; + } + if ( aEvent.Action() == EMceItcUpdateFailed && observer ) + { + observer->UpdateFailed( *this, container ); + } + else + { + Updated(); + } + } + MCECLI_DEBUG("CMceSession::HandleEvent, Exit") + return; + } + + // Handling of Request / Responses Received within a Session + + if ( aEvent.Action() == EMceItcRequestReceived ) + + { + TRAPD( error, HandleEventRequestReceivedL (aEvent)); + if ( error != KErrNone ) + { + //TBD + } + } + + if ( aEvent.Action() == EMceItcResponseReceived ) + { + TRAPD( error, HandleEventResponseReceivedL (aEvent)); + if ( error != KErrNone ) + { + //TBD + } + + } + + MCECLI_DEBUG("CMceSession::HandleEvent, Exit") + return; + } + +// ----------------------------------------------------------------------------- +// CMceSession::HandleEventRequestReceivedL +// ----------------------------------------------------------------------------- +// +void CMceSession::HandleEventRequestReceivedL( TMceEvent& aEvent ) + { + MCECLI_DEBUG("CMceSession::HandleEventRequestReceivedL, Entry ") + + TMceTransactionDataContainer* container = iManager->TransactionContainer(); + HBufC8* content = aEvent.Content(); + + MMceInTransactionObserver* observer = iManager->InTransactionObserver(); + + if ( aEvent.MessageType() == EMceItcMsgTypeSIPRequest ) + { + + if ( observer ) + { + if ( aEvent.Action() == EMceItcRequestReceived ) + { + TMceTransactionId TransactonID; + TransactonID = aEvent.Id().iTransactionID; + + CMceMsgSIPRequest* msgRequest = + static_cast( aEvent.Message() ); + + SetContainer( *msgRequest, content ); + + observer->IncomingRequest( *msgRequest->RequestMethod(), + *this, TransactonID, container ); + } + + if ( container ) + { + container->Clear(); + } + } + + else + { + // Reject the Transaction with 501 Error Response + // Saying Its not implemented. + const TUint KMceSipNotImplemented = 501; + _LIT8( KNotImplemented ,"Not Implemented"); + + HBufC8* reason = KNotImplemented().AllocLC(); + SendResponseL( aEvent.Id().iTransactionID, + *reason, + KMceSipNotImplemented, + NULL, + NULL, + NULL); + + CleanupStack::PopAndDestroy( reason ); + + delete content; + } + } + + MCECLI_DEBUG("CMceSession::HandleEventRequestReceivedL, Exit ") + } + +// ----------------------------------------------------------------------------- +// CMceSession::HandleEventResponseReceivedL +// ----------------------------------------------------------------------------- +// +void CMceSession::HandleEventResponseReceivedL( TMceEvent& aEvent ) + { + MCECLI_DEBUG("CMceSession::HandleEventResponseReceivedL, Entry" ) + TMceTransactionDataContainer* container = iManager->TransactionContainer(); + HBufC8* content = aEvent.Content(); + + if ( aEvent.MessageType() == EMceItcMsgTypeSIPReply ) + { + MMceTransactionObserver* observer = iManager->TransactionObserver(); + + CMceMsgSIPReply* msgReply = + static_cast( aEvent.Message() ); + + if ( observer ) + { + SetContainer( *msgReply, content ); + TMceTransactionId TransactonID; + TransactonID = aEvent.Id().iTransactionID; + observer->TransactionResponse(*this, TransactonID, container ); + + if ( container ) + { + container->Clear(); + } + } + else + { + if ( msgReply ) + { + msgReply->Close(); + } + delete content; + } + } + + MCECLI_DEBUG("CMceSession::HandleEventResponseReceivedL, Exit" ) + } + +// ----------------------------------------------------------------------------- +// CMceSession::UpdateFailed +// ----------------------------------------------------------------------------- +// +void CMceSession::UpdateFailed( TMceEvent& aEvent, + TMceTransactionDataContainer* aContainer ) + { + MMceSessionObserver* observer = iManager->SessionObserver(); + HBufC8* content = aEvent.Content(); + + if ( aEvent.Id().iStatus == KMceErrOldSchool ) + { + TRAPD( leaveErr, SendUpdateL( content ) ); + if ( leaveErr == KMceErrOldSchool ) + { + observer->UpdateFailed( *this, aContainer ); + } + } + else + { + observer->UpdateFailed( *this, aContainer ); + } + } + +// ----------------------------------------------------------------------------- +// CMceSession::UpdateL +// ----------------------------------------------------------------------------- +// +void CMceSession::UpdateL( CMceSession& aSession ) + { + MCECLI_DEBUG("CMceSession::UpdateL(received), Entry") + MCECLI_DEBUG("CMceSession::UpdateL(received), updating session data") + + iFlatData->UpdateFlatL( *aSession.iFlatData ); + + MCECLI_DEBUG("CMceSession::UpdateL(received), \ +removing old streams and bundles") + iMediaStreams.ResetAndDestroy(); + iBundles.ResetAndDestroy(); + + while( aSession.iMediaStreams.Count() > 0 ) + { + CMceMediaStream* stream = aSession.iMediaStreams[0]; + aSession.iMediaStreams.Remove( 0 ); + CleanupStack::PushL( stream ); + CMceSession::AddStreamL( stream ); + CleanupStack::Pop( stream ); + MCECLI_DEBUG("CMceSession::UpdateL(received), added updated stream") + MCECLI_DEBUG_DVALUE("id", stream->Id().iId ) + MCECLI_DEBUG_DVALUE("enabled", stream->IsEnabled() ) + CMceMediaStream::TState state = stream->State(); + MCECLI_DEBUG_MEDIASTATE("state", state ) + } + + while( aSession.iBundles.Count() > 0 ) + { + CMceStreamBundle* bundle = aSession.iBundles[0]; + aSession.iBundles.Remove( 0 ); + CleanupStack::PushL( bundle ); + AddBundleL( bundle ); + CleanupStack::Pop( bundle ); + MCECLI_DEBUG("CMceSession::UpdateL(received), added updated bundle") + } + + InitializeL(); + + MCECLI_DEBUG("CMceSession::UpdateL(received), Exit") + } + +// ----------------------------------------------------------------------------- +// CMceSession::SendITCEventL +// ----------------------------------------------------------------------------- +// +void CMceSession::SendITCEventL( TUint8 aITCFunction ) + { + __ASSERT_ALWAYS( iSender, User::Leave( KErrGeneral ) ); + + TMceIds ids; + PrepareForITC( ids ); + ids.iState = State(); + iSender->SendL( ids, static_cast( aITCFunction ) ); + //update the state + FLAT_DATA( iState ) = static_cast( ids.iState ); + } + +// ----------------------------------------------------------------------------- +// CMceSession::SendRequestL +// ----------------------------------------------------------------------------- +// +EXPORT_C TMceTransactionId CMceSession::SendRequestL( const TDesC8& aMethod, + CDesC8Array* aHeaders, + HBufC8* aContentType, + HBufC8* aContent ) + { + MCECLI_DEBUG("CMceSession::SendRequestL, Entry") + TState state = State(); + MCECLI_DEBUG_CLISTATE( "state", state ) + + User::LeaveIfError( IsZombie() ? KErrArgument : KErrNone ); + + TCleanupItem sipParamsCleanup( SIPParamsCleanup, this ); + CleanupStack::PushL( sipParamsCleanup ); + + TMceIds ids; + PrepareForITC( ids ); + ids.iState = State(); + + HBufC8* method = aMethod.AllocLC(); + + CMceMsgSIPRequest* msg = + new (ELeave) CMceMsgSIPRequest( *method, *aHeaders, *aContentType ); + CleanupStack::PushL( msg ); + // Don't pass aContent's ownership. Delete it when this function can't leave + // anymore + iSender->SendL( ids, EMceItcRequestSend, *msg, aContent, EFalse ); + CleanupStack::PopAndDestroy( msg ); + CleanupStack::PopAndDestroy( method ); + + FLAT_DATA( iState ) = static_cast( ids.iState ); + + if ( ids.iStatus != KErrNone ) + { + MCECLI_DEBUG("CMceSession::SendInfoRequestL, info failed. rollback") + TMceIds ids2; + SynchronizeL( ids2 ); + state = State(); + MCECLI_DEBUG_CLISTATE( + "CMceSession::SendInfoRequestL, after ITC, state", state ) + CleanupStack::Pop(); // sipParamsCleanup + + MMceTransactionObserver* observer = iManager->TransactionObserver(); + if ( observer ) + { + observer->TransactionFailed( *this, ids.iTransactionID, ids.iStatus ); + } + } + else + { + CleanupStack::Pop(); // sipParamsCleanup + } + + delete aHeaders; + delete aContentType; + delete aContent; + + MCECLI_DEBUG("CMceSession::SendRequestL, Exit") + return ids.iTransactionID; + } + +// ----------------------------------------------------------------------------- +// CMceSession::SendResponseL +// ----------------------------------------------------------------------------- +// +EXPORT_C void CMceSession::SendResponseL( TMceTransactionId aTransactionId, + const TDesC8& aReason, + TUint32 aCode, + CDesC8Array* aHeaders, + HBufC8* aContentType, + HBufC8* aContent ) + { + MCECLI_DEBUG("CMceSession::SendResponseL, Entry") + TState state = State(); + MCECLI_DEBUG_CLISTATE( "state", state ) + + User::LeaveIfError( State() != CMceSession::EEstablished ); + + TCleanupItem sipParamsCleanup( SIPParamsCleanup, this ); + CleanupStack::PushL( sipParamsCleanup ); + + TMceIds ids; + PrepareForITC( ids ); + ids.iState = State(); + ids.iTransactionID = aTransactionId; + + HBufC8* reason = aReason.AllocLC(); + CMceMsgSIPReply* msg = new ( ELeave ) CMceMsgSIPReply( aTransactionId, + *reason, + aCode, + *aHeaders, + *aContentType ); + CleanupStack::PushL( msg ); + // Don't pass aContent's ownership. Delete it when this function can't leave + // anymore + iSender->SendL( ids, EMceItcReplySend, *msg, aContent, EFalse ); + CleanupStack::PopAndDestroy( msg ); + CleanupStack::PopAndDestroy( reason ); + + FLAT_DATA( iState ) = static_cast( ids.iState ); + MCECLI_DEBUG_CLISTATE( "CMceSession::SendResponseL, after ITC, state", state ) + + if ( ids.iStatus != KErrNone ) + { + MCECLI_DEBUG( "CMceSession::SendInfoRequestL, info failed. rollback" ) + + TMceIds ids2; + SynchronizeL( ids2 ); + state = State(); + MCECLI_DEBUG_CLISTATE( + "CMceSession::SendInfoRequestL, after ITC, state", state ) + + CleanupStack::Pop(); // sipParamsCleanup + + MMceTransactionObserver* observer = iManager->TransactionObserver(); + if ( observer ) + { + // Pass the proper Error Event to the Client.. + observer->TransactionFailed( *this, ids.iTransactionID, KErrNone ); + } + } + else + { + CleanupStack::Pop(); // sipParamsCleanup + } + + delete aHeaders; + delete aContentType; + delete aContent; + + MCECLI_DEBUG("CMceSession::SendInfoL, Exit") + } + +// End of File