diff -r 000000000000 -r 307788aac0a8 realtimenetprots/sipfw/SIP/ConnectionMgr/src/CTransport.cpp --- /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 +#include + + +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( aMessage ) ) ); + } + else + { + HandleResponseNATTraversalL( + static_cast< CSIPResponse& >( *aMessage ), + aRemoteAddr, + const_cast( + tpParams ).NATBindingObserver() ); + + TRAP( leaveValue, + receiver->ReceiveL( static_cast( 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( *aMessage ), + tpParams, + id ); + if ( receiver ) + { + if ( IsConnectedTransport() ) + { + TResponseRoute route( id, aRemoteAddr ); + iIDArray.Append( route ); + } + TRAP( leaveValue, + receiver->ReceiveL( static_cast( 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( *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 iter = + aMessage.Headers( SIPStrings::StringF( SipStrConsts::EViaHeader ) ); + CSIPHeaderBase* header = 0; + iter.SetToFirst(); + + while ( ( header = iter++ ) != 0 ) + { + CSIPViaHeader* via = static_cast( 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 iter = + aMessage.Headers( SIPStrings::StringF( SipStrConsts::EViaHeader ) ); + CSIPHeaderBase* header = 0; + iter.SetToFirst(); + + while ( ( header = iter++ ) != 0 ) + { + CSIPViaHeader* via = static_cast( 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 address; + aAddr.Output( address ); + TBuf8 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 sourcePortDes; + sourcePortDes.AppendNum( static_cast( 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( aMessage->Content().Length() ) == + aMessage->AnnouncedContentLength() ) + { + return KErrNone; + } + + if ( static_cast( 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 iter = + aMessage->Headers( SIPStrings::StringF(SipStrConsts::EViaHeader) ); + CSIPHeaderBase* header = iter; + return static_cast( header ); + } + + return 0; + } + +// ----------------------------------------------------------------------------- +// CTransport::UpdateListenersL +// ----------------------------------------------------------------------------- +// +void CTransport::UpdateListenersL( + const TSIPTransportParams& aParams, + CSIPMessage* aMessage ) + { + if ( aMessage->IsRequest() ) + { + if ( static_cast(aMessage)->Method() != + SIPStrings::StringF(SipStrConsts::ERegister) ) + { + return; + } + } + if ( aMessage->HasHeader( + SIPStrings::StringF(SipStrConsts::EContactHeader) ) ) + { + TSglQueIter iter = + aMessage->Headers( + SIPStrings::StringF(SipStrConsts::EContactHeader) ); + CSIPHeaderBase* header = 0; + CURIContainer* uriContainer = 0; + while ( ( header = iter++ ) != 0 ) + { + CSIPContactHeader* contact = + static_cast( 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 iter = + aMessage.Headers(SIPStrings::StringF(SipStrConsts::ECSeqHeader) ); + CSIPHeaderBase* header = iter; + CSIPCSeqHeader* cseq = static_cast( 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( &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 iter = + aMessage.Headers( + SIPStrings::StringF(SipStrConsts::EContactHeader) ); + CSIPHeaderBase* header = 0; + while ( ( header = iter++ ) != 0 ) + { + CSIPContactHeader* contact = + static_cast( 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 iter = + aMessage->Headers( SIPStrings::StringF(SipStrConsts::EContactHeader) ); + CSIPHeaderBase* header = NULL; + while ( ( header = iter++ ) != NULL ) + { + CSIPContactHeader* contact = static_cast( 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