--- a/dom/network/PTCPSocket.ipdl
+++ b/dom/network/PTCPSocket.ipdl
@@ -40,17 +40,18 @@ parent:
// is expanded to |useSSL| (from TCPOptions.useSecureTransport) and
// |binaryType| (from TCPOption.binaryType).
async Open(nsString host, uint16_t port, bool useSSL, bool useArrayBuffers);
// Ask parent to open a socket and bind the newly-opened socket to a local
// 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 useRealtimeOptions,
+ bool aUseArrayBuffers, nsCString aFilter);
// When child's send() is called, this message requrests parent to send
// data and update it's trackingNumber.
async Data(SendableData data, uint32_t trackingNumber);
// Forward calling to child's upgradeToSecure() method to parent.
async StartTLS();
--- a/dom/network/TCPSocketChild.cpp
+++ b/dom/network/TCPSocketChild.cpp
@@ -105,26 +105,28 @@ TCPSocketChild::SendOpen(nsITCPSocketCal
MOZ_ASSERT(mFilterName.IsEmpty()); // Currently nobody should use this
PTCPSocketChild::SendOpen(mHost, mPort, aUseSSL, aUseArrayBuffers);
}
void
TCPSocketChild::SendWindowlessOpenBind(nsITCPSocketCallback* aSocket,
const nsACString& aRemoteHost, uint16_t aRemotePort,
const nsACString& aLocalHost, uint16_t aLocalPort,
- bool aUseSSL)
+ bool aUseSSL,
+ bool aUseRealtimeOptions)
{
mSocket = aSocket;
AddIPDLReference();
gNeckoChild->SendPTCPSocketConstructor(this,
NS_ConvertUTF8toUTF16(aRemoteHost),
aRemotePort);
PTCPSocketChild::SendOpenBind(nsCString(aRemoteHost), aRemotePort,
nsCString(aLocalHost), aLocalPort,
- aUseSSL, true, mFilterName);
+ aUseSSL, aUseRealtimeOptions,
+ true, mFilterName);
}
void
TCPSocketChildBase::ReleaseIPDLReference()
{
MOZ_ASSERT(mIPCOpen);
mIPCOpen = false;
mSocket = nullptr;
--- a/dom/network/TCPSocketChild.h
+++ b/dom/network/TCPSocketChild.h
@@ -51,17 +51,18 @@ public:
TCPSocketChild(const nsAString& aHost, const uint16_t& aPort);
~TCPSocketChild();
void SendOpen(nsITCPSocketCallback* aSocket, bool aUseSSL, bool aUseArrayBuffers);
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<uint8_t>& aArray,
uint32_t aTrackingNumber);
void SendSend(const nsACString& aData, uint32_t aTrackingNumber);
nsresult SendSend(const ArrayBuffer& aData,
uint32_t aByteOffset,
uint32_t aByteLength,
uint32_t aTrackingNumber);
void SendSendArray(nsTArray<uint8_t>* arr,
--- a/dom/network/TCPSocketParent.cpp
+++ b/dom/network/TCPSocketParent.cpp
@@ -144,16 +144,17 @@ TCPSocketParent::RecvOpen(const nsString
}
bool
TCPSocketParent::RecvOpenBind(const nsCString& aRemoteHost,
const uint16_t& aRemotePort,
const nsCString& aLocalAddr,
const uint16_t& aLocalPort,
const bool& aUseSSL,
+ const bool& aUseRealtimeOptions,
const bool& aUseArrayBuffers,
const nsCString& aFilter)
{
if (net::UsingNeckoIPCSecurity() &&
!AssertAppProcessPermission(Manager()->Manager(), "tcp-socket")) {
FireInteralError(this, __LINE__);
return true;
}
@@ -170,16 +171,20 @@ TCPSocketParent::RecvOpenBind(const nsCS
rv = sts->CreateTransport(nullptr, 0,
aRemoteHost, aRemotePort,
nullptr, getter_AddRefs(socketTransport));
if (NS_FAILED(rv)) {
FireInteralError(this, __LINE__);
return true;
}
+ // in most cases aUseRealTimeOptions is false, but for e10s ICE TCP needs
+ // sockets options set that allow addr/port reuse
+ socketTransport->SetRealtimeOptions(aUseRealtimeOptions);
+
PRNetAddr prAddr;
if (PR_SUCCESS != PR_InitializeNetAddr(PR_IpAddrAny, aLocalPort, &prAddr)) {
FireInteralError(this, __LINE__);
return true;
}
if (PR_SUCCESS != PR_StringToNetAddr(aLocalAddr.BeginReading(), &prAddr)) {
FireInteralError(this, __LINE__);
return true;
--- a/dom/network/TCPSocketParent.h
+++ b/dom/network/TCPSocketParent.h
@@ -50,16 +50,17 @@ public:
virtual bool RecvOpen(const nsString& aHost, const uint16_t& aPort,
const bool& useSSL, const bool& aUseArrayBuffers) override;
virtual bool RecvOpenBind(const nsCString& aRemoteHost,
const uint16_t& aRemotePort,
const nsCString& aLocalAddr,
const uint16_t& aLocalPort,
const bool& aUseSSL,
+ const bool& aUseRealtimeOptions,
const bool& aUseArrayBuffers,
const nsCString& aFilter) override;
virtual bool RecvStartTLS() override;
virtual bool RecvSuspend() override;
virtual bool RecvResume() override;
virtual bool RecvClose() override;
virtual bool RecvData(const SendableData& aData,
--- a/media/mtransport/nr_socket_prsock.cpp
+++ b/media/mtransport/nr_socket_prsock.cpp
@@ -1963,17 +1963,18 @@ void NrTcpSocketIpc::connect_i(const nsA
socket_child_ = child;
// Bug 1285330: put filtering back in here
// XXX remove remote!
socket_child_->SendWindowlessOpenBind(this,
remote_addr, remote_port,
local_addr, local_port,
- /* use ssl */ false);
+ /* use ssl */ false,
+ /* use real time options */ true);
}
void NrTcpSocketIpc::write_i(nsAutoPtr<InfallibleTArray<uint8_t>> arr,
uint32_t tracking_number) {
ASSERT_ON_THREAD(io_thread_);
if (!socket_child_) {
return;
}
--- a/media/mtransport/nricectx.cpp
+++ b/media/mtransport/nricectx.cpp
@@ -834,32 +834,40 @@ abort:
nr_proxy_tunnel_config_destroy(&config);
if (_status) {
nr_socket_wrapper_factory_destroy(&wrapper);
return NS_ERROR_FAILURE;
}
return NS_OK;
}
-nsresult NrIceCtx::StartGathering(bool default_route_only, bool proxy_only) {
+nsresult NrIceCtx::StartGathering(bool default_route_only,
+ bool proxy_only,
+ bool block_udp_candidates) {
ASSERT_ON_THREAD(sts_target_);
SetGatheringState(ICE_CTX_GATHER_STARTED);
if (default_route_only) {
nr_ice_ctx_add_flags(ctx_, NR_ICE_CTX_FLAGS_ONLY_DEFAULT_ADDRS);
} else {
nr_ice_ctx_remove_flags(ctx_, NR_ICE_CTX_FLAGS_ONLY_DEFAULT_ADDRS);
}
if (proxy_only) {
nr_ice_ctx_add_flags(ctx_, NR_ICE_CTX_FLAGS_ONLY_PROXY);
} else {
nr_ice_ctx_remove_flags(ctx_, NR_ICE_CTX_FLAGS_ONLY_PROXY);
}
+ if (block_udp_candidates) {
+ nr_ice_ctx_add_flags(ctx_, NR_ICE_CTX_BLOCK_UDP_CANDIDATES);
+ } else {
+ nr_ice_ctx_remove_flags(ctx_, NR_ICE_CTX_BLOCK_UDP_CANDIDATES);
+ }
+
// This might start gathering for the first time, or again after
// renegotiation, or might do nothing at all if gathering has already
// finished.
int r = nr_ice_gather(ctx_, &NrIceCtx::gather_cb, this);
if (!r) {
SetGatheringState(ICE_CTX_GATHER_COMPLETE);
} else if (r != R_WOULDBLOCK) {
--- a/media/mtransport/nricectx.h
+++ b/media/mtransport/nricectx.h
@@ -304,17 +304,19 @@ class NrIceCtx {
// StartGathering.
nsresult SetResolver(nr_resolver *resolver);
// Provide the proxy address. Must be called before
// StartGathering.
nsresult SetProxyServer(const NrIceProxyServer& proxy_server);
// Start ICE gathering
- nsresult StartGathering(bool default_route_only, bool proxy_only);
+ nsresult StartGathering(bool default_route_only,
+ bool proxy_only,
+ bool block_udp_candidates = false);
// Start checking
nsresult StartChecks();
// Finalize the ICE negotiation. I.e., there will be no
// more forking.
nsresult Finalize();
--- a/media/mtransport/test/ice_unittest.cpp
+++ b/media/mtransport/test/ice_unittest.cpp
@@ -537,16 +537,17 @@ class IceTestPeer : public sigslot::has_
void Gather(bool default_route_only = false) {
nsresult res;
test_utils_->sts_target()->Dispatch(
WrapRunnableRet(&res,
ice_ctx_->ctx(),
&NrIceCtx::StartGathering,
default_route_only,
+ false,
false),
NS_DISPATCH_SYNC);
ASSERT_TRUE(NS_SUCCEEDED(res));
}
void UseNat() {
nat_->enabled_ = true;
--- a/media/mtransport/test/transport_unittests.cpp
+++ b/media/mtransport/test/transport_unittests.cpp
@@ -639,16 +639,17 @@ class TransportTestPeer : public sigslot
flow_->SignalStateChange.connect(this, &TransportTestPeer::StateChanged);
// Start gathering
test_utils_->sts_target()->Dispatch(
WrapRunnableRet(&res,
ice_ctx_->ctx(),
&NrIceCtx::StartGathering,
false,
+ false,
false),
NS_DISPATCH_SYNC);
ASSERT_TRUE(NS_SUCCEEDED(res));
}
void ConnectIce(TransportTestPeer *peer) {
peer_ = peer;
--- a/media/mtransport/third_party/nICEr/src/ice/ice_component.c
+++ b/media/mtransport/third_party/nICEr/src/ice/ice_component.c
@@ -634,18 +634,22 @@ int nr_ice_component_initialize(struct n
ABORT(R_INTERNAL);
lpwd=component->stream->pwd ? component->stream->pwd :ctx->pwd;
assert(lpwd);
if (!lpwd)
ABORT(R_INTERNAL);
INIT_DATA(pwd, (UCHAR *)lpwd, strlen(lpwd));
/* Initialize the UDP candidates */
- if (r=nr_ice_component_initialize_udp(ctx, component, addrs, addr_ct, lufrag, &pwd))
- r_log(LOG_ICE,LOG_INFO,"ICE(%s): failed to create UDP candidates with error %d",ctx->label,r);
+ if (ctx->flags & NR_ICE_CTX_BLOCK_UDP_CANDIDATES) {
+ r_log(LOG_ICE,LOG_INFO,"ICE(%s): blocking call to nr_ice_component_initialize_udp",ctx->label);
+ } else {
+ if (r=nr_ice_component_initialize_udp(ctx, component, addrs, addr_ct, lufrag, &pwd))
+ r_log(LOG_ICE,LOG_INFO,"ICE(%s): failed to create UDP candidates with error %d",ctx->label,r);
+ }
/* And the TCP candidates */
if (r=nr_ice_component_initialize_tcp(ctx, component, addrs, addr_ct, lufrag, &pwd))
r_log(LOG_ICE,LOG_INFO,"ICE(%s): failed to create TCP candidates with error %d",ctx->label,r);
/* count the candidates that will be initialized */
cand=TAILQ_FIRST(&component->candidates);
if(!cand){
r_log(LOG_ICE,LOG_ERR,"ICE(%s): couldn't create any valid candidates",ctx->label);
--- a/media/mtransport/third_party/nICEr/src/ice/ice_ctx.h
+++ b/media/mtransport/third_party/nICEr/src/ice/ice_ctx.h
@@ -161,16 +161,17 @@ int nr_ice_ctx_create_with_credentials(c
#define NR_ICE_CTX_FLAGS_OFFERER 1
#define NR_ICE_CTX_FLAGS_ANSWERER (1<<1)
#define NR_ICE_CTX_FLAGS_AGGRESSIVE_NOMINATION (1<<2)
#define NR_ICE_CTX_FLAGS_LITE (1<<3)
#define NR_ICE_CTX_FLAGS_RELAY_ONLY (1<<4)
#define NR_ICE_CTX_FLAGS_HIDE_HOST_CANDIDATES (1<<5)
#define NR_ICE_CTX_FLAGS_ONLY_DEFAULT_ADDRS (1<<6)
#define NR_ICE_CTX_FLAGS_ONLY_PROXY (1<<7)
+#define NR_ICE_CTX_BLOCK_UDP_CANDIDATES (1<<8)
void nr_ice_ctx_add_flags(nr_ice_ctx *ctx, UINT4 flags);
void nr_ice_ctx_remove_flags(nr_ice_ctx *ctx, UINT4 flags);
int nr_ice_ctx_destroy(nr_ice_ctx **ctxp);
int nr_ice_gather(nr_ice_ctx *ctx, NR_async_cb done_cb, void *cb_arg);
int nr_ice_add_candidate(nr_ice_ctx *ctx, nr_ice_candidate *cand);
void nr_ice_gather_finished_cb(NR_SOCKET s, int h, void *cb_arg);
int nr_ice_add_media_stream(nr_ice_ctx *ctx,char *label,int components, nr_ice_media_stream **streamp);
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
@@ -329,16 +329,17 @@ PeerConnectionImpl::PeerConnectionImpl(c
, mCertificate(nullptr)
#else
, mIdentity(nullptr)
#endif
, mPrivacyRequested(false)
, mSTSThread(nullptr)
, mAllowIceLoopback(false)
, mAllowIceLinkLocal(false)
+ , mBlockIceUdpCandidates(false)
, mMedia(nullptr)
, mUuidGen(MakeUnique<PCUuidGenerator>())
, mNumAudioStreams(0)
, mNumVideoStreams(0)
, mHaveConfiguredCodecs(false)
, mHaveDataStream(false)
, mAddCandidateErrorCount(0)
, mTrickle(true) // TODO(ekr@rtfm.com): Use pref
@@ -359,16 +360,18 @@ PeerConnectionImpl::PeerConnectionImpl(c
CSFLogInfo(logTag, "%s: PeerConnectionImpl constructor for %s",
__FUNCTION__, mHandle.c_str());
STAMP_TIMECARD(mTimeCard, "Constructor Completed");
#if !defined(MOZILLA_EXTERNAL_LINKAGE)
mAllowIceLoopback = Preferences::GetBool(
"media.peerconnection.ice.loopback", false);
mAllowIceLinkLocal = Preferences::GetBool(
"media.peerconnection.ice.link_local", false);
+ mBlockIceUdpCandidates = Preferences::GetBool(
+ "media.peerconnection.ice.block_udp_candidates", false);
#endif
memset(mMaxReceiving, 0, sizeof(mMaxReceiving));
memset(mMaxSending, 0, sizeof(mMaxSending));
}
PeerConnectionImpl::~PeerConnectionImpl()
{
if (mTimeCard) {
@@ -3319,16 +3322,21 @@ toDomIceGatheringState(NrIceCtx::Gatheri
MOZ_CRASH();
}
void
PeerConnectionImpl::CandidateReady(const std::string& candidate,
uint16_t level) {
PC_AUTO_ENTER_API_CALL_VOID_RETURN(false);
+ if (mBlockIceUdpCandidates && std::string::npos != candidate.find("UDP")) {
+ CSFLogError(logTag, "Block UDP candidate: %s", candidate.c_str());
+ return;
+ }
+
std::string mid;
bool skipped = false;
nsresult res = mJsepSession->AddLocalIceCandidate(candidate,
level,
&mid,
&skipped);
if (NS_FAILED(res)) {
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
@@ -806,16 +806,17 @@ private:
#if !defined(MOZILLA_EXTERNAL_LINKAGE)
// DataConnection that's used to get all the DataChannels
RefPtr<mozilla::DataChannelConnection> mDataConnection;
#endif
bool mAllowIceLoopback;
bool mAllowIceLinkLocal;
+ bool mBlockIceUdpCandidates;
RefPtr<PeerConnectionMedia> mMedia;
// The JSEP negotiation session.
mozilla::UniquePtr<PCUuidGenerator> mUuidGen;
mozilla::UniquePtr<mozilla::JsepSession> mJsepSession;
std::string mPreviousIceUfrag; // used during rollback of ice restart
std::string mPreviousIcePwd; // used during rollback of ice restart
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp
@@ -797,16 +797,29 @@ PeerConnectionMedia::GetPrefProxyOnly()
#if !defined(MOZILLA_EXTERNAL_LINKAGE)
return Preferences::GetBool("media.peerconnection.ice.proxy_only", false);
#else
return false;
#endif
}
+bool
+PeerConnectionMedia::GetPrefBlockUdpCandidates() const
+{
+ ASSERT_ON_THREAD(mMainThread); // will crash on STS thread
+
+#if !defined(MOZILLA_EXTERNAL_LINKAGE)
+ return Preferences::GetBool("media.peerconnection.ice.block_udp_candidates",
+ false);
+#else
+ return false;
+#endif
+}
+
void
PeerConnectionMedia::ConnectSignals(NrIceCtx *aCtx, NrIceCtx *aOldCtx)
{
aCtx->SignalGatheringStateChange.connect(
this,
&PeerConnectionMedia::IceGatheringStateChange_s);
aCtx->SignalConnectionStateChange.connect(
this,
@@ -895,36 +908,40 @@ PeerConnectionMedia::PerformOrEnqueueIce
void
PeerConnectionMedia::GatherIfReady() {
ASSERT_ON_THREAD(mMainThread);
nsCOMPtr<nsIRunnable> runnable(WrapRunnable(
RefPtr<PeerConnectionMedia>(this),
&PeerConnectionMedia::EnsureIceGathering_s,
GetPrefDefaultAddressOnly(),
- GetPrefProxyOnly()));
+ GetPrefProxyOnly(),
+ GetPrefBlockUdpCandidates()));
PerformOrEnqueueIceCtxOperation(runnable);
}
void
PeerConnectionMedia::EnsureIceGathering_s(bool aDefaultRouteOnly,
- bool aProxyOnly) {
+ bool aProxyOnly,
+ bool aBlockUdpCandidates) {
if (mProxyServer) {
mIceCtxHdlr->ctx()->SetProxyServer(*mProxyServer);
} else if (aProxyOnly) {
IceGatheringStateChange_s(mIceCtxHdlr->ctx().get(),
NrIceCtx::ICE_CTX_GATHER_COMPLETE);
return;
}
// Start gathering, but only if there are streams
for (size_t i = 0; i < mIceCtxHdlr->ctx()->GetStreamCount(); ++i) {
if (mIceCtxHdlr->ctx()->GetStream(i)) {
- mIceCtxHdlr->ctx()->StartGathering(aDefaultRouteOnly, aProxyOnly);
+ mIceCtxHdlr->ctx()->StartGathering(aDefaultRouteOnly,
+ aProxyOnly,
+ aBlockUdpCandidates);
return;
}
}
// If there are no streams, we're probably in a situation where we've rolled
// back while still waiting for our proxy configuration to come back. Make
// sure content knows that the rollback has stuck wrt gathering.
IceGatheringStateChange_s(mIceCtxHdlr->ctx().get(),
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h
@@ -467,26 +467,29 @@ class PeerConnectionMedia : public sigsl
const std::string& aUfrag,
const std::string& aPassword,
const std::vector<std::string>& aCandidateList);
void RemoveTransportsAtOrAfter_s(size_t aMLine);
void GatherIfReady();
void FlushIceCtxOperationQueueIfReady();
void PerformOrEnqueueIceCtxOperation(nsIRunnable* runnable);
- void EnsureIceGathering_s(bool aDefaultRouteOnly, bool aProxyOnly);
+ void EnsureIceGathering_s(bool aDefaultRouteOnly,
+ bool aProxyOnly,
+ bool aBlockUdpCandidates);
void StartIceChecks_s(bool aIsControlling,
bool aIsIceLite,
const std::vector<std::string>& aIceOptionsList);
void BeginIceRestart_s(RefPtr<NrIceCtx> new_ctx);
void FinalizeIceRestart_s();
void RollbackIceRestart_s();
bool GetPrefDefaultAddressOnly() const;
bool GetPrefProxyOnly() const;
+ bool GetPrefBlockUdpCandidates() const;
void ConnectSignals(NrIceCtx *aCtx, NrIceCtx *aOldCtx=nullptr);
// Process a trickle ICE candidate.
void AddIceCandidate_s(const std::string& aCandidate, const std::string& aMid,
uint32_t aMLine);
--- a/netwerk/base/nsISocketTransport.idl
+++ b/netwerk/base/nsISocketTransport.idl
@@ -114,16 +114,21 @@ interface nsISocketTransport : nsITransp
* Socket timeouts in seconds. To specify no timeout, pass UINT32_MAX
* as aValue to setTimeout. The implementation may truncate timeout values
* to a smaller range of values (e.g., 0 to 0xFFFF).
*/
unsigned long getTimeout(in unsigned long aType);
void setTimeout(in unsigned long aType, in unsigned long aValue);
/**
+ * True to setup realtime friendly options, namely addr and port reuse.
+ */
+ void setRealtimeOptions(in bool realtimeOptions);
+
+ /**
* Values for the aType parameter passed to get/setTimeout.
*/
const unsigned long TIMEOUT_CONNECT = 0;
const unsigned long TIMEOUT_READ_WRITE = 1;
/**
* nsITransportEventSink status codes.
*
--- a/netwerk/base/nsSocketTransport2.cpp
+++ b/netwerk/base/nsSocketTransport2.cpp
@@ -734,16 +734,17 @@ nsSocketTransport::nsSocketTransport()
, mTypeCount(0)
, mPort(0)
, mProxyPort(0)
, mOriginPort(0)
, mProxyTransparent(false)
, mProxyTransparentResolvesHost(false)
, mHttpsProxy(false)
, mConnectionFlags(0)
+ , mUseRealtimeOptions(false)
, mState(STATE_CLOSED)
, mAttached(false)
, mInputClosed(true)
, mOutputClosed(true)
, mResolving(false)
, mNetAddrIsSet(false)
, mSelfAddrIsSet(false)
, mNetAddrPreResolved(false)
@@ -1345,16 +1346,42 @@ nsSocketTransport::InitiateSocket()
// Make the socket non-blocking...
PRSocketOptionData opt;
opt.option = PR_SockOpt_Nonblocking;
opt.value.non_blocking = true;
status = PR_SetSocketOption(fd, &opt);
NS_ASSERTION(status == PR_SUCCESS, "unable to make socket non-blocking");
+ if (mUseRealtimeOptions) {
+ SOCKET_LOG((" setting realtime options (port/addr resuse)\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
opt.option = PR_SockOpt_NoDelay;
opt.value.no_delay = true;
PR_SetSocketOption(fd, &opt);
// if the network.tcp.sendbuffer preference is set, use it to size SO_SNDBUF
@@ -2503,16 +2530,23 @@ nsSocketTransport::SetTimeout(uint32_t t
NS_ENSURE_ARG_MAX(type, nsISocketTransport::TIMEOUT_READ_WRITE);
// truncate overly large timeout values.
mTimeouts[type] = (uint16_t) std::min<uint32_t>(value, UINT16_MAX);
PostEvent(MSG_TIMEOUT_CHANGED);
return NS_OK;
}
NS_IMETHODIMP
+nsSocketTransport::SetRealtimeOptions(bool realtimeOptions)
+{
+ mUseRealtimeOptions = realtimeOptions;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
nsSocketTransport::SetQoSBits(uint8_t aQoSBits)
{
// Don't do any checking here of bits. Why? Because as of RFC-4594
// several different Class Selector and Assured Forwarding values
// have been defined, but that isn't to say more won't be added later.
// In that case, any checking would be an impediment to interoperating
// with newer QoS definitions.
--- a/netwerk/base/nsSocketTransport2.h
+++ b/netwerk/base/nsSocketTransport2.h
@@ -297,16 +297,17 @@ private:
uint16_t mPort;
nsCOMPtr<nsIProxyInfo> mProxyInfo;
uint16_t mProxyPort;
uint16_t mOriginPort;
bool mProxyTransparent;
bool mProxyTransparentResolvesHost;
bool mHttpsProxy;
uint32_t mConnectionFlags;
+ bool mUseRealtimeOptions;
// This is only non-empty when "privacy.firstparty.isolate" is enabled.
// It is used to create sockets. It's the only way to carry it down to NSPR
// layers which are final consumers. It must be set before the socket
// transport is built.
nsCString mFirstPartyDomain;
uint16_t SocketPort() { return (!mProxyHost.IsEmpty() && !mProxyTransparent) ? mProxyPort : mPort; }
--- a/netwerk/protocol/http/TunnelUtils.cpp
+++ b/netwerk/protocol/http/TunnelUtils.cpp
@@ -1622,16 +1622,22 @@ SocketTransportShim::SetNetworkInterface
NS_IMETHODIMP
SocketTransportShim::SetTimeout(uint32_t aType, uint32_t aValue)
{
return mWrapped->SetTimeout(aType, aValue);
}
NS_IMETHODIMP
+SocketTransportShim::SetRealtimeOptions(bool aRealtimeOptions)
+{
+ return mWrapped->SetRealtimeOptions(aRealtimeOptions);
+}
+
+NS_IMETHODIMP
SocketTransportShim::GetQoSBits(uint8_t *aQoSBits)
{
return mWrapped->GetQoSBits(aQoSBits);
}
NS_IMETHODIMP
SocketTransportShim::SetQoSBits(uint8_t aQoSBits)
{