Add a turn port prune policy to keep the first ready turn port.
Bug: webrtc:11026
Change-Id: I6222e9613ee4ce2dcfbb717e2430ea833c0dc373
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/155542
Commit-Queue: Honghai Zhang <honghaiz@webrtc.org>
Reviewed-by: Qingsi Wang <qingsi@webrtc.org>
Reviewed-by: Patrik Höglund <phoglund@webrtc.org>
Reviewed-by: Jonas Oreland <jonaso@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29470}
diff --git a/api/BUILD.gn b/api/BUILD.gn
index 58fd04e..4eed48c 100644
--- a/api/BUILD.gn
+++ b/api/BUILD.gn
@@ -181,6 +181,7 @@
"task_queue",
"transport:bitrate_settings",
"transport:datagram_transport_interface",
+ "transport:enums",
"transport:network_control",
"transport/media:audio_interfaces",
"transport/media:media_transport_interface",
diff --git a/api/peer_connection_interface.h b/api/peer_connection_interface.h
index f526c37..12c5162 100644
--- a/api/peer_connection_interface.h
+++ b/api/peer_connection_interface.h
@@ -99,6 +99,7 @@
#include "api/stats_types.h"
#include "api/task_queue/task_queue_factory.h"
#include "api/transport/bitrate_settings.h"
+#include "api/transport/enums.h"
#include "api/transport/media/media_transport_interface.h"
#include "api/transport/network_control.h"
#include "api/turn_customizer.h"
@@ -394,7 +395,7 @@
int max_ipv6_networks = cricket::kDefaultMaxIPv6Networks;
// Exclude link-local network interfaces
- // from considertaion for gathering ICE candidates.
+ // from consideration for gathering ICE candidates.
bool disable_link_local_networks = false;
// If set to true, use RTP data channels instead of SCTP.
@@ -479,8 +480,18 @@
// If set to true, only one preferred TURN allocation will be used per
// network interface. UDP is preferred over TCP and IPv6 over IPv4. This
// can be used to cut down on the number of candidate pairings.
+ // Deprecated. TODO(webrtc:11026) Remove this flag once the downstream
+ // dependency is removed.
bool prune_turn_ports = false;
+ // The policy used to prune turn port.
+ PortPrunePolicy turn_port_prune_policy = NO_PRUNE;
+
+ PortPrunePolicy GetTurnPortPrunePolicy() const {
+ return prune_turn_ports ? PRUNE_BASED_ON_PRIORITY
+ : turn_port_prune_policy;
+ }
+
// If set to true, this means the ICE transport should presume TURN-to-TURN
// candidate pairs will succeed, even before a binding response is received.
// This can be used to optimize the initial connection time, since the DTLS
diff --git a/api/transport/enums.h b/api/transport/enums.h
index b1d5770..eb33e91 100644
--- a/api/transport/enums.h
+++ b/api/transport/enums.h
@@ -27,6 +27,13 @@
kClosed,
};
+enum PortPrunePolicy {
+ NO_PRUNE, // Do not prune.
+ PRUNE_BASED_ON_PRIORITY, // Prune lower-priority ports on the same network.
+ KEEP_FIRST_READY // Keep the first ready port and prune the rest
+ // on the same network.
+};
+
} // namespace webrtc
#endif // API_TRANSPORT_ENUMS_H_
diff --git a/p2p/base/p2p_transport_channel_unittest.cc b/p2p/base/p2p_transport_channel_unittest.cc
index 5a060a8..8f7fd4a 100644
--- a/p2p/base/p2p_transport_channel_unittest.cc
+++ b/p2p/base/p2p_transport_channel_unittest.cc
@@ -171,7 +171,7 @@
cricket::BasicPortAllocator* allocator =
new cricket::BasicPortAllocator(network_manager);
allocator->Initialize();
- allocator->SetConfiguration(stun_servers, turn_servers, 0, false);
+ allocator->SetConfiguration(stun_servers, turn_servers, 0, webrtc::NO_PRUNE);
return allocator;
}
} // namespace
@@ -2036,9 +2036,11 @@
auto& allocator_2 = GetEndpoint(1)->allocator_;
int pool_size = 1;
allocator_1->SetConfiguration(allocator_1->stun_servers(),
- allocator_1->turn_servers(), pool_size, false);
+ allocator_1->turn_servers(), pool_size,
+ webrtc::NO_PRUNE);
allocator_2->SetConfiguration(allocator_2->stun_servers(),
- allocator_2->turn_servers(), pool_size, false);
+ allocator_2->turn_servers(), pool_size,
+ webrtc::NO_PRUNE);
const PortAllocatorSession* pooled_session_1 =
allocator_1->GetPooledSession();
const PortAllocatorSession* pooled_session_2 =
@@ -2079,9 +2081,11 @@
auto& allocator_2 = GetEndpoint(1)->allocator_;
int pool_size = 1;
allocator_1->SetConfiguration(allocator_1->stun_servers(),
- allocator_1->turn_servers(), pool_size, false);
+ allocator_1->turn_servers(), pool_size,
+ webrtc::NO_PRUNE);
allocator_2->SetConfiguration(allocator_2->stun_servers(),
- allocator_2->turn_servers(), pool_size, false);
+ allocator_2->turn_servers(), pool_size,
+ webrtc::NO_PRUNE);
const PortAllocatorSession* pooled_session_1 =
allocator_1->GetPooledSession();
const PortAllocatorSession* pooled_session_2 =
diff --git a/p2p/base/port_allocator.cc b/p2p/base/port_allocator.cc
index a9d7cb6..b30416f 100644
--- a/p2p/base/port_allocator.cc
+++ b/p2p/base/port_allocator.cc
@@ -116,6 +116,7 @@
restrict_ice_credentials_change_ = value;
}
+// Deprecated
bool PortAllocator::SetConfiguration(
const ServerAddresses& stun_servers,
const std::vector<RelayServerConfig>& turn_servers,
@@ -123,6 +124,20 @@
bool prune_turn_ports,
webrtc::TurnCustomizer* turn_customizer,
const absl::optional<int>& stun_candidate_keepalive_interval) {
+ webrtc::PortPrunePolicy turn_port_prune_policy =
+ prune_turn_ports ? webrtc::PRUNE_BASED_ON_PRIORITY : webrtc::NO_PRUNE;
+ return SetConfiguration(stun_servers, turn_servers, candidate_pool_size,
+ turn_port_prune_policy, turn_customizer,
+ stun_candidate_keepalive_interval);
+}
+
+bool PortAllocator::SetConfiguration(
+ const ServerAddresses& stun_servers,
+ const std::vector<RelayServerConfig>& turn_servers,
+ int candidate_pool_size,
+ webrtc::PortPrunePolicy turn_port_prune_policy,
+ webrtc::TurnCustomizer* turn_customizer,
+ const absl::optional<int>& stun_candidate_keepalive_interval) {
CheckRunOnValidThreadIfInitialized();
// A positive candidate pool size would lead to the creation of a pooled
// allocator session and starting getting ports, which we should only do on
@@ -132,7 +147,7 @@
(stun_servers != stun_servers_ || turn_servers != turn_servers_);
stun_servers_ = stun_servers;
turn_servers_ = turn_servers;
- prune_turn_ports_ = prune_turn_ports;
+ turn_port_prune_policy_ = turn_port_prune_policy;
if (candidate_pool_frozen_) {
if (candidate_pool_size != candidate_pool_size_) {
diff --git a/p2p/base/port_allocator.h b/p2p/base/port_allocator.h
index f29877c..eb04cc2 100644
--- a/p2p/base/port_allocator.h
+++ b/p2p/base/port_allocator.h
@@ -16,6 +16,7 @@
#include <string>
#include <vector>
+#include "api/transport/enums.h"
#include "p2p/base/port.h"
#include "p2p/base/port_interface.h"
#include "rtc_base/helpers.h"
@@ -360,6 +361,7 @@
// created or destroyed as necessary.
//
// Returns true if the configuration could successfully be changed.
+ // Deprecated
bool SetConfiguration(const ServerAddresses& stun_servers,
const std::vector<RelayServerConfig>& turn_servers,
int candidate_pool_size,
@@ -367,6 +369,13 @@
webrtc::TurnCustomizer* turn_customizer = nullptr,
const absl::optional<int>&
stun_candidate_keepalive_interval = absl::nullopt);
+ bool SetConfiguration(const ServerAddresses& stun_servers,
+ const std::vector<RelayServerConfig>& turn_servers,
+ int candidate_pool_size,
+ webrtc::PortPrunePolicy turn_port_prune_policy,
+ webrtc::TurnCustomizer* turn_customizer = nullptr,
+ const absl::optional<int>&
+ stun_candidate_keepalive_interval = absl::nullopt);
const ServerAddresses& stun_servers() const {
CheckRunOnValidThreadIfInitialized();
@@ -555,9 +564,15 @@
// TODO(qingsi): Remove this after Chromium migrates to the new method.
void set_candidate_filter(uint32_t filter) { SetCandidateFilter(filter); }
+ // Deprecated (by the next method).
bool prune_turn_ports() const {
CheckRunOnValidThreadIfInitialized();
- return prune_turn_ports_;
+ return turn_port_prune_policy_ == webrtc::PRUNE_BASED_ON_PRIORITY;
+ }
+
+ webrtc::PortPrunePolicy turn_port_prune_policy() const {
+ CheckRunOnValidThreadIfInitialized();
+ return turn_port_prune_policy_;
}
// Gets/Sets the Origin value used for WebRTC STUN requests.
@@ -634,7 +649,7 @@
int candidate_pool_size_ = 0; // Last value passed into SetConfiguration.
std::vector<std::unique_ptr<PortAllocatorSession>> pooled_sessions_;
bool candidate_pool_frozen_ = false;
- bool prune_turn_ports_ = false;
+ webrtc::PortPrunePolicy turn_port_prune_policy_ = webrtc::NO_PRUNE;
// Customizer for TURN messages.
// The instance is owned by application and will be shared among
diff --git a/p2p/base/port_allocator_unittest.cc b/p2p/base/port_allocator_unittest.cc
index 5606168..70946a3 100644
--- a/p2p/base/port_allocator_unittest.cc
+++ b/p2p/base/port_allocator_unittest.cc
@@ -37,13 +37,13 @@
void SetConfigurationWithPoolSize(int candidate_pool_size) {
EXPECT_TRUE(allocator_->SetConfiguration(
cricket::ServerAddresses(), std::vector<cricket::RelayServerConfig>(),
- candidate_pool_size, false));
+ candidate_pool_size, webrtc::NO_PRUNE));
}
void SetConfigurationWithPoolSizeExpectFailure(int candidate_pool_size) {
EXPECT_FALSE(allocator_->SetConfiguration(
cricket::ServerAddresses(), std::vector<cricket::RelayServerConfig>(),
- candidate_pool_size, false));
+ candidate_pool_size, webrtc::NO_PRUNE));
}
std::unique_ptr<cricket::FakePortAllocatorSession> CreateSession(
@@ -114,16 +114,16 @@
TEST_F(PortAllocatorTest, SetConfigurationUpdatesIceServers) {
cricket::ServerAddresses stun_servers_1 = {stun_server_1};
std::vector<cricket::RelayServerConfig> turn_servers_1 = {turn_server_1};
- EXPECT_TRUE(
- allocator_->SetConfiguration(stun_servers_1, turn_servers_1, 0, false));
+ EXPECT_TRUE(allocator_->SetConfiguration(stun_servers_1, turn_servers_1, 0,
+ webrtc::NO_PRUNE));
EXPECT_EQ(stun_servers_1, allocator_->stun_servers());
EXPECT_EQ(turn_servers_1, allocator_->turn_servers());
// Update with a different set of servers.
cricket::ServerAddresses stun_servers_2 = {stun_server_2};
std::vector<cricket::RelayServerConfig> turn_servers_2 = {turn_server_2};
- EXPECT_TRUE(
- allocator_->SetConfiguration(stun_servers_2, turn_servers_2, 0, false));
+ EXPECT_TRUE(allocator_->SetConfiguration(stun_servers_2, turn_servers_2, 0,
+ webrtc::NO_PRUNE));
EXPECT_EQ(stun_servers_2, allocator_->stun_servers());
EXPECT_EQ(turn_servers_2, allocator_->turn_servers());
}
@@ -179,14 +179,16 @@
SetConfigurationRecreatesPooledSessionsWhenIceServersChange) {
cricket::ServerAddresses stun_servers_1 = {stun_server_1};
std::vector<cricket::RelayServerConfig> turn_servers_1 = {turn_server_1};
- allocator_->SetConfiguration(stun_servers_1, turn_servers_1, 1, false);
+ allocator_->SetConfiguration(stun_servers_1, turn_servers_1, 1,
+ webrtc::NO_PRUNE);
EXPECT_EQ(stun_servers_1, allocator_->stun_servers());
EXPECT_EQ(turn_servers_1, allocator_->turn_servers());
// Update with a different set of servers (and also change pool size).
cricket::ServerAddresses stun_servers_2 = {stun_server_2};
std::vector<cricket::RelayServerConfig> turn_servers_2 = {turn_server_2};
- allocator_->SetConfiguration(stun_servers_2, turn_servers_2, 2, false);
+ allocator_->SetConfiguration(stun_servers_2, turn_servers_2, 2,
+ webrtc::NO_PRUNE);
EXPECT_EQ(stun_servers_2, allocator_->stun_servers());
EXPECT_EQ(turn_servers_2, allocator_->turn_servers());
auto session_1 = TakePooledSession();
@@ -207,7 +209,8 @@
SetConfigurationDoesNotRecreatePooledSessionsAfterFreezeCandidatePool) {
cricket::ServerAddresses stun_servers_1 = {stun_server_1};
std::vector<cricket::RelayServerConfig> turn_servers_1 = {turn_server_1};
- allocator_->SetConfiguration(stun_servers_1, turn_servers_1, 1, false);
+ allocator_->SetConfiguration(stun_servers_1, turn_servers_1, 1,
+ webrtc::NO_PRUNE);
EXPECT_EQ(stun_servers_1, allocator_->stun_servers());
EXPECT_EQ(turn_servers_1, allocator_->turn_servers());
@@ -215,7 +218,8 @@
allocator_->FreezeCandidatePool();
cricket::ServerAddresses stun_servers_2 = {stun_server_2};
std::vector<cricket::RelayServerConfig> turn_servers_2 = {turn_server_2};
- allocator_->SetConfiguration(stun_servers_2, turn_servers_2, 2, false);
+ allocator_->SetConfiguration(stun_servers_2, turn_servers_2, 2,
+ webrtc::NO_PRUNE);
EXPECT_EQ(stun_servers_2, allocator_->stun_servers());
EXPECT_EQ(turn_servers_2, allocator_->turn_servers());
auto session = TakePooledSession();
diff --git a/p2p/base/regathering_controller_unittest.cc b/p2p/base/regathering_controller_unittest.cc
index d583ef8..cee4a67 100644
--- a/p2p/base/regathering_controller_unittest.cc
+++ b/p2p/base/regathering_controller_unittest.cc
@@ -70,7 +70,7 @@
std::vector<cricket::RelayServerConfig> turn_servers(1, turn_server);
allocator_->set_flags(kOnlyLocalPorts);
allocator_->SetConfiguration(stun_servers, turn_servers, 0 /* pool size */,
- false /* prune turn ports */);
+ webrtc::NO_PRUNE);
allocator_session_ = allocator_->CreateSession(
"test", cricket::ICE_CANDIDATE_COMPONENT_RTP, kIceUfrag, kIcePwd);
// The gathering will take place on the current thread and the following
diff --git a/p2p/client/basic_port_allocator.cc b/p2p/client/basic_port_allocator.cc
index 3608fe1..b49e2f8 100644
--- a/p2p/client/basic_port_allocator.cc
+++ b/p2p/client/basic_port_allocator.cc
@@ -161,7 +161,7 @@
RTC_DCHECK(network_manager_ != nullptr);
RTC_DCHECK(socket_factory_ != nullptr);
SetConfiguration(ServerAddresses(), std::vector<RelayServerConfig>(), 0,
- false, customizer);
+ webrtc::NO_PRUNE, customizer);
Construct();
}
@@ -185,8 +185,8 @@
: network_manager_(network_manager), socket_factory_(socket_factory) {
InitRelayPortFactory(nullptr);
RTC_DCHECK(relay_port_factory_ != nullptr);
- SetConfiguration(stun_servers, std::vector<RelayServerConfig>(), 0, false,
- nullptr);
+ SetConfiguration(stun_servers, std::vector<RelayServerConfig>(), 0,
+ webrtc::NO_PRUNE, nullptr);
Construct();
}
@@ -242,7 +242,7 @@
std::vector<RelayServerConfig> new_turn_servers = turn_servers();
new_turn_servers.push_back(turn_server);
SetConfiguration(stun_servers(), new_turn_servers, candidate_pool_size(),
- prune_turn_ports(), turn_customizer());
+ turn_port_prune_policy(), turn_customizer());
}
void BasicPortAllocator::InitRelayPortFactory(
@@ -273,7 +273,7 @@
allocation_started_(false),
network_manager_started_(false),
allocation_sequences_created_(false),
- prune_turn_ports_(allocator->prune_turn_ports()) {
+ turn_port_prune_policy_(allocator->turn_port_prune_policy()) {
allocator_->network_manager()->SignalNetworksChanged.connect(
this, &BasicPortAllocatorSession::OnNetworksChanged);
allocator_->network_manager()->StartUpdating();
@@ -378,8 +378,8 @@
network_thread_->Post(RTC_FROM_HERE, this, MSG_CONFIG_START);
- RTC_LOG(LS_INFO) << "Start getting ports with prune_turn_ports "
- << (prune_turn_ports_ ? "enabled" : "disabled");
+ RTC_LOG(LS_INFO) << "Start getting ports with turn_port_prune_policy "
+ << turn_port_prune_policy_;
}
void BasicPortAllocatorSession::StopGettingPorts() {
@@ -967,9 +967,14 @@
if (CandidatePairable(c, port) && !data->has_pairable_candidate()) {
data->set_has_pairable_candidate(true);
- if (prune_turn_ports_ && port->Type() == RELAY_PORT_TYPE) {
- pruned = PruneTurnPorts(port);
+ if (port->Type() == RELAY_PORT_TYPE) {
+ if (turn_port_prune_policy_ == webrtc::KEEP_FIRST_READY) {
+ pruned = PruneNewlyPairableTurnPort(data);
+ } else if (turn_port_prune_policy_ == webrtc::PRUNE_BASED_ON_PRIORITY) {
+ pruned = PruneTurnPorts(port);
+ }
}
+
// If the current port is not pruned yet, SignalPortReady.
if (!data->pruned()) {
RTC_LOG(LS_INFO) << port->ToString() << ": Port ready.";
@@ -1015,6 +1020,28 @@
return best_turn_port;
}
+bool BasicPortAllocatorSession::PruneNewlyPairableTurnPort(
+ PortData* newly_pairable_port_data) {
+ RTC_DCHECK_RUN_ON(network_thread_);
+ RTC_DCHECK(newly_pairable_port_data->port()->Type() == RELAY_PORT_TYPE);
+ // If an existing turn port is ready on the same network, prune the newly
+ // pairable port.
+ const std::string& network_name =
+ newly_pairable_port_data->port()->Network()->name();
+
+ for (PortData& data : ports_) {
+ if (data.port()->Network()->name() == network_name &&
+ data.port()->Type() == RELAY_PORT_TYPE && data.ready() &&
+ &data != newly_pairable_port_data) {
+ RTC_LOG(LS_INFO) << "Port pruned: "
+ << newly_pairable_port_data->port()->ToString();
+ newly_pairable_port_data->Prune();
+ return true;
+ }
+ }
+ return false;
+}
+
bool BasicPortAllocatorSession::PruneTurnPorts(Port* newly_pairable_turn_port) {
RTC_DCHECK_RUN_ON(network_thread_);
// Note: We determine the same network based only on their network names. So
diff --git a/p2p/client/basic_port_allocator.h b/p2p/client/basic_port_allocator.h
index 29c514f..10188ba 100644
--- a/p2p/client/basic_port_allocator.h
+++ b/p2p/client/basic_port_allocator.h
@@ -262,6 +262,7 @@
Port* GetBestTurnPortForNetwork(const std::string& network_name) const;
// Returns true if at least one TURN port is pruned.
bool PruneTurnPorts(Port* newly_pairable_turn_port);
+ bool PruneNewlyPairableTurnPort(PortData* newly_pairable_turn_port);
BasicPortAllocator* allocator_;
rtc::Thread* network_thread_;
@@ -274,8 +275,8 @@
std::vector<AllocationSequence*> sequences_;
std::vector<PortData> ports_;
uint32_t candidate_filter_ = CF_ALL;
- // Whether to prune low-priority ports, taken from the port allocator.
- bool prune_turn_ports_;
+ // Policy on how to prune turn ports, taken from the port allocator.
+ webrtc::PortPrunePolicy turn_port_prune_policy_;
SessionState state_ = SessionState::CLEARED;
friend class AllocationSequence;
diff --git a/p2p/client/basic_port_allocator_unittest.cc b/p2p/client/basic_port_allocator_unittest.cc
index 9d97dc9..31877ff 100644
--- a/p2p/client/basic_port_allocator_unittest.cc
+++ b/p2p/client/basic_port_allocator_unittest.cc
@@ -571,7 +571,8 @@
allocator_.reset(new BasicPortAllocator(&network_manager_));
allocator_->Initialize();
allocator_->SetConfiguration(allocator_->stun_servers(),
- allocator_->turn_servers(), 0, true);
+ allocator_->turn_servers(), 0,
+ webrtc::PRUNE_BASED_ON_PRIORITY);
AddTurnServers(kTurnUdpIntIPv6Addr, rtc::SocketAddress());
AddTurnServers(kTurnUdpIntAddr, rtc::SocketAddress());
@@ -603,13 +604,15 @@
rtc::SocketAddress(kTurnUdpExtAddr.ipaddr(), 0)));
}
- void TestUdpTurnPortPrunesTcpTurnPort() {
+ void TestTurnPortPrunesWithUdpAndTcpPorts(
+ webrtc::PortPrunePolicy prune_policy,
+ bool tcp_pruned) {
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);
+ allocator_->turn_servers(), 0, prune_policy);
AddTurnServers(kTurnUdpIntAddr, kTurnTcpIntAddr);
allocator_->set_step_delay(kMinimumStepDelay);
allocator_->set_flags(allocator().flags() |
@@ -627,8 +630,11 @@
// |ready_ports|, so we only need to verify the content in one of them.
EXPECT_EQ(2U, ports_.size());
EXPECT_EQ(1, CountPorts(ports_, "local", PROTO_UDP, kClientAddr));
- EXPECT_EQ(1, CountPorts(ports_, "relay", PROTO_UDP, kClientAddr));
- EXPECT_EQ(0, CountPorts(ports_, "relay", PROTO_TCP, kClientAddr));
+ int num_udp_ports = tcp_pruned ? 1 : 0;
+ EXPECT_EQ(num_udp_ports,
+ CountPorts(ports_, "relay", PROTO_UDP, kClientAddr));
+ EXPECT_EQ(1 - num_udp_ports,
+ CountPorts(ports_, "relay", PROTO_TCP, kClientAddr));
// Now that we remove candidates when a TURN port is pruned, |candidates_|
// should only contains two candidates regardless whether the TCP TURN port
@@ -640,6 +646,8 @@
session_->ReadyCandidates();
EXPECT_EQ(2U, ready_candidates.size());
EXPECT_TRUE(HasCandidate(ready_candidates, "local", "udp", kClientAddr));
+
+ // The external candidate is always udp.
EXPECT_TRUE(HasCandidate(ready_candidates, "relay", "udp",
rtc::SocketAddress(kTurnUdpExtAddr.ipaddr(), 0)));
}
@@ -656,7 +664,8 @@
allocator_.reset(new BasicPortAllocator(&network_manager_));
allocator_->Initialize();
allocator_->SetConfiguration(allocator_->stun_servers(),
- allocator_->turn_servers(), 0, true);
+ allocator_->turn_servers(), 0,
+ webrtc::PRUNE_BASED_ON_PRIORITY);
// Have both UDP/TCP and IPv4/IPv6 TURN ports.
AddTurnServers(kTurnUdpIntAddr, kTurnTcpIntAddr);
AddTurnServers(kTurnUdpIntIPv6Addr, kTurnTcpIntIPv6Addr);
@@ -1649,30 +1658,59 @@
rtc::SocketAddress(kTurnUdpExtAddr.ipaddr(), 0)));
}
-// Test that if prune_turn_ports is set, TCP TURN port will not be used
-// if UDP TurnPort is used, given that TCP TURN port becomes ready first.
+// Test that if the turn port prune policy is PRUNE_BASED_ON_PRIORITY, TCP TURN
+// port will not be used if UDP TurnPort is used, given that TCP TURN port
+// becomes ready first.
TEST_F(BasicPortAllocatorTest,
TestUdpTurnPortPrunesTcpTurnPortWithTcpPortReadyFirst) {
// UDP has longer delay than TCP so that TCP TURN port becomes ready first.
virtual_socket_server()->SetDelayOnAddress(kTurnUdpIntAddr, 200);
virtual_socket_server()->SetDelayOnAddress(kTurnTcpIntAddr, 100);
- TestUdpTurnPortPrunesTcpTurnPort();
+ TestTurnPortPrunesWithUdpAndTcpPorts(webrtc::PRUNE_BASED_ON_PRIORITY,
+ true /* tcp_pruned */);
}
-// Test that if prune_turn_ports is set, TCP TURN port will not be used
-// if UDP TurnPort is used, given that UDP TURN port becomes ready first.
+// Test that if turn port prune policy is PRUNE_BASED_ON_PRIORITY, TCP TURN port
+// will not be used if UDP TurnPort is used, given that UDP TURN port becomes
+// ready first.
TEST_F(BasicPortAllocatorTest,
TestUdpTurnPortPrunesTcpTurnPortsWithUdpPortReadyFirst) {
// UDP has shorter delay than TCP so that UDP TURN port becomes ready first.
virtual_socket_server()->SetDelayOnAddress(kTurnUdpIntAddr, 100);
virtual_socket_server()->SetDelayOnAddress(kTurnTcpIntAddr, 200);
- TestUdpTurnPortPrunesTcpTurnPort();
+ TestTurnPortPrunesWithUdpAndTcpPorts(webrtc::PRUNE_BASED_ON_PRIORITY,
+ true /* tcp_pruned */);
}
-// Tests that if prune_turn_ports is set, IPv4 TurnPort will not be used
-// if IPv6 TurnPort is used, given that IPv4 TURN port becomes ready first.
+// Test that if turn_port_prune policy is KEEP_FIRST_READY, the first ready port
+// will be kept regardless of the priority.
+TEST_F(BasicPortAllocatorTest,
+ TestUdpTurnPortPrunesTcpTurnPortIfUdpReadyFirst) {
+ // UDP has shorter delay than TCP so that UDP TURN port becomes ready first.
+ virtual_socket_server()->SetDelayOnAddress(kTurnUdpIntAddr, 100);
+ virtual_socket_server()->SetDelayOnAddress(kTurnTcpIntAddr, 200);
+
+ TestTurnPortPrunesWithUdpAndTcpPorts(webrtc::KEEP_FIRST_READY,
+ true /* tcp_pruned */);
+}
+
+// Test that if turn_port_prune policy is KEEP_FIRST_READY, the first ready port
+// will be kept regardless of the priority.
+TEST_F(BasicPortAllocatorTest,
+ TestTcpTurnPortPrunesUdpTurnPortIfTcpReadyFirst) {
+ // UDP has longer delay than TCP so that TCP TURN port becomes ready first.
+ virtual_socket_server()->SetDelayOnAddress(kTurnUdpIntAddr, 200);
+ virtual_socket_server()->SetDelayOnAddress(kTurnTcpIntAddr, 100);
+
+ TestTurnPortPrunesWithUdpAndTcpPorts(webrtc::KEEP_FIRST_READY,
+ false /* tcp_pruned */);
+}
+
+// Tests that if turn port prune policy is PRUNE_BASED_ON_PRIORITY, IPv4
+// TurnPort will not be used if IPv6 TurnPort is used, given that IPv4 TURN port
+// becomes ready first.
TEST_F(BasicPortAllocatorTest,
TestIPv6TurnPortPrunesIPv4TurnPortWithIPv4PortReadyFirst) {
// IPv6 has longer delay than IPv4, so that IPv4 TURN port becomes ready
@@ -1683,8 +1721,9 @@
TestIPv6TurnPortPrunesIPv4TurnPort();
}
-// Tests that if prune_turn_ports is set, IPv4 TurnPort will not be used
-// if IPv6 TurnPort is used, given that IPv6 TURN port becomes ready first.
+// Tests that if turn port prune policy is PRUNE_BASED_ON_PRIORITY, IPv4
+// TurnPort will not be used if IPv6 TurnPort is used, given that IPv6 TURN port
+// becomes ready first.
TEST_F(BasicPortAllocatorTest,
TestIPv6TurnPortPrunesIPv4TurnPortWithIPv6PortReadyFirst) {
// IPv6 has longer delay than IPv4, so that IPv6 TURN port becomes ready
@@ -1695,16 +1734,16 @@
TestIPv6TurnPortPrunesIPv4TurnPort();
}
-// Tests that if prune_turn_ports is set, each network interface
-// will has its own set of TurnPorts based on their priorities, in the default
-// case where no transit delay is set.
+// Tests that if turn port prune policy is PRUNE_BASED_ON_PRIORITY, each network
+// interface will has its own set of TurnPorts based on their priorities, in the
+// default case where no transit delay is set.
TEST_F(BasicPortAllocatorTest, TestEachInterfaceHasItsOwnTurnPortsNoDelay) {
TestEachInterfaceHasItsOwnTurnPorts();
}
-// Tests that if prune_turn_ports is set, each network interface
-// will has its own set of TurnPorts based on their priorities, given that
-// IPv4/TCP TURN port becomes ready first.
+// Tests that if turn port prune policy is PRUNE_BASED_ON_PRIORITY, each network
+// interface will has its own set of TurnPorts based on their priorities, given
+// that IPv4/TCP TURN port becomes ready first.
TEST_F(BasicPortAllocatorTest,
TestEachInterfaceHasItsOwnTurnPortsWithTcpIPv4ReadyFirst) {
// IPv6/UDP have longer delay than IPv4/TCP, so that IPv4/TCP TURN port
@@ -2038,7 +2077,8 @@
AddInterface(kClientAddr);
int pool_size = 1;
allocator_->SetConfiguration(allocator_->stun_servers(),
- allocator_->turn_servers(), pool_size, false);
+ allocator_->turn_servers(), pool_size,
+ webrtc::NO_PRUNE);
const PortAllocatorSession* peeked_session = allocator_->GetPooledSession();
ASSERT_NE(nullptr, peeked_session);
EXPECT_EQ_SIMULATED_WAIT(true, peeked_session->CandidatesAllocationDone(),
@@ -2074,7 +2114,8 @@
AddInterface(kClientAddr);
int pool_size = 1;
allocator_->SetConfiguration(allocator_->stun_servers(),
- allocator_->turn_servers(), pool_size, false);
+ allocator_->turn_servers(), pool_size,
+ webrtc::NO_PRUNE);
const PortAllocatorSession* peeked_session = allocator_->GetPooledSession();
ASSERT_NE(nullptr, peeked_session);
EXPECT_EQ_SIMULATED_WAIT(true, peeked_session->CandidatesAllocationDone(),
@@ -2248,9 +2289,9 @@
const int pool_size = 1;
const int expected_stun_keepalive_interval = 123;
AddInterface(kClientAddr);
- allocator_->SetConfiguration(allocator_->stun_servers(),
- allocator_->turn_servers(), pool_size, false,
- nullptr, expected_stun_keepalive_interval);
+ allocator_->SetConfiguration(
+ allocator_->stun_servers(), allocator_->turn_servers(), pool_size,
+ webrtc::NO_PRUNE, nullptr, expected_stun_keepalive_interval);
auto* pooled_session = allocator_->GetPooledSession();
ASSERT_NE(nullptr, pooled_session);
EXPECT_EQ_SIMULATED_WAIT(true, pooled_session->CandidatesAllocationDone(),
@@ -2263,17 +2304,17 @@
ChangeStunKeepaliveIntervalForPortsAfterInitialConfig) {
const int pool_size = 1;
AddInterface(kClientAddr);
- allocator_->SetConfiguration(allocator_->stun_servers(),
- allocator_->turn_servers(), pool_size, false,
- nullptr, 123 /* stun keepalive interval */);
+ allocator_->SetConfiguration(
+ allocator_->stun_servers(), allocator_->turn_servers(), pool_size,
+ webrtc::NO_PRUNE, nullptr, 123 /* stun keepalive interval */);
auto* pooled_session = allocator_->GetPooledSession();
ASSERT_NE(nullptr, pooled_session);
EXPECT_EQ_SIMULATED_WAIT(true, pooled_session->CandidatesAllocationDone(),
kDefaultAllocationTimeout, fake_clock);
const int expected_stun_keepalive_interval = 321;
- allocator_->SetConfiguration(allocator_->stun_servers(),
- allocator_->turn_servers(), pool_size, false,
- nullptr, expected_stun_keepalive_interval);
+ allocator_->SetConfiguration(
+ allocator_->stun_servers(), allocator_->turn_servers(), pool_size,
+ webrtc::NO_PRUNE, nullptr, expected_stun_keepalive_interval);
CheckStunKeepaliveIntervalOfAllReadyPorts(pooled_session,
expected_stun_keepalive_interval);
}
@@ -2285,9 +2326,9 @@
AddInterface(kClientAddr);
allocator_->set_flags(allocator().flags() |
PORTALLOCATOR_ENABLE_SHARED_SOCKET);
- allocator_->SetConfiguration(allocator_->stun_servers(),
- allocator_->turn_servers(), pool_size, false,
- nullptr, expected_stun_keepalive_interval);
+ allocator_->SetConfiguration(
+ allocator_->stun_servers(), allocator_->turn_servers(), pool_size,
+ webrtc::NO_PRUNE, nullptr, expected_stun_keepalive_interval);
ASSERT_TRUE(CreateSession(ICE_CANDIDATE_COMPONENT_RTP));
session_->StartGettingPorts();
EXPECT_TRUE_SIMULATED_WAIT(candidate_allocation_done_,
@@ -2303,9 +2344,9 @@
AddInterface(kClientAddr);
allocator_->set_flags(allocator().flags() &
~(PORTALLOCATOR_ENABLE_SHARED_SOCKET));
- allocator_->SetConfiguration(allocator_->stun_servers(),
- allocator_->turn_servers(), pool_size, false,
- nullptr, expected_stun_keepalive_interval);
+ allocator_->SetConfiguration(
+ allocator_->stun_servers(), allocator_->turn_servers(), pool_size,
+ webrtc::NO_PRUNE, nullptr, expected_stun_keepalive_interval);
ASSERT_TRUE(CreateSession(ICE_CANDIDATE_COMPONENT_RTP));
session_->StartGettingPorts();
EXPECT_TRUE_SIMULATED_WAIT(candidate_allocation_done_,
diff --git a/pc/peer_connection.cc b/pc/peer_connection.cc
index c0e1831..f019ec9 100644
--- a/pc/peer_connection.cc
+++ b/pc/peer_connection.cc
@@ -758,6 +758,7 @@
bool prioritize_most_likely_ice_candidate_pairs;
struct cricket::MediaConfig media_config;
bool prune_turn_ports;
+ PortPrunePolicy turn_port_prune_policy;
bool presume_writable_when_fully_relayed;
bool enable_ice_renomination;
bool redetermine_role_on_ice_restart;
@@ -817,6 +818,7 @@
enable_dtls_srtp == o.enable_dtls_srtp &&
ice_candidate_pool_size == o.ice_candidate_pool_size &&
prune_turn_ports == o.prune_turn_ports &&
+ turn_port_prune_policy == o.turn_port_prune_policy &&
presume_writable_when_fully_relayed ==
o.presume_writable_when_fully_relayed &&
enable_ice_renomination == o.enable_ice_renomination &&
@@ -3675,6 +3677,7 @@
modified_config.ice_candidate_pool_size =
configuration.ice_candidate_pool_size;
modified_config.prune_turn_ports = configuration.prune_turn_ports;
+ modified_config.turn_port_prune_policy = configuration.turn_port_prune_policy;
modified_config.surface_ice_candidates_on_ice_transport_type_changed =
configuration.surface_ice_candidates_on_ice_transport_type_changed;
modified_config.ice_check_min_interval = configuration.ice_check_min_interval;
@@ -3746,7 +3749,7 @@
rtc::Bind(&PeerConnection::ReconfigurePortAllocator_n, this,
stun_servers, turn_servers, modified_config.type,
modified_config.ice_candidate_pool_size,
- modified_config.prune_turn_ports,
+ modified_config.GetTurnPortPrunePolicy(),
modified_config.turn_customizer,
modified_config.stun_candidate_keepalive_interval,
static_cast<bool>(local_description())))) {
@@ -3759,7 +3762,8 @@
// triggers an ICE restart which will pick up the changes.
if (modified_config.servers != configuration_.servers ||
modified_config.type != configuration_.type ||
- modified_config.prune_turn_ports != configuration_.prune_turn_ports) {
+ modified_config.GetTurnPortPrunePolicy() !=
+ configuration_.GetTurnPortPrunePolicy()) {
transport_controller_->SetNeedsIceRestartFlag();
}
@@ -5736,8 +5740,8 @@
// properties set above.
port_allocator_->SetConfiguration(
stun_servers, std::move(turn_servers_copy),
- configuration.ice_candidate_pool_size, configuration.prune_turn_ports,
- configuration.turn_customizer,
+ configuration.ice_candidate_pool_size,
+ configuration.GetTurnPortPrunePolicy(), configuration.turn_customizer,
configuration.stun_candidate_keepalive_interval);
InitializePortAllocatorResult res;
@@ -5750,7 +5754,7 @@
const std::vector<cricket::RelayServerConfig>& turn_servers,
IceTransportsType type,
int candidate_pool_size,
- bool prune_turn_ports,
+ PortPrunePolicy turn_port_prune_policy,
webrtc::TurnCustomizer* turn_customizer,
absl::optional<int> stun_candidate_keepalive_interval,
bool have_local_description) {
@@ -5771,7 +5775,8 @@
// candidate filter set above.
return port_allocator_->SetConfiguration(
stun_servers, std::move(turn_servers_copy), candidate_pool_size,
- prune_turn_ports, turn_customizer, stun_candidate_keepalive_interval);
+ turn_port_prune_policy, turn_customizer,
+ stun_candidate_keepalive_interval);
}
cricket::ChannelManager* PeerConnection::channel_manager() const {
diff --git a/pc/peer_connection.h b/pc/peer_connection.h
index 393a1dd..428c2e8 100644
--- a/pc/peer_connection.h
+++ b/pc/peer_connection.h
@@ -907,7 +907,7 @@
const std::vector<cricket::RelayServerConfig>& turn_servers,
IceTransportsType type,
int candidate_pool_size,
- bool prune_turn_ports,
+ PortPrunePolicy turn_port_prune_policy,
webrtc::TurnCustomizer* turn_customizer,
absl::optional<int> stun_candidate_keepalive_interval,
bool have_local_description);
diff --git a/pc/peer_connection_interface_unittest.cc b/pc/peer_connection_interface_unittest.cc
index 2d0687c..5a01430 100644
--- a/pc/peer_connection_interface_unittest.cc
+++ b/pc/peer_connection_interface_unittest.cc
@@ -1395,7 +1395,8 @@
EXPECT_TRUE(raw_port_allocator->flags() & cricket::PORTALLOCATOR_DISABLE_TCP);
EXPECT_TRUE(raw_port_allocator->flags() &
cricket::PORTALLOCATOR_DISABLE_COSTLY_NETWORKS);
- EXPECT_TRUE(raw_port_allocator->prune_turn_ports());
+ EXPECT_EQ(webrtc::PRUNE_BASED_ON_PRIORITY,
+ raw_port_allocator->turn_port_prune_policy());
}
// Check that GetConfiguration returns the configuration the PeerConnection was
@@ -2448,11 +2449,12 @@
config.prune_turn_ports = false;
CreatePeerConnection(config);
config = pc_->GetConfiguration();
- EXPECT_FALSE(port_allocator_->prune_turn_ports());
+ EXPECT_EQ(webrtc::NO_PRUNE, port_allocator_->turn_port_prune_policy());
config.prune_turn_ports = true;
EXPECT_TRUE(pc_->SetConfiguration(config).ok());
- EXPECT_TRUE(port_allocator_->prune_turn_ports());
+ EXPECT_EQ(webrtc::PRUNE_BASED_ON_PRIORITY,
+ port_allocator_->turn_port_prune_policy());
}
// Test that the ice check interval can be changed. This does not verify that
diff --git a/sdk/android/api/org/webrtc/PeerConnection.java b/sdk/android/api/org/webrtc/PeerConnection.java
index 7317573..b981520 100644
--- a/sdk/android/api/org/webrtc/PeerConnection.java
+++ b/sdk/android/api/org/webrtc/PeerConnection.java
@@ -407,6 +407,13 @@
/** Java version of PeerConnectionInterface.ContinualGatheringPolicy */
public enum ContinualGatheringPolicy { GATHER_ONCE, GATHER_CONTINUALLY }
+ /** Java version of webrtc::PortPrunePolicy */
+ public enum PortPrunePolicy {
+ NO_PRUNE, // Do not prune turn port.
+ PRUNE_BASED_ON_PRIORITY, // Prune turn port based the priority on the same network
+ KEEP_FIRST_READY // Keep the first ready port and prune the rest on the same network.
+ }
+
/** Java version of rtc::IntervalRange */
public static class IntervalRange {
private final int min;
@@ -472,7 +479,9 @@
public KeyType keyType;
public ContinualGatheringPolicy continualGatheringPolicy;
public int iceCandidatePoolSize;
+ @Deprecated // by the turnPortPrunePolicy. See bugs.webrtc.org/11026
public boolean pruneTurnPorts;
+ public PortPrunePolicy turnPortPrunePolicy;
public boolean presumeWritableWhenFullyRelayed;
public boolean surfaceIceCandidatesOnIceTransportTypeChanged;
// The following fields define intervals in milliseconds at which ICE
@@ -583,6 +592,7 @@
continualGatheringPolicy = ContinualGatheringPolicy.GATHER_ONCE;
iceCandidatePoolSize = 0;
pruneTurnPorts = false;
+ turnPortPrunePolicy = PortPrunePolicy.NO_PRUNE;
presumeWritableWhenFullyRelayed = false;
surfaceIceCandidatesOnIceTransportTypeChanged = false;
iceCheckIntervalStrongConnectivityMs = null;
@@ -626,6 +636,11 @@
return bundlePolicy;
}
+ @CalledByNative("RTCConfiguration")
+ PortPrunePolicy getTurnPortPrunePolicy() {
+ return turnPortPrunePolicy;
+ }
+
@Nullable
@CalledByNative("RTCConfiguration")
RtcCertificatePem getCertificate() {
diff --git a/sdk/android/src/jni/pc/ice_candidate.cc b/sdk/android/src/jni/pc/ice_candidate.cc
index 247e8fa..af92ff8 100644
--- a/sdk/android/src/jni/pc/ice_candidate.cc
+++ b/sdk/android/src/jni/pc/ice_candidate.cc
@@ -194,6 +194,25 @@
return PeerConnectionInterface::GATHER_ONCE;
}
+webrtc::PortPrunePolicy JavaToNativePortPrunePolicy(
+ JNIEnv* jni,
+ const JavaRef<jobject>& j_port_prune_policy) {
+ std::string enum_name = GetJavaEnumName(jni, j_port_prune_policy);
+ if (enum_name == "NO_PRUNE") {
+ return webrtc::NO_PRUNE;
+ }
+ if (enum_name == "PRUNE_BASED_ON_PRIORITY") {
+ return webrtc::PRUNE_BASED_ON_PRIORITY;
+ }
+ if (enum_name == "KEEP_FIRST_READY") {
+ return webrtc::KEEP_FIRST_READY;
+ }
+
+ RTC_CHECK(false) << " Unexpected PortPrunePolicy enum name " << enum_name;
+
+ return webrtc::NO_PRUNE;
+}
+
PeerConnectionInterface::TlsCertPolicy JavaToNativeTlsCertPolicy(
JNIEnv* jni,
const JavaRef<jobject>& j_ice_server_tls_cert_policy) {
diff --git a/sdk/android/src/jni/pc/ice_candidate.h b/sdk/android/src/jni/pc/ice_candidate.h
index 0feeeb4..4bdeea6 100644
--- a/sdk/android/src/jni/pc/ice_candidate.h
+++ b/sdk/android/src/jni/pc/ice_candidate.h
@@ -71,6 +71,10 @@
JNIEnv* jni,
const JavaRef<jobject>& j_gathering_policy);
+webrtc::PortPrunePolicy JavaToNativePortPrunePolicy(
+ JNIEnv* jni,
+ const JavaRef<jobject>& j_port_prune_policy);
+
PeerConnectionInterface::TlsCertPolicy JavaToNativeTlsCertPolicy(
JNIEnv* jni,
const JavaRef<jobject>& j_ice_server_tls_cert_policy);
diff --git a/sdk/android/src/jni/pc/peer_connection.cc b/sdk/android/src/jni/pc/peer_connection.cc
index 20804de..f40a7bf 100644
--- a/sdk/android/src/jni/pc/peer_connection.cc
+++ b/sdk/android/src/jni/pc/peer_connection.cc
@@ -158,6 +158,8 @@
Java_RTCConfiguration_getIceServers(jni, j_rtc_config);
ScopedJavaLocalRef<jobject> j_continual_gathering_policy =
Java_RTCConfiguration_getContinualGatheringPolicy(jni, j_rtc_config);
+ ScopedJavaLocalRef<jobject> j_turn_port_prune_policy =
+ Java_RTCConfiguration_getTurnPortPrunePolicy(jni, j_rtc_config);
ScopedJavaLocalRef<jobject> j_turn_customizer =
Java_RTCConfiguration_getTurnCustomizer(jni, j_rtc_config);
ScopedJavaLocalRef<jobject> j_network_preference =
@@ -199,6 +201,8 @@
Java_RTCConfiguration_getIceCandidatePoolSize(jni, j_rtc_config);
rtc_config->prune_turn_ports =
Java_RTCConfiguration_getPruneTurnPorts(jni, j_rtc_config);
+ rtc_config->turn_port_prune_policy =
+ JavaToNativePortPrunePolicy(jni, j_turn_port_prune_policy);
rtc_config->presume_writable_when_fully_relayed =
Java_RTCConfiguration_getPresumeWritableWhenFullyRelayed(jni,
j_rtc_config);
diff --git a/test/peer_scenario/scenario_connection.cc b/test/peer_scenario/scenario_connection.cc
index 2c0ed36..9f0d3bf 100644
--- a/test/peer_scenario/scenario_connection.cc
+++ b/test/peer_scenario/scenario_connection.cc
@@ -109,7 +109,8 @@
port_allocator_->set_flags(port_allocator_->flags() | flags);
port_allocator_->Initialize();
RTC_CHECK(port_allocator_->SetConfiguration(/*stun_servers*/ {},
- /*turn_servers*/ {}, 0, false));
+ /*turn_servers*/ {}, 0,
+ webrtc::NO_PRUNE));
jsep_controller_->SetLocalCertificate(certificate_);
});
}