diff -r 000000000000 -r 307788aac0a8 realtimenetprots/sipfw/SIP/ConnectionMgr/src/CTransportUdp.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/realtimenetprots/sipfw/SIP/ConnectionMgr/src/CTransportUdp.cpp Tue Feb 02 01:03:15 2010 +0200 @@ -0,0 +1,787 @@ +// Copyright (c) 2002-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 : CTransportUdp.cpp +// Part of : ConnectionMgr +// Version : SIP/4.0 +// + + + + +#include "CTransportUdp.h" +#include "CSipConnection.h" +#include "CErrorHandler.h" +#include "CReceiver.h" +#include "CSenderUdp.h" +#include "CSIPServerResolver.h" +#include "sipviaheader.h" +#include "siphostport.h" +#include "sipmessage.h" +#include "sipresponse.h" +#include "Lwtimer.h" +#include "SipLogs.h" +#include "CResHandler.h" +#include "utf.h" +#include "CommonConsts.h" +#include "sipstrings.h" +#include "sipstrconsts.h" +#include "siperr.h" +#include "NetworkInfo.h" +#include "COwnerSettingsList.h" +#include "CSocketContainer.h" +#include "MSocketUsagePermissionObserver.h" +#include + + +const TInt KTransportUsersGranularity = 2; + + +// ----------------------------------------------------------------------------- +// CTransportUdp::NewL +// ----------------------------------------------------------------------------- +// +CTransportUdp* CTransportUdp::NewL( + RSocketServ& aServer, + TUint aPort, + MTransactionFinder& aFinder, + MServerTaFactory& aTaFactory, + MTransportOwner& aTransportOwner, + MTimerManager& aTimerManager, + CSIPServerResolver& aServerResolver, + RConnection& aConnection, + MSigCompController& aSigCompHandler, + TUint aICMPErrorWaitTime, + CNetworkInfo& aNetworkInfo, + COwnerSettingsList& aSettingsList, + const TSIPTransportParams& aTransportParams, + CSIPNATTraversalController& aNATTraversal, + TBool aOnlyForReceiving ) + { + CTransportUdp* self = NewLC( aServer, aPort, aFinder, aTaFactory, + aTransportOwner, aTimerManager, + aServerResolver, aConnection, aSigCompHandler, + aICMPErrorWaitTime, aNetworkInfo, + aSettingsList, aTransportParams, + aNATTraversal, aOnlyForReceiving ); + CleanupStack::Pop( self ); + return self; + } + +// ----------------------------------------------------------------------------- +// CTransportUdp::NewLC +// ----------------------------------------------------------------------------- +// +CTransportUdp* CTransportUdp::NewLC( + RSocketServ& aServer, + TUint aPort, + MTransactionFinder& aFinder, + MServerTaFactory& aTaFactory, + MTransportOwner& aTransportOwner, + MTimerManager& aTimerManager, + CSIPServerResolver& aServerResolver, + RConnection& aConnection, + MSigCompController& aSigCompHandler, + TUint aICMPErrorWaitTime, + CNetworkInfo& aNetworkInfo, + COwnerSettingsList& aSettingsList, + const TSIPTransportParams& aTransportParams, + CSIPNATTraversalController& aNATTraversal, + TBool aOnlyForReceiving ) + { + CTransportUdp* self = new ( ELeave ) CTransportUdp( aServer, + aPort, + aFinder, + aTaFactory, + aTransportOwner, + aTimerManager, + aServerResolver, + aConnection, + aSigCompHandler, + aICMPErrorWaitTime, + aNetworkInfo, + aSettingsList, + aTransportParams, + aNATTraversal, + aOnlyForReceiving ); + CleanupStack::PushL( self ); + self->ConstructL(); + return self; + } + +// ----------------------------------------------------------------------------- +// CTransportUdp::CTransportUdp +// ----------------------------------------------------------------------------- +// +CTransportUdp::CTransportUdp( + RSocketServ& aServer, + TUint aPort, + MTransactionFinder& aFinder, + MServerTaFactory& aTaFactory, + MTransportOwner& aTransportOwner, + MTimerManager& aTimerManager, + CSIPServerResolver& aServerResolver, + RConnection& aConnection, + MSigCompController& aSigCompHandler, + TUint aICMPErrorWaitTime, + CNetworkInfo& aNetworkInfo, + COwnerSettingsList& aSettingsList, + const TSIPTransportParams& aTransportParams, + CSIPNATTraversalController& aNATTraversal, + TBool aOnlyForReceiving ) + : + CTransport( aFinder, aTaFactory, aTransportOwner, aServerResolver, + aSigCompHandler, aTransportParams, aNetworkInfo, + aSettingsList, aNATTraversal ), + iSocketServ( &aServer ), + iConnection( &aConnection ), + iSourcePort( aPort ), + iTimerManager( aTimerManager ), + iList( CResponseHandler::iOffset ), + iListIter( iList ), + iICMPErrorWaitTime( aICMPErrorWaitTime ), + iTransportUsers( KTransportUsersGranularity ), + iOnlyForReceiving( aOnlyForReceiving ), + iIsSending( EFalse ) + { + } + +// ----------------------------------------------------------------------------- +// CTransportUdp::ConstructL +// ----------------------------------------------------------------------------- +// +void CTransportUdp::ConstructL() + { + iErrorHandler = CTransportErrorHandler::NewL( *this ); + + RefreshSocketContainerL( KAfInet ); + RefreshSocketContainerL( KAfInet6 ); + + iSender = CSenderUdp::NewL( *this, iSettingsList ); + + iTransportUsers.AppendL( iTransportParams.TransportId() ); + } + +// ----------------------------------------------------------------------------- +// CTransportUdp::~CTransportUdp +// ----------------------------------------------------------------------------- +// +CTransportUdp::~CTransportUdp() + { + if ( iSocketUsagePermissionObserver ) + { + iSocketUsagePermissionObserver->UsagePermissionChanged( iIPv4Socket, EFalse ); + iSocketUsagePermissionObserver->UsagePermissionChanged( iIPv6Socket, EFalse ); + } + + iNATTraversal.SocketIdle( EFalse, iIPv4Socket ); + iNATTraversal.SocketIdle( EFalse, iIPv6Socket ); + + CResponseHandler* listItem; + iListIter.SetToFirst(); + while ( ( listItem = iListIter++ ) != 0 ) + { + iList.Remove( *listItem ); + delete listItem; + } + delete iErrorHandler; + delete iIPv4Receiver; + delete iIPv6Receiver; + delete iSender; + delete iIPv4SocketContainer; + delete iIPv6SocketContainer; + iNATTraversal.SocketIdle( EFalse, iIPv4Socket ); + iIPv4Socket.Close(); + iNATTraversal.SocketIdle( EFalse, iIPv6Socket ); + iIPv6Socket.Close(); + iTransportUsers.Close(); + } + +// ----------------------------------------------------------------------------- +// CTransportUdp::Handle +// ----------------------------------------------------------------------------- +// +TBool CTransportUdp::Handle( TUint32 aTransportId ) + { + // Only interested about "protected" transports + return ( ( aTransportId > 0 ) && + ( iTransportUsers.Find( aTransportId ) != KErrNotFound ) ); + } + +// ----------------------------------------------------------------------------- +// CTransportUdp::HandleMessage +// ----------------------------------------------------------------------------- +// +TBool CTransportUdp::HandleMessage( const TSIPTransportParams& aParams, + RStringF aProtocol, + const TInetAddr& /*aRemoteAddr*/, + TUint aLocalPort, + TBool aIsStrict ) + { + // If not strict comparison, receiveonly mode has no significance + return ( aProtocol == SIPStrings::StringF( SipStrConsts::EUDP ) && + Match( aParams ) && + ( aLocalPort == 0 || iSourcePort == aLocalPort ) && + ( !aIsStrict || !iOnlyForReceiving ) ); + } + +// ----------------------------------------------------------------------------- +// CTransportUdp::ResetSocketL +// ----------------------------------------------------------------------------- +// +void CTransportUdp::ResetSocketL() + { + iIPv4Socket.Close(); + CSocketContainer* tmp = CreateSocketContainerL( KAfInet, iIPv4Socket ); + delete iIPv4SocketContainer; + iIPv4SocketContainer = tmp; + + iIPv6Socket.Close(); + tmp = CreateSocketContainerL( KAfInet6, iIPv6Socket ); + delete iIPv6SocketContainer; + iIPv6SocketContainer = tmp; + } + +// ----------------------------------------------------------------------------- +// CTransportUdp::StopL +// ----------------------------------------------------------------------------- +// +TBool CTransportUdp::StopL() + { + if ( iIPv4Receiver ) + { + iIPv4Receiver->Cancel(); + } + if ( iIPv6Receiver ) + { + iIPv6Receiver->Cancel(); + } + iSender->Cancel(); + + // If there's binding observers, notify that old socket + // cannot be used anymore + return NotifyFlowFailure(); + } + +// ----------------------------------------------------------------------------- +// CTransportUdp::ContinueL +// ----------------------------------------------------------------------------- +// +void CTransportUdp::ContinueL() + { + WaitL(); + iSender->SendNextL(); + } + +// ----------------------------------------------------------------------------- +// CTransportUdp::SourcePort +// ----------------------------------------------------------------------------- +// +TUint CTransportUdp::SourcePort() + { + return iSourcePort; + } + +// ----------------------------------------------------------------------------- +// CTransportUdp::WaitL +// ----------------------------------------------------------------------------- +// +void CTransportUdp::WaitL() + { + if ( iIPv4Receiver ) + { + iIPv4Receiver->Listen(); + } + if ( iIPv6Receiver ) + { + iIPv6Receiver->Listen(); + } + } + +// ----------------------------------------------------------------------------- +// CTransportUdp::SendToNetL +// ----------------------------------------------------------------------------- +// +void CTransportUdp::SendToNetL( const TSIPTransportParams& aParams, + const TInetAddr& aAddress, + CSIPMessage& aMessage, + TBool aForceUDP, + TUint aOrigTransport, + TRequestStatus &aStatus ) + { + RefreshSocketContainerL( CSender::IpAddrType( aAddress ) ); + HandleMixedAddressFamilysL( aMessage, aAddress ); + + iSender->SendL( + aParams, + aMessage, + aAddress, + aOrigTransport, + aStatus, + EFalse, + aForceUDP ); + } + +// ----------------------------------------------------------------------------- +// CTransportUdp::SendToNetL +// ----------------------------------------------------------------------------- +// +void CTransportUdp::SendToNetL( const TSIPTransportParams& aParams, + const TInetAddr& aAddress, + CSIPMessage& aMessage, + TRequestStatus &aStatus ) + { + RefreshSocketContainerL( CSender::IpAddrType( aAddress ) ); + HandleMixedAddressFamilysL( aMessage, aAddress ); + + iSender->SendL( + aParams, + aMessage, + aAddress, + 0, + aStatus, + EFalse, + EFalse ); + } + +// ----------------------------------------------------------------------------- +// CTransportUdp::SendToNetL +// ----------------------------------------------------------------------------- +// +void CTransportUdp::SendToNetL( const TSIPTransportParams& aParams, + const TInetAddr& aAddress, + TTransactionId aId, + CSIPMessage& aMessage, + TRequestStatus &aStatus ) + { + RefreshSocketContainerL( CSender::IpAddrType( aAddress ) ); + HandleMixedAddressFamilysL( aMessage, aAddress ); + + CResponseHandler* listItem = 0; + iListIter.SetToFirst(); + while ( ( listItem = iListIter++ ) != 0 ) + { + if(listItem->Handle( aId ) ) + { + listItem->SendL( aParams, + static_cast( aMessage ), + aAddress, + aStatus ); + return; + } + } + CResponseHandler* responsehandler = + CResponseHandler::NewL( *this, iTimerManager, *iServerResolver, aId, + iICMPErrorWaitTime ); + iList.AddLast( *responsehandler ); + responsehandler->SendL( aParams, + static_cast( aMessage ), + aAddress, + aStatus); + } + +// ----------------------------------------------------------------------------- +// CTransportUdp::CancelSend +// ----------------------------------------------------------------------------- +// +TBool CTransportUdp::CancelSend( TRequestStatus& aStatus ) + { + return iSender->FindAndCancel( aStatus ); + } + +// ----------------------------------------------------------------------------- +// CTransportUdp::CancelAllRequests +// ----------------------------------------------------------------------------- +// +void CTransportUdp::CancelAllRequests( CSIPConnection::TState aReason ) + { + iSender->CancelAllRequests( aReason ); + } + +// ----------------------------------------------------------------------------- +// CTransportUdp::CancelResponseSend +// ----------------------------------------------------------------------------- +// +TBool CTransportUdp::CancelResponseSend( + TTransactionId aId, + TBool aCancelAlso2xxResponses ) + { + CResponseHandler* listItem = 0; + iListIter.SetToFirst(); + while ( ( listItem = iListIter++ ) != 0 ) + { + if ( listItem->Handle( aId ) ) + { + return listItem->CancelAll( aId, aCancelAlso2xxResponses ); + } + } + return EFalse; + } + +// ----------------------------------------------------------------------------- +// CTransportUdp::IsWaiting +// ----------------------------------------------------------------------------- +// +TBool CTransportUdp::IsWaiting( TUint aProtocol, TUint aPort ) + { + return ( aPort == SourcePort() && aProtocol == KProtocolInetUdp ); + } + +// ----------------------------------------------------------------------------- +// CTransportUdp::SocketContainer +// ----------------------------------------------------------------------------- +// +CSocketContainer& CTransportUdp::SocketContainer() + { + if ( iIPv6SocketContainer ) + { + return *iIPv6SocketContainer; + } + return *iIPv4SocketContainer; + } +// ----------------------------------------------------------------------------- +// CTransportUdp::SocketContainer +// ----------------------------------------------------------------------------- +// +CSocketContainer* CTransportUdp::SocketContainer( TUint aIPAddrFamily ) + { + if ( aIPAddrFamily == KAfInet ) + { + if ( iIPv4SocketContainer ) + { + return iIPv4SocketContainer; + } + return iIPv6SocketContainer; + } + else + { + if ( iIPv6SocketContainer ) + { + return iIPv6SocketContainer; + } + } + return NULL; // Only IPv6 socket can be used for sending to a IPv6 address + } + +// ----------------------------------------------------------------------------- +// CTransportUdp::ICMPErrorL +// ----------------------------------------------------------------------------- +// +void CTransportUdp::ICMPErrorL( CSipConnectionMgr::TICMPError aICMPError, + const TInetAddr& aSourceAddr ) + { + CResponseHandler* listItem = 0; + iListIter.SetToFirst(); + while ( ( listItem = iListIter++ ) != 0 ) + { + listItem->ICMPErrorL( aICMPError, aSourceAddr ); + } + } + +// ----------------------------------------------------------------------------- +// CTransportUdp::RemoveResHandler +// ----------------------------------------------------------------------------- +// +void CTransportUdp::RemoveResHandler( CResponseHandler* aHandler ) + { + if ( !iList.IsEmpty() ) + { + iList.Remove( *aHandler ); + delete aHandler; + __SIP_LOG( "CResHandler removed" ) + } + } + +// ----------------------------------------------------------------------------- +// CTransportUdp::ConnectionOpenL +// ----------------------------------------------------------------------------- +// +TBool CTransportUdp::ConnectionOpenL() + { + User::Leave( KErrNotSupported ); + return EFalse; + } + +// ----------------------------------------------------------------------------- +// CTransportUdp::DisconnectedL +// ----------------------------------------------------------------------------- +// +TBool CTransportUdp::DisconnectedL() + { + return EFalse; + } + +// ----------------------------------------------------------------------------- +// CTransportUdp::GetSocketContainerL +// ----------------------------------------------------------------------------- +// +CSocketContainer& CTransportUdp::GetSocketContainerL( + const TInetAddr& aRemoteAddr ) + { + CSocketContainer* socketContainer = + SocketContainer( CSender::IpAddrType( aRemoteAddr ) ); + __ASSERT_ALWAYS( socketContainer, User::Leave( KErrNotFound ) ); + return *socketContainer; + } + +// ----------------------------------------------------------------------------- +// CTransportUdp::InformSendingStatus +// ----------------------------------------------------------------------------- +// +void CTransportUdp::InformSendingStatus( const TInetAddr& /*aRemoteAddr*/ ) + { + __SIP_INT_LOG2( "CTransportUdp::InformSendingStatus (socket IPv4,sending)", + iIPv4Socket.SubSessionHandle(), iIsSending ) + + __SIP_INT_LOG2( "CTransportUdp::InformSendingStatus (socket IPv6,sending)", + iIPv6Socket.SubSessionHandle(), iIsSending ) + + iNATTraversal.SocketIdle( !iIsSending, iIPv4Socket ); + iNATTraversal.SocketIdle( !iIsSending, iIPv6Socket ); + } + +// ----------------------------------------------------------------------------- +// CTransportUdp::Sender +// ----------------------------------------------------------------------------- +// +CSender* CTransportUdp::Sender( const TSIPTransportParams& aParams, + TUint aProtocol, + const TInetAddr& /*aRemoteAddr*/) + { + if ( aProtocol == Protocol() && Match( aParams ) ) + { + return iSender; + } + return 0; + } + +// ----------------------------------------------------------------------------- +// CTransportUdp::Remove +// ----------------------------------------------------------------------------- +// +TBool CTransportUdp::Remove( TUint32 aTransportId ) + { + TInt index = iTransportUsers.Find( aTransportId ); + if ( index != KErrNotFound ) + { + iTransportUsers.Remove( index ); + iTransportUsers.Compress(); + } + + // If no more transport users left and this is "protected" transport, + // the whole transport can be removed + return ( iTransportUsers.Count() == 0 && IsReservedTransport() ); + } + +// ----------------------------------------------------------------------------- +// CTransportUdp::AddUserL +// ----------------------------------------------------------------------------- +// +TBool CTransportUdp::AddUserL( + const TSIPTransportParams& aParams, + TUint aReceivePort ) + { + __ASSERT_ALWAYS( aReceivePort == iSourcePort, User::Leave( KErrArgument ) ); + + // Don't allow duplicate entries + User::LeaveIfError( iTransportUsers.InsertInOrder( aParams.TransportId() ) ); + + return ETrue; + } + +// ----------------------------------------------------------------------------- +// CTransportUdp::AcquireUdpSocket +// ----------------------------------------------------------------------------- +// +RSocket* CTransportUdp::AcquireUdpSocket( + MSocketUsagePermissionObserver* aObserver, + const TInetAddr& aRemoteAddr, + TBool& aPermissionToUse ) + { + aPermissionToUse = EFalse; + + // If observer is not provided, caller cannot use the socket + if ( aObserver ) + { + // If sender is active, we cannot give permission until the + // send is complete. + aPermissionToUse = !iSender->IsActive(); + + // When we give permission for the caller to use the socket, + // sender cannot send until UdpSocketReleased is called. + iSender->SetSendPermission( !aPermissionToUse ); + + iSocketUsagePermissionObserver = aObserver; + } + + RSocket* socket = NULL; + if ( aRemoteAddr.Address() && iIPv4SocketContainer ) + { + socket = &iIPv4Socket; + } + else + { + socket = &iIPv6Socket; + } + + return socket; + } + +// ----------------------------------------------------------------------------- +// CTransportUdp::UdpSocketReleased +// ----------------------------------------------------------------------------- +// +void CTransportUdp::UdpSocketReleased( + MSocketUsagePermissionObserver* aObserver, + RSocket& aSocket ) + { + if ( aObserver && + ( iIPv4Socket.SubSessionHandle() == aSocket.SubSessionHandle() || + iIPv6Socket.SubSessionHandle() == aSocket.SubSessionHandle() ) ) + { + iSocketUsagePermissionObserver = 0; + iSender->SetSendPermission( ETrue ); + TRAP_IGNORE( iSender->SendNextL() ) + } + } + +// ----------------------------------------------------------------------------- +// CTransportUdp::Remove +// ----------------------------------------------------------------------------- +// +TInt CTransportUdp::Remove() + { + return iTransportOwner->RemoveTransport( this ); + } + +// ----------------------------------------------------------------------------- +// CTransportUdp::IapId +// ----------------------------------------------------------------------------- +// +TUint32 CTransportUdp::IapId() + { + return iTransportOwner->IapId(); + } + +// ----------------------------------------------------------------------------- +// CTransportUdp::Sending +// ----------------------------------------------------------------------------- +// +void CTransportUdp::Sending( TBool aIsSending ) + { + __SIP_INT_LOG2( "CTransportUdp::Sending (socket IPv4,sending)", + iIPv4Socket.SubSessionHandle(), iIsSending ) + + __SIP_INT_LOG2( "CTransportUdp::Sending (socket IPv6,sending)", + iIPv6Socket.SubSessionHandle(), iIsSending ) + + iIsSending = aIsSending; + + if ( iSocketUsagePermissionObserver ) + { + iSocketUsagePermissionObserver->UsagePermissionChanged( iIPv4Socket, + !iIsSending ); + iSocketUsagePermissionObserver->UsagePermissionChanged( iIPv6Socket, + !iIsSending ); + } + + iNATTraversal.SocketIdle( !iIsSending, iIPv4Socket ); + iNATTraversal.SocketIdle( !iIsSending, iIPv6Socket ); + } + +// ----------------------------------------------------------------------------- +// CTransportUdp::ReRouteL +// ----------------------------------------------------------------------------- +// +void CTransportUdp::ReRouteL( TUint aProtocol, + COutgoingData* aData ) + { + iTransportOwner->ReRouteL( aProtocol, aData ); + } + +// ----------------------------------------------------------------------------- +// CTransportUdp::ReceivedDataL +// ----------------------------------------------------------------------------- +// +void CTransportUdp::ReceivedDataL( HBufC8* aData, + const TInetAddr& aRemoteAddr, + TBool aCompressed ) + { + RecvL( aData, aRemoteAddr, aCompressed ); + } + +// ----------------------------------------------------------------------------- +// CTransportUdp::SigCompHandler +// ----------------------------------------------------------------------------- +// +MSigCompController* CTransportUdp::SigCompHandler() + { + return SigCompressionHandler(); + } +// ----------------------------------------------------------------------------- +// CTransportUdp::RefreshSocketContainerL +// ----------------------------------------------------------------------------- +// +void CTransportUdp::RefreshSocketContainerL( TUint aFamily ) + { + if ( aFamily == KAfInet && !iIPv4SocketContainer ) + { + iIPv4SocketContainer = CreateSocketContainerL( KAfInet, iIPv4Socket ); + if ( iIPv4SocketContainer ) + { + iIPv4Receiver = CReceiver::NewL( *this, KAfInet ); + iIPv4Receiver->Listen(); + } + } + if ( aFamily == KAfInet6 && !iIPv6SocketContainer ) + { + iIPv6SocketContainer = CreateSocketContainerL( KAfInet6, iIPv6Socket ); + if ( iIPv6SocketContainer ) + { + iIPv6Receiver = CReceiver::NewL( *this, KAfInet6 ); + iIPv6Receiver->Listen(); + } + } + } +// ----------------------------------------------------------------------------- +// CTransportUdp::CreateSocketContainerL +// ----------------------------------------------------------------------------- +// +CSocketContainer* CTransportUdp::CreateSocketContainerL( + TUint aFamily, + RSocket& aSocket ) + { + CSocketContainer* socketContainer( NULL ); + TInetAddr addr; + if ( iTransportOwner->GetLocalIPAddr( aFamily, addr ) ) + { + User::LeaveIfError( + aSocket.Open( *iSocketServ, KAfInet, KSockDatagram, + KProtocolInetUdp, *iConnection ) ); + socketContainer = CSocketContainer::NewLC( aSocket ); + aSocket.SetOpt( KSoReuseAddr, KSolInetIp, 1 ); + addr.SetPort( iSourcePort ); + addr.SetFamily( aFamily ); + TInt err = aSocket.Bind( addr ); + if ( err == KErrInUse ) + { + User::Leave( KErrSIPTransportFailure ); + } + else + { + User::LeaveIfError( err ); + } + CleanupStack::Pop( socketContainer ); + } + return socketContainer; + }