Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(230)

Unified Diff: webrtc/p2p/client/basicportallocator.cc

Issue 2093623004: Add config to prune TURN ports (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Partially disable the test TestEachInterfaceHasItsOwnTurnPorts Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « webrtc/p2p/client/basicportallocator.h ('k') | webrtc/p2p/client/basicportallocator_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webrtc/p2p/client/basicportallocator.cc
diff --git a/webrtc/p2p/client/basicportallocator.cc b/webrtc/p2p/client/basicportallocator.cc
index e39a44013cdcf4f5b4cf627e225c499afb1e1687..edd5fed9cf55843c8e56a7d8089c6ec4a61c4dba 100644
--- a/webrtc/p2p/client/basicportallocator.cc
+++ b/webrtc/p2p/client/basicportallocator.cc
@@ -47,6 +47,47 @@ const int PHASE_SSLTCP = 3;
const int kNumPhases = 4;
+// Gets protocol priority: UDP > TCP > SSLTCP.
+int GetProtocolPriority(cricket::ProtocolType protocol) {
+ switch (protocol) {
+ case cricket::PROTO_UDP:
+ return 2;
+ case cricket::PROTO_TCP:
+ return 1;
+ case cricket::PROTO_SSLTCP:
+ return 0;
+ default:
+ RTC_DCHECK(false);
+ return 0;
+ }
+}
+// Gets address family priority: IPv6 > IPv4 > Unspecified.
+int GetAddressFamilyPriority(int ip_family) {
+ switch (ip_family) {
+ case AF_INET6:
+ return 2;
+ case AF_INET:
+ return 1;
+ default:
+ RTC_DCHECK(false);
+ return 0;
+ }
+}
+
+// Returns positive if a is better, negative if b is better, and 0 otherwise.
+int ComparePort(const cricket::Port* a, const cricket::Port* b) {
+ int a_protocol = GetProtocolPriority(a->GetProtocol());
+ int b_protocol = GetProtocolPriority(b->GetProtocol());
+ int cmp_protocol = a_protocol - b_protocol;
+ if (cmp_protocol != 0) {
+ return cmp_protocol;
+ }
+
+ int a_family = GetAddressFamilyPriority(a->Network()->GetBestIP().family());
+ int b_family = GetAddressFamilyPriority(b->Network()->GetBestIP().family());
+ return a_family - b_family;
+}
+
} // namespace
namespace cricket {
@@ -74,7 +115,7 @@ BasicPortAllocator::BasicPortAllocator(rtc::NetworkManager* network_manager,
const ServerAddresses& stun_servers)
: network_manager_(network_manager), socket_factory_(socket_factory) {
ASSERT(socket_factory_ != NULL);
- SetConfiguration(stun_servers, std::vector<RelayServerConfig>(), 0);
+ SetConfiguration(stun_servers, std::vector<RelayServerConfig>(), 0, false);
Construct();
}
@@ -101,7 +142,7 @@ BasicPortAllocator::BasicPortAllocator(
turn_servers.push_back(config);
}
- SetConfiguration(stun_servers, turn_servers, 0);
+ SetConfiguration(stun_servers, turn_servers, 0, false);
Construct();
}
@@ -122,24 +163,30 @@ PortAllocatorSession* BasicPortAllocator::CreateSessionInternal(
void BasicPortAllocator::AddTurnServer(const RelayServerConfig& turn_server) {
std::vector<RelayServerConfig> new_turn_servers = turn_servers();
new_turn_servers.push_back(turn_server);
- SetConfiguration(stun_servers(), new_turn_servers, candidate_pool_size());
+ SetConfiguration(stun_servers(), new_turn_servers, candidate_pool_size(),
+ prune_turn_ports());
}
// BasicPortAllocatorSession
BasicPortAllocatorSession::BasicPortAllocatorSession(
- BasicPortAllocator *allocator,
+ BasicPortAllocator* allocator,
const std::string& content_name,
int component,
const std::string& ice_ufrag,
const std::string& ice_pwd)
- : PortAllocatorSession(content_name, component,
- ice_ufrag, ice_pwd, allocator->flags()),
- allocator_(allocator), network_thread_(NULL),
+ : PortAllocatorSession(content_name,
+ component,
+ ice_ufrag,
+ ice_pwd,
+ allocator->flags()),
+ allocator_(allocator),
+ network_thread_(NULL),
socket_factory_(allocator->socket_factory()),
allocation_started_(false),
network_manager_started_(false),
running_(false),
- allocation_sequences_created_(false) {
+ allocation_sequences_created_(false),
+ prune_turn_ports_(allocator->prune_turn_ports()) {
allocator_->network_manager()->SignalNetworksChanged.connect(
this, &BasicPortAllocatorSession::OnNetworksChanged);
allocator_->network_manager()->StartUpdating();
@@ -217,9 +264,9 @@ void BasicPortAllocatorSession::ClearGettingPorts() {
std::vector<PortInterface*> BasicPortAllocatorSession::ReadyPorts() const {
std::vector<PortInterface*> ret;
- for (const PortData& port : ports_) {
- if (port.has_pairable_candidate() && !port.error()) {
- ret.push_back(port.port());
+ for (const PortData& data : ports_) {
+ if (data.ready()) {
+ ret.push_back(data.port());
}
}
return ret;
@@ -228,6 +275,10 @@ std::vector<PortInterface*> BasicPortAllocatorSession::ReadyPorts() const {
std::vector<Candidate> BasicPortAllocatorSession::ReadyCandidates() const {
std::vector<Candidate> candidates;
for (const PortData& data : ports_) {
+ if (!data.ready()) {
+ continue;
+ }
+
for (const Candidate& candidate : data.port()->Candidates()) {
if (!CheckCandidateFilter(candidate)) {
continue;
@@ -278,16 +329,11 @@ bool BasicPortAllocatorSession::CandidatesAllocationDone() const {
return false;
}
- // If all allocated ports are in complete state, session must have got all
+ // If all allocated ports are no longer gathering, session must have got all
// expected candidates. Session will trigger candidates allocation complete
// signal.
- if (!std::all_of(ports_.begin(), ports_.end(), [](const PortData& port) {
- return (port.complete() || port.error());
- })) {
- return false;
- }
-
- return true;
+ return std::none_of(ports_.begin(), ports_.end(),
+ [](const PortData& port) { return port.inprogress(); });
}
void BasicPortAllocatorSession::OnMessage(rtc::Message *message) {
@@ -357,7 +403,7 @@ void BasicPortAllocatorSession::OnConfigStop() {
bool send_signal = false;
for (std::vector<PortData>::iterator it = ports_.begin();
it != ports_.end(); ++it) {
- if (!it->complete() && !it->error()) {
+ if (it->inprogress()) {
// Updating port state to error, which didn't finish allocating candidates
// yet.
it->set_error();
@@ -443,11 +489,8 @@ void BasicPortAllocatorSession::DoAllocate() {
LOG(LS_WARNING) << "Machine has no networks; no ports will be allocated";
done_signal_needed = true;
} else {
+ PortConfiguration* config = configs_.empty() ? nullptr : configs_.back();
for (uint32_t i = 0; i < networks.size(); ++i) {
- PortConfiguration* config = NULL;
- if (configs_.size() > 0)
- config = configs_.back();
-
uint32_t sequence_flags = flags();
if ((sequence_flags & DISABLE_ALL_PHASES) == DISABLE_ALL_PHASES) {
// If all the ports are disabled we should just fire the allocation
@@ -568,37 +611,85 @@ void BasicPortAllocatorSession::OnCandidateReady(
PortData* data = FindPort(port);
ASSERT(data != NULL);
// Discarding any candidate signal if port allocation status is
- // already in completed state.
- if (data->complete() || data->error()) {
+ // already done with gathering.
+ if (!data->inprogress()) {
return;
}
+ // Mark that the port has a pairable candidate, either because we have a
+ // usable candidate from the port, or simply because the port is bound to the
+ // any address and therefore has no host candidate. This will trigger the port
+ // to start creating candidate pairs (connections) and issue connectivity
+ // checks. If port has already been marked as having a pairable candidate,
+ // do nothing here.
+ // Note: We should check whether any candidates may become ready after this
+ // because there we will check whether the candidate is generated by the ready
+ // ports, which may include this port.
+ bool pruned_port = false;
+ if (CandidatePairable(c, port) && !data->has_pairable_candidate()) {
+ data->set_has_pairable_candidate(true);
+
+ if (prune_turn_ports_ && port->Type() == RELAY_PORT_TYPE) {
+ pruned_port = PruneTurnPorts(port);
+ }
+ // If the current port is not pruned yet, SignalPortReady.
+ if (!data->pruned()) {
+ SignalPortReady(this, port);
+ }
+ }
+
ProtocolType pvalue;
bool candidate_protocol_enabled =
StringToProto(c.protocol().c_str(), &pvalue) &&
data->sequence()->ProtocolEnabled(pvalue);
- if (CheckCandidateFilter(c) && candidate_protocol_enabled) {
+ if (data->ready() && CheckCandidateFilter(c) && candidate_protocol_enabled) {
std::vector<Candidate> candidates;
candidates.push_back(SanitizeRelatedAddress(c));
SignalCandidatesReady(this, candidates);
}
- // Port has already been marked as having a pairable candidate.
- // Nothing to do here.
- if (data->has_pairable_candidate()) {
- return;
+ // If we have pruned any port, maybe need to signal port allocation done.
+ if (pruned_port) {
+ MaybeSignalCandidatesAllocationDone();
}
+}
- // Mark that the port has a pairable candidate, either because we have a
- // usable candidate from the port, or simply because the port is bound to the
- // any address and therefore has no host candidate. This will trigger the port
- // to start creating candidate pairs (connections) and issue connectivity
- // checks.
- if (CandidatePairable(c, port)) {
- data->set_has_pairable_candidate(true);
- SignalPortReady(this, port);
+Port* BasicPortAllocatorSession::GetBestTurnPortForNetwork(
+ const std::string& network_name) const {
+ Port* best_turn_port = nullptr;
+ for (const PortData& data : ports_) {
+ if (data.port()->Network()->name() == network_name &&
+ data.port()->Type() == RELAY_PORT_TYPE && data.ready() &&
+ (!best_turn_port || ComparePort(data.port(), best_turn_port) > 0)) {
+ best_turn_port = data.port();
+ }
+ }
+ return best_turn_port;
+}
+
+bool BasicPortAllocatorSession::PruneTurnPorts(Port* newly_pairable_turn_port) {
+ bool pruned_port = false;
+ // Note: We determine the same network based only on their network names. So
+ // if an IPv4 address and an IPv6 address have the same network name, they
+ // are considered the same network here.
+ const std::string& network_name = newly_pairable_turn_port->Network()->name();
+ Port* best_turn_port = GetBestTurnPortForNetwork(network_name);
+ // |port| is already in the list of ports, so the best port cannot be nullptr.
+ RTC_CHECK(best_turn_port != nullptr);
+
+ for (PortData& data : ports_) {
+ if (data.port()->Network()->name() == network_name &&
+ data.port()->Type() == RELAY_PORT_TYPE && !data.pruned() &&
+ ComparePort(data.port(), best_turn_port) < 0) {
+ data.set_pruned();
+ pruned_port = true;
+ if (data.port() != newly_pairable_turn_port) {
+ SignalPortPruned(this, data.port());
+ }
+ }
}
+ return pruned_port;
}
void BasicPortAllocatorSession::OnPortComplete(Port* port) {
@@ -607,7 +698,7 @@ void BasicPortAllocatorSession::OnPortComplete(Port* port) {
ASSERT(data != NULL);
// Ignore any late signals.
- if (data->complete() || data->error()) {
+ if (!data->inprogress()) {
return;
}
@@ -622,7 +713,7 @@ void BasicPortAllocatorSession::OnPortError(Port* port) {
PortData* data = FindPort(port);
ASSERT(data != NULL);
// We might have already given up on this port and stopped it.
- if (data->complete() || data->error()) {
+ if (!data->inprogress()) {
return;
}
@@ -1028,13 +1119,11 @@ void AllocationSequence::CreateRelayPorts() {
return;
}
- PortConfiguration::RelayList::const_iterator relay;
- for (relay = config_->relays.begin();
- relay != config_->relays.end(); ++relay) {
- if (relay->type == RELAY_GTURN) {
- CreateGturnPort(*relay);
- } else if (relay->type == RELAY_TURN) {
- CreateTurnPort(*relay);
+ for (RelayServerConfig& relay : config_->relays) {
+ if (relay.type == RELAY_GTURN) {
+ CreateGturnPort(relay);
+ } else if (relay.type == RELAY_TURN) {
+ CreateTurnPort(relay);
} else {
ASSERT(false);
}
« no previous file with comments | « webrtc/p2p/client/basicportallocator.h ('k') | webrtc/p2p/client/basicportallocator_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698