• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/base/p2p_transport_channel.h"
12 
13 #include <iterator>
14 #include <memory>
15 #include <set>
16 #include <utility>
17 
18 #include "absl/algorithm/container.h"
19 #include "absl/strings/match.h"
20 #include "api/candidate.h"
21 #include "logging/rtc_event_log/ice_logger.h"
22 #include "p2p/base/basic_ice_controller.h"
23 #include "p2p/base/candidate_pair_interface.h"
24 #include "p2p/base/connection.h"
25 #include "p2p/base/port.h"
26 #include "rtc_base/checks.h"
27 #include "rtc_base/crc32.h"
28 #include "rtc_base/experiments/struct_parameters_parser.h"
29 #include "rtc_base/logging.h"
30 #include "rtc_base/net_helper.h"
31 #include "rtc_base/net_helpers.h"
32 #include "rtc_base/string_encode.h"
33 #include "rtc_base/task_utils/to_queued_task.h"
34 #include "rtc_base/time_utils.h"
35 #include "system_wrappers/include/field_trial.h"
36 #include "system_wrappers/include/metrics.h"
37 
38 namespace {
39 
GetOrigin(cricket::PortInterface * port,cricket::PortInterface * origin_port)40 cricket::PortInterface::CandidateOrigin GetOrigin(
41     cricket::PortInterface* port,
42     cricket::PortInterface* origin_port) {
43   if (!origin_port)
44     return cricket::PortInterface::ORIGIN_MESSAGE;
45   else if (port == origin_port)
46     return cricket::PortInterface::ORIGIN_THIS_PORT;
47   else
48     return cricket::PortInterface::ORIGIN_OTHER_PORT;
49 }
50 
GetWeakPingIntervalInFieldTrial()51 uint32_t GetWeakPingIntervalInFieldTrial() {
52   uint32_t weak_ping_interval = ::strtoul(
53       webrtc::field_trial::FindFullName("WebRTC-StunInterPacketDelay").c_str(),
54       nullptr, 10);
55   if (weak_ping_interval) {
56     return static_cast<int>(weak_ping_interval);
57   }
58   return cricket::WEAK_PING_INTERVAL;
59 }
60 
GuessAdapterTypeFromNetworkCost(int network_cost)61 rtc::AdapterType GuessAdapterTypeFromNetworkCost(int network_cost) {
62   // The current network costs have been unchanged since they were added
63   // to webrtc. If they ever were to change we would need to reconsider
64   // this method.
65   switch (network_cost) {
66     case rtc::kNetworkCostMin:
67       return rtc::ADAPTER_TYPE_ETHERNET;
68     case rtc::kNetworkCostLow:
69       return rtc::ADAPTER_TYPE_WIFI;
70     case rtc::kNetworkCostCellular:
71       return rtc::ADAPTER_TYPE_CELLULAR;
72     case rtc::kNetworkCostCellular2G:
73       return rtc::ADAPTER_TYPE_CELLULAR_2G;
74     case rtc::kNetworkCostCellular3G:
75       return rtc::ADAPTER_TYPE_CELLULAR_3G;
76     case rtc::kNetworkCostCellular4G:
77       return rtc::ADAPTER_TYPE_CELLULAR_4G;
78     case rtc::kNetworkCostCellular5G:
79       return rtc::ADAPTER_TYPE_CELLULAR_5G;
80     case rtc::kNetworkCostUnknown:
81       return rtc::ADAPTER_TYPE_UNKNOWN;
82     case rtc::kNetworkCostMax:
83       return rtc::ADAPTER_TYPE_ANY;
84   }
85   return rtc::ADAPTER_TYPE_UNKNOWN;
86 }
87 
CreateRouteEndpointFromCandidate(bool local,const cricket::Candidate & candidate,bool uses_turn)88 rtc::RouteEndpoint CreateRouteEndpointFromCandidate(
89     bool local,
90     const cricket::Candidate& candidate,
91     bool uses_turn) {
92   auto adapter_type = candidate.network_type();
93   if (!local && adapter_type == rtc::ADAPTER_TYPE_UNKNOWN) {
94     adapter_type = GuessAdapterTypeFromNetworkCost(candidate.network_cost());
95   }
96 
97   // TODO(bugs.webrtc.org/9446) : Rewrite if information about remote network
98   // adapter becomes available. The implication of this implementation is that
99   // we will only ever report 1 adapter per type. In practice this is probably
100   // fine, since the endpoint also contains network-id.
101   uint16_t adapter_id = static_cast<int>(adapter_type);
102   return rtc::RouteEndpoint(adapter_type, adapter_id, candidate.network_id(),
103                             uses_turn);
104 }
105 
106 }  // unnamed namespace
107 
108 namespace cricket {
109 
110 using webrtc::RTCError;
111 using webrtc::RTCErrorType;
112 
IceCredentialsChanged(const std::string & old_ufrag,const std::string & old_pwd,const std::string & new_ufrag,const std::string & new_pwd)113 bool IceCredentialsChanged(const std::string& old_ufrag,
114                            const std::string& old_pwd,
115                            const std::string& new_ufrag,
116                            const std::string& new_pwd) {
117   // The standard (RFC 5245 Section 9.1.1.1) says that ICE restarts MUST change
118   // both the ufrag and password. However, section 9.2.1.1 says changing the
119   // ufrag OR password indicates an ICE restart. So, to keep compatibility with
120   // endpoints that only change one, we'll treat this as an ICE restart.
121   return (old_ufrag != new_ufrag) || (old_pwd != new_pwd);
122 }
123 
P2PTransportChannel(const std::string & transport_name,int component,PortAllocator * allocator)124 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name,
125                                          int component,
126                                          PortAllocator* allocator)
127     : P2PTransportChannel(transport_name,
128                           component,
129                           allocator,
130                           nullptr,
131                           nullptr) {}
132 
P2PTransportChannel(const std::string & transport_name,int component,PortAllocator * allocator,webrtc::AsyncResolverFactory * async_resolver_factory,webrtc::RtcEventLog * event_log,IceControllerFactoryInterface * ice_controller_factory)133 P2PTransportChannel::P2PTransportChannel(
134     const std::string& transport_name,
135     int component,
136     PortAllocator* allocator,
137     webrtc::AsyncResolverFactory* async_resolver_factory,
138     webrtc::RtcEventLog* event_log,
139     IceControllerFactoryInterface* ice_controller_factory)
140     : transport_name_(transport_name),
141       component_(component),
142       allocator_(allocator),
143       async_resolver_factory_(async_resolver_factory),
144       network_thread_(rtc::Thread::Current()),
145       incoming_only_(false),
146       error_(0),
147       sort_dirty_(false),
148       remote_ice_mode_(ICEMODE_FULL),
149       ice_role_(ICEROLE_UNKNOWN),
150       tiebreaker_(0),
151       gathering_state_(kIceGatheringNew),
152       config_(RECEIVING_TIMEOUT,
153               BACKUP_CONNECTION_PING_INTERVAL,
154               GATHER_ONCE /* continual_gathering_policy */,
155               false /* prioritize_most_likely_candidate_pairs */,
156               STRONG_AND_STABLE_WRITABLE_CONNECTION_PING_INTERVAL,
157               true /* presume_writable_when_fully_relayed */,
158               REGATHER_ON_FAILED_NETWORKS_INTERVAL,
159               RECEIVING_SWITCHING_DELAY) {
160   RTC_DCHECK(allocator_ != nullptr);
161   weak_ping_interval_ = GetWeakPingIntervalInFieldTrial();
162   // Validate IceConfig even for mostly built-in constant default values in case
163   // we change them.
164   RTC_DCHECK(ValidateIceConfig(config_).ok());
165   webrtc::BasicRegatheringController::Config regathering_config;
166   regathering_config.regather_on_failed_networks_interval =
167       config_.regather_on_failed_networks_interval_or_default();
168   regathering_controller_ =
169       std::make_unique<webrtc::BasicRegatheringController>(
170           regathering_config, this, network_thread_);
171   // We populate the change in the candidate filter to the session taken by
172   // the transport.
173   allocator_->SignalCandidateFilterChanged.connect(
174       this, &P2PTransportChannel::OnCandidateFilterChanged);
175   ice_event_log_.set_event_log(event_log);
176 
177   IceControllerFactoryArgs args{
178       [this] { return GetState(); }, [this] { return GetIceRole(); },
179       [this](const Connection* connection) {
180         // TODO(webrtc:10647/jonaso): Figure out a way to remove friendship
181         // between P2PTransportChannel and Connection.
182         return IsPortPruned(connection->port()) ||
183                IsRemoteCandidatePruned(connection->remote_candidate());
184       },
185       &field_trials_,
186       webrtc::field_trial::FindFullName("WebRTC-IceControllerFieldTrials")};
187   if (ice_controller_factory != nullptr) {
188     ice_controller_ = ice_controller_factory->Create(args);
189   } else {
190     ice_controller_ = std::make_unique<BasicIceController>(args);
191   }
192 }
193 
~P2PTransportChannel()194 P2PTransportChannel::~P2PTransportChannel() {
195   std::vector<Connection*> copy(connections().begin(), connections().end());
196   for (Connection* con : copy) {
197     con->Destroy();
198   }
199   for (auto& p : resolvers_) {
200     p.resolver_->Destroy(false);
201   }
202   resolvers_.clear();
203   RTC_DCHECK_RUN_ON(network_thread_);
204 }
205 
206 // Add the allocator session to our list so that we know which sessions
207 // are still active.
AddAllocatorSession(std::unique_ptr<PortAllocatorSession> session)208 void P2PTransportChannel::AddAllocatorSession(
209     std::unique_ptr<PortAllocatorSession> session) {
210   RTC_DCHECK_RUN_ON(network_thread_);
211 
212   session->set_generation(static_cast<uint32_t>(allocator_sessions_.size()));
213   session->SignalPortReady.connect(this, &P2PTransportChannel::OnPortReady);
214   session->SignalPortsPruned.connect(this, &P2PTransportChannel::OnPortsPruned);
215   session->SignalCandidatesReady.connect(
216       this, &P2PTransportChannel::OnCandidatesReady);
217   session->SignalCandidateError.connect(this,
218                                         &P2PTransportChannel::OnCandidateError);
219   session->SignalCandidatesRemoved.connect(
220       this, &P2PTransportChannel::OnCandidatesRemoved);
221   session->SignalCandidatesAllocationDone.connect(
222       this, &P2PTransportChannel::OnCandidatesAllocationDone);
223   if (!allocator_sessions_.empty()) {
224     allocator_session()->PruneAllPorts();
225   }
226   allocator_sessions_.push_back(std::move(session));
227   regathering_controller_->set_allocator_session(allocator_session());
228 
229   // We now only want to apply new candidates that we receive to the ports
230   // created by this new session because these are replacing those of the
231   // previous sessions.
232   PruneAllPorts();
233 }
234 
AddConnection(Connection * connection)235 void P2PTransportChannel::AddConnection(Connection* connection) {
236   RTC_DCHECK_RUN_ON(network_thread_);
237   connection->set_remote_ice_mode(remote_ice_mode_);
238   connection->set_receiving_timeout(config_.receiving_timeout);
239   connection->set_unwritable_timeout(config_.ice_unwritable_timeout);
240   connection->set_unwritable_min_checks(config_.ice_unwritable_min_checks);
241   connection->set_inactive_timeout(config_.ice_inactive_timeout);
242   connection->SignalReadPacket.connect(this,
243                                        &P2PTransportChannel::OnReadPacket);
244   connection->SignalReadyToSend.connect(this,
245                                         &P2PTransportChannel::OnReadyToSend);
246   connection->SignalStateChange.connect(
247       this, &P2PTransportChannel::OnConnectionStateChange);
248   connection->SignalDestroyed.connect(
249       this, &P2PTransportChannel::OnConnectionDestroyed);
250   connection->SignalNominated.connect(this, &P2PTransportChannel::OnNominated);
251 
252   had_connection_ = true;
253 
254   connection->set_ice_event_log(&ice_event_log_);
255   connection->SetIceFieldTrials(&field_trials_);
256   LogCandidatePairConfig(connection,
257                          webrtc::IceCandidatePairConfigType::kAdded);
258 
259   ice_controller_->AddConnection(connection);
260 }
261 
MaybeSwitchSelectedConnection(Connection * new_connection,IceControllerEvent reason)262 bool P2PTransportChannel::MaybeSwitchSelectedConnection(
263     Connection* new_connection,
264     IceControllerEvent reason) {
265   RTC_DCHECK_RUN_ON(network_thread_);
266 
267   return MaybeSwitchSelectedConnection(
268       reason, ice_controller_->ShouldSwitchConnection(reason, new_connection));
269 }
270 
MaybeSwitchSelectedConnection(IceControllerEvent reason,IceControllerInterface::SwitchResult result)271 bool P2PTransportChannel::MaybeSwitchSelectedConnection(
272     IceControllerEvent reason,
273     IceControllerInterface::SwitchResult result) {
274   RTC_DCHECK_RUN_ON(network_thread_);
275   if (result.connection.has_value()) {
276     RTC_LOG(LS_INFO) << "Switching selected connection due to: "
277                      << reason.ToString();
278     SwitchSelectedConnection(FromIceController(*result.connection), reason);
279   }
280 
281   if (result.recheck_event.has_value()) {
282     // If we do not switch to the connection because it missed the receiving
283     // threshold, the new connection is in a better receiving state than the
284     // currently selected connection. So we need to re-check whether it needs
285     // to be switched at a later time.
286     invoker_.AsyncInvokeDelayed<void>(
287         RTC_FROM_HERE, thread(),
288         rtc::Bind(&P2PTransportChannel::SortConnectionsAndUpdateState, this,
289                   *result.recheck_event),
290         result.recheck_event->recheck_delay_ms);
291   }
292 
293   for (const auto* con : result.connections_to_forget_state_on) {
294     FromIceController(con)->ForgetLearnedState();
295   }
296 
297   return result.connection.has_value();
298 }
299 
SetIceRole(IceRole ice_role)300 void P2PTransportChannel::SetIceRole(IceRole ice_role) {
301   RTC_DCHECK_RUN_ON(network_thread_);
302   if (ice_role_ != ice_role) {
303     ice_role_ = ice_role;
304     for (PortInterface* port : ports_) {
305       port->SetIceRole(ice_role);
306     }
307     // Update role on pruned ports as well, because they may still have
308     // connections alive that should be using the correct role.
309     for (PortInterface* port : pruned_ports_) {
310       port->SetIceRole(ice_role);
311     }
312   }
313 }
314 
GetIceRole() const315 IceRole P2PTransportChannel::GetIceRole() const {
316   RTC_DCHECK_RUN_ON(network_thread_);
317   return ice_role_;
318 }
319 
SetIceTiebreaker(uint64_t tiebreaker)320 void P2PTransportChannel::SetIceTiebreaker(uint64_t tiebreaker) {
321   RTC_DCHECK_RUN_ON(network_thread_);
322   if (!ports_.empty() || !pruned_ports_.empty()) {
323     RTC_LOG(LS_ERROR)
324         << "Attempt to change tiebreaker after Port has been allocated.";
325     return;
326   }
327 
328   tiebreaker_ = tiebreaker;
329 }
330 
GetState() const331 IceTransportState P2PTransportChannel::GetState() const {
332   RTC_DCHECK_RUN_ON(network_thread_);
333   return state_;
334 }
335 
GetIceTransportState() const336 webrtc::IceTransportState P2PTransportChannel::GetIceTransportState() const {
337   RTC_DCHECK_RUN_ON(network_thread_);
338   return standardized_state_;
339 }
340 
transport_name() const341 const std::string& P2PTransportChannel::transport_name() const {
342   RTC_DCHECK_RUN_ON(network_thread_);
343   return transport_name_;
344 }
345 
component() const346 int P2PTransportChannel::component() const {
347   RTC_DCHECK_RUN_ON(network_thread_);
348   return component_;
349 }
350 
writable() const351 bool P2PTransportChannel::writable() const {
352   RTC_DCHECK_RUN_ON(network_thread_);
353   return writable_;
354 }
355 
receiving() const356 bool P2PTransportChannel::receiving() const {
357   RTC_DCHECK_RUN_ON(network_thread_);
358   return receiving_;
359 }
360 
gathering_state() const361 IceGatheringState P2PTransportChannel::gathering_state() const {
362   RTC_DCHECK_RUN_ON(network_thread_);
363   return gathering_state_;
364 }
365 
GetRttEstimate()366 absl::optional<int> P2PTransportChannel::GetRttEstimate() {
367   RTC_DCHECK_RUN_ON(network_thread_);
368   if (selected_connection_ != nullptr &&
369       selected_connection_->rtt_samples() > 0) {
370     return selected_connection_->rtt();
371   } else {
372     return absl::nullopt;
373   }
374 }
375 
376 absl::optional<const CandidatePair>
GetSelectedCandidatePair() const377 P2PTransportChannel::GetSelectedCandidatePair() const {
378   RTC_DCHECK_RUN_ON(network_thread_);
379   if (selected_connection_ == nullptr) {
380     return absl::nullopt;
381   }
382 
383   CandidatePair pair;
384   pair.local = SanitizeLocalCandidate(selected_connection_->local_candidate());
385   pair.remote =
386       SanitizeRemoteCandidate(selected_connection_->remote_candidate());
387   return pair;
388 }
389 
390 // A channel is considered ICE completed once there is at most one active
391 // connection per network and at least one active connection.
ComputeState() const392 IceTransportState P2PTransportChannel::ComputeState() const {
393   RTC_DCHECK_RUN_ON(network_thread_);
394   if (!had_connection_) {
395     return IceTransportState::STATE_INIT;
396   }
397 
398   std::vector<Connection*> active_connections;
399   for (Connection* connection : connections()) {
400     if (connection->active()) {
401       active_connections.push_back(connection);
402     }
403   }
404   if (active_connections.empty()) {
405     return IceTransportState::STATE_FAILED;
406   }
407 
408   std::set<const rtc::Network*> networks;
409   for (Connection* connection : active_connections) {
410     const rtc::Network* network = connection->network();
411     if (networks.find(network) == networks.end()) {
412       networks.insert(network);
413     } else {
414       RTC_LOG(LS_VERBOSE) << ToString()
415                           << ": Ice not completed yet for this channel as "
416                           << network->ToString()
417                           << " has more than 1 connection.";
418       return IceTransportState::STATE_CONNECTING;
419     }
420   }
421 
422   ice_event_log_.DumpCandidatePairDescriptionToMemoryAsConfigEvents();
423   return IceTransportState::STATE_COMPLETED;
424 }
425 
426 // Compute the current RTCIceTransportState as described in
427 // https://www.w3.org/TR/webrtc/#dom-rtcicetransportstate
428 // TODO(bugs.webrtc.org/9218): Start signaling kCompleted once we have
429 // implemented end-of-candidates signalling.
ComputeIceTransportState() const430 webrtc::IceTransportState P2PTransportChannel::ComputeIceTransportState()
431     const {
432   RTC_DCHECK_RUN_ON(network_thread_);
433   bool has_connection = false;
434   for (Connection* connection : connections()) {
435     if (connection->active()) {
436       has_connection = true;
437       break;
438     }
439   }
440 
441   if (had_connection_ && !has_connection) {
442     return webrtc::IceTransportState::kFailed;
443   }
444 
445   if (!writable() && has_been_writable_) {
446     return webrtc::IceTransportState::kDisconnected;
447   }
448 
449   if (!had_connection_ && !has_connection) {
450     return webrtc::IceTransportState::kNew;
451   }
452 
453   if (has_connection && !writable()) {
454     // A candidate pair has been formed by adding a remote candidate
455     // and gathering a local candidate.
456     return webrtc::IceTransportState::kChecking;
457   }
458 
459   return webrtc::IceTransportState::kConnected;
460 }
461 
SetIceParameters(const IceParameters & ice_params)462 void P2PTransportChannel::SetIceParameters(const IceParameters& ice_params) {
463   RTC_DCHECK_RUN_ON(network_thread_);
464   RTC_LOG(LS_INFO) << "Set ICE ufrag: " << ice_params.ufrag
465                    << " pwd: " << ice_params.pwd << " on transport "
466                    << transport_name();
467   ice_parameters_ = ice_params;
468   // Note: Candidate gathering will restart when MaybeStartGathering is next
469   // called.
470 }
471 
SetRemoteIceParameters(const IceParameters & ice_params)472 void P2PTransportChannel::SetRemoteIceParameters(
473     const IceParameters& ice_params) {
474   RTC_DCHECK_RUN_ON(network_thread_);
475   RTC_LOG(LS_INFO) << "Received remote ICE parameters: ufrag="
476                    << ice_params.ufrag << ", renomination "
477                    << (ice_params.renomination ? "enabled" : "disabled");
478   IceParameters* current_ice = remote_ice();
479   if (!current_ice || *current_ice != ice_params) {
480     // Keep the ICE credentials so that newer connections
481     // are prioritized over the older ones.
482     remote_ice_parameters_.push_back(ice_params);
483   }
484 
485   // Update the pwd of remote candidate if needed.
486   for (RemoteCandidate& candidate : remote_candidates_) {
487     if (candidate.username() == ice_params.ufrag &&
488         candidate.password().empty()) {
489       candidate.set_password(ice_params.pwd);
490     }
491   }
492   // We need to update the credentials and generation for any peer reflexive
493   // candidates.
494   for (Connection* conn : connections()) {
495     conn->MaybeSetRemoteIceParametersAndGeneration(
496         ice_params, static_cast<int>(remote_ice_parameters_.size() - 1));
497   }
498   // Updating the remote ICE candidate generation could change the sort order.
499   RequestSortAndStateUpdate(
500       IceControllerEvent::REMOTE_CANDIDATE_GENERATION_CHANGE);
501 }
502 
SetRemoteIceMode(IceMode mode)503 void P2PTransportChannel::SetRemoteIceMode(IceMode mode) {
504   RTC_DCHECK_RUN_ON(network_thread_);
505   remote_ice_mode_ = mode;
506 }
507 
508 // TODO(qingsi): We apply the convention that setting a absl::optional parameter
509 // to null restores its default value in the implementation. However, some
510 // absl::optional parameters are only processed below if non-null, e.g.,
511 // regather_on_failed_networks_interval, and thus there is no way to restore the
512 // defaults. Fix this issue later for consistency.
SetIceConfig(const IceConfig & config)513 void P2PTransportChannel::SetIceConfig(const IceConfig& config) {
514   RTC_DCHECK_RUN_ON(network_thread_);
515   if (config_.continual_gathering_policy != config.continual_gathering_policy) {
516     if (!allocator_sessions_.empty()) {
517       RTC_LOG(LS_ERROR) << "Trying to change continual gathering policy "
518                            "when gathering has already started!";
519     } else {
520       config_.continual_gathering_policy = config.continual_gathering_policy;
521       RTC_LOG(LS_INFO) << "Set continual_gathering_policy to "
522                        << config_.continual_gathering_policy;
523     }
524   }
525 
526   if (config_.backup_connection_ping_interval !=
527       config.backup_connection_ping_interval) {
528     config_.backup_connection_ping_interval =
529         config.backup_connection_ping_interval;
530     RTC_LOG(LS_INFO) << "Set backup connection ping interval to "
531                      << config_.backup_connection_ping_interval_or_default()
532                      << " milliseconds.";
533   }
534   if (config_.receiving_timeout != config.receiving_timeout) {
535     config_.receiving_timeout = config.receiving_timeout;
536     for (Connection* connection : connections()) {
537       connection->set_receiving_timeout(config_.receiving_timeout);
538     }
539     RTC_LOG(LS_INFO) << "Set ICE receiving timeout to "
540                      << config_.receiving_timeout_or_default()
541                      << " milliseconds";
542   }
543 
544   config_.prioritize_most_likely_candidate_pairs =
545       config.prioritize_most_likely_candidate_pairs;
546   RTC_LOG(LS_INFO) << "Set ping most likely connection to "
547                    << config_.prioritize_most_likely_candidate_pairs;
548 
549   if (config_.stable_writable_connection_ping_interval !=
550       config.stable_writable_connection_ping_interval) {
551     config_.stable_writable_connection_ping_interval =
552         config.stable_writable_connection_ping_interval;
553     RTC_LOG(LS_INFO)
554         << "Set stable_writable_connection_ping_interval to "
555         << config_.stable_writable_connection_ping_interval_or_default();
556   }
557 
558   if (config_.presume_writable_when_fully_relayed !=
559       config.presume_writable_when_fully_relayed) {
560     if (!connections().empty()) {
561       RTC_LOG(LS_ERROR) << "Trying to change 'presume writable' "
562                            "while connections already exist!";
563     } else {
564       config_.presume_writable_when_fully_relayed =
565           config.presume_writable_when_fully_relayed;
566       RTC_LOG(LS_INFO) << "Set presume writable when fully relayed to "
567                        << config_.presume_writable_when_fully_relayed;
568     }
569   }
570 
571   config_.surface_ice_candidates_on_ice_transport_type_changed =
572       config.surface_ice_candidates_on_ice_transport_type_changed;
573   if (config_.surface_ice_candidates_on_ice_transport_type_changed &&
574       config_.continual_gathering_policy != GATHER_CONTINUALLY) {
575     RTC_LOG(LS_WARNING)
576         << "surface_ice_candidates_on_ice_transport_type_changed is "
577            "ineffective since we do not gather continually.";
578   }
579 
580   if (config_.regather_on_failed_networks_interval !=
581       config.regather_on_failed_networks_interval) {
582     config_.regather_on_failed_networks_interval =
583         config.regather_on_failed_networks_interval;
584     RTC_LOG(LS_INFO)
585         << "Set regather_on_failed_networks_interval to "
586         << config_.regather_on_failed_networks_interval_or_default();
587   }
588 
589   if (config_.receiving_switching_delay != config.receiving_switching_delay) {
590     config_.receiving_switching_delay = config.receiving_switching_delay;
591     RTC_LOG(LS_INFO) << "Set receiving_switching_delay to "
592                      << config_.receiving_switching_delay_or_default();
593   }
594 
595   if (config_.default_nomination_mode != config.default_nomination_mode) {
596     config_.default_nomination_mode = config.default_nomination_mode;
597     RTC_LOG(LS_INFO) << "Set default nomination mode to "
598                      << static_cast<int>(config_.default_nomination_mode);
599   }
600 
601   if (config_.ice_check_interval_strong_connectivity !=
602       config.ice_check_interval_strong_connectivity) {
603     config_.ice_check_interval_strong_connectivity =
604         config.ice_check_interval_strong_connectivity;
605     RTC_LOG(LS_INFO)
606         << "Set strong ping interval to "
607         << config_.ice_check_interval_strong_connectivity_or_default();
608   }
609 
610   if (config_.ice_check_interval_weak_connectivity !=
611       config.ice_check_interval_weak_connectivity) {
612     config_.ice_check_interval_weak_connectivity =
613         config.ice_check_interval_weak_connectivity;
614     RTC_LOG(LS_INFO)
615         << "Set weak ping interval to "
616         << config_.ice_check_interval_weak_connectivity_or_default();
617   }
618 
619   if (config_.ice_check_min_interval != config.ice_check_min_interval) {
620     config_.ice_check_min_interval = config.ice_check_min_interval;
621     RTC_LOG(LS_INFO) << "Set min ping interval to "
622                      << config_.ice_check_min_interval_or_default();
623   }
624 
625   if (config_.ice_unwritable_timeout != config.ice_unwritable_timeout) {
626     config_.ice_unwritable_timeout = config.ice_unwritable_timeout;
627     for (Connection* conn : connections()) {
628       conn->set_unwritable_timeout(config_.ice_unwritable_timeout);
629     }
630     RTC_LOG(LS_INFO) << "Set unwritable timeout to "
631                      << config_.ice_unwritable_timeout_or_default();
632   }
633 
634   if (config_.ice_unwritable_min_checks != config.ice_unwritable_min_checks) {
635     config_.ice_unwritable_min_checks = config.ice_unwritable_min_checks;
636     for (Connection* conn : connections()) {
637       conn->set_unwritable_min_checks(config_.ice_unwritable_min_checks);
638     }
639     RTC_LOG(LS_INFO) << "Set unwritable min checks to "
640                      << config_.ice_unwritable_min_checks_or_default();
641   }
642 
643   if (config_.ice_inactive_timeout != config.ice_inactive_timeout) {
644     config_.ice_inactive_timeout = config.ice_inactive_timeout;
645     for (Connection* conn : connections()) {
646       conn->set_inactive_timeout(config_.ice_inactive_timeout);
647     }
648     RTC_LOG(LS_INFO) << "Set inactive timeout to "
649                      << config_.ice_inactive_timeout_or_default();
650   }
651 
652   if (config_.network_preference != config.network_preference) {
653     config_.network_preference = config.network_preference;
654     RequestSortAndStateUpdate(IceControllerEvent::NETWORK_PREFERENCE_CHANGE);
655     RTC_LOG(LS_INFO) << "Set network preference to "
656                      << (config_.network_preference.has_value()
657                              ? config_.network_preference.value()
658                              : -1);  // network_preference cannot be bound to
659                                      // int with value_or.
660   }
661 
662   // TODO(qingsi): Resolve the naming conflict of stun_keepalive_delay in
663   // UDPPort and stun_keepalive_interval.
664   if (config_.stun_keepalive_interval != config.stun_keepalive_interval) {
665     config_.stun_keepalive_interval = config.stun_keepalive_interval;
666     allocator_session()->SetStunKeepaliveIntervalForReadyPorts(
667         config_.stun_keepalive_interval);
668     RTC_LOG(LS_INFO) << "Set STUN keepalive interval to "
669                      << config.stun_keepalive_interval_or_default();
670   }
671 
672   if (webrtc::field_trial::IsEnabled("WebRTC-ExtraICEPing")) {
673     RTC_LOG(LS_INFO) << "Set WebRTC-ExtraICEPing: Enabled";
674   }
675   if (webrtc::field_trial::IsEnabled("WebRTC-TurnAddMultiMapping")) {
676     RTC_LOG(LS_INFO) << "Set WebRTC-TurnAddMultiMapping: Enabled";
677   }
678 
679   webrtc::StructParametersParser::Create(
680       // go/skylift-light
681       "skip_relay_to_non_relay_connections",
682       &field_trials_.skip_relay_to_non_relay_connections,
683       // Limiting pings sent.
684       "max_outstanding_pings", &field_trials_.max_outstanding_pings,
685       // Delay initial selection of connection.
686       "initial_select_dampening", &field_trials_.initial_select_dampening,
687       // Delay initial selection of connections, that are receiving.
688       "initial_select_dampening_ping_received",
689       &field_trials_.initial_select_dampening_ping_received,
690       // Reply that we support goog ping.
691       "announce_goog_ping", &field_trials_.announce_goog_ping,
692       // Use goog ping if remote support it.
693       "enable_goog_ping", &field_trials_.enable_goog_ping,
694       // How fast does a RTT sample decay.
695       "rtt_estimate_halftime_ms", &field_trials_.rtt_estimate_halftime_ms,
696       // Make sure that nomination reaching ICE controlled asap.
697       "send_ping_on_switch_ice_controlling",
698       &field_trials_.send_ping_on_switch_ice_controlling,
699       // Reply to nomination ASAP.
700       "send_ping_on_nomination_ice_controlled",
701       &field_trials_.send_ping_on_nomination_ice_controlled,
702       // Allow connections to live untouched longer that 30s.
703       "dead_connection_timeout_ms", &field_trials_.dead_connection_timeout_ms)
704       ->Parse(webrtc::field_trial::FindFullName("WebRTC-IceFieldTrials"));
705 
706   if (field_trials_.dead_connection_timeout_ms < 30000) {
707     RTC_LOG(LS_WARNING) << "dead_connection_timeout_ms set to "
708                         << field_trials_.dead_connection_timeout_ms
709                         << " increasing it to 30000";
710     field_trials_.dead_connection_timeout_ms = 30000;
711   }
712 
713   if (field_trials_.skip_relay_to_non_relay_connections) {
714     RTC_LOG(LS_INFO) << "Set skip_relay_to_non_relay_connections";
715   }
716 
717   if (field_trials_.max_outstanding_pings.has_value()) {
718     RTC_LOG(LS_INFO) << "Set max_outstanding_pings: "
719                      << *field_trials_.max_outstanding_pings;
720   }
721 
722   if (field_trials_.initial_select_dampening.has_value()) {
723     RTC_LOG(LS_INFO) << "Set initial_select_dampening: "
724                      << *field_trials_.initial_select_dampening;
725   }
726 
727   if (field_trials_.initial_select_dampening_ping_received.has_value()) {
728     RTC_LOG(LS_INFO) << "Set initial_select_dampening_ping_received: "
729                      << *field_trials_.initial_select_dampening_ping_received;
730   }
731 
732   webrtc::BasicRegatheringController::Config regathering_config;
733   regathering_config.regather_on_failed_networks_interval =
734       config_.regather_on_failed_networks_interval_or_default();
735   regathering_controller_->SetConfig(regathering_config);
736 
737   ice_controller_->SetIceConfig(config_);
738 
739   RTC_DCHECK(ValidateIceConfig(config_).ok());
740 }
741 
config() const742 const IceConfig& P2PTransportChannel::config() const {
743   RTC_DCHECK_RUN_ON(network_thread_);
744   return config_;
745 }
746 
747 // TODO(qingsi): Add tests for the config validation starting from
748 // PeerConnection::SetConfiguration.
749 // Static
ValidateIceConfig(const IceConfig & config)750 RTCError P2PTransportChannel::ValidateIceConfig(const IceConfig& config) {
751   if (config.ice_check_interval_strong_connectivity_or_default() <
752       config.ice_check_interval_weak_connectivity.value_or(
753           GetWeakPingIntervalInFieldTrial())) {
754     return RTCError(RTCErrorType::INVALID_PARAMETER,
755                     "Ping interval of candidate pairs is shorter when ICE is "
756                     "strongly connected than that when ICE is weakly "
757                     "connected");
758   }
759 
760   if (config.receiving_timeout_or_default() <
761       std::max(config.ice_check_interval_strong_connectivity_or_default(),
762                config.ice_check_min_interval_or_default())) {
763     return RTCError(
764         RTCErrorType::INVALID_PARAMETER,
765         "Receiving timeout is shorter than the minimal ping interval.");
766   }
767 
768   if (config.backup_connection_ping_interval_or_default() <
769       config.ice_check_interval_strong_connectivity_or_default()) {
770     return RTCError(RTCErrorType::INVALID_PARAMETER,
771                     "Ping interval of backup candidate pairs is shorter than "
772                     "that of general candidate pairs when ICE is strongly "
773                     "connected");
774   }
775 
776   if (config.stable_writable_connection_ping_interval_or_default() <
777       config.ice_check_interval_strong_connectivity_or_default()) {
778     return RTCError(RTCErrorType::INVALID_PARAMETER,
779                     "Ping interval of stable and writable candidate pairs is "
780                     "shorter than that of general candidate pairs when ICE is "
781                     "strongly connected");
782   }
783 
784   if (config.ice_unwritable_timeout_or_default() >
785       config.ice_inactive_timeout_or_default()) {
786     return RTCError(RTCErrorType::INVALID_PARAMETER,
787                     "The timeout period for the writability state to become "
788                     "UNRELIABLE is longer than that to become TIMEOUT.");
789   }
790 
791   return RTCError::OK();
792 }
793 
selected_connection() const794 const Connection* P2PTransportChannel::selected_connection() const {
795   RTC_DCHECK_RUN_ON(network_thread_);
796   return selected_connection_;
797 }
798 
check_receiving_interval() const799 int P2PTransportChannel::check_receiving_interval() const {
800   RTC_DCHECK_RUN_ON(network_thread_);
801   return std::max(MIN_CHECK_RECEIVING_INTERVAL,
802                   config_.receiving_timeout_or_default() / 10);
803 }
804 
MaybeStartGathering()805 void P2PTransportChannel::MaybeStartGathering() {
806   RTC_DCHECK_RUN_ON(network_thread_);
807   if (ice_parameters_.ufrag.empty() || ice_parameters_.pwd.empty()) {
808     RTC_LOG(LS_ERROR)
809         << "Cannot gather candidates because ICE parameters are empty"
810            " ufrag: "
811         << ice_parameters_.ufrag << " pwd: " << ice_parameters_.pwd;
812     return;
813   }
814   // Start gathering if we never started before, or if an ICE restart occurred.
815   if (allocator_sessions_.empty() ||
816       IceCredentialsChanged(allocator_sessions_.back()->ice_ufrag(),
817                             allocator_sessions_.back()->ice_pwd(),
818                             ice_parameters_.ufrag, ice_parameters_.pwd)) {
819     if (gathering_state_ != kIceGatheringGathering) {
820       gathering_state_ = kIceGatheringGathering;
821       SignalGatheringState(this);
822     }
823 
824     if (!allocator_sessions_.empty()) {
825       IceRestartState state;
826       if (writable()) {
827         state = IceRestartState::CONNECTED;
828       } else if (IsGettingPorts()) {
829         state = IceRestartState::CONNECTING;
830       } else {
831         state = IceRestartState::DISCONNECTED;
832       }
833       RTC_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.IceRestartState",
834                                 static_cast<int>(state),
835                                 static_cast<int>(IceRestartState::MAX_VALUE));
836     }
837 
838     // Time for a new allocator.
839     std::unique_ptr<PortAllocatorSession> pooled_session =
840         allocator_->TakePooledSession(transport_name(), component(),
841                                       ice_parameters_.ufrag,
842                                       ice_parameters_.pwd);
843     if (pooled_session) {
844       AddAllocatorSession(std::move(pooled_session));
845       PortAllocatorSession* raw_pooled_session =
846           allocator_sessions_.back().get();
847       // Process the pooled session's existing candidates/ports, if they exist.
848       OnCandidatesReady(raw_pooled_session,
849                         raw_pooled_session->ReadyCandidates());
850       for (PortInterface* port : allocator_sessions_.back()->ReadyPorts()) {
851         OnPortReady(raw_pooled_session, port);
852       }
853       if (allocator_sessions_.back()->CandidatesAllocationDone()) {
854         OnCandidatesAllocationDone(raw_pooled_session);
855       }
856     } else {
857       AddAllocatorSession(allocator_->CreateSession(
858           transport_name(), component(), ice_parameters_.ufrag,
859           ice_parameters_.pwd));
860       allocator_sessions_.back()->StartGettingPorts();
861     }
862   }
863 }
864 
865 // A new port is available, attempt to make connections for it
OnPortReady(PortAllocatorSession * session,PortInterface * port)866 void P2PTransportChannel::OnPortReady(PortAllocatorSession* session,
867                                       PortInterface* port) {
868   RTC_DCHECK_RUN_ON(network_thread_);
869 
870   // Set in-effect options on the new port
871   for (OptionMap::const_iterator it = options_.begin(); it != options_.end();
872        ++it) {
873     int val = port->SetOption(it->first, it->second);
874     if (val < 0) {
875       // Errors are frequent, so use LS_INFO. bugs.webrtc.org/9221
876       RTC_LOG(LS_INFO) << port->ToString() << ": SetOption(" << it->first
877                        << ", " << it->second
878                        << ") failed: " << port->GetError();
879     }
880   }
881 
882   // Remember the ports and candidates, and signal that candidates are ready.
883   // The session will handle this, and send an initiate/accept/modify message
884   // if one is pending.
885 
886   port->SetIceRole(ice_role_);
887   port->SetIceTiebreaker(tiebreaker_);
888   ports_.push_back(port);
889   port->SignalUnknownAddress.connect(this,
890                                      &P2PTransportChannel::OnUnknownAddress);
891   port->SignalDestroyed.connect(this, &P2PTransportChannel::OnPortDestroyed);
892 
893   port->SignalRoleConflict.connect(this, &P2PTransportChannel::OnRoleConflict);
894   port->SignalSentPacket.connect(this, &P2PTransportChannel::OnSentPacket);
895 
896   // Attempt to create a connection from this new port to all of the remote
897   // candidates that we were given so far.
898 
899   std::vector<RemoteCandidate>::iterator iter;
900   for (iter = remote_candidates_.begin(); iter != remote_candidates_.end();
901        ++iter) {
902     CreateConnection(port, *iter, iter->origin_port());
903   }
904 
905   SortConnectionsAndUpdateState(
906       IceControllerEvent::NEW_CONNECTION_FROM_LOCAL_CANDIDATE);
907 }
908 
909 // A new candidate is available, let listeners know
OnCandidatesReady(PortAllocatorSession * session,const std::vector<Candidate> & candidates)910 void P2PTransportChannel::OnCandidatesReady(
911     PortAllocatorSession* session,
912     const std::vector<Candidate>& candidates) {
913   RTC_DCHECK_RUN_ON(network_thread_);
914   for (size_t i = 0; i < candidates.size(); ++i) {
915     SignalCandidateGathered(this, candidates[i]);
916   }
917 }
918 
OnCandidateError(PortAllocatorSession * session,const IceCandidateErrorEvent & event)919 void P2PTransportChannel::OnCandidateError(
920     PortAllocatorSession* session,
921     const IceCandidateErrorEvent& event) {
922   RTC_DCHECK(network_thread_ == rtc::Thread::Current());
923   SignalCandidateError(this, event);
924 }
925 
OnCandidatesAllocationDone(PortAllocatorSession * session)926 void P2PTransportChannel::OnCandidatesAllocationDone(
927     PortAllocatorSession* session) {
928   RTC_DCHECK_RUN_ON(network_thread_);
929   if (config_.gather_continually()) {
930     RTC_LOG(LS_INFO) << "P2PTransportChannel: " << transport_name()
931                      << ", component " << component()
932                      << " gathering complete, but using continual "
933                         "gathering so not changing gathering state.";
934     return;
935   }
936   gathering_state_ = kIceGatheringComplete;
937   RTC_LOG(LS_INFO) << "P2PTransportChannel: " << transport_name()
938                    << ", component " << component() << " gathering complete";
939   SignalGatheringState(this);
940 }
941 
942 // Handle stun packets
OnUnknownAddress(PortInterface * port,const rtc::SocketAddress & address,ProtocolType proto,IceMessage * stun_msg,const std::string & remote_username,bool port_muxed)943 void P2PTransportChannel::OnUnknownAddress(PortInterface* port,
944                                            const rtc::SocketAddress& address,
945                                            ProtocolType proto,
946                                            IceMessage* stun_msg,
947                                            const std::string& remote_username,
948                                            bool port_muxed) {
949   RTC_DCHECK_RUN_ON(network_thread_);
950 
951   // Port has received a valid stun packet from an address that no Connection
952   // is currently available for. See if we already have a candidate with the
953   // address. If it isn't we need to create new candidate for it.
954   //
955   // TODO(qingsi): There is a caveat of the logic below if we have remote
956   // candidates with hostnames. We could create a prflx candidate that is
957   // identical to a host candidate that are currently in the process of name
958   // resolution. We would not have a duplicate candidate since when adding the
959   // resolved host candidate, FinishingAddingRemoteCandidate does
960   // MaybeUpdatePeerReflexiveCandidate, and the prflx candidate would be updated
961   // to a host candidate. As a result, for a brief moment we would have a prflx
962   // candidate showing a private IP address, though we do not signal prflx
963   // candidates to applications and we could obfuscate the IP addresses of prflx
964   // candidates in P2PTransportChannel::GetStats. The difficulty of preventing
965   // creating the prflx from the beginning is that we do not have a reliable way
966   // to claim two candidates are identical without the address information. If
967   // we always pause the addition of a prflx candidate when there is ongoing
968   // name resolution and dedup after we have a resolved address, we run into the
969   // risk of losing/delaying the addition of a non-identical candidate that
970   // could be the only way to have a connection, if the resolution never
971   // completes or is significantly delayed.
972   const Candidate* candidate = nullptr;
973   for (const Candidate& c : remote_candidates_) {
974     if (c.username() == remote_username && c.address() == address &&
975         c.protocol() == ProtoToString(proto)) {
976       candidate = &c;
977       break;
978     }
979   }
980 
981   uint32_t remote_generation = 0;
982   std::string remote_password;
983   // The STUN binding request may arrive after setRemoteDescription and before
984   // adding remote candidate, so we need to set the password to the shared
985   // password and set the generation if the user name matches.
986   const IceParameters* ice_param =
987       FindRemoteIceFromUfrag(remote_username, &remote_generation);
988   // Note: if not found, the remote_generation will still be 0.
989   if (ice_param != nullptr) {
990     remote_password = ice_param->pwd;
991   }
992 
993   Candidate remote_candidate;
994   bool remote_candidate_is_new = (candidate == nullptr);
995   if (!remote_candidate_is_new) {
996     remote_candidate = *candidate;
997   } else {
998     // Create a new candidate with this address.
999     // The priority of the candidate is set to the PRIORITY attribute
1000     // from the request.
1001     const StunUInt32Attribute* priority_attr =
1002         stun_msg->GetUInt32(STUN_ATTR_PRIORITY);
1003     if (!priority_attr) {
1004       RTC_LOG(LS_WARNING) << "P2PTransportChannel::OnUnknownAddress - "
1005                              "No STUN_ATTR_PRIORITY found in the "
1006                              "stun request message";
1007       port->SendBindingErrorResponse(stun_msg, address, STUN_ERROR_BAD_REQUEST,
1008                                      STUN_ERROR_REASON_BAD_REQUEST);
1009       return;
1010     }
1011     int remote_candidate_priority = priority_attr->value();
1012 
1013     uint16_t network_id = 0;
1014     uint16_t network_cost = 0;
1015     const StunUInt32Attribute* network_attr =
1016         stun_msg->GetUInt32(STUN_ATTR_NETWORK_INFO);
1017     if (network_attr) {
1018       uint32_t network_info = network_attr->value();
1019       network_id = static_cast<uint16_t>(network_info >> 16);
1020       network_cost = static_cast<uint16_t>(network_info);
1021     }
1022 
1023     // RFC 5245
1024     // If the source transport address of the request does not match any
1025     // existing remote candidates, it represents a new peer reflexive remote
1026     // candidate.
1027     remote_candidate = Candidate(
1028         component(), ProtoToString(proto), address, remote_candidate_priority,
1029         remote_username, remote_password, PRFLX_PORT_TYPE, remote_generation,
1030         "", network_id, network_cost);
1031     if (proto == PROTO_TCP) {
1032       remote_candidate.set_tcptype(TCPTYPE_ACTIVE_STR);
1033     }
1034 
1035     // From RFC 5245, section-7.2.1.3:
1036     // The foundation of the candidate is set to an arbitrary value, different
1037     // from the foundation for all other remote candidates.
1038     remote_candidate.set_foundation(
1039         rtc::ToString(rtc::ComputeCrc32(remote_candidate.id())));
1040   }
1041 
1042   // RFC5245, the agent constructs a pair whose local candidate is equal to
1043   // the transport address on which the STUN request was received, and a
1044   // remote candidate equal to the source transport address where the
1045   // request came from.
1046 
1047   // There shouldn't be an existing connection with this remote address.
1048   // When ports are muxed, this channel might get multiple unknown address
1049   // signals. In that case if the connection is already exists, we should
1050   // simply ignore the signal otherwise send server error.
1051   if (port->GetConnection(remote_candidate.address())) {
1052     if (port_muxed) {
1053       RTC_LOG(LS_INFO) << "Connection already exists for peer reflexive "
1054                           "candidate: "
1055                        << remote_candidate.ToSensitiveString();
1056       return;
1057     } else {
1058       RTC_NOTREACHED();
1059       port->SendBindingErrorResponse(stun_msg, address, STUN_ERROR_SERVER_ERROR,
1060                                      STUN_ERROR_REASON_SERVER_ERROR);
1061       return;
1062     }
1063   }
1064 
1065   Connection* connection =
1066       port->CreateConnection(remote_candidate, PortInterface::ORIGIN_THIS_PORT);
1067   if (!connection) {
1068     // This could happen in some scenarios. For example, a TurnPort may have
1069     // had a refresh request timeout, so it won't create connections.
1070     port->SendBindingErrorResponse(stun_msg, address, STUN_ERROR_SERVER_ERROR,
1071                                    STUN_ERROR_REASON_SERVER_ERROR);
1072     return;
1073   }
1074 
1075   RTC_LOG(LS_INFO) << "Adding connection from "
1076                    << (remote_candidate_is_new ? "peer reflexive"
1077                                                : "resurrected")
1078                    << " candidate: " << remote_candidate.ToSensitiveString();
1079   AddConnection(connection);
1080   connection->HandleStunBindingOrGoogPingRequest(stun_msg);
1081 
1082   // Update the list of connections since we just added another.  We do this
1083   // after sending the response since it could (in principle) delete the
1084   // connection in question.
1085   SortConnectionsAndUpdateState(
1086       IceControllerEvent::NEW_CONNECTION_FROM_UNKNOWN_REMOTE_ADDRESS);
1087 }
1088 
OnCandidateFilterChanged(uint32_t prev_filter,uint32_t cur_filter)1089 void P2PTransportChannel::OnCandidateFilterChanged(uint32_t prev_filter,
1090                                                    uint32_t cur_filter) {
1091   RTC_DCHECK_RUN_ON(network_thread_);
1092   if (prev_filter == cur_filter || allocator_session() == nullptr) {
1093     return;
1094   }
1095   if (config_.surface_ice_candidates_on_ice_transport_type_changed) {
1096     allocator_session()->SetCandidateFilter(cur_filter);
1097   }
1098 }
1099 
OnRoleConflict(PortInterface * port)1100 void P2PTransportChannel::OnRoleConflict(PortInterface* port) {
1101   SignalRoleConflict(this);  // STUN ping will be sent when SetRole is called
1102                              // from Transport.
1103 }
1104 
FindRemoteIceFromUfrag(const std::string & ufrag,uint32_t * generation)1105 const IceParameters* P2PTransportChannel::FindRemoteIceFromUfrag(
1106     const std::string& ufrag,
1107     uint32_t* generation) {
1108   RTC_DCHECK_RUN_ON(network_thread_);
1109   const auto& params = remote_ice_parameters_;
1110   auto it = std::find_if(
1111       params.rbegin(), params.rend(),
1112       [ufrag](const IceParameters& param) { return param.ufrag == ufrag; });
1113   if (it == params.rend()) {
1114     // Not found.
1115     return nullptr;
1116   }
1117   *generation = params.rend() - it - 1;
1118   return &(*it);
1119 }
1120 
OnNominated(Connection * conn)1121 void P2PTransportChannel::OnNominated(Connection* conn) {
1122   RTC_DCHECK_RUN_ON(network_thread_);
1123   RTC_DCHECK(ice_role_ == ICEROLE_CONTROLLED);
1124 
1125   if (selected_connection_ == conn) {
1126     return;
1127   }
1128 
1129   if (field_trials_.send_ping_on_nomination_ice_controlled && conn != nullptr) {
1130     PingConnection(conn);
1131     MarkConnectionPinged(conn);
1132   }
1133 
1134   // TODO(qingsi): RequestSortAndStateUpdate will eventually call
1135   // MaybeSwitchSelectedConnection again. Rewrite this logic.
1136   if (MaybeSwitchSelectedConnection(
1137           conn, IceControllerEvent::NOMINATION_ON_CONTROLLED_SIDE)) {
1138     // Now that we have selected a connection, it is time to prune other
1139     // connections and update the read/write state of the channel.
1140     RequestSortAndStateUpdate(
1141         IceControllerEvent::NOMINATION_ON_CONTROLLED_SIDE);
1142   } else {
1143     RTC_LOG(LS_INFO)
1144         << "Not switching the selected connection on controlled side yet: "
1145         << conn->ToString();
1146   }
1147 }
1148 
ResolveHostnameCandidate(const Candidate & candidate)1149 void P2PTransportChannel::ResolveHostnameCandidate(const Candidate& candidate) {
1150   RTC_DCHECK_RUN_ON(network_thread_);
1151   if (!async_resolver_factory_) {
1152     RTC_LOG(LS_WARNING) << "Dropping ICE candidate with hostname address "
1153                            "(no AsyncResolverFactory)";
1154     return;
1155   }
1156 
1157   rtc::AsyncResolverInterface* resolver = async_resolver_factory_->Create();
1158   resolvers_.emplace_back(candidate, resolver);
1159   resolver->SignalDone.connect(this, &P2PTransportChannel::OnCandidateResolved);
1160   resolver->Start(candidate.address());
1161   RTC_LOG(LS_INFO) << "Asynchronously resolving ICE candidate hostname "
1162                    << candidate.address().HostAsSensitiveURIString();
1163 }
1164 
AddRemoteCandidate(const Candidate & candidate)1165 void P2PTransportChannel::AddRemoteCandidate(const Candidate& candidate) {
1166   RTC_DCHECK_RUN_ON(network_thread_);
1167 
1168   uint32_t generation = GetRemoteCandidateGeneration(candidate);
1169   // If a remote candidate with a previous generation arrives, drop it.
1170   if (generation < remote_ice_generation()) {
1171     RTC_LOG(LS_WARNING) << "Dropping a remote candidate because its ufrag "
1172                         << candidate.username()
1173                         << " indicates it was for a previous generation.";
1174     return;
1175   }
1176 
1177   Candidate new_remote_candidate(candidate);
1178   new_remote_candidate.set_generation(generation);
1179   // ICE candidates don't need to have username and password set, but
1180   // the code below this (specifically, ConnectionRequest::Prepare in
1181   // port.cc) uses the remote candidates's username.  So, we set it
1182   // here.
1183   if (remote_ice()) {
1184     if (candidate.username().empty()) {
1185       new_remote_candidate.set_username(remote_ice()->ufrag);
1186     }
1187     if (new_remote_candidate.username() == remote_ice()->ufrag) {
1188       if (candidate.password().empty()) {
1189         new_remote_candidate.set_password(remote_ice()->pwd);
1190       }
1191     } else {
1192       // The candidate belongs to the next generation. Its pwd will be set
1193       // when the new remote ICE credentials arrive.
1194       RTC_LOG(LS_WARNING)
1195           << "A remote candidate arrives with an unknown ufrag: "
1196           << candidate.username();
1197     }
1198   }
1199 
1200   if (new_remote_candidate.address().IsUnresolvedIP()) {
1201     // Don't do DNS lookups if the IceTransportPolicy is "none" or "relay".
1202     bool sharing_host = ((allocator_->candidate_filter() & CF_HOST) != 0);
1203     bool sharing_stun = ((allocator_->candidate_filter() & CF_REFLEXIVE) != 0);
1204     if (sharing_host || sharing_stun) {
1205       ResolveHostnameCandidate(new_remote_candidate);
1206     }
1207     return;
1208   }
1209 
1210   FinishAddingRemoteCandidate(new_remote_candidate);
1211 }
1212 
CandidateAndResolver(const Candidate & candidate,rtc::AsyncResolverInterface * resolver)1213 P2PTransportChannel::CandidateAndResolver::CandidateAndResolver(
1214     const Candidate& candidate,
1215     rtc::AsyncResolverInterface* resolver)
1216     : candidate_(candidate), resolver_(resolver) {}
1217 
~CandidateAndResolver()1218 P2PTransportChannel::CandidateAndResolver::~CandidateAndResolver() {}
1219 
OnCandidateResolved(rtc::AsyncResolverInterface * resolver)1220 void P2PTransportChannel::OnCandidateResolved(
1221     rtc::AsyncResolverInterface* resolver) {
1222   RTC_DCHECK_RUN_ON(network_thread_);
1223   auto p =
1224       absl::c_find_if(resolvers_, [resolver](const CandidateAndResolver& cr) {
1225         return cr.resolver_ == resolver;
1226       });
1227   if (p == resolvers_.end()) {
1228     RTC_LOG(LS_ERROR) << "Unexpected AsyncResolver signal";
1229     RTC_NOTREACHED();
1230     return;
1231   }
1232   Candidate candidate = p->candidate_;
1233   resolvers_.erase(p);
1234   AddRemoteCandidateWithResolver(candidate, resolver);
1235   thread()->PostTask(
1236       webrtc::ToQueuedTask([] {}, [resolver] { resolver->Destroy(false); }));
1237 }
1238 
AddRemoteCandidateWithResolver(Candidate candidate,rtc::AsyncResolverInterface * resolver)1239 void P2PTransportChannel::AddRemoteCandidateWithResolver(
1240     Candidate candidate,
1241     rtc::AsyncResolverInterface* resolver) {
1242   RTC_DCHECK_RUN_ON(network_thread_);
1243   if (resolver->GetError()) {
1244     RTC_LOG(LS_WARNING) << "Failed to resolve ICE candidate hostname "
1245                         << candidate.address().HostAsSensitiveURIString()
1246                         << " with error " << resolver->GetError();
1247     return;
1248   }
1249 
1250   rtc::SocketAddress resolved_address;
1251   // Prefer IPv6 to IPv4 if we have it (see RFC 5245 Section 15.1).
1252   // TODO(zstein): This won't work if we only have IPv4 locally but receive an
1253   // AAAA DNS record.
1254   bool have_address =
1255       resolver->GetResolvedAddress(AF_INET6, &resolved_address) ||
1256       resolver->GetResolvedAddress(AF_INET, &resolved_address);
1257   if (!have_address) {
1258     RTC_LOG(LS_INFO) << "ICE candidate hostname "
1259                      << candidate.address().HostAsSensitiveURIString()
1260                      << " could not be resolved";
1261     return;
1262   }
1263 
1264   RTC_LOG(LS_INFO) << "Resolved ICE candidate hostname "
1265                    << candidate.address().HostAsSensitiveURIString() << " to "
1266                    << resolved_address.ipaddr().ToSensitiveString();
1267   candidate.set_address(resolved_address);
1268   FinishAddingRemoteCandidate(candidate);
1269 }
1270 
FinishAddingRemoteCandidate(const Candidate & new_remote_candidate)1271 void P2PTransportChannel::FinishAddingRemoteCandidate(
1272     const Candidate& new_remote_candidate) {
1273   RTC_DCHECK_RUN_ON(network_thread_);
1274   // If this candidate matches what was thought to be a peer reflexive
1275   // candidate, we need to update the candidate priority/etc.
1276   for (Connection* conn : connections()) {
1277     conn->MaybeUpdatePeerReflexiveCandidate(new_remote_candidate);
1278   }
1279 
1280   // Create connections to this remote candidate.
1281   CreateConnections(new_remote_candidate, NULL);
1282 
1283   // Resort the connections list, which may have new elements.
1284   SortConnectionsAndUpdateState(
1285       IceControllerEvent::NEW_CONNECTION_FROM_REMOTE_CANDIDATE);
1286 }
1287 
RemoveRemoteCandidate(const Candidate & cand_to_remove)1288 void P2PTransportChannel::RemoveRemoteCandidate(
1289     const Candidate& cand_to_remove) {
1290   RTC_DCHECK_RUN_ON(network_thread_);
1291   auto iter =
1292       std::remove_if(remote_candidates_.begin(), remote_candidates_.end(),
1293                      [cand_to_remove](const Candidate& candidate) {
1294                        return cand_to_remove.MatchesForRemoval(candidate);
1295                      });
1296   if (iter != remote_candidates_.end()) {
1297     RTC_LOG(LS_VERBOSE) << "Removed remote candidate "
1298                         << cand_to_remove.ToSensitiveString();
1299     remote_candidates_.erase(iter, remote_candidates_.end());
1300   }
1301 }
1302 
RemoveAllRemoteCandidates()1303 void P2PTransportChannel::RemoveAllRemoteCandidates() {
1304   RTC_DCHECK_RUN_ON(network_thread_);
1305   remote_candidates_.clear();
1306 }
1307 
1308 // Creates connections from all of the ports that we care about to the given
1309 // remote candidate.  The return value is true if we created a connection from
1310 // the origin port.
CreateConnections(const Candidate & remote_candidate,PortInterface * origin_port)1311 bool P2PTransportChannel::CreateConnections(const Candidate& remote_candidate,
1312                                             PortInterface* origin_port) {
1313   RTC_DCHECK_RUN_ON(network_thread_);
1314 
1315   // If we've already seen the new remote candidate (in the current candidate
1316   // generation), then we shouldn't try creating connections for it.
1317   // We either already have a connection for it, or we previously created one
1318   // and then later pruned it. If we don't return, the channel will again
1319   // re-create any connections that were previously pruned, which will then
1320   // immediately be re-pruned, churning the network for no purpose.
1321   // This only applies to candidates received over signaling (i.e. origin_port
1322   // is NULL).
1323   if (!origin_port && IsDuplicateRemoteCandidate(remote_candidate)) {
1324     // return true to indicate success, without creating any new connections.
1325     return true;
1326   }
1327 
1328   // Add a new connection for this candidate to every port that allows such a
1329   // connection (i.e., if they have compatible protocols) and that does not
1330   // already have a connection to an equivalent candidate.  We must be careful
1331   // to make sure that the origin port is included, even if it was pruned,
1332   // since that may be the only port that can create this connection.
1333   bool created = false;
1334   std::vector<PortInterface*>::reverse_iterator it;
1335   for (it = ports_.rbegin(); it != ports_.rend(); ++it) {
1336     if (CreateConnection(*it, remote_candidate, origin_port)) {
1337       if (*it == origin_port)
1338         created = true;
1339     }
1340   }
1341 
1342   if ((origin_port != NULL) && !absl::c_linear_search(ports_, origin_port)) {
1343     if (CreateConnection(origin_port, remote_candidate, origin_port))
1344       created = true;
1345   }
1346 
1347   // Remember this remote candidate so that we can add it to future ports.
1348   RememberRemoteCandidate(remote_candidate, origin_port);
1349 
1350   return created;
1351 }
1352 
1353 // Setup a connection object for the local and remote candidate combination.
1354 // And then listen to connection object for changes.
CreateConnection(PortInterface * port,const Candidate & remote_candidate,PortInterface * origin_port)1355 bool P2PTransportChannel::CreateConnection(PortInterface* port,
1356                                            const Candidate& remote_candidate,
1357                                            PortInterface* origin_port) {
1358   RTC_DCHECK_RUN_ON(network_thread_);
1359   if (!port->SupportsProtocol(remote_candidate.protocol())) {
1360     return false;
1361   }
1362 
1363   if (field_trials_.skip_relay_to_non_relay_connections) {
1364     if ((port->Type() != remote_candidate.type()) &&
1365         (port->Type() == RELAY_PORT_TYPE ||
1366          remote_candidate.type() == RELAY_PORT_TYPE)) {
1367       RTC_LOG(LS_INFO) << ToString() << ": skip creating connection "
1368                        << port->Type() << " to " << remote_candidate.type();
1369       return false;
1370     }
1371   }
1372 
1373   // Look for an existing connection with this remote address.  If one is not
1374   // found or it is found but the existing remote candidate has an older
1375   // generation, then we can create a new connection for this address.
1376   Connection* connection = port->GetConnection(remote_candidate.address());
1377   if (connection == nullptr || connection->remote_candidate().generation() <
1378                                    remote_candidate.generation()) {
1379     // Don't create a connection if this is a candidate we received in a
1380     // message and we are not allowed to make outgoing connections.
1381     PortInterface::CandidateOrigin origin = GetOrigin(port, origin_port);
1382     if (origin == PortInterface::ORIGIN_MESSAGE && incoming_only_) {
1383       return false;
1384     }
1385     Connection* connection = port->CreateConnection(remote_candidate, origin);
1386     if (!connection) {
1387       return false;
1388     }
1389     AddConnection(connection);
1390     RTC_LOG(LS_INFO) << ToString()
1391                      << ": Created connection with origin: " << origin
1392                      << ", total: " << connections().size();
1393     return true;
1394   }
1395 
1396   // No new connection was created.
1397   // It is not legal to try to change any of the parameters of an existing
1398   // connection; however, the other side can send a duplicate candidate.
1399   if (!remote_candidate.IsEquivalent(connection->remote_candidate())) {
1400     RTC_LOG(INFO) << "Attempt to change a remote candidate."
1401                      " Existing remote candidate: "
1402                   << connection->remote_candidate().ToSensitiveString()
1403                   << "New remote candidate: "
1404                   << remote_candidate.ToSensitiveString();
1405   }
1406   return false;
1407 }
1408 
FindConnection(const Connection * connection) const1409 bool P2PTransportChannel::FindConnection(const Connection* connection) const {
1410   RTC_DCHECK_RUN_ON(network_thread_);
1411   return absl::c_linear_search(connections(), connection);
1412 }
1413 
GetRemoteCandidateGeneration(const Candidate & candidate)1414 uint32_t P2PTransportChannel::GetRemoteCandidateGeneration(
1415     const Candidate& candidate) {
1416   RTC_DCHECK_RUN_ON(network_thread_);
1417   // If the candidate has a ufrag, use it to find the generation.
1418   if (!candidate.username().empty()) {
1419     uint32_t generation = 0;
1420     if (!FindRemoteIceFromUfrag(candidate.username(), &generation)) {
1421       // If the ufrag is not found, assume the next/future generation.
1422       generation = static_cast<uint32_t>(remote_ice_parameters_.size());
1423     }
1424     return generation;
1425   }
1426   // If candidate generation is set, use that.
1427   if (candidate.generation() > 0) {
1428     return candidate.generation();
1429   }
1430   // Otherwise, assume the generation from remote ice parameters.
1431   return remote_ice_generation();
1432 }
1433 
1434 // Check if remote candidate is already cached.
IsDuplicateRemoteCandidate(const Candidate & candidate)1435 bool P2PTransportChannel::IsDuplicateRemoteCandidate(
1436     const Candidate& candidate) {
1437   RTC_DCHECK_RUN_ON(network_thread_);
1438   for (size_t i = 0; i < remote_candidates_.size(); ++i) {
1439     if (remote_candidates_[i].IsEquivalent(candidate)) {
1440       return true;
1441     }
1442   }
1443   return false;
1444 }
1445 
1446 // Maintain our remote candidate list, adding this new remote one.
RememberRemoteCandidate(const Candidate & remote_candidate,PortInterface * origin_port)1447 void P2PTransportChannel::RememberRemoteCandidate(
1448     const Candidate& remote_candidate,
1449     PortInterface* origin_port) {
1450   RTC_DCHECK_RUN_ON(network_thread_);
1451   // Remove any candidates whose generation is older than this one.  The
1452   // presence of a new generation indicates that the old ones are not useful.
1453   size_t i = 0;
1454   while (i < remote_candidates_.size()) {
1455     if (remote_candidates_[i].generation() < remote_candidate.generation()) {
1456       RTC_LOG(INFO) << "Pruning candidate from old generation: "
1457                     << remote_candidates_[i].address().ToSensitiveString();
1458       remote_candidates_.erase(remote_candidates_.begin() + i);
1459     } else {
1460       i += 1;
1461     }
1462   }
1463 
1464   // Make sure this candidate is not a duplicate.
1465   if (IsDuplicateRemoteCandidate(remote_candidate)) {
1466     RTC_LOG(INFO) << "Duplicate candidate: "
1467                   << remote_candidate.ToSensitiveString();
1468     return;
1469   }
1470 
1471   // Try this candidate for all future ports.
1472   remote_candidates_.push_back(RemoteCandidate(remote_candidate, origin_port));
1473 }
1474 
1475 // Set options on ourselves is simply setting options on all of our available
1476 // port objects.
SetOption(rtc::Socket::Option opt,int value)1477 int P2PTransportChannel::SetOption(rtc::Socket::Option opt, int value) {
1478   RTC_DCHECK_RUN_ON(network_thread_);
1479   OptionMap::iterator it = options_.find(opt);
1480   if (it == options_.end()) {
1481     options_.insert(std::make_pair(opt, value));
1482   } else if (it->second == value) {
1483     return 0;
1484   } else {
1485     it->second = value;
1486   }
1487 
1488   for (PortInterface* port : ports_) {
1489     int val = port->SetOption(opt, value);
1490     if (val < 0) {
1491       // Because this also occurs deferred, probably no point in reporting an
1492       // error
1493       RTC_LOG(WARNING) << "SetOption(" << opt << ", " << value
1494                        << ") failed: " << port->GetError();
1495     }
1496   }
1497   return 0;
1498 }
1499 
GetOption(rtc::Socket::Option opt,int * value)1500 bool P2PTransportChannel::GetOption(rtc::Socket::Option opt, int* value) {
1501   RTC_DCHECK_RUN_ON(network_thread_);
1502 
1503   const auto& found = options_.find(opt);
1504   if (found == options_.end()) {
1505     return false;
1506   }
1507   *value = found->second;
1508   return true;
1509 }
1510 
GetError()1511 int P2PTransportChannel::GetError() {
1512   RTC_DCHECK_RUN_ON(network_thread_);
1513   return error_;
1514 }
1515 
1516 // Send data to the other side, using our selected connection.
SendPacket(const char * data,size_t len,const rtc::PacketOptions & options,int flags)1517 int P2PTransportChannel::SendPacket(const char* data,
1518                                     size_t len,
1519                                     const rtc::PacketOptions& options,
1520                                     int flags) {
1521   RTC_DCHECK_RUN_ON(network_thread_);
1522   if (flags != 0) {
1523     error_ = EINVAL;
1524     return -1;
1525   }
1526   // If we don't think the connection is working yet, return ENOTCONN
1527   // instead of sending a packet that will probably be dropped.
1528   if (!ReadyToSend(selected_connection_)) {
1529     error_ = ENOTCONN;
1530     return -1;
1531   }
1532 
1533   last_sent_packet_id_ = options.packet_id;
1534   rtc::PacketOptions modified_options(options);
1535   modified_options.info_signaled_after_sent.packet_type =
1536       rtc::PacketType::kData;
1537   int sent = selected_connection_->Send(data, len, modified_options);
1538   if (sent <= 0) {
1539     RTC_DCHECK(sent < 0);
1540     error_ = selected_connection_->GetError();
1541   }
1542   return sent;
1543 }
1544 
GetStats(IceTransportStats * ice_transport_stats)1545 bool P2PTransportChannel::GetStats(IceTransportStats* ice_transport_stats) {
1546   RTC_DCHECK_RUN_ON(network_thread_);
1547   // Gather candidate and candidate pair stats.
1548   ice_transport_stats->candidate_stats_list.clear();
1549   ice_transport_stats->connection_infos.clear();
1550 
1551   if (!allocator_sessions_.empty()) {
1552     allocator_session()->GetCandidateStatsFromReadyPorts(
1553         &ice_transport_stats->candidate_stats_list);
1554   }
1555 
1556   // TODO(qingsi): Remove naming inconsistency for candidate pair/connection.
1557   for (Connection* connection : connections()) {
1558     ConnectionInfo stats = connection->stats();
1559     stats.local_candidate = SanitizeLocalCandidate(stats.local_candidate);
1560     stats.remote_candidate = SanitizeRemoteCandidate(stats.remote_candidate);
1561     stats.best_connection = (selected_connection_ == connection);
1562     ice_transport_stats->connection_infos.push_back(std::move(stats));
1563     connection->set_reported(true);
1564   }
1565 
1566   ice_transport_stats->selected_candidate_pair_changes =
1567       selected_candidate_pair_changes_;
1568   return true;
1569 }
1570 
network_route() const1571 absl::optional<rtc::NetworkRoute> P2PTransportChannel::network_route() const {
1572   RTC_DCHECK_RUN_ON(network_thread_);
1573   return network_route_;
1574 }
1575 
DefaultDscpValue() const1576 rtc::DiffServCodePoint P2PTransportChannel::DefaultDscpValue() const {
1577   RTC_DCHECK_RUN_ON(network_thread_);
1578   OptionMap::const_iterator it = options_.find(rtc::Socket::OPT_DSCP);
1579   if (it == options_.end()) {
1580     return rtc::DSCP_NO_CHANGE;
1581   }
1582   return static_cast<rtc::DiffServCodePoint>(it->second);
1583 }
1584 
connections() const1585 rtc::ArrayView<Connection*> P2PTransportChannel::connections() const {
1586   RTC_DCHECK_RUN_ON(network_thread_);
1587   rtc::ArrayView<const Connection*> res = ice_controller_->connections();
1588   return rtc::ArrayView<Connection*>(const_cast<Connection**>(res.data()),
1589                                      res.size());
1590 }
1591 
1592 // Monitor connection states.
UpdateConnectionStates()1593 void P2PTransportChannel::UpdateConnectionStates() {
1594   RTC_DCHECK_RUN_ON(network_thread_);
1595   int64_t now = rtc::TimeMillis();
1596 
1597   // We need to copy the list of connections since some may delete themselves
1598   // when we call UpdateState.
1599   for (Connection* c : connections()) {
1600     c->UpdateState(now);
1601   }
1602 }
1603 
1604 // Prepare for best candidate sorting.
RequestSortAndStateUpdate(IceControllerEvent reason_to_sort)1605 void P2PTransportChannel::RequestSortAndStateUpdate(
1606     IceControllerEvent reason_to_sort) {
1607   RTC_DCHECK_RUN_ON(network_thread_);
1608   if (!sort_dirty_) {
1609     invoker_.AsyncInvoke<void>(
1610         RTC_FROM_HERE, thread(),
1611         rtc::Bind(&P2PTransportChannel::SortConnectionsAndUpdateState, this,
1612                   reason_to_sort));
1613     sort_dirty_ = true;
1614   }
1615 }
1616 
MaybeStartPinging()1617 void P2PTransportChannel::MaybeStartPinging() {
1618   RTC_DCHECK_RUN_ON(network_thread_);
1619   if (started_pinging_) {
1620     return;
1621   }
1622 
1623   if (ice_controller_->HasPingableConnection()) {
1624     RTC_LOG(LS_INFO) << ToString()
1625                      << ": Have a pingable connection for the first time; "
1626                         "starting to ping.";
1627     invoker_.AsyncInvoke<void>(
1628         RTC_FROM_HERE, thread(),
1629         rtc::Bind(&P2PTransportChannel::CheckAndPing, this));
1630     regathering_controller_->Start();
1631     started_pinging_ = true;
1632   }
1633 }
1634 
IsPortPruned(const Port * port) const1635 bool P2PTransportChannel::IsPortPruned(const Port* port) const {
1636   RTC_DCHECK_RUN_ON(network_thread_);
1637   return !absl::c_linear_search(ports_, port);
1638 }
1639 
IsRemoteCandidatePruned(const Candidate & cand) const1640 bool P2PTransportChannel::IsRemoteCandidatePruned(const Candidate& cand) const {
1641   RTC_DCHECK_RUN_ON(network_thread_);
1642   return !absl::c_linear_search(remote_candidates_, cand);
1643 }
1644 
PresumedWritable(const Connection * conn) const1645 bool P2PTransportChannel::PresumedWritable(const Connection* conn) const {
1646   RTC_DCHECK_RUN_ON(network_thread_);
1647   return (conn->write_state() == Connection::STATE_WRITE_INIT &&
1648           config_.presume_writable_when_fully_relayed &&
1649           conn->local_candidate().type() == RELAY_PORT_TYPE &&
1650           (conn->remote_candidate().type() == RELAY_PORT_TYPE ||
1651            conn->remote_candidate().type() == PRFLX_PORT_TYPE));
1652 }
1653 
1654 // Sort the available connections to find the best one.  We also monitor
1655 // the number of available connections and the current state.
SortConnectionsAndUpdateState(IceControllerEvent reason_to_sort)1656 void P2PTransportChannel::SortConnectionsAndUpdateState(
1657     IceControllerEvent reason_to_sort) {
1658   RTC_DCHECK_RUN_ON(network_thread_);
1659 
1660   // Make sure the connection states are up-to-date since this affects how they
1661   // will be sorted.
1662   UpdateConnectionStates();
1663 
1664   // Any changes after this point will require a re-sort.
1665   sort_dirty_ = false;
1666 
1667   // If necessary, switch to the new choice. Note that |top_connection| doesn't
1668   // have to be writable to become the selected connection although it will
1669   // have higher priority if it is writable.
1670   MaybeSwitchSelectedConnection(
1671       reason_to_sort, ice_controller_->SortAndSwitchConnection(reason_to_sort));
1672 
1673   // The controlled side can prune only if the selected connection has been
1674   // nominated because otherwise it may prune the connection that will be
1675   // selected by the controlling side.
1676   // TODO(honghaiz): This is not enough to prevent a connection from being
1677   // pruned too early because with aggressive nomination, the controlling side
1678   // will nominate every connection until it becomes writable.
1679   if (ice_role_ == ICEROLE_CONTROLLING ||
1680       (selected_connection_ && selected_connection_->nominated())) {
1681     PruneConnections();
1682   }
1683 
1684   // Check if all connections are timedout.
1685   bool all_connections_timedout = true;
1686   for (const Connection* conn : connections()) {
1687     if (conn->write_state() != Connection::STATE_WRITE_TIMEOUT) {
1688       all_connections_timedout = false;
1689       break;
1690     }
1691   }
1692 
1693   // Now update the writable state of the channel with the information we have
1694   // so far.
1695   if (all_connections_timedout) {
1696     HandleAllTimedOut();
1697   }
1698 
1699   // Update the state of this channel.
1700   UpdateState();
1701 
1702   // Also possibly start pinging.
1703   // We could start pinging if:
1704   // * The first connection was created.
1705   // * ICE credentials were provided.
1706   // * A TCP connection became connected.
1707   MaybeStartPinging();
1708 }
1709 
PruneConnections()1710 void P2PTransportChannel::PruneConnections() {
1711   RTC_DCHECK_RUN_ON(network_thread_);
1712   std::vector<const Connection*> connections_to_prune =
1713       ice_controller_->PruneConnections();
1714   for (const Connection* conn : connections_to_prune) {
1715     FromIceController(conn)->Prune();
1716   }
1717 }
1718 
1719 // Change the selected connection, and let listeners know.
SwitchSelectedConnection(Connection * conn,IceControllerEvent reason)1720 void P2PTransportChannel::SwitchSelectedConnection(Connection* conn,
1721                                                    IceControllerEvent reason) {
1722   RTC_DCHECK_RUN_ON(network_thread_);
1723   // Note: if conn is NULL, the previous |selected_connection_| has been
1724   // destroyed, so don't use it.
1725   Connection* old_selected_connection = selected_connection_;
1726   selected_connection_ = conn;
1727   LogCandidatePairConfig(conn, webrtc::IceCandidatePairConfigType::kSelected);
1728   network_route_.reset();
1729   if (old_selected_connection) {
1730     old_selected_connection->set_selected(false);
1731   }
1732   if (selected_connection_) {
1733     ++nomination_;
1734     selected_connection_->set_selected(true);
1735     if (old_selected_connection) {
1736       RTC_LOG(LS_INFO) << ToString() << ": Previous selected connection: "
1737                        << old_selected_connection->ToString();
1738     }
1739     RTC_LOG(LS_INFO) << ToString() << ": New selected connection: "
1740                      << selected_connection_->ToString();
1741     SignalRouteChange(this, selected_connection_->remote_candidate());
1742     // This is a temporary, but safe fix to webrtc issue 5705.
1743     // TODO(honghaiz): Make all ENOTCONN error routed through the transport
1744     // channel so that it knows whether the media channel is allowed to
1745     // send; then it will only signal ready-to-send if the media channel
1746     // has been disallowed to send.
1747     if (selected_connection_->writable() ||
1748         PresumedWritable(selected_connection_)) {
1749       SignalReadyToSend(this);
1750     }
1751 
1752     network_route_.emplace(rtc::NetworkRoute());
1753     network_route_->connected = ReadyToSend(selected_connection_);
1754     network_route_->local = CreateRouteEndpointFromCandidate(
1755         /* local= */ true, selected_connection_->local_candidate(),
1756         /* uses_turn= */ selected_connection_->port()->Type() ==
1757             RELAY_PORT_TYPE);
1758     network_route_->remote = CreateRouteEndpointFromCandidate(
1759         /* local= */ false, selected_connection_->remote_candidate(),
1760         /* uses_turn= */ selected_connection_->remote_candidate().type() ==
1761             RELAY_PORT_TYPE);
1762 
1763     network_route_->last_sent_packet_id = last_sent_packet_id_;
1764     network_route_->packet_overhead =
1765         selected_connection_->local_candidate().address().ipaddr().overhead() +
1766         GetProtocolOverhead(selected_connection_->local_candidate().protocol());
1767   } else {
1768     RTC_LOG(LS_INFO) << ToString() << ": No selected connection";
1769   }
1770 
1771   if (field_trials_.send_ping_on_switch_ice_controlling &&
1772       ice_role_ == ICEROLE_CONTROLLING && old_selected_connection != nullptr &&
1773       conn != nullptr) {
1774     PingConnection(conn);
1775     MarkConnectionPinged(conn);
1776   }
1777 
1778   SignalNetworkRouteChanged(network_route_);
1779 
1780   // Create event for candidate pair change.
1781   if (selected_connection_) {
1782     CandidatePairChangeEvent pair_change;
1783     pair_change.reason = reason.ToString();
1784     pair_change.selected_candidate_pair = *GetSelectedCandidatePair();
1785     pair_change.last_data_received_ms =
1786         selected_connection_->last_data_received();
1787     SignalCandidatePairChanged(pair_change);
1788   }
1789 
1790   ++selected_candidate_pair_changes_;
1791 
1792   ice_controller_->SetSelectedConnection(selected_connection_);
1793 }
1794 
1795 // Warning: UpdateState should eventually be called whenever a connection
1796 // is added, deleted, or the write state of any connection changes so that the
1797 // transport controller will get the up-to-date channel state. However it
1798 // should not be called too often; in the case that multiple connection states
1799 // change, it should be called after all the connection states have changed. For
1800 // example, we call this at the end of SortConnectionsAndUpdateState.
UpdateState()1801 void P2PTransportChannel::UpdateState() {
1802   RTC_DCHECK_RUN_ON(network_thread_);
1803   // If our selected connection is "presumed writable" (TURN-TURN with no
1804   // CreatePermission required), act like we're already writable to the upper
1805   // layers, so they can start media quicker.
1806   bool writable =
1807       selected_connection_ && (selected_connection_->writable() ||
1808                                PresumedWritable(selected_connection_));
1809   SetWritable(writable);
1810 
1811   bool receiving = false;
1812   for (const Connection* connection : connections()) {
1813     if (connection->receiving()) {
1814       receiving = true;
1815       break;
1816     }
1817   }
1818   SetReceiving(receiving);
1819 
1820   IceTransportState state = ComputeState();
1821   webrtc::IceTransportState current_standardized_state =
1822       ComputeIceTransportState();
1823 
1824   if (state_ != state) {
1825     RTC_LOG(LS_INFO) << ToString() << ": Transport channel state changed from "
1826                      << static_cast<int>(state_) << " to "
1827                      << static_cast<int>(state);
1828     // Check that the requested transition is allowed. Note that
1829     // P2PTransportChannel does not (yet) implement a direct mapping of the ICE
1830     // states from the standard; the difference is covered by
1831     // TransportController and PeerConnection.
1832     switch (state_) {
1833       case IceTransportState::STATE_INIT:
1834         // TODO(deadbeef): Once we implement end-of-candidates signaling,
1835         // we shouldn't go from INIT to COMPLETED.
1836         RTC_DCHECK(state == IceTransportState::STATE_CONNECTING ||
1837                    state == IceTransportState::STATE_COMPLETED ||
1838                    state == IceTransportState::STATE_FAILED);
1839         break;
1840       case IceTransportState::STATE_CONNECTING:
1841         RTC_DCHECK(state == IceTransportState::STATE_COMPLETED ||
1842                    state == IceTransportState::STATE_FAILED);
1843         break;
1844       case IceTransportState::STATE_COMPLETED:
1845         // TODO(deadbeef): Once we implement end-of-candidates signaling,
1846         // we shouldn't go from COMPLETED to CONNECTING.
1847         // Though we *can* go from COMPlETED to FAILED, if consent expires.
1848         RTC_DCHECK(state == IceTransportState::STATE_CONNECTING ||
1849                    state == IceTransportState::STATE_FAILED);
1850         break;
1851       case IceTransportState::STATE_FAILED:
1852         // TODO(deadbeef): Once we implement end-of-candidates signaling,
1853         // we shouldn't go from FAILED to CONNECTING or COMPLETED.
1854         RTC_DCHECK(state == IceTransportState::STATE_CONNECTING ||
1855                    state == IceTransportState::STATE_COMPLETED);
1856         break;
1857       default:
1858         RTC_NOTREACHED();
1859         break;
1860     }
1861     state_ = state;
1862     SignalStateChanged(this);
1863   }
1864 
1865   if (standardized_state_ != current_standardized_state) {
1866     standardized_state_ = current_standardized_state;
1867     SignalIceTransportStateChanged(this);
1868   }
1869 }
1870 
MaybeStopPortAllocatorSessions()1871 void P2PTransportChannel::MaybeStopPortAllocatorSessions() {
1872   RTC_DCHECK_RUN_ON(network_thread_);
1873   if (!IsGettingPorts()) {
1874     return;
1875   }
1876 
1877   for (const auto& session : allocator_sessions_) {
1878     if (session->IsStopped()) {
1879       continue;
1880     }
1881     // If gathering continually, keep the last session running so that
1882     // it can gather candidates if the networks change.
1883     if (config_.gather_continually() && session == allocator_sessions_.back()) {
1884       session->ClearGettingPorts();
1885     } else {
1886       session->StopGettingPorts();
1887     }
1888   }
1889 }
1890 
1891 // If all connections timed out, delete them all.
HandleAllTimedOut()1892 void P2PTransportChannel::HandleAllTimedOut() {
1893   RTC_DCHECK_RUN_ON(network_thread_);
1894   for (Connection* connection : connections()) {
1895     connection->Destroy();
1896   }
1897 }
1898 
ReadyToSend(Connection * connection) const1899 bool P2PTransportChannel::ReadyToSend(Connection* connection) const {
1900   RTC_DCHECK_RUN_ON(network_thread_);
1901   // Note that we allow sending on an unreliable connection, because it's
1902   // possible that it became unreliable simply due to bad chance.
1903   // So this shouldn't prevent attempting to send media.
1904   return connection != nullptr &&
1905          (connection->writable() ||
1906           connection->write_state() == Connection::STATE_WRITE_UNRELIABLE ||
1907           PresumedWritable(connection));
1908 }
1909 
1910 // Handle queued up check-and-ping request
CheckAndPing()1911 void P2PTransportChannel::CheckAndPing() {
1912   RTC_DCHECK_RUN_ON(network_thread_);
1913   // Make sure the states of the connections are up-to-date (since this affects
1914   // which ones are pingable).
1915   UpdateConnectionStates();
1916 
1917   auto result = ice_controller_->SelectConnectionToPing(last_ping_sent_ms_);
1918   int delay = result.recheck_delay_ms;
1919 
1920   if (result.connection.value_or(nullptr)) {
1921     Connection* conn = FromIceController(*result.connection);
1922     PingConnection(conn);
1923     MarkConnectionPinged(conn);
1924   }
1925 
1926   invoker_.AsyncInvokeDelayed<void>(
1927       RTC_FROM_HERE, thread(),
1928       rtc::Bind(&P2PTransportChannel::CheckAndPing, this), delay);
1929 }
1930 
1931 // This method is only for unit testing.
FindNextPingableConnection()1932 Connection* P2PTransportChannel::FindNextPingableConnection() {
1933   RTC_DCHECK_RUN_ON(network_thread_);
1934   auto* conn = ice_controller_->FindNextPingableConnection();
1935   if (conn) {
1936     return FromIceController(conn);
1937   } else {
1938     return nullptr;
1939   }
1940 }
1941 
1942 // A connection is considered a backup connection if the channel state
1943 // is completed, the connection is not the selected connection and it is active.
MarkConnectionPinged(Connection * conn)1944 void P2PTransportChannel::MarkConnectionPinged(Connection* conn) {
1945   RTC_DCHECK_RUN_ON(network_thread_);
1946   ice_controller_->MarkConnectionPinged(conn);
1947 }
1948 
1949 // Apart from sending ping from |conn| this method also updates
1950 // |use_candidate_attr| and |nomination| flags. One of the flags is set to
1951 // nominate |conn| if this channel is in CONTROLLING.
PingConnection(Connection * conn)1952 void P2PTransportChannel::PingConnection(Connection* conn) {
1953   RTC_DCHECK_RUN_ON(network_thread_);
1954   bool use_candidate_attr = false;
1955   uint32_t nomination = 0;
1956   if (ice_role_ == ICEROLE_CONTROLLING) {
1957     bool renomination_supported = ice_parameters_.renomination &&
1958                                   !remote_ice_parameters_.empty() &&
1959                                   remote_ice_parameters_.back().renomination;
1960     if (renomination_supported) {
1961       nomination = GetNominationAttr(conn);
1962     } else {
1963       use_candidate_attr = GetUseCandidateAttr(conn);
1964     }
1965   }
1966   conn->set_nomination(nomination);
1967   conn->set_use_candidate_attr(use_candidate_attr);
1968   last_ping_sent_ms_ = rtc::TimeMillis();
1969   conn->Ping(last_ping_sent_ms_);
1970 }
1971 
GetNominationAttr(Connection * conn) const1972 uint32_t P2PTransportChannel::GetNominationAttr(Connection* conn) const {
1973   RTC_DCHECK_RUN_ON(network_thread_);
1974   return (conn == selected_connection_) ? nomination_ : 0;
1975 }
1976 
1977 // Nominate a connection based on the NominationMode.
GetUseCandidateAttr(Connection * conn) const1978 bool P2PTransportChannel::GetUseCandidateAttr(Connection* conn) const {
1979   RTC_DCHECK_RUN_ON(network_thread_);
1980   return ice_controller_->GetUseCandidateAttr(
1981       conn, config_.default_nomination_mode, remote_ice_mode_);
1982 }
1983 
1984 // When a connection's state changes, we need to figure out who to use as
1985 // the selected connection again.  It could have become usable, or become
1986 // unusable.
OnConnectionStateChange(Connection * connection)1987 void P2PTransportChannel::OnConnectionStateChange(Connection* connection) {
1988   RTC_DCHECK_RUN_ON(network_thread_);
1989 
1990   // May stop the allocator session when at least one connection becomes
1991   // strongly connected after starting to get ports and the local candidate of
1992   // the connection is at the latest generation. It is not enough to check
1993   // that the connection becomes weakly connected because the connection may be
1994   // changing from (writable, receiving) to (writable, not receiving).
1995   bool strongly_connected = !connection->weak();
1996   bool latest_generation = connection->local_candidate().generation() >=
1997                            allocator_session()->generation();
1998   if (strongly_connected && latest_generation) {
1999     MaybeStopPortAllocatorSessions();
2000   }
2001   // We have to unroll the stack before doing this because we may be changing
2002   // the state of connections while sorting.
2003   RequestSortAndStateUpdate(
2004       IceControllerEvent::CONNECT_STATE_CHANGE);  // "candidate pair state
2005                                                   // changed");
2006 }
2007 
2008 // When a connection is removed, edit it out, and then update our best
2009 // connection.
OnConnectionDestroyed(Connection * connection)2010 void P2PTransportChannel::OnConnectionDestroyed(Connection* connection) {
2011   RTC_DCHECK_RUN_ON(network_thread_);
2012 
2013   // Note: the previous selected_connection_ may be destroyed by now, so don't
2014   // use it.
2015 
2016   // Remove this connection from the list.
2017   ice_controller_->OnConnectionDestroyed(connection);
2018 
2019   RTC_LOG(LS_INFO) << ToString() << ": Removed connection " << connection
2020                    << " (" << connections().size() << " remaining)";
2021 
2022   // If this is currently the selected connection, then we need to pick a new
2023   // one. The call to SortConnectionsAndUpdateState will pick a new one. It
2024   // looks at the current selected connection in order to avoid switching
2025   // between fairly similar ones. Since this connection is no longer an option,
2026   // we can just set selected to nullptr and re-choose a best assuming that
2027   // there was no selected connection.
2028   if (selected_connection_ == connection) {
2029     RTC_LOG(LS_INFO) << "Selected connection destroyed. Will choose a new one.";
2030     IceControllerEvent reason =
2031         IceControllerEvent::SELECTED_CONNECTION_DESTROYED;
2032     SwitchSelectedConnection(nullptr, reason);
2033     RequestSortAndStateUpdate(reason);
2034   } else {
2035     // If a non-selected connection was destroyed, we don't need to re-sort but
2036     // we do need to update state, because we could be switching to "failed" or
2037     // "completed".
2038     UpdateState();
2039   }
2040 }
2041 
2042 // When a port is destroyed, remove it from our list of ports to use for
2043 // connection attempts.
OnPortDestroyed(PortInterface * port)2044 void P2PTransportChannel::OnPortDestroyed(PortInterface* port) {
2045   RTC_DCHECK_RUN_ON(network_thread_);
2046 
2047   ports_.erase(std::remove(ports_.begin(), ports_.end(), port), ports_.end());
2048   pruned_ports_.erase(
2049       std::remove(pruned_ports_.begin(), pruned_ports_.end(), port),
2050       pruned_ports_.end());
2051   RTC_LOG(INFO) << "Removed port because it is destroyed: " << ports_.size()
2052                 << " remaining";
2053 }
2054 
OnPortsPruned(PortAllocatorSession * session,const std::vector<PortInterface * > & ports)2055 void P2PTransportChannel::OnPortsPruned(
2056     PortAllocatorSession* session,
2057     const std::vector<PortInterface*>& ports) {
2058   RTC_DCHECK_RUN_ON(network_thread_);
2059   for (PortInterface* port : ports) {
2060     if (PrunePort(port)) {
2061       RTC_LOG(INFO) << "Removed port: " << port->ToString() << " "
2062                     << ports_.size() << " remaining";
2063     }
2064   }
2065 }
2066 
OnCandidatesRemoved(PortAllocatorSession * session,const std::vector<Candidate> & candidates)2067 void P2PTransportChannel::OnCandidatesRemoved(
2068     PortAllocatorSession* session,
2069     const std::vector<Candidate>& candidates) {
2070   RTC_DCHECK_RUN_ON(network_thread_);
2071   // Do not signal candidate removals if continual gathering is not enabled, or
2072   // if this is not the last session because an ICE restart would have signaled
2073   // the remote side to remove all candidates in previous sessions.
2074   if (!config_.gather_continually() || session != allocator_session()) {
2075     return;
2076   }
2077 
2078   std::vector<Candidate> candidates_to_remove;
2079   for (Candidate candidate : candidates) {
2080     candidate.set_transport_name(transport_name());
2081     candidates_to_remove.push_back(candidate);
2082   }
2083   SignalCandidatesRemoved(this, candidates_to_remove);
2084 }
2085 
PruneAllPorts()2086 void P2PTransportChannel::PruneAllPorts() {
2087   RTC_DCHECK_RUN_ON(network_thread_);
2088   pruned_ports_.insert(pruned_ports_.end(), ports_.begin(), ports_.end());
2089   ports_.clear();
2090 }
2091 
PrunePort(PortInterface * port)2092 bool P2PTransportChannel::PrunePort(PortInterface* port) {
2093   RTC_DCHECK_RUN_ON(network_thread_);
2094   auto it = absl::c_find(ports_, port);
2095   // Don't need to do anything if the port has been deleted from the port list.
2096   if (it == ports_.end()) {
2097     return false;
2098   }
2099   ports_.erase(it);
2100   pruned_ports_.push_back(port);
2101   return true;
2102 }
2103 
2104 // We data is available, let listeners know
OnReadPacket(Connection * connection,const char * data,size_t len,int64_t packet_time_us)2105 void P2PTransportChannel::OnReadPacket(Connection* connection,
2106                                        const char* data,
2107                                        size_t len,
2108                                        int64_t packet_time_us) {
2109   RTC_DCHECK_RUN_ON(network_thread_);
2110 
2111   if (connection == selected_connection_) {
2112     // Let the client know of an incoming packet
2113     SignalReadPacket(this, data, len, packet_time_us, 0);
2114     return;
2115   }
2116 
2117   // Do not deliver, if packet doesn't belong to the correct transport channel.
2118   if (!FindConnection(connection))
2119     return;
2120 
2121   // Let the client know of an incoming packet
2122   SignalReadPacket(this, data, len, packet_time_us, 0);
2123 
2124   // May need to switch the sending connection based on the receiving media path
2125   // if this is the controlled side.
2126   if (ice_role_ == ICEROLE_CONTROLLED) {
2127     MaybeSwitchSelectedConnection(connection,
2128                                   IceControllerEvent::DATA_RECEIVED);
2129   }
2130 }
2131 
OnSentPacket(const rtc::SentPacket & sent_packet)2132 void P2PTransportChannel::OnSentPacket(const rtc::SentPacket& sent_packet) {
2133   RTC_DCHECK_RUN_ON(network_thread_);
2134 
2135   SignalSentPacket(this, sent_packet);
2136 }
2137 
OnReadyToSend(Connection * connection)2138 void P2PTransportChannel::OnReadyToSend(Connection* connection) {
2139   RTC_DCHECK_RUN_ON(network_thread_);
2140   if (connection == selected_connection_ && writable()) {
2141     SignalReadyToSend(this);
2142   }
2143 }
2144 
SetWritable(bool writable)2145 void P2PTransportChannel::SetWritable(bool writable) {
2146   RTC_DCHECK_RUN_ON(network_thread_);
2147   if (writable_ == writable) {
2148     return;
2149   }
2150   RTC_LOG(LS_VERBOSE) << ToString() << ": Changed writable_ to " << writable;
2151   writable_ = writable;
2152   if (writable_) {
2153     has_been_writable_ = true;
2154     SignalReadyToSend(this);
2155   }
2156   SignalWritableState(this);
2157 }
2158 
SetReceiving(bool receiving)2159 void P2PTransportChannel::SetReceiving(bool receiving) {
2160   RTC_DCHECK_RUN_ON(network_thread_);
2161   if (receiving_ == receiving) {
2162     return;
2163   }
2164   receiving_ = receiving;
2165   SignalReceivingState(this);
2166 }
2167 
SanitizeLocalCandidate(const Candidate & c) const2168 Candidate P2PTransportChannel::SanitizeLocalCandidate(
2169     const Candidate& c) const {
2170   RTC_DCHECK_RUN_ON(network_thread_);
2171   // Delegates to the port allocator.
2172   return allocator_->SanitizeCandidate(c);
2173 }
2174 
SanitizeRemoteCandidate(const Candidate & c) const2175 Candidate P2PTransportChannel::SanitizeRemoteCandidate(
2176     const Candidate& c) const {
2177   RTC_DCHECK_RUN_ON(network_thread_);
2178   // If the remote endpoint signaled us an mDNS candidate, we assume it
2179   // is supposed to be sanitized.
2180   bool use_hostname_address = absl::EndsWith(c.address().hostname(), LOCAL_TLD);
2181   // Remove the address for prflx remote candidates. See
2182   // https://w3c.github.io/webrtc-stats/#dom-rtcicecandidatestats.
2183   use_hostname_address |= c.type() == PRFLX_PORT_TYPE;
2184   return c.ToSanitizedCopy(use_hostname_address,
2185                            false /* filter_related_address */);
2186 }
2187 
LogCandidatePairConfig(Connection * conn,webrtc::IceCandidatePairConfigType type)2188 void P2PTransportChannel::LogCandidatePairConfig(
2189     Connection* conn,
2190     webrtc::IceCandidatePairConfigType type) {
2191   RTC_DCHECK_RUN_ON(network_thread_);
2192   if (conn == nullptr) {
2193     return;
2194   }
2195   ice_event_log_.LogCandidatePairConfig(type, conn->id(),
2196                                         conn->ToLogDescription());
2197 }
2198 
2199 }  // namespace cricket
2200