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

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: Add all tests and fix a bug to set port type 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
Index: webrtc/p2p/client/basicportallocator.cc
diff --git a/webrtc/p2p/client/basicportallocator.cc b/webrtc/p2p/client/basicportallocator.cc
index e39a44013cdcf4f5b4cf627e225c499afb1e1687..f60807869a63f852209176d7f9b29ba064827fff 100644
--- a/webrtc/p2p/client/basicportallocator.cc
+++ b/webrtc/p2p/client/basicportallocator.cc
@@ -47,6 +47,45 @@ const int PHASE_SSLTCP = 3;
const int kNumPhases = 4;
+enum class AddressFamily { UNSPEC, IPV4, IPV6 };
+
+AddressFamily ToAddressFamily(int ip_family) {
+ switch (ip_family) {
+ case AF_UNSPEC:
+ return AddressFamily::UNSPEC;
+ case AF_INET:
+ return AddressFamily::IPV4;
+ case AF_INET6:
+ return AddressFamily::IPV6;
+ default:
+ RTC_DCHECK(false);
+ return AddressFamily::UNSPEC;
+ }
+}
pthatcher1 2016/06/27 20:35:55 Is this just for sorting? If so, instead of makin
honghaiz3 2016/06/28 01:49:25 You are right. Make it return an integer.
+
+// Returns positive if a is better, negative if b is better, and 0 otherwise.
+int ComparePort(const cricket::Port* a, const cricket::Port* b) {
+ static constexpr int a_is_better = 1;
+ static constexpr int b_is_better = -1;
+ // Protocol type is defined as UDP = 0, TCP = 1, SSLTCP = 2.
+ if (a->GetProtocol() < b->GetProtocol()) {
+ return a_is_better;
+ }
+ if (a->GetProtocol() > b->GetProtocol()) {
+ return b_is_better;
+ }
+
+ AddressFamily a_family = ToAddressFamily(a->Network()->GetBestIP().family());
+ AddressFamily b_family = ToAddressFamily(b->Network()->GetBestIP().family());
+ if (a_family > b_family) {
+ return a_is_better;
+ }
+ if (a_family < b_family) {
+ return b_is_better;
+ }
+ return 0;
+}
+
} // namespace
namespace cricket {
@@ -74,7 +113,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 +140,7 @@ BasicPortAllocator::BasicPortAllocator(
turn_servers.push_back(config);
}
- SetConfiguration(stun_servers, turn_servers, 0);
+ SetConfiguration(stun_servers, turn_servers, 0, false);
Construct();
}
@@ -122,7 +161,8 @@ 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(),
+ disable_low_priority_turn_ports());
}
// BasicPortAllocatorSession
@@ -217,8 +257,10 @@ void BasicPortAllocatorSession::ClearGettingPorts() {
std::vector<PortInterface*> BasicPortAllocatorSession::ReadyPorts() const {
std::vector<PortInterface*> ret;
+ // Add all non-TURN ports.
for (const PortData& port : ports_) {
- if (port.has_pairable_candidate() && !port.error()) {
+ if (IsPortInUse(port.port()) && port.has_pairable_candidate() &&
+ !port.error()) {
ret.push_back(port.port());
}
}
@@ -228,6 +270,10 @@ std::vector<PortInterface*> BasicPortAllocatorSession::ReadyPorts() const {
std::vector<Candidate> BasicPortAllocatorSession::ReadyCandidates() const {
std::vector<Candidate> candidates;
for (const PortData& data : ports_) {
+ if (!IsPortInUse(data.port())) {
+ continue;
+ }
+
for (const Candidate& candidate : data.port()->Candidates()) {
if (!CheckCandidateFilter(candidate)) {
continue;
@@ -438,16 +484,14 @@ void BasicPortAllocatorSession::DoAllocate() {
bool done_signal_needed = false;
std::vector<rtc::Network*> networks;
GetNetworks(&networks);
+ turn_ports_in_use_by_network_names_.clear();
if (networks.empty()) {
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
@@ -573,6 +617,19 @@ void BasicPortAllocatorSession::OnCandidateReady(
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: Need to do MaybeSignalCandidateReady after this because we will
+ // check whether the candidate is generated by the port in use.
+ if (!data->has_pairable_candidate() && CandidatePairable(c, port)) {
+ data->set_has_pairable_candidate(true);
+ MaybeSignalPortReady(port);
pthatcher1 2016/06/27 20:35:55 If this is only called once, can we just inline it
honghaiz3 2016/06/28 01:49:25 A separate method will make it more readable here.
+ }
+
ProtocolType pvalue;
bool candidate_protocol_enabled =
StringToProto(c.protocol().c_str(), &pvalue) &&
@@ -581,26 +638,72 @@ void BasicPortAllocatorSession::OnCandidateReady(
if (CheckCandidateFilter(c) && candidate_protocol_enabled) {
std::vector<Candidate> candidates;
candidates.push_back(SanitizeRelatedAddress(c));
- SignalCandidatesReady(this, candidates);
+ MaybeSignalCandidatesReady(port, candidates);
pthatcher1 2016/06/27 20:35:54 Since this is only called once, can you inline it?
honghaiz3 2016/06/28 01:49:25 Done.
}
+}
- // Port has already been marked as having a pairable candidate.
- // Nothing to do here.
- if (data->has_pairable_candidate()) {
+void BasicPortAllocatorSession::MaybeSignalPortReady(Port* port) {
+ if (!allocator_->disable_low_priority_turn_ports() ||
+ port->Type() != RELAY_PORT_TYPE) {
+ SignalPortReady(this, port);
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 (CandidatePairable(c, port)) {
- data->set_has_pairable_candidate(true);
+ std::vector<Port*>& turn_ports =
+ turn_ports_in_use_by_network_names_[port->Network()->name()];
pthatcher1 2016/06/27 20:35:55 Shouldn't we do a find() just in case it's not in
honghaiz3 2016/06/28 01:49:25 If it is not in the map, we create a new vector an
+
+ bool use_port = true;
+ auto iter = turn_ports.begin();
+ while (iter != turn_ports.end()) {
+ int cmp = ComparePort(port, *iter);
+ if (cmp > 0) {
+ // The new port has higher precedence. Deprecate the existing port.
+ SignalPortDeprecated(this, *iter);
+ iter = turn_ports.erase(iter);
+ // TODO(honghaiz): Maybe also remove the candidates in the port.
+ } else {
+ ++iter;
+ if (cmp < 0) {
+ // If this new port has a lower precedence than any existing port, do
+ // not use it.
+ use_port = false;
+ }
+ }
+ }
pthatcher1 2016/06/27 20:35:54 Correct me if I'm wrong, but it looks like turn_po
honghaiz3 2016/06/28 01:49:25 You are right, although we have removed the map no
+ if (use_port) {
pthatcher1 2016/06/27 20:35:55 Actually, if we just store all ports in ports_ and
honghaiz3 2016/06/28 01:49:25 Done. Did not use std::max as it is not really muc
+ turn_ports.push_back(port);
SignalPortReady(this, port);
pthatcher1 2016/06/27 20:35:54 I think we need a better pair of names than Signal
honghaiz3 2016/06/28 01:49:25 SignalPortReady is used elsewhere by downstream co
}
}
+void BasicPortAllocatorSession::MaybeSignalCandidatesReady(
+ Port* port,
+ const std::vector<Candidate>& candidates) {
+ if (IsPortInUse(port)) {
+ SignalCandidatesReady(this, candidates);
+ }
+}
+
+bool BasicPortAllocatorSession::IsPortInUse(Port* port) const {
+ // If the port is not disabling low priority ports, every port is in use.
+ if (!allocator_->disable_low_priority_turn_ports()) {
+ return true;
+ }
+ // If it is not a turn port, it is in use.
+ if (port->Type() != RELAY_PORT_TYPE) {
+ return true;
+ }
+ // For TURN port, if it can be found in |turn_ports_in_use_by_network_name_|,
+ // it is in use.
+ const auto iter =
+ turn_ports_in_use_by_network_names_.find(port->Network()->name());
+ if (iter == turn_ports_in_use_by_network_names_.end()) {
+ return false;
+ }
+ const std::vector<Port*>& turn_ports = iter->second;
+ return std::find(turn_ports.begin(), turn_ports.end(), port) !=
+ turn_ports.end();
pthatcher1 2016/06/27 20:35:54 If we store all port in ports_ and just mark them
honghaiz3 2016/06/28 01:49:26 Done.
+}
+
void BasicPortAllocatorSession::OnPortComplete(Port* port) {
ASSERT(rtc::Thread::Current() == network_thread_);
PortData* data = FindPort(port);
@@ -1028,13 +1131,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);
}
@@ -1084,6 +1185,18 @@ void AllocationSequence::CreateTurnPort(const RelayServerConfig& config) {
continue;
}
+ // Do not create the port if the server address family is known and does
+ // not match the local ip address family.
+ int server_ip_family = relay_port->address.ipaddr().family();
+ int local_ip_family = network_->GetBestIP().family();
+ if (server_ip_family != AF_UNSPEC && server_ip_family != local_ip_family) {
+ LOG(LS_INFO) << "Server and local address families are not compatible. "
+ << "Server address: "
+ << relay_port->address.ipaddr().ToString()
+ << " Local address: " << network_->GetBestIP().ToString();
+ continue;
+ }
pthatcher1 2016/06/27 20:35:54 Should this be a separate CL? It seems like a bug
honghaiz3 2016/06/28 01:49:26 Done.
+
// Shared socket mode must be enabled only for UDP based ports. Hence
// don't pass shared socket for ports which will create TCP sockets.
// TODO(mallinath) - Enable shared socket mode for TURN ports. Disabled

Powered by Google App Engine
This is Rietveld 408576698