xref: /aosp_15_r20/external/webrtc/p2p/client/basic_port_allocator.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "p2p/client/basic_port_allocator.h"
12 
13 #include <algorithm>
14 #include <functional>
15 #include <memory>
16 #include <set>
17 #include <string>
18 #include <utility>
19 #include <vector>
20 
21 #include "absl/algorithm/container.h"
22 #include "absl/memory/memory.h"
23 #include "absl/strings/string_view.h"
24 #include "api/task_queue/pending_task_safety_flag.h"
25 #include "api/transport/field_trial_based_config.h"
26 #include "api/units/time_delta.h"
27 #include "p2p/base/basic_packet_socket_factory.h"
28 #include "p2p/base/port.h"
29 #include "p2p/base/stun_port.h"
30 #include "p2p/base/tcp_port.h"
31 #include "p2p/base/turn_port.h"
32 #include "p2p/base/udp_port.h"
33 #include "rtc_base/checks.h"
34 #include "rtc_base/experiments/field_trial_parser.h"
35 #include "rtc_base/helpers.h"
36 #include "rtc_base/logging.h"
37 #include "rtc_base/network_constants.h"
38 #include "rtc_base/strings/string_builder.h"
39 #include "rtc_base/trace_event.h"
40 #include "system_wrappers/include/metrics.h"
41 
42 namespace cricket {
43 namespace {
44 using ::rtc::CreateRandomId;
45 using ::webrtc::SafeTask;
46 using ::webrtc::TimeDelta;
47 
48 const int PHASE_UDP = 0;
49 const int PHASE_RELAY = 1;
50 const int PHASE_TCP = 2;
51 
52 const int kNumPhases = 3;
53 
54 // Gets protocol priority: UDP > TCP > SSLTCP == TLS.
GetProtocolPriority(cricket::ProtocolType protocol)55 int GetProtocolPriority(cricket::ProtocolType protocol) {
56   switch (protocol) {
57     case cricket::PROTO_UDP:
58       return 2;
59     case cricket::PROTO_TCP:
60       return 1;
61     case cricket::PROTO_SSLTCP:
62     case cricket::PROTO_TLS:
63       return 0;
64     default:
65       RTC_DCHECK_NOTREACHED();
66       return 0;
67   }
68 }
69 // Gets address family priority:  IPv6 > IPv4 > Unspecified.
GetAddressFamilyPriority(int ip_family)70 int GetAddressFamilyPriority(int ip_family) {
71   switch (ip_family) {
72     case AF_INET6:
73       return 2;
74     case AF_INET:
75       return 1;
76     default:
77       RTC_DCHECK_NOTREACHED();
78       return 0;
79   }
80 }
81 
82 // Returns positive if a is better, negative if b is better, and 0 otherwise.
ComparePort(const cricket::Port * a,const cricket::Port * b)83 int ComparePort(const cricket::Port* a, const cricket::Port* b) {
84   int a_protocol = GetProtocolPriority(a->GetProtocol());
85   int b_protocol = GetProtocolPriority(b->GetProtocol());
86   int cmp_protocol = a_protocol - b_protocol;
87   if (cmp_protocol != 0) {
88     return cmp_protocol;
89   }
90 
91   int a_family = GetAddressFamilyPriority(a->Network()->GetBestIP().family());
92   int b_family = GetAddressFamilyPriority(b->Network()->GetBestIP().family());
93   return a_family - b_family;
94 }
95 
96 struct NetworkFilter {
97   using Predicate = std::function<bool(const rtc::Network*)>;
NetworkFiltercricket::__anon5c8be1460111::NetworkFilter98   NetworkFilter(Predicate pred, absl::string_view description)
99       : predRemain(
100             [pred](const rtc::Network* network) { return !pred(network); }),
101         description(description) {}
102   Predicate predRemain;
103   const std::string description;
104 };
105 
FilterNetworks(std::vector<const rtc::Network * > * networks,NetworkFilter filter)106 void FilterNetworks(std::vector<const rtc::Network*>* networks,
107                     NetworkFilter filter) {
108   auto start_to_remove =
109       std::partition(networks->begin(), networks->end(), filter.predRemain);
110   if (start_to_remove == networks->end()) {
111     return;
112   }
113   RTC_LOG(LS_INFO) << "Filtered out " << filter.description << " networks:";
114   for (auto it = start_to_remove; it != networks->end(); ++it) {
115     RTC_LOG(LS_INFO) << (*it)->ToString();
116   }
117   networks->erase(start_to_remove, networks->end());
118 }
119 
IsAllowedByCandidateFilter(const Candidate & c,uint32_t filter)120 bool IsAllowedByCandidateFilter(const Candidate& c, uint32_t filter) {
121   // When binding to any address, before sending packets out, the getsockname
122   // returns all 0s, but after sending packets, it'll be the NIC used to
123   // send. All 0s is not a valid ICE candidate address and should be filtered
124   // out.
125   if (c.address().IsAnyIP()) {
126     return false;
127   }
128 
129   if (c.type() == RELAY_PORT_TYPE) {
130     return ((filter & CF_RELAY) != 0);
131   } else if (c.type() == STUN_PORT_TYPE) {
132     return ((filter & CF_REFLEXIVE) != 0);
133   } else if (c.type() == LOCAL_PORT_TYPE) {
134     if ((filter & CF_REFLEXIVE) && !c.address().IsPrivateIP()) {
135       // We allow host candidates if the filter allows server-reflexive
136       // candidates and the candidate is a public IP. Because we don't generate
137       // server-reflexive candidates if they have the same IP as the host
138       // candidate (i.e. when the host candidate is a public IP), filtering to
139       // only server-reflexive candidates won't work right when the host
140       // candidates have public IPs.
141       return true;
142     }
143 
144     return ((filter & CF_HOST) != 0);
145   }
146   return false;
147 }
148 
NetworksToString(const std::vector<const rtc::Network * > & networks)149 std::string NetworksToString(const std::vector<const rtc::Network*>& networks) {
150   rtc::StringBuilder ost;
151   for (auto n : networks) {
152     ost << n->name() << " ";
153   }
154   return ost.Release();
155 }
156 
IsDiversifyIpv6InterfacesEnabled(const webrtc::FieldTrialsView * field_trials)157 bool IsDiversifyIpv6InterfacesEnabled(
158     const webrtc::FieldTrialsView* field_trials) {
159   // webrtc:14334: Improve IPv6 network resolution and candidate creation
160   if (field_trials &&
161       field_trials->IsEnabled("WebRTC-IPv6NetworkResolutionFixes")) {
162     webrtc::FieldTrialParameter<bool> diversify_ipv6_interfaces(
163         "DiversifyIpv6Interfaces", false);
164     webrtc::ParseFieldTrial(
165         {&diversify_ipv6_interfaces},
166         field_trials->Lookup("WebRTC-IPv6NetworkResolutionFixes"));
167     return diversify_ipv6_interfaces;
168   }
169   return false;
170 }
171 
172 }  // namespace
173 
174 const uint32_t DISABLE_ALL_PHASES =
175     PORTALLOCATOR_DISABLE_UDP | PORTALLOCATOR_DISABLE_TCP |
176     PORTALLOCATOR_DISABLE_STUN | PORTALLOCATOR_DISABLE_RELAY;
177 
178 // BasicPortAllocator
BasicPortAllocator(rtc::NetworkManager * network_manager,rtc::PacketSocketFactory * socket_factory,webrtc::TurnCustomizer * customizer,RelayPortFactoryInterface * relay_port_factory,const webrtc::FieldTrialsView * field_trials)179 BasicPortAllocator::BasicPortAllocator(
180     rtc::NetworkManager* network_manager,
181     rtc::PacketSocketFactory* socket_factory,
182     webrtc::TurnCustomizer* customizer,
183     RelayPortFactoryInterface* relay_port_factory,
184     const webrtc::FieldTrialsView* field_trials)
185     : field_trials_(field_trials),
186       network_manager_(network_manager),
187       socket_factory_(socket_factory) {
188   Init(relay_port_factory);
189   RTC_DCHECK(relay_port_factory_ != nullptr);
190   RTC_DCHECK(network_manager_ != nullptr);
191   RTC_CHECK(socket_factory_ != nullptr);
192   SetConfiguration(ServerAddresses(), std::vector<RelayServerConfig>(), 0,
193                    webrtc::NO_PRUNE, customizer);
194 }
195 
BasicPortAllocator(rtc::NetworkManager * network_manager,std::unique_ptr<rtc::PacketSocketFactory> owned_socket_factory,const webrtc::FieldTrialsView * field_trials)196 BasicPortAllocator::BasicPortAllocator(
197     rtc::NetworkManager* network_manager,
198     std::unique_ptr<rtc::PacketSocketFactory> owned_socket_factory,
199     const webrtc::FieldTrialsView* field_trials)
200     : field_trials_(field_trials),
201       network_manager_(network_manager),
202       socket_factory_(std::move(owned_socket_factory)) {
203   Init(nullptr);
204   RTC_DCHECK(relay_port_factory_ != nullptr);
205   RTC_DCHECK(network_manager_ != nullptr);
206   RTC_CHECK(socket_factory_ != nullptr);
207 }
208 
BasicPortAllocator(rtc::NetworkManager * network_manager,std::unique_ptr<rtc::PacketSocketFactory> owned_socket_factory,const ServerAddresses & stun_servers,const webrtc::FieldTrialsView * field_trials)209 BasicPortAllocator::BasicPortAllocator(
210     rtc::NetworkManager* network_manager,
211     std::unique_ptr<rtc::PacketSocketFactory> owned_socket_factory,
212     const ServerAddresses& stun_servers,
213     const webrtc::FieldTrialsView* field_trials)
214     : field_trials_(field_trials),
215       network_manager_(network_manager),
216       socket_factory_(std::move(owned_socket_factory)) {
217   Init(nullptr);
218   RTC_DCHECK(relay_port_factory_ != nullptr);
219   RTC_DCHECK(network_manager_ != nullptr);
220   RTC_CHECK(socket_factory_ != nullptr);
221   SetConfiguration(stun_servers, std::vector<RelayServerConfig>(), 0,
222                    webrtc::NO_PRUNE, nullptr);
223 }
224 
BasicPortAllocator(rtc::NetworkManager * network_manager,rtc::PacketSocketFactory * socket_factory,const ServerAddresses & stun_servers,const webrtc::FieldTrialsView * field_trials)225 BasicPortAllocator::BasicPortAllocator(
226     rtc::NetworkManager* network_manager,
227     rtc::PacketSocketFactory* socket_factory,
228     const ServerAddresses& stun_servers,
229     const webrtc::FieldTrialsView* field_trials)
230     : field_trials_(field_trials),
231       network_manager_(network_manager),
232       socket_factory_(socket_factory) {
233   Init(nullptr);
234   RTC_DCHECK(relay_port_factory_ != nullptr);
235   RTC_DCHECK(network_manager_ != nullptr);
236   RTC_CHECK(socket_factory_ != nullptr);
237   SetConfiguration(stun_servers, std::vector<RelayServerConfig>(), 0,
238                    webrtc::NO_PRUNE, nullptr);
239 }
240 
OnIceRegathering(PortAllocatorSession * session,IceRegatheringReason reason)241 void BasicPortAllocator::OnIceRegathering(PortAllocatorSession* session,
242                                           IceRegatheringReason reason) {
243   // If the session has not been taken by an active channel, do not report the
244   // metric.
245   for (auto& allocator_session : pooled_sessions()) {
246     if (allocator_session.get() == session) {
247       return;
248     }
249   }
250 
251   RTC_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.IceRegatheringReason",
252                             static_cast<int>(reason),
253                             static_cast<int>(IceRegatheringReason::MAX_VALUE));
254 }
255 
~BasicPortAllocator()256 BasicPortAllocator::~BasicPortAllocator() {
257   CheckRunOnValidThreadIfInitialized();
258   // Our created port allocator sessions depend on us, so destroy our remaining
259   // pooled sessions before anything else.
260   DiscardCandidatePool();
261 }
262 
SetNetworkIgnoreMask(int network_ignore_mask)263 void BasicPortAllocator::SetNetworkIgnoreMask(int network_ignore_mask) {
264   // TODO(phoglund): implement support for other types than loopback.
265   // See https://code.google.com/p/webrtc/issues/detail?id=4288.
266   // Then remove set_network_ignore_list from NetworkManager.
267   CheckRunOnValidThreadIfInitialized();
268   network_ignore_mask_ = network_ignore_mask;
269 }
270 
GetNetworkIgnoreMask() const271 int BasicPortAllocator::GetNetworkIgnoreMask() const {
272   CheckRunOnValidThreadIfInitialized();
273   int mask = network_ignore_mask_;
274   switch (vpn_preference_) {
275     case webrtc::VpnPreference::kOnlyUseVpn:
276       mask |= ~static_cast<int>(rtc::ADAPTER_TYPE_VPN);
277       break;
278     case webrtc::VpnPreference::kNeverUseVpn:
279       mask |= static_cast<int>(rtc::ADAPTER_TYPE_VPN);
280       break;
281     default:
282       break;
283   }
284   return mask;
285 }
286 
CreateSessionInternal(absl::string_view content_name,int component,absl::string_view ice_ufrag,absl::string_view ice_pwd)287 PortAllocatorSession* BasicPortAllocator::CreateSessionInternal(
288     absl::string_view content_name,
289     int component,
290     absl::string_view ice_ufrag,
291     absl::string_view ice_pwd) {
292   CheckRunOnValidThreadAndInitialized();
293   PortAllocatorSession* session = new BasicPortAllocatorSession(
294       this, std::string(content_name), component, std::string(ice_ufrag),
295       std::string(ice_pwd));
296   session->SignalIceRegathering.connect(this,
297                                         &BasicPortAllocator::OnIceRegathering);
298   return session;
299 }
300 
AddTurnServerForTesting(const RelayServerConfig & turn_server)301 void BasicPortAllocator::AddTurnServerForTesting(
302     const RelayServerConfig& turn_server) {
303   CheckRunOnValidThreadAndInitialized();
304   std::vector<RelayServerConfig> new_turn_servers = turn_servers();
305   new_turn_servers.push_back(turn_server);
306   SetConfiguration(stun_servers(), new_turn_servers, candidate_pool_size(),
307                    turn_port_prune_policy(), turn_customizer());
308 }
309 
Init(RelayPortFactoryInterface * relay_port_factory)310 void BasicPortAllocator::Init(RelayPortFactoryInterface* relay_port_factory) {
311   if (relay_port_factory != nullptr) {
312     relay_port_factory_ = relay_port_factory;
313   } else {
314     default_relay_port_factory_.reset(new TurnPortFactory());
315     relay_port_factory_ = default_relay_port_factory_.get();
316   }
317 }
318 
319 // BasicPortAllocatorSession
BasicPortAllocatorSession(BasicPortAllocator * allocator,absl::string_view content_name,int component,absl::string_view ice_ufrag,absl::string_view ice_pwd)320 BasicPortAllocatorSession::BasicPortAllocatorSession(
321     BasicPortAllocator* allocator,
322     absl::string_view content_name,
323     int component,
324     absl::string_view ice_ufrag,
325     absl::string_view ice_pwd)
326     : PortAllocatorSession(content_name,
327                            component,
328                            ice_ufrag,
329                            ice_pwd,
330                            allocator->flags()),
331       allocator_(allocator),
332       network_thread_(rtc::Thread::Current()),
333       socket_factory_(allocator->socket_factory()),
334       allocation_started_(false),
335       network_manager_started_(false),
336       allocation_sequences_created_(false),
337       turn_port_prune_policy_(allocator->turn_port_prune_policy()) {
338   TRACE_EVENT0("webrtc",
339                "BasicPortAllocatorSession::BasicPortAllocatorSession");
340   allocator_->network_manager()->SignalNetworksChanged.connect(
341       this, &BasicPortAllocatorSession::OnNetworksChanged);
342   allocator_->network_manager()->StartUpdating();
343 }
344 
~BasicPortAllocatorSession()345 BasicPortAllocatorSession::~BasicPortAllocatorSession() {
346   TRACE_EVENT0("webrtc",
347                "BasicPortAllocatorSession::~BasicPortAllocatorSession");
348   RTC_DCHECK_RUN_ON(network_thread_);
349   allocator_->network_manager()->StopUpdating();
350 
351   for (uint32_t i = 0; i < sequences_.size(); ++i) {
352     // AllocationSequence should clear it's map entry for turn ports before
353     // ports are destroyed.
354     sequences_[i]->Clear();
355   }
356 
357   std::vector<PortData>::iterator it;
358   for (it = ports_.begin(); it != ports_.end(); it++)
359     delete it->port();
360 
361   configs_.clear();
362 
363   for (uint32_t i = 0; i < sequences_.size(); ++i)
364     delete sequences_[i];
365 }
366 
allocator()367 BasicPortAllocator* BasicPortAllocatorSession::allocator() {
368   RTC_DCHECK_RUN_ON(network_thread_);
369   return allocator_;
370 }
371 
SetCandidateFilter(uint32_t filter)372 void BasicPortAllocatorSession::SetCandidateFilter(uint32_t filter) {
373   RTC_DCHECK_RUN_ON(network_thread_);
374   if (filter == candidate_filter_) {
375     return;
376   }
377   uint32_t prev_filter = candidate_filter_;
378   candidate_filter_ = filter;
379   for (PortData& port_data : ports_) {
380     if (port_data.error() || port_data.pruned()) {
381       continue;
382     }
383     PortData::State cur_state = port_data.state();
384     bool found_signalable_candidate = false;
385     bool found_pairable_candidate = false;
386     cricket::Port* port = port_data.port();
387     for (const auto& c : port->Candidates()) {
388       if (!IsStopped() && !IsAllowedByCandidateFilter(c, prev_filter) &&
389           IsAllowedByCandidateFilter(c, filter)) {
390         // This candidate was not signaled because of not matching the previous
391         // filter (see OnCandidateReady below). Let the Port to fire the signal
392         // again.
393         //
394         // Note that
395         //  1) we would need the Port to enter the state of in-progress of
396         //     gathering to have candidates signaled;
397         //
398         //  2) firing the signal would also let the session set the port ready
399         //     if needed, so that we could form candidate pairs with candidates
400         //     from this port;
401         //
402         //  *  See again OnCandidateReady below for 1) and 2).
403         //
404         //  3) we only try to resurface candidates if we have not stopped
405         //     getting ports, which is always true for the continual gathering.
406         if (!found_signalable_candidate) {
407           found_signalable_candidate = true;
408           port_data.set_state(PortData::STATE_INPROGRESS);
409         }
410         port->SignalCandidateReady(port, c);
411       }
412 
413       if (CandidatePairable(c, port)) {
414         found_pairable_candidate = true;
415       }
416     }
417     // Restore the previous state.
418     port_data.set_state(cur_state);
419     // Setting a filter may cause a ready port to become non-ready
420     // if it no longer has any pairable candidates.
421     //
422     // Note that we only set for the negative case here, since a port would be
423     // set to have pairable candidates when it signals a ready candidate, which
424     // requires the port is still in the progress of gathering/surfacing
425     // candidates, and would be done in the firing of the signal above.
426     if (!found_pairable_candidate) {
427       port_data.set_has_pairable_candidate(false);
428     }
429   }
430 }
431 
StartGettingPorts()432 void BasicPortAllocatorSession::StartGettingPorts() {
433   RTC_DCHECK_RUN_ON(network_thread_);
434   state_ = SessionState::GATHERING;
435 
436   network_thread_->PostTask(
437       SafeTask(network_safety_.flag(), [this] { GetPortConfigurations(); }));
438 
439   RTC_LOG(LS_INFO) << "Start getting ports with turn_port_prune_policy "
440                    << turn_port_prune_policy_;
441 }
442 
StopGettingPorts()443 void BasicPortAllocatorSession::StopGettingPorts() {
444   RTC_DCHECK_RUN_ON(network_thread_);
445   ClearGettingPorts();
446   // Note: this must be called after ClearGettingPorts because both may set the
447   // session state and we should set the state to STOPPED.
448   state_ = SessionState::STOPPED;
449 }
450 
ClearGettingPorts()451 void BasicPortAllocatorSession::ClearGettingPorts() {
452   RTC_DCHECK_RUN_ON(network_thread_);
453   ++allocation_epoch_;
454   for (uint32_t i = 0; i < sequences_.size(); ++i) {
455     sequences_[i]->Stop();
456   }
457   network_thread_->PostTask(
458       SafeTask(network_safety_.flag(), [this] { OnConfigStop(); }));
459   state_ = SessionState::CLEARED;
460 }
461 
IsGettingPorts()462 bool BasicPortAllocatorSession::IsGettingPorts() {
463   RTC_DCHECK_RUN_ON(network_thread_);
464   return state_ == SessionState::GATHERING;
465 }
466 
IsCleared() const467 bool BasicPortAllocatorSession::IsCleared() const {
468   RTC_DCHECK_RUN_ON(network_thread_);
469   return state_ == SessionState::CLEARED;
470 }
471 
IsStopped() const472 bool BasicPortAllocatorSession::IsStopped() const {
473   RTC_DCHECK_RUN_ON(network_thread_);
474   return state_ == SessionState::STOPPED;
475 }
476 
477 std::vector<const rtc::Network*>
GetFailedNetworks()478 BasicPortAllocatorSession::GetFailedNetworks() {
479   RTC_DCHECK_RUN_ON(network_thread_);
480 
481   std::vector<const rtc::Network*> networks = GetNetworks();
482   // A network interface may have both IPv4 and IPv6 networks. Only if
483   // neither of the networks has any connections, the network interface
484   // is considered failed and need to be regathered on.
485   std::set<std::string> networks_with_connection;
486   for (const PortData& data : ports_) {
487     Port* port = data.port();
488     if (!port->connections().empty()) {
489       networks_with_connection.insert(port->Network()->name());
490     }
491   }
492 
493   networks.erase(
494       std::remove_if(networks.begin(), networks.end(),
495                      [networks_with_connection](const rtc::Network* network) {
496                        // If a network does not have any connection, it is
497                        // considered failed.
498                        return networks_with_connection.find(network->name()) !=
499                               networks_with_connection.end();
500                      }),
501       networks.end());
502   return networks;
503 }
504 
RegatherOnFailedNetworks()505 void BasicPortAllocatorSession::RegatherOnFailedNetworks() {
506   RTC_DCHECK_RUN_ON(network_thread_);
507 
508   // Find the list of networks that have no connection.
509   std::vector<const rtc::Network*> failed_networks = GetFailedNetworks();
510   if (failed_networks.empty()) {
511     return;
512   }
513 
514   RTC_LOG(LS_INFO) << "Regather candidates on failed networks";
515 
516   // Mark a sequence as "network failed" if its network is in the list of failed
517   // networks, so that it won't be considered as equivalent when the session
518   // regathers ports and candidates.
519   for (AllocationSequence* sequence : sequences_) {
520     if (!sequence->network_failed() &&
521         absl::c_linear_search(failed_networks, sequence->network())) {
522       sequence->set_network_failed();
523     }
524   }
525 
526   bool disable_equivalent_phases = true;
527   Regather(failed_networks, disable_equivalent_phases,
528            IceRegatheringReason::NETWORK_FAILURE);
529 }
530 
Regather(const std::vector<const rtc::Network * > & networks,bool disable_equivalent_phases,IceRegatheringReason reason)531 void BasicPortAllocatorSession::Regather(
532     const std::vector<const rtc::Network*>& networks,
533     bool disable_equivalent_phases,
534     IceRegatheringReason reason) {
535   RTC_DCHECK_RUN_ON(network_thread_);
536   // Remove ports from being used locally and send signaling to remove
537   // the candidates on the remote side.
538   std::vector<PortData*> ports_to_prune = GetUnprunedPorts(networks);
539   if (!ports_to_prune.empty()) {
540     RTC_LOG(LS_INFO) << "Prune " << ports_to_prune.size() << " ports";
541     PrunePortsAndRemoveCandidates(ports_to_prune);
542   }
543 
544   if (allocation_started_ && network_manager_started_ && !IsStopped()) {
545     SignalIceRegathering(this, reason);
546 
547     DoAllocate(disable_equivalent_phases);
548   }
549 }
550 
GetCandidateStatsFromReadyPorts(CandidateStatsList * candidate_stats_list) const551 void BasicPortAllocatorSession::GetCandidateStatsFromReadyPorts(
552     CandidateStatsList* candidate_stats_list) const {
553   auto ports = ReadyPorts();
554   for (auto* port : ports) {
555     auto candidates = port->Candidates();
556     for (const auto& candidate : candidates) {
557       absl::optional<StunStats> stun_stats;
558       port->GetStunStats(&stun_stats);
559       CandidateStats candidate_stats(allocator_->SanitizeCandidate(candidate),
560                                      std::move(stun_stats));
561       candidate_stats_list->push_back(std::move(candidate_stats));
562     }
563   }
564 }
565 
SetStunKeepaliveIntervalForReadyPorts(const absl::optional<int> & stun_keepalive_interval)566 void BasicPortAllocatorSession::SetStunKeepaliveIntervalForReadyPorts(
567     const absl::optional<int>& stun_keepalive_interval) {
568   RTC_DCHECK_RUN_ON(network_thread_);
569   auto ports = ReadyPorts();
570   for (PortInterface* port : ports) {
571     // The port type and protocol can be used to identify different subclasses
572     // of Port in the current implementation. Note that a TCPPort has the type
573     // LOCAL_PORT_TYPE but uses the protocol PROTO_TCP.
574     if (port->Type() == STUN_PORT_TYPE ||
575         (port->Type() == LOCAL_PORT_TYPE && port->GetProtocol() == PROTO_UDP)) {
576       static_cast<UDPPort*>(port)->set_stun_keepalive_delay(
577           stun_keepalive_interval);
578     }
579   }
580 }
581 
ReadyPorts() const582 std::vector<PortInterface*> BasicPortAllocatorSession::ReadyPorts() const {
583   RTC_DCHECK_RUN_ON(network_thread_);
584   std::vector<PortInterface*> ret;
585   for (const PortData& data : ports_) {
586     if (data.ready()) {
587       ret.push_back(data.port());
588     }
589   }
590   return ret;
591 }
592 
ReadyCandidates() const593 std::vector<Candidate> BasicPortAllocatorSession::ReadyCandidates() const {
594   RTC_DCHECK_RUN_ON(network_thread_);
595   std::vector<Candidate> candidates;
596   for (const PortData& data : ports_) {
597     if (!data.ready()) {
598       continue;
599     }
600     GetCandidatesFromPort(data, &candidates);
601   }
602   return candidates;
603 }
604 
GetCandidatesFromPort(const PortData & data,std::vector<Candidate> * candidates) const605 void BasicPortAllocatorSession::GetCandidatesFromPort(
606     const PortData& data,
607     std::vector<Candidate>* candidates) const {
608   RTC_DCHECK_RUN_ON(network_thread_);
609   RTC_CHECK(candidates != nullptr);
610   for (const Candidate& candidate : data.port()->Candidates()) {
611     if (!CheckCandidateFilter(candidate)) {
612       continue;
613     }
614     candidates->push_back(allocator_->SanitizeCandidate(candidate));
615   }
616 }
617 
MdnsObfuscationEnabled() const618 bool BasicPortAllocator::MdnsObfuscationEnabled() const {
619   return network_manager()->GetMdnsResponder() != nullptr;
620 }
621 
CandidatesAllocationDone() const622 bool BasicPortAllocatorSession::CandidatesAllocationDone() const {
623   RTC_DCHECK_RUN_ON(network_thread_);
624   // Done only if all required AllocationSequence objects
625   // are created.
626   if (!allocation_sequences_created_) {
627     return false;
628   }
629 
630   // Check that all port allocation sequences are complete (not running).
631   if (absl::c_any_of(sequences_, [](const AllocationSequence* sequence) {
632         return sequence->state() == AllocationSequence::kRunning;
633       })) {
634     return false;
635   }
636 
637   // If all allocated ports are no longer gathering, session must have got all
638   // expected candidates. Session will trigger candidates allocation complete
639   // signal.
640   return absl::c_none_of(
641       ports_, [](const PortData& port) { return port.inprogress(); });
642 }
643 
UpdateIceParametersInternal()644 void BasicPortAllocatorSession::UpdateIceParametersInternal() {
645   RTC_DCHECK_RUN_ON(network_thread_);
646   for (PortData& port : ports_) {
647     port.port()->set_content_name(content_name());
648     port.port()->SetIceParameters(component(), ice_ufrag(), ice_pwd());
649   }
650 }
651 
GetPortConfigurations()652 void BasicPortAllocatorSession::GetPortConfigurations() {
653   RTC_DCHECK_RUN_ON(network_thread_);
654 
655   auto config = std::make_unique<PortConfiguration>(
656       allocator_->stun_servers(), username(), password(),
657       allocator()->field_trials());
658 
659   for (const RelayServerConfig& turn_server : allocator_->turn_servers()) {
660     config->AddRelay(turn_server);
661   }
662   ConfigReady(std::move(config));
663 }
664 
ConfigReady(PortConfiguration * config)665 void BasicPortAllocatorSession::ConfigReady(PortConfiguration* config) {
666   RTC_DCHECK_RUN_ON(network_thread_);
667   ConfigReady(absl::WrapUnique(config));
668 }
669 
ConfigReady(std::unique_ptr<PortConfiguration> config)670 void BasicPortAllocatorSession::ConfigReady(
671     std::unique_ptr<PortConfiguration> config) {
672   RTC_DCHECK_RUN_ON(network_thread_);
673   network_thread_->PostTask(SafeTask(
674       network_safety_.flag(), [this, config = std::move(config)]() mutable {
675         OnConfigReady(std::move(config));
676       }));
677 }
678 
679 // Adds a configuration to the list.
OnConfigReady(std::unique_ptr<PortConfiguration> config)680 void BasicPortAllocatorSession::OnConfigReady(
681     std::unique_ptr<PortConfiguration> config) {
682   RTC_DCHECK_RUN_ON(network_thread_);
683   if (config)
684     configs_.push_back(std::move(config));
685 
686   AllocatePorts();
687 }
688 
OnConfigStop()689 void BasicPortAllocatorSession::OnConfigStop() {
690   RTC_DCHECK_RUN_ON(network_thread_);
691 
692   // If any of the allocated ports have not completed the candidates allocation,
693   // mark those as error. Since session doesn't need any new candidates
694   // at this stage of the allocation, it's safe to discard any new candidates.
695   bool send_signal = false;
696   for (std::vector<PortData>::iterator it = ports_.begin(); it != ports_.end();
697        ++it) {
698     if (it->inprogress()) {
699       // Updating port state to error, which didn't finish allocating candidates
700       // yet.
701       it->set_state(PortData::STATE_ERROR);
702       send_signal = true;
703     }
704   }
705 
706   // Did we stop any running sequences?
707   for (std::vector<AllocationSequence*>::iterator it = sequences_.begin();
708        it != sequences_.end() && !send_signal; ++it) {
709     if ((*it)->state() == AllocationSequence::kStopped) {
710       send_signal = true;
711     }
712   }
713 
714   // If we stopped anything that was running, send a done signal now.
715   if (send_signal) {
716     MaybeSignalCandidatesAllocationDone();
717   }
718 }
719 
AllocatePorts()720 void BasicPortAllocatorSession::AllocatePorts() {
721   RTC_DCHECK_RUN_ON(network_thread_);
722   network_thread_->PostTask(SafeTask(
723       network_safety_.flag(), [this, allocation_epoch = allocation_epoch_] {
724         OnAllocate(allocation_epoch);
725       }));
726 }
727 
OnAllocate(int allocation_epoch)728 void BasicPortAllocatorSession::OnAllocate(int allocation_epoch) {
729   RTC_DCHECK_RUN_ON(network_thread_);
730   if (allocation_epoch != allocation_epoch_)
731     return;
732 
733   if (network_manager_started_ && !IsStopped()) {
734     bool disable_equivalent_phases = true;
735     DoAllocate(disable_equivalent_phases);
736   }
737 
738   allocation_started_ = true;
739 }
740 
GetNetworks()741 std::vector<const rtc::Network*> BasicPortAllocatorSession::GetNetworks() {
742   RTC_DCHECK_RUN_ON(network_thread_);
743   std::vector<const rtc::Network*> networks;
744   rtc::NetworkManager* network_manager = allocator_->network_manager();
745   RTC_DCHECK(network_manager != nullptr);
746   // If the network permission state is BLOCKED, we just act as if the flag has
747   // been passed in.
748   if (network_manager->enumeration_permission() ==
749       rtc::NetworkManager::ENUMERATION_BLOCKED) {
750     set_flags(flags() | PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION);
751   }
752   // If the adapter enumeration is disabled, we'll just bind to any address
753   // instead of specific NIC. This is to ensure the same routing for http
754   // traffic by OS is also used here to avoid any local or public IP leakage
755   // during stun process.
756   if (flags() & PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION) {
757     networks = network_manager->GetAnyAddressNetworks();
758   } else {
759     networks = network_manager->GetNetworks();
760     // If network enumeration fails, use the ANY address as a fallback, so we
761     // can at least try gathering candidates using the default route chosen by
762     // the OS. Or, if the PORTALLOCATOR_ENABLE_ANY_ADDRESS_PORTS flag is
763     // set, we'll use ANY address candidates either way.
764     if (networks.empty() ||
765         (flags() & PORTALLOCATOR_ENABLE_ANY_ADDRESS_PORTS)) {
766       std::vector<const rtc::Network*> any_address_networks =
767           network_manager->GetAnyAddressNetworks();
768       networks.insert(networks.end(), any_address_networks.begin(),
769                       any_address_networks.end());
770     }
771   }
772   // Filter out link-local networks if needed.
773   if (flags() & PORTALLOCATOR_DISABLE_LINK_LOCAL_NETWORKS) {
774     NetworkFilter link_local_filter(
775         [](const rtc::Network* network) {
776           return IPIsLinkLocal(network->prefix());
777         },
778         "link-local");
779     FilterNetworks(&networks, link_local_filter);
780   }
781   // Do some more filtering, depending on the network ignore mask and "disable
782   // costly networks" flag.
783   NetworkFilter ignored_filter(
784       [this](const rtc::Network* network) {
785         return allocator_->GetNetworkIgnoreMask() & network->type();
786       },
787       "ignored");
788   FilterNetworks(&networks, ignored_filter);
789   if (flags() & PORTALLOCATOR_DISABLE_COSTLY_NETWORKS) {
790     uint16_t lowest_cost = rtc::kNetworkCostMax;
791     for (const rtc::Network* network : networks) {
792       // Don't determine the lowest cost from a link-local network.
793       // On iOS, a device connected to the computer will get a link-local
794       // network for communicating with the computer, however this network can't
795       // be used to connect to a peer outside the network.
796       if (rtc::IPIsLinkLocal(network->GetBestIP())) {
797         continue;
798       }
799       lowest_cost = std::min<uint16_t>(
800           lowest_cost, network->GetCost(*allocator()->field_trials()));
801     }
802     NetworkFilter costly_filter(
803         [lowest_cost, this](const rtc::Network* network) {
804           return network->GetCost(*allocator()->field_trials()) >
805                  lowest_cost + rtc::kNetworkCostLow;
806         },
807         "costly");
808     FilterNetworks(&networks, costly_filter);
809   }
810 
811   // Lastly, if we have a limit for the number of IPv6 network interfaces (by
812   // default, it's 5), remove networks to ensure that limit is satisfied.
813   //
814   // TODO(deadbeef): Instead of just taking the first N arbitrary IPv6
815   // networks, we could try to choose a set that's "most likely to work". It's
816   // hard to define what that means though; it's not just "lowest cost".
817   // Alternatively, we could just focus on making our ICE pinging logic smarter
818   // such that this filtering isn't necessary in the first place.
819   const webrtc::FieldTrialsView* field_trials = allocator_->field_trials();
820   if (IsDiversifyIpv6InterfacesEnabled(field_trials)) {
821     std::vector<const rtc::Network*> ipv6_networks;
822     for (auto it = networks.begin(); it != networks.end();) {
823       if ((*it)->prefix().family() == AF_INET6) {
824         ipv6_networks.push_back(*it);
825         it = networks.erase(it);
826         continue;
827       }
828       ++it;
829     }
830     ipv6_networks =
831         SelectIPv6Networks(ipv6_networks, allocator_->max_ipv6_networks());
832     networks.insert(networks.end(), ipv6_networks.begin(), ipv6_networks.end());
833   } else {
834     int ipv6_networks = 0;
835     for (auto it = networks.begin(); it != networks.end();) {
836       if ((*it)->prefix().family() == AF_INET6) {
837         if (ipv6_networks >= allocator_->max_ipv6_networks()) {
838           it = networks.erase(it);
839           continue;
840         } else {
841           ++ipv6_networks;
842         }
843       }
844       ++it;
845     }
846   }
847   return networks;
848 }
849 
SelectIPv6Networks(std::vector<const rtc::Network * > & all_ipv6_networks,int max_ipv6_networks)850 std::vector<const rtc::Network*> BasicPortAllocatorSession::SelectIPv6Networks(
851     std::vector<const rtc::Network*>& all_ipv6_networks,
852     int max_ipv6_networks) {
853   if (static_cast<int>(all_ipv6_networks.size()) <= max_ipv6_networks) {
854     return all_ipv6_networks;
855   }
856   // Adapter types are placed in priority order. Cellular type is an alias of
857   // cellular, 2G..5G types.
858   std::vector<rtc::AdapterType> adapter_types = {
859       rtc::ADAPTER_TYPE_ETHERNET, rtc::ADAPTER_TYPE_LOOPBACK,
860       rtc::ADAPTER_TYPE_WIFI,     rtc::ADAPTER_TYPE_CELLULAR,
861       rtc::ADAPTER_TYPE_VPN,      rtc::ADAPTER_TYPE_UNKNOWN,
862       rtc::ADAPTER_TYPE_ANY};
863   int adapter_types_cnt = adapter_types.size();
864   std::vector<const rtc::Network*> selected_networks;
865   int adapter_types_pos = 0;
866 
867   while (static_cast<int>(selected_networks.size()) < max_ipv6_networks &&
868          adapter_types_pos < adapter_types_cnt * max_ipv6_networks) {
869     int network_pos = 0;
870     while (network_pos < static_cast<int>(all_ipv6_networks.size())) {
871       if (adapter_types[adapter_types_pos % adapter_types_cnt] ==
872               all_ipv6_networks[network_pos]->type() ||
873           (adapter_types[adapter_types_pos % adapter_types_cnt] ==
874                rtc::ADAPTER_TYPE_CELLULAR &&
875            all_ipv6_networks[network_pos]->IsCellular())) {
876         selected_networks.push_back(all_ipv6_networks[network_pos]);
877         all_ipv6_networks.erase(all_ipv6_networks.begin() + network_pos);
878         break;
879       }
880       network_pos++;
881     }
882     adapter_types_pos++;
883   }
884 
885   return selected_networks;
886 }
887 
888 // For each network, see if we have a sequence that covers it already.  If not,
889 // create a new sequence to create the appropriate ports.
DoAllocate(bool disable_equivalent)890 void BasicPortAllocatorSession::DoAllocate(bool disable_equivalent) {
891   RTC_DCHECK_RUN_ON(network_thread_);
892   bool done_signal_needed = false;
893   std::vector<const rtc::Network*> networks = GetNetworks();
894   if (networks.empty()) {
895     RTC_LOG(LS_WARNING)
896         << "Machine has no networks; no ports will be allocated";
897     done_signal_needed = true;
898   } else {
899     RTC_LOG(LS_INFO) << "Allocate ports on " << NetworksToString(networks);
900     PortConfiguration* config =
901         configs_.empty() ? nullptr : configs_.back().get();
902     for (uint32_t i = 0; i < networks.size(); ++i) {
903       uint32_t sequence_flags = flags();
904       if ((sequence_flags & DISABLE_ALL_PHASES) == DISABLE_ALL_PHASES) {
905         // If all the ports are disabled we should just fire the allocation
906         // done event and return.
907         done_signal_needed = true;
908         break;
909       }
910 
911       if (!config || config->relays.empty()) {
912         // No relay ports specified in this config.
913         sequence_flags |= PORTALLOCATOR_DISABLE_RELAY;
914       }
915 
916       if (!(sequence_flags & PORTALLOCATOR_ENABLE_IPV6) &&
917           networks[i]->GetBestIP().family() == AF_INET6) {
918         // Skip IPv6 networks unless the flag's been set.
919         continue;
920       }
921 
922       if (!(sequence_flags & PORTALLOCATOR_ENABLE_IPV6_ON_WIFI) &&
923           networks[i]->GetBestIP().family() == AF_INET6 &&
924           networks[i]->type() == rtc::ADAPTER_TYPE_WIFI) {
925         // Skip IPv6 Wi-Fi networks unless the flag's been set.
926         continue;
927       }
928 
929       if (disable_equivalent) {
930         // Disable phases that would only create ports equivalent to
931         // ones that we have already made.
932         DisableEquivalentPhases(networks[i], config, &sequence_flags);
933 
934         if ((sequence_flags & DISABLE_ALL_PHASES) == DISABLE_ALL_PHASES) {
935           // New AllocationSequence would have nothing to do, so don't make it.
936           continue;
937         }
938       }
939 
940       AllocationSequence* sequence =
941           new AllocationSequence(this, networks[i], config, sequence_flags,
942                                  [this, safety_flag = network_safety_.flag()] {
943                                    if (safety_flag->alive())
944                                      OnPortAllocationComplete();
945                                  });
946       sequence->Init();
947       sequence->Start();
948       sequences_.push_back(sequence);
949       done_signal_needed = true;
950     }
951   }
952   if (done_signal_needed) {
953     network_thread_->PostTask(SafeTask(network_safety_.flag(), [this] {
954       OnAllocationSequenceObjectsCreated();
955     }));
956   }
957 }
958 
OnNetworksChanged()959 void BasicPortAllocatorSession::OnNetworksChanged() {
960   RTC_DCHECK_RUN_ON(network_thread_);
961   std::vector<const rtc::Network*> networks = GetNetworks();
962   std::vector<const rtc::Network*> failed_networks;
963   for (AllocationSequence* sequence : sequences_) {
964     // Mark the sequence as "network failed" if its network is not in
965     // `networks`.
966     if (!sequence->network_failed() &&
967         !absl::c_linear_search(networks, sequence->network())) {
968       sequence->OnNetworkFailed();
969       failed_networks.push_back(sequence->network());
970     }
971   }
972   std::vector<PortData*> ports_to_prune = GetUnprunedPorts(failed_networks);
973   if (!ports_to_prune.empty()) {
974     RTC_LOG(LS_INFO) << "Prune " << ports_to_prune.size()
975                      << " ports because their networks were gone";
976     PrunePortsAndRemoveCandidates(ports_to_prune);
977   }
978 
979   if (allocation_started_ && !IsStopped()) {
980     if (network_manager_started_) {
981       // If the network manager has started, it must be regathering.
982       SignalIceRegathering(this, IceRegatheringReason::NETWORK_CHANGE);
983     }
984     bool disable_equivalent_phases = true;
985     DoAllocate(disable_equivalent_phases);
986   }
987 
988   if (!network_manager_started_) {
989     RTC_LOG(LS_INFO) << "Network manager has started";
990     network_manager_started_ = true;
991   }
992 }
993 
DisableEquivalentPhases(const rtc::Network * network,PortConfiguration * config,uint32_t * flags)994 void BasicPortAllocatorSession::DisableEquivalentPhases(
995     const rtc::Network* network,
996     PortConfiguration* config,
997     uint32_t* flags) {
998   RTC_DCHECK_RUN_ON(network_thread_);
999   for (uint32_t i = 0; i < sequences_.size() &&
1000                        (*flags & DISABLE_ALL_PHASES) != DISABLE_ALL_PHASES;
1001        ++i) {
1002     sequences_[i]->DisableEquivalentPhases(network, config, flags);
1003   }
1004 }
1005 
AddAllocatedPort(Port * port,AllocationSequence * seq)1006 void BasicPortAllocatorSession::AddAllocatedPort(Port* port,
1007                                                  AllocationSequence* seq) {
1008   RTC_DCHECK_RUN_ON(network_thread_);
1009   if (!port)
1010     return;
1011 
1012   RTC_LOG(LS_INFO) << "Adding allocated port for " << content_name();
1013   port->set_content_name(content_name());
1014   port->set_component(component());
1015   port->set_generation(generation());
1016   if (allocator_->proxy().type != rtc::PROXY_NONE)
1017     port->set_proxy(allocator_->user_agent(), allocator_->proxy());
1018   port->set_send_retransmit_count_attribute(
1019       (flags() & PORTALLOCATOR_ENABLE_STUN_RETRANSMIT_ATTRIBUTE) != 0);
1020 
1021   PortData data(port, seq);
1022   ports_.push_back(data);
1023 
1024   port->SignalCandidateReady.connect(
1025       this, &BasicPortAllocatorSession::OnCandidateReady);
1026   port->SignalCandidateError.connect(
1027       this, &BasicPortAllocatorSession::OnCandidateError);
1028   port->SignalPortComplete.connect(this,
1029                                    &BasicPortAllocatorSession::OnPortComplete);
1030   port->SubscribePortDestroyed(
1031       [this](PortInterface* port) { OnPortDestroyed(port); });
1032 
1033   port->SignalPortError.connect(this, &BasicPortAllocatorSession::OnPortError);
1034   RTC_LOG(LS_INFO) << port->ToString() << ": Added port to allocator";
1035 
1036   port->PrepareAddress();
1037 }
1038 
OnAllocationSequenceObjectsCreated()1039 void BasicPortAllocatorSession::OnAllocationSequenceObjectsCreated() {
1040   RTC_DCHECK_RUN_ON(network_thread_);
1041   allocation_sequences_created_ = true;
1042   // Send candidate allocation complete signal if we have no sequences.
1043   MaybeSignalCandidatesAllocationDone();
1044 }
1045 
OnCandidateReady(Port * port,const Candidate & c)1046 void BasicPortAllocatorSession::OnCandidateReady(Port* port,
1047                                                  const Candidate& c) {
1048   RTC_DCHECK_RUN_ON(network_thread_);
1049   PortData* data = FindPort(port);
1050   RTC_DCHECK(data != NULL);
1051   RTC_LOG(LS_INFO) << port->ToString()
1052                    << ": Gathered candidate: " << c.ToSensitiveString();
1053   // Discarding any candidate signal if port allocation status is
1054   // already done with gathering.
1055   if (!data->inprogress()) {
1056     RTC_LOG(LS_WARNING)
1057         << "Discarding candidate because port is already done gathering.";
1058     return;
1059   }
1060 
1061   // Mark that the port has a pairable candidate, either because we have a
1062   // usable candidate from the port, or simply because the port is bound to the
1063   // any address and therefore has no host candidate. This will trigger the port
1064   // to start creating candidate pairs (connections) and issue connectivity
1065   // checks. If port has already been marked as having a pairable candidate,
1066   // do nothing here.
1067   // Note: We should check whether any candidates may become ready after this
1068   // because there we will check whether the candidate is generated by the ready
1069   // ports, which may include this port.
1070   bool pruned = false;
1071   if (CandidatePairable(c, port) && !data->has_pairable_candidate()) {
1072     data->set_has_pairable_candidate(true);
1073 
1074     if (port->Type() == RELAY_PORT_TYPE) {
1075       if (turn_port_prune_policy_ == webrtc::KEEP_FIRST_READY) {
1076         pruned = PruneNewlyPairableTurnPort(data);
1077       } else if (turn_port_prune_policy_ == webrtc::PRUNE_BASED_ON_PRIORITY) {
1078         pruned = PruneTurnPorts(port);
1079       }
1080     }
1081 
1082     // If the current port is not pruned yet, SignalPortReady.
1083     if (!data->pruned()) {
1084       RTC_LOG(LS_INFO) << port->ToString() << ": Port ready.";
1085       SignalPortReady(this, port);
1086       port->KeepAliveUntilPruned();
1087     }
1088   }
1089 
1090   if (data->ready() && CheckCandidateFilter(c)) {
1091     std::vector<Candidate> candidates;
1092     candidates.push_back(allocator_->SanitizeCandidate(c));
1093     SignalCandidatesReady(this, candidates);
1094   } else {
1095     RTC_LOG(LS_INFO) << "Discarding candidate because it doesn't match filter.";
1096   }
1097 
1098   // If we have pruned any port, maybe need to signal port allocation done.
1099   if (pruned) {
1100     MaybeSignalCandidatesAllocationDone();
1101   }
1102 }
1103 
OnCandidateError(Port * port,const IceCandidateErrorEvent & event)1104 void BasicPortAllocatorSession::OnCandidateError(
1105     Port* port,
1106     const IceCandidateErrorEvent& event) {
1107   RTC_DCHECK_RUN_ON(network_thread_);
1108   RTC_DCHECK(FindPort(port));
1109   if (event.address.empty()) {
1110     candidate_error_events_.push_back(event);
1111   } else {
1112     SignalCandidateError(this, event);
1113   }
1114 }
1115 
GetBestTurnPortForNetwork(absl::string_view network_name) const1116 Port* BasicPortAllocatorSession::GetBestTurnPortForNetwork(
1117     absl::string_view network_name) const {
1118   RTC_DCHECK_RUN_ON(network_thread_);
1119   Port* best_turn_port = nullptr;
1120   for (const PortData& data : ports_) {
1121     if (data.port()->Network()->name() == network_name &&
1122         data.port()->Type() == RELAY_PORT_TYPE && data.ready() &&
1123         (!best_turn_port || ComparePort(data.port(), best_turn_port) > 0)) {
1124       best_turn_port = data.port();
1125     }
1126   }
1127   return best_turn_port;
1128 }
1129 
PruneNewlyPairableTurnPort(PortData * newly_pairable_port_data)1130 bool BasicPortAllocatorSession::PruneNewlyPairableTurnPort(
1131     PortData* newly_pairable_port_data) {
1132   RTC_DCHECK_RUN_ON(network_thread_);
1133   RTC_DCHECK(newly_pairable_port_data->port()->Type() == RELAY_PORT_TYPE);
1134   // If an existing turn port is ready on the same network, prune the newly
1135   // pairable port.
1136   const std::string& network_name =
1137       newly_pairable_port_data->port()->Network()->name();
1138 
1139   for (PortData& data : ports_) {
1140     if (data.port()->Network()->name() == network_name &&
1141         data.port()->Type() == RELAY_PORT_TYPE && data.ready() &&
1142         &data != newly_pairable_port_data) {
1143       RTC_LOG(LS_INFO) << "Port pruned: "
1144                        << newly_pairable_port_data->port()->ToString();
1145       newly_pairable_port_data->Prune();
1146       return true;
1147     }
1148   }
1149   return false;
1150 }
1151 
PruneTurnPorts(Port * newly_pairable_turn_port)1152 bool BasicPortAllocatorSession::PruneTurnPorts(Port* newly_pairable_turn_port) {
1153   RTC_DCHECK_RUN_ON(network_thread_);
1154   // Note: We determine the same network based only on their network names. So
1155   // if an IPv4 address and an IPv6 address have the same network name, they
1156   // are considered the same network here.
1157   const std::string& network_name = newly_pairable_turn_port->Network()->name();
1158   Port* best_turn_port = GetBestTurnPortForNetwork(network_name);
1159   // `port` is already in the list of ports, so the best port cannot be nullptr.
1160   RTC_CHECK(best_turn_port != nullptr);
1161 
1162   bool pruned = false;
1163   std::vector<PortData*> ports_to_prune;
1164   for (PortData& data : ports_) {
1165     if (data.port()->Network()->name() == network_name &&
1166         data.port()->Type() == RELAY_PORT_TYPE && !data.pruned() &&
1167         ComparePort(data.port(), best_turn_port) < 0) {
1168       pruned = true;
1169       if (data.port() != newly_pairable_turn_port) {
1170         // These ports will be pruned in PrunePortsAndRemoveCandidates.
1171         ports_to_prune.push_back(&data);
1172       } else {
1173         data.Prune();
1174       }
1175     }
1176   }
1177 
1178   if (!ports_to_prune.empty()) {
1179     RTC_LOG(LS_INFO) << "Prune " << ports_to_prune.size()
1180                      << " low-priority TURN ports";
1181     PrunePortsAndRemoveCandidates(ports_to_prune);
1182   }
1183   return pruned;
1184 }
1185 
PruneAllPorts()1186 void BasicPortAllocatorSession::PruneAllPorts() {
1187   RTC_DCHECK_RUN_ON(network_thread_);
1188   for (PortData& data : ports_) {
1189     data.Prune();
1190   }
1191 }
1192 
OnPortComplete(Port * port)1193 void BasicPortAllocatorSession::OnPortComplete(Port* port) {
1194   RTC_DCHECK_RUN_ON(network_thread_);
1195   RTC_LOG(LS_INFO) << port->ToString()
1196                    << ": Port completed gathering candidates.";
1197   PortData* data = FindPort(port);
1198   RTC_DCHECK(data != NULL);
1199 
1200   // Ignore any late signals.
1201   if (!data->inprogress()) {
1202     return;
1203   }
1204 
1205   // Moving to COMPLETE state.
1206   data->set_state(PortData::STATE_COMPLETE);
1207   // Send candidate allocation complete signal if this was the last port.
1208   MaybeSignalCandidatesAllocationDone();
1209 }
1210 
OnPortError(Port * port)1211 void BasicPortAllocatorSession::OnPortError(Port* port) {
1212   RTC_DCHECK_RUN_ON(network_thread_);
1213   RTC_LOG(LS_INFO) << port->ToString()
1214                    << ": Port encountered error while gathering candidates.";
1215   PortData* data = FindPort(port);
1216   RTC_DCHECK(data != NULL);
1217   // We might have already given up on this port and stopped it.
1218   if (!data->inprogress()) {
1219     return;
1220   }
1221 
1222   // SignalAddressError is currently sent from StunPort/TurnPort.
1223   // But this signal itself is generic.
1224   data->set_state(PortData::STATE_ERROR);
1225   // Send candidate allocation complete signal if this was the last port.
1226   MaybeSignalCandidatesAllocationDone();
1227 }
1228 
CheckCandidateFilter(const Candidate & c) const1229 bool BasicPortAllocatorSession::CheckCandidateFilter(const Candidate& c) const {
1230   RTC_DCHECK_RUN_ON(network_thread_);
1231 
1232   return IsAllowedByCandidateFilter(c, candidate_filter_);
1233 }
1234 
CandidatePairable(const Candidate & c,const Port * port) const1235 bool BasicPortAllocatorSession::CandidatePairable(const Candidate& c,
1236                                                   const Port* port) const {
1237   RTC_DCHECK_RUN_ON(network_thread_);
1238 
1239   bool candidate_signalable = CheckCandidateFilter(c);
1240 
1241   // When device enumeration is disabled (to prevent non-default IP addresses
1242   // from leaking), we ping from some local candidates even though we don't
1243   // signal them. However, if host candidates are also disabled (for example, to
1244   // prevent even default IP addresses from leaking), we still don't want to
1245   // ping from them, even if device enumeration is disabled.  Thus, we check for
1246   // both device enumeration and host candidates being disabled.
1247   bool network_enumeration_disabled = c.address().IsAnyIP();
1248   bool can_ping_from_candidate =
1249       (port->SharedSocket() || c.protocol() == TCP_PROTOCOL_NAME);
1250   bool host_candidates_disabled = !(candidate_filter_ & CF_HOST);
1251 
1252   return candidate_signalable ||
1253          (network_enumeration_disabled && can_ping_from_candidate &&
1254           !host_candidates_disabled);
1255 }
1256 
OnPortAllocationComplete()1257 void BasicPortAllocatorSession::OnPortAllocationComplete() {
1258   RTC_DCHECK_RUN_ON(network_thread_);
1259   // Send candidate allocation complete signal if all ports are done.
1260   MaybeSignalCandidatesAllocationDone();
1261 }
1262 
MaybeSignalCandidatesAllocationDone()1263 void BasicPortAllocatorSession::MaybeSignalCandidatesAllocationDone() {
1264   RTC_DCHECK_RUN_ON(network_thread_);
1265   if (CandidatesAllocationDone()) {
1266     if (pooled()) {
1267       RTC_LOG(LS_INFO) << "All candidates gathered for pooled session.";
1268     } else {
1269       RTC_LOG(LS_INFO) << "All candidates gathered for " << content_name()
1270                        << ":" << component() << ":" << generation();
1271     }
1272     for (const auto& event : candidate_error_events_) {
1273       SignalCandidateError(this, event);
1274     }
1275     candidate_error_events_.clear();
1276     SignalCandidatesAllocationDone(this);
1277   }
1278 }
1279 
OnPortDestroyed(PortInterface * port)1280 void BasicPortAllocatorSession::OnPortDestroyed(PortInterface* port) {
1281   RTC_DCHECK_RUN_ON(network_thread_);
1282   for (std::vector<PortData>::iterator iter = ports_.begin();
1283        iter != ports_.end(); ++iter) {
1284     if (port == iter->port()) {
1285       ports_.erase(iter);
1286       RTC_LOG(LS_INFO) << port->ToString() << ": Removed port from allocator ("
1287                        << static_cast<int>(ports_.size()) << " remaining)";
1288       return;
1289     }
1290   }
1291   RTC_DCHECK_NOTREACHED();
1292 }
1293 
FindPort(Port * port)1294 BasicPortAllocatorSession::PortData* BasicPortAllocatorSession::FindPort(
1295     Port* port) {
1296   RTC_DCHECK_RUN_ON(network_thread_);
1297   for (std::vector<PortData>::iterator it = ports_.begin(); it != ports_.end();
1298        ++it) {
1299     if (it->port() == port) {
1300       return &*it;
1301     }
1302   }
1303   return NULL;
1304 }
1305 
1306 std::vector<BasicPortAllocatorSession::PortData*>
GetUnprunedPorts(const std::vector<const rtc::Network * > & networks)1307 BasicPortAllocatorSession::GetUnprunedPorts(
1308     const std::vector<const rtc::Network*>& networks) {
1309   RTC_DCHECK_RUN_ON(network_thread_);
1310   std::vector<PortData*> unpruned_ports;
1311   for (PortData& port : ports_) {
1312     if (!port.pruned() &&
1313         absl::c_linear_search(networks, port.sequence()->network())) {
1314       unpruned_ports.push_back(&port);
1315     }
1316   }
1317   return unpruned_ports;
1318 }
1319 
PrunePortsAndRemoveCandidates(const std::vector<PortData * > & port_data_list)1320 void BasicPortAllocatorSession::PrunePortsAndRemoveCandidates(
1321     const std::vector<PortData*>& port_data_list) {
1322   RTC_DCHECK_RUN_ON(network_thread_);
1323   std::vector<PortInterface*> pruned_ports;
1324   std::vector<Candidate> removed_candidates;
1325   for (PortData* data : port_data_list) {
1326     // Prune the port so that it may be destroyed.
1327     data->Prune();
1328     pruned_ports.push_back(data->port());
1329     if (data->has_pairable_candidate()) {
1330       GetCandidatesFromPort(*data, &removed_candidates);
1331       // Mark the port as having no pairable candidates so that its candidates
1332       // won't be removed multiple times.
1333       data->set_has_pairable_candidate(false);
1334     }
1335   }
1336   if (!pruned_ports.empty()) {
1337     SignalPortsPruned(this, pruned_ports);
1338   }
1339   if (!removed_candidates.empty()) {
1340     RTC_LOG(LS_INFO) << "Removed " << removed_candidates.size()
1341                      << " candidates";
1342     SignalCandidatesRemoved(this, removed_candidates);
1343   }
1344 }
1345 
SetVpnList(const std::vector<rtc::NetworkMask> & vpn_list)1346 void BasicPortAllocator::SetVpnList(
1347     const std::vector<rtc::NetworkMask>& vpn_list) {
1348   network_manager_->set_vpn_list(vpn_list);
1349 }
1350 
1351 // AllocationSequence
1352 
AllocationSequence(BasicPortAllocatorSession * session,const rtc::Network * network,PortConfiguration * config,uint32_t flags,std::function<void ()> port_allocation_complete_callback)1353 AllocationSequence::AllocationSequence(
1354     BasicPortAllocatorSession* session,
1355     const rtc::Network* network,
1356     PortConfiguration* config,
1357     uint32_t flags,
1358     std::function<void()> port_allocation_complete_callback)
1359     : session_(session),
1360       network_(network),
1361       config_(config),
1362       state_(kInit),
1363       flags_(flags),
1364       udp_socket_(),
1365       udp_port_(NULL),
1366       phase_(0),
1367       port_allocation_complete_callback_(
1368           std::move(port_allocation_complete_callback)) {}
1369 
Init()1370 void AllocationSequence::Init() {
1371   if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET)) {
1372     udp_socket_.reset(session_->socket_factory()->CreateUdpSocket(
1373         rtc::SocketAddress(network_->GetBestIP(), 0),
1374         session_->allocator()->min_port(), session_->allocator()->max_port()));
1375     if (udp_socket_) {
1376       udp_socket_->SignalReadPacket.connect(this,
1377                                             &AllocationSequence::OnReadPacket);
1378     }
1379     // Continuing if `udp_socket_` is NULL, as local TCP and RelayPort using TCP
1380     // are next available options to setup a communication channel.
1381   }
1382 }
1383 
Clear()1384 void AllocationSequence::Clear() {
1385   TRACE_EVENT0("webrtc", "AllocationSequence::Clear");
1386   udp_port_ = NULL;
1387   relay_ports_.clear();
1388 }
1389 
OnNetworkFailed()1390 void AllocationSequence::OnNetworkFailed() {
1391   RTC_DCHECK(!network_failed_);
1392   network_failed_ = true;
1393   // Stop the allocation sequence if its network failed.
1394   Stop();
1395 }
1396 
DisableEquivalentPhases(const rtc::Network * network,PortConfiguration * config,uint32_t * flags)1397 void AllocationSequence::DisableEquivalentPhases(const rtc::Network* network,
1398                                                  PortConfiguration* config,
1399                                                  uint32_t* flags) {
1400   if (network_failed_) {
1401     // If the network of this allocation sequence has ever become failed,
1402     // it won't be equivalent to the new network.
1403     return;
1404   }
1405 
1406   if (!((network == network_) && (previous_best_ip_ == network->GetBestIP()))) {
1407     // Different network setup; nothing is equivalent.
1408     return;
1409   }
1410 
1411   // Else turn off the stuff that we've already got covered.
1412 
1413   // Every config implicitly specifies local, so turn that off right away if we
1414   // already have a port of the corresponding type. Look for a port that
1415   // matches this AllocationSequence's network, is the right protocol, and
1416   // hasn't encountered an error.
1417   // TODO(deadbeef): This doesn't take into account that there may be another
1418   // AllocationSequence that's ABOUT to allocate a UDP port, but hasn't yet.
1419   // This can happen if, say, there's a network change event right before an
1420   // application-triggered ICE restart. Hopefully this problem will just go
1421   // away if we get rid of the gathering "phases" though, which is planned.
1422   //
1423   //
1424   // PORTALLOCATOR_DISABLE_UDP is used to disable a Port from gathering the host
1425   // candidate (and srflx candidate if Port::SharedSocket()), and we do not want
1426   // to disable the gathering of these candidates just becaue of an existing
1427   // Port over PROTO_UDP, namely a TurnPort over UDP.
1428   if (absl::c_any_of(session_->ports_,
1429                      [this](const BasicPortAllocatorSession::PortData& p) {
1430                        return !p.pruned() && p.port()->Network() == network_ &&
1431                               p.port()->GetProtocol() == PROTO_UDP &&
1432                               p.port()->Type() == LOCAL_PORT_TYPE && !p.error();
1433                      })) {
1434     *flags |= PORTALLOCATOR_DISABLE_UDP;
1435   }
1436   // Similarly we need to check both the protocol used by an existing Port and
1437   // its type.
1438   if (absl::c_any_of(session_->ports_,
1439                      [this](const BasicPortAllocatorSession::PortData& p) {
1440                        return !p.pruned() && p.port()->Network() == network_ &&
1441                               p.port()->GetProtocol() == PROTO_TCP &&
1442                               p.port()->Type() == LOCAL_PORT_TYPE && !p.error();
1443                      })) {
1444     *flags |= PORTALLOCATOR_DISABLE_TCP;
1445   }
1446 
1447   if (config_ && config) {
1448     // We need to regather srflx candidates if either of the following
1449     // conditions occurs:
1450     //  1. The STUN servers are different from the previous gathering.
1451     //  2. We will regather host candidates, hence possibly inducing new NAT
1452     //     bindings.
1453     if (config_->StunServers() == config->StunServers() &&
1454         (*flags & PORTALLOCATOR_DISABLE_UDP)) {
1455       // Already got this STUN servers covered.
1456       *flags |= PORTALLOCATOR_DISABLE_STUN;
1457     }
1458     if (!config_->relays.empty()) {
1459       // Already got relays covered.
1460       // NOTE: This will even skip a _different_ set of relay servers if we
1461       // were to be given one, but that never happens in our codebase. Should
1462       // probably get rid of the list in PortConfiguration and just keep a
1463       // single relay server in each one.
1464       *flags |= PORTALLOCATOR_DISABLE_RELAY;
1465     }
1466   }
1467 }
1468 
Start()1469 void AllocationSequence::Start() {
1470   state_ = kRunning;
1471 
1472   session_->network_thread()->PostTask(
1473       SafeTask(safety_.flag(), [this, epoch = epoch_] { Process(epoch); }));
1474   // Take a snapshot of the best IP, so that when DisableEquivalentPhases is
1475   // called next time, we enable all phases if the best IP has since changed.
1476   previous_best_ip_ = network_->GetBestIP();
1477 }
1478 
Stop()1479 void AllocationSequence::Stop() {
1480   // If the port is completed, don't set it to stopped.
1481   if (state_ == kRunning) {
1482     state_ = kStopped;
1483     // Cause further Process calls in the previous epoch to be ignored.
1484     ++epoch_;
1485   }
1486 }
1487 
Process(int epoch)1488 void AllocationSequence::Process(int epoch) {
1489   RTC_DCHECK(rtc::Thread::Current() == session_->network_thread());
1490   const char* const PHASE_NAMES[kNumPhases] = {"Udp", "Relay", "Tcp"};
1491 
1492   if (epoch != epoch_)
1493     return;
1494 
1495   // Perform all of the phases in the current step.
1496   RTC_LOG(LS_INFO) << network_->ToString()
1497                    << ": Allocation Phase=" << PHASE_NAMES[phase_];
1498 
1499   switch (phase_) {
1500     case PHASE_UDP:
1501       CreateUDPPorts();
1502       CreateStunPorts();
1503       break;
1504 
1505     case PHASE_RELAY:
1506       CreateRelayPorts();
1507       break;
1508 
1509     case PHASE_TCP:
1510       CreateTCPPorts();
1511       state_ = kCompleted;
1512       break;
1513 
1514     default:
1515       RTC_DCHECK_NOTREACHED();
1516   }
1517 
1518   if (state() == kRunning) {
1519     ++phase_;
1520     session_->network_thread()->PostDelayedTask(
1521         SafeTask(safety_.flag(), [this, epoch = epoch_] { Process(epoch); }),
1522         TimeDelta::Millis(session_->allocator()->step_delay()));
1523   } else {
1524     // No allocation steps needed further if all phases in AllocationSequence
1525     // are completed. Cause further Process calls in the previous epoch to be
1526     // ignored.
1527     ++epoch_;
1528     port_allocation_complete_callback_();
1529   }
1530 }
1531 
CreateUDPPorts()1532 void AllocationSequence::CreateUDPPorts() {
1533   if (IsFlagSet(PORTALLOCATOR_DISABLE_UDP)) {
1534     RTC_LOG(LS_VERBOSE) << "AllocationSequence: UDP ports disabled, skipping.";
1535     return;
1536   }
1537 
1538   // TODO(mallinath) - Remove UDPPort creating socket after shared socket
1539   // is enabled completely.
1540   std::unique_ptr<UDPPort> port;
1541   bool emit_local_candidate_for_anyaddress =
1542       !IsFlagSet(PORTALLOCATOR_DISABLE_DEFAULT_LOCAL_CANDIDATE);
1543   if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET) && udp_socket_) {
1544     port = UDPPort::Create(
1545         session_->network_thread(), session_->socket_factory(), network_,
1546         udp_socket_.get(), session_->username(), session_->password(),
1547         emit_local_candidate_for_anyaddress,
1548         session_->allocator()->stun_candidate_keepalive_interval(),
1549         session_->allocator()->field_trials());
1550   } else {
1551     port = UDPPort::Create(
1552         session_->network_thread(), session_->socket_factory(), network_,
1553         session_->allocator()->min_port(), session_->allocator()->max_port(),
1554         session_->username(), session_->password(),
1555         emit_local_candidate_for_anyaddress,
1556         session_->allocator()->stun_candidate_keepalive_interval(),
1557         session_->allocator()->field_trials());
1558   }
1559 
1560   if (port) {
1561     port->SetIceTiebreaker(session_->ice_tiebreaker());
1562     // If shared socket is enabled, STUN candidate will be allocated by the
1563     // UDPPort.
1564     if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET)) {
1565       udp_port_ = port.get();
1566       port->SubscribePortDestroyed(
1567           [this](PortInterface* port) { OnPortDestroyed(port); });
1568 
1569       // If STUN is not disabled, setting stun server address to port.
1570       if (!IsFlagSet(PORTALLOCATOR_DISABLE_STUN)) {
1571         if (config_ && !config_->StunServers().empty()) {
1572           RTC_LOG(LS_INFO)
1573               << "AllocationSequence: UDPPort will be handling the "
1574                  "STUN candidate generation.";
1575           port->set_server_addresses(config_->StunServers());
1576         }
1577       }
1578     }
1579 
1580     session_->AddAllocatedPort(port.release(), this);
1581   }
1582 }
1583 
CreateTCPPorts()1584 void AllocationSequence::CreateTCPPorts() {
1585   if (IsFlagSet(PORTALLOCATOR_DISABLE_TCP)) {
1586     RTC_LOG(LS_VERBOSE) << "AllocationSequence: TCP ports disabled, skipping.";
1587     return;
1588   }
1589 
1590   std::unique_ptr<Port> port = TCPPort::Create(
1591       session_->network_thread(), session_->socket_factory(), network_,
1592       session_->allocator()->min_port(), session_->allocator()->max_port(),
1593       session_->username(), session_->password(),
1594       session_->allocator()->allow_tcp_listen(),
1595       session_->allocator()->field_trials());
1596   if (port) {
1597     port->SetIceTiebreaker(session_->ice_tiebreaker());
1598     session_->AddAllocatedPort(port.release(), this);
1599     // Since TCPPort is not created using shared socket, `port` will not be
1600     // added to the dequeue.
1601   }
1602 }
1603 
CreateStunPorts()1604 void AllocationSequence::CreateStunPorts() {
1605   if (IsFlagSet(PORTALLOCATOR_DISABLE_STUN)) {
1606     RTC_LOG(LS_VERBOSE) << "AllocationSequence: STUN ports disabled, skipping.";
1607     return;
1608   }
1609 
1610   if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET)) {
1611     return;
1612   }
1613 
1614   if (!(config_ && !config_->StunServers().empty())) {
1615     RTC_LOG(LS_WARNING)
1616         << "AllocationSequence: No STUN server configured, skipping.";
1617     return;
1618   }
1619 
1620   std::unique_ptr<StunPort> port = StunPort::Create(
1621       session_->network_thread(), session_->socket_factory(), network_,
1622       session_->allocator()->min_port(), session_->allocator()->max_port(),
1623       session_->username(), session_->password(), config_->StunServers(),
1624       session_->allocator()->stun_candidate_keepalive_interval(),
1625       session_->allocator()->field_trials());
1626   if (port) {
1627     port->SetIceTiebreaker(session_->ice_tiebreaker());
1628     session_->AddAllocatedPort(port.release(), this);
1629     // Since StunPort is not created using shared socket, `port` will not be
1630     // added to the dequeue.
1631   }
1632 }
1633 
CreateRelayPorts()1634 void AllocationSequence::CreateRelayPorts() {
1635   if (IsFlagSet(PORTALLOCATOR_DISABLE_RELAY)) {
1636     RTC_LOG(LS_VERBOSE)
1637         << "AllocationSequence: Relay ports disabled, skipping.";
1638     return;
1639   }
1640 
1641   // If BasicPortAllocatorSession::OnAllocate left relay ports enabled then we
1642   // ought to have a relay list for them here.
1643   RTC_DCHECK(config_);
1644   RTC_DCHECK(!config_->relays.empty());
1645   if (!(config_ && !config_->relays.empty())) {
1646     RTC_LOG(LS_WARNING)
1647         << "AllocationSequence: No relay server configured, skipping.";
1648     return;
1649   }
1650 
1651   // Relative priority of candidates from this TURN server in relation
1652   // to the candidates from other servers. Required because ICE priorities
1653   // need to be unique.
1654   int relative_priority = config_->relays.size();
1655   for (RelayServerConfig& relay : config_->relays) {
1656     CreateTurnPort(relay, relative_priority--);
1657   }
1658 }
1659 
CreateTurnPort(const RelayServerConfig & config,int relative_priority)1660 void AllocationSequence::CreateTurnPort(const RelayServerConfig& config,
1661                                         int relative_priority) {
1662   PortList::const_iterator relay_port;
1663   for (relay_port = config.ports.begin(); relay_port != config.ports.end();
1664        ++relay_port) {
1665     // Skip UDP connections to relay servers if it's disallowed.
1666     if (IsFlagSet(PORTALLOCATOR_DISABLE_UDP_RELAY) &&
1667         relay_port->proto == PROTO_UDP) {
1668       continue;
1669     }
1670 
1671     // Do not create a port if the server address family is known and does
1672     // not match the local IP address family.
1673     int server_ip_family = relay_port->address.ipaddr().family();
1674     int local_ip_family = network_->GetBestIP().family();
1675     if (server_ip_family != AF_UNSPEC && server_ip_family != local_ip_family) {
1676       RTC_LOG(LS_INFO)
1677           << "Server and local address families are not compatible. "
1678              "Server address: "
1679           << relay_port->address.ipaddr().ToSensitiveString()
1680           << " Local address: " << network_->GetBestIP().ToSensitiveString();
1681       continue;
1682     }
1683 
1684     CreateRelayPortArgs args;
1685     args.network_thread = session_->network_thread();
1686     args.socket_factory = session_->socket_factory();
1687     args.network = network_;
1688     args.username = session_->username();
1689     args.password = session_->password();
1690     args.server_address = &(*relay_port);
1691     args.config = &config;
1692     args.turn_customizer = session_->allocator()->turn_customizer();
1693     args.field_trials = session_->allocator()->field_trials();
1694     args.relative_priority = relative_priority;
1695 
1696     std::unique_ptr<cricket::Port> port;
1697     // Shared socket mode must be enabled only for UDP based ports. Hence
1698     // don't pass shared socket for ports which will create TCP sockets.
1699     // TODO(mallinath) - Enable shared socket mode for TURN ports. Disabled
1700     // due to webrtc bug https://code.google.com/p/webrtc/issues/detail?id=3537
1701     if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET) &&
1702         relay_port->proto == PROTO_UDP && udp_socket_) {
1703       port = session_->allocator()->relay_port_factory()->Create(
1704           args, udp_socket_.get());
1705 
1706       if (!port) {
1707         RTC_LOG(LS_WARNING) << "Failed to create relay port with "
1708                             << args.server_address->address.ToSensitiveString();
1709         continue;
1710       }
1711 
1712       relay_ports_.push_back(port.get());
1713       // Listen to the port destroyed signal, to allow AllocationSequence to
1714       // remove the entry from it's map.
1715       port->SubscribePortDestroyed(
1716           [this](PortInterface* port) { OnPortDestroyed(port); });
1717 
1718     } else {
1719       port = session_->allocator()->relay_port_factory()->Create(
1720           args, session_->allocator()->min_port(),
1721           session_->allocator()->max_port());
1722 
1723       if (!port) {
1724         RTC_LOG(LS_WARNING) << "Failed to create relay port with "
1725                             << args.server_address->address.ToSensitiveString();
1726         continue;
1727       }
1728     }
1729     RTC_DCHECK(port != NULL);
1730     port->SetIceTiebreaker(session_->ice_tiebreaker());
1731     session_->AddAllocatedPort(port.release(), this);
1732   }
1733 }
1734 
OnReadPacket(rtc::AsyncPacketSocket * socket,const char * data,size_t size,const rtc::SocketAddress & remote_addr,const int64_t & packet_time_us)1735 void AllocationSequence::OnReadPacket(rtc::AsyncPacketSocket* socket,
1736                                       const char* data,
1737                                       size_t size,
1738                                       const rtc::SocketAddress& remote_addr,
1739                                       const int64_t& packet_time_us) {
1740   RTC_DCHECK(socket == udp_socket_.get());
1741 
1742   bool turn_port_found = false;
1743 
1744   // Try to find the TurnPort that matches the remote address. Note that the
1745   // message could be a STUN binding response if the TURN server is also used as
1746   // a STUN server. We don't want to parse every message here to check if it is
1747   // a STUN binding response, so we pass the message to TurnPort regardless of
1748   // the message type. The TurnPort will just ignore the message since it will
1749   // not find any request by transaction ID.
1750   for (auto* port : relay_ports_) {
1751     if (port->CanHandleIncomingPacketsFrom(remote_addr)) {
1752       if (port->HandleIncomingPacket(socket, data, size, remote_addr,
1753                                      packet_time_us)) {
1754         return;
1755       }
1756       turn_port_found = true;
1757     }
1758   }
1759 
1760   if (udp_port_) {
1761     const ServerAddresses& stun_servers = udp_port_->server_addresses();
1762 
1763     // Pass the packet to the UdpPort if there is no matching TurnPort, or if
1764     // the TURN server is also a STUN server.
1765     if (!turn_port_found ||
1766         stun_servers.find(remote_addr) != stun_servers.end()) {
1767       RTC_DCHECK(udp_port_->SharedSocket());
1768       udp_port_->HandleIncomingPacket(socket, data, size, remote_addr,
1769                                       packet_time_us);
1770     }
1771   }
1772 }
1773 
OnPortDestroyed(PortInterface * port)1774 void AllocationSequence::OnPortDestroyed(PortInterface* port) {
1775   if (udp_port_ == port) {
1776     udp_port_ = NULL;
1777     return;
1778   }
1779 
1780   auto it = absl::c_find(relay_ports_, port);
1781   if (it != relay_ports_.end()) {
1782     relay_ports_.erase(it);
1783   } else {
1784     RTC_LOG(LS_ERROR) << "Unexpected OnPortDestroyed for nonexistent port.";
1785     RTC_DCHECK_NOTREACHED();
1786   }
1787 }
1788 
PortConfiguration(const ServerAddresses & stun_servers,absl::string_view username,absl::string_view password,const webrtc::FieldTrialsView * field_trials)1789 PortConfiguration::PortConfiguration(
1790     const ServerAddresses& stun_servers,
1791     absl::string_view username,
1792     absl::string_view password,
1793     const webrtc::FieldTrialsView* field_trials)
1794     : stun_servers(stun_servers), username(username), password(password) {
1795   if (!stun_servers.empty())
1796     stun_address = *(stun_servers.begin());
1797   // Note that this won't change once the config is initialized.
1798   if (field_trials) {
1799     use_turn_server_as_stun_server_disabled =
1800         field_trials->IsDisabled("WebRTC-UseTurnServerAsStunServer");
1801   }
1802 }
1803 
StunServers()1804 ServerAddresses PortConfiguration::StunServers() {
1805   if (!stun_address.IsNil() &&
1806       stun_servers.find(stun_address) == stun_servers.end()) {
1807     stun_servers.insert(stun_address);
1808   }
1809 
1810   if (!stun_servers.empty() && use_turn_server_as_stun_server_disabled) {
1811     return stun_servers;
1812   }
1813 
1814   // Every UDP TURN server should also be used as a STUN server if
1815   // use_turn_server_as_stun_server is not disabled or the stun servers are
1816   // empty.
1817   ServerAddresses turn_servers = GetRelayServerAddresses(PROTO_UDP);
1818   for (const rtc::SocketAddress& turn_server : turn_servers) {
1819     if (stun_servers.find(turn_server) == stun_servers.end()) {
1820       stun_servers.insert(turn_server);
1821     }
1822   }
1823   return stun_servers;
1824 }
1825 
AddRelay(const RelayServerConfig & config)1826 void PortConfiguration::AddRelay(const RelayServerConfig& config) {
1827   relays.push_back(config);
1828 }
1829 
SupportsProtocol(const RelayServerConfig & relay,ProtocolType type) const1830 bool PortConfiguration::SupportsProtocol(const RelayServerConfig& relay,
1831                                          ProtocolType type) const {
1832   PortList::const_iterator relay_port;
1833   for (relay_port = relay.ports.begin(); relay_port != relay.ports.end();
1834        ++relay_port) {
1835     if (relay_port->proto == type)
1836       return true;
1837   }
1838   return false;
1839 }
1840 
SupportsProtocol(ProtocolType type) const1841 bool PortConfiguration::SupportsProtocol(ProtocolType type) const {
1842   for (size_t i = 0; i < relays.size(); ++i) {
1843     if (SupportsProtocol(relays[i], type))
1844       return true;
1845   }
1846   return false;
1847 }
1848 
GetRelayServerAddresses(ProtocolType type) const1849 ServerAddresses PortConfiguration::GetRelayServerAddresses(
1850     ProtocolType type) const {
1851   ServerAddresses servers;
1852   for (size_t i = 0; i < relays.size(); ++i) {
1853     if (SupportsProtocol(relays[i], type)) {
1854       servers.insert(relays[i].ports.front().address);
1855     }
1856   }
1857   return servers;
1858 }
1859 
1860 }  // namespace cricket
1861