realtimenetprots/sipfw/SIP/Dialogs/src/SipDialogItem.cpp
changeset 0 307788aac0a8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/realtimenetprots/sipfw/SIP/Dialogs/src/SipDialogItem.cpp	Tue Feb 02 01:03:15 2010 +0200
@@ -0,0 +1,1537 @@
+// Copyright (c) 2007-2009 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:
+// Name          : SipDialogItem.cpp
+// Part of       : SIPDialogs
+// Version       : SIP/6.0 
+//
+
+
+
+
+#include "CSipDialogItem.h"
+#include "MSipRefreshMgr.h"
+#include "MTransactionUser.h"
+#include "sipsec.h"
+#include "DeleteMgr.h"
+#include "MDialogOwner.h"
+#include "SipLogs.h"
+#include "SipAssert.h"
+#include "siprequest.h"
+#include "sipresponse.h"
+#include "sipcontactheader.h"
+#include "siptoheader.h"
+#include "sipfromheader.h"
+#include "sipcseqheader.h"
+#include "sipcallidheader.h"
+#include "siprecordrouteheader.h"
+#include "siprouteheader.h"
+#include "sipaddress.h"
+#include "uricontainer.h"
+#include "sipuri.h"
+#include "Establishing.h"
+#include "Early.h"
+#include "Confirmed.h"
+#include "Terminated.h"
+#include "DialogsStore.h"
+#include "TransactionItemStore.h"
+#include "TransactionItemBase.h"
+#include "RefreshItem.h"
+#include "TransactionItem.h"
+#include "CSigCompMgr.h"
+#include "MSigComp.h"
+#include "sipcodecutils.h"
+#include "sipstrings.h"
+#include "sipstrconsts.h"
+#include "sipcodecerr.h"
+#include "siperr.h"
+#include "TSIPTransportParams.h"
+
+const TUint K100Response = 100;
+const TUint K400Response = 400;
+const TUint K500Response = 500;
+
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::NewLC
+// -----------------------------------------------------------------------------
+//
+CSipDialogItem* CSipDialogItem::NewLC(CDialogsStore& aDialogStore,
+                                      MDialogOwner* aDialogOwner,
+                                      MSIPSecUser& aSIPSecUser,
+                                      MTransactionUser& aTransactionUser, 
+                                      MSipRefreshMgr& aRefreshMgr,
+                                      CSIPSec& aSIPSec,
+                                      CDeleteMgr& aDeleteMgr,
+                                      MSigComp& aSigComp,
+                                      TRegistrationId aRegistrationId)
+	{
+	CSipDialogItem* self = new(ELeave)CSipDialogItem(aDialogStore,
+	                                                 aSIPSecUser,
+                                                     aTransactionUser,
+                                                     aRefreshMgr,
+                                                     aSIPSec,
+                                                     aDeleteMgr,
+                                                     aSigComp,
+                                                     aRegistrationId);
+	CleanupStack::PushL(self);	
+	self->ConstructL(aDialogOwner);
+	return self;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::CSipDialogItem
+// -----------------------------------------------------------------------------
+//
+CSipDialogItem::CSipDialogItem (CDialogsStore& aDialogStore,
+                                MSIPSecUser& aSIPSecUser,
+								MTransactionUser& aTransactionUser, 
+								MSipRefreshMgr& aRefreshMgr,
+								CSIPSec& aSIPSec,
+								CDeleteMgr& aDeleteMgr,
+								MSigComp& aSigComp,
+								TRegistrationId aRegistrationId)
+: iRegistrationId(aRegistrationId),
+  iDialogStore(aDialogStore),
+  iTU(aTransactionUser),
+  iRefreshMgr(aRefreshMgr),
+  iSIPSec(aSIPSec), 
+  iDeleteMgr(aDeleteMgr),
+  iSigComp(aSigComp),
+  iSIPSecUser(aSIPSecUser),
+  iTerminated(*this),
+  iConfirmed(*this,iTerminated),
+  iEarly(*this,iConfirmed,iTerminated),
+  iEstablishing(*this,iEarly,iConfirmed,iTerminated),    
+  iRemoteTagSet(EFalse)
+  	{
+  	iTagParamName = SIPStrings::StringF(SipStrConsts::ETag);
+  	iTransportParamName = SIPStrings::StringF(SipStrConsts::ETransport);
+  	iContactHeaderName = SIPStrings::StringF(SipStrConsts::EContactHeader);
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::ConstructL
+// -----------------------------------------------------------------------------
+//
+void CSipDialogItem::ConstructL (MDialogOwner* aDialogOwner)
+	{
+    __SIP_ASSERT_LEAVE(aDialogOwner, KErrArgument);
+
+    iDialogOwner = aDialogOwner;
+    iTransactionItemStore = CTransactionItemStore::NewL();
+    iSigCompMgr = CSigCompMgr::NewL(
+        aDialogOwner->TransportParams(KEmptyRegistrationId).IapId(),iSigComp);
+
+    iDialogId = iDialogStore.NewDialogId();
+	ChangeState(iEstablishing);
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::~CSipDialogItem
+// -----------------------------------------------------------------------------
+//
+CSipDialogItem::~CSipDialogItem()
+	{
+    iTU.ClearTransactionOwner(this);
+    delete iSigCompMgr;
+	delete iCallId;
+	iLocalTag.Close();
+	iRemoteTag.Close();
+	delete iLocalAddress;
+	delete iRemoteAddress;
+	delete iLocalTarget;
+	delete iRemoteTarget;
+	iRouteSet.ResetAndDestroy();
+    delete iTransactionItemStore;
+    iSIPSec.ClearCache(this);
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::IapId
+// -----------------------------------------------------------------------------
+//
+TUint32 CSipDialogItem::IapId()
+    {
+    return TransportParams(KEmptyRegistrationId).IapId();
+    }
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::RegistrationId
+// -----------------------------------------------------------------------------
+//
+TRegistrationId CSipDialogItem::RegistrationId() const
+    {
+    return iRegistrationId;
+    }
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::Offset
+// -----------------------------------------------------------------------------
+//
+TInt CSipDialogItem::Offset ()
+	{
+    return _FOFF(CSipDialogItem,iLink);
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::ResetStateL
+// -----------------------------------------------------------------------------
+//
+void CSipDialogItem::ResetStateL()
+    {
+    CTransactionItemStore* transactionStore = CTransactionItemStore::NewLC();
+    CSigCompMgr* sigCompMgr = 
+        CSigCompMgr::NewL(
+            iDialogOwner->TransportParams(KEmptyRegistrationId).IapId(),
+            iSigComp);
+    CleanupStack::Pop(transactionStore);
+    iTU.ClearTransactionOwner(this);
+    iSIPSec.ClearCache(this);
+    delete iTransactionItemStore;
+    iTransactionItemStore = transactionStore;  
+    delete iSigCompMgr;
+    iSigCompMgr = sigCompMgr;
+    iRemoteTag = SIPStrings::StringF(SipStrConsts::EEmpty);
+    iRemoteTagSet = EFalse;
+    ChangeState(iEstablishing);
+    }
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::DialogOwner
+// -----------------------------------------------------------------------------
+//
+MDialogOwner* CSipDialogItem::DialogOwner()
+	{
+	return iDialogOwner;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::DeleteMgr
+// -----------------------------------------------------------------------------
+//
+CDeleteMgr& CSipDialogItem::DeleteMgr()
+	{
+	return iDeleteMgr;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::Match
+// -----------------------------------------------------------------------------
+//	
+TBool CSipDialogItem::Match(CSIPRequest& aRequest) const
+    {
+	CSIPCallIDHeader* callId = aRequest.CallID();
+	CSIPToHeader* to = aRequest.To();	
+	CSIPFromHeader* from = aRequest.From();
+	
+	if ((callId && *callId == *iCallId) &&
+		(to && 
+		 to->HasParam(iTagParamName) && 
+	     iLocalTag == to->ParamValue(iTagParamName)))
+		{
+		if (iRemoteTagSet)
+			{
+			if (from && 
+			    from->HasParam(iTagParamName) &&
+                iRemoteTag == from->ParamValue(iTagParamName))
+                {
+                return iCurrentState->Accept(aRequest);
+                }
+            }
+        else
+            {
+			return iCurrentState->Accept(aRequest);
+            }
+		}
+		
+    return EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::ContactOk
+// -----------------------------------------------------------------------------
+//    
+TBool CSipDialogItem::ContactOk(const CSIPContactHeader& aContact)
+    {		
+	if (aContact.Star() || !aContact.SIPAddress())
+        {
+        return EFalse;
+        }
+    return (aContact.SIPAddress()->URI().IsSIPURI());   
+    }
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::SetFirstTransactionIdId
+// -----------------------------------------------------------------------------
+//
+void CSipDialogItem::SetFirstTransactionId(const TTransactionId& aTransactionId)
+	{
+	iFirstTransactionId = aTransactionId;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::FirstTransactionId
+// -----------------------------------------------------------------------------
+//
+TTransactionId CSipDialogItem::FirstTransactionId()
+	{
+	return iFirstTransactionId;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::DialogId
+// -----------------------------------------------------------------------------
+//
+TDialogId CSipDialogItem::DialogId() const
+	{
+	return iDialogId;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::SelfDestruct
+// -----------------------------------------------------------------------------
+//
+void CSipDialogItem::SelfDestruct ()
+    {
+	iTU.ClearTransactionOwner(this);
+	ChangeState(iTerminated);
+    iDialogStore.Remove(this);
+    }
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::TerminateForkedDialogs
+// -----------------------------------------------------------------------------
+//
+void CSipDialogItem::TerminateForkedDialogs (TTransactionId aTransactionId)
+    {
+    iDialogStore.RemoveAllEarlyDialogsWith(aTransactionId);
+    }
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::IsEarly
+// -----------------------------------------------------------------------------
+//
+TBool CSipDialogItem::IsEarly () const
+    {
+    return (iCurrentState == &iEarly);
+    }
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::TransactionItems
+// -----------------------------------------------------------------------------
+//
+CTransactionItemStore& CSipDialogItem::TransactionItems ()
+    {
+    return *iTransactionItemStore;
+    }
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::HasTransactionItem
+// -----------------------------------------------------------------------------
+//
+TBool CSipDialogItem::HasTransactionItem (TTransactionId aTransactionId)
+    {
+    return iTransactionItemStore->HasItem(aTransactionId);
+    }
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::RemoveTransactionItem
+// -----------------------------------------------------------------------------
+//
+TInt CSipDialogItem::RemoveTransactionItem(TTransactionId& aTransactionId)
+    {
+    return iTransactionItemStore->RemoveItem(aTransactionId);
+    }
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::ChangeState
+// -----------------------------------------------------------------------------
+//
+void CSipDialogItem::ChangeState(TDialogStateBase& aState)
+	{
+	if (iCurrentState != &aState)
+		{
+		iCurrentState = &aState;
+		__SIP_INT_LOG1( "CSipDialogItem::ChangeState: ID", iDialogId )
+		__SIP_DES8_LOG( "CSipDialogItem::ChangeState: state", aState.Name() )
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::CurrentState
+// -----------------------------------------------------------------------------
+//
+TDialogStateBase& CSipDialogItem::CurrentState()
+	{
+	return *iCurrentState;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::CallId
+// -----------------------------------------------------------------------------
+//
+CSIPCallIDHeader* CSipDialogItem::CallId()
+	{
+	return iCallId;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::SetCallId
+// -----------------------------------------------------------------------------
+//
+void CSipDialogItem::SetCallId (CSIPCallIDHeader* aCallId)
+	{
+    delete iCallId;
+	iCallId = aCallId;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::LocalTag
+// -----------------------------------------------------------------------------
+//
+RStringF CSipDialogItem::LocalTag ()
+	{
+	return iLocalTag;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::SetLocalTag
+// -----------------------------------------------------------------------------
+//
+void CSipDialogItem::SetLocalTag (RStringF aTag)
+	{
+	iLocalTag.Close();
+	iLocalTag = aTag.Copy();
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::RemoteTag
+// -----------------------------------------------------------------------------
+//
+RStringF CSipDialogItem::RemoteTag ()
+	{
+	return iRemoteTag;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::RemoteTag
+// -----------------------------------------------------------------------------
+//
+TBool CSipDialogItem::RemoteTagSet ()
+	{
+	return iRemoteTagSet;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::SetRemoteTagL
+// -----------------------------------------------------------------------------
+//
+void CSipDialogItem::SetRemoteTagL (CSIPFromToHeaderBase* aFromTo)
+	{
+    if (aFromTo->HasParam(iTagParamName))
+        {
+	    if (iRemoteTagSet)
+            {
+            if (iRemoteTag != aFromTo->ParamValue(iTagParamName))
+                {
+                User::Leave (KErrAlreadyExists);
+                }
+            }
+        else
+            {
+            RStringF tmp = aFromTo->ParamValue(iTagParamName);
+			UpdateRemoteTagForRefreshesL(tmp);
+	        iRemoteTag.Close();
+            iRemoteTag = tmp.Copy();
+			iRemoteTagSet = ETrue;
+            }
+        }
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::LocalSeqNum
+// -----------------------------------------------------------------------------
+//
+TUint CSipDialogItem::LocalSeqNum()
+	{
+	return iLocalSeqNum;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::SetLocalSeqNum
+// -----------------------------------------------------------------------------
+//
+void CSipDialogItem::SetLocalSeqNum(TUint aNum)
+	{
+	iLocalSeqNum = aNum;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::RemoteSeqNum
+// -----------------------------------------------------------------------------
+//
+TUint CSipDialogItem::RemoteSeqNum()
+	{
+	return iRemoteSeqNum;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::SetRemoteSeqNum
+// -----------------------------------------------------------------------------
+//
+void CSipDialogItem::SetRemoteSeqNum(TUint aNum)
+	{
+	iRemoteSeqNum = aNum;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::LocalAddress
+// -----------------------------------------------------------------------------
+//
+const CSIPAddress* CSipDialogItem::LocalAddress()
+	{
+	return iLocalAddress;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::SetLocalAddressL
+// -----------------------------------------------------------------------------
+//
+void CSipDialogItem::SetLocalAddressL (const CSIPAddress& aAddr)
+	{
+	CSIPAddress* tmp = CSIPAddress::NewL(aAddr);
+	delete iLocalAddress;
+	iLocalAddress = tmp;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::RemoteAddress
+// -----------------------------------------------------------------------------
+//
+const CSIPAddress* CSipDialogItem::RemoteAddress()
+	{
+	return iRemoteAddress;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::SetRemoteAddressL
+// -----------------------------------------------------------------------------
+//
+void CSipDialogItem::SetRemoteAddressL (const CSIPAddress& aAddr)
+	{
+	CSIPAddress* tmp = CSIPAddress::NewL(aAddr);
+	delete iRemoteAddress;
+	iRemoteAddress = tmp;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::RemoteTarget
+// -----------------------------------------------------------------------------
+//
+CURIContainer* CSipDialogItem::RemoteTarget()
+	{
+	return iRemoteTarget;
+	}
+	
+// -----------------------------------------------------------------------------
+// CSipDialogItem::SetInitialRemoteTargetL
+// -----------------------------------------------------------------------------
+//	
+void CSipDialogItem::SetInitialRemoteTargetL (CURIContainer& aUri)
+    {
+    CURIContainer* tmp = CURIContainer::NewL(aUri);
+	delete iRemoteTarget;
+    iRemoteTarget = tmp;    
+    }
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::SetRemoteTargetL
+// -----------------------------------------------------------------------------
+//
+void CSipDialogItem::SetRemoteTargetL (CURIContainer& aUri)
+	{
+	__ASSERT_ALWAYS(aUri.IsSIPURI(), User::Leave(KErrSIPInvalidURIType));
+	if (iLocalTarget)
+		{
+		CSIPURI* localTargetURI = iLocalTarget->SIPAddress()->URI().SIPURI();
+		iSigCompMgr->UpdateL(aUri,iRouteSet,*localTargetURI);
+		}
+    CURIContainer* tmp = CURIContainer::NewL(aUri);
+	if (iTransactionItemStore->HasRefreshedItems())
+		{
+		CleanupStack::PushL(tmp);
+		iRefreshMgr.UpdateRemoteTargetL(this,*tmp);
+		CleanupStack::Pop(tmp);
+		}
+	delete iRemoteTarget;
+    iRemoteTarget = tmp;
+ 	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::SetRemoteTargetWithMsgL
+// -----------------------------------------------------------------------------
+//
+void CSipDialogItem::SetRemoteTargetWithMsgL (CSIPMessage& aMsg)
+	{
+	CSIPContactHeader* contact = static_cast<CSIPContactHeader*> 
+                                   (aMsg.Header(iContactHeaderName,0));
+	if (contact && contact->SIPAddress())
+        {
+		SetRemoteTargetL(contact->SIPAddress()->URI());
+		// Contact is updated only for outgoing requests
+		UpdateTransportForNextHopAndLocalTargetL(NULL);
+        }
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::LocalTarget
+// -----------------------------------------------------------------------------
+//
+CSIPContactHeader* CSipDialogItem::LocalTarget()
+	{
+	return iLocalTarget;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::SetLocalTargetL
+// -----------------------------------------------------------------------------
+//
+void CSipDialogItem::SetLocalTargetL(CSIPContactHeader& aContact,
+                                     TBool aUpdateSigCompParam)
+	{
+	__ASSERT_ALWAYS(aContact.SIPAddress(), 
+	                User::Leave(KErrSIPInvalidURIType));
+	CURIContainer& contactURI = aContact.SIPAddress()->URI();
+	__ASSERT_ALWAYS(contactURI.IsSIPURI(), User::Leave(KErrSIPInvalidURIType));
+    if (iRouteSet.Count() > 0 && iRouteSet[0] != NULL &&
+        iRouteSet[0]->SIPAddress().URI().IsSIPURI() && 
+        iRouteSet[0]->SIPAddress().URI().SIPURI()->IsSIPSURI())
+        {
+        // Next hop has sips-scheme
+		aContact.SIPAddress()->URI().SIPURI()->SetSIPS(ETrue);
+		}	
+	if (iRemoteTarget)
+		{
+		iSigCompMgr->UpdateL(*iRemoteTarget, iRouteSet,
+		                     *contactURI.SIPURI(), aUpdateSigCompParam);
+		}
+    CSIPContactHeader* tmp = static_cast<CSIPContactHeader*>(aContact.CloneL());
+	delete iLocalTarget;
+	iLocalTarget = tmp;
+    }
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::SetLocalTargetWithMsgL
+// -----------------------------------------------------------------------------
+//
+void CSipDialogItem::SetLocalTargetWithMsgL(CSIPMessage& aMsg, 
+											TBool aUpdateSigCompParam)
+	{
+	CSIPContactHeader* contact = 
+	    static_cast<CSIPContactHeader*>(aMsg.Header(iContactHeaderName,0));
+	if (contact)
+        {       
+		SetLocalTargetL(*contact,aUpdateSigCompParam);
+		UpdateTransportForNextHopAndLocalTargetL(contact);
+		if (aMsg.IsRequest())
+		    {
+		    // UpdateTransportForNextHopAndLocalTargetL 
+		    // may have updated the next hop transport
+		    aMsg.DeleteHeaders(SIPStrings::StringF(SipStrConsts::ERouteHeader));
+		    AddRouteToMessageL(aMsg);
+		    }
+        }
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::SetRouteSetL
+// -----------------------------------------------------------------------------
+//
+void CSipDialogItem::SetRouteSetL(RPointerArray<CSIPRouteHeaderBase>& aRoute)
+	{
+	RPointerArray<CSIPRouteHeader>* routeSet = 
+        new(ELeave)RPointerArray<CSIPRouteHeader>;
+    TCleanupItem cleanupItem(CleanupRouteSet,routeSet);
+	CleanupStack::PushL (cleanupItem);
+
+	for (TInt i=0; i < aRoute.Count(); i++)
+		{
+		CSIPRouteHeader* routeHeader = 
+		    SIPCodecUtils::CreateRouteHeaderLC(*(aRoute[i]));    
+		User::LeaveIfError(routeSet->Append(routeHeader));
+		CleanupStack::Pop(routeHeader);
+		}
+
+	/* Ownership is transferred for routeset, so popping routset before passing 
+	 * to SetRouteSet()
+	 */
+	CleanupStack::Pop(1); // cleanupItem
+	SetRouteSet(routeSet); // ownership transferred
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::SetRouteSetUsingRouteL
+// -----------------------------------------------------------------------------
+//
+void CSipDialogItem::SetRouteSetUsingRouteL (CSIPMessage& aMessage)
+	{
+	TSglQueIter<CSIPHeaderBase> iter = 
+        aMessage.Headers(SIPStrings::StringF(SipStrConsts::ERouteHeader));
+	
+	RPointerArray<CSIPRouteHeader>* routeSet = 
+        new(ELeave)RPointerArray<CSIPRouteHeader>;
+    TCleanupItem cleanupItem(CleanupRouteSet,routeSet);
+	CleanupStack::PushL (cleanupItem);
+
+	while (iter)
+		{
+		CSIPHeaderBase* header = iter++;
+		CSIPRouteHeader* newRoute = 
+		    static_cast<CSIPRouteHeader*>(header->CloneL());
+		CleanupStack::PushL(newRoute);
+        User::LeaveIfError(routeSet->Append(newRoute));
+        CleanupStack::Pop(newRoute);
+		}
+
+	/* Ownership is transferred for routeset, so popping routset before passing 
+	 * to SetRouteSet()
+	 */
+	CleanupStack::Pop(1); // cleanupItem
+	SetRouteSet(routeSet); // ownership transferred
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::SetRouteSetUsingRecordRouteL
+// -----------------------------------------------------------------------------
+//
+void CSipDialogItem::SetRouteSetUsingRecordRouteL (CSIPMessage& aMessage, 
+												   TBool aIsUAC,
+												   TInt aLeaveCode)
+	{
+	TSglQueIter<CSIPHeaderBase> iter = 
+        aMessage.Headers(SIPStrings::StringF(SipStrConsts::ERecordRouteHeader));
+	
+	if (iter)
+		{
+		RPointerArray<CSIPRouteHeader>* routeSet = 
+            new(ELeave)RPointerArray<CSIPRouteHeader>;
+		TCleanupItem cleanupItem(CleanupRouteSet,routeSet);
+		CleanupStack::PushL (cleanupItem);
+	
+	    while (iter)
+    		{
+	    	CSIPHeaderBase* header = iter++;
+		    CSIPRecordRouteHeader* recRoute = 
+                static_cast<CSIPRecordRouteHeader*>(header);
+	    	CSIPRouteHeader* newRoute = 
+	    	    SIPCodecUtils::CreateRouteHeaderLC(*recRoute);
+            if (aIsUAC)
+                {
+		    	User::LeaveIfError(routeSet->Insert(newRoute, 0));
+                }
+	    	else
+                {
+	    		User::LeaveIfError(routeSet->Append(newRoute));
+                }
+		    CleanupStack::Pop(newRoute);
+		    }
+		CSIPRouteHeader* firstRoute = (*routeSet)[0];
+		if (!firstRoute->SIPAddress().URI().IsSIPURI())
+		    {
+		    User::Leave(aLeaveCode);
+		    }           
+		iRefreshMgr.UpdateRouteSetsL(this,*routeSet);
+
+		/* Ownership is transferred for routeset, so popping routset before passing 
+	 	* to SetRouteSet()
+	 	*/
+		CleanupStack::Pop(1); // cleanupItem
+		SetRouteSet(routeSet); // ownership transferred
+    	
+	    }
+    else
+		{
+		iRefreshMgr.RemoveRouteSets(this);
+		iRouteSet.ResetAndDestroy();
+		}
+	// Route updated, tell Refreshes not to include Registration Id 
+	// for the calls to TU anymore.
+	iRefreshMgr.SetRegistrationIdsEmpty(this);
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::SetRouteSet
+// -----------------------------------------------------------------------------
+//
+void CSipDialogItem::SetRouteSet (RPointerArray<CSIPRouteHeader>* aRouteSet)
+	{
+	iRouteSet.ResetAndDestroy();
+	if (aRouteSet)
+		{
+		iRouteSet = *aRouteSet;
+		
+		delete aRouteSet;
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::HasRouteSet
+// -----------------------------------------------------------------------------
+//
+TBool CSipDialogItem::HasRouteSet() const
+    {
+    return (iRouteSet.Count() > 0);
+    }
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::AddRouteToMessageL
+// -----------------------------------------------------------------------------
+//
+void CSipDialogItem::AddRouteToMessageL(CSIPMessage& aMessage)
+	{
+	for (TInt i=0; i < iRouteSet.Count(); i++)
+		{
+		CSIPRouteHeader* route = 
+		    static_cast<CSIPRouteHeader*>(iRouteSet[i]->CloneL());
+		CleanupStack::PushL(route);		    
+		aMessage.AddHeaderL(route);
+		CleanupStack::Pop(route);
+        }
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::AddRecordRouteToMessageL
+// -----------------------------------------------------------------------------
+//
+void CSipDialogItem::AddRecordRouteToMessageL(CSIPMessage& aMessage)
+	{
+	for (TInt i=0; i < iRouteSet.Count(); i++)
+		{
+		CSIPRecordRouteHeader* route = 
+		    SIPCodecUtils::CreateRecordRouteHeaderLC(*(iRouteSet[i]));
+		aMessage.AddHeaderL(route);
+		CleanupStack::Pop(route);
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::AddToHeaderInDialogL
+// -----------------------------------------------------------------------------
+//
+void CSipDialogItem::AddToHeaderInDialogL(CSIPRequest& aRequest)
+	{
+    if (!aRequest.To())
+        {
+	    CSIPAddress* address = CSIPAddress::NewLC(*iRemoteAddress);
+	    CSIPToHeader* to = CSIPToHeader::NewL(address);
+	    CleanupStack::Pop(address);
+	    CleanupStack::PushL(to);
+	    if (iRemoteTagSet)
+            {
+    		to->SetParamL(iTagParamName,iRemoteTag);
+			}
+    	aRequest.AddHeaderL(to);
+    	CleanupStack::Pop(to);
+        }
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::AddFromHeaderInDialogL
+// -----------------------------------------------------------------------------
+//
+void CSipDialogItem::AddFromHeaderInDialogL(CSIPRequest& aRequest)
+	{
+    if (!aRequest.From())
+        {
+    	CSIPAddress* address = CSIPAddress::NewLC(*iLocalAddress);
+    	CSIPFromHeader* from = CSIPFromHeader::NewL(address);
+    	CleanupStack::Pop(address);
+    	CleanupStack::PushL(from);
+    	from->SetParamL(iTagParamName,iLocalTag);
+    	aRequest.AddHeaderL(from);
+    	CleanupStack::Pop(from);
+        }
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::AddCallIdHeaderInDialogL
+// -----------------------------------------------------------------------------
+//
+void CSipDialogItem::AddCallIdHeaderInDialogL(CSIPMessage& aMessage)
+	{    
+    if (!aMessage.CallID())
+        {
+    	CSIPCallIDHeader* callId = 
+    	    static_cast<CSIPCallIDHeader*>(iCallId->CloneL());
+    	CleanupStack::PushL(callId);
+    	aMessage.AddHeaderL(callId);
+    	CleanupStack::Pop(callId);
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::AddCSeqHeaderInDialogL
+// -----------------------------------------------------------------------------
+//
+void CSipDialogItem::AddCSeqHeaderInDialogL(CSIPRequest& aRequest)
+	{
+    if (!aRequest.CSeq())
+        {
+    	CSIPCSeqHeader* cseq = 
+    	    CSIPCSeqHeader::NewLC(iLocalSeqNum+1,aRequest.Method());
+    	aRequest.AddHeaderL(cseq);
+    	CleanupStack::Pop(cseq);
+    	iLocalSeqNum++;
+    	}
+    }
+    
+// -----------------------------------------------------------------------------
+// CSipDialogItem::ReceiveL
+// From MTransactionOwner:
+// -----------------------------------------------------------------------------
+//
+void CSipDialogItem::ReceiveL (TTransactionId aTransactionId,
+                               CSIPResponse* aResponse)
+	{
+    __SIP_ASSERT_LEAVE(aTransactionId, KErrSIPInvalidDialogResponse);
+	__SIP_ASSERT_LEAVE(aResponse, KErrSIPInvalidDialogResponse);
+    CTransactionItemBase* transactionItem = 
+        iTransactionItemStore->FindItem(aTransactionId);
+    __SIP_ASSERT_LEAVE (transactionItem, KErrNotFound);
+    
+	__SIP_MESSAGE_LOG("Dialogs", *aResponse)
+	
+	if (transactionItem->TargetRefresh())
+	    {
+	    CheckContactsL(aTransactionId,*aResponse);
+	    }
+
+    CSIPToHeader* to = aResponse->To();
+	if (!CheckResponse(aResponse) || 
+        (aResponse->ResponseCode() > K100Response &&
+         iRemoteTagSet && iRemoteTag != to->ParamValue(iTagParamName) && 
+         aTransactionId != FirstTransactionId()))
+		{
+        iDialogOwner->DialogsError(aTransactionId,KEmptyRefreshId,iDialogId,
+                                   KErrSIPInvalidDialogResponse);
+		delete aResponse;
+		return;
+		}
+
+	if (aResponse->ResponseCode() > K100Response && 
+	    !aResponse->IsErrorResponse() &&
+		iRemoteTagSet && 
+		iRemoteTag != to->ParamValue(iTagParamName))
+		{
+		if(to->HasParam(iTagParamName))
+			{		
+			CSipDialogItem* dialog = 
+                iDialogStore.FindDialogItemForPass(aTransactionId,aResponse);
+			if(!dialog)
+				{
+				dialog = CreateForkingDialogLC(); 
+                dialog->SetRemoteTagL(to);
+				dialog->ReceiveL(aTransactionId, aResponse);
+            	iDialogStore.AddDialogItem(dialog);
+	            CleanupStack::Pop(dialog);
+				}
+            else
+                {
+				dialog->ReceiveL(aTransactionId, aResponse);
+                }
+            return;
+			}
+		}
+		
+	iCurrentState->ReceiveL(*transactionItem,aResponse);
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::ReceiveL
+// From MTransactionOwner:
+// -----------------------------------------------------------------------------
+//
+void CSipDialogItem::ReceiveL (TUint32 aIapId,
+                               TTransactionId aTransactionId,
+                               CSIPRequest* aRequest)
+	{
+	__SIP_ASSERT_LEAVE(aTransactionId, KErrSIPInvalidDialogResponse);
+	__SIP_ASSERT_LEAVE(aRequest, KErrSIPInvalidDialogRequest);
+	__SIP_ASSERT_LEAVE(CheckRequest(aRequest), KErrSIPMalformedMessage);
+	__SIP_ASSERT_LEAVE(aIapId == IapId(), KErrArgument);
+	__SIP_MESSAGE_LOG("Dialogs", *aRequest)
+
+    TSIPTransportParams transportParams(TransportParams(KEmptyRegistrationId));
+	if (!CheckContacts(*aRequest))
+		{
+		if (aRequest->Method() == SIPStrings::StringF(SipStrConsts::EAck))
+			{
+			iDialogOwner->DialogsError(aTransactionId, KEmptyRefreshId,
+                                       iDialogId, KErrSIPNoAckReceived);
+			delete aRequest;
+			return;
+			}
+		CSIPResponse* response = 
+		    CSIPResponse::NewLC(K400Response,
+		        SIPStrings::StringF(SipStrConsts::EPhraseBadRequest));
+		iTU.SendL(aTransactionId, response, this, transportParams);
+		CleanupStack::Pop(response);
+		delete aRequest;
+		return;
+		}
+
+	// check cseq compared to iRemoteSeqNum
+	if (aRequest->Method() != SIPStrings::StringF(SipStrConsts::EAck))
+		{	
+		if (iRemoteSeqNum > aRequest->CSeq()->Seq())
+			{
+			CSIPResponse* response = 
+			    CSIPResponse::NewLC(K500Response,
+			        SIPStrings::StringF(
+			            SipStrConsts::EPhraseServerInternalError));
+			iTU.SendL(aTransactionId, response, this, transportParams);
+			CleanupStack::Pop(response);
+			delete aRequest;
+			return;
+			}
+		}
+
+	iRemoteSeqNum = aRequest->CSeq()->Seq();
+    CTransactionItem* transactionItem = 
+        CTransactionItem::NewLC(iTU,this,aTransactionId,aRequest->Method());
+    iCurrentState->ReceiveL(aTransactionId, aRequest);
+	iTransactionItemStore->AddItem(transactionItem);
+	CleanupStack::Pop(transactionItem);
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::TransactionEnded
+// From MTransactionOwner:
+// -----------------------------------------------------------------------------
+//
+TInt CSipDialogItem::TransactionEnded (TUint32 /*aIapId*/,
+                                       TTransactionId aTransactionId, 
+                                       TInt aReason)
+	{
+    TInt err = KErrNone;
+
+    CTransactionItemBase* item = 
+        iTransactionItemStore->FindItem(aTransactionId);
+    if (item && 
+        aReason == KErrNone && 
+        item->Method() == SIPStrings::StringF(SipStrConsts::EInvite))
+        {
+        err = iDialogOwner->InviteTransactionCompleted(aTransactionId);
+        }
+
+    iDialogStore.TransactionEnded(aTransactionId,aReason);
+
+	return err;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::NextCSeq
+// From MTransactionOwner:
+// -----------------------------------------------------------------------------
+//
+TInt CSipDialogItem::NextCSeq(TUint& aCSeq)
+	{
+	aCSeq = ++iLocalSeqNum;
+	return KErrNone;
+	}
+	
+// -----------------------------------------------------------------------------
+// CSipDialogItem::SIPSecUser
+// From MTransactionOwner:
+// -----------------------------------------------------------------------------
+//    
+const MSIPSecUser* CSipDialogItem::SIPSecUser() const
+    {
+    return this;
+    }    
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::RefreshReceivedL
+// From MRefreshOwner:
+// -----------------------------------------------------------------------------
+//
+void CSipDialogItem::RefreshReceivedL (TTransactionId aTransactionId,
+                                       TRefreshId aRefreshId,
+                                       CSIPResponse* aResponse)
+	{
+    __SIP_ASSERT_LEAVE(aTransactionId, KErrSIPInvalidDialogResponse);
+    __SIP_ASSERT_LEAVE(aResponse, KErrSIPInvalidDialogResponse);
+	__SIP_MESSAGE_LOG("Dialogs", *aResponse)
+
+	// Check Call-ID, CSeq and From-tag
+	if (!CheckResponse(aResponse))
+		{
+		iDialogOwner->DialogsError(aTransactionId, aRefreshId, iDialogId,
+                                   KErrSIPInvalidDialogResponse);
+		delete aResponse;
+		return;
+		}
+
+	CRefreshItem* item = iTransactionItemStore->FindRefreshItem(aRefreshId);
+	if (!item)
+		{
+		iDialogOwner->DialogsError(aTransactionId,aRefreshId,iDialogId,
+                                   KErrSIPInvalidTransactionState);
+		delete aResponse;
+		return;
+		}
+
+	if (iRemoteTagSet)
+		{
+		if (iRemoteTag != aResponse->To()->ParamValue(iTagParamName))
+			{
+			iDialogOwner->DialogsError(aTransactionId,aRefreshId,iDialogId, 
+                                       KErrSIPInvalidDialogResponse);
+			delete aResponse;
+			return;
+			}
+		}
+
+	if (item->TargetRefresh())
+	    {
+	    CheckContactsL(aTransactionId,*aResponse);
+	    }
+
+	if (aResponse->IsErrorResponse())
+		{
+		item->SetTerminated();
+		}
+
+    item->SetTransactionId(aTransactionId);
+	iCurrentState->ReceiveL(*item, aResponse);
+	}
+	
+// -----------------------------------------------------------------------------
+// CSipDialogItem::RefreshError
+// From MRefreshOwner:
+// -----------------------------------------------------------------------------
+//
+TInt CSipDialogItem::RefreshError (TRefreshId aRefreshId,
+                                   TTransactionId aTransactionId,
+                                   TInt aReason)
+	{
+	CTransactionItemBase* refreshItem = 
+		iTransactionItemStore->FindItem(aTransactionId);
+	if (!refreshItem)
+		{
+		refreshItem = iTransactionItemStore->FindRefreshItem(aRefreshId);
+		if (!refreshItem)
+			{
+			return KErrArgument;
+			}
+		}
+    refreshItem->SetTransactionId(aTransactionId);
+    iDialogStore.TransactionEnded(refreshItem->Id(),aReason);
+	return KErrNone;
+	}	
+	
+// -----------------------------------------------------------------------------
+// CSipDialogItem::NextRefreshCSeq
+// From MRefreshOwner:
+// -----------------------------------------------------------------------------
+//
+TInt CSipDialogItem::NextRefreshCSeq(TUint& aCSeq)
+	{
+	return NextCSeq(aCSeq);
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::TransportParams
+// From MRefreshOwner:
+// -----------------------------------------------------------------------------
+//
+TSIPTransportParams CSipDialogItem::TransportParams(
+    const TRegistrationId& aRegistrationId)
+	{
+	TSIPTransportParams transportParams(
+	    iDialogOwner->TransportParams(aRegistrationId));
+	if (aRegistrationId == KEmptyRegistrationId)
+	    {
+	    // Registration id is set empty after receiving the first
+	    // response to the refreshed initial request.
+	    // See function SetRouteSetUsingRecordRouteL.
+	    transportParams.SetCompartmentId(iSigCompMgr->CompartmentId());
+	    }
+	return transportParams;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::SIPSecUser
+// From MRefreshOwner:
+// -----------------------------------------------------------------------------
+//	
+const MSIPSecUser* CSipDialogItem::SIPSecUser(
+    const TRegistrationId& aRegistrationId)
+    {
+    return iDialogOwner->SIPSecUser(aRegistrationId);
+    }
+	
+// -----------------------------------------------------------------------------
+// CSipDialogItem::RefreshDurationL
+// -----------------------------------------------------------------------------
+//
+TUint CSipDialogItem::RefreshDurationL()
+	{
+	User::Leave(KErrNotFound);
+	return 0;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::PassOnlyRealmsToUser
+// From MSIPSecUser:
+// -----------------------------------------------------------------------------
+//    
+TBool CSipDialogItem::PassOnlyRealmsToUser() const
+    {
+    return iSIPSecUser.PassOnlyRealmsToUser();
+    }
+    
+// -----------------------------------------------------------------------------
+// CSipDialogItem::RequestCredentialsL
+// From MSIPSecUser:
+// -----------------------------------------------------------------------------
+//
+void CSipDialogItem::RequestCredentialsL(const TDesC8& aRealm)
+    {
+    iSIPSecUser.RequestCredentialsL(aRealm);
+    }    	
+	
+// -----------------------------------------------------------------------------
+// CSipDialogItem::RequestCredentialsL
+// From MSIPSecUser:
+// -----------------------------------------------------------------------------
+//	
+void CSipDialogItem::RequestCredentialsL(CSIPResponse& aResponse,
+	                                     TTransactionId aTransactionId,
+	                                     TRefreshId aRefreshId)
+    {
+    iSIPSecUser.RequestCredentialsL(aResponse,aTransactionId,aRefreshId);
+    }
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::TrustedUser
+// From MSIPSecUser:
+// -----------------------------------------------------------------------------
+//    
+const MSIPSecUser* CSipDialogItem::TrustedUser(
+    TRegistrationId /*aRegistrationId*/)
+    {
+    return iDialogOwner->SIPSecUser(iRegistrationId);
+    }
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::ByPassSIPSec
+// From MSIPSecUser:
+// -----------------------------------------------------------------------------
+//
+TBool CSipDialogItem::ByPassSIPSec() const
+    {
+    const MSIPSecUser* trustedUser = iDialogOwner->SIPSecUser(iRegistrationId);
+    if (trustedUser)
+        {
+        // Use the same value as the related registration, if possible
+        return trustedUser->ByPassSIPSec();
+        }
+    return iSIPSecUser.ByPassSIPSec();
+    }
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::EndTransaction
+// -----------------------------------------------------------------------------
+//
+void CSipDialogItem::EndTransaction (TTransactionId aTransactionId,
+									 TInt aReason)
+	{
+    CTransactionItemBase* transactionItem = 
+        iTransactionItemStore->FindItem(aTransactionId);
+	if (transactionItem)
+        {
+	    iCurrentState->EndTransaction(*transactionItem, aReason);
+	    iTransactionItemStore->RemoveItem(transactionItem->Id());
+        }
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::CheckResponse
+// -----------------------------------------------------------------------------
+//
+TBool CSipDialogItem::CheckResponse(CSIPResponse* aResponse)
+	{
+	CSIPCallIDHeader* callId = aResponse->CallID();
+    if (!callId)
+        {
+        return EFalse;
+        }
+    if (!(*iCallId == *callId))
+        {
+        return EFalse;
+        }
+	CSIPFromHeader* from = aResponse->From();
+    if (!from)
+        {
+        return EFalse;
+        }   
+    if (iLocalTag != from->ParamValue(iTagParamName))
+        {
+        return EFalse;
+        }
+    if (!aResponse->CSeq())
+        {
+        return EFalse;
+        }
+	return ETrue;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::CheckRequest
+// -----------------------------------------------------------------------------
+//
+TBool CSipDialogItem::CheckRequest(CSIPRequest* aRequest)
+	{
+	CSIPCallIDHeader* callId = aRequest->CallID();
+    if (!callId)
+        {
+        return EFalse;
+        }
+    if (!(*iCallId == *callId))
+        {
+        return EFalse;
+        }
+	CSIPToHeader* to = aRequest->To();
+    if (!to)
+        {
+        return EFalse;
+        }   
+    if (iLocalTag != to->ParamValue(iTagParamName))
+        {
+        return EFalse;
+        }
+	return ETrue;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::UpdateRemoteTagForRefreshesL
+// -----------------------------------------------------------------------------
+//
+void CSipDialogItem::UpdateRemoteTagForRefreshesL (RStringF aRemoteTag)
+	{
+    RArray<TRefreshId> ids = iTransactionItemStore->RefreshItemIdsL();
+    CleanupClosePushL(ids);
+    for (TInt i=0; i<ids.Count(); i++)
+		{					
+		TRefreshId refreshId = ids[i];
+		CSIPRequest* refreshReq = iRefreshMgr.Request(refreshId);
+		if (refreshReq)
+			{
+			CSIPToHeader* refreshReqTo = refreshReq->To();
+			if (refreshReqTo && !refreshReqTo->HasParam(iTagParamName))
+				{
+				refreshReqTo->SetParamL(iTagParamName,aRemoteTag);
+				}
+			}
+		}
+    CleanupStack::PopAndDestroy(1); // ids
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::UpdateLocalTargetL
+// -----------------------------------------------------------------------------
+//
+void CSipDialogItem::UpdateLocalTargetL(CSIPMessage& aMessage)
+	{
+	SetLocalTargetWithMsgL(aMessage);
+	CSIPContactHeader* contact = 
+	    static_cast<CSIPContactHeader*>(aMessage.Header(iContactHeaderName,0));
+	
+    RArray<TRefreshId> ids = iTransactionItemStore->RefreshItemIdsL();
+    CleanupClosePushL(ids);
+    for (TInt i=0; i<ids.Count(); i++)
+		{
+		CSIPContactHeader* newContact = 
+		    static_cast<CSIPContactHeader*>(contact->CloneL());
+		CleanupStack::PushL(newContact);
+		iRefreshMgr.UpdateHeaderL(ids[i],this,newContact);
+		CleanupStack::Pop(newContact);
+		}
+    CleanupStack::PopAndDestroy(1); // ids
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::CheckContacts
+// -----------------------------------------------------------------------------
+//
+TBool CSipDialogItem::CheckContacts (CSIPMessage& aMessage, 
+                                     TBool aContactRequired) const
+	{
+	TInt contactCount = aMessage.HeaderCount(iContactHeaderName);
+    if (contactCount == 1)
+        {
+		CSIPContactHeader* contact = 
+            static_cast<CSIPContactHeader*>(
+                aMessage.Header(iContactHeaderName,0));
+		if (!ContactOk(*contact))
+            {
+			return EFalse;
+            }
+        }
+    if (aContactRequired)
+        {
+        return (contactCount == 1);
+        }
+    return (contactCount <= 1);
+	}
+	
+// -----------------------------------------------------------------------------
+// CSipDialogItem::CheckContactsL
+// -----------------------------------------------------------------------------
+//	
+void CSipDialogItem::CheckContactsL (TTransactionId aTransactionId,
+                                     CSIPResponse& aResponse) const
+    {
+    if (aResponse.ResponseCode() > K100Response && 
+        !aResponse.IsErrorResponse())
+        {        
+        TBool contactRequired = 
+            (aResponse.Type() == CSIPResponse::E2XX &&
+             aTransactionId == iFirstTransactionId);
+        if (!CheckContacts(aResponse,contactRequired))
+            {
+            User::Leave(KErrSIPInvalidDialogResponse);
+            }   
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::CreateForkingDialogLC
+// -----------------------------------------------------------------------------
+//
+CSipDialogItem* CSipDialogItem::CreateForkingDialogLC ()
+	{
+	CSipDialogItem* dialog = 
+        CSipDialogItem::NewLC(iDialogStore,iDialogOwner,iSIPSecUser,iTU,
+                              iRefreshMgr,iSIPSec,iDeleteMgr,iSigComp);
+
+	//copy the first TransactionItem from parent dialog
+    TTransactionId firstTransactionId = iFirstTransactionId;
+	CTransactionItemBase* firstTransactionItem = 
+        iTransactionItemStore->FindItem(firstTransactionId);
+    __ASSERT_ALWAYS (firstTransactionItem, User::Leave(KErrGeneral));
+
+    CTransactionItemBase* forkingTransactionItem =
+        CTransactionItem::NewL(iTU,this,*firstTransactionItem);
+    
+    dialog->TransactionItems().AddItem(forkingTransactionItem);
+
+	dialog->SetFirstTransactionId(iFirstTransactionId);
+
+	CSIPCallIDHeader* callIdHeader = 
+	    static_cast<CSIPCallIDHeader*>(iCallId->CloneL());
+	dialog->SetCallId(callIdHeader);
+	dialog->SetLocalTag(iLocalTag);
+
+	__SIP_ASSERT_LEAVE(iLocalAddress, KErrArgument);
+	dialog->SetLocalAddressL(*iLocalAddress);
+
+	__SIP_ASSERT_LEAVE(iRemoteAddress, KErrArgument);
+	dialog->SetRemoteAddressL(*iRemoteAddress);
+
+	dialog->SetLocalSeqNum(iLocalSeqNum);
+
+	__SIP_ASSERT_LEAVE(iLocalTarget, KErrArgument);
+	dialog->SetLocalTargetL(*iLocalTarget);
+
+	return dialog;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::UpdateTransportForNextHopAndLocalTargetL
+// -----------------------------------------------------------------------------
+//
+void CSipDialogItem::UpdateTransportForNextHopAndLocalTargetL(
+    CSIPContactHeader* aContactInOutgoingRequest)
+    {
+    CSIPURI& localTarget = ExtractUriL(iLocalTarget);
+    RStringF localTargetTransport = localTarget.ParamValue(iTransportParamName);
+   
+    CSIPURI* nextHop = NULL;
+    if (iRouteSet.Count() > 0)
+        {
+        CURIContainer& uri = iRouteSet[0]->SIPAddress().URI();
+        __ASSERT_ALWAYS(uri.IsSIPURI(), User::Leave(KErrSIPInvalidURIType));
+        nextHop = uri.SIPURI();
+        }
+    else
+        {
+        __ASSERT_ALWAYS(iRemoteTarget, User::Leave(KErrNotFound));
+        __ASSERT_ALWAYS(iRemoteTarget->IsSIPURI(), 
+                        User::Leave(KErrSIPInvalidURIType));
+        nextHop = iRemoteTarget->SIPURI();        
+        }
+    RStringF nextHopTransport = nextHop->ParamValue(iTransportParamName);
+    
+    if (nextHopTransport.DesC().Length() > 0)
+        {
+        if (localTargetTransport.DesC().Length() == 0 &&
+            !localTarget.IsSIPSURI())
+            {
+            localTarget.SetParamL(iTransportParamName,nextHopTransport);
+            if (aContactInOutgoingRequest)
+                {
+                CSIPURI& contactUri = ExtractUriL(aContactInOutgoingRequest);
+                contactUri.SetParamL(iTransportParamName,nextHopTransport);
+                }
+            }        
+        }
+    else
+        {
+        if (localTargetTransport.DesC().Length() > 0 &&
+            !nextHop->IsSIPSURI())
+            {
+            nextHop->SetParamL(iTransportParamName,localTargetTransport);
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::ExtractUriL
+// -----------------------------------------------------------------------------
+//
+CSIPURI& CSipDialogItem::ExtractUriL(CSIPContactHeader* aContact)
+    {
+    __ASSERT_ALWAYS(aContact, User::Leave(KErrNotReady));
+    __ASSERT_ALWAYS(aContact->SIPAddress(), User::Leave(KErrNotReady));
+    __ASSERT_ALWAYS(aContact->SIPAddress()->URI().IsSIPURI(), 
+                    User::Leave(KErrSIPInvalidURIType));
+    return *(aContact->SIPAddress()->URI().SIPURI()); 
+    }
+
+// -----------------------------------------------------------------------------
+// CSipDialogItem::CleanupRouteSet
+// -----------------------------------------------------------------------------
+//
+void CSipDialogItem::CleanupRouteSet (TAny* aRouteSet)
+	{
+    RPointerArray<CSIPRouteHeader>* routeSet =
+        reinterpret_cast<RPointerArray<CSIPRouteHeader>*>(aRouteSet);
+    if (routeSet)
+        {
+        routeSet->ResetAndDestroy();
+        }
+    delete routeSet;
+	}