realtimenetprots/sipfw/SIP/Registration/src/CSIPRegistrationBindingBase.cpp
changeset 0 307788aac0a8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/realtimenetprots/sipfw/SIP/Registration/src/CSIPRegistrationBindingBase.cpp	Tue Feb 02 01:03:15 2010 +0200
@@ -0,0 +1,1139 @@
+// 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          : CSIPRegistrationBindingBase.cpp
+// Part of       : Registration
+// Version       : SIP/6.0
+//
+
+
+
+#include "CSIPRegistrationRefreshBinding.h"
+#include "CSIPRegistrationBinding.h"
+#include "TSIPRegistrationUtility.h"
+#include "CSIPRegistrar.h"
+#include "CSIPRegistrarStore.h"
+#include "CSIPRegistrationBindingStore.h"
+#include "CSIPResponseUtility.h"
+#include "MRegistrationOwner.h"
+#include "sipresponse.h"
+#include "siprequest.h"
+#include "siptoheader.h"
+#include "sipfromheader.h"
+#include "sipaddress.h"
+#include "sipcontactheader.h"
+#include "uricontainer.h"
+#include "sipuri.h"
+#include "siphostport.h"
+#include "siprouteheader.h"
+#include "sipminexpiresheader.h"
+#include "sipservicerouteheader.h"
+#include "sippassociateduriheader.h"
+#include "MSigComp.h"
+#include "sipsec.h"
+#include "siperr.h"
+#include "SipLogs.h"
+#include "SipAssert.h"
+#include "sipcodecutils.h"
+#include "sipstrings.h"
+#include "sipstrconsts.h"
+#include "csipregistering.h"
+#include "csip423responsereceived.h"
+#include "csipregistered.h"
+#include "csipregisterupdating.h"
+#include "csipunregistering.h"
+#include "csipunregistered.h"
+#include "TSIPTransportParams.h"
+#include "MSIPTransportMgr.h"
+#include <utf.h>
+
+
+#define HEADER(H, M, N) static_cast<H*>((M).Header(N,0))
+const TUint KDefaultSipPort = 5060;
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::ConstructL
+// -----------------------------------------------------------------------------
+//
+void CSIPRegistrationBindingBase::ConstructL(CSIPRequest* aSIPRequest,
+											 CURIContainer& aRemoteTarget)
+	{
+	__ASSERT_ALWAYS (aSIPRequest, User::Leave (KErrArgument));
+    __ASSERT_ALWAYS (aSIPRequest->To(), User::Leave (KErrArgument));
+    __ASSERT_ALWAYS (aSIPRequest->From(), User::Leave (KErrArgument));
+
+	InitializeStatesL();
+
+	// copy to header from request
+	SetToHeaderL(*aSIPRequest);
+
+	// copy from header from request
+	SetFromHeaderL(*aSIPRequest);
+
+	// copy contact header from request.
+	SetContactHeaderL(*aSIPRequest);
+		
+	iRegistrationId = iBindingStore.NextRegistrationId();
+
+	iRegistrar = iBindingStore.RegistrarStore().FindRegistrar(aRemoteTarget);
+
+	if (!iRegistrar) // registrar not found
+		{
+		iRemoteTarget = CURIContainer::NewL(aRemoteTarget);
+		}
+	else
+		{
+		iRegistrar->AddRegistrationIdL(iRegistrationId);
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::InitializeStatesL
+// -----------------------------------------------------------------------------
+//
+void CSIPRegistrationBindingBase::InitializeStatesL()
+	{
+	iRegistering = CSIPRegistering::NewL(*this);
+	iRegistered = CSIPRegistered::NewL(*this);
+	iResponse423Received = CSIP423ResponseReceived::NewL(*this);
+	iUpdating = CSIPRegisterUpdating::NewL(*this);
+	iUnregistering = CSIPUnregistering::NewL(*this);
+	iUnregistered = CSIPUnregistered::NewL(*this);
+
+	// set registering neighbour states.
+	iRegistering->SetNeighbourStates(iResponse423Received, iRegistered,
+		iUnregistered);
+	// set current state to registering.
+	iCurrentState = iRegistering;
+	// set registered neighbour states.
+	iRegistered->SetNeighbourStates(iUpdating, iUnregistering, iUnregistered,
+		iResponse423Received);
+	// set response 423 received neighbour states.
+	iResponse423Received->SetNeighbourStates(iRegistered, iUnregistered);
+	// set unregistering states.
+	iUnregistering->SetNeighbourStates(iUnregistered);
+	// set updating states.
+	iUpdating->SetNeighbourStates(iResponse423Received, iRegistered,
+		iUnregistered);
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::CSIPRegistrationBindingBase
+// -----------------------------------------------------------------------------
+//
+CSIPRegistrationBindingBase::CSIPRegistrationBindingBase (
+    MTransactionUser&             aTransactionUser,
+	MSigComp&                     aSigComp,
+	CSIPSec&                      aSIPSec,
+	CSIPRegistrationBindingStore& aBindingStore,
+	MRegistrationOwner*           aRegistrationOwner,
+	MSIPSecUser&                  aSIPSecUser,
+	MSIPTransportMgr&             aTransportMgr,
+	TBool 						  aSendWithExpires,
+	TBool 						  aCacheOutboundProxyIP)
+  : iTransactionUser     (aTransactionUser),
+    iOwner               (aRegistrationOwner),
+    iRegistrationId      (KEmptyRegistrationId),
+	iSIPSecUser          (aSIPSecUser),    
+    iSigComp             (aSigComp),
+	iSIPSec              (aSIPSec),
+    iBindingStore        (aBindingStore),
+	iTransportMgr        (aTransportMgr),
+	iSendWithExpires     (aSendWithExpires),
+	iCacheOutboundProxyIP(aCacheOutboundProxyIP)
+	{
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::~CSIPRegistrationBindingBase
+// -----------------------------------------------------------------------------
+//
+CSIPRegistrationBindingBase::~CSIPRegistrationBindingBase()
+	{
+	if (iRegistrar)
+		{
+		iRegistrar->BindingRemoved(iRegistrationId);
+		}
+	FreeProxyTransportResources();
+	delete iPAssociatedURIHeader;
+	delete iOutboundProxy;
+	delete iOutboundProxyIP;
+	delete iTo;
+	delete iFrom;
+	delete iContact;
+	delete iRemoteTarget;
+	iRouteSet.ResetAndDestroy();
+	delete iRequest;
+
+	// delete register states
+	delete iRegistering;
+	delete iRegistered;
+	delete iResponse423Received;
+	delete iUpdating;
+	delete iUnregistering;
+	delete iUnregistered;
+	iTransportMgr.RemoveTransport(iTransportId);
+	iSIPSec.ClearCache(this);
+	iTransactionUser.FreeResources(*this);
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::PassOnlyRealmsToUser
+// From MSIPSecUser
+// -----------------------------------------------------------------------------
+//
+TBool CSIPRegistrationBindingBase::PassOnlyRealmsToUser() const
+    {
+    return iSIPSecUser.PassOnlyRealmsToUser();
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::RequestCredentialsL
+// From MSIPSecUser
+// -----------------------------------------------------------------------------
+//
+void CSIPRegistrationBindingBase::RequestCredentialsL(const TDesC8& aRealm)
+    {
+    iSIPSecUser.RequestCredentialsL(aRealm);
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::RequestCredentialsL
+// From MSIPSecUser
+// -----------------------------------------------------------------------------
+//
+void CSIPRegistrationBindingBase::RequestCredentialsL(
+    CSIPResponse& aResponse,
+    TTransactionId aTransactionId,
+    TRefreshId aRefreshId)
+    {
+    iSIPSecUser.RequestCredentialsL(aResponse,aTransactionId,aRefreshId);
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::TrustedUser
+// From MSIPSecUser
+// -----------------------------------------------------------------------------
+//
+const MSIPSecUser* CSIPRegistrationBindingBase::TrustedUser(
+    TRegistrationId /*aRegistrationId*/)
+    {
+    return NULL;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::ByPassSIPSec
+// From MSIPSecUser
+// -----------------------------------------------------------------------------
+//
+TBool CSIPRegistrationBindingBase::ByPassSIPSec() const
+    {
+    return iSIPSecUser.ByPassSIPSec();
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::FlowFailure
+// From MSIPNATBindingObserver
+// -----------------------------------------------------------------------------
+//
+void CSIPRegistrationBindingBase::FlowFailure(TInt /*aError*/)
+    {
+    iOwner->RegistrationError(iTransactionId,iRegistrationId,
+                              KErrSIPTransportFailure);
+    ChangeState(iUnregistered);
+    iTransactionUser.FreeResources(*this);
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::RefreshId
+// -----------------------------------------------------------------------------
+//	
+TRefreshId CSIPRegistrationBindingBase::RefreshId() const
+    {
+    return KEmptyRefreshId;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::SetRequest
+// -----------------------------------------------------------------------------
+//
+void CSIPRegistrationBindingBase::SetRequest (CSIPRequest* aSIPRequest)
+	{
+	delete iRequest;
+	iRequest = aSIPRequest;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::Owner
+// -----------------------------------------------------------------------------
+//
+const MRegistrationOwner* CSIPRegistrationBindingBase::Owner() const
+	{
+	return iOwner;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::RegisterPending
+// -----------------------------------------------------------------------------
+//
+TBool CSIPRegistrationBindingBase::RegisterPending () const
+	{
+	// return ETrue when binding is in following states.
+	return (iCurrentState == iRegistering ||
+		    iCurrentState == iUpdating ||
+			iCurrentState == iUnregistering ||
+			iCurrentState == iResponse423Received);
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::UpdateBindingFromResponseL
+// -----------------------------------------------------------------------------
+//
+void CSIPRegistrationBindingBase::UpdateBindingFromResponseL(
+	CSIPResponse& aResponse)
+	{
+	// no related registrar, create one, add registrar pointer to binding
+	if (!iRegistrar)
+		{
+		HBufC8* callId = CSIPResponseUtility::CallIdL(aResponse);
+		CleanupStack::PushL(callId);
+		iRegistrar = iBindingStore.RegistrarStore().CreateRegistrarL(
+			*iRemoteTarget, *callId,
+			CSIPResponseUtility::CSeqValueL(aResponse), iRegistrationId);
+		CleanupStack::PopAndDestroy(callId);
+		delete iRemoteTarget;
+		iRemoteTarget = NULL;
+		}
+
+    const RStringF KTagParam = SIPStrings::StringF(SipStrConsts::ETag);
+	if ((aResponse.From()) && (aResponse.From()->HasParam(KTagParam)))
+		{
+		iFrom->SetParamL(KTagParam,aResponse.From()->ParamValue(KTagParam));
+		}
+	SetRouteHeaderFromResponseL(aResponse);
+	SetPAssociatedURIFromResponseL(aResponse);
+	}
+
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::SetToHeaderL
+// -----------------------------------------------------------------------------
+//
+void CSIPRegistrationBindingBase::SetToHeaderL(CSIPRequest& aSIPRequest)
+	{
+    CSIPToHeader* to = aSIPRequest.To();
+	CSIPToHeader* tempTo = CSIPToHeader::NewL(*to);
+	delete iTo;
+	iTo = tempTo;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::SetFromHeaderL
+// -----------------------------------------------------------------------------
+//
+void CSIPRegistrationBindingBase::SetFromHeaderL(CSIPRequest& aSIPRequest)
+	{
+	CSIPFromHeader* fromHeader = aSIPRequest.From();
+
+	CSIPFromHeader* temp = CSIPFromHeader::NewL(*fromHeader);
+	delete iFrom;
+	iFrom = temp;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::SetContactHeaderL
+// -----------------------------------------------------------------------------
+//
+void CSIPRegistrationBindingBase::SetContactHeaderL(CSIPRequest& aSIPRequest)
+	{
+    const RStringF KContactHeaderName = 
+        SIPStrings::StringF(SipStrConsts::EContactHeader);	
+	
+    CSIPContactHeader* contact =
+        HEADER(CSIPContactHeader, aSIPRequest, KContactHeaderName);
+
+	CSIPContactHeader* tmp = static_cast<CSIPContactHeader*>(contact->CloneL());
+	CleanupStack::PushL(tmp);
+	if(iContact && tmp->ExpiresParameter() == KErrNotFound)
+		tmp->SetExpiresParameterL(iContact->ExpiresParameter());
+	delete iContact;
+	CleanupStack::Pop(tmp);
+	iContact = tmp;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::SetExpiresValueL
+// -----------------------------------------------------------------------------
+//
+void CSIPRegistrationBindingBase::SetExpiresValueL(CSIPRequest& aSIPRequest)
+	{
+    const RStringF KContactHeaderName = 
+        SIPStrings::StringF(SipStrConsts::EContactHeader);	
+	
+	CSIPContactHeader* contactHeader =
+        HEADER(CSIPContactHeader, aSIPRequest, KContactHeaderName);
+
+	iContact->SetExpiresParameterL(contactHeader->ExpiresParameter());
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::SetMinExpiresToRequestL
+// -----------------------------------------------------------------------------
+//
+void CSIPRegistrationBindingBase::SetMinExpiresToRequestL (
+	CSIPResponse& aResponse)
+	{
+    const RStringF KContactHeaderName = 
+        SIPStrings::StringF(SipStrConsts::EContactHeader);
+        	
+	// the request must not be empty
+	__SIP_ASSERT_LEAVE(iRequest, KErrArgument);
+	__SIP_ASSERT_LEAVE(iRequest->HasHeader(KContactHeaderName),
+		               KErrArgument);
+    // get the Min expires header from response
+	CSIPMinExpiresHeader* minExpiresHeader = HEADER(
+		CSIPMinExpiresHeader, aResponse, 
+		SIPStrings::StringF(SipStrConsts::EMinExpiresHeader));
+	// get contact header from request
+	CSIPContactHeader* contactInRequest = HEADER(
+	    CSIPContactHeader, *iRequest, KContactHeaderName);
+	// set the min expires value to contact in the original request
+	contactInRequest->SetExpiresParameterL(minExpiresHeader->Value());
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::SetRouteHeaderFromResponseL
+// -----------------------------------------------------------------------------
+//
+void CSIPRegistrationBindingBase::SetRouteHeaderFromResponseL(
+    CSIPResponse& aResponse)
+	{
+	iRouteSet.ResetAndDestroy();
+
+	TSglQueIter<CSIPHeaderBase> iter =
+        aResponse.Headers(
+            SIPStrings::StringF(SipStrConsts::EServiceRouteHeader));
+
+	for (CSIPHeaderBase* header = iter++; header; header = iter++)
+		{
+		CSIPServiceRouteHeader* routeHeader =
+			static_cast<CSIPServiceRouteHeader*>(header);
+		CSIPRouteHeader* newRouteHeader = 
+		    SIPCodecUtils::CreateRouteHeaderLC(*routeHeader);
+        iRouteSet.AppendL(newRouteHeader);
+		CleanupStack::Pop(newRouteHeader);
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::ServiceRouteOk
+// -----------------------------------------------------------------------------
+//	
+TBool CSIPRegistrationBindingBase::ServiceRouteOk(
+    CSIPResponse& aResponse) const
+    {
+    // Check if the last Service-Route-header has changed
+    TBool ok = ETrue;
+    if (iRouteSet.Count() > 0)
+        {
+        TInt headerCount = 
+            aResponse.HeaderCount(
+                SIPStrings::StringF(SipStrConsts::EServiceRouteHeader));
+        if (headerCount > 0)
+            {
+            CSIPRouteHeaderBase* myLastRoute = iRouteSet[iRouteSet.Count()-1];
+            
+            CSIPRouteHeaderBase* newLastRoute = 
+                static_cast<CSIPRouteHeaderBase*>(
+                    aResponse.Header(
+                        SIPStrings::StringF(SipStrConsts::EServiceRouteHeader),
+                        headerCount-1));      
+            
+            ok = (myLastRoute->SIPAddress() == newLastRoute->SIPAddress()); 
+            }
+        }
+    return ok;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::SetPAssociatedURIFromResponseL
+// -----------------------------------------------------------------------------
+//	
+void CSIPRegistrationBindingBase::SetPAssociatedURIFromResponseL(
+    CSIPResponse& aResponse)
+    {
+    CSIPHeaderBase* headerInResponse = 
+        aResponse.Header(
+            SIPStrings::StringF(SipStrConsts::EPAssociatedURIHeader),0);
+    CSIPHeaderBase* header = NULL;
+    if (headerInResponse)
+        {
+        header = headerInResponse->CloneL();
+        }
+    delete iPAssociatedURIHeader;
+    iPAssociatedURIHeader = static_cast<CSIPPAssociatedURIHeader*>(header);
+    }
+    
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::PAssociatedURIHeader
+// -----------------------------------------------------------------------------
+//    
+const CSIPPAssociatedURIHeader* 
+CSIPRegistrationBindingBase::PAssociatedURIHeader() const
+    {
+    return iPAssociatedURIHeader;
+    }
+    
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::FillTransportParams
+// -----------------------------------------------------------------------------
+//
+TSIPTransportParams CSIPRegistrationBindingBase::FillTransportParams()
+    {
+    TSIPTransportParams transportParams(iOwner->TransportParams());
+    transportParams.SetTransportId(iTransportId);
+    transportParams.SetCompartmentId(iSigCompCompartmentId);
+    transportParams.SetNATBindingObserver(this);
+    return transportParams; 
+    }    
+	
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::HasTransaction
+// -----------------------------------------------------------------------------
+//
+TBool CSIPRegistrationBindingBase::HasTransaction(
+    const TTransactionId& aTransactionId) const
+    {
+    return (iTransactionId == aTransactionId || 
+            iRetryTransactionId == aTransactionId);
+    }	
+	
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::OutboundProxyFailed
+// -----------------------------------------------------------------------------
+//	
+void CSIPRegistrationBindingBase::OutboundProxyFailed()
+    {
+    if (!RegisterPending())
+        {
+        iCurrentState->TransactionEnded(KEmptyTransactionId,
+                                        KErrSIPOutboundProxyNotResponding);
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::RouteSet
+// -----------------------------------------------------------------------------
+//
+RPointerArray<CSIPRouteHeader>& CSIPRegistrationBindingBase::RouteSet()
+	{
+	return iRouteSet;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::IAPId
+// -----------------------------------------------------------------------------
+//
+TUint32 CSIPRegistrationBindingBase::IAPId() const
+	{
+	return iOwner->TransportParams().IapId();
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::SigCompCompartmentId
+// -----------------------------------------------------------------------------
+//
+TUint32 CSIPRegistrationBindingBase::SigCompCompartmentId() const
+	{
+	return iSigCompCompartmentId;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::Contact
+// -----------------------------------------------------------------------------
+//
+CSIPContactHeader& CSIPRegistrationBindingBase::Contact()
+	{
+	return *iContact;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::AOR
+// -----------------------------------------------------------------------------
+//
+const CSIPToHeader& CSIPRegistrationBindingBase::AOR () const
+    {
+    return *iTo;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::FindContactByFromL
+// -----------------------------------------------------------------------------
+//
+TBool CSIPRegistrationBindingBase::FindContactByFromL(
+	const CSIPFromToHeaderBase* aFromToHeader,
+	CSIPContactHeader&      	aContact)
+	{
+	TBool found = EFalse;
+
+	const CURIContainer& uriOfFromTo  = (const_cast<CSIPFromToHeaderBase*>(
+		aFromToHeader))->SIPAddress().URI();
+
+	// if URI of To header in binding == URI of aFromToHeader header
+	if (uriOfFromTo.IsSIPURI() &&
+	    iTo->SIPAddress().URI().IsSIPURI() &&
+	    iTo->SIPAddress().URI() == uriOfFromTo)
+		{
+		CSIPURI& sipuri = *aContact.SIPAddress()->URI().SIPURI();
+		CSIPURI& sipuriInBinding = *iContact->SIPAddress()->URI().SIPURI();
+
+		if (sipuri.User().Length() > 0)
+			{
+			if (sipuri.User().Compare(sipuriInBinding.User()) == 0)
+				{
+				// fill in host part
+				CSIPHostPort* hostPort =
+					CSIPHostPort::NewLC(sipuriInBinding.HostPort());
+				sipuri.SetHostPortL(hostPort);
+				CleanupStack::Pop(hostPort);
+				found = ETrue;
+				}
+			}
+		else
+			{
+			// fill in user part
+			sipuri.SetUserL(sipuriInBinding.User());
+			// fill in host part
+			CSIPHostPort* hostPort =
+				CSIPHostPort::NewLC(sipuriInBinding.HostPort());
+			sipuri.SetHostPortL(hostPort);
+			CleanupStack::Pop(hostPort);
+			found = ETrue;
+			}
+		}
+
+	return found;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::CompareWithRegisterRequest
+// -----------------------------------------------------------------------------
+//
+TBool CSIPRegistrationBindingBase::CompareWithRegisterRequest(
+	const MRegistrationOwner& aRegistrationOwner,
+	CSIPRequest&              aSIPRequest)
+	{
+	TBool returnValue = EFalse;
+
+	if (iOwner == &aRegistrationOwner)
+		{
+		// get To header from request
+		CSIPToHeader* toHeader = aSIPRequest.To();
+		CURIContainer& uriOfToInReq = toHeader->SIPAddress().URI();
+		
+		// get From header from request
+		CSIPFromHeader* fromHeader = aSIPRequest.From();
+		CURIContainer& uriOfFromInReq  = fromHeader->SIPAddress().URI();
+
+		// get Contact header from request
+        CSIPContactHeader* contactHeader = HEADER(
+			CSIPContactHeader, aSIPRequest,
+			SIPStrings::StringF(SipStrConsts::EContactHeader));
+
+		CURIContainer& uriOfContactInReq = contactHeader->SIPAddress()->URI();
+		CURIContainer& uriOfTo = iTo->SIPAddress().URI();
+		CURIContainer& uriOfFrom = iFrom->SIPAddress().URI();
+		CURIContainer& uriOfContact = iContact->SIPAddress()->URI();
+
+		if ((uriOfToInReq      == uriOfTo) &&
+			(uriOfFromInReq    == uriOfFrom) &&
+			(uriOfContactInReq == uriOfContact))
+			{
+			returnValue = ETrue;
+			}
+		}
+
+	return returnValue;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::RegistrationId
+// -----------------------------------------------------------------------------
+//
+TRegistrationId CSIPRegistrationBindingBase::RegistrationId() const
+	{
+	return iRegistrationId;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::OutboundProxy
+// -----------------------------------------------------------------------------
+//
+const CSIPRouteHeader* CSIPRegistrationBindingBase::OutboundProxy()
+	{
+	return iOutboundProxy;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::HasOutboundProxy
+// -----------------------------------------------------------------------------
+//
+TBool CSIPRegistrationBindingBase::HasOutboundProxy() const
+	{
+	return (iOutboundProxy != 0);
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::SetOutboundProxy
+// -----------------------------------------------------------------------------
+//
+void CSIPRegistrationBindingBase::SetOutboundProxy(
+	CSIPRouteHeader* aOutboundProxy)
+	{
+	__SIP_ASSERT_RETURN (aOutboundProxy, KErrArgument);
+
+	delete iOutboundProxy;
+	iOutboundProxy = aOutboundProxy;
+	}
+	
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::SetOutboundProxyL
+// -----------------------------------------------------------------------------
+//
+void CSIPRegistrationBindingBase::SetOutboundProxyL(
+	CSIPRouteHeader* aOutboundProxy)
+	{
+	__SIP_ASSERT_LEAVE (aOutboundProxy, KErrArgument);
+
+    CreateProxyTransportResourcesL(*aOutboundProxy);
+    SetOutboundProxy(aOutboundProxy);
+	}	
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::RemoveOutboundProxy
+// -----------------------------------------------------------------------------
+//
+TInt CSIPRegistrationBindingBase::RemoveOutboundProxy()
+	{
+	TInt err = KErrNotFound;
+	if (iOutboundProxy)
+		{
+		FreeProxyTransportResources();
+		delete iOutboundProxy;
+		iOutboundProxy = NULL;
+		err = KErrNone;
+		}
+	return err;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::RemoveBinding
+// -----------------------------------------------------------------------------
+//
+TInt CSIPRegistrationBindingBase::RemoveBinding ()
+	{
+	TInt err = iBindingStore.RemoveBinding (this);
+
+	if (err == KErrNone && iRegistrar)
+		{
+		if(iRegistrar->BindingRemoved(iRegistrationId))
+			{
+			iRegistrar = NULL;
+			}
+		}
+
+	return err;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::CreateProxyTransportResourcesL
+// -----------------------------------------------------------------------------
+//
+void CSIPRegistrationBindingBase::CreateProxyTransportResourcesL (
+	CSIPRouteHeader& aOutboundProxy)
+	{
+	CURIContainer& uri = aOutboundProxy.SIPAddress().URI();
+	TUint32 oldCompartmentId = iSigCompCompartmentId;
+	if (uri.IsSIPURI() && HasSigCompParameter(*uri.SIPURI()))
+		{
+		iSigCompCompartmentId = iSigComp.CreateCompartmentL(IAPId());
+		}
+    else
+        {
+        iSigCompCompartmentId = 0;
+        }
+    iSigComp.RemoveCompartment(oldCompartmentId);
+    TUint32 oldTransportId = iTransportId;
+    if (uri.IsSIPURI() && uri.SIPURI()->IsSIPSURI())
+        {
+		TSIPTransportParams transportParams(FillTransportParams());
+		iTransportMgr.CreateTLSTransportL(transportParams);
+		iTransportId = transportParams.TransportId();
+        }
+    else
+        {
+        iTransportId = 0;
+        }
+    iTransportMgr.RemoveTransport(oldTransportId);   
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::FreeProxyTransportResources
+// -----------------------------------------------------------------------------
+//
+void CSIPRegistrationBindingBase::FreeProxyTransportResources()
+	{
+	if (iSigCompCompartmentId)
+		{
+        iSigComp.RemoveCompartment(iSigCompCompartmentId);
+        iSigCompCompartmentId = 0;
+		}
+	if (iTransportId)
+		{
+        iTransportMgr.RemoveTransport(iTransportId);
+        iTransportId = 0;
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::HasSigCompParameter
+// -----------------------------------------------------------------------------
+//
+TBool CSIPRegistrationBindingBase::HasSigCompParameter (
+	const CSIPURI& aUri) const
+	{
+    RStringF comp = SIPStrings::StringF(SipStrConsts::EComp);
+    RStringF sigcomp = SIPStrings::StringF(SipStrConsts::ESigComp);
+	return (iSigComp.IsSupported() && aUri.ParamValue(comp) == sigcomp);
+	}
+
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::RegisterL
+// -----------------------------------------------------------------------------
+//
+void CSIPRegistrationBindingBase::RegisterL(TTransactionId&  aTransactionId,
+		                                    CSIPRequest*     aRequest,
+						                    CSIPRouteHeader* aOutboundProxy)
+	{
+	__SIP_ASSERT_LEAVE(aRequest, KErrArgument);
+	if(!iSendWithExpires)
+		TSIPRegistrationUtility::RemoveRegisterExpiresParam(*aRequest);
+	DoRegisterL(aTransactionId, aRequest, aOutboundProxy);
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::UpdateL
+// -----------------------------------------------------------------------------
+//
+void CSIPRegistrationBindingBase::UpdateL(TTransactionId& aTransactionId,
+		                                  CSIPRequest*    aRequest)
+	{
+	__SIP_ASSERT_LEAVE(aRequest, KErrArgument);
+	if(!iSendWithExpires)
+			TSIPRegistrationUtility::RemoveRegisterExpiresParam(*aRequest);
+	DoUpdateL(aTransactionId, aRequest);
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::UnregisterL
+// -----------------------------------------------------------------------------
+//
+void CSIPRegistrationBindingBase::UnregisterL(TTransactionId& aTransactionId,
+		                                      CSIPRequest*    aRequest)
+	{
+	__SIP_ASSERT_LEAVE(aRequest, KErrArgument);
+	DoUnregisterL(aTransactionId, aRequest);
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::Registrar
+// -----------------------------------------------------------------------------
+//
+CSIPRegistrar* CSIPRegistrationBindingBase::Registrar()
+	{
+	return iRegistrar;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::FillToFromL
+// -----------------------------------------------------------------------------
+//
+void CSIPRegistrationBindingBase::FillToFromL(CSIPRequest& aRequest)
+	{
+	// fill in to header from binding
+	CSIPToHeader* to = aRequest.To();
+	if (!to)
+		{
+		to = CSIPToHeader::NewLC(*iTo);
+		aRequest.AddHeaderL(to);
+		CleanupStack::Pop(to);
+		}
+
+	// fill in from header from binding
+	CSIPFromHeader* from = aRequest.From();
+	if (!from)
+		{
+		from = CSIPFromHeader::NewLC(*iFrom);
+		aRequest.AddHeaderL(from);
+		CleanupStack::Pop(from);
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::CurrentState
+// -----------------------------------------------------------------------------
+//
+CSIPRegistrationState& CSIPRegistrationBindingBase::CurrentState()
+	{
+	return *iCurrentState;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::ChangeState
+// -----------------------------------------------------------------------------
+//
+void CSIPRegistrationBindingBase::ChangeState(CSIPRegistrationState* aState)
+	{
+	iCurrentState = aState;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::Request
+// -----------------------------------------------------------------------------
+//
+CSIPRequest* CSIPRegistrationBindingBase::Request()
+	{
+	return iRequest;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::UpdateContactFromRequestL
+// -----------------------------------------------------------------------------
+//	
+void CSIPRegistrationBindingBase::UpdateContactFromRequestL()
+    {
+    if (iRequest)
+        {
+        SetContactHeaderL(*iRequest);
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::SelfDetach
+// -----------------------------------------------------------------------------
+//
+void CSIPRegistrationBindingBase::SelfDetach(TBool aRefresh)
+	{
+	if (IsRefresh())
+		{
+		if (aRefresh)
+			{
+			static_cast<CSIPRegistrationRefreshBinding*>(this)->
+				ClearRefreshOwner();
+			}
+		}
+	else
+		{
+		static_cast<CSIPRegistrationBinding*>(this)->ClearTransactionOwner();
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::SelfDetach
+// -----------------------------------------------------------------------------
+//
+void CSIPRegistrationBindingBase::SelfDetach(TBool aRefresh, TBool aUseRetryId)
+	{
+	if( !IsRefresh() && aUseRetryId )
+		{
+		static_cast<CSIPRegistrationBinding*>(this)->
+			ClearTransactionOwner( aUseRetryId );
+		}
+	else
+		{
+		SelfDetach( aRefresh );
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::Received2XXResponseL
+// -----------------------------------------------------------------------------
+//
+void CSIPRegistrationBindingBase::Received2XXResponseL(CSIPResponse& aResponse,
+			TTransactionId aTransactionId)
+	{
+	if (iRequest)
+	    {
+	    // Update the From- and To-headers in case some parameters have changed
+	    SetToHeaderL(*iRequest);
+	    SetFromHeaderL(*iRequest);
+	    }
+	
+	UpdateBindingFromResponseL(aResponse);
+	if (HasOutboundProxy() && iCacheOutboundProxyIP)
+		SetOutboundProxyIPL(aTransactionId);		
+	if (!IsRefresh())
+		{
+		// start timer for non refresh binding
+		static_cast<CSIPRegistrationBinding*>(this)->StartTimerL(
+				CSIPResponseUtility::ExpireValueL(*iContact, aResponse));
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::ClearRequest
+// -----------------------------------------------------------------------------
+//
+void CSIPRegistrationBindingBase::ClearRequest()
+	{
+	if (!IsRefresh() && iRequest)
+		{
+		delete iRequest;
+		iRequest = NULL;
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::ReceivedErrorResponseL
+// -----------------------------------------------------------------------------
+//
+void CSIPRegistrationBindingBase::ReceivedErrorResponseL()
+	{
+	// return KErrNotFound when binding could not found,
+	// return KErrNone when binding is found and is added to delete manager
+	TInt err = RemoveBinding ();
+
+	// leaves if binding is found and it is not added to delete manager
+	if (err != KErrNotFound && err != KErrNone)
+		{
+		User::Leave(err);
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::Received423ResponseL
+// -----------------------------------------------------------------------------
+//
+void CSIPRegistrationBindingBase::Received423ResponseL(CSIPResponse& aResponse)
+	{
+	// set min expires value to request contact header.
+	SetMinExpiresToRequestL(aResponse);
+	// detaching "this" registration from lower layer.
+	SelfDetach(ETrue);
+	// set refresh id to KEmptyRefreshId if it's refresh binding
+	if (IsRefresh())
+		{
+		static_cast<CSIPRegistrationRefreshBinding*>(this)->SetRefreshId(
+			KEmptyRefreshId);
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::DetachFromStore
+// -----------------------------------------------------------------------------
+//
+void CSIPRegistrationBindingBase::DetachFromStore()
+	{
+	iBindingStore.DetachBinding(this);
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::DetachOutboundProxy
+// -----------------------------------------------------------------------------
+//
+void CSIPRegistrationBindingBase::DetachOutboundProxy(TAny* aBinding)
+	{
+	__SIP_ASSERT_RETURN(aBinding, KErrGeneral);
+
+	CSIPRegistrationBindingBase* binding =
+		reinterpret_cast<CSIPRegistrationBindingBase*>(aBinding);
+
+	binding->FreeProxyTransportResources();
+	binding->iOutboundProxy = NULL; // detach the OutboundProxy
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::SetOutboundProxyIPL
+// -----------------------------------------------------------------------------
+//
+TInt CSIPRegistrationBindingBase::SetOutboundProxyIPL(const TTransactionId& aTransactionId)
+	{   
+	TInetAddr outboundProxyIP;
+	TInt error = iTransactionUser.NextHopIP(aTransactionId, outboundProxyIP);
+	if (!error)
+		{
+		CSIPAddress* sipAddress = CSIPAddress::NewLC(iOutboundProxy->SIPAddress());
+		
+		HBufC8* addressText = ConvertInetAddrToTextL(outboundProxyIP);
+		CleanupStack::PushL(addressText);
+		CSIPHostPort* hostport = CSIPHostPort::DecodeL( *addressText );
+		CleanupStack::PopAndDestroy(addressText);
+		CleanupStack::PushL(hostport);
+		
+		TUint port = outboundProxyIP.Port() > 0 ?
+				outboundProxyIP.Port() : KDefaultSipPort;
+		hostport->SetPort(port);
+		
+		sipAddress->URI().SIPURI()->SetHostPortL(hostport);
+		
+		sipAddress->URI().SIPURI()->SetSIPS(
+				iOutboundProxy->SIPAddress().URI().SIPURI()->IsSIPSURI());
+		
+		CleanupStack::Pop(hostport);
+		delete iOutboundProxyIP;
+		iOutboundProxyIP = NULL;
+		iOutboundProxyIP = CSIPRouteHeader::NewL(sipAddress);
+		CleanupStack::Pop(sipAddress);
+		}
+	return error;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::ConvertInetAddrToTextL
+// -----------------------------------------------------------------------------
+//        
+HBufC8* CSIPRegistrationBindingBase::ConvertInetAddrToTextL(const TInetAddr& aAddr)
+    {
+    const TInt KMaxIPAddrLen = 256;
+    HBufC* addressOut = HBufC::NewLC(KMaxIPAddrLen);
+	TPtr outputPtr(addressOut->Des());
+	aAddr.Output(outputPtr);
+	
+	HBufC8* addressResult = HBufC8::NewL(addressOut->Length());
+	TPtr8 resultPtr(addressResult->Des());
+	CnvUtfConverter::ConvertFromUnicodeToUtf8(resultPtr, *addressOut);
+	CleanupStack::PopAndDestroy(addressOut);
+	
+	return addressResult;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::IsCacheOutboundProxyIPEnabled
+// -----------------------------------------------------------------------------
+//
+TBool CSIPRegistrationBindingBase::IsCacheOutboundProxyIPEnabled()
+	{
+	return iCacheOutboundProxyIP;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPRegistrationBindingBase::OutboundProxyIPL
+// -----------------------------------------------------------------------------
+//
+CSIPRouteHeader& CSIPRegistrationBindingBase::OutboundProxyIPL()
+	{
+	__ASSERT_ALWAYS (iOutboundProxyIP, User::Leave (KErrNotSupported));
+	return *iOutboundProxyIP;
+	}
+