--- /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