realtimenetprots/sipfw/SIP/sipapi/src/RegBindingImplementation.cpp
changeset 0 307788aac0a8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/realtimenetprots/sipfw/SIP/sipapi/src/RegBindingImplementation.cpp	Tue Feb 02 01:03:15 2010 +0200
@@ -0,0 +1,948 @@
+// Copyright (c) 2006-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          : RegBindingImplementation.cpp
+// Part of       : SIPAPI
+// Version       : SIP/5.0 
+//
+
+
+
+#include <uri8.h>
+#include "siperr.h"
+#include "sipdefs.h"
+#include "SipAssert.h"
+#include "sipclientconnection.h"
+#include "SipConnectionImplementation.h"
+#include "RegBindingImplementation.h"
+#include "sipregistrationstate.h"
+#include "sipclienttransaction.h"
+#include "sipmessageelements.h"
+#include "sipresponseelements.h"
+#include "siprefresh.h"
+#include "siprouteheader.h"
+#include "sipcontactheader.h"
+#include "siptoheader.h"
+#include "sipfromheader.h"
+#include "sipconnectioncallback.h"
+#include "sipstrings.h"
+#include "sipstrconsts.h"
+#include <sipregistrationbinding.h>
+
+#ifdef CPPUNIT_TEST
+#include "TestCleanupStack.h"
+#endif
+
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::NewL
+// -----------------------------------------------------------------------------
+//
+CRegBindingImplementation*
+CRegBindingImplementation::NewL(CSIPRegistrationBinding& aRegistration,
+								CSIPConnection& aConnection,
+					   		    CSIPToHeader* aAor,
+					   		    CSIPContactHeader* aContact,
+					   		    CSIPRefresh* aRefresh,
+					   		    CSIPRouteHeader* aOutboundProxy,
+					   		    CUri8* aRemoteUri,
+                       		    CSIPFromHeader* aFrom)
+    {
+    __ASSERT_ALWAYS(aAor && aContact, User::Leave(KErrArgument));
+
+    TInt expires = aContact->ExpiresParameter();
+    __ASSERT_ALWAYS(expires >= static_cast<TInt>(KSIPMinExpirationValue) ||
+    				expires == KErrNotFound, User::Leave(KErrArgument));
+    CRegBindingImplementation* self =
+    	new (ELeave) CRegBindingImplementation(aRegistration, aConnection);
+    CleanupStack::PushL(self);
+    self->ConstructL(aAor,
+                     aContact,
+                     aRefresh,
+                     aOutboundProxy,
+                     aRemoteUri,
+                     aFrom);	
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::CRegBindingImplementation
+// -----------------------------------------------------------------------------
+//
+CRegBindingImplementation::CRegBindingImplementation(
+									CSIPRegistrationBinding& aRegistration,
+									CSIPConnection& aConnection) :
+	iRegistration(aRegistration),
+    iConnection(&aConnection)
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::ConstructL
+// aAor and aContact have been checked in NewLC so they aren't checked again
+// -----------------------------------------------------------------------------
+//
+void CRegBindingImplementation::ConstructL(CSIPToHeader* aAor,
+								  		   CSIPContactHeader* aContact,                                  
+							  	  		   CSIPRefresh* aRefresh,
+								  		   CSIPRouteHeader* aOutboundProxy,
+								  		   CUri8* aRemoteUri,
+                                  		   CSIPFromHeader* aFrom)
+    {
+    CheckConnectionL();
+
+    iConnection->Implementation().AddRegistrationL(*this);
+    iState = iConnection->Implementation().InitialRegisterStateL();
+    iContact = aContact;
+    iAor = aAor;
+    iRefresh = aRefresh;
+    if (iRefresh)
+        {
+        iRefresh->SetRefreshOwner(*this);
+        iRefresh->SetRequestType(SIPStrings::StringF(SipStrConsts::ERegister));
+        }
+
+    iOutboundProxy = aOutboundProxy;
+    iRemoteUri = aRemoteUri;
+    iFrom = aFrom;
+    iSendWithExpires = ETrue;
+    iCacheOutboundProxyIP = EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::~CRegBindingImplementation
+// -----------------------------------------------------------------------------
+//
+CRegBindingImplementation::~CRegBindingImplementation()
+    {
+    if (iConnection)
+        {
+        CSIPClientConnection* clientConn =
+        	iConnection->Implementation().ClientConnection();
+        if (clientConn)
+        	{
+        	clientConn->TerminateRegistration(iRegistrationId);
+        	}
+        iConnection->Implementation().RemoveRegistration(*this);
+        }
+
+    for (TInt i = 0; i < iTransactions.Count(); i++)
+        {
+        iTransactions[i]->Detach(*this);
+        }
+    iTransactions.Reset();
+
+    delete iRefresh;
+    delete iOutboundProxy;
+    delete iContact;
+    delete iAor;
+    delete iRemoteUri;
+    delete iFrom;
+    delete iRegisteredContact;
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::IsContextActive
+// -----------------------------------------------------------------------------
+//
+TBool CRegBindingImplementation::IsContextActive() const
+    {
+    __TEST_INVARIANT;
+    return iState && iState->IsContextActive();
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::ContextId
+// -----------------------------------------------------------------------------
+//
+TUint32 CRegBindingImplementation::ContextId() const
+    {
+    __TEST_INVARIANT;
+    return iRegistrationId;
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::RegisterL
+// -----------------------------------------------------------------------------
+//
+CSIPClientTransaction*
+CRegBindingImplementation::RegisterL(CSIPMessageElements* aElements)
+    {
+    __TEST_INVARIANT;
+
+    CheckElementsL(aElements);
+    return StateL().RegisterL(*this, aElements);
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::DoRegisterL
+// -----------------------------------------------------------------------------
+//
+CSIPClientTransaction*
+CRegBindingImplementation::DoRegisterL(CSIPMessageElements* aElements)
+    {
+    __TEST_INVARIANT;
+    CheckConnectionL();
+
+	CSIPClientTransaction* ta = CreateClientTransactionL();
+	CleanupStack::PushL(ta);
+
+    CSIPMessageElements* elem = aElements;
+    if (!aElements)
+        {
+        elem = CSIPMessageElements::NewLC();
+        }
+
+    //Put contact temporarily to elem. Once REGISTER is sent, clear it from elem
+    CleanupStack::PushL(TCleanupItem(DetachContactHeader, elem));
+    elem->AddHeaderL(iContact);
+
+    CSIPFromHeader* from = iFrom;
+    if (!iFrom)
+        {
+        from = CSIPFromHeader::NewLC(*iAor);
+        }
+
+    TUint32 requestId(0);
+    iConnection->Implementation().ClientConnectionL().SendRegisterL(requestId,
+                                                   *iAor,
+                                                   *from,
+                                                   *elem,
+                                                   iRemoteUri,
+                                                   iOutboundProxy,
+                                                   (iRefresh != NULL),
+                                                   iSendWithExpires,
+                                                   iCacheOutboundProxyIP);
+    if (!iFrom)
+        {
+        CleanupStack::PopAndDestroy(from);
+        }
+    CleanupStack::PopAndDestroy(); //TCleanupItem
+
+    if (aElements)
+        {
+        delete aElements;
+        }
+    else
+        {
+        CleanupStack::PopAndDestroy(elem);
+        }
+    CleanupStack::Pop(ta);
+	ta->SetRequestId(requestId);
+
+    __TEST_INVARIANT;
+    return ta;
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::DeregisterL
+// -----------------------------------------------------------------------------
+//
+CSIPClientTransaction*
+CRegBindingImplementation::DeregisterL(CSIPMessageElements* aElements)
+    {
+    __TEST_INVARIANT;    
+    return StateL().DeregisterL(*this, aElements);
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::DoDeregisterL
+// -----------------------------------------------------------------------------
+//
+CSIPClientTransaction*
+CRegBindingImplementation::DoDeregisterL(CSIPMessageElements* aElements)
+    {
+    __TEST_INVARIANT;
+    CheckConnectionL();
+
+    CSIPClientTransaction* ta = CSIPClientTransaction::NewLC(
+    	SIPStrings::StringF(SipStrConsts::ERegister), *this);
+
+    TUint32 requestId(0);
+	iConnection->Implementation().ClientConnectionL().UnregisterL(
+												iRegistrationId,
+					                            requestId,
+                                                aElements);
+    CleanupStack::Pop(ta);
+	ta->SetRequestId(requestId);    
+    delete aElements;
+
+    __TEST_INVARIANT;
+    return ta;
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::UpdateL
+// -----------------------------------------------------------------------------
+//
+CSIPClientTransaction*
+CRegBindingImplementation::UpdateL(CSIPMessageElements* aElements,
+								   TUint* aExpirationValue)
+    {
+    __TEST_INVARIANT;
+    return StateL().UpdateL(*this, aElements, aExpirationValue);
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::DoUpdateL
+// -----------------------------------------------------------------------------
+//
+CSIPClientTransaction*
+CRegBindingImplementation::DoUpdateL(CSIPMessageElements* aElements,
+                            	     TUint* aExpirationValue)
+    {
+    __TEST_INVARIANT;    
+    CheckConnectionL();
+
+    CSIPClientTransaction* ta = CSIPClientTransaction::NewLC(
+    					SIPStrings::StringF(SipStrConsts::ERegister),		                
+		                *this);
+
+	CSIPMessageElements* elem = aElements;
+    if (!aElements)
+        {
+        elem = CSIPMessageElements::NewLC();
+        }
+
+    if (aExpirationValue)
+        {
+        iContact->SetExpiresParameterL(*aExpirationValue);
+        }
+
+    //Put contact temporarily to elem. Once REGISTER is sent, clear it from elem
+	CleanupStack::PushL(TCleanupItem(DetachContactHeader, elem));
+    elem->AddHeaderL(iContact);
+
+    TUint32 requestId(0);
+    iConnection->Implementation().ClientConnectionL().UpdateRegistrationL(
+    													iRegistrationId,
+                                                        requestId,
+                                                        elem);
+	CleanupStack::PopAndDestroy(); //TCleanupItem
+    if (aElements)
+        {
+        delete aElements;
+        }
+    else
+        {
+        CleanupStack::PopAndDestroy(elem);
+        }
+
+    CleanupStack::Pop(ta);
+	ta->SetRequestId(requestId);
+
+    __TEST_INVARIANT;
+    return ta;
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::SetOutboundProxyL
+// -----------------------------------------------------------------------------
+//
+void
+CRegBindingImplementation::SetOutboundProxyL(CSIPRouteHeader* aOutboundProxy)
+    {
+    __TEST_INVARIANT;
+
+	if (IsContextActive())
+		{
+    	CheckConnectionL();
+
+		CSIPClientConnection& conn =
+			iConnection->Implementation().ClientConnectionL();
+	    if (aOutboundProxy)
+    	    {
+        	conn.SetOutboundProxyL(iRegistrationId,	*aOutboundProxy);
+			}
+		else
+			{
+        	conn.RemoveOutboundProxy(iRegistrationId);
+			}
+        }
+
+    //Remove old proxy when leave can not occur
+    delete iOutboundProxy;
+    iOutboundProxy = aOutboundProxy;
+
+    __TEST_INVARIANT;
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::Aor
+// -----------------------------------------------------------------------------
+//
+const CSIPToHeader& CRegBindingImplementation::Aor() const
+    {
+    __TEST_INVARIANT;
+    return *iAor;
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::ContactHeader
+// -----------------------------------------------------------------------------
+//
+const CSIPContactHeader& CRegBindingImplementation::ContactHeader() const
+    {
+    __TEST_INVARIANT;
+    return *iContact;
+    }
+    
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::RegisteredContact
+// -----------------------------------------------------------------------------
+//
+const CSIPContactHeader* CRegBindingImplementation::RegisteredContact() const
+    {
+    __TEST_INVARIANT;
+    return iRegisteredContact;
+    }    
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::ContactHeader
+// -----------------------------------------------------------------------------
+//
+CSIPContactHeader& CRegBindingImplementation::ContactHeader()
+    {
+    __TEST_INVARIANT;
+    return *iContact;
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::OutboundProxy
+// -----------------------------------------------------------------------------
+//
+const CSIPRouteHeader* CRegBindingImplementation::OutboundProxy() const
+    {
+    __TEST_INVARIANT;
+    return iOutboundProxy;
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::SIPRefresh
+// -----------------------------------------------------------------------------
+//
+const CSIPRefresh* CRegBindingImplementation::SIPRefresh() const
+    {
+    __TEST_INVARIANT;
+    return iRefresh;
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::SIPRefresh
+// -----------------------------------------------------------------------------
+//
+CSIPRefresh* CRegBindingImplementation::SIPRefresh()
+    {
+    __TEST_INVARIANT;
+    return iRefresh;
+    }
+    
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::Connection
+// -----------------------------------------------------------------------------
+//
+CSIPConnection* CRegBindingImplementation::Connection()
+    {
+    __TEST_INVARIANT;
+    return iConnection;    
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::Connection
+// -----------------------------------------------------------------------------
+//
+const CSIPConnection* CRegBindingImplementation::Connection() const
+    {
+    __TEST_INVARIANT;
+    return iConnection;
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::IncomingResponseL
+// -----------------------------------------------------------------------------
+//
+TBool
+CRegBindingImplementation::IncomingResponseL(CSIPResponseElements* aElements,
+				                             TUint32 aRequestId,
+							                 TUint32 aRegistrationId,
+							                 TUint32 aRefreshId,
+		                                     CConnectionCallback& aCallback)
+    {
+    __TEST_INVARIANT;
+    __SIP_ASSERT_LEAVE(aElements != NULL, KErrArgument);
+
+    if (iState)
+        {
+        return iState->IncomingResponseL(*this,
+                                         aElements,
+		                                 aRequestId,
+					                     aRegistrationId,
+					                     aRefreshId,
+                                         aCallback);
+        }
+    delete aElements;    
+    return EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::ErrorOccured
+// -----------------------------------------------------------------------------
+//
+TBool CRegBindingImplementation::ErrorOccured(TInt aError,
+                                     		  TUint32 aRequestId,
+                                     		  CConnectionCallback& aCallback)
+    {
+    __TEST_INVARIANT;
+	return iState && iState->ErrorOccured(*this, aError, aRequestId, aCallback);
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::SetRegistrationId
+// -----------------------------------------------------------------------------
+//
+void CRegBindingImplementation::SetRegistrationId(TUint32 aRegistrationId)
+    {
+    __TEST_INVARIANT;
+
+    iRegistrationId = aRegistrationId;
+
+    __TEST_INVARIANT;
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::UpdateRefreshState
+// -----------------------------------------------------------------------------
+//
+void CRegBindingImplementation::UpdateRefreshState(TUint aStatusCode) const
+    {
+    __TEST_INVARIANT;
+    __SIP_ASSERT_RETURN(iRefresh, KErrNotFound);
+
+    iRefresh->UpdateRefreshState(aStatusCode);
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::FindTransaction
+// -----------------------------------------------------------------------------
+//
+CSIPClientTransaction*
+CRegBindingImplementation::FindTransaction(TUint32 aRequestId)
+    {
+    __TEST_INVARIANT;
+
+    for (TInt i = 0; i < iTransactions.Count(); i++)
+        {
+        if (iTransactions[i]->RequestId() == aRequestId)
+            {
+            return iTransactions[i];
+            }
+        }
+
+    return NULL;
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::ConnectionDeleted
+// As CSIPClientConnection is deleted, SIP client stops all registrations. So no
+// need to use TerminateRegistration. Clear iState as this object won't know
+// when the CSIP owning the state handlers is deleted.
+// -----------------------------------------------------------------------------
+//
+void CRegBindingImplementation::ConnectionDeleted()
+    {
+    __TEST_INVARIANT;
+
+    iConnection = NULL;
+    iState = NULL;
+
+    __TEST_INVARIANT;
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::CheckConnectionL
+// Don't use invariant here as CheckConnectionL is used from ConstructL.
+// -----------------------------------------------------------------------------
+//
+void CRegBindingImplementation::CheckConnectionL() const
+    {
+    __ASSERT_ALWAYS(iConnection, User::Leave(KErrSIPResourceNotAvailable));    
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::StateL
+// -----------------------------------------------------------------------------
+//
+const CRegistrationState& CRegBindingImplementation::StateL() const
+    {
+    __TEST_INVARIANT;
+	__ASSERT_ALWAYS(iState != NULL, User::Leave(KErrSIPResourceNotAvailable));
+
+    return *iState;
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::ClientConnectionL
+// -----------------------------------------------------------------------------
+//
+CSIPClientConnection& CRegBindingImplementation::ClientConnectionL()
+    {
+    __TEST_INVARIANT;
+
+    CSIPClientConnection* clientConn = ClientConnection();
+    __ASSERT_ALWAYS(clientConn, User::Leave(KErrSIPResourceNotAvailable));
+
+    return *clientConn;
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::ClientConnection
+// -----------------------------------------------------------------------------
+//
+CSIPClientConnection* CRegBindingImplementation::ClientConnection()
+	{
+	__TEST_INVARIANT;
+
+	if (iConnection)
+		{
+		return iConnection->Implementation().ClientConnection();
+		}
+	return NULL;
+	}
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::SIPConnectionL
+// -----------------------------------------------------------------------------
+//
+CSIPConnection& CRegBindingImplementation::SIPConnectionL()
+    {
+    __TEST_INVARIANT;
+    CheckConnectionL();    
+
+    return *iConnection;
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::ChangeState
+// -----------------------------------------------------------------------------
+//
+void CRegBindingImplementation::ChangeState(const CRegistrationState* aNewState)
+    {
+    __TEST_INVARIANT;
+
+	iState = aNewState;	
+
+    if (iRefresh)
+        {
+        if (iState)
+            {
+            iRefresh->ChangeState(iState->RefreshState());
+            }
+        else
+            {
+            iRefresh->ChangeState(CSIPRefresh::ETerminated);
+            }
+        }
+
+    __TEST_INVARIANT;
+	}
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::ConnectionLost
+// -----------------------------------------------------------------------------
+//
+void CRegBindingImplementation::ConnectionLost()
+    {
+    __TEST_INVARIANT;
+
+    if (iState)
+        {
+        iState->ConnectionLost(*this);
+        }
+    
+    for (TInt i = 0; i < iTransactions.Count(); i++)
+        {
+        iTransactions[i]->ChangeState(CSIPTransactionBase::ETerminated);
+        }
+
+    __TEST_INVARIANT;
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::operator==
+// -----------------------------------------------------------------------------
+//
+TBool CRegBindingImplementation::operator==(
+	const CRegBindingImplementation& aRegistration) const
+    {
+    __TEST_INVARIANT;
+
+    return ( ContextId() && aRegistration.ContextId() &&
+        	 (ContextId() == aRegistration.ContextId()) ) ||
+    	   this == &aRegistration;
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::Binding
+// -----------------------------------------------------------------------------
+//
+CSIPRegistrationBinding& CRegBindingImplementation::Binding() const
+	{
+	__TEST_INVARIANT;
+	return iRegistration;
+	}
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::UpdateRegisteredContactL
+// -----------------------------------------------------------------------------
+//	
+void CRegBindingImplementation::UpdateRegisteredContactL()
+    {
+    CSIPContactHeader* contact = ClientConnectionL().ContactL(iRegistrationId);
+    delete iRegisteredContact;
+    iRegisteredContact = contact;
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::RemoveRegisteredContact
+// -----------------------------------------------------------------------------
+//	
+void CRegBindingImplementation::RemoveRegisteredContact()
+    {
+    delete iRegisteredContact;
+    iRegisteredContact = NULL;
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::UpdateRefreshL
+// Application may not update or terminate a registration refresh.
+// -----------------------------------------------------------------------------
+//
+CSIPClientTransaction*
+CRegBindingImplementation::UpdateRefreshL(CSIPRefresh& /*aRefresh*/,
+                       		              CSIPMessageElements* /*aElements*/,
+                       		              TBool /*aTerminate*/)
+    {
+    User::Leave(KErrSIPInvalidRegistrationState);
+    return NULL;
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::DeletingRefresh
+// No need to use CSIPClientConnection::TerminateRefresh, as destructor calls
+// TerminateRegistration freeing possible refresh from the SIP stack.
+// -----------------------------------------------------------------------------
+//
+void CRegBindingImplementation::DeletingRefresh(CSIPRefresh& /*aRefresh*/,
+                                       		    TUint32 /*aRefreshId*/)
+    {
+    __TEST_INVARIANT;
+
+    iRefresh = NULL;
+
+    __TEST_INVARIANT;
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::TransactionAssociation
+// -----------------------------------------------------------------------------
+//
+MTransactionAssociation& CRegBindingImplementation::TransactionAssociation()
+	{
+	__TEST_INVARIANT;
+	return *this;
+	}
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::CheckIfStandAlone
+// -----------------------------------------------------------------------------
+//
+TInt CRegBindingImplementation::CheckIfStandAlone()
+	{
+	__TEST_INVARIANT;
+	return KErrSIPInvalidRegistrationState;
+	}
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::AddTransactionL
+// -----------------------------------------------------------------------------
+//
+void
+CRegBindingImplementation::AddTransactionL(CSIPTransactionBase& aTransaction)
+    {
+    __TEST_INVARIANT;
+	__SIP_ASSERT_LEAVE(aTransaction.IsSIPClientTransaction(), KErrArgument);
+
+	/*lint -e826 */
+	iTransactions.AppendL(static_cast<CSIPClientTransaction*>(&aTransaction));    
+
+    __TEST_INVARIANT;
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::RemoveTransaction
+// -----------------------------------------------------------------------------
+//
+void CRegBindingImplementation::RemoveTransaction(
+									const CSIPTransactionBase& aTransaction)
+    {
+    __TEST_INVARIANT;
+    __SIP_ASSERT_RETURN(aTransaction.IsSIPClientTransaction(), KErrArgument);
+
+	/*lint -e826 */
+    TInt pos = iTransactions.Find(
+    	static_cast<const CSIPClientTransaction*>(&aTransaction));
+    if (pos != KErrNotFound)
+        {
+        iTransactions.Remove(pos);
+        }
+
+    __TEST_INVARIANT;
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::CreateClientTransactionL
+// -----------------------------------------------------------------------------
+//
+CSIPClientTransaction*
+CRegBindingImplementation::CreateClientTransactionL()
+    {
+    __TEST_INVARIANT;
+    return CSIPClientTransaction::NewL(
+    						SIPStrings::StringF(SipStrConsts::ERegister),
+                            *this,
+                            iRefresh);
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::HandleError
+// -----------------------------------------------------------------------------
+//
+TBool
+CRegBindingImplementation::HandleError(CConnectionCallback& aCallback,
+                                       TInt aError,
+                                       TUint32 aRequestId,
+                                       const CRegistrationState& aUnregistered)
+    {
+    __TEST_INVARIANT;
+    __SIP_ASSERT_RETURN_VALUE(aError != KErrNone, EFalse);
+
+    RemoveRegisteredContact();
+	ChangeState(&aUnregistered);
+
+	CConnectionCallback::TCallbackMethod callback =
+		CConnectionCallback::EErrorOccuredInRegistration;	
+	CSIPClientTransaction* ta = FindTransaction(aRequestId);
+    if (ta)
+        {
+        ta->ChangeState(CSIPTransactionBase::ETerminated);
+        callback =
+        	CConnectionCallback::EErrorOccuredInRegistrationWithTransaction;
+        }
+
+	aCallback.Set(callback, ta, &Binding(), NULL, NULL, aError);
+
+	__TEST_INVARIANT;
+    return ETrue;
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::CheckElementsL
+// -----------------------------------------------------------------------------
+//
+void CRegBindingImplementation::CheckElementsL(
+								const CSIPMessageElements* aElements) const
+    {
+    __TEST_INVARIANT;
+
+    if (aElements)
+        {
+        RStringF contact = SIPStrings::StringF(SipStrConsts::EContactHeader);
+        RStringF expires = SIPStrings::StringF(SipStrConsts::EExpiresHeader);
+
+        const RPointerArray<CSIPHeaderBase>& headers = aElements->UserHeaders();
+        for (TInt i = 0; i < headers.Count(); i++)
+            {
+            if (headers[i]->Name() == contact || headers[i]->Name() == expires)
+                {
+                User::Leave(KErrSIPMalformedMessage);
+                }
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::DetachContactHeader
+// -----------------------------------------------------------------------------
+//
+void CRegBindingImplementation::DetachContactHeader(TAny* aElements)
+	{
+    __SIP_ASSERT_RETURN(aElements, KErrArgument);
+    DetachHeaders(aElements, SIPStrings::StringF(SipStrConsts::EContactHeader));
+	}
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::DetachHeaders
+// -----------------------------------------------------------------------------
+//
+void CRegBindingImplementation::DetachHeaders(TAny* aElements, RStringF aName)
+	{
+    __SIP_ASSERT_RETURN(aElements, KErrArgument);
+
+    CSIPMessageElements* elem =
+    	reinterpret_cast<CSIPMessageElements*>(aElements);
+    const RPointerArray<CSIPHeaderBase>& headers = elem->UserHeaders();
+
+	for (TInt i = headers.Count() - 1; i >= 0; i--)
+        {
+        if (headers[i]->Name() == aName)
+            {
+            elem->DetachUserHeader(headers[i]);
+            }
+        }
+	}
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::SetPropertyL
+// -----------------------------------------------------------------------------
+//
+void CRegBindingImplementation::SetPropertyL(TUint32 aProperty,TBool aValue)
+	{
+	__ASSERT_ALWAYS(!IsContextActive(), User::Leave(KErrSIPInvalidRegistrationState));
+	switch(aProperty)
+		{
+		case KSIPSendWithExpires:
+			{
+			iSendWithExpires = aValue;
+			break;
+			}
+		case KSIPCacheOutboundProxyIP:
+			{
+			iCacheOutboundProxyIP = aValue;
+			break;
+			}
+		default:
+			User::Leave(KErrNotFound);
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CRegBindingImplementation::__DbgTestInvariant
+// -----------------------------------------------------------------------------
+//
+void CRegBindingImplementation::__DbgTestInvariant() const
+	{
+    if (!iContact || !iAor)
+        {
+		User::Invariant();
+		}
+	}