Reland "Add thread checker to PortAllocator and its subclasses and fix a bug causing memory contention by threads."
This is a reland of fc43d11717e16dd427ac84fee614e5511e43cefd
Original change's description:
> Add thread checker to PortAllocator and its subclasses and fix a bug
> causing memory contention by threads.
>
> PortAllocator and its subclasses assume all of their methods except the
> constructor must be called on the same thread (the network thread in
> practice). This CL adds a thread checker to PortAllocator and its
> subclasses for thread safety, and fixes bugs of invoking some of their
> methods in PeerConnection on the signaling thread.
>
> Bug: webrtc:9112
> Change-Id: I33ba9bae72ec09a45ec70435962f3f25cd31583c
> Reviewed-on: https://webrtc-review.googlesource.com/66945
> Commit-Queue: Qingsi Wang <qingsi@google.com>
> Reviewed-by: Taylor Brandstetter <deadbeef@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#22814}
Bug: webrtc:9112
Change-Id: I5c7377f05c0daccbe469e2fdbdfacabc5c222f4c
Reviewed-on: https://webrtc-review.googlesource.com/69422
Commit-Queue: Qingsi Wang <qingsi@google.com>
Reviewed-by: Taylor Brandstetter <deadbeef@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22889}
diff --git a/p2p/base/fakeportallocator.h b/p2p/base/fakeportallocator.h
index 3f0a1d4..b5db823 100644
--- a/p2p/base/fakeportallocator.h
+++ b/p2p/base/fakeportallocator.h
@@ -18,11 +18,12 @@
#include "p2p/base/basicpacketsocketfactory.h"
#include "p2p/base/portallocator.h"
#include "p2p/base/udpport.h"
+#include "rtc_base/bind.h"
#include "rtc_base/nethelpers.h"
+#include "rtc_base/thread.h"
namespace rtc {
class SocketFactory;
-class Thread;
}
namespace cricket {
@@ -219,12 +220,15 @@
owned_factory_.reset(new rtc::BasicPacketSocketFactory(network_thread_));
factory_ = owned_factory_.get();
}
- }
- void Initialize() override {
- // Port allocator should be initialized on the network thread.
- RTC_CHECK(network_thread_->IsCurrent());
- initialized_ = true;
+ if (network_thread_ == nullptr) {
+ network_thread_ = rtc::Thread::Current();
+ Initialize();
+ return;
+ }
+ network_thread_->Invoke<void>(RTC_FROM_HERE,
+ rtc::Bind(&PortAllocator::Initialize,
+ static_cast<PortAllocator*>(this)));
}
void SetNetworkIgnoreMask(int network_ignore_mask) override {}
@@ -245,7 +249,6 @@
rtc::Thread* network_thread_;
rtc::PacketSocketFactory* factory_;
std::unique_ptr<rtc::BasicPacketSocketFactory> owned_factory_;
- bool initialized_ = false;
};
} // namespace cricket
diff --git a/p2p/base/p2ptransportchannel_unittest.cc b/p2p/base/p2ptransportchannel_unittest.cc
index 192cbaa..19562f4 100644
--- a/p2p/base/p2ptransportchannel_unittest.cc
+++ b/p2p/base/p2ptransportchannel_unittest.cc
@@ -155,6 +155,7 @@
cricket::BasicPortAllocator* allocator =
new cricket::BasicPortAllocator(network_manager);
+ allocator->Initialize();
allocator->SetConfiguration(stun_servers, turn_servers, 0, false);
return allocator;
}
diff --git a/p2p/base/portallocator.cc b/p2p/base/portallocator.cc
index e766fa7..d938361 100644
--- a/p2p/base/portallocator.cc
+++ b/p2p/base/portallocator.cc
@@ -107,9 +107,19 @@
max_ipv6_networks_(kDefaultMaxIPv6Networks),
step_delay_(kDefaultStepDelay),
allow_tcp_listen_(true),
- candidate_filter_(CF_ALL) {}
+ candidate_filter_(CF_ALL) {
+ // The allocator will be attached to a thread in Initialize.
+ thread_checker_.DetachFromThread();
+}
-PortAllocator::~PortAllocator() = default;
+void PortAllocator::Initialize() {
+ RTC_DCHECK(thread_checker_.CalledOnValidThread());
+ initialized_ = true;
+}
+
+PortAllocator::~PortAllocator() {
+ CheckRunOnValidThreadIfInitialized();
+}
bool PortAllocator::SetConfiguration(
const ServerAddresses& stun_servers,
@@ -118,6 +128,7 @@
bool prune_turn_ports,
webrtc::TurnCustomizer* turn_customizer,
const rtc::Optional<int>& stun_candidate_keepalive_interval) {
+ CheckRunOnValidThreadIfInitialized();
bool ice_servers_changed =
(stun_servers != stun_servers_ || turn_servers != turn_servers_);
stun_servers_ = stun_servers;
@@ -181,6 +192,7 @@
int component,
const std::string& ice_ufrag,
const std::string& ice_pwd) {
+ CheckRunOnValidThreadAndInitialized();
auto session = std::unique_ptr<PortAllocatorSession>(
CreateSessionInternal(content_name, component, ice_ufrag, ice_pwd));
session->SetCandidateFilter(candidate_filter());
@@ -192,6 +204,7 @@
int component,
const std::string& ice_ufrag,
const std::string& ice_pwd) {
+ CheckRunOnValidThreadAndInitialized();
RTC_DCHECK(!ice_ufrag.empty());
RTC_DCHECK(!ice_pwd.empty());
if (pooled_sessions_.empty()) {
@@ -208,6 +221,7 @@
}
const PortAllocatorSession* PortAllocator::GetPooledSession() const {
+ CheckRunOnValidThreadAndInitialized();
if (pooled_sessions_.empty()) {
return nullptr;
}
@@ -215,15 +229,18 @@
}
void PortAllocator::FreezeCandidatePool() {
+ CheckRunOnValidThreadAndInitialized();
candidate_pool_frozen_ = true;
}
void PortAllocator::DiscardCandidatePool() {
+ CheckRunOnValidThreadIfInitialized();
pooled_sessions_.clear();
}
void PortAllocator::GetCandidateStatsFromPooledSessions(
CandidateStatsList* candidate_stats_list) {
+ CheckRunOnValidThreadAndInitialized();
for (const auto& session : pooled_sessions()) {
session->GetCandidateStatsFromReadyPorts(candidate_stats_list);
}
diff --git a/p2p/base/portallocator.h b/p2p/base/portallocator.h
index 5f1c091..9ee248b 100644
--- a/p2p/base/portallocator.h
+++ b/p2p/base/portallocator.h
@@ -22,6 +22,7 @@
#include "rtc_base/proxyinfo.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/thread.h"
+#include "rtc_base/thread_checker.h"
namespace webrtc {
class MetricsObserverInterface;
@@ -320,19 +321,18 @@
};
// Every method of PortAllocator (including the destructor) must be called on
-// the same thread, except for the constructor which may be called on any
-// thread.
+// the same thread after Initialize is called.
//
-// This allows constructing a PortAllocator subclass on one thread and
-// passing it into an object that uses it on a different thread.
+// This allows a PortAllocator subclass to be constructed and configured on one
+// thread, and passed into an object that uses it on a different thread.
class PortAllocator : public sigslot::has_slots<> {
public:
PortAllocator();
~PortAllocator() override;
- // This should be called on the PortAllocator's thread before the
- // PortAllocator is used. Subclasses may override this if necessary.
- virtual void Initialize() {}
+ // This MUST be called on the PortAllocator's thread after finishing
+ // constructing and configuring the PortAllocator subclasses.
+ virtual void Initialize();
// Set STUN and TURN servers to be used in future sessions, and set
// candidate pool size, as described in JSEP.
@@ -354,14 +354,23 @@
const rtc::Optional<int>&
stun_candidate_keepalive_interval = rtc::nullopt);
- const ServerAddresses& stun_servers() const { return stun_servers_; }
+ const ServerAddresses& stun_servers() const {
+ CheckRunOnValidThreadIfInitialized();
+ return stun_servers_;
+ }
const std::vector<RelayServerConfig>& turn_servers() const {
+ CheckRunOnValidThreadIfInitialized();
return turn_servers_;
}
- int candidate_pool_size() const { return candidate_pool_size_; }
+ int candidate_pool_size() const {
+ CheckRunOnValidThreadIfInitialized();
+ return candidate_pool_size_;
+ }
+
const rtc::Optional<int>& stun_candidate_keepalive_interval() const {
+ CheckRunOnValidThreadIfInitialized();
return stun_candidate_keepalive_interval_;
}
@@ -404,23 +413,48 @@
// Discard any remaining pooled sessions.
void DiscardCandidatePool();
- uint32_t flags() const { return flags_; }
- void set_flags(uint32_t flags) { flags_ = flags; }
+ uint32_t flags() const {
+ CheckRunOnValidThreadIfInitialized();
+ return flags_;
+ }
+
+ void set_flags(uint32_t flags) {
+ CheckRunOnValidThreadIfInitialized();
+ flags_ = flags;
+ }
// These three methods are deprecated. If connections need to go through a
// proxy, the application should create a BasicPortAllocator given a custom
// PacketSocketFactory that creates proxy sockets.
- const std::string& user_agent() const { return agent_; }
- const rtc::ProxyInfo& proxy() const { return proxy_; }
+ const std::string& user_agent() const {
+ CheckRunOnValidThreadIfInitialized();
+ return agent_;
+ }
+
+ const rtc::ProxyInfo& proxy() const {
+ CheckRunOnValidThreadIfInitialized();
+ return proxy_;
+ }
+
void set_proxy(const std::string& agent, const rtc::ProxyInfo& proxy) {
+ CheckRunOnValidThreadIfInitialized();
agent_ = agent;
proxy_ = proxy;
}
// Gets/Sets the port range to use when choosing client ports.
- int min_port() const { return min_port_; }
- int max_port() const { return max_port_; }
+ int min_port() const {
+ CheckRunOnValidThreadIfInitialized();
+ return min_port_;
+ }
+
+ int max_port() const {
+ CheckRunOnValidThreadIfInitialized();
+ return max_port_;
+ }
+
bool SetPortRange(int min_port, int max_port) {
+ CheckRunOnValidThreadIfInitialized();
if (min_port > max_port) {
return false;
}
@@ -438,8 +472,15 @@
// ICE down. We should work on making our ICE logic smarter (for example,
// prioritizing pinging connections that are most likely to work) so that
// every network interface can be used without impacting ICE's speed.
- void set_max_ipv6_networks(int networks) { max_ipv6_networks_ = networks; }
- int max_ipv6_networks() { return max_ipv6_networks_; }
+ void set_max_ipv6_networks(int networks) {
+ CheckRunOnValidThreadIfInitialized();
+ max_ipv6_networks_ = networks;
+ }
+
+ int max_ipv6_networks() {
+ CheckRunOnValidThreadIfInitialized();
+ return max_ipv6_networks_;
+ }
// Delay between different candidate gathering phases (UDP, TURN, TCP).
// Defaults to 1 second, but PeerConnection sets it to 50ms.
@@ -447,30 +488,59 @@
// STUN transactions at once, but that's already happening if you configure
// multiple STUN servers or have multiple network interfaces. We should
// implement some global pacing logic instead if that's our goal.
- uint32_t step_delay() const { return step_delay_; }
- void set_step_delay(uint32_t delay) { step_delay_ = delay; }
+ uint32_t step_delay() const {
+ CheckRunOnValidThreadIfInitialized();
+ return step_delay_;
+ }
- bool allow_tcp_listen() const { return allow_tcp_listen_; }
+ void set_step_delay(uint32_t delay) {
+ CheckRunOnValidThreadIfInitialized();
+ step_delay_ = delay;
+ }
+
+ bool allow_tcp_listen() const {
+ CheckRunOnValidThreadIfInitialized();
+ return allow_tcp_listen_;
+ }
+
void set_allow_tcp_listen(bool allow_tcp_listen) {
+ CheckRunOnValidThreadIfInitialized();
allow_tcp_listen_ = allow_tcp_listen;
}
- uint32_t candidate_filter() { return candidate_filter_; }
+ uint32_t candidate_filter() {
+ CheckRunOnValidThreadIfInitialized();
+ return candidate_filter_;
+ }
+
void set_candidate_filter(uint32_t filter) {
+ CheckRunOnValidThreadIfInitialized();
candidate_filter_ = filter;
}
- bool prune_turn_ports() const { return prune_turn_ports_; }
+ bool prune_turn_ports() const {
+ CheckRunOnValidThreadIfInitialized();
+ return prune_turn_ports_;
+ }
// Gets/Sets the Origin value used for WebRTC STUN requests.
- const std::string& origin() const { return origin_; }
- void set_origin(const std::string& origin) { origin_ = origin; }
+ const std::string& origin() const {
+ CheckRunOnValidThreadIfInitialized();
+ return origin_;
+ }
+
+ void set_origin(const std::string& origin) {
+ CheckRunOnValidThreadIfInitialized();
+ origin_ = origin;
+ }
void SetMetricsObserver(webrtc::MetricsObserverInterface* observer) {
+ CheckRunOnValidThreadIfInitialized();
metrics_observer_ = observer;
}
webrtc::TurnCustomizer* turn_customizer() {
+ CheckRunOnValidThreadIfInitialized();
return turn_customizer_;
}
@@ -497,6 +567,17 @@
return pooled_sessions_;
}
+ // The following thread checks are only done in DCHECK for the consistency
+ // with the exsiting thread checks.
+ void CheckRunOnValidThreadIfInitialized() const {
+ RTC_DCHECK(!initialized_ || thread_checker_.CalledOnValidThread());
+ }
+
+ void CheckRunOnValidThreadAndInitialized() const {
+ RTC_DCHECK(initialized_ && thread_checker_.CalledOnValidThread());
+ }
+
+ bool initialized_ = false;
uint32_t flags_;
std::string agent_;
rtc::ProxyInfo proxy_;
@@ -507,6 +588,7 @@
bool allow_tcp_listen_;
uint32_t candidate_filter_;
std::string origin_;
+ rtc::ThreadChecker thread_checker_;
private:
ServerAddresses stun_servers_;
diff --git a/p2p/client/basicportallocator.cc b/p2p/client/basicportallocator.cc
index 1b3947b..a25a937 100644
--- a/p2p/client/basicportallocator.cc
+++ b/p2p/client/basicportallocator.cc
@@ -186,6 +186,7 @@
}
BasicPortAllocator::~BasicPortAllocator() {
+ CheckRunOnValidThreadIfInitialized();
// Our created port allocator sessions depend on us, so destroy our remaining
// pooled sessions before anything else.
DiscardCandidatePool();
@@ -195,12 +196,14 @@
// TODO(phoglund): implement support for other types than loopback.
// See https://code.google.com/p/webrtc/issues/detail?id=4288.
// Then remove set_network_ignore_list from NetworkManager.
+ CheckRunOnValidThreadIfInitialized();
network_ignore_mask_ = network_ignore_mask;
}
PortAllocatorSession* BasicPortAllocator::CreateSessionInternal(
const std::string& content_name, int component,
const std::string& ice_ufrag, const std::string& ice_pwd) {
+ CheckRunOnValidThreadAndInitialized();
PortAllocatorSession* session = new BasicPortAllocatorSession(
this, content_name, component, ice_ufrag, ice_pwd);
session->SignalIceRegathering.connect(this,
@@ -209,6 +212,7 @@
}
void BasicPortAllocator::AddTurnServer(const RelayServerConfig& turn_server) {
+ CheckRunOnValidThreadAndInitialized();
std::vector<RelayServerConfig> new_turn_servers = turn_servers();
new_turn_servers.push_back(turn_server);
SetConfiguration(stun_servers(), new_turn_servers, candidate_pool_size(),
diff --git a/p2p/client/basicportallocator.h b/p2p/client/basicportallocator.h
index fb74ba5..1822b7d 100644
--- a/p2p/client/basicportallocator.h
+++ b/p2p/client/basicportallocator.h
@@ -47,13 +47,22 @@
// Set to kDefaultNetworkIgnoreMask by default.
void SetNetworkIgnoreMask(int network_ignore_mask) override;
- int network_ignore_mask() const { return network_ignore_mask_; }
+ int network_ignore_mask() const {
+ CheckRunOnValidThreadIfInitialized();
+ return network_ignore_mask_;
+ }
- rtc::NetworkManager* network_manager() const { return network_manager_; }
+ rtc::NetworkManager* network_manager() const {
+ CheckRunOnValidThreadIfInitialized();
+ return network_manager_;
+ }
// If socket_factory() is set to NULL each PortAllocatorSession
// creates its own socket factory.
- rtc::PacketSocketFactory* socket_factory() { return socket_factory_; }
+ rtc::PacketSocketFactory* socket_factory() {
+ CheckRunOnValidThreadIfInitialized();
+ return socket_factory_;
+ }
PortAllocatorSession* CreateSessionInternal(
const std::string& content_name,
@@ -65,6 +74,7 @@
void AddTurnServer(const RelayServerConfig& turn_server);
RelayPortFactoryInterface* relay_port_factory() {
+ CheckRunOnValidThreadIfInitialized();
return relay_port_factory_;
}
diff --git a/p2p/client/basicportallocator_unittest.cc b/p2p/client/basicportallocator_unittest.cc
index f39e61e..6ed13b57 100644
--- a/p2p/client/basicportallocator_unittest.cc
+++ b/p2p/client/basicportallocator_unittest.cc
@@ -166,6 +166,7 @@
allocator_.reset(new BasicPortAllocator(&network_manager_, stun_servers,
kRelayUdpIntAddr, kRelayTcpIntAddr,
kRelaySslTcpIntAddr));
+ allocator_->Initialize();
allocator_->set_step_delay(kMinimumStepDelay);
}
@@ -201,6 +202,7 @@
// Endpoint is on the public network. No STUN or TURN.
void ResetWithNoServersOrNat() {
allocator_.reset(new BasicPortAllocator(&network_manager_));
+ allocator_->Initialize();
allocator_->set_step_delay(kMinimumStepDelay);
}
// Endpoint is behind a NAT, with STUN specified.
@@ -483,7 +485,8 @@
}
allocator_.reset(new BasicPortAllocator(
&network_manager_, nat_socket_factory_.get(), stun_servers));
- allocator().set_step_delay(kMinimumStepDelay);
+ allocator_->Initialize();
+ allocator_->set_step_delay(kMinimumStepDelay);
}
std::unique_ptr<rtc::VirtualSocketServer> vss_;
@@ -579,6 +582,7 @@
AddInterface(kClientAddr, "net1");
AddInterface(kClientIPv6Addr, "net1");
allocator_.reset(new BasicPortAllocator(&network_manager_));
+ allocator_->Initialize();
allocator_->SetConfiguration(allocator_->stun_servers(),
allocator_->turn_servers(), 0, true);
AddTurnServers(kTurnUdpIntIPv6Addr, rtc::SocketAddress());
@@ -616,6 +620,7 @@
turn_server_.AddInternalSocket(kTurnTcpIntAddr, PROTO_TCP);
AddInterface(kClientAddr);
allocator_.reset(new BasicPortAllocator(&network_manager_));
+ allocator_->Initialize();
allocator_->SetConfiguration(allocator_->stun_servers(),
allocator_->turn_servers(), 0, true);
AddTurnServers(kTurnUdpIntAddr, kTurnTcpIntAddr);
@@ -662,6 +667,7 @@
AddInterface(kClientAddr2, "net2", rtc::ADAPTER_TYPE_CELLULAR);
AddInterface(kClientIPv6Addr2, "net2", rtc::ADAPTER_TYPE_CELLULAR);
allocator_.reset(new BasicPortAllocator(&network_manager_));
+ allocator_->Initialize();
allocator_->SetConfiguration(allocator_->stun_servers(),
allocator_->turn_servers(), 0, true);
// Have both UDP/TCP and IPv4/IPv6 TURN ports.
@@ -1651,6 +1657,7 @@
turn_server_.AddInternalSocket(kTurnTcpIntAddr, PROTO_TCP);
AddInterface(kClientAddr);
allocator_.reset(new BasicPortAllocator(&network_manager_));
+ allocator_->Initialize();
AddTurnServers(kTurnUdpIntAddr, kTurnTcpIntAddr);
@@ -1755,6 +1762,7 @@
PROTO_UDP);
AddInterface(kClientAddr);
allocator_.reset(new BasicPortAllocator(&network_manager_));
+ allocator_->Initialize();
RelayServerConfig turn_server(RELAY_TURN);
RelayCredentials credentials(kTurnUsername, kTurnPassword);
turn_server.credentials = credentials;
diff --git a/pc/peerconnection.cc b/pc/peerconnection.cc
index c7dc73b..092b69a 100644
--- a/pc/peerconnection.cc
+++ b/pc/peerconnection.cc
@@ -1977,11 +1977,6 @@
PostSetSessionDescriptionSuccess(observer);
- // According to JSEP, after setLocalDescription, changing the candidate pool
- // size is not allowed, and changing the set of ICE servers will not result
- // in new candidates being gathered.
- port_allocator_->FreezeCandidatePool();
-
// MaybeStartGathering needs to be called after posting
// MSG_SET_SESSIONDESCRIPTION_SUCCESS, so that we don't signal any candidates
// before signaling that SetLocalDescription completed.
@@ -2818,6 +2813,9 @@
RTCError* error) {
TRACE_EVENT0("webrtc", "PeerConnection::SetConfiguration");
+ // According to JSEP, after setLocalDescription, changing the candidate pool
+ // size is not allowed, and changing the set of ICE servers will not result
+ // in new candidates being gathered.
if (local_description() && configuration.ice_candidate_pool_size !=
configuration_.ice_candidate_pool_size) {
RTC_LOG(LS_ERROR) << "Can't change candidate pool size after calling "
@@ -2975,8 +2973,26 @@
void PeerConnection::RegisterUMAObserver(UMAObserver* observer) {
TRACE_EVENT0("webrtc", "PeerConnection::RegisterUmaObserver");
- uma_observer_ = observer;
+ network_thread()->Invoke<void>(
+ RTC_FROM_HERE,
+ rtc::Bind(&PeerConnection::SetMetricObserver_n, this, observer));
+ // Send information about IPv4/IPv6 status.
+ if (uma_observer_) {
+ if (port_allocator_flags_ & cricket::PORTALLOCATOR_ENABLE_IPV6) {
+ uma_observer_->IncrementEnumCounter(
+ kEnumCounterAddressFamily, kPeerConnection_IPv6,
+ kPeerConnectionAddressFamilyCounter_Max);
+ } else {
+ uma_observer_->IncrementEnumCounter(
+ kEnumCounterAddressFamily, kPeerConnection_IPv4,
+ kPeerConnectionAddressFamilyCounter_Max);
+ }
+ }
+}
+void PeerConnection::SetMetricObserver_n(UMAObserver* observer) {
+ RTC_DCHECK(network_thread()->IsCurrent());
+ uma_observer_ = observer;
if (transport_controller()) {
transport_controller()->SetMetricsObserver(uma_observer_);
}
@@ -2988,18 +3004,8 @@
}
}
- // Send information about IPv4/IPv6 status.
if (uma_observer_) {
port_allocator_->SetMetricsObserver(uma_observer_);
- if (port_allocator_->flags() & cricket::PORTALLOCATOR_ENABLE_IPV6) {
- uma_observer_->IncrementEnumCounter(
- kEnumCounterAddressFamily, kPeerConnection_IPv6,
- kPeerConnectionAddressFamilyCounter_Max);
- } else {
- uma_observer_->IncrementEnumCounter(
- kEnumCounterAddressFamily, kPeerConnection_IPv4,
- kPeerConnectionAddressFamilyCounter_Max);
- }
}
}
@@ -4589,44 +4595,43 @@
}
port_allocator_->Initialize();
-
// To handle both internal and externally created port allocator, we will
// enable BUNDLE here.
- int portallocator_flags = port_allocator_->flags();
- portallocator_flags |= cricket::PORTALLOCATOR_ENABLE_SHARED_SOCKET |
- cricket::PORTALLOCATOR_ENABLE_IPV6 |
- cricket::PORTALLOCATOR_ENABLE_IPV6_ON_WIFI;
+ port_allocator_flags_ = port_allocator_->flags();
+ port_allocator_flags_ |= cricket::PORTALLOCATOR_ENABLE_SHARED_SOCKET |
+ cricket::PORTALLOCATOR_ENABLE_IPV6 |
+ cricket::PORTALLOCATOR_ENABLE_IPV6_ON_WIFI;
// If the disable-IPv6 flag was specified, we'll not override it
// by experiment.
if (configuration.disable_ipv6) {
- portallocator_flags &= ~(cricket::PORTALLOCATOR_ENABLE_IPV6);
+ port_allocator_flags_ &= ~(cricket::PORTALLOCATOR_ENABLE_IPV6);
} else if (webrtc::field_trial::FindFullName("WebRTC-IPv6Default")
.find("Disabled") == 0) {
- portallocator_flags &= ~(cricket::PORTALLOCATOR_ENABLE_IPV6);
+ port_allocator_flags_ &= ~(cricket::PORTALLOCATOR_ENABLE_IPV6);
}
if (configuration.disable_ipv6_on_wifi) {
- portallocator_flags &= ~(cricket::PORTALLOCATOR_ENABLE_IPV6_ON_WIFI);
+ port_allocator_flags_ &= ~(cricket::PORTALLOCATOR_ENABLE_IPV6_ON_WIFI);
RTC_LOG(LS_INFO) << "IPv6 candidates on Wi-Fi are disabled.";
}
if (configuration.tcp_candidate_policy == kTcpCandidatePolicyDisabled) {
- portallocator_flags |= cricket::PORTALLOCATOR_DISABLE_TCP;
+ port_allocator_flags_ |= cricket::PORTALLOCATOR_DISABLE_TCP;
RTC_LOG(LS_INFO) << "TCP candidates are disabled.";
}
if (configuration.candidate_network_policy ==
kCandidateNetworkPolicyLowCost) {
- portallocator_flags |= cricket::PORTALLOCATOR_DISABLE_COSTLY_NETWORKS;
+ port_allocator_flags_ |= cricket::PORTALLOCATOR_DISABLE_COSTLY_NETWORKS;
RTC_LOG(LS_INFO) << "Do not gather candidates on high-cost networks";
}
if (configuration.disable_link_local_networks) {
- portallocator_flags |= cricket::PORTALLOCATOR_DISABLE_LINK_LOCAL_NETWORKS;
+ port_allocator_flags_ |= cricket::PORTALLOCATOR_DISABLE_LINK_LOCAL_NETWORKS;
RTC_LOG(LS_INFO) << "Disable candidates on link-local network interfaces.";
}
- port_allocator_->set_flags(portallocator_flags);
+ port_allocator_->set_flags(port_allocator_flags_);
// No step delay is used while allocating ports.
port_allocator_->set_step_delay(cricket::kMinimumStepDelay);
port_allocator_->set_candidate_filter(
@@ -4652,6 +4657,12 @@
rtc::Optional<int> stun_candidate_keepalive_interval) {
port_allocator_->set_candidate_filter(
ConvertIceTransportTypeToCandidateFilter(type));
+ // According to JSEP, after setLocalDescription, changing the candidate pool
+ // size is not allowed, and changing the set of ICE servers will not result
+ // in new candidates being gathered.
+ if (local_description()) {
+ port_allocator_->FreezeCandidatePool();
+ }
// Call this last since it may create pooled allocator sessions using the
// candidate filter set above.
return port_allocator_->SetConfiguration(
@@ -5053,7 +5064,10 @@
cricket::CandidateStatsList PeerConnection::GetPooledCandidateStats() const {
cricket::CandidateStatsList candidate_states_list;
- port_allocator_->GetCandidateStatsFromPooledSessions(&candidate_states_list);
+ network_thread()->Invoke<void>(
+ RTC_FROM_HERE,
+ rtc::Bind(&cricket::PortAllocator::GetCandidateStatsFromPooledSessions,
+ port_allocator_.get(), &candidate_states_list));
return candidate_states_list;
}
diff --git a/pc/peerconnection.h b/pc/peerconnection.h
index c019ef9..3545479 100644
--- a/pc/peerconnection.h
+++ b/pc/peerconnection.h
@@ -655,6 +655,8 @@
webrtc::TurnCustomizer* turn_customizer,
rtc::Optional<int> stun_candidate_keepalive_interval);
+ void SetMetricObserver_n(UMAObserver* observer);
+
// Starts output of an RTC event log to the given output object.
// This function should only be called from the worker thread.
bool StartRtcEventLog_w(std::unique_ptr<RtcEventLogOutput> output,
@@ -907,6 +909,7 @@
PeerConnectionInterface::RTCConfiguration configuration_;
std::unique_ptr<cricket::PortAllocator> port_allocator_;
+ int port_allocator_flags_ = 0;
// One PeerConnection has only one RTCP CNAME.
// https://tools.ietf.org/html/draft-ietf-rtcweb-rtp-usage-26#section-4.9
diff --git a/pc/peerconnection_integrationtest.cc b/pc/peerconnection_integrationtest.cc
index 583765d..ab4410b 100644
--- a/pc/peerconnection_integrationtest.cc
+++ b/pc/peerconnection_integrationtest.cc
@@ -3237,8 +3237,14 @@
}
void SetPortAllocatorFlags() {
- caller()->port_allocator()->set_flags(port_allocator_flags_);
- callee()->port_allocator()->set_flags(port_allocator_flags_);
+ network_thread()->Invoke<void>(
+ RTC_FROM_HERE,
+ rtc::Bind(&cricket::PortAllocator::set_flags,
+ caller()->port_allocator(), port_allocator_flags_));
+ network_thread()->Invoke<void>(
+ RTC_FROM_HERE,
+ rtc::Bind(&cricket::PortAllocator::set_flags,
+ callee()->port_allocator(), port_allocator_flags_));
}
std::vector<SocketAddress> CallerAddresses() {
diff --git a/pc/peerconnectioninterface_unittest.cc b/pc/peerconnectioninterface_unittest.cc
index 8ee39c9..acb0dbdd 100644
--- a/pc/peerconnectioninterface_unittest.cc
+++ b/pc/peerconnectioninterface_unittest.cc
@@ -1414,31 +1414,6 @@
EXPECT_TRUE(raw_port_allocator->prune_turn_ports());
}
-// Test that the PeerConnection initializes the port allocator passed into it,
-// and on the correct thread.
-TEST_P(PeerConnectionInterfaceTest,
- CreatePeerConnectionInitializesPortAllocatorOnNetworkThread) {
- std::unique_ptr<rtc::Thread> network_thread(
- rtc::Thread::CreateWithSocketServer());
- network_thread->Start();
- rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> pc_factory(
- webrtc::CreatePeerConnectionFactory(
- network_thread.get(), rtc::Thread::Current(), rtc::Thread::Current(),
- fake_audio_capture_module_,
- webrtc::CreateBuiltinAudioEncoderFactory(),
- webrtc::CreateBuiltinAudioDecoderFactory(), nullptr, nullptr));
- std::unique_ptr<cricket::FakePortAllocator> port_allocator(
- new cricket::FakePortAllocator(network_thread.get(), nullptr));
- cricket::FakePortAllocator* raw_port_allocator = port_allocator.get();
- PeerConnectionInterface::RTCConfiguration config;
- rtc::scoped_refptr<PeerConnectionInterface> pc(
- pc_factory->CreatePeerConnection(
- config, nullptr, std::move(port_allocator), nullptr, &observer_));
- // FakePortAllocator RTC_CHECKs that it's initialized on the right thread,
- // so all we have to do here is check that it's initialized.
- EXPECT_TRUE(raw_port_allocator->initialized());
-}
-
// Check that GetConfiguration returns the configuration the PeerConnection was
// constructed with, before SetConfiguration is called.
TEST_P(PeerConnectionInterfaceTest, GetConfigurationAfterCreatePeerConnection) {