realtimenetprots/sipfw/SIP/ConnectionMgr/src/CTransport.cpp
changeset 0 307788aac0a8
child 20 a7d1e54a7332
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/realtimenetprots/sipfw/SIP/ConnectionMgr/src/CTransport.cpp	Tue Feb 02 01:03:15 2010 +0200
@@ -0,0 +1,1680 @@
+// 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          : CTransport.cpp
+// Part of       : ConnectionMgr
+// Version       : SIP/6.0 
+//
+
+
+
+#include "MHandler.h"
+#include "CTransport.h"
+#include "MTransportOwner.h"
+#include "CErrorHandler.h"
+#include "MTransactionFinder.h"
+#include "MServerTaFactory.h"
+#include "sipmessageparser.h"
+#include "MReceiverObserver.h"
+#include "SipLogs.h"
+#include "sipcontactheader.h"
+#include "sipaddress.h"
+#include "sipuri.h"
+#include "siptoheader.h"
+#include "sipfromheader.h"
+#include "sipcallidheader.h"
+#include "sipcseqheader.h"
+#include "sipviaheader.h"
+#include "sipheaderbase.h"
+#include "sipmessageparser.h"
+#include "siphostport.h"
+#include "sipcontenttypeheader.h"
+#include "sipmaxforwardsheader.h"
+#include "CSIPServerResolver.h"
+#include "utf.h"
+#include "CommonConsts.h"
+#include "sipstrings.h"
+#include "sipstrconsts.h"
+#include "uricontainer.h"
+#include "NetworkInfo.h"
+#include "COwnerSettingsList.h"
+#include "TSIPTransportParams.h"
+#include "MSigCompController.h"
+#include "CSocketContainer.h"
+#include "siperr.h"
+#include <sipnatbindingobserver.h>
+#include <sipnattraversalcontroller.h>
+
+
+const TUint KBadRequest = 400;
+const TUint KVersionError = 505;
+
+// -----------------------------------------------------------------------------
+// CTransport::CTransport
+// -----------------------------------------------------------------------------
+//
+CTransport::CTransport( MTransactionFinder& aFinder, 
+					    MServerTaFactory& aTaFactory,
+					    MTransportOwner& aTransportOwner,
+					    CSIPServerResolver& aServerResolver,
+					    MSigCompController& aSigCompHandler,
+					    const TSIPTransportParams& aTransportParams,
+					    CNetworkInfo& aNetworkInfo,
+					    COwnerSettingsList& aSettingsList,
+					    CSIPNATTraversalController& aNATTraversal ) :
+	iTransportParams( aTransportParams ),
+	iSettingsList( aSettingsList ),
+	iNATTraversal( aNATTraversal ),
+	iTaFinder( &aFinder ),
+	iTaFactory( &aTaFactory ),
+	iSigCompHandler( &aSigCompHandler ),
+	iNetworkInfo( aNetworkInfo )
+	{
+	iServerResolver = &aServerResolver;
+	iTransportOwner = &aTransportOwner;
+	}
+
+// -----------------------------------------------------------------------------
+// CTransport::~CTransport
+// -----------------------------------------------------------------------------
+//
+CTransport::~CTransport()
+	{
+	iIDArray.Reset();
+	iIDArray.Close();
+	iBindingObservers.Reset();
+	iBindingObservers.Close();
+	}
+
+// -----------------------------------------------------------------------------
+// CTransport::RecvL
+// -----------------------------------------------------------------------------
+//
+void CTransport::RecvL( HBufC8* aData,
+					    const TInetAddr& aRemoteAddr,
+					    TBool aCompressed )
+
+	{
+	__ASSERT_DEBUG( aData, User::Panic( _L("Nullpointer"), KErrGeneral ) );
+
+	CleanupStack::PushL( aData );
+	CSIPMessageParser* sipparser = CSIPMessageParser::NewLC();	
+	HBufC8* dataCopy = aData->Des().AllocL();
+	CSIPMessage* message( NULL );
+	TInt parserError = sipparser->FromText( aData, &message );
+	CleanupStack::PopAndDestroy( sipparser );
+    CleanupStack::Pop(aData);
+    CleanupStack::PushL(dataCopy);
+	
+	if ( !message && parserError )
+	    {
+	    // Show data to NATTraversalController if message couldn't be parsed
+	    // and it was received via UDP (might be e.g. a STUN binding response).
+	    TBool permissionToUse( EFalse );
+	    RSocket* socket = AcquireUdpSocket( 0, aRemoteAddr, permissionToUse );
+	    if ( socket )
+	        {
+	       	__SIP_LOG( "Received unrecognized data, passing to NATTraversal" )
+	        
+	        // NOTE: NATTraversal does not use the socket for sending
+	        // in DataReceived phase.
+	        TBool handled( EFalse );
+	        iNATTraversal.DataReceivedL( *dataCopy, *socket, handled );
+	        
+	        // Release immediately
+	        UdpSocketReleased( 0, *socket );
+	        }
+	    CleanupStack::PopAndDestroy( dataCopy );
+	    }
+	else
+	    {
+	    CleanupStack::PopAndDestroy( dataCopy );
+	    CleanupStack::PushL( message );
+	    RecvL( message, aRemoteAddr, parserError, aCompressed );
+	    CleanupStack::Pop( message );
+	    }
+	}
+
+// -----------------------------------------------------------------------------
+// CTransport::RecvL
+// -----------------------------------------------------------------------------
+//
+void CTransport::RecvL( CSIPMessage* aMessage,
+					    const TInetAddr& aRemoteAddr, 
+					    TInt aParserError,
+					    TBool aCompressed )
+	{
+	HandleSigCompAllowDenyL( aRemoteAddr, aParserError, aCompressed ); 
+	
+	if ( aMessage )
+		{
+		if ( aParserError == KErrNone && AllMandatoryHeaders( *aMessage ) )
+			{
+            __SIP_ADDR_LOG( "Incoming message from", aRemoteAddr )
+				
+			if ( aMessage->IsRequest() )
+				{
+				if ( HandleServerRequestL( aMessage, aRemoteAddr ) == KErrNone )
+					{
+					RouteL( aMessage, aRemoteAddr );
+					return;
+					}
+				}
+			else
+				{
+				if ( HandleServerResponseL( aMessage, aRemoteAddr ) )
+					{
+					RouteL( aMessage, aRemoteAddr );
+					return;
+					}
+				}
+			}
+		else
+			{			
+			if ( aMessage->IsRequest() && !IsAck( *aMessage ) )
+				{
+				SetReceivedIfNeededL( TopViaHeader( aMessage ), aRemoteAddr );
+				SendErrorResponseL( KBadRequest,
+			                        SipStrConsts::EPhraseBadRequest, 
+					                *aMessage,
+				                    aRemoteAddr );
+				__SIP_LOG( "Invalid SIP Request" )
+				}
+			else
+				{
+				__SIP_LOG( "Invalid SIP Response or ACK" )
+				}
+				
+			__SIP_DES8_LOG( "Invalid data: ", aMessage->Content() )
+			__SIP_INT_LOG1( "Parser error", aParserError )
+			}
+		}
+	else
+		{
+		__SIP_INT_LOG1( "Parser error", aParserError )
+		}
+	delete aMessage;
+	}
+
+// -----------------------------------------------------------------------------
+// CTransport::RouteL
+// -----------------------------------------------------------------------------
+//
+void CTransport::RouteL( CSIPMessage* aMessage, const TInetAddr& aRemoteAddr )
+	{
+	TInt leaveValue = KErrNone;
+	
+	MReceiverObserver* receiver = iTaFinder->Search( *aMessage );
+	if ( receiver )
+		{
+		const TSIPTransportParams& tpParams = receiver->TransportParams();
+		
+		// Discard the message if receiving is not allowed
+		if ( !iSettingsList.IsReceivingAllowed( tpParams, 
+		                                        aRemoteAddr, 
+		                                        Protocol(), 
+		                                        SourcePort() ) )
+		    {
+		    delete aMessage;
+		    return;
+		    }
+		
+		if ( aMessage->IsRequest() )
+			{
+			TRAP( leaveValue,
+				  receiver->ReceiveL( static_cast<CSIPRequest*>( aMessage ) ) );
+			}
+		else
+			{
+			HandleResponseNATTraversalL( 
+			        static_cast< CSIPResponse& >( *aMessage ), 
+			        aRemoteAddr,
+			        const_cast<TSIPTransportParams&>(
+			            tpParams ).NATBindingObserver() );
+			   
+			TRAP( leaveValue,
+				  receiver->ReceiveL( static_cast<CSIPResponse*>( aMessage ) ) );
+			}
+		if ( leaveValue != KErrNone )
+			{
+			delete aMessage;
+			receiver->LeaveOccurred( leaveValue );
+			}
+		}
+	else
+		{
+		if ( aMessage->IsRequest() )
+			{
+			TTransactionId id;
+			// OwnerId cannot be known at this stage, default id will be used
+			TSIPTransportParams tpParams( KDefaultOwnerId,
+										  iTransportOwner->IapId() );
+			// Find out whether some existing SAs should be used also for
+			// this new transaction
+			TUint32 tpId = iSettingsList.FindTransportId( aRemoteAddr );
+			
+			tpParams.SetTransportId( tpId );
+			
+			receiver = iTaFactory->NewTransactionL(
+				static_cast<CSIPRequest&>( *aMessage ),
+				tpParams,
+				id );
+			if ( receiver )
+				{
+				if ( IsConnectedTransport() )
+					{
+					TResponseRoute route( id, aRemoteAddr );
+					iIDArray.Append( route );
+					}
+				TRAP( leaveValue,
+					  receiver->ReceiveL( static_cast<CSIPRequest*>( aMessage ) ) );
+				if ( leaveValue != KErrNone )
+					{
+					delete aMessage;
+					receiver->LeaveOccurred( leaveValue );
+					}
+				}
+			else
+				{
+				delete aMessage;
+				}
+			}
+		else
+			{
+			delete aMessage;
+			}
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CTransport::Send
+// -----------------------------------------------------------------------------
+//
+void CTransport::Send( const TSIPTransportParams& aParams,
+                       CSIPResponse& aResponse,
+					   const TInetAddr& aAddr,
+					   TRequestStatus &aStatus )
+	{
+	TRAPD( leaveValue,
+		   SendToNetL( aParams, aAddr, aResponse, EFalse, Protocol(), aStatus ) );
+	if ( leaveValue != KErrNone )
+		{
+		TRequestStatus* stat = &aStatus;
+		User::RequestComplete( stat, leaveValue );
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CTransport::Send
+// -----------------------------------------------------------------------------
+//
+void CTransport::Send( const TSIPTransportParams& aParams,
+                       CSIPResponse& aResponse,
+					   TTransactionId aId,
+					   TRequestStatus &aStatus )
+	{
+	TInt leaveValue = KErrNone;
+	TInetAddr remoteAddr;
+	
+	if ( Protocol() == KProtocolInetUdp )
+		{
+		TRAP( leaveValue, 
+			  HandleClientResponseL( aParams, &aResponse, remoteAddr );
+			  SendToNetL( aParams, remoteAddr, aId, aResponse, aStatus ) );
+		if ( leaveValue != KErrNone )
+			{
+			TRequestStatus* stat = &aStatus;
+			User::RequestComplete( stat, leaveValue );
+			}
+		}
+	else
+		{
+		TInt pos;
+		pos = iIDArray.Count();
+		while ( pos > 0 )
+			{
+			if ( iIDArray[ pos - 1 ].TAId() == aId )
+				{
+				TRAP( leaveValue,
+					  UpdateContactHeadersL( aParams, &aResponse, ETrue );
+					  SendToNetL( aParams,
+	                              iIDArray[ pos - 1 ].Address(),
+								  aResponse,
+								  EFalse,
+								  0,
+								  aStatus ) );
+				if ( leaveValue != KErrNone )
+					{
+					TRequestStatus* stat = &aStatus;
+					User::RequestComplete( stat, leaveValue );
+					}
+				return;
+				}
+			pos--;
+			}
+		TRAP( leaveValue,
+			  HandleClientResponseL( aParams, &aResponse, remoteAddr );
+			  SendToNetL( aParams, remoteAddr, aResponse, EFalse, Protocol(), aStatus ) );
+		if ( leaveValue != KErrNone )
+			{
+			TRequestStatus* stat = &aStatus;
+			User::RequestComplete( stat, leaveValue );
+			}
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CTransport::Send
+// -----------------------------------------------------------------------------
+//
+void CTransport::Send( const TSIPTransportParams& aParams,
+                       CSIPRequest& aRequest,
+                       TBool aForceUDP,
+					   const TInetAddr& aAddr,
+					   TUint aOrigTransport,
+					   TRequestStatus &aStatus,
+					   TBool aPublicAddrResolved )
+	{
+	TInt leaveValue = KErrNone;
+	TRAP( leaveValue, 
+		  HandleClientRequestL( aParams, aRequest, aPublicAddrResolved );
+		  UpdateListenersL( aParams, &aRequest );
+		  SendToNetL( aParams, aAddr, aRequest, aForceUDP, aOrigTransport, aStatus ) );
+		 
+	if ( leaveValue != KErrNone )
+		{
+		TRequestStatus* stat = &aStatus;
+		User::RequestComplete( stat, leaveValue );
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CTransport::HandleL
+// -----------------------------------------------------------------------------
+//
+TBool CTransport::HandleL(
+    const TSIPTransportParams& aParams,
+    CSIPMessage* aMessage, 
+    TTransactionId aId,
+    TBool aIsStrict )
+	{
+	if ( !aMessage ) 
+		{
+		return EFalse;
+		}
+	TInt pos = iIDArray.Count();
+	while ( pos > 0 )
+		{
+		if ( iIDArray[ pos - 1 ].TAId() == aId )	
+			{
+			return ETrue;
+			}
+		pos--;
+		}
+
+    if ( aIsStrict )
+        {
+        return EFalse;
+        }
+        
+	TInetAddr remoteAddr;
+	HandleClientResponseL( aParams, aMessage, remoteAddr );
+	return HandleL( aParams, aMessage, remoteAddr, 0, ETrue );
+	}
+
+// -----------------------------------------------------------------------------
+// CTransport::HandleL
+// -----------------------------------------------------------------------------
+//
+TBool CTransport::HandleL(
+    const TSIPTransportParams& aParams,
+    CSIPMessage* aMessage, 
+    const TInetAddr& aAddr,
+    TUint aLocalPort,
+    TBool aIsStrict )
+	{
+	if ( !aMessage ) 
+		{
+		return EFalse;
+		}
+	CSIPViaHeader* viaHeader = TopViaHeader( aMessage );
+	if ( viaHeader )
+		{
+		if ( HandleMessage( aParams, 
+		                    viaHeader->Transport(), 
+		                    aAddr,
+		                    aLocalPort,
+		                    aIsStrict ) )
+			{
+			return ETrue;
+			}
+		}
+	return EFalse;
+	}
+
+// -----------------------------------------------------------------------------
+// CTransport::Handle
+// -----------------------------------------------------------------------------
+//
+TBool CTransport::Handle( TUint32 aTransportId )
+    {
+    return ( IsReservedTransport() && 
+             iTransportParams.TransportId() == aTransportId );
+    }
+    
+// -----------------------------------------------------------------------------
+// CTransport::Match
+// -----------------------------------------------------------------------------
+//	
+TBool CTransport::Match( const TSIPTransportParams& aParams )
+    {
+	return ( aParams.TransportId() == 0 || Handle( aParams.TransportId() ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CTransport::HasRemoteHost
+// -----------------------------------------------------------------------------
+//
+TBool CTransport::HasRemoteHost(
+    const TSIPTransportParams& aParams,
+    const TInetAddr& aRemoteHost,
+    RStringF aProtocol )
+	{
+	return HandleMessage( aParams, aProtocol, aRemoteHost, 0, ETrue );
+	}
+
+// -----------------------------------------------------------------------------
+// CTransport::Remove
+// -----------------------------------------------------------------------------
+//
+TBool CTransport::Remove( const TSIPTransportParams& aParams )
+    {
+    // Default transports are not removed when owner closes its connection.
+    // Also removal of persistent and reserved transport are handled separately.
+    return ( !IsDefault() &&
+             iTransportParams.OwnerId() == aParams.OwnerId() &&
+             !IsPersistent() &&
+             !IsReservedTransport() );
+    }
+
+// -----------------------------------------------------------------------------
+// CTransport::Remove
+// -----------------------------------------------------------------------------
+//
+TBool CTransport::Remove( MSIPNATBindingObserver& aSIPNATBindingObserver )
+    {
+    return ( !IsDefault() && RemoveBindingObserver( aSIPNATBindingObserver ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CTransport::Shutdown
+// -----------------------------------------------------------------------------
+//    
+TBool CTransport::Shutdown( 
+    TUint32 /*aTransportId*/,
+    MSIPTransportRemovalObserver* /*aRemovalObserver*/ )
+    {
+    return EFalse;
+    }
+    
+// -----------------------------------------------------------------------------
+// CTransport::IsReservedTransport
+// -----------------------------------------------------------------------------
+//	
+TBool CTransport::IsReservedTransport() const
+    {
+    return ( iTransportParams.TransportId() > 0 );
+    }
+
+// -----------------------------------------------------------------------------
+// CTransport::AcquireUdpSocketL
+// -----------------------------------------------------------------------------
+//    
+RSocket* CTransport::AcquireUdpSocket( 
+    MSocketUsagePermissionObserver* /*aObserver*/,
+    const TInetAddr& /*aRemoteAddr*/,
+    TBool& /*aPermissionToUse*/ )
+    {
+    return 0;
+    }
+
+// -----------------------------------------------------------------------------
+// CTransport::UdpSocketReleased
+// -----------------------------------------------------------------------------
+//                                        
+void CTransport::UdpSocketReleased( 
+    MSocketUsagePermissionObserver* /*aObserver*/,
+    RSocket& /*aSocket*/ )
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CTransport::PersistentRemoteAddr
+// -----------------------------------------------------------------------------
+// 
+TInetAddr* CTransport::PersistentRemoteAddr( 
+    MSIPNATBindingObserver* /*aBindingObserver*/ )
+    {
+    return 0;
+    }
+    
+// -----------------------------------------------------------------------------
+// CTransport::HandleClientRequestL
+// -----------------------------------------------------------------------------
+//
+void CTransport::HandleClientRequestL(
+    const TSIPTransportParams& aParams,
+    CSIPRequest& aRequest,
+    TBool aPublicAddrResolved )
+	{
+	__ASSERT_DEBUG( aRequest.HasHeader(
+		SIPStrings::StringF( SipStrConsts::EMaxForwardsHeader ) ),
+		User::Panic( _L( "no MaxForwards header" ), KErrArgument ) );
+	
+	__ASSERT_DEBUG( AllMandatoryHeaders( aRequest ),
+		User::Panic( _L( "Mandatory header is missing" ), KErrArgument ) );
+		
+    TUint32 transportId = aParams.TransportId();
+
+   	CSIPViaHeader* viaHeader = TopViaHeader( &aRequest );
+    if ( viaHeader )
+    	{
+    	// Currently both (aPublicAddrResolved==ETrue) and (receivePort>0)
+    	// never happen at the same time.
+    	if ( !aPublicAddrResolved )
+    		{
+    		TUint receivePort =
+    			iSettingsList.SavedLocalReceivePort( transportId );
+    		// If host is already filled (e.g. ConnectionMgr put public address
+    		// to Via, sends request, gets 401, TU sends an updated request, Via
+    		// has the public addr) don't put the private address to Via.
+    		// Even if host is already set, set port if receivePort exists.
+    		if ( viaHeader->SentByHostPort().Host().CompareF(
+			     SIPStrings::StringF( SipStrConsts::ELocalHost ).DesC() ) == 0 )
+        		{
+		    	HBufC8* localaddress = LocalAddressL();
+		    	CleanupStack::PushL( localaddress );
+		    	viaHeader->SentByHostPort().SetHostL( *localaddress );
+				CleanupStack::PopAndDestroy( localaddress );
+
+				// Sent-by is now set for the first time, must set the port too
+				if ( receivePort == 0 )
+		            {
+		            receivePort = KDefaultSipPort;
+		            }
+	        	}
+	        if ( receivePort )
+	            {
+	            viaHeader->SentByHostPort().SetPort( receivePort );
+	            }
+    		}
+
+        // Add empty rport param
+       	RStringF rport = SIPStrings::Pool().OpenFStringL( KParamrport );
+        CleanupClosePushL( rport );
+        viaHeader->SetParamL( rport );
+        CleanupStack::PopAndDestroy(); // rport
+        }
+
+    UpdateContactHeadersL( aParams, &aRequest, !aPublicAddrResolved );
+	
+	// Check if request is sent integrity protected 
+	// (i.e. IPSec SA exists, ignore TLS)
+	iNetworkInfo.HandleRequestL( aRequest,
+	        iSettingsList.HasSavedTransportInfo( transportId ) &&
+	        !iSettingsList.HasSavedTLSTransportInfo( transportId ) );		
+	}
+
+// -----------------------------------------------------------------------------
+// CTransport::GetAddrFromResponseL
+// -----------------------------------------------------------------------------
+//
+void CTransport::GetAddrFromResponseL(
+    const TSIPTransportParams& aParams,
+    CSIPMessage& aMessage, 
+    TInetAddr& aAddr )
+	{
+	HandleClientResponseL( aParams, &aMessage, aAddr );
+	}
+
+// -----------------------------------------------------------------------------
+// CTransport::HandleClientResponseL
+// -----------------------------------------------------------------------------
+//
+void CTransport::HandleClientResponseL(
+    const TSIPTransportParams& aParams,
+    CSIPMessage* aMessage, 
+    TInetAddr& aAddr )
+	{	
+	CSIPViaHeader* viaHeader = TopViaHeader( aMessage );
+	if ( viaHeader )
+		{
+		TBool portSet( EFalse );
+		
+		if ( viaHeader->HasParam( SIPStrings::StringF( SipStrConsts::EMaddr ) ) )
+			{
+			ConvertToInetAddrL( 
+			    viaHeader->ParamValue(
+			        SIPStrings::StringF( SipStrConsts::EMaddr ) ).DesC(), aAddr );
+			
+			if ( !viaHeader->HasParam( 
+			        SIPStrings::StringF( SipStrConsts::ETtl ) ) )
+				{
+				viaHeader->SetTtlParamL(1);
+				}
+			}
+		else if ( viaHeader->HasParam(
+		    SIPStrings::StringF( SipStrConsts::EReceived ) ) )
+			{
+			ConvertToInetAddrL( 
+			    viaHeader->ParamValue(
+			        SIPStrings::StringF( SipStrConsts::EReceived ) ).DesC(),
+			        aAddr );
+			
+			portSet = HandleClientResponseRPortL( *viaHeader, aAddr );
+			}
+		else
+			{
+			ConvertToInetAddrL( viaHeader->SentByHostPort().Host(),
+			                    aAddr );
+			}
+	    
+	    // Port could be already set if received and rport values existed.
+	    if ( !portSet )
+	        {
+    		if ( viaHeader->SentByHostPort().HasPort() )
+    			{
+    			aAddr.SetPort( viaHeader->SentByHostPort().Port() );
+    			}
+    		else
+    			{
+    			aAddr.SetPort( KDefaultSipPort );
+    			}
+	        }
+		}
+		
+	UpdateContactHeadersL( aParams, aMessage, ETrue );
+	}
+
+// -----------------------------------------------------------------------------
+// CTransport::HandleServerResponseL
+// -----------------------------------------------------------------------------
+//
+TBool CTransport::HandleServerResponseL( CSIPMessage* aMessage,
+										 const TInetAddr& aAddr )
+	{
+	__ASSERT_DEBUG( aMessage, User::Panic( _L("Nullpointer"), KErrGeneral ) );
+	
+	if ( !CorrectProtocolInVia( *aMessage ) )
+		{
+		return EFalse;
+		}
+
+	if ( !OnlyOneViaHeader( *aMessage ) )
+		{
+		return EFalse;
+		}
+	if ( Protocol() == KProtocolInetUdp )
+		{
+		if (CheckAndUpdateContentLengthL( aMessage, aAddr ) != KErrNone )
+			{
+			return EFalse;
+			}
+		}
+	
+	if ( IsConnectedTransport() &&
+		 !aMessage->HasAnnouncedContentLength() )
+		{
+		return EFalse;
+		}
+
+	if ( !SupportedSIPVersion( *aMessage ) )
+		{
+		return EFalse;
+		}
+
+	return ETrue;
+	}
+
+// -----------------------------------------------------------------------------
+// CTransport::HandleServerRequestL
+// -----------------------------------------------------------------------------
+//
+TInt CTransport::HandleServerRequestL( CSIPMessage* aMessage,
+									   const TInetAddr& aAddr )
+	{
+	__ASSERT_ALWAYS( aMessage, User::Leave( KErrArgument ) );
+	
+	SetReceivedIfNeededL( TopViaHeader( aMessage ), aAddr );
+
+	if ( !SupportedSIPVersion( *aMessage ) || 
+	     !CorrectProtocolInVia( *aMessage ) )
+		{
+		SendErrorResponseL( KVersionError,
+			                SipStrConsts::EPhraseVersionNotSupported,
+					        *aMessage,
+					        aAddr );
+		return KErrArgument;
+		}
+
+	if ( ( IsConnectedTransport() && 
+	     !aMessage->HasAnnouncedContentLength() ) ||
+	     !ContentTypeOk( *aMessage ) ||
+	     !MethodIsSameInCSecAndReqLine( static_cast<CSIPRequest&>( *aMessage ) ) )
+		{
+		SendErrorResponseL( KBadRequest,
+					        SipStrConsts::EPhraseBadRequest,
+					        *aMessage,
+				          	aAddr );
+		return KErrArgument;
+		}
+		
+	if ( Protocol() == KProtocolInetUdp )
+		{
+		if ( CheckAndUpdateContentLengthL( aMessage, aAddr ) != KErrNone )
+			{
+			return KErrGeneral;
+			}
+		}
+
+	CSIPViaHeader* viaHeader = TopViaHeader( aMessage );
+	if ( viaHeader )
+	{
+		TBool isPortPresent = viaHeader->SentByHostPort().HasPort();
+		if (isPortPresent)
+		{
+			TUint sentByPort = viaHeader->SentByHostPort().Port();
+			if ((sentByPort > KMaxPortValue) || (sentByPort < KMinPortValue))
+			{
+		    	__SIP_LOG( "Topmost Via-header has invalid port value, dropping request" )
+		    	return KErrArgument;
+			}
+		}
+	}
+
+	return KErrNone;
+	}
+
+// -----------------------------------------------------------------------------
+// CTransport::AllMandatoryHeaders
+// -----------------------------------------------------------------------------
+//
+TBool CTransport::AllMandatoryHeaders( CSIPMessage& aMessage )
+	{
+	return aMessage.HasHeader( SIPStrings::StringF( SipStrConsts::EViaHeader ) )
+		&&
+		aMessage.HasHeader( SIPStrings::StringF( SipStrConsts::EToHeader ) )
+		&&
+		aMessage.HasHeader( SIPStrings::StringF( SipStrConsts::EFromHeader ) )
+		&&
+		aMessage.HasHeader( SIPStrings::StringF( SipStrConsts::ECallIDHeader ) )
+		&&
+		aMessage.HasHeader( SIPStrings::StringF( SipStrConsts::ECSeqHeader ) );
+	}
+
+// -----------------------------------------------------------------------------
+// CTransport::SupportedSIPVersion
+// -----------------------------------------------------------------------------
+//
+TBool CTransport::SupportedSIPVersion( CSIPMessage& aMessage )
+	{
+	TSglQueIter<CSIPHeaderBase> iter = 
+	    aMessage.Headers( SIPStrings::StringF( SipStrConsts::EViaHeader ) );
+	CSIPHeaderBase* header = 0;
+	iter.SetToFirst();
+	
+	while ( ( header = iter++ ) != 0 )
+		{
+		CSIPViaHeader* via = static_cast<CSIPViaHeader*>( header );
+		if ( !( via->SentProtocolVersion() ==
+		        SIPStrings::StringF( SipStrConsts::EDefaultVersionNumber ) ) )
+			{
+			return EFalse;
+			}
+		}
+
+	return ( aMessage.SIPVersion() == 
+	         SIPStrings::StringF( SipStrConsts::EDefaultProtocolVersion ) );
+	}
+
+// -----------------------------------------------------------------------------
+// CTransport::CorrectProtocolInVia
+// -----------------------------------------------------------------------------
+//
+TBool CTransport::CorrectProtocolInVia( CSIPMessage& aMessage )
+	{
+	TSglQueIter<CSIPHeaderBase> iter = 
+	    aMessage.Headers( SIPStrings::StringF( SipStrConsts::EViaHeader ) );
+	CSIPHeaderBase* header = 0;
+	iter.SetToFirst();
+	
+	while ( ( header = iter++ ) != 0 )
+		{
+		CSIPViaHeader* via = static_cast<CSIPViaHeader*>( header );
+		if ( via->SentProtocolName() !=
+			 SIPStrings::StringF( SipStrConsts::ESIP ) )
+			{
+			return EFalse;
+			}
+		}
+	
+	return ETrue;
+	}
+
+// -----------------------------------------------------------------------------
+// CTransport::ContentTypeOk
+// -----------------------------------------------------------------------------
+//
+TBool CTransport::ContentTypeOk( CSIPMessage& aMessage )
+	{
+	if ( aMessage.Content().Length() > 0 )
+		{
+		if ( !aMessage.HasHeader(
+		        SIPStrings::StringF( SipStrConsts::EContentTypeHeader ) ) )
+			{
+			return EFalse;
+			}
+		}
+	return ETrue;
+	}
+
+// -----------------------------------------------------------------------------
+// CTransport::SetReceivedIfNeededL
+// aAddr has to be passed by value
+// -----------------------------------------------------------------------------
+//
+void CTransport::SetReceivedIfNeededL( CSIPViaHeader* aViaHeader,
+									   TInetAddr aAddr )
+	{
+	if ( aViaHeader )
+		{
+		if ( aAddr.IsV4Mapped() )
+			{
+			aAddr.ConvertToV4();
+			}
+		aAddr.SetScope( 0 );
+		
+		const TInt KMaxAddrLen = 64;
+		TBuf<KMaxAddrLen> address;
+		aAddr.Output( address );
+		TBuf8<KMaxAddrLen> received;
+		CnvUtfConverter::ConvertFromUnicodeToUtf8( received, address );
+			            
+	    RStringF rport = SIPStrings::Pool().OpenFStringL( KParamrport );
+	    CleanupClosePushL( rport );
+	
+	    // If rport param exists but value has not been set, 
+	    // set it to be the source port
+	    TBool rportSet( EFalse );
+	    if ( aViaHeader->HasParam( rport ) && !HasValue( *aViaHeader, rport ) )
+	        {
+	        const TInt KMaxTUintAsDesLen = 10;
+	        TBuf8<KMaxTUintAsDesLen> sourcePortDes;
+	        sourcePortDes.AppendNum( static_cast<TInt64>( aAddr.Port() ) );
+	        
+	        RStringF rportVal = SIPStrings::Pool().OpenFStringL( sourcePortDes );
+	    	CleanupClosePushL( rportVal );
+	        aViaHeader->SetParamL( rport, rportVal );
+	        CleanupStack::PopAndDestroy(); // rportVal
+	        rportSet = ETrue;
+	        }
+	        
+	    CleanupStack::PopAndDestroy(); // rport
+	    
+	    // Set received param even if the address is same as in sent-by if
+	    // rport value was set   
+	    if ( aViaHeader->SentByHostPort().Host().CompareF( received ) != 0 ||
+	         rportSet )
+			{
+			RStringF recv = SIPStrings::Pool().OpenFStringL( received );
+			CleanupClosePushL( recv );
+			aViaHeader->SetParamL(
+			            SIPStrings::StringF(SipStrConsts::EReceived), recv );
+			CleanupStack::PopAndDestroy(); //recv
+			}
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CTransport::CheckAndUpdateContentLengthL
+// -----------------------------------------------------------------------------
+//
+TInt CTransport::CheckAndUpdateContentLengthL( CSIPMessage* aMessage,
+											   const TInetAddr& aAddr )
+	{
+	if ( aMessage->HasAnnouncedContentLength() )
+		{
+		if ( static_cast<TUint>( aMessage->Content().Length() ) == 
+			 aMessage->AnnouncedContentLength() )
+			{
+			return KErrNone;
+			}
+
+		if ( static_cast<TUint>( aMessage->Content().Length() ) > 
+			 aMessage->AnnouncedContentLength() )
+			{
+			HBufC8* content = aMessage->Content().AllocL();
+			content->Des().Delete( aMessage->AnnouncedContentLength(),
+								   aMessage->Content().Length() - 
+								   aMessage->AnnouncedContentLength() );
+
+			aMessage->SetContent( content );
+			return KErrNone;
+			}
+
+		if ( aMessage->IsRequest() )
+			{
+			SendErrorResponseL( KBadRequest, 
+			                    SipStrConsts::EPhraseBadRequest,
+            			        *aMessage, 
+            			        aAddr );
+			}
+		return KErrGeneral;
+		}
+	else
+		{
+		return KErrNone;
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CTransport::TopViaHeader
+// -----------------------------------------------------------------------------
+//
+CSIPViaHeader* CTransport::TopViaHeader( CSIPMessage* aMessage )
+	{
+	if ( aMessage->HasHeader( SIPStrings::StringF(SipStrConsts::EViaHeader) ) )
+		{
+		TSglQueIter<CSIPHeaderBase> iter =
+			aMessage->Headers( SIPStrings::StringF(SipStrConsts::EViaHeader) );
+		CSIPHeaderBase* header = iter;
+		return static_cast<CSIPViaHeader*>( header );
+		}
+
+	return 0;
+	}
+
+// -----------------------------------------------------------------------------
+// CTransport::UpdateListenersL
+// -----------------------------------------------------------------------------
+//
+void CTransport::UpdateListenersL(
+    const TSIPTransportParams& aParams, 
+    CSIPMessage* aMessage )
+	{	
+	if ( aMessage->IsRequest() )
+		{
+		if ( static_cast<CSIPRequest*>(aMessage)->Method() != 
+		     SIPStrings::StringF(SipStrConsts::ERegister) )
+			{
+			return;
+			}
+		}
+	if ( aMessage->HasHeader( 
+	        SIPStrings::StringF(SipStrConsts::EContactHeader) ) )
+		{
+		TSglQueIter<CSIPHeaderBase> iter = 
+		    aMessage->Headers( 
+		        SIPStrings::StringF(SipStrConsts::EContactHeader) );
+		CSIPHeaderBase* header = 0;
+		CURIContainer* uriContainer = 0;
+		while ( ( header = iter++ ) != 0 )
+			{
+			CSIPContactHeader* contact =
+				static_cast<CSIPContactHeader*>( header );
+				
+		    CSIPAddress* sipAddr = contact->SIPAddress();
+			if ( sipAddr )
+			    {
+			    uriContainer = &sipAddr->URI();
+			
+    			if ( uriContainer->IsSIPURI() )
+    				{
+    				CSIPURI* sipUri = uriContainer->SIPURI();
+    				HBufC8* localaddress = LocalAddressL();
+    				CleanupStack::PushL( localaddress );
+    				TUint port = sipUri->HostPort().Port();
+    				
+    				if ( sipUri->HostPort().Host().CompareF( *localaddress ) == 0 &&
+    				     sipUri->HostPort().HasPort() )
+    					{
+    					if ( sipUri->HasParam(
+    					     SIPStrings::StringF(SipStrConsts::ETransport) ) )
+    					    {
+    					    RStringF transport = 
+    					        sipUri->ParamValue(
+    					            SIPStrings::StringF(SipStrConsts::ETransport) );
+    					         
+    					    if ( transport == SIPStrings::StringF(SipStrConsts::ETCP) )
+    					        {
+    				            iSettingsList.ReservePrivatePortL( aParams, port );
+    					        iTransportOwner->AddListenerL( aParams,
+    					                                       KProtocolInetTcp, 
+    					                                       port );
+    					        CleanupStack::PopAndDestroy( localaddress );
+    					        return;
+    					        }
+    					    
+    					    if ( transport == SIPStrings::StringF(SipStrConsts::ETLS) )
+    					        {
+    					        // No support for incoming TLS connections
+    					        CleanupStack::PopAndDestroy( localaddress );
+    					        return;
+    					        }
+    					    }
+    					    
+    				    iSettingsList.ReservePrivatePortL( aParams, port );     
+    				    iTransportOwner->AddListenerL( aParams,
+    				                                   KProtocolInetUdp, 
+    				                                   port );	
+    					}
+    				CleanupStack::PopAndDestroy( localaddress );
+    				}
+			    }
+			}
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CTransport::OnlyOneViaHeader
+// -----------------------------------------------------------------------------
+//
+TBool CTransport::OnlyOneViaHeader( CSIPMessage& aMessage )
+	{
+	return aMessage.HeaderCount(
+	                    SIPStrings::StringF(SipStrConsts::EViaHeader) ) == 1;	
+	}
+
+// -----------------------------------------------------------------------------
+// CTransport::MethodIsSameInCSecAndReqLine
+// -----------------------------------------------------------------------------
+//
+TBool CTransport::MethodIsSameInCSecAndReqLine( CSIPRequest& aMessage )
+	{
+	if ( aMessage.HasHeader( SIPStrings::StringF(SipStrConsts::ECSeqHeader) ) )
+		{
+		TSglQueIter<CSIPHeaderBase> iter =
+			aMessage.Headers(SIPStrings::StringF(SipStrConsts::ECSeqHeader) );
+		CSIPHeaderBase* header = iter;
+		CSIPCSeqHeader* cseq = static_cast<CSIPCSeqHeader*>( header );
+		if ( cseq->Method() == aMessage.Method() )
+			{
+			return ETrue;
+			}
+		}
+	return EFalse;
+	}
+
+// -----------------------------------------------------------------------------
+// CTransport::SetPersistencyL
+// -----------------------------------------------------------------------------
+//	
+void CTransport::SetPersistencyL( 
+    const TInetAddr& /*aRemoteAddr*/, 
+    TBool aIsPersistent,
+    MSIPNATBindingObserver* aBindingObserver )
+    {
+    if ( !aBindingObserver )
+        {
+        return;
+        }
+        
+    if ( aIsPersistent )
+        {
+        AddBindingObserverL( *aBindingObserver );
+        }
+    else
+        {
+        RemoveBindingObserver( *aBindingObserver );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CTransport::IsPersistent
+// -----------------------------------------------------------------------------
+//
+TBool CTransport::IsPersistent() const
+    {
+    return ( iBindingObservers.Count() > 0 );
+    }
+
+// -----------------------------------------------------------------------------
+// CTransport::IsDefault
+// -----------------------------------------------------------------------------
+//
+TBool CTransport::IsDefault() const
+    {
+    return ( iTransportParams.OwnerId() == KDefaultOwnerId );
+    }
+
+// -----------------------------------------------------------------------------
+// CTransport::RemoveResponseRoute
+// -----------------------------------------------------------------------------
+//
+void CTransport::RemoveResponseRoute( const TInetAddr& aRemoteAddr )
+	{
+	TInt pos = iIDArray.Count();
+	while ( pos > 0 )
+		{
+		if ( iIDArray[ pos - 1 ].Address().CmpAddr( aRemoteAddr ) )
+			{
+			iIDArray.Remove( pos - 1 );
+			}
+		pos--;
+		}
+	}
+	
+// -----------------------------------------------------------------------------
+// CTransport::RemoveResponseRoute
+// -----------------------------------------------------------------------------
+//
+void CTransport::RemoveResponseRoute( TTransactionId aId )
+	{
+	TInt pos = iIDArray.Count();
+	while ( pos > 0 )
+		{
+		if ( iIDArray[ pos - 1 ].TAId() == aId )
+			{
+			iIDArray.Remove( pos - 1 );
+			}
+		pos--;
+		}
+	iIDArray.Compress();
+	}
+
+// -----------------------------------------------------------------------------
+// CTransport::SendToNetL
+// -----------------------------------------------------------------------------
+//
+void CTransport::SendToNetL( const TSIPTransportParams& /*aParams*/,
+                             const TInetAddr& /*aAddress*/,
+							 CSIPMessage& /*aMessage*/, 
+							 TBool /*aForceUDP*/,
+							 TUint /*aOrigTransport*/,
+							 TRequestStatus& /*aStatus*/ )
+	{	
+	__ASSERT_DEBUG(EFalse,
+		User::Panic(_L("CTransport::SendToNetL is called"),
+		KErrGeneral));
+	}
+
+// -----------------------------------------------------------------------------
+// CTransport::SendToNetL
+// -----------------------------------------------------------------------------
+//
+void CTransport::SendToNetL( const TSIPTransportParams& /*aParams*/,
+                             const TInetAddr& /*aAddress*/,
+							 TTransactionId /*aId*/, 
+							 CSIPMessage& /*aMessage*/,
+						 	 TRequestStatus& /*aStatus*/ )
+	{
+	__ASSERT_DEBUG(EFalse,
+		User::Panic(_L("CTransport::SendToNetL is called"),
+		KErrGeneral));
+	}
+
+// -----------------------------------------------------------------------------
+// CTransport::SendToNetL
+// -----------------------------------------------------------------------------
+//
+void CTransport::SendToNetL( const TSIPTransportParams& /*aParams*/,
+                             const TInetAddr& /*aAddress*/,
+					   		 CSIPMessage& /*aMessage*/,
+					   		 TRequestStatus& /*aStatus*/ )
+	{
+	}
+
+// -----------------------------------------------------------------------------
+// CTransport::IsAck
+// -----------------------------------------------------------------------------
+//
+TBool CTransport::IsAck( CSIPMessage& aMessage )
+	{
+	if ( aMessage.IsRequest() )
+		{
+		if ( static_cast<CSIPRequest*>( &aMessage )->Method() == 
+		     SIPStrings::StringF(SipStrConsts::EAck) )
+			{
+			return ETrue;
+			}
+		}
+	return EFalse;
+	}
+
+// -----------------------------------------------------------------------------
+// CTransport::HandleSigCompAllowDenyL
+// -----------------------------------------------------------------------------
+//	
+void CTransport::HandleSigCompAllowDenyL(
+    const TInetAddr& aRemoteAddr, 
+    TInt aParserError,
+    TBool aCompressed )
+    {
+    if ( !iSigCompHandler->IsSupported() || !aCompressed )
+        {
+        return;
+        }
+        
+	if ( aParserError == KErrNone )
+	    {
+	    iSigCompHandler->AllowL( aRemoteAddr, 
+	                             iTransportOwner->IapId() );
+	    }
+	else
+	    {
+	    iSigCompHandler->Deny();
+	    }
+    }
+
+// -----------------------------------------------------------------------------
+// CTransport::CancelResponseSend
+// -----------------------------------------------------------------------------
+//
+TBool CTransport::CancelResponseSend( 
+    TTransactionId aId, 
+    TBool aCancelAlso2xxResponses )
+	{
+	// Remove response route information only after all responses related
+	// to the transaction are canceled.
+	if ( aCancelAlso2xxResponses )
+	    {
+	    RemoveResponseRoute( aId );
+	    }
+	
+	return EFalse;
+	}
+
+// -----------------------------------------------------------------------------
+// CTransport::ProtocolType
+// -----------------------------------------------------------------------------
+//
+TUint CTransport::ProtocolType()
+	{
+	return Protocol();
+	}
+
+// -----------------------------------------------------------------------------
+// CTransport::LocalAddressL
+// -----------------------------------------------------------------------------
+//
+HBufC8* CTransport::LocalAddressL()
+	{
+	TInetAddr address;
+	iTransportOwner->GetLocalAddrL( address, NULL );
+    return ConvertInetAddrToTextL( address );
+	}
+    
+// -----------------------------------------------------------------------------
+// CTransport::HandleMixedAddressFamilysL
+// -----------------------------------------------------------------------------
+// 
+void CTransport::HandleMixedAddressFamilysL( 
+    CSIPMessage& aMessage, 
+	const TInetAddr& aRemoteAddr )
+    {
+    // Possibly update contact header if message is request
+    if ( aMessage.IsRequest() )
+        {
+        if ( aMessage.HasHeader( 
+                        SIPStrings::StringF(SipStrConsts::EContactHeader) ) )
+    		{
+            TSglQueIter<CSIPHeaderBase> iter = 
+                aMessage.Headers( 
+                            SIPStrings::StringF(SipStrConsts::EContactHeader) );
+    		CSIPHeaderBase* header = 0;
+    		while ( ( header = iter++ ) != 0 )
+    			{
+    			CSIPContactHeader* contact = 
+    			        static_cast<CSIPContactHeader*>( header );
+    			CSIPAddress* sipAddr = contact->SIPAddress();
+    			
+    			if ( sipAddr )
+    			    {
+    			    CURIContainer& uriContainer = sipAddr->URI();
+    			    if ( uriContainer.IsSIPURI() )
+    			        {
+    			        ChangeHostAddressFamilyIfNeededL( 
+    			                uriContainer.SIPURI()->HostPort(), 
+    			                aRemoteAddr );
+    			        }
+    			    }
+    			}
+    		}
+        }
+        
+    // Possibly update via header (also if message is response)
+    CSIPViaHeader* viaHeader = TopViaHeader( &aMessage );
+    if ( viaHeader )
+        {
+        ChangeHostAddressFamilyIfNeededL( viaHeader->SentByHostPort(), 
+                                          aRemoteAddr );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CTransport::IsConnectedTransport
+// -----------------------------------------------------------------------------
+//
+TBool CTransport::IsConnectedTransport()
+    {
+    TUint protocol( Protocol() );
+    return ( protocol == KProtocolInetTcp || protocol == KProtocolTls );
+    }
+
+// -----------------------------------------------------------------------------
+// CTransport::NotifyFlowFailure
+// -----------------------------------------------------------------------------
+//   
+TBool CTransport::NotifyFlowFailure()
+    {
+    // NOTE: Notification leads to synchronous removal of the bindingobserver
+    // from the array and the whole transport is removed when all observers
+    // has been removed.
+    
+    TInt observerCount( iBindingObservers.Count() );
+    TInt lastIndex( observerCount - 1 );
+    for ( TInt i = lastIndex; i >= 0; i-- )
+        {
+        iBindingObservers[ i ]->FlowFailure( KErrSIPTransportFailure );
+        }
+        
+    return ( observerCount > 0 );
+    }
+    
+// -----------------------------------------------------------------------------
+// CTransport::SendErrorResponseL
+// -----------------------------------------------------------------------------
+//  
+void CTransport::SendErrorResponseL( 
+	TUint aResponseCode, 
+	TInt aStrIndex, 
+	CSIPMessage& aMessage, 
+	const TInetAddr& aAddr )
+    {
+    if ( !IsAck( aMessage ) )
+		{			
+		ErrorHandler().SendErrorResponseL( 
+		    iTransportParams,
+		    aResponseCode,
+	        SIPStrings::StringF( aStrIndex ),
+			aMessage,
+			aAddr );
+		}
+    }
+  
+// -----------------------------------------------------------------------------
+// CTransport::UpdateContactHeadersL
+// -----------------------------------------------------------------------------
+//  
+void CTransport::UpdateContactHeadersL( 
+    const TSIPTransportParams& aParams, 
+    CSIPMessage* aMessage,
+    TBool aUpdatePorts )
+    {
+    if ( !aMessage )
+        {
+        return;
+        }
+        
+    TSglQueIter<CSIPHeaderBase> iter = 
+        aMessage->Headers( SIPStrings::StringF(SipStrConsts::EContactHeader) );
+    CSIPHeaderBase* header = NULL;
+    while ( ( header = iter++ ) != NULL )
+    	{
+    	CSIPContactHeader* contact = static_cast<CSIPContactHeader*>( header );
+        CSIPAddress* sipAddr = contact->SIPAddress();
+			
+        if ( sipAddr )
+            {
+            CURIContainer& uri = sipAddr->URI();
+            if ( uri.IsSIPURI() )
+                {
+                TUint receivePort = 
+                    iSettingsList.SavedLocalReceivePort( aParams.TransportId() );
+            
+                if ( aUpdatePorts && receivePort > 0 )
+                    {
+                    uri.SIPURI()->HostPort().SetPort( receivePort );
+                    }
+                
+                RStringF transportParam =
+                    uri.SIPURI()->ParamValue(
+                        SIPStrings::StringF( SipStrConsts::ETransport ) );
+
+                if ( Protocol() == KProtocolTls )
+                    {
+                    RStringF tls = SIPStrings::StringF( SipStrConsts::ETLS );
+                    // SIP-URI with transport=TLS must not use sips scheme
+                    uri.SIPURI()->SetSIPS( transportParam != tls );
+                    if(transportParam == tls)
+                        {
+                        uri.SIPURI()->SetSIPS(EFalse);
+                        //Delete the param transport=tls from the URI as it is deprecated in RFC 3261
+                        uri.SIPURI()->DeleteParam(SIPStrings::StringF( SipStrConsts::ETransport ));
+                        }
+                    }
+                else
+                    {
+                    uri.SIPURI()->SetSIPS( EFalse );
+                    }
+			    }
+			}
+		}    
+        
+    }
+
+// -----------------------------------------------------------------------------
+// CTransport::ChangeHostAddressFamilyIfNeededL
+// -----------------------------------------------------------------------------
+//     
+void CTransport::ChangeHostAddressFamilyIfNeededL( 
+    CSIPHostPort& aHostPort, 
+    const TInetAddr& aRemoteAddr )
+    {
+    if ( aHostPort.HostType() == CSIPHostPort::ESIPHostName ||
+         aHostPort.HostType() == CSIPHostPort::ESIPNoHost )
+        {
+        return;
+        }
+        
+    TInetAddr hostInetAddr;
+    ConvertToInetAddrL( aHostPort.Host(), hostInetAddr );
+    
+    if ( iTransportOwner->IsLocalAddr( hostInetAddr ) )
+        {
+        // Fills hostInetAddr based on the address family of aRemoteAddr.
+        // If aRemoteAddr is IPv6, then hostInetAddr is set to IPv6.
+        // If aRemoteAddr is IPv4, then hostInetAddr is set to IPv4 if possible.
+        iTransportOwner->FillWithMatchingAddrFamily( 
+            hostInetAddr, &aRemoteAddr );
+        }
+    else
+        {
+        TBool isRemoteIPv6Addr( aRemoteAddr.Address() == 0 ||
+                                aRemoteAddr.IsV4Compat() );
+        
+        if ( isRemoteIPv6Addr && aHostPort.HostType() == CSIPHostPort::ESIPIpv4 )
+            {
+             // Update host if remote address is IPv6 and host address is IPv4
+            hostInetAddr.ConvertToV4Compat();
+            }
+        else if ( !isRemoteIPv6Addr && 
+                ( hostInetAddr.IsV4Compat() || hostInetAddr.IsV4Mapped() ) )
+            {
+            // Update host if remote address is IPv4 address and host is
+            // IPv6 address which can be converted to V4
+            hostInetAddr.ConvertToV4();
+            }
+        else
+            {
+            // Otherwise no actions taken
+            return;
+            }
+        }
+        
+    HBufC8* hostAddr = ConvertInetAddrToTextL( hostInetAddr );
+    CleanupStack::PushL( hostAddr );
+    aHostPort.SetHostL( *hostAddr );
+    CleanupStack::PopAndDestroy( hostAddr );
+    }
+ 
+// -----------------------------------------------------------------------------
+// CTransport::HandleClientResponseRPortL
+// -----------------------------------------------------------------------------
+// 
+ TBool CTransport::HandleClientResponseRPortL( 
+    CSIPViaHeader& aViaHeader, 
+    TInetAddr& aAddr )
+    {
+    if ( aViaHeader.Transport() != SIPStrings::StringF( SipStrConsts::EUDP ) )
+        {
+        return EFalse;
+        }
+    
+    TBool portSet( EFalse ); 
+    RStringF rport = SIPStrings::Pool().OpenFStringL( KParamrport );
+	CleanupClosePushL( rport );
+	
+	if ( HasValue( aViaHeader, rport ) )
+	    {
+	    TLex8 lexer( aViaHeader.ParamValue( rport ).DesC() );
+    	TInt rportVal( 0 );
+    	User::LeaveIfError( lexer.Val( rportVal ) );
+    	aAddr.SetPort( rportVal );
+    	portSet = ETrue;
+	    }
+	    
+    CleanupStack::PopAndDestroy(); // rport
+    
+    return portSet;
+    }
+
+// -----------------------------------------------------------------------------
+// CTransport::HandleResponseNATTraversalL
+// -----------------------------------------------------------------------------
+//    
+void CTransport::HandleResponseNATTraversalL( 
+    CSIPResponse& aResponse, 
+    const TInetAddr& aRemoteAddr,
+    MSIPNATBindingObserver* aBindingObserver )
+    {
+    TBool persistent( EFalse );
+    CSIPCSeqHeader* cseq = aResponse.CSeq();
+    if ( aResponse.Type() == CSIPResponse::E2XX && 
+         cseq && 
+         cseq->Method() == SIPStrings::StringF( SipStrConsts::ERegister ) )
+        {
+        CSocketContainer& container = GetSocketContainerL( aRemoteAddr );
+    
+        if ( container.HasSecureSocket() )
+            {
+            persistent = iNATTraversal.RefreshNATBindingL( 
+                *container.SecureSocket(),
+                aBindingObserver );
+            }
+        else
+            {
+            persistent = iNATTraversal.RefreshNATBindingL(  
+                container.Socket(), 
+                aBindingObserver );
+            }
+        SetPersistencyL( aRemoteAddr, persistent, aBindingObserver );
+        }
+    InformSendingStatus( aRemoteAddr );
+    }
+
+// -----------------------------------------------------------------------------
+// CTransport::HasValue
+// -----------------------------------------------------------------------------
+//   
+TBool CTransport::HasValue( CSIPViaHeader& aViaHeader, RStringF& aParam )
+    {
+    TBool hasVal( EFalse );
+	if ( aViaHeader.HasParam( aParam ) )
+	    {
+		hasVal = aViaHeader.ParamValue( aParam ).DesC().Length() > 0;
+	    }
+	return hasVal;
+    }
+
+// -----------------------------------------------------------------------------
+// CTransport::AddBindingObserverL
+// -----------------------------------------------------------------------------
+//     
+void CTransport::AddBindingObserverL( MSIPNATBindingObserver& aBindingObserver )
+    {
+    // Don't mind if the observer already exists.
+    TInt err = iBindingObservers.InsertInAddressOrder( &aBindingObserver );
+    if ( err && err != KErrAlreadyExists )
+        {
+        User::Leave( err );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CTransport::RemoveBindingObserver
+// -----------------------------------------------------------------------------
+//     
+TBool CTransport::RemoveBindingObserver( 
+    MSIPNATBindingObserver& aBindingObserver )
+    {
+    TInt index = iBindingObservers.FindInAddressOrder( &aBindingObserver );
+    TBool found( index >= 0 && index < iBindingObservers.Count() );
+    if ( found )
+        {
+        iBindingObservers.Remove( index );
+        iBindingObservers.Compress();
+        }
+    
+    // Allow removal of whole transport if no more observers exist.
+    // Reserved transports are removed with different mechanism.
+    return ( found && !IsPersistent() && !IsReservedTransport() );
+    }
+    
+// -----------------------------------------------------------------------------
+// CTransport::ConvertToInetAddrL
+// -----------------------------------------------------------------------------
+//     
+void CTransport::ConvertToInetAddrL( 
+    const TDesC8& aAddrStr, 
+    TInetAddr& aAddr )
+    {	                        
+	HBufC* tempInputAddr = HBufC::NewLC( aAddrStr.Length() );
+	TPtr ptempInputAddr( tempInputAddr->Des() );
+	ptempInputAddr.Copy( aAddrStr );
+
+	User::LeaveIfError( aAddr.Input( ptempInputAddr ) );
+	
+	CleanupStack::PopAndDestroy( tempInputAddr );
+    }
+    
+// -----------------------------------------------------------------------------
+// CTransport::ConvertInetAddrToTextL
+// -----------------------------------------------------------------------------
+//        
+HBufC8* CTransport::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;
+    }
+
+// End of File