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