From aacd52f00f3fc0e466fbd56da3688607cd81377c Mon Sep 17 00:00:00 2001 From: Basilisk-Dev Date: Sat, 20 Aug 2022 22:08:28 -0400 Subject: Issue #1991 - backport Mozilla bug 1266667 --- dom/network/PTCPSocket.ipdl | 3 +- dom/network/TCPSocketChild.cpp | 5 ++-- dom/network/TCPSocketChild.h | 2 +- dom/network/TCPSocketParent.cpp | 5 ++++ dom/network/TCPSocketParent.h | 1 + .../src/peerconnection/PeerConnectionImpl.cpp | 15 +++++++++- .../src/peerconnection/PeerConnectionImpl.h | 1 + .../src/peerconnection/PeerConnectionMedia.cpp | 11 ++++++- .../src/peerconnection/PeerConnectionMedia.h | 3 +- netwerk/base/nsISocketTransport.idl | 5 ++++ netwerk/base/nsSocketTransport2.cpp | 34 ++++++++++++++++++++++ netwerk/base/nsSocketTransport2.h | 1 + netwerk/protocol/http/TunnelUtils.cpp | 6 ++++ 13 files changed, 85 insertions(+), 7 deletions(-) diff --git a/dom/network/PTCPSocket.ipdl b/dom/network/PTCPSocket.ipdl index aa7c51e45f..ea00856029 100644 --- a/dom/network/PTCPSocket.ipdl +++ b/dom/network/PTCPSocket.ipdl @@ -44,7 +44,8 @@ parent: // address specified in |localAddr| and |localPort|. async OpenBind(nsCString host, uint16_t port, nsCString localAddr, uint16_t localPort, - bool useSSL, bool aUseArrayBuffers, nsCString aFilter); + bool useSSL, bool reuseAddrPort, + bool aUseArrayBuffers, nsCString aFilter); // When child's send() is called, this message requrests parent to send // data and update it's trackingNumber. diff --git a/dom/network/TCPSocketChild.cpp b/dom/network/TCPSocketChild.cpp index 9e1dce2769..b2b8db78a3 100644 --- a/dom/network/TCPSocketChild.cpp +++ b/dom/network/TCPSocketChild.cpp @@ -108,7 +108,7 @@ void TCPSocketChild::SendWindowlessOpenBind(nsITCPSocketCallback* aSocket, const nsACString& aRemoteHost, uint16_t aRemotePort, const nsACString& aLocalHost, uint16_t aLocalPort, - bool aUseSSL) + bool aUseSSL, bool aReuseAddrPort) { mSocket = aSocket; AddIPDLReference(); @@ -117,7 +117,8 @@ TCPSocketChild::SendWindowlessOpenBind(nsITCPSocketCallback* aSocket, aRemotePort); PTCPSocketChild::SendOpenBind(nsCString(aRemoteHost), aRemotePort, nsCString(aLocalHost), aLocalPort, - aUseSSL, true, mFilterName); + aUseSSL, aReuseAddrPort, + true, mFilterName); } void diff --git a/dom/network/TCPSocketChild.h b/dom/network/TCPSocketChild.h index 7e9b59e8b5..46e9b0a90f 100644 --- a/dom/network/TCPSocketChild.h +++ b/dom/network/TCPSocketChild.h @@ -55,7 +55,7 @@ public: void SendWindowlessOpenBind(nsITCPSocketCallback* aSocket, const nsACString& aRemoteHost, uint16_t aRemotePort, const nsACString& aLocalHost, uint16_t aLocalPort, - bool aUseSSL); + bool aUseSSL, bool aUseRealtimeOptions); NS_IMETHOD SendSendArray(nsTArray& aArray, uint32_t aTrackingNumber); void SendSend(const nsACString& aData, uint32_t aTrackingNumber); diff --git a/dom/network/TCPSocketParent.cpp b/dom/network/TCPSocketParent.cpp index 27d4d057e7..96eab44510 100644 --- a/dom/network/TCPSocketParent.cpp +++ b/dom/network/TCPSocketParent.cpp @@ -149,6 +149,7 @@ TCPSocketParent::RecvOpenBind(const nsCString& aRemoteHost, const nsCString& aLocalAddr, const uint16_t& aLocalPort, const bool& aUseSSL, + const bool& aReuseAddrPort, const bool& aUseArrayBuffers, const nsCString& aFilter) { @@ -184,6 +185,10 @@ TCPSocketParent::RecvOpenBind(const nsCString& aRemoteHost, return true; } + // in most cases aReuseAddrPort is false, but ICE TCP needs + // sockets options set that allow addr/port reuse + socketTransport->SetReuseAddrPort(aReuseAddrPort); + PRNetAddr prAddr; if (PR_SUCCESS != PR_InitializeNetAddr(PR_IpAddrAny, aLocalPort, &prAddr)) { FireInteralError(this, __LINE__); diff --git a/dom/network/TCPSocketParent.h b/dom/network/TCPSocketParent.h index 07112f1e2d..e0f987b17f 100644 --- a/dom/network/TCPSocketParent.h +++ b/dom/network/TCPSocketParent.h @@ -54,6 +54,7 @@ public: const nsCString& aLocalAddr, const uint16_t& aLocalPort, const bool& aUseSSL, + const bool& aReuseAddrPort, const bool& aUseArrayBuffers, const nsCString& aFilter) override; diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp index 7f3bb90d44..ad87fa1f91 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp @@ -335,6 +335,7 @@ PeerConnectionImpl::PeerConnectionImpl(const GlobalObject* aGlobal) , mSTSThread(nullptr) , mAllowIceLoopback(false) , mAllowIceLinkLocal(false) + , mForceIceTcp(false) , mMedia(nullptr) , mUuidGen(MakeUnique()) , mNumAudioStreams(0) @@ -365,6 +366,8 @@ PeerConnectionImpl::PeerConnectionImpl(const GlobalObject* aGlobal) "media.peerconnection.ice.loopback", false); mAllowIceLinkLocal = Preferences::GetBool( "media.peerconnection.ice.link_local", false); + mForceIceTcp = Preferences::GetBool( + "media.peerconnection.ice.force_ice_tcp", false); #endif memset(mMaxReceiving, 0, sizeof(mMaxReceiving)); memset(mMaxSending, 0, sizeof(mMaxSending)); @@ -2260,6 +2263,11 @@ NS_IMETHODIMP PeerConnectionImpl::AddIceCandidate(const char* aCandidate, const char* aMid, unsigned short aLevel) { PC_AUTO_ENTER_API_CALL(true); + if (mForceIceTcp && std::string::npos != std::string(aCandidate).find(" UDP ")) { + CSFLogError(logTag, "Blocking remote UDP candidate: %s", aCandidate); + return NS_OK; + } + JSErrorResult rv; RefPtr pco = do_QueryObjectReferent(mPCObserver); if (!pco) { @@ -3111,7 +3119,7 @@ PeerConnectionImpl::SetSignalingState_m(PCImplSignalingState aSignalingState, mNegotiationNeeded = false; // If we're rolling back a local offer, we might need to remove some // transports, but nothing further needs to be done. - mMedia->ActivateOrRemoveTransports(*mJsepSession); + mMedia->ActivateOrRemoveTransports(*mJsepSession, mForceIceTcp); if (!rollback) { mMedia->UpdateMediaPipelines(*mJsepSession); InitializeDataChannel(); @@ -3273,6 +3281,11 @@ PeerConnectionImpl::CandidateReady(const std::string& candidate, uint16_t level) { PC_AUTO_ENTER_API_CALL_VOID_RETURN(false); + if (mForceIceTcp && std::string::npos != candidate.find(" UDP ")) { + CSFLogError(logTag, "Blocking local UDP candidate: %s", candidate.c_str()); + return; + } + std::string mid; bool skipped = false; nsresult res = mJsepSession->AddLocalIceCandidate(candidate, diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h index 7b53ea1160..098b34249a 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h @@ -803,6 +803,7 @@ private: bool mAllowIceLoopback; bool mAllowIceLinkLocal; + bool mForceIceTcp; RefPtr mMedia; // The JSEP negotiation session. diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp index 0d388a8f49..0306b57904 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp @@ -457,7 +457,8 @@ PeerConnectionMedia::EnsureTransport_s(size_t aLevel, size_t aComponentCount) } void -PeerConnectionMedia::ActivateOrRemoveTransports(const JsepSession& aSession) +PeerConnectionMedia::ActivateOrRemoveTransports(const JsepSession& aSession, + const bool forceIceTcp) { auto transports = aSession.GetTransports(); for (size_t i = 0; i < transports.size(); ++i) { @@ -480,6 +481,14 @@ PeerConnectionMedia::ActivateOrRemoveTransports(const JsepSession& aSession) RemoveTransportFlow(i, true); } + if (forceIceTcp) { + candidates.erase(std::remove_if(candidates.begin(), + candidates.end(), + [](const std::string & s) { + return s.find(" UDP "); }), + candidates.end()); + } + RUN_ON_THREAD( GetSTSThread(), WrapRunnable(RefPtr(this), diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h index c0001a5e54..8908e51546 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h @@ -270,7 +270,8 @@ class PeerConnectionMedia : public sigslot::has_slots<> { // Activate or remove ICE transports at the conclusion of offer/answer, // or when rollback occurs. - void ActivateOrRemoveTransports(const JsepSession& aSession); + void ActivateOrRemoveTransports(const JsepSession& aSession, + const bool forceIceTcp); // Start ICE checks. void StartIceChecks(const JsepSession& session); diff --git a/netwerk/base/nsISocketTransport.idl b/netwerk/base/nsISocketTransport.idl index 9b5bc23fb7..3525aad5d9 100644 --- a/netwerk/base/nsISocketTransport.idl +++ b/netwerk/base/nsISocketTransport.idl @@ -129,6 +129,11 @@ interface nsISocketTransport : nsITransport unsigned long getTimeout(in unsigned long aType); void setTimeout(in unsigned long aType, in unsigned long aValue); + /** + * True to set addr and port reuse socket options. + */ + void setReuseAddrPort(in bool reuseAddrPort); + /** * Values for the aType parameter passed to get/setTimeout. */ diff --git a/netwerk/base/nsSocketTransport2.cpp b/netwerk/base/nsSocketTransport2.cpp index ff5fc3070d..ab20737443 100644 --- a/netwerk/base/nsSocketTransport2.cpp +++ b/netwerk/base/nsSocketTransport2.cpp @@ -737,6 +737,7 @@ nsSocketTransport::nsSocketTransport() , mProxyTransparentResolvesHost(false) , mHttpsProxy(false) , mConnectionFlags(0) + , mReuseAddrPort(false) , mState(STATE_CLOSED) , mAttached(false) , mInputClosed(true) @@ -1354,6 +1355,32 @@ nsSocketTransport::InitiateSocket() status = PR_SetSocketOption(fd, &opt); NS_ASSERTION(status == PR_SUCCESS, "unable to make socket non-blocking"); + if (mReuseAddrPort) { + SOCKET_LOG((" Setting port/addr reuse socket options\n")); + + // Set ReuseAddr for TCP sockets to enable having several + // sockets bound to same local IP and port + PRSocketOptionData opt_reuseaddr; + opt_reuseaddr.option = PR_SockOpt_Reuseaddr; + opt_reuseaddr.value.reuse_addr = PR_TRUE; + status = PR_SetSocketOption(fd, &opt_reuseaddr); + if (status != PR_SUCCESS) { + SOCKET_LOG((" Couldn't set reuse addr socket option: %d\n", + status)); + } + + // And also set ReusePort for platforms supporting this socket option + PRSocketOptionData opt_reuseport; + opt_reuseport.option = PR_SockOpt_Reuseport; + opt_reuseport.value.reuse_port = PR_TRUE; + status = PR_SetSocketOption(fd, &opt_reuseport); + if (status != PR_SUCCESS + && PR_GetError() != PR_OPERATION_NOT_SUPPORTED_ERROR) { + SOCKET_LOG((" Couldn't set reuse port socket option: %d\n", + status)); + } + } + // disable the nagle algorithm - if we rely on it to coalesce writes into // full packets the final packet of a multi segment POST/PUT or pipeline // sequence is delayed a full rtt @@ -2468,6 +2495,13 @@ nsSocketTransport::SetTimeout(uint32_t type, uint32_t value) return NS_OK; } +NS_IMETHODIMP +nsSocketTransport::SetReuseAddrPort(bool reuseAddrPort) +{ + mReuseAddrPort = reuseAddrPort; + return NS_OK; +} + NS_IMETHODIMP nsSocketTransport::SetQoSBits(uint8_t aQoSBits) { diff --git a/netwerk/base/nsSocketTransport2.h b/netwerk/base/nsSocketTransport2.h index 89b75efa57..a61e432b48 100644 --- a/netwerk/base/nsSocketTransport2.h +++ b/netwerk/base/nsSocketTransport2.h @@ -295,6 +295,7 @@ private: bool mProxyTransparentResolvesHost; bool mHttpsProxy; uint32_t mConnectionFlags; + bool mReuseAddrPort; // The origin attributes are used to create sockets. The first party domain // will eventually be used to isolate OCSP cache and is only non-empty when diff --git a/netwerk/protocol/http/TunnelUtils.cpp b/netwerk/protocol/http/TunnelUtils.cpp index eeaf57f55c..01075d2c0c 100644 --- a/netwerk/protocol/http/TunnelUtils.cpp +++ b/netwerk/protocol/http/TunnelUtils.cpp @@ -1685,6 +1685,12 @@ SocketTransportShim::SetTimeout(uint32_t aType, uint32_t aValue) return mWrapped->SetTimeout(aType, aValue); } +NS_IMETHODIMP +SocketTransportShim::SetReuseAddrPort(bool aReuseAddrPort) +{ + return mWrapped->SetReuseAddrPort(aReuseAddrPort); +} + NS_IMETHODIMP SocketTransportShim::GetQoSBits(uint8_t *aQoSBits) { -- cgit v1.2.3