multimediacommsengine/mmcesrv/mmceserver/src/mcecssubsession.cpp
changeset 0 1bce908db942
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multimediacommsengine/mmcesrv/mmceserver/src/mcecssubsession.cpp	Tue Feb 02 01:04:58 2010 +0200
@@ -0,0 +1,1242 @@
+/*
+* 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 <sipdialogassocbase.h>
+#include <sipdialog.h>
+#include <sipcontactheader.h>
+#include <sipprofile.h>
+#include "mceserver.pan"
+
+#include "mcecssubsession.h"
+#include "mcesipmanager.h"
+#include "mcecssessionimplementation.h"
+#include "mcecssession.h"
+#include "mceservercore.h"
+#include "mcesipconnection.h"
+#include "mcecssubsessionreceiver.h"
+#include "mcecsserveritc.h"
+#include "mcecomsession.h"
+#include "mcecommediastream.h"
+#include "mcecommediastream.h"
+#include "mcecomaudiocodec.h"
+#include "mcecommediasink.h"
+#include "mcecommediasource.h"
+#include "mceserial.h"
+#include "mcesrvlogs.h"
+#include "mcemessagedispatcher.h"
+
+
+const TInt KMaxAddressLength = 256;    
+    
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::CMceCsSubSession
+// -----------------------------------------------------------------------------
+//
+
+CMceCsSubSession::CMceCsSubSession ( TMceCsSessionType aType,
+                                     CMceCsSession& aClientSession,
+                                     CMceSipConnection& aSIPConnection )
+: iType( EUnknown ),
+  iClientType( aType ),
+  iDialogId( KMceNotAssigned ),
+  iClientExists( EFalse ),
+  iCurrentDialog( NULL ),
+  iClientSession (NULL ),
+  iSIPConnection( aSIPConnection ),
+  iServerCore( aClientSession.ServerCore() ),
+  iProfile( NULL )
+  	{
+	}
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::CMceCsSubSession
+// -----------------------------------------------------------------------------
+//
+CMceCsSubSession::CMceCsSubSession ( TMceCsSessionType aType,
+                                     CMceCsSession& aClientSession,
+                                     CMceSipConnection& aSIPConnection,
+                                     CSIPProfile& aProfile )
+: iType( EUnknown ),
+  iClientType( aType ),
+  iDialogId( KMceNotAssigned ),
+  iClientExists( EFalse ),
+  iCurrentDialog( NULL ),
+  iClientSession (NULL ),
+  iSIPConnection( aSIPConnection ),
+  iServerCore( aClientSession.ServerCore() ),
+  iProfile( &aProfile )
+  	{
+	}
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::ConstructL
+// -----------------------------------------------------------------------------
+//
+void CMceCsSubSession::ConstructL ( CMceCsSession& aClientSession )
+	{
+    MCESRV_DEBUG("CMceCsSubSession::ConstructL, Entry")
+	
+    SetSessionReceiver( aClientSession.CreateSubSessionReceiverL() );
+    SetClient( aClientSession.Implementation() );
+    
+    MCESRV_DEBUG("CMceCsSubSession::ConstructL, Exit")
+	}
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::~CMceCsSubSession
+// -----------------------------------------------------------------------------
+//
+CMceCsSubSession::~CMceCsSubSession()
+	{
+    MCESRV_DEBUG("CMceCsSubSession::~CMceCsSubSession, Entry")
+		
+    TInt index = iPendingTransactions.Find( iInitialInvite );
+    if ( index != KErrNotFound )
+        {
+        iPendingTransactions.Remove( index );
+        }
+    index = iPendingTransactions.Find( iResponse );
+    if ( index != KErrNotFound )
+        {
+        iPendingTransactions.Remove( index );
+        }
+    
+    iPendingTransactions.ResetAndDestroy();
+    iPendingTransactions.Close();
+    
+    iPendingReceivedRequests.ResetAndDestroy();
+    
+    if ( iInitialInvite != iResponse )
+        {
+        delete iInitialInvite;
+        }
+        
+    iInitialInvite = NULL;
+    delete iReceiver;
+    delete iDialog;
+    delete iResponse;
+    delete iClientContent;
+    Manager().UnRegisterSubSession( *this );
+    
+    delete iAutoEventMsg;
+    delete iAutoEventIds;
+    delete iAutoEvent;
+    
+    MCESRV_DEBUG("CMceCsSubSession::~CMceCsSubSession, Exit")
+	}
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::Type
+// -----------------------------------------------------------------------------
+//
+CMceCsSubSession::TType CMceCsSubSession::Type() const
+    {
+    return iType;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::ClientType
+// -----------------------------------------------------------------------------
+//
+TMceCsSessionType CMceCsSubSession::ClientType() const
+    {
+    return iClientType;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::ClientSession
+// -----------------------------------------------------------------------------
+//
+CMceCsSessionImplementation& CMceCsSubSession::Client() const
+    {
+    return *iClientSession;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::SetClient
+// -----------------------------------------------------------------------------
+//
+void CMceCsSubSession::SetClient( CMceCsSessionImplementation& aClient )
+    {
+    iClientSession = &aClient;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::SetClient
+// -----------------------------------------------------------------------------
+//
+void CMceCsSubSession::SetSessionReceiver( 
+                                  CMceCsSubSessionReceiver* aSessionReceiver )
+    {
+    delete iReceiver;
+    iReceiver = aSessionReceiver;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::IsOrphan
+// -----------------------------------------------------------------------------
+//
+TBool CMceCsSubSession::IsOrphan()   
+    {
+    return !iReceiver;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::HasInitialInviteTransactionBeenCompleted()
+// -----------------------------------------------------------------------------
+//
+TBool CMceCsSubSession::HasInitialInviteTransactionBeenCompleted() const
+    {
+    TBool completed( ETrue );
+    if ( iInitialInvite )
+        {
+        CSIPTransactionBase::TState state( CSIPTransactionBase::ETerminated  );
+        TRAP_IGNORE( ( state = iInitialInvite->StateL() ) )
+        completed = ( state == CSIPTransactionBase::ECompleted || 
+                      state == CSIPTransactionBase::ETerminated );
+        }
+    return completed; 
+    }
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::SIPConnection
+// -----------------------------------------------------------------------------
+//
+CMceSipConnection& CMceCsSubSession::SIPConnection() const
+    {
+    return iSIPConnection;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::DialogId
+// -----------------------------------------------------------------------------
+//
+TUint32 CMceCsSubSession::DialogId() const
+    {
+    return iDialogId;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::Manager
+// -----------------------------------------------------------------------------
+//
+CMceSipManager& CMceCsSubSession::Manager() const
+    {
+    return ServerCore().Manager();
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::ServerCore
+// -----------------------------------------------------------------------------
+//
+CMceServerCore& CMceCsSubSession::ServerCore() const
+    {
+    return iServerCore;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::FCSession
+// -----------------------------------------------------------------------------
+//
+const CFCSession* CMceCsSubSession::FCSession() const
+	{
+	return iFCSession;
+	}
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::Request
+// -----------------------------------------------------------------------------
+//
+CSIPServerTransaction& CMceCsSubSession::Request() const
+    {
+    if ( iAutoEventEnabled && iAutoEventAssociatedRequest )
+        {
+        TInt index = iPendingReceivedRequests.Find( iAutoEventAssociatedRequest );
+        if ( index != KErrNotFound )
+            {
+            return *iAutoEventAssociatedRequest;
+            }
+        }
+    return *CURRENT_REQUEST();
+    }
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::InitialRequest
+// -----------------------------------------------------------------------------
+//
+CSIPServerTransaction& CMceCsSubSession::InitialRequest() const
+    {
+    return *FIRST_REQUEST();
+    }
+    
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::PopRequest
+// -----------------------------------------------------------------------------
+//
+CSIPServerTransaction* CMceCsSubSession::PopRequest()
+    {
+    CSIPServerTransaction* request = NULL;
+    
+    request = CURRENT_REQUEST();
+    if ( request )
+        {
+        iPendingReceivedRequests.Remove( CURRENT_REQUEST_IND );
+        }
+    return request;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::Response
+// -----------------------------------------------------------------------------
+//
+CSIPClientTransaction& CMceCsSubSession::Response() const
+    {
+    return *iResponse;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::PopResponse
+// -----------------------------------------------------------------------------
+//
+CSIPClientTransaction* CMceCsSubSession::PopResponse()
+    {
+    CSIPClientTransaction* response = iResponse;
+    if ( response && MceSip::TrxCompleted( *response ) )
+        {
+        iResponse = NULL;
+        }
+    else
+        {
+        response = NULL;
+        }
+        
+    return response;
+    
+    }
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::SetDialog
+// -----------------------------------------------------------------------------
+//
+void CMceCsSubSession::SetDialog( CMceCsSubSession::TType aType, 
+                                  CSIPDialogAssocBase* aDialog, 
+                                  TUint32 aDialogId )
+    {
+    __ASSERT_ALWAYS( !iDialog, User::Panic( KMceServerPanic, KErrArgument ) );
+    iType = aType;
+    iDialogId = aDialogId;
+    iDialog = aDialog;
+    }
+
+    
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::SetPendingTransactionL
+// -----------------------------------------------------------------------------
+//
+void CMceCsSubSession::SetPendingTransactionL( 
+                                    CSIPClientTransaction* aTransaction )
+    {
+    __ASSERT_ALWAYS( aTransaction, User::Leave( KErrArgument ) );
+    __ASSERT_ALWAYS( iPendingTransactions.Find( aTransaction ) == KErrNotFound, 
+        User::Leave( KErrArgument ) );
+    
+    iPendingTransactions.AppendL( aTransaction );
+    
+    if ( Type() == EOutSession && 
+         aTransaction->Type() == SIPStrings::StringF( SipStrConsts::EInvite ) )
+        {
+        iType = EOutSIPSession;
+        iInitialInvite = aTransaction;
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::Consumes
+// -----------------------------------------------------------------------------
+//
+TBool CMceCsSubSession::Consumes( CSIPTransactionBase& aTransaction )
+    {
+    TBool isPending = EFalse;
+
+    if ( aTransaction.IsSIPClientTransaction() )
+        {
+        CSIPClientTransaction& transaction = 
+            static_cast<CSIPClientTransaction&>( aTransaction );
+        isPending = iPendingTransactions.Find( &transaction ) >= 0;
+        }
+    else
+        {
+        CSIPServerTransaction& transaction = 
+            static_cast<CSIPServerTransaction&>( aTransaction );
+        isPending = iPendingReceivedRequests.Find( &transaction ) >= 0; 
+        }
+        
+    return isPending;    
+    }
+   
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::AcceptDialogTransaction
+// -----------------------------------------------------------------------------
+//
+TBool CMceCsSubSession::AcceptDialogTransaction( 
+                                    CSIPServerTransaction& /*aTransaction*/ )
+    {        
+    return ETrue;    
+    }
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::AcceptStandAloneTransaction
+// -----------------------------------------------------------------------------
+//
+TBool CMceCsSubSession::AcceptStandAloneTransaction( 
+                                    CSIPServerTransaction& /*aTransaction*/ )
+    {        
+    return ETrue;    
+    }
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::Consumes
+// -----------------------------------------------------------------------------
+//
+TBool CMceCsSubSession::Consumes( CSIPDialog& aDialog, 
+                                  CSIPServerTransaction& aTransaction,
+                                  TBool& aAssociatesWithDialog )
+    {
+    aAssociatesWithDialog = ( Dialog()->Dialog() == aDialog );
+    return aAssociatesWithDialog && ( Consumes( aTransaction ) ||
+           AcceptMethod( MceSip::Method( aTransaction ) ) );
+    }
+    
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::DoServiceL
+// -----------------------------------------------------------------------------
+//
+HBufC8* CMceCsSubSession::DoServiceL( TMceIds& /*aIds*/, 
+                                      TMceItcFunctions /*aFunction*/ )
+    {
+    MCESRV_DEBUG("CMceCsSubSession::DoServiceL( no message ), NOT SUPPORTED")
+    User::Leave( KErrNotSupported );
+    return NULL;
+    }
+    
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::DoServiceL
+// -----------------------------------------------------------------------------
+//
+void CMceCsSubSession::DoServiceL( TMceIds& /*aIds*/, 
+                                 TMceItcFunctions /*aFunction*/, 
+                                 const TDesC8& /*aMessage*/ )
+    {
+    MCESRV_DEBUG("CMceCsSubSession::DoServiceL( data ), NOT SUPPORTED")
+    User::Leave( KErrNotSupported );
+    }
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::DoServiceL
+// -----------------------------------------------------------------------------
+//
+void CMceCsSubSession::DoServiceL( TMceIds& /*aIds*/, 
+                                 TMceItcFunctions /*aFunction*/, 
+                                 TPtr8& /*aMessage*/ )
+    {
+    MCESRV_DEBUG("CMceCsSubSession::DoServiceL( data ), NOT SUPPORTED")
+    User::Leave( KErrNotSupported );
+    }
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::DoServiceL
+// -----------------------------------------------------------------------------
+//
+void CMceCsSubSession::DoServiceL( TMceIds& /*aIds*/, 
+                                 TMceItcFunctions /*aFunction*/, 
+                                 CMceMsgBase& /*aMessage*/ )
+    {
+    MCESRV_DEBUG("CMceCsSubSession::DoServiceL( message ), NOT SUPPORTED")
+    User::Leave( KErrNotSupported );
+    }
+    
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::PendingTransactions
+// -----------------------------------------------------------------------------
+//
+const RPointerArray<CSIPClientTransaction>& 
+    CMceCsSubSession::PendingTransactions()
+    {
+    return iPendingTransactions;
+    }
+    
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::PendingReceivedRequests 
+// -----------------------------------------------------------------------------
+//
+const RPointerArray<CSIPServerTransaction>&
+    CMceCsSubSession::PendingReceivedRequests()
+    {
+    return iPendingReceivedRequests;
+    }
+    
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::PendingTransaction
+// -----------------------------------------------------------------------------
+//
+CSIPClientTransaction* CMceCsSubSession::PendingTransaction( RStringF aType )
+    {
+    CSIPClientTransaction* trx = NULL;
+    TInt index = PendingTransactions().Count()-1;
+    
+    while( !trx && index >= 0 )
+        {
+        trx = PendingTransactions()[ index-- ];
+        TBool isMatch = trx->Type() == aType;
+        trx = isMatch ? trx : NULL;
+        }
+        
+    return trx;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::RegisterDialogAssoc
+// -----------------------------------------------------------------------------
+//
+void CMceCsSubSession::RegisterDialogAssoc( CSIPDialogAssocBase& aDialogAssoc )
+    {
+    iCurrentDialog = &aDialogAssoc;
+    }
+    
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::ResponseReceivedWithinDialog
+// -----------------------------------------------------------------------------
+//
+void CMceCsSubSession::ResponseReceivedWithinDialog( CSIPClientTransaction& aTransaction,
+                                                  	 CSIPDialogAssocBase& aDialogAssoc )
+    {
+    RegisterDialogAssoc( aDialogAssoc );
+    DialogResponseReceived( aTransaction );
+    }
+    
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::DialogRequestReceived
+// -----------------------------------------------------------------------------
+//
+TBool CMceCsSubSession::DialogRequestReceived( 
+                                        CSIPServerTransaction* aTransaction, 
+                                        CSIPDialog& aDialog )
+    {
+    RemoveCompletedRequests();
+    TBool consumed = ETrue;
+    
+    CSIPServerTransaction* firstRequest = FIRST_REQUEST();
+    
+    MCESRV_DEBUG("CMceCsSubSession::DialogRequestReceived, Entry")
+    if ( !AcceptDialogTransaction( *aTransaction ) )
+        {
+        consumed = EFalse;
+        }
+    else
+        {
+        MCESRV_DEBUG("no pending request")
+        
+        consumed = iPendingReceivedRequests.Append( aTransaction ) == KErrNone;
+        if ( consumed )
+            {
+            RequestReceived( ETrue, aDialog );
+            }
+        }
+    
+    MCESRV_DEBUG("CMceCsSubSession::DialogRequestReceived, Exit")
+    return consumed;    
+    }
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::SetResponse
+// -----------------------------------------------------------------------------
+//
+void CMceCsSubSession::SetResponse( CSIPClientTransaction& aTransaction )
+    {
+    
+    if ( iResponse && 
+         iPendingTransactions.Find( iResponse ) < 0 )
+        {
+        iInitialInvite = iResponse == iInitialInvite ? NULL : iInitialInvite;
+        delete iResponse;
+        iResponse = NULL;
+        }
+
+    iResponse = &aTransaction;
+    
+    }
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::RemovePendingTrx
+// -----------------------------------------------------------------------------
+//
+TBool CMceCsSubSession::RemovePendingTrx( 
+                                        CSIPClientTransaction& aTransaction )
+    {
+    TBool removed = EFalse;
+    
+    if ( iInitialInvite ? !( *iInitialInvite == aTransaction ) : ETrue )
+        {
+        TInt index = iPendingTransactions.Find( &aTransaction );
+        iPendingTransactions.Remove( index );
+        removed = ETrue;
+        }
+        
+    return removed;    
+    }
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::RemovePendingCompletedTrx
+// -----------------------------------------------------------------------------
+//
+TBool CMceCsSubSession::RemovePendingCompletedTrx( 
+                                        CSIPClientTransaction& aTransaction )
+    {
+    TBool removed = EFalse;
+    
+    TBool trxCompleted = MceSip::TrxCompleted( aTransaction );
+    
+    if ( trxCompleted )
+        {
+        RemovePendingTrx( aTransaction );
+        }
+        
+    return removed;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::RemoveCompletedRequests
+// -----------------------------------------------------------------------------
+//
+void CMceCsSubSession::RemoveCompletedRequests( TBool aAll )
+    {
+    TInt ind = iPendingReceivedRequests.Count() - 1;
+    while ( ind >= 0 )
+        {
+        CSIPServerTransaction* transaction = iPendingReceivedRequests[ ind ];
+        if ( MceSip::TrxCompleted( *transaction ) )
+            {
+            // Don't remove the incoming invite until ACK has been received
+            if ( MceSip::TrxType( *transaction ) != SipStrConsts::EInvite || aAll )
+            	{
+            	iPendingReceivedRequests.Remove( ind );
+            	delete transaction;
+            	}
+            }
+        ind--;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::InitializeIncomingDialogL
+// -----------------------------------------------------------------------------
+//
+void CMceCsSubSession::InitializeIncomingDialogL( 
+                                        CSIPServerTransaction* aTransaction )
+    {
+    MCESRV_DEBUG("CMceCsSubSession::InitializeIncomingDialogL, Entry")
+    __ASSERT_ALWAYS( !CURRENT_REQUEST(), User::Leave( KErrArgument ) );
+    DoInitializeIncomingDialogL( *aTransaction );
+    iPendingReceivedRequests.AppendL( aTransaction );
+
+    RequestReceived( EFalse, Dialog()->Dialog() );
+        
+    MCESRV_DEBUG("CMceCsSubSession::InitializeIncomingDialogL, Exit")
+    }
+    
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::DialogResponseReceived
+// -----------------------------------------------------------------------------
+//
+void CMceCsSubSession::DialogResponseReceived( 
+                                        CSIPClientTransaction& aTransaction )
+    {
+    MCESRV_DEBUG("CMceCsSubSession::DialogResponseReceived, Entry")
+    SetResponse( aTransaction );
+    switch ( MceSip::ResponseType( aTransaction ) )
+        {
+        case E1XX:
+            {
+            ProvisionalResponseReceived();
+            break;
+            }
+        case E2XX:
+            {
+            ResponseReceived();
+            break;
+            }
+        case E3XX:
+            {
+            RedirectionResponseReceived();
+            break;
+            }
+        case E4XX:
+        case E5XX:
+        case E6XX:
+        default:
+            {
+            ErrorResponseReceived();
+            break;
+            }
+        }
+        
+    RemovePendingCompletedTrx( aTransaction );
+    MCESRV_DEBUG("CMceCsSubSession::DialogResponseReceived, Exit")
+    }
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::MessageRequestReceived
+// -----------------------------------------------------------------------------
+//
+TBool CMceCsSubSession::MessageRequestReceived( 
+                                        CSIPServerTransaction* aTransaction )
+    {
+    MCESRV_DEBUG("CMceCsSubSession::MessageRequestReceived, Entry")
+    TBool consumed = AcceptStandAloneTransaction( *aTransaction );
+    RemoveCompletedRequests();
+    if ( consumed )
+        {
+        consumed = iPendingReceivedRequests.Append( aTransaction ) == KErrNone;
+        if ( consumed )
+            {
+            StandAloneRequestReceived();
+            }
+        }
+    MCESRV_DEBUG("CMceCsSubSession::MessageRequestReceived, Exit")
+    return consumed;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::MessageResponseReceived
+// -----------------------------------------------------------------------------
+//
+void CMceCsSubSession::MessageResponseReceived( 
+                                        CSIPClientTransaction& aTransaction )
+    {
+    MCESRV_DEBUG("CMceCsSubSession::MessageResponseReceived, Entry")
+    
+    SetResponse( aTransaction );
+    
+    StandAloneResponseReceived( MceSip::ResponseType( aTransaction ) );
+    
+    RemovePendingCompletedTrx( aTransaction );
+    
+    MCESRV_DEBUG("CMceCsSubSession::MessageResponseReceived, Exit")
+    }
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::InviteCompleted
+// -----------------------------------------------------------------------------
+//
+void CMceCsSubSession::InviteCompleted( CSIPClientTransaction& aTransaction )
+    {
+    MCESRV_DEBUG("CMceCsSubSession::InviteCompleted, Entry")
+    
+    TInt index = iPendingTransactions.Find( &aTransaction );
+    if ( index != KErrNotFound )
+        {
+        iPendingTransactions.Remove( index );
+        if ( iInitialInvite != iResponse )
+            {
+            delete iInitialInvite;
+            iInitialInvite = NULL;
+            }
+        }
+    else
+        {
+        MCESRV_DEBUG("InviteCompleted: NO PENDING TRANSACTION")
+        }
+        
+    MCESRV_DEBUG("CMceCsSubSession::InviteCompleted, Exit")
+    }
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::ErrorOccured
+// -----------------------------------------------------------------------------
+//
+void CMceCsSubSession::ErrorOccured( TInt aError, 
+                                     CSIPTransactionBase& aTransaction )
+    {
+    MCESRV_DEBUG("CMceCsSubSession::ErrorOccured, Entry")
+    MCESRV_DEBUG_DVALUE("ERROR", aError )
+
+    if ( aTransaction.IsSIPClientTransaction() )
+        {
+        CSIPClientTransaction& clientTransaction = 
+            static_cast<CSIPClientTransaction&>( aTransaction );
+        SetResponse( clientTransaction );
+        DoErrorOccured( aError, clientTransaction );
+        RemovePendingCompletedTrx( clientTransaction );
+        }
+    else
+        {
+        DoErrorOccured( aError, aTransaction );
+        }
+        
+    MCESRV_DEBUG("CMceCsSubSession::ErrorOccured, Exit")
+    }
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::Dialog
+// -----------------------------------------------------------------------------
+//
+CSIPDialogAssocBase* CMceCsSubSession::Dialog() const
+    {
+    return iDialog;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::ServiceL
+// -----------------------------------------------------------------------------
+//
+void CMceCsSubSession::ServiceL( TMceIds& aIds, 
+                                 TMceItcFunctions aFunction, 
+								 const RMessage2& aMessage)
+    {
+    MCESRV_DEBUG("CMceCsSubSession::ServiceL, Entry")
+    MCESRV_DEBUG_EVENT("ITC", aFunction )
+    
+    User::LeaveIfNull( iReceiver );
+        
+    switch (aFunction)
+		{
+        case EMceItcClientReadyToReceive: // Asynchronous. Do not complete yet.
+        	{
+            ClientReadyToReceiveL (aMessage); 
+            return;  
+			}
+        case EMceItcClientCancelReceive:
+        	{
+            CancelClientReceiveL ();
+            break;		    
+        	} 
+        case EMceItcReceive:
+        	{
+            ReceiveL (aMessage);
+            break;		    
+        	} 
+        default: 
+        	{
+        	DoServiceL(aIds, aFunction, aMessage );
+        	}
+        }
+	iReceiver->ITC().WriteL(aMessage, aIds);
+    iReceiver->ITC().Complete(aMessage, KErrNone);
+    
+    MCESRV_DEBUG("CMceCsSubSession::ServiceL, Exit")
+    }
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::DoServiceL
+// -----------------------------------------------------------------------------
+//
+void CMceCsSubSession::DoServiceL( TMceIds& aIds, 
+                                   TMceItcFunctions aFunction, 
+								   const RMessage2& aMessage )
+    {
+    MCESRV_DEBUG("CMceCsSubSession::DoServiceL, Entry")
+    MCESRV_DEBUG_IDS("IDS", aIds )
+
+    // Clean completed requests
+    RemoveCompletedRequests();
+    
+    TMceMessageDispatcher<CMceCsSubSession> dispatcher( *this, iReceiver->ITC() );
+    
+    dispatcher.DispatchL( aIds, aFunction, aMessage );
+        
+    MCESRV_DEBUG("CMceCsSubSession::DoServiceL, Exit")
+    }
+    
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::SendErrorToClient
+// -----------------------------------------------------------------------------
+//
+TInt CMceCsSubSession::SendErrorToClient( TMceIds& aIds, TInt aError )
+    {
+    MCESRV_DEBUG("CMceCsSubSession::SendErrorToClient, Entry")
+    MCESRV_DEBUG_DVALUE("error", aError )
+    
+    TInt status = KErrNone;
+    if ( !IsOrphan() )
+        {
+        TMceIds ids = iReceiver->Ids();
+        ids.Copy( aIds );
+        
+        MCESRV_DEBUG_IDS("IDS", ids )
+
+        TRAP( status, iReceiver->SendToClientL( ids, aError ) );
+        }
+    else
+        {
+        MCESRV_DEBUG("orphan -> no recipient to send")
+        }
+        
+    MCESRV_DEBUG("CMceCsSubSession::SendErrorToClient, Exit")
+    return status;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::SendToClient
+// -----------------------------------------------------------------------------
+//
+TInt CMceCsSubSession::SendToClient( TMceIds& aIds )
+    {
+    MCESRV_DEBUG("CMceCsSubSession::SendToClient( ids ), Entry")
+    
+    TInt status = KErrNone;
+    if ( !IsOrphan() )
+        {
+        TMceIds ids = iReceiver->Ids();
+        ids.Copy( aIds );
+        
+        MCESRV_DEBUG_IDS("IDS", ids )
+        
+        TRAP( status, iReceiver->SendToClientL( ids ) );
+        }
+    else
+        {
+        MCESRV_DEBUG("orphan -> no recipient to send")
+        }
+        
+    MCESRV_DEBUG("CMceCsSubSession::SendToClient( ids ), Exit")
+    return status;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::SendToClientL
+// -----------------------------------------------------------------------------
+//
+void CMceCsSubSession::SendToClientL( TMceIds& aIds, 
+                                      HBufC8* aContext, 
+                                      HBufC8* aContent )
+    {
+    MCESRV_DEBUG("CMceCsSubSession::SendToClient(ids,context,content), Entry")
+    
+    if ( !IsOrphan() )
+        {
+        TMceIds ids = iReceiver->Ids();
+        ids.Copy( aIds );
+
+        MCESRV_DEBUG_IDS("IDS", ids )
+                        
+        if ( aContent )
+            {
+            iReceiver->SendToClientL( ids, aContext, aContent );
+            }
+        else
+            {
+            iReceiver->SendToClientL( ids, aContext );
+            }
+        }
+    else
+        {
+        delete aContext;
+        delete aContent;
+        }
+
+    MCESRV_DEBUG("CMceCsSubSession::SendToClient(ids,context,content), Exit")
+    }
+    
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::ClientReadyToReceiveL
+// -----------------------------------------------------------------------------
+//
+void CMceCsSubSession::ClientReadyToReceiveL( const RMessage2& aMessage )
+	{
+    MCESRV_DEBUG("CMceCsSubSession::ClientReadyToReceiveL, Entry")
+	
+    iReceiver->ClientReadyToReceiveL( aMessage );
+    iClientExists = ETrue;
+    
+    MCESRV_DEBUG("CMceCsSubSession::ClientReadyToReceiveL, Exit")
+	}
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::CancelClientReceiveL
+// -----------------------------------------------------------------------------
+//
+void CMceCsSubSession::CancelClientReceiveL()
+	{
+    MCESRV_DEBUG("CMceCsSubSession::CancelClientReceiveL, Entry")
+    
+    iClientExists = EFalse;
+    iReceiver->CancelClientReceiveL();
+    
+    MCESRV_DEBUG("CMceCsSubSession::CancelClientReceiveL, Exit")
+	}
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::ReceiveL
+// -----------------------------------------------------------------------------
+//
+void CMceCsSubSession::ReceiveL( const RMessage2& aMessage )
+	{
+    MCESRV_DEBUG("CMceCsSubSession::ReceiveL, Entry")
+	
+    iReceiver->ReceiveL (aMessage);	
+    
+    MCESRV_DEBUG("CMceCsSubSession::ReceiveL, Exit")
+	}
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::ClientExists
+// -----------------------------------------------------------------------------
+//
+TBool CMceCsSubSession::ClientExists()
+	{
+    return iClientExists;
+	}
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::DefaultHeaders
+// -----------------------------------------------------------------------------
+//
+CDesC8Array& CMceCsSubSession::DefaultHeaders( TInt aMethodInd )
+    {
+    return Client().DefaultHeaders( aMethodInd );
+    }
+    
+    
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::StoreClientContent
+// -----------------------------------------------------------------------------
+//
+void CMceCsSubSession::StoreClientContent( HBufC8* aClientContent )
+    {
+    delete iClientContent;
+    iClientContent = aClientContent;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::PopClientContent
+// -----------------------------------------------------------------------------
+//
+HBufC8* CMceCsSubSession::PopClientContent()
+    {
+    HBufC8* clientContent = iClientContent;
+    iClientContent = NULL;
+    return clientContent;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::ConnectionStateChanged
+// -----------------------------------------------------------------------------
+//
+void CMceCsSubSession::ConnectionStateChanged( CSIPConnection::TState aState )
+    {
+    TBool isActive = EFalse;
+    if ( aState == CSIPConnection::EActive )
+        {
+        isActive = ETrue;
+        }
+    
+    DoConnectionStateChanged( isActive );
+    
+    TMceIds ids;
+    ids.iCallbackID = EMceItcSessionConnectionStateChanged;
+	ids.iState = isActive;
+	SendToClient( ids );
+    }
+        
+// ---------------------------------------------------------------------------------
+// CMceCsSubSession::ResetInitialInvite
+// ---------------------------------------------------------------------------------    
+//
+void CMceCsSubSession::ResetInitialInvite()
+    {
+    iInitialInvite = NULL;
+    }
+
+// ---------------------------------------------------------------------------------
+// CMceCsSubSession::SetAutoEvent
+// ---------------------------------------------------------------------------------    
+//
+void CMceCsSubSession::SetAutoEvent( TBool aIsEnabled )
+    {
+    iAutoEventEnabled = aIsEnabled;
+    }
+
+// ---------------------------------------------------------------------------------
+// CMceCsSubSession::AutoEvent
+// ---------------------------------------------------------------------------------    
+//   
+TBool CMceCsSubSession::AutoEvent()
+    {
+    return iAutoEventEnabled;
+    }
+	
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::StoreAutoEventL
+// -----------------------------------------------------------------------------
+//
+/*lint -e506*/
+void CMceCsSubSession::StoreAutoEventL( 
+    TMceStateTransitionEvent* aEvent, 
+    CSIPServerTransaction* aAssociatedRequest )
+    {
+    delete iAutoEventMsg;
+    iAutoEventMsg = NULL;
+    delete iAutoEventIds;
+    iAutoEventIds = NULL;
+    delete iAutoEvent;
+    iAutoEvent = NULL;
+    
+    if ( aEvent )
+        {
+        // Have to duplicate certain elements as their lifetime may end
+        // while waiting for auto accept.
+        TMceIds* ids = NULL;
+        if ( &aEvent->ParamIDs() )
+            {
+            ids = new ( ELeave ) TMceIds( aEvent->ParamIDs() );
+            }
+        else
+            {
+            ids = new ( ELeave ) TMceIds;
+            }
+        CleanupStack::PushL( ids );
+        
+        CMceMsgBase& clonedMsg = aEvent->ParamClientMessage();
+        if ( &clonedMsg )
+            {
+            CMceMsgSIPReply* msg = new ( ELeave ) CMceMsgSIPReply();
+            CleanupStack::PushL( msg );
+            msg->PushL();
+            clonedMsg.EncodeL();
+            msg->DecodeL( clonedMsg.EncodeBuffer().Ptr( 0 ) );
+            iAutoEventMsg = msg;
+            CleanupStack::Pop( msg );
+            }
+
+        iAutoEventIds = ids;
+        CleanupStack::Pop( ids );
+        
+        iAutoEvent = new ( ELeave ) TMceStateTransitionEvent;
+        *iAutoEvent = *aEvent;
+        iAutoEvent->SetParamIDs( *iAutoEventIds );
+        iAutoEvent->SetParamClientMessage( iAutoEventMsg );
+        }
+        
+    iAutoEventAssociatedRequest = aAssociatedRequest;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::StoredAutoEvent
+// -----------------------------------------------------------------------------
+//		
+TMceStateTransitionEvent* CMceCsSubSession::StoredAutoEvent()
+    {
+    return iAutoEvent;
+    }
+    
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::Profile
+// -----------------------------------------------------------------------------
+//
+CSIPProfile& CMceCsSubSession::Profile() const
+	{
+	return *iProfile;
+	}
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::SetProfile
+// -----------------------------------------------------------------------------
+//
+void CMceCsSubSession::SetProfile( CSIPProfile& aProfile )
+	{
+	iProfile = &aProfile;
+	}
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::ProfileConfigured
+// -----------------------------------------------------------------------------
+//
+TBool CMceCsSubSession::ProfileConfigured() const
+	{
+	return ( iProfile != 0 );
+	}
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::NextHopL
+// -----------------------------------------------------------------------------
+//
+TInetAddr* CMceCsSubSession::NextHopL( TInetAddr& aNextHop )
+    {
+    TInetAddr* nextHop = NULL;
+    
+    const TDesC8* registeredContact = NULL;
+    
+    if ( ProfileConfigured() && Profile().GetParameter( KSIPRegisteredContact, 
+    					registeredContact ) == KErrNone )
+        {
+        CSIPContactHeader* contact = MceSip::ToContactHeaderL( *registeredContact );
+        CleanupStack::PushL( contact );
+        const CUri8& contactUri = contact->SIPAddress()->Uri8();
+        const TDesC8& contactUriHost = contactUri.Uri().Extract( EUriHost );
+        TBuf<KMaxAddressLength> addr16;
+        addr16.Copy( contactUriHost );
+        if ( aNextHop.Input( addr16 ) == KErrNone )
+            {
+            CleanupStack::PopAndDestroy( contact );
+            nextHop = &aNextHop;
+            }
+        }
+        
+    return nextHop;    
+    }
+
+// -----------------------------------------------------------------------------
+// CMceCsSubSession::IsProfileContactSecureL
+// -----------------------------------------------------------------------------
+//
+TBool CMceCsSubSession::IsProfileContactSecureL( )
+    {
+    MCESRV_DEBUG("CMceSipConnection::IsProfileContactSecureL, Entry")
+    const TDesC8* registeredContact = NULL;
+    TBool contactSecure = EFalse;
+    if ( ProfileConfigured() &&
+         Profile().GetParameter( KSIPRegisteredContact, 
+                                 registeredContact ) == KErrNone )
+        {
+        CSIPContactHeader* contact = MceSip::ToContactHeaderL( *registeredContact );
+        CleanupStack::PushL( contact );
+        const CUri8& contactUri = contact->SIPAddress()->Uri8();
+        const TDesC8& uriScheme = contactUri.Uri().Extract( EUriScheme );
+		const TDesC8& uriPath = contactUri.Uri().Extract( EUriPath );
+		if ( uriScheme.FindF( KMceSipUriSchemeSIPs ) != KErrNotFound ||
+			uriPath.FindF( KMceSipTransportTLS ) != KErrNotFound )
+			{
+			contactSecure = ETrue;
+			MCESRV_DEBUG("profile contact header has sips uri or tls")
+			}
+			
+		CleanupStack::PopAndDestroy( contact );
+		return contactSecure;
+		}
+	MCESRV_DEBUG("CMceSipConnection::IsProfileContactSecureL, Entry")
+    return contactSecure;
+    }
+
+//  End of File