realtimenetprots/sipfw/SIP/Registration/src/TSIPRegistrationUtility.cpp
changeset 0 307788aac0a8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/realtimenetprots/sipfw/SIP/Registration/src/TSIPRegistrationUtility.cpp	Tue Feb 02 01:03:15 2010 +0200
@@ -0,0 +1,464 @@
+// 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          : TSIPRegistrationUtility.cpp
+// Part of       : Registration
+// Version       : SIP/4.0 
+//
+
+
+
+#include "TSIPRegistrationUtility.h"
+#include "MTransactionUser.h"
+#include "MSigComp.h"
+#include "siprequest.h"
+#include "siptoheader.h"
+#include "sipfromheader.h"
+#include "sipcontactheader.h"
+#include "sipaddress.h"
+#include "uricontainer.h"
+#include "sipuri.h"
+#include "siphostport.h"
+#include "sipexpiresheader.h"
+#include "siprouteheader.h"
+#include "CSIPRegistrationBindingBase.h"
+#include "SipAssert.h"
+#include "sipstrings.h"
+#include "sipstrconsts.h"
+#include "siperr.h"
+
+const TInt KOneHourInSeconds = 3600;
+
+#define HEADER_IN_REQUEST(H, N) static_cast<H*>(aRequest.Header(N,0))
+
+// -----------------------------------------------------------------------------
+// TSIPRegistrationUtility::LocalAddressLC
+// -----------------------------------------------------------------------------
+//
+HBufC8* TSIPRegistrationUtility::LocalAddressLC (const TUint       aIapId,
+                                                 MTransactionUser& aTU)
+	{
+	// get local IP address by giving IAP id
+	TInetAddr localAddress;
+	aTU.GetLocalAddress(aIapId, localAddress);
+
+	// create Local IP address
+	const TInt KMaxIPAddrLength = 256;
+	HBufC* ipAddressOutputBuf = HBufC::NewLC(KMaxIPAddrLength);
+	TPtr ipAddressOutputPtr(ipAddressOutputBuf->Des());
+	localAddress.Output(ipAddressOutputPtr);
+
+	HBufC8* outPutBuf = HBufC8::NewL(ipAddressOutputPtr.Length());
+	TPtr8 outPutPtr(outPutBuf->Des());
+	outPutPtr.Copy(ipAddressOutputPtr);
+	CleanupStack::PopAndDestroy(ipAddressOutputBuf);
+    CleanupStack::PushL(outPutBuf);
+
+	return outPutBuf;
+	}
+
+// -----------------------------------------------------------------------------
+// TSIPRegistrationUtility::CheckRegisterRequestL
+// -----------------------------------------------------------------------------
+//
+void TSIPRegistrationUtility::CheckRegisterRequestL (
+	CSIPRequest&           aRequest,
+	const CSIPRouteHeader* aOutboundProxy,
+    const TUint32          aIapId,
+	MTransactionUser&      aTU)
+	{
+	// panic if there is no To header in request in debug mode.
+	// leaves with error code KErrArgument in release mode.
+	__SIP_ASSERT_LEAVE(aRequest.To() != 0, KErrArgument);
+	
+	// panic if RegisterRequestNoFromHeader in debug mode.
+	// leaves with error code KErrArgument in release mode.
+	__SIP_ASSERT_LEAVE(aRequest.From() != 0, KErrArgument);
+
+	CheckToHeaderL(*(aRequest.To()));
+	CheckRegisterContactL(aRequest, aIapId, aTU);
+	CheckRegisterExpiresValueL(aRequest);
+	if (aOutboundProxy)
+	    {
+	    CheckSipsSchemeInAorAndOtherAddressL(
+	        *aRequest.To(),aOutboundProxy->SIPAddress());
+	    }
+	}
+
+// -----------------------------------------------------------------------------
+// TSIPRegistrationUtility::CheckUpdateRegisterRequestL
+// -----------------------------------------------------------------------------
+//
+void TSIPRegistrationUtility::CheckUpdateRegisterRequestL (
+	CSIPRequest&                 aRequest, 
+	CSIPRegistrationBindingBase& aBinding)
+	{
+	// panic if there is to header in update register request in debug
+	// mode. leaves with error code KErrArgument in release build
+    __SIP_ASSERT_LEAVE(!aRequest.To(), KErrArgument);
+
+	// panic if there is from header in update register request in debug
+	// mode. leaves with error code KErrArgument in release build
+    __SIP_ASSERT_LEAVE(!aRequest.From(), KErrArgument);
+
+	CheckUpdateRegisterContactL(aRequest, aBinding);
+	CheckUpdateRegisterExpiresValueL(aRequest, aBinding);
+	}
+
+// -----------------------------------------------------------------------------
+// TSIPRegistrationUtility::CheckUnregisterRequestL
+// -----------------------------------------------------------------------------
+//
+void TSIPRegistrationUtility::CheckUnregisterRequestL (
+	CSIPRequest&                 aRequest, 
+	CSIPRegistrationBindingBase& aBinding)
+	{
+    const RStringF KContactHeaderName = 
+        SIPStrings::StringF(SipStrConsts::EContactHeader);	
+	
+	// panic if there is to header in unregister request in debug mode,
+	// Leaves with error code KErrArgument in release mode
+    __SIP_ASSERT_LEAVE(!aRequest.To(), KErrArgument);
+
+	// panic if there is from header in unregister request in debug mode,
+	// Leaves with error code KErrArgument in release mode
+    __SIP_ASSERT_LEAVE(!aRequest.From(), KErrArgument);
+
+	// panic if there is contact header in unregister request in debug mode,
+	// Leaves with error code KErrArgument in release mode
+    __SIP_ASSERT_LEAVE(!aRequest.HasHeader(KContactHeaderName),
+                       KErrArgument);
+
+    // fill in contact header
+	CSIPContactHeader* contact = 
+		static_cast<CSIPContactHeader*>(aBinding.Contact().CloneL());
+    CleanupStack::PushL(contact);
+	contact->SetExpiresParameterL(0); //set expires parameter to 0
+	aRequest.AddHeaderL(contact);
+	CleanupStack::Pop(contact);
+	}
+
+// -----------------------------------------------------------------------------
+// TSIPRegistrationUtility::CheckFetchingRequestL
+// -----------------------------------------------------------------------------
+//
+void TSIPRegistrationUtility::CheckFetchingRequestL (CSIPRequest& aRequest)
+	{
+    const RStringF KContactHeaderName = 
+        SIPStrings::StringF(SipStrConsts::EContactHeader);	
+	
+	// panic if there is contact header in binding in debug mode.
+	// leaves with error code KErrArgument in release mode.
+    __SIP_ASSERT_LEAVE(!(aRequest.HasHeader(KContactHeaderName)), 
+		               KErrArgument);
+
+	CheckToHeaderL (*(aRequest.To()));
+	}
+
+// -----------------------------------------------------------------------------
+// TSIPRegistrationUtility::CheckOutboundProxyCompParameterL
+// -----------------------------------------------------------------------------
+//
+void TSIPRegistrationUtility::CheckOutboundProxyCompParameterL(
+	CSIPRouteHeader& aOutboundProxy,
+	MSigComp&        aSigComp)
+	{
+	if (aOutboundProxy.SIPAddress().URI().IsSIPURI())
+	    {
+	    CSIPURI& uri = *(aOutboundProxy.SIPAddress().URI().SIPURI());
+	
+	    // when the uri of outboundProxy contains "comp" parameter and
+	    // comp == "sigcomp", leave if sigComp asked from MSigComp 
+	    // is not supported.
+        RStringF comp = SIPStrings::StringF(SipStrConsts::EComp);
+        RStringF sigcomp = SIPStrings::StringF(SipStrConsts::ESigComp);
+	    if (uri.ParamValue(comp) == sigcomp && !aSigComp.IsSupported())
+		    {
+		    User::Leave(KErrNotSupported);
+		    }
+	    }
+	}
+
+// -----------------------------------------------------------------------------
+// TSIPRegistrationUtility::CheckToHeaderL
+// -----------------------------------------------------------------------------
+//
+void TSIPRegistrationUtility::CheckToHeaderL(CSIPToHeader& aTo)
+	{
+	CURIContainer& uri = aTo.SIPAddress().URI();
+    if (uri.IsSIPURI())
+        {
+	    __ASSERT_ALWAYS(uri.SIPURI()->User().Length() > 0, 
+	                    User::Leave(KErrArgument));
+        }
+	}
+
+// -----------------------------------------------------------------------------
+// TSIPRegistrationUtility::CheckRegisterContactL
+// -----------------------------------------------------------------------------
+//
+void TSIPRegistrationUtility::CheckRegisterContactL(
+    CSIPRequest&      aRequest,
+	const TUint32     aIapId,
+    MTransactionUser& aTU)
+	{
+    const RStringF KContactHeaderName = 
+        SIPStrings::StringF(SipStrConsts::EContactHeader);	
+
+	__SIP_ASSERT_LEAVE(aRequest.HeaderCount(KContactHeaderName) == 1,
+		               KErrArgument);
+
+	CSIPContactHeader* contact = 
+		HEADER_IN_REQUEST(CSIPContactHeader, KContactHeaderName);
+
+	__SIP_ASSERT_LEAVE(!contact->Star(), KErrArgument);
+	__SIP_ASSERT_LEAVE(contact->SIPAddress() != 0, KErrArgument);
+
+    CheckSipsSchemeInAorAndOtherAddressL(*aRequest.To(),*contact->SIPAddress());
+
+	CheckSIPAddressInContactHeaderL(*contact, aIapId, aTU);
+	}
+
+// -----------------------------------------------------------------------------
+// TSIPRegistrationUtility::CheckUpdateRegisterContactL
+// -----------------------------------------------------------------------------
+//	
+void TSIPRegistrationUtility::CheckUpdateRegisterContactL(
+    CSIPRequest&                 aRequest,
+	CSIPRegistrationBindingBase& aBinding)
+	{
+    const RStringF KContactHeaderName = 
+        SIPStrings::StringF(SipStrConsts::EContactHeader);
+	
+	// contact header is not empty in request
+	if (aRequest.HasHeader(KContactHeaderName))
+		{
+		__SIP_ASSERT_LEAVE(aRequest.HeaderCount(KContactHeaderName) == 1, 
+                           KErrArgument);      
+
+		CSIPContactHeader* contactInRequest = 
+			HEADER_IN_REQUEST(CSIPContactHeader, KContactHeaderName);
+	
+		__SIP_ASSERT_LEAVE(!contactInRequest->Star(), KErrArgument);
+	
+	    CheckSipsSchemeInAorAndOtherAddressL(
+	        aBinding.AOR(),*contactInRequest->SIPAddress());
+		
+		if (contactInRequest->SIPAddress()->URI().IsSIPURI())
+		    {
+		    __ASSERT_ALWAYS(aBinding.Contact().SIPAddress()->URI().IsSIPURI(),
+                            User::Leave(KErrArgument));
+
+		    CSIPURI& uriInRequestContact = 
+		        *(contactInRequest->SIPAddress()->URI().SIPURI());
+		    
+		    CSIPURI& uriInBindingContact = 
+		        *(aBinding.Contact().SIPAddress()->URI().SIPURI());
+			
+		    CSIPHostPort& hostPortInRequestContact = 
+			    uriInRequestContact.HostPort();
+		    
+		    CSIPHostPort& hostPortInBindingContact = 
+			    uriInBindingContact.HostPort();
+	
+		    // if there is no host in contact of request
+		    if (hostPortInRequestContact.Host().CompareF(
+		            SIPStrings::StringF(SipStrConsts::ELocalHost).DesC()) == 0)
+			    {
+			    hostPortInRequestContact.SetHostL(hostPortInBindingContact.Host());
+			    }
+		    // if there is no port in contact of request
+		    if (!hostPortInRequestContact.HasPort() && 
+			    hostPortInBindingContact.HasPort())
+			    {
+			    hostPortInRequestContact.SetPort(hostPortInBindingContact.Port());
+			    }
+		    }
+	
+		// leave if the contact in binding is different as the one in request
+		__ASSERT_ALWAYS (contactInRequest->SIPAddress()->URI() ==
+		                 aBinding.Contact().SIPAddress()->URI(), 
+			             User::Leave (KErrArgument));	
+		}
+	else 
+		{
+		// create contact header, fill in the sip address from contact 
+		// in binding. add the contact header to request
+		CSIPAddress* address = 
+			CSIPAddress::NewLC(*(aBinding.Contact().SIPAddress()));
+		CSIPContactHeader* contactHeader = CSIPContactHeader::NewL(address);
+		CleanupStack::Pop(address);
+		CleanupStack::PushL(contactHeader);
+		aRequest.AddHeaderL(contactHeader);
+		CleanupStack::Pop(contactHeader);
+		}
+	}
+	
+// -----------------------------------------------------------------------------
+// TSIPRegistrationUtility::CheckRegisterExpiresValueL
+// -----------------------------------------------------------------------------
+//
+void TSIPRegistrationUtility::CheckRegisterExpiresValueL(CSIPRequest& aRequest)
+	{
+    const RStringF KContactHeaderName = 
+        SIPStrings::StringF(SipStrConsts::EContactHeader);
+
+    const RStringF KExpiresHeaderName = 
+        SIPStrings::StringF(SipStrConsts::EExpiresHeader);	
+	
+	CSIPContactHeader* contactHeader = 
+		HEADER_IN_REQUEST(CSIPContactHeader, KContactHeaderName);
+
+    // panic if there is no contact header == 0 in debug mode.
+	// leaves with error code KErrArgument in release mode.
+	__SIP_ASSERT_LEAVE(contactHeader, KErrArgument);
+
+	if (contactHeader->ExpiresParameter() >= 0)
+		{
+		// panic RegisterRequestExpiresParameterIsZero in release mode.
+		// leaves with error code KErrArgument in release mode.
+		__SIP_ASSERT_LEAVE((contactHeader->ExpiresParameter() != 0),
+			               KErrArgument);	
+		}
+    else if (!aRequest.HasHeader(KExpiresHeaderName))
+		{
+		// set default expires value one hour
+		contactHeader->SetExpiresParameterL(KOneHourInSeconds);
+		}
+	else
+		{
+		CSIPExpiresHeader* expiresHeader = 
+            HEADER_IN_REQUEST(CSIPExpiresHeader, KExpiresHeaderName);
+
+		// panic expires header value is 0 in release mode.
+		// leaves with error code KErrArgument in release mode.
+		__SIP_ASSERT_LEAVE(expiresHeader->Value() != 0, KErrArgument);
+		
+		// copies expires value from expire header to expires parameter
+		// in Contact, remove the expires header.
+		contactHeader->SetExpiresParameterL(expiresHeader->Value());
+		if (aRequest.RemoveHeader(expiresHeader) == KErrNone)
+			{	
+			delete expiresHeader; expiresHeader = 0; 
+			}
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// TSIPRegistrationUtility::RemoveRegisterExpiresParam
+// -----------------------------------------------------------------------------
+//
+void TSIPRegistrationUtility::RemoveRegisterExpiresParam(CSIPRequest& aRequest)
+	{
+    const RStringF KContactHeaderName = 
+        SIPStrings::StringF(SipStrConsts::EContactHeader);
+    
+    //remove the expires param
+	if (aRequest.HasHeader(KContactHeaderName))
+		{
+		CSIPContactHeader* contactHeader = 
+				HEADER_IN_REQUEST(CSIPContactHeader, KContactHeaderName);
+		if(contactHeader->ExpiresParameter() != KErrNotFound)
+			{
+			contactHeader->RemoveExpiresParam();
+			}
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// TSIPRegistrationUtility::CheckUpdateRegisterExpiresValueL
+// -----------------------------------------------------------------------------
+//
+void TSIPRegistrationUtility::CheckUpdateRegisterExpiresValueL(
+	CSIPRequest&                 aRequest,
+	CSIPRegistrationBindingBase& aBinding)
+	{
+    const RStringF KContactHeaderName = 
+        SIPStrings::StringF(SipStrConsts::EContactHeader);
+
+    const RStringF KExpiresHeaderName = 
+        SIPStrings::StringF(SipStrConsts::EExpiresHeader);	
+	
+	CSIPContactHeader* contactHeader = 
+		HEADER_IN_REQUEST(CSIPContactHeader, KContactHeaderName);
+
+	// panic is contactHeader == 0 in debug mode.
+	// leaves with error code KErrArgument in release mode.
+	__SIP_ASSERT_LEAVE(contactHeader, KErrArgument);
+
+	if (contactHeader->ExpiresParameter() < 0)
+		{
+        if (!aRequest.HasHeader(KExpiresHeaderName))
+			{
+			// set default expires value from binding
+			contactHeader->SetExpiresParameterL(
+				aBinding.Contact().ExpiresParameter());
+			}
+		else
+			{
+			// copies expires value from expire header to expires parameter
+			// in Contact, remove the expires header.
+			CSIPExpiresHeader* expiresHeader = 
+                HEADER_IN_REQUEST(CSIPExpiresHeader, KExpiresHeaderName);
+
+			contactHeader->SetExpiresParameterL(expiresHeader->Value());
+			if (aRequest.RemoveHeader(expiresHeader) == KErrNone)
+				{	
+				delete expiresHeader; expiresHeader = 0; 
+				}
+			}
+		}
+	}
+	
+// -----------------------------------------------------------------------------
+// TSIPRegistrationUtility::CheckSIPAddressInContactHeaderL
+// -----------------------------------------------------------------------------
+//
+void TSIPRegistrationUtility::CheckSIPAddressInContactHeaderL(
+	CSIPContactHeader& aContact,
+	const TUint32      aIapId,
+    MTransactionUser&  aTransationUser)
+    {
+    if (aContact.SIPAddress()->URI().IsSIPURI())
+        {
+	    CSIPURI& contactUri = *(aContact.SIPAddress()->URI().SIPURI());
+	    if (contactUri.HostPort().Host().CompareF(
+	            SIPStrings::StringF(SipStrConsts::ELocalHost).DesC()) == 0)
+		    {
+		    // fills in the host part by coping the Local IP address
+		    HBufC8* localAddr = 
+		        TSIPRegistrationUtility::LocalAddressLC(
+		            aIapId, aTransationUser);
+		    contactUri.HostPort().SetHostL(*localAddr);
+		    CleanupStack::PopAndDestroy(); //localAddr
+		    }
+        }
+    }
+    
+// -----------------------------------------------------------------------------
+// TSIPRegistrationUtility::CheckSipsSchemeInAorAndOtherAddressL
+// -----------------------------------------------------------------------------
+//
+void TSIPRegistrationUtility::CheckSipsSchemeInAorAndOtherAddressL(
+    const CSIPToHeader& aAor,
+    const CSIPAddress& aAddress)
+    {
+    if (aAor.SIPAddress().URI().IsSIPURI() &&
+        aAor.SIPAddress().URI().SIPURI()->IsSIPSURI())
+        {
+	    __ASSERT_ALWAYS(aAddress.URI().IsSIPURI(),
+	                    User::Leave(KErrSIPInvalidURIType));
+	    __ASSERT_ALWAYS(aAddress.URI().SIPURI()->IsSIPSURI(),
+	                    User::Leave(KErrSIPInvalidURIType));       
+        }
+    }