Issue #1991 - backport Mozilla bug 1266667

This commit is contained in:
Basilisk-Dev 2022-08-20 22:08:28 -04:00 • committed by roytam1
commit b4c5ebf00a
13 changed files with 85 additions and 7 deletions

View file

@ -44,7 +44,8 @@ parent:
// address specified in |localAddr| and |localPort|. // address specified in |localAddr| and |localPort|.
async OpenBind(nsCString host, uint16_t port, async OpenBind(nsCString host, uint16_t port,
nsCString localAddr, uint16_t localPort, 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 // When child's send() is called, this message requrests parent to send
// data and update it's trackingNumber. // data and update it's trackingNumber.

View file

@ -108,7 +108,7 @@ void
TCPSocketChild::SendWindowlessOpenBind(nsITCPSocketCallback* aSocket, TCPSocketChild::SendWindowlessOpenBind(nsITCPSocketCallback* aSocket,
const nsACString& aRemoteHost, uint16_t aRemotePort, const nsACString& aRemoteHost, uint16_t aRemotePort,
const nsACString& aLocalHost, uint16_t aLocalPort, const nsACString& aLocalHost, uint16_t aLocalPort,
bool aUseSSL) bool aUseSSL, bool aReuseAddrPort)
{ {
mSocket = aSocket; mSocket = aSocket;
AddIPDLReference(); AddIPDLReference();
@ -117,7 +117,8 @@ TCPSocketChild::SendWindowlessOpenBind(nsITCPSocketCallback* aSocket,
aRemotePort); aRemotePort);
PTCPSocketChild::SendOpenBind(nsCString(aRemoteHost), aRemotePort, PTCPSocketChild::SendOpenBind(nsCString(aRemoteHost), aRemotePort,
nsCString(aLocalHost), aLocalPort, nsCString(aLocalHost), aLocalPort,
aUseSSL, true, mFilterName); aUseSSL, aReuseAddrPort,
true, mFilterName);
} }
void void

View file

@ -55,7 +55,7 @@ public:
void SendWindowlessOpenBind(nsITCPSocketCallback* aSocket, void SendWindowlessOpenBind(nsITCPSocketCallback* aSocket,
const nsACString& aRemoteHost, uint16_t aRemotePort, const nsACString& aRemoteHost, uint16_t aRemotePort,
const nsACString& aLocalHost, uint16_t aLocalPort, const nsACString& aLocalHost, uint16_t aLocalPort,
bool aUseSSL); bool aUseSSL, bool aUseRealtimeOptions);
NS_IMETHOD SendSendArray(nsTArray<uint8_t>& aArray, NS_IMETHOD SendSendArray(nsTArray<uint8_t>& aArray,
uint32_t aTrackingNumber); uint32_t aTrackingNumber);
void SendSend(const nsACString& aData, uint32_t aTrackingNumber); void SendSend(const nsACString& aData, uint32_t aTrackingNumber);

View file

@ -149,6 +149,7 @@ TCPSocketParent::RecvOpenBind(const nsCString& aRemoteHost,
const nsCString& aLocalAddr, const nsCString& aLocalAddr,
const uint16_t& aLocalPort, const uint16_t& aLocalPort,
const bool& aUseSSL, const bool& aUseSSL,
const bool& aReuseAddrPort,
const bool& aUseArrayBuffers, const bool& aUseArrayBuffers,
const nsCString& aFilter) const nsCString& aFilter)
{ {
@ -184,6 +185,10 @@ TCPSocketParent::RecvOpenBind(const nsCString& aRemoteHost,
return true; 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; PRNetAddr prAddr;
if (PR_SUCCESS != PR_InitializeNetAddr(PR_IpAddrAny, aLocalPort, &prAddr)) { if (PR_SUCCESS != PR_InitializeNetAddr(PR_IpAddrAny, aLocalPort, &prAddr)) {
FireInteralError(this, __LINE__); FireInteralError(this, __LINE__);

View file

@ -54,6 +54,7 @@ public:
const nsCString& aLocalAddr, const nsCString& aLocalAddr,
const uint16_t& aLocalPort, const uint16_t& aLocalPort,
const bool& aUseSSL, const bool& aUseSSL,
const bool& aReuseAddrPort,
const bool& aUseArrayBuffers, const bool& aUseArrayBuffers,
const nsCString& aFilter) override; const nsCString& aFilter) override;

View file

@ -335,6 +335,7 @@ PeerConnectionImpl::PeerConnectionImpl(const GlobalObject* aGlobal)
, mSTSThread(nullptr) , mSTSThread(nullptr)
, mAllowIceLoopback(false) , mAllowIceLoopback(false)
, mAllowIceLinkLocal(false) , mAllowIceLinkLocal(false)
, mForceIceTcp(false)
, mMedia(nullptr) , mMedia(nullptr)
, mUuidGen(MakeUnique<PCUuidGenerator>()) , mUuidGen(MakeUnique<PCUuidGenerator>())
, mNumAudioStreams(0) , mNumAudioStreams(0)
@ -365,6 +366,8 @@ PeerConnectionImpl::PeerConnectionImpl(const GlobalObject* aGlobal)
"media.peerconnection.ice.loopback", false); "media.peerconnection.ice.loopback", false);
mAllowIceLinkLocal = Preferences::GetBool( mAllowIceLinkLocal = Preferences::GetBool(
"media.peerconnection.ice.link_local", false); "media.peerconnection.ice.link_local", false);
mForceIceTcp = Preferences::GetBool(
"media.peerconnection.ice.force_ice_tcp", false);
#endif #endif
memset(mMaxReceiving, 0, sizeof(mMaxReceiving)); memset(mMaxReceiving, 0, sizeof(mMaxReceiving));
memset(mMaxSending, 0, sizeof(mMaxSending)); memset(mMaxSending, 0, sizeof(mMaxSending));
@ -2260,6 +2263,11 @@ NS_IMETHODIMP
PeerConnectionImpl::AddIceCandidate(const char* aCandidate, const char* aMid, unsigned short aLevel) { PeerConnectionImpl::AddIceCandidate(const char* aCandidate, const char* aMid, unsigned short aLevel) {
PC_AUTO_ENTER_API_CALL(true); 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; JSErrorResult rv;
RefPtr<PeerConnectionObserver> pco = do_QueryObjectReferent(mPCObserver); RefPtr<PeerConnectionObserver> pco = do_QueryObjectReferent(mPCObserver);
if (!pco) { if (!pco) {
@ -3111,7 +3119,7 @@ PeerConnectionImpl::SetSignalingState_m(PCImplSignalingState aSignalingState,
mNegotiationNeeded = false; mNegotiationNeeded = false;
// If we're rolling back a local offer, we might need to remove some // If we're rolling back a local offer, we might need to remove some
// transports, but nothing further needs to be done. // transports, but nothing further needs to be done.
mMedia->ActivateOrRemoveTransports(*mJsepSession); mMedia->ActivateOrRemoveTransports(*mJsepSession, mForceIceTcp);
if (!rollback) { if (!rollback) {
mMedia->UpdateMediaPipelines(*mJsepSession); mMedia->UpdateMediaPipelines(*mJsepSession);
InitializeDataChannel(); InitializeDataChannel();
@ -3273,6 +3281,11 @@ PeerConnectionImpl::CandidateReady(const std::string& candidate,
uint16_t level) { uint16_t level) {
PC_AUTO_ENTER_API_CALL_VOID_RETURN(false); 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; std::string mid;
bool skipped = false; bool skipped = false;
nsresult res = mJsepSession->AddLocalIceCandidate(candidate, nsresult res = mJsepSession->AddLocalIceCandidate(candidate,

View file

@ -803,6 +803,7 @@ private:
bool mAllowIceLoopback; bool mAllowIceLoopback;
bool mAllowIceLinkLocal; bool mAllowIceLinkLocal;
bool mForceIceTcp;
RefPtr<PeerConnectionMedia> mMedia; RefPtr<PeerConnectionMedia> mMedia;
// The JSEP negotiation session. // The JSEP negotiation session.

View file

@ -457,7 +457,8 @@ PeerConnectionMedia::EnsureTransport_s(size_t aLevel, size_t aComponentCount)
} }
void void
PeerConnectionMedia::ActivateOrRemoveTransports(const JsepSession& aSession) PeerConnectionMedia::ActivateOrRemoveTransports(const JsepSession& aSession,
const bool forceIceTcp)
{ {
auto transports = aSession.GetTransports(); auto transports = aSession.GetTransports();
for (size_t i = 0; i < transports.size(); ++i) { for (size_t i = 0; i < transports.size(); ++i) {
@ -480,6 +481,14 @@ PeerConnectionMedia::ActivateOrRemoveTransports(const JsepSession& aSession)
RemoveTransportFlow(i, true); 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( RUN_ON_THREAD(
GetSTSThread(), GetSTSThread(),
WrapRunnable(RefPtr<PeerConnectionMedia>(this), WrapRunnable(RefPtr<PeerConnectionMedia>(this),

View file

@ -270,7 +270,8 @@ class PeerConnectionMedia : public sigslot::has_slots<> {
// Activate or remove ICE transports at the conclusion of offer/answer, // Activate or remove ICE transports at the conclusion of offer/answer,
// or when rollback occurs. // or when rollback occurs.
void ActivateOrRemoveTransports(const JsepSession& aSession); void ActivateOrRemoveTransports(const JsepSession& aSession,
const bool forceIceTcp);
// Start ICE checks. // Start ICE checks.
void StartIceChecks(const JsepSession& session); void StartIceChecks(const JsepSession& session);

View file

@ -129,6 +129,11 @@ interface nsISocketTransport : nsITransport
unsigned long getTimeout(in unsigned long aType); unsigned long getTimeout(in unsigned long aType);
void setTimeout(in unsigned long aType, in unsigned long aValue); 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. * Values for the aType parameter passed to get/setTimeout.
*/ */

View file

@ -738,6 +738,7 @@ nsSocketTransport::nsSocketTransport()
, mProxyTransparentResolvesHost(false) , mProxyTransparentResolvesHost(false)
, mHttpsProxy(false) , mHttpsProxy(false)
, mConnectionFlags(0) , mConnectionFlags(0)
, mReuseAddrPort(false)
, mState(STATE_CLOSED) , mState(STATE_CLOSED)
, mAttached(false) , mAttached(false)
, mInputClosed(true) , mInputClosed(true)
@ -1355,6 +1356,32 @@ nsSocketTransport::InitiateSocket()
status = PR_SetSocketOption(fd, &opt); status = PR_SetSocketOption(fd, &opt);
NS_ASSERTION(status == PR_SUCCESS, "unable to make socket non-blocking"); 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 // 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 // full packets the final packet of a multi segment POST/PUT or pipeline
// sequence is delayed a full rtt // sequence is delayed a full rtt
@ -2484,6 +2511,13 @@ nsSocketTransport::SetTimeout(uint32_t type, uint32_t value)
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
nsSocketTransport::SetReuseAddrPort(bool reuseAddrPort)
{
mReuseAddrPort = reuseAddrPort;
return NS_OK;
}
NS_IMETHODIMP NS_IMETHODIMP
nsSocketTransport::SetQoSBits(uint8_t aQoSBits) nsSocketTransport::SetQoSBits(uint8_t aQoSBits)
{ {

View file

@ -295,6 +295,7 @@ private:
bool mProxyTransparentResolvesHost; bool mProxyTransparentResolvesHost;
bool mHttpsProxy; bool mHttpsProxy;
uint32_t mConnectionFlags; uint32_t mConnectionFlags;
bool mReuseAddrPort;
// The origin attributes are used to create sockets. The first party domain // 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 // will eventually be used to isolate OCSP cache and is only non-empty when

View file

@ -1685,6 +1685,12 @@ SocketTransportShim::SetTimeout(uint32_t aType, uint32_t aValue)
return mWrapped->SetTimeout(aType, aValue); return mWrapped->SetTimeout(aType, aValue);
} }
NS_IMETHODIMP
SocketTransportShim::SetReuseAddrPort(bool aReuseAddrPort)
{
return mWrapped->SetReuseAddrPort(aReuseAddrPort);
}
NS_IMETHODIMP NS_IMETHODIMP
SocketTransportShim::GetQoSBits(uint8_t *aQoSBits) SocketTransportShim::GetQoSBits(uint8_t *aQoSBits)
{ {