realtimenetprots/sipfw/SIP/Dialogs/src/SipDialogMgr.cpp
changeset 0 307788aac0a8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/realtimenetprots/sipfw/SIP/Dialogs/src/SipDialogMgr.cpp	Tue Feb 02 01:03:15 2010 +0200
@@ -0,0 +1,912 @@
+// Copyright (c) 2005-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          : SipDialogMgr.cpp
+// Part of       : SIPDialogs
+// Version       : SIP/4.0 
+//
+
+
+
+
+#include "CSipDialogMgr.h"
+#include "sipfromheader.h"
+#include "DialogStateBase.h"
+#include "MSipRegistrationContact.h"
+#include "MTransactionUser.h"
+#include "MSipRefreshMgr.h"
+#include "MDialogOwner.h"
+#include "DeleteMgr.h"
+#include "sipcontactheader.h"
+#include "siprequest.h"
+#include "sipresponse.h"
+#include "siptoheader.h"
+#include "sipcallidheader.h"
+#include "sipcseqheader.h"
+#include "SipLogs.h"
+#include "sipaddress.h"
+#include "siphostport.h"
+#include "uricontainer.h"
+#include "sipuri.h"
+#include "sipcodecutils.h"
+#include "sipinternalstates.h"
+#include "MTransactionHeaders.h"
+#include "siprouteheader.h"
+#include "DialogsStore.h"
+#include "SipAssert.h"
+#include "RefreshItem.h"
+#include "TransactionItem.h"
+#include "TransactionItemStore.h"
+#include "Establishing.h"
+#include "Early.h"
+#include "Confirmed.h"
+#include "Terminated.h"
+#include "CSigCompMgr.h"
+#include "sipstrings.h"
+#include "sipstrconsts.h"
+#include "siperr.h"
+#include "TSIPTransportParams.h"
+
+_LIT8(KLocalHostSIPURI, "sip:localhost");
+const TUint K100Response = 100;
+const TUint K400Response = 400;
+const TUint K481Response = 481;
+
+
+// -----------------------------------------------------------------------------
+// CSipDialogMgr::NewL
+// -----------------------------------------------------------------------------
+//
+CSipDialogMgr* CSipDialogMgr::NewL(
+    MTransactionUser& aTU,
+    MSipRefreshMgr& aRefreshMgr,
+    MSipRegistrationContact& aRegistrationContact,
+    CSIPSec& aSIPSec,
+    MSigComp& aSigComp)
+	{
+	CSipDialogMgr* self = new(ELeave)CSipDialogMgr(aTU,aRefreshMgr, 
+                                                   aRegistrationContact,
+                                                   aSIPSec, aSigComp);	
+	CleanupStack::PushL(self);	
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogMgr::CSipDialogMgr
+// -----------------------------------------------------------------------------
+//
+CSipDialogMgr::CSipDialogMgr (MTransactionUser& aTU,  
+                              MSipRefreshMgr& aRefreshMgr,
+							  MSipRegistrationContact& aRegistratinonContact,
+							  CSIPSec& aSIPSec,
+							  MSigComp& aSigComp)
+: iTU(aTU), 
+  iRefreshMgr(aRefreshMgr), 
+  iRegistrationContact(aRegistratinonContact),
+  iSIPSec(aSIPSec),
+  iSigComp(aSigComp)
+	{
+	iContactHeaderName = SIPStrings::StringF(SipStrConsts::EContactHeader);
+	iRouteHeaderName = SIPStrings::StringF(SipStrConsts::ERouteHeader);
+	iTagParamName = SIPStrings::StringF(SipStrConsts::ETag);
+    iPhraseCallTransactionDoesNotExist = 
+        SIPStrings::StringF(SipStrConsts::EPhraseCallTransactionDoesNotExist);
+    iPhraseBadRequest = SIPStrings::StringF(SipStrConsts::EPhraseBadRequest);
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogMgr::ConstructL
+// -----------------------------------------------------------------------------
+//
+void CSipDialogMgr::ConstructL ()
+	{
+	iDialogsStore = CDialogsStore::NewL();
+	iDeleteMgr = CDeleteMgr::NewL();
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogMgr::~CSipDialogMgr
+// -----------------------------------------------------------------------------
+//
+CSipDialogMgr::~CSipDialogMgr ()
+	{
+	delete iDialogsStore;
+	delete iDeleteMgr;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogMgr::SendAndCreateDialogL
+// -----------------------------------------------------------------------------
+//
+void CSipDialogMgr::SendAndCreateDialogL (TTransactionId& aTransactionId,
+                                          TRefreshId& aRefreshId,
+                                          TRegistrationId aRegistrationId,
+                                          TDialogId& aDialogId,
+                                          CSIPRequest* aRequest,
+                                          CURIContainer& aRemoteTarget,
+                                          MDialogOwner* aOwner,
+                                          MSIPSecUser& aSIPSecUser,
+                                          TBool aRefresh)	
+	{
+    __SIP_ASSERT_LEAVE(aOwner, KErrArgument);
+	__SIP_ASSERT_LEAVE(aRequest, KErrArgument);
+	__SIP_ASSERT_LEAVE(aRequest->To(), KErrSIPMalformedMessage);
+	__SIP_ASSERT_LEAVE(aRequest->From(), KErrSIPMalformedMessage);
+	__SIP_ASSERT_LEAVE(aRequest->Method().DesC().Length() > 0, 
+                       KErrSIPMalformedMessage);
+	__SIP_ASSERT_LEAVE(aRequest->HeaderCount(iContactHeaderName) <= 1,
+                       KErrSIPMalformedMessage);
+	__SIP_MESSAGE_LOG("Dialogs", *aRequest)
+
+    TBool newDialogCreated = EFalse;
+    CSipDialogItem* dialog = iDialogsStore->FindDialogItem(aDialogId,aOwner);
+    if (!dialog)
+        {
+	    dialog = CSipDialogItem::NewLC(*iDialogsStore,aOwner,aSIPSecUser,iTU,
+                                       iRefreshMgr,iSIPSec,*iDeleteMgr,
+                                       iSigComp,aRegistrationId);
+        newDialogCreated = ETrue;
+        }
+
+	dialog->SetLocalAddressL(aRequest->From()->SIPAddress());
+	dialog->SetRemoteAddressL(aRequest->To()->SIPAddress());
+	dialog->SetInitialRemoteTargetL(aRemoteTarget);
+	dialog->SetRouteSetUsingRouteL(*aRequest);
+	AddContactHeaderL(dialog->IapId(),aRegistrationId,
+	                  *aRequest,aRequest->From());
+	dialog->SetLocalTargetWithMsgL(*aRequest,EFalse);
+
+    CTransactionItemBase* transactionItem = 0;
+	if (aRefresh)
+		{
+        transactionItem = CRefreshItem::NewLC(iRefreshMgr,dialog,
+                                              *dialog,aRequest->Method());
+		}
+	else
+		{
+        transactionItem = CTransactionItem::NewLC(iTU,dialog,
+                                                  aRequest->Method());
+        }
+    transactionItem->SetTargetRefresh();
+
+	dialog->CurrentState().SendL(aTransactionId,aRequest,*transactionItem,
+	                             *dialog->RemoteTarget());
+    
+    dialog->TransactionItems().AddItem(transactionItem);
+    CleanupStack::Pop(transactionItem);
+    dialog->SetFirstTransactionId(aTransactionId);
+    
+    if (newDialogCreated)
+        {
+        aDialogId = dialog->DialogId();
+	    iDialogsStore->AddDialogItem(dialog);
+	    CleanupStack::Pop(dialog);
+        }
+	
+	if (aRefresh)
+	    {
+	    aRefreshId = static_cast<CRefreshItem*>(transactionItem)->RefreshId();
+	    }
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogMgr::SendWithinDialogL
+// -----------------------------------------------------------------------------
+//
+void CSipDialogMgr::SendWithinDialogL (TTransactionId& aTransactionId,
+                                       TRefreshId& aRefreshId,
+                                       const TDialogId& aDialogId,
+                                       CSIPRequest* aRequest,
+                                       const MDialogOwner* aOwner,
+                                       TBool aRefresh,
+                                       TBool aAllowOverlap, 
+                                       TBool aTargetRefresh)
+	{
+	__SIP_ASSERT_LEAVE(aDialogId, KErrArgument);
+	__SIP_ASSERT_LEAVE(aRequest, KErrArgument);
+	__SIP_ASSERT_LEAVE(aRequest->Method().DesC().Length() != 0, 
+                       KErrSIPMalformedMessage);
+	__SIP_ASSERT_LEAVE(aRequest->HeaderCount(iContactHeaderName) <= 1, 
+                       KErrSIPMalformedMessage);
+	__ASSERT_ALWAYS(!aRequest->HasHeader(iRouteHeaderName), 
+                    User::Leave(KErrSIPMalformedMessage));
+	
+	CSipDialogItem* dialog = iDialogsStore->FindDialogItem(aDialogId,aOwner);
+	__ASSERT_ALWAYS(dialog, User::Leave(KErrSIPInvalidDialogState));
+	__ASSERT_ALWAYS(dialog->CurrentState().RequestsWithinDialogAllowed(),
+					User::Leave(KErrSIPInvalidDialogState));
+
+	RStringF method = aRequest->Method();
+	if (dialog->TransactionItems().OverlappingRestricted(method))
+        {
+		User::Leave(KErrSIPRequestPending);
+        }
+
+	__SIP_MESSAGE_LOG("Dialogs", *aRequest)
+	
+	dialog->AddToHeaderInDialogL(*aRequest);
+	dialog->AddFromHeaderInDialogL(*aRequest);
+	dialog->AddCallIdHeaderInDialogL(*aRequest);
+	dialog->AddRouteToMessageL(*aRequest);
+	AddContactHeaderL(*dialog,*aRequest,aRequest->From(),aTargetRefresh);
+	if (aTargetRefresh)
+		{
+		dialog->UpdateLocalTargetL(*aRequest);
+		}
+	if (method != SIPStrings::StringF(SipStrConsts::EAck))
+        {
+		dialog->AddCSeqHeaderInDialogL(*aRequest);
+        }		
+	
+    CTransactionItemBase* transactionItem = 0;
+	if (aRefresh)
+		{
+        transactionItem = 
+			CRefreshItem::NewLC(iRefreshMgr,dialog,*dialog,method);
+		}
+    else
+        {
+        transactionItem = CTransactionItem::NewLC(iTU,dialog,method);
+        }
+    transactionItem->SetOverlappingRestricted(!aAllowOverlap);
+    transactionItem->SetTargetRefresh(aTargetRefresh);
+
+	dialog->CurrentState().SendL(aTransactionId,aRequest,*transactionItem,
+	                             *dialog->RemoteTarget());
+
+    dialog->TransactionItems().AddItem(transactionItem);
+	CleanupStack::Pop(transactionItem);
+	if (aRefresh)
+	    {
+	    aRefreshId = static_cast<CRefreshItem*>(transactionItem)->RefreshId();
+	    }
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogMgr::SendAndUpdateRefreshL
+// -----------------------------------------------------------------------------
+//
+void CSipDialogMgr::SendAndUpdateRefreshL (TTransactionId& aTransactionId,
+                                           const TRefreshId& aRefreshId,
+                                           const TDialogId& aDialogId,
+                                           CSIPRequest* aRequest,
+                                           const MDialogOwner* aOwner)
+    {
+	__SIP_ASSERT_LEAVE(aRefreshId, KErrArgument);
+	__SIP_ASSERT_LEAVE(aDialogId, KErrArgument);
+	__SIP_ASSERT_LEAVE(aRequest, KErrArgument);
+	__SIP_ASSERT_LEAVE(aRequest->HeaderCount(iContactHeaderName) <= 1, 
+                       KErrSIPMalformedMessage);
+	__ASSERT_ALWAYS (!aRequest->HasHeader(iRouteHeaderName), 
+                     User::Leave(KErrSIPMalformedMessage));
+	
+	CSipDialogItem* dialog = iDialogsStore->FindDialogItem(aDialogId,aOwner);
+	__ASSERT_ALWAYS(dialog, User::Leave(KErrSIPInvalidDialogState));
+	__ASSERT_ALWAYS(dialog->CurrentState().RequestsWithinDialogAllowed(),
+					User::Leave(KErrSIPInvalidDialogState));
+
+    CTransactionItemBase* refreshItem = 
+        dialog->TransactionItems().FindRefreshItem(aRefreshId);
+    __ASSERT_ALWAYS(refreshItem,User::Leave(KErrSIPInvalidTransactionState));
+
+	__SIP_MESSAGE_LOG("Dialogs", *aRequest)
+	
+	dialog->AddToHeaderInDialogL(*aRequest);
+	dialog->AddFromHeaderInDialogL(*aRequest);
+	dialog->AddCallIdHeaderInDialogL(*aRequest);
+    if (aRequest->Method().DesC().Length() == 0)
+        {
+        aRequest->SetMethodL(refreshItem->Method());
+        }
+	dialog->AddRouteToMessageL(*aRequest);
+    TBool targetRefresh = refreshItem->TargetRefresh();
+	AddContactHeaderL(*dialog,*aRequest,aRequest->From(),targetRefresh);
+	if (targetRefresh)
+		{
+		dialog->UpdateLocalTargetL(*aRequest);
+		}
+	dialog->CurrentState().SendL(aTransactionId,aRequest,*refreshItem,
+	                             *dialog->RemoteTarget());
+    }
+
+// -----------------------------------------------------------------------------
+// CSipDialogMgr::SendAndCreateDialogL
+// -----------------------------------------------------------------------------
+//
+void CSipDialogMgr::SendAndCreateDialogL (const TTransactionId& aTransactionId,
+										  TRegistrationId aRegistrationId,
+                                          TDialogId& aDialogId,
+                                          CSIPResponse* aResponse,
+                                          MDialogOwner* aOwner,
+                                          MSIPSecUser& aSIPSecUser)
+	{
+	__SIP_ASSERT_LEAVE (aTransactionId != 0, KErrArgument);
+	__SIP_ASSERT_LEAVE (!aDialogId, KErrNotSupported);
+	__SIP_ASSERT_LEAVE (aResponse, KErrArgument);
+	__SIP_ASSERT_LEAVE (aOwner, KErrArgument);
+	__SIP_ASSERT_LEAVE (aResponse->ResponseCode() > K100Response, KErrArgument);
+
+	__SIP_MESSAGE_LOG("Dialogs", *aResponse)
+	
+	
+	CSipDialogItem* dialog = 
+        CSipDialogItem::NewLC(*iDialogsStore,aOwner,aSIPSecUser,
+                              iTU,iRefreshMgr,iSIPSec,*iDeleteMgr,iSigComp, aRegistrationId);
+    TSIPTransportParams transportParams(
+        dialog->TransportParams(aRegistrationId));
+    
+	MTransactionHeaders* trHeaders = iTU.TransactionHeadersL(aTransactionId);
+	__ASSERT_ALWAYS(trHeaders, User::Leave(KErrSIPInvalidTransactionState));
+    TCleanupItem cleanupItem(DeleteTransactionHeaders,trHeaders);
+	CleanupStack::PushL (cleanupItem);
+
+	// Remote target 
+    CSIPContactHeader* remoteContact = 
+        ExtractContactL(aTransactionId,*trHeaders,transportParams,ETrue);
+    CleanupStack::PushL(remoteContact);
+	dialog->SetRemoteTargetL(remoteContact->SIPAddress()->URI());
+	CleanupStack::PopAndDestroy(remoteContact);
+
+	// Remote CSeq
+	dialog->SetRemoteSeqNum(trHeaders->CSeqNumber());
+
+	// Call-ID 
+	CSIPCallIDHeader* callId = trHeaders->CallIDHeader();
+	__SIP_ASSERT_LEAVE(callId, KErrSIPInvalidDialogRequest);
+	dialog->SetCallId(callId);
+
+    // Route-set
+	RPointerArray<CSIPRouteHeaderBase>* route = trHeaders->RecordRoute();
+	if (route)
+		{
+		TCleanupItem routeCleanupItem(DeleteRouteSet,route);
+		CleanupStack::PushL (routeCleanupItem);
+		CheckRecordRouteL(aTransactionId,*route,transportParams);
+		dialog->SetRouteSetL(*route);
+		CleanupStack::PopAndDestroy(1);// routeCleanupItem
+		}
+
+    // From
+	CSIPFromHeader* from = trHeaders->FromHeader();
+	CleanupStack::PushL(from);
+	__SIP_ASSERT_LEAVE(from, KErrSIPInvalidDialogRequest);
+	dialog->SetRemoteAddressL(from->SIPAddress());
+	if (from->HasParam(iTagParamName))
+        {
+		dialog->SetRemoteTagL(from);
+        }
+	aResponse->AddHeaderL(from);
+	CleanupStack::Pop(from);
+
+	// To
+	CSIPToHeader* to = trHeaders->ToHeader();
+	CleanupStack::PushL(to);
+	__SIP_ASSERT_LEAVE(to, KErrSIPInvalidDialogRequest);    
+	dialog->SetLocalAddressL(to->SIPAddress());
+	if (!to->HasParam(iTagParamName))
+        {
+		HBufC8* tagBuf = HBufC8::NewLC(MTransactionUser::KTagLength);
+		TPtr8 tagPtr = tagBuf->Des();
+		iTU.MakeTagL(tagPtr);
+		RStringF tag = SIPStrings::Pool().OpenFStringL(tagPtr);
+		CleanupClosePushL(tag);
+        to->SetParamL(iTagParamName,tag);
+        CleanupStack::PopAndDestroy(); // tag
+        CleanupStack::PopAndDestroy(tagBuf); 
+		}
+	dialog->SetLocalTag(to->ParamValue(iTagParamName));
+	aResponse->AddHeaderL(to);
+	CleanupStack::Pop(to);
+
+	// Local target (Contact)
+	CURIContainer* requestURI = trHeaders->RequestURI();
+	__SIP_ASSERT_LEAVE(requestURI, KErrSIPInvalidDialogRequest);
+	CleanupStack::PushL(requestURI);
+	if (!aResponse->IsErrorResponse())
+	    {
+	    AddContactHeaderL(dialog->IapId(),*aResponse,aResponse->To(),
+	                      *requestURI);
+	    }
+	CleanupStack::PopAndDestroy(requestURI);
+	dialog->SetLocalTargetWithMsgL(*aResponse);
+
+	dialog->AddRecordRouteToMessageL(*aResponse);
+	dialog->AddCallIdHeaderInDialogL(*aResponse);
+	dialog->SetFirstTransactionId(aTransactionId);
+
+    CTransactionItem* transactionItem = 
+        CTransactionItem::NewLC(iTU,dialog,aTransactionId);
+	dialog->CurrentState().SendL(*transactionItem,aResponse);
+    dialog->TransactionItems().AddItem(transactionItem);
+	iDialogsStore->AddDialogItem(dialog);
+
+    aDialogId = dialog->DialogId();
+
+    CleanupStack::Pop(transactionItem); 
+    CleanupStack::PopAndDestroy(); // trHeaders
+    CleanupStack::Pop(dialog);
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogMgr::SendWithinDialogL
+// -----------------------------------------------------------------------------
+//
+void CSipDialogMgr::SendWithinDialogL (const TTransactionId& aTransactionId,
+                                       const TDialogId& aDialogId,
+                                       CSIPResponse* aResponse,
+                                       const MDialogOwner* aOwner,
+                                       TBool aTargetRefresh)
+	{
+	__SIP_ASSERT_LEAVE (aTransactionId, KErrArgument);
+	__SIP_ASSERT_LEAVE (aDialogId, KErrSIPInvalidDialogState);
+	__SIP_ASSERT_LEAVE (aResponse, KErrArgument);
+	__SIP_ASSERT_LEAVE (aResponse->ResponseCode() > K100Response, KErrArgument);
+
+	__SIP_MESSAGE_LOG("Dialogs", *aResponse)
+
+	CSipDialogItem* dialog = iDialogsStore->FindDialogItem(aDialogId,aOwner);
+	__ASSERT_ALWAYS(dialog, User::Leave(KErrSIPInvalidDialogState));
+    CTransactionItemBase* transactionItem = 
+        dialog->TransactionItems().FindItem(aTransactionId);
+    __ASSERT_ALWAYS(transactionItem,
+                    User::Leave(KErrSIPInvalidTransactionState));
+
+	MTransactionHeaders* trHeaders = iTU.TransactionHeadersL(aTransactionId);
+	__ASSERT_ALWAYS(trHeaders, User::Leave(KErrSIPInvalidTransactionState));
+    TCleanupItem cleanupItem(DeleteTransactionHeaders,trHeaders);
+	CleanupStack::PushL (cleanupItem);
+ 
+    // To
+	CSIPToHeader* to = trHeaders->ToHeader();
+	CleanupStack::PushL(to);
+	if (!to->HasParam(iTagParamName))
+		{
+		to->SetParamL(iTagParamName,dialog->LocalTag());
+		}
+	aResponse->AddHeaderL(to);
+	CleanupStack::Pop(to);
+    
+    // Add Record-Route only to the responses to the first transaction
+    if (aTransactionId == dialog->FirstTransactionId())
+        {
+	    dialog->AddRecordRouteToMessageL(*aResponse);
+        }
+
+    // Remote and local target
+	if (!aResponse->IsErrorResponse())
+	    {    
+        AddContactHeaderL(*dialog,*aResponse,aResponse->To(),aTargetRefresh);
+	    }
+	if (aTargetRefresh && aResponse->Type() == CSIPResponse::E2XX)
+		{		
+		CSIPContactHeader* remoteContact = 
+		    ExtractContactL(aTransactionId,*trHeaders,
+                            dialog->TransportParams(KEmptyRegistrationId),
+                            EFalse);
+		if (remoteContact) 
+		    {
+		    CleanupStack::PushL(remoteContact);
+            CURIContainer& remoteTarget = remoteContact->SIPAddress()->URI();
+    	    dialog->SetRemoteTargetL(remoteTarget);
+    		CleanupStack::PopAndDestroy(remoteContact);		    
+		    }    
+		dialog->UpdateLocalTargetL(*aResponse);
+		}
+    CleanupStack::PopAndDestroy(); // trHeaders
+	dialog->CurrentState().SendL(*transactionItem, aResponse);	
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogMgr::TerminateDialog
+// -----------------------------------------------------------------------------
+//
+TInt CSipDialogMgr::TerminateDialog (const TDialogId& aDialogId,
+                                     const MDialogOwner* aOwner)
+	{
+	CSipDialogItem* dialog = iDialogsStore->FindDialogItem(aDialogId,aOwner);
+	if(!dialog) 
+        {
+		return KErrNotFound;
+        }
+	return iDialogsStore->Remove(dialog);
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogMgr::TerminateDialogsFor
+// -----------------------------------------------------------------------------
+//
+TInt CSipDialogMgr::TerminateDialogsFor (const MDialogOwner* aOwner)
+    {
+    return iDialogsStore->RemoveAllWith(aOwner);
+    }
+
+// -----------------------------------------------------------------------------
+// CSipDialogMgr::TerminateDialogRefresh
+// -----------------------------------------------------------------------------
+//
+TInt CSipDialogMgr::TerminateDialogRefresh (const TDialogId& aDialogId,
+											const TRefreshId& aRefreshId,
+											const MDialogOwner* aOwner)
+    {
+	CSipDialogItem* dialog = iDialogsStore->FindDialogItem(aDialogId,aOwner);
+    if (!dialog)
+        {
+        return KErrNotFound;
+        }
+    CTransactionItemBase* refreshItem = 
+        dialog->TransactionItems().FindRefreshItem(aRefreshId);
+    if (!refreshItem)
+        {
+        return KErrNotFound;
+        }
+    return dialog->TransactionItems().RemoveItem(refreshItem->Id());
+    }
+
+// -----------------------------------------------------------------------------
+// CSipDialogMgr::GetStateL
+// -----------------------------------------------------------------------------
+//
+void CSipDialogMgr::GetStateL (const TDialogId& aDialogId, 
+                               CSIPInternalStates::TState& aState)
+    {
+	CSipDialogItem* dialog = iDialogsStore->FindDialogItem(aDialogId);
+    if (!dialog)
+        {
+        User::Leave(KErrNotFound);
+        }
+	dialog->CurrentState().GetState(aState);
+    }
+    
+// -----------------------------------------------------------------------------
+// CSipDialogMgr::CallIDL
+// -----------------------------------------------------------------------------
+//    
+const CSIPCallIDHeader& CSipDialogMgr::CallIDL (const TDialogId& aDialogId,
+                                                const MDialogOwner* aOwner)
+    {
+	CSipDialogItem* dialog = iDialogsStore->FindDialogItem(aDialogId,aOwner);
+    if (!dialog)
+        {
+	    User::Leave(KErrNotFound);
+        }
+    if (!dialog->CallId())
+        {
+	    User::Leave(KErrNotFound);
+        }         
+    return *(dialog->CallId());
+    }
+    
+// -----------------------------------------------------------------------------
+// CSipDialogMgr::LocalTagL
+// -----------------------------------------------------------------------------
+//     
+const TDesC8& CSipDialogMgr::LocalTagL(const TDialogId& aDialogId,
+	                                   const MDialogOwner* aOwner)
+    {
+	CSipDialogItem* dialog = iDialogsStore->FindDialogItem(aDialogId,aOwner);
+    if (!dialog)
+        {
+	    User::Leave(KErrNotFound);
+        }
+    return dialog->LocalTag().DesC();
+    }
+
+// -----------------------------------------------------------------------------
+// CSipDialogMgr::ResetStateL
+// -----------------------------------------------------------------------------
+//
+void CSipDialogMgr::ResetStateL(const TDialogId& aDialogId,
+                                const MDialogOwner* aOwner)
+    {
+	CSipDialogItem* dialog = iDialogsStore->FindDialogItem(aDialogId,aOwner);
+    if (!dialog)
+        {
+	    User::Leave(KErrNotFound);
+        }
+    dialog->ResetStateL();
+    }
+
+// -----------------------------------------------------------------------------
+// CSipDialogMgr::SIPSecUserForTransaction
+// -----------------------------------------------------------------------------
+//
+const MSIPSecUser* CSipDialogMgr::SIPSecUserForTransaction(
+    const TTransactionId& aTransactionId)
+    {
+    return iDialogsStore->FindDialogItemByTransaction(aTransactionId);
+    }
+
+// -----------------------------------------------------------------------------
+// CSipDialogMgr::TransactionOwnerL
+// -----------------------------------------------------------------------------
+//
+MTransactionOwner* CSipDialogMgr::TransactionOwnerL (CSIPRequest& aRequest,
+													 CSIPResponse** aResponse)
+	{
+	if (aRequest.To() && !(aRequest.To()->HasParam(iTagParamName)))
+        {
+		return 0;
+        }
+	CSipDialogItem* dialog = iDialogsStore->DialogItemForRequest(&aRequest);
+	if (!dialog)
+		{
+		*aResponse = 
+		    CSIPResponse::NewL(K481Response,iPhraseCallTransactionDoesNotExist);
+		}
+	return dialog;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogMgr::ConnectionStateChangedL
+// -----------------------------------------------------------------------------
+//
+void CSipDialogMgr::ConnectionStateChangedL (TUint32 aIapId,
+											 CSIPConnection::TState aState)
+	{
+	if (aState == CSIPConnection::EInactive ||
+        aState == CSIPConnection::EUnavailable)
+        {
+		iDialogsStore->DeleteItemsWithThisIapId(aIapId);
+        }
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogMgr::ExtractContactL
+// -----------------------------------------------------------------------------
+//
+CSIPContactHeader* CSipDialogMgr::ExtractContactL (
+    TTransactionId aTransactionId,
+    MTransactionHeaders& aHeaders,
+    const TSIPTransportParams& aParams,
+    TBool aContactMandatory)
+    {
+    RPointerArray<CSIPContactHeader>* contacts = aHeaders.Contact();
+    TCleanupItem contactsCleanupItem(DeleteContacts,contacts);
+	CleanupStack::PushL(contactsCleanupItem);    
+    CSIPContactHeader* contact = NULL; 
+    if (contacts && contacts->Count() == 1)
+        {
+        contact = (*contacts)[0];
+        contacts->Remove(0);
+        CleanupStack::PushL(contact);
+        if (!CSipDialogItem::ContactOk(*contact))
+            {
+            SendErrorResponseAndLeaveL(aTransactionId,
+                                       KErrSIPInvalidURIType,
+                                       aParams);
+            }
+        CleanupStack::Pop(contact);      
+        }
+    if (!contact && aContactMandatory)
+        {
+        SendErrorResponseAndLeaveL(aTransactionId,
+                                   KErrSIPInvalidDialogRequest,
+                                   aParams);
+        }
+    CleanupStack::PopAndDestroy(1); // contactsCleanupItem
+    return contact;
+    }
+    
+// -----------------------------------------------------------------------------
+// CSipDialogMgr::CheckRecordRouteL
+// -----------------------------------------------------------------------------
+//    
+void CSipDialogMgr::CheckRecordRouteL (
+    TTransactionId aTransactionId,
+    RPointerArray<CSIPRouteHeaderBase>& aRecordRoute,
+    const TSIPTransportParams& aParams)
+    {
+    // For an incoming request creating a dialog it must be checked 
+    // that the first Record-Route-header (the next hop) has a SIP-URI.
+    TInt count = aRecordRoute.Count();
+    if (count > 0)
+        {
+        CSIPRouteHeaderBase* nextHop = aRecordRoute[0];
+        if (!nextHop->SIPAddress().URI().IsSIPURI())
+            {
+            SendErrorResponseAndLeaveL(aTransactionId,KErrSIPInvalidURIType,
+                                       aParams);      
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSipDialogMgr::AddContactHeaderL
+// -----------------------------------------------------------------------------
+//
+void CSipDialogMgr::AddContactHeaderL (TUint32 aIapId,
+                                       TRegistrationId aRegistrationId,
+									   CSIPRequest& aRequest,
+									   const CSIPFromHeader* aFrom)
+	{
+	if (!aRequest.HasHeader(iContactHeaderName))
+		{
+		CreateAndAddContactL(aIapId,aRegistrationId,aRequest,aFrom);
+		}
+	else
+		{
+		FillHostInContactL(aIapId,aRegistrationId,aRequest,aFrom);
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogMgr::AddContactHeaderL
+// -----------------------------------------------------------------------------
+//
+void CSipDialogMgr::AddContactHeaderL (TUint32 aIapId,
+									   CSIPResponse& aResponse,
+									   const CSIPToHeader* aTo,
+									   const CURIContainer& aRequestUri)
+	{
+	if (!aResponse.HasHeader(iContactHeaderName))
+		{
+		CreateAndAddContactL(aRequestUri,aResponse);
+		}
+	else
+		{
+		FillHostInContactL(aIapId,KEmptyRegistrationId,aResponse,aTo);
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogMgr::AddContactHeaderL
+// -----------------------------------------------------------------------------
+//
+void CSipDialogMgr::AddContactHeaderL (CSipDialogItem& aDialog, 
+                                       CSIPMessage& aMessage,
+									   const CSIPFromToHeaderBase* aFromTo,
+                                       TBool aTargetRefresh)
+	{
+	if (!aMessage.HasHeader(iContactHeaderName))
+		{
+		if (aTargetRefresh)
+            {
+ 	        CSIPContactHeader* contact = 
+ 	            static_cast<CSIPContactHeader*>(
+ 	                aDialog.LocalTarget()->CloneL());
+	        CleanupStack::PushL(contact);
+	        aMessage.AddHeaderL(contact);
+	        CleanupStack::Pop(contact);
+            }
+		}
+	else
+		{
+		FillHostInContactL(aDialog.IapId(),aDialog.RegistrationId(),
+		                   aMessage,aFromTo);
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogMgr::CreateAndAddContactL
+// -----------------------------------------------------------------------------
+//
+void CSipDialogMgr::CreateAndAddContactL (TUint32 aIapId,
+                                          TRegistrationId aRegistrationId,
+                                          CSIPMessage& aMessage,
+                                          const CSIPFromToHeaderBase* aFromTo)
+	{
+	// Create and and Contact with empty host
+	CURIContainer* uri = CURIContainer::DecodeL(KLocalHostSIPURI);
+	CleanupStack::PushL(uri);
+	CreateAndAddContactL(*uri,aMessage);
+	CleanupStack::PopAndDestroy(uri);
+	// Fill host
+	FillHostInContactL(aIapId,aRegistrationId,aMessage,aFromTo);
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogMgr::FillHostInContactL
+// -----------------------------------------------------------------------------
+//
+void CSipDialogMgr::FillHostInContactL (TUint32 aIapId,
+                                        TRegistrationId aRegistrationId,
+										CSIPMessage& aMessage,
+										const CSIPFromToHeaderBase* aFromTo)
+	{
+	__SIP_ASSERT_LEAVE (aFromTo != 0, KErrArgument);	
+	
+	CSIPContactHeader* contact = 
+        static_cast<CSIPContactHeader*>(
+            aMessage.Header(iContactHeaderName,0));
+
+	__SIP_ASSERT_LEAVE (contact != 0, KErrArgument);
+	__SIP_ASSERT_LEAVE (contact->SIPAddress() != 0, KErrArgument);
+
+    TPtrC8 localHost(SIPStrings::StringF(SipStrConsts::ELocalHost).DesC());
+
+    CSIPURI* contactUri = contact->SIPAddress()->URI().SIPURI();
+    if (contactUri && contactUri->HostPort().Host().CompareF(localHost) == 0)
+		{ 
+		// if contact header does not have host --> add it
+		iRegistrationContact.ContactL(aIapId,aRegistrationId,aFromTo,*contact);
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogMgr::CreateContactL
+// -----------------------------------------------------------------------------
+//
+void CSipDialogMgr::CreateAndAddContactL (const CURIContainer& aUri,
+										  CSIPMessage& aMessage)
+	{
+	CURIContainer* uri = CURIContainer::NewLC(aUri);
+	CSIPAddress* sipAddress = SIPCodecUtils::CreateSIPAddressLC(uri);
+	CleanupStack::Pop(sipAddress);
+	CleanupStack::Pop(uri);
+	CleanupStack::PushL(sipAddress);
+	CSIPContactHeader* contact = CSIPContactHeader::NewL(sipAddress);
+	CleanupStack::Pop(sipAddress);
+	CleanupStack::PushL(contact);
+	aMessage.AddHeaderL(contact);
+	CleanupStack::Pop(contact);
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogMgr::SendErrorResponseAndLeaveL
+// -----------------------------------------------------------------------------
+//	
+void CSipDialogMgr::SendErrorResponseAndLeaveL (
+    TTransactionId aTransactionId,
+    TInt aLeaveCode,
+    const TSIPTransportParams& aParams)
+    {
+    CSIPResponse* response = 
+        CSIPResponse::NewLC(K400Response,iPhraseBadRequest);
+    iTU.SendL(aTransactionId, response, aParams);
+    CleanupStack::Pop(response); // ownership given to TU 
+    iTU.ClearTransactionOwner(aTransactionId);
+    User::Leave(aLeaveCode);    
+    }
+
+// -----------------------------------------------------------------------------
+// CSipDialogMgr::DeleteTransactionHeaders
+// -----------------------------------------------------------------------------
+//
+void CSipDialogMgr::DeleteTransactionHeaders (TAny* aTransactionHeaders)
+	{
+	MTransactionHeaders* transactionHeaders = 
+        reinterpret_cast<MTransactionHeaders*>(aTransactionHeaders);
+    delete transactionHeaders;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogMgr::DeleteRouteSet
+// -----------------------------------------------------------------------------
+//
+void CSipDialogMgr::DeleteRouteSet (TAny* aRouteSet)
+	{
+    RPointerArray<CSIPRouteHeaderBase>* routeSet =
+        reinterpret_cast<RPointerArray<CSIPRouteHeaderBase>*>(aRouteSet);
+    if (routeSet)
+        {
+        routeSet->ResetAndDestroy();
+        }
+	delete routeSet;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipDialogMgr::DeleteContacts
+// -----------------------------------------------------------------------------
+//
+void CSipDialogMgr::DeleteContacts (TAny* aContacts)
+	{
+    RPointerArray<CSIPContactHeader>* contacts =
+        reinterpret_cast<RPointerArray<CSIPContactHeader>*>(aContacts);
+    if (contacts)
+        {
+        contacts->ResetAndDestroy();
+        }
+	delete contacts;
+	}