• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright 2019 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/connection.h"
12 
13 #include <math.h>
14 
15 #include <algorithm>
16 #include <memory>
17 #include <utility>
18 #include <vector>
19 
20 #include "absl/algorithm/container.h"
21 #include "absl/strings/escaping.h"
22 #include "absl/strings/match.h"
23 #include "absl/strings/string_view.h"
24 #include "p2p/base/port_allocator.h"
25 #include "rtc_base/checks.h"
26 #include "rtc_base/crc32.h"
27 #include "rtc_base/helpers.h"
28 #include "rtc_base/logging.h"
29 #include "rtc_base/mdns_responder_interface.h"
30 #include "rtc_base/message_digest.h"
31 #include "rtc_base/network.h"
32 #include "rtc_base/numerics/safe_minmax.h"
33 #include "rtc_base/string_encode.h"
34 #include "rtc_base/string_utils.h"
35 #include "rtc_base/strings/string_builder.h"
36 #include "rtc_base/third_party/base64/base64.h"
37 
38 namespace cricket {
39 namespace {
40 
41 // Determines whether we have seen at least the given maximum number of
42 // pings fail to have a response.
TooManyFailures(const std::vector<Connection::SentPing> & pings_since_last_response,uint32_t maximum_failures,int rtt_estimate,int64_t now)43 inline bool TooManyFailures(
44     const std::vector<Connection::SentPing>& pings_since_last_response,
45     uint32_t maximum_failures,
46     int rtt_estimate,
47     int64_t now) {
48   // If we haven't sent that many pings, then we can't have failed that many.
49   if (pings_since_last_response.size() < maximum_failures)
50     return false;
51 
52   // Check if the window in which we would expect a response to the ping has
53   // already elapsed.
54   int64_t expected_response_time =
55       pings_since_last_response[maximum_failures - 1].sent_time + rtt_estimate;
56   return now > expected_response_time;
57 }
58 
59 // Determines whether we have gone too long without seeing any response.
TooLongWithoutResponse(const std::vector<Connection::SentPing> & pings_since_last_response,int64_t maximum_time,int64_t now)60 inline bool TooLongWithoutResponse(
61     const std::vector<Connection::SentPing>& pings_since_last_response,
62     int64_t maximum_time,
63     int64_t now) {
64   if (pings_since_last_response.size() == 0)
65     return false;
66 
67   auto first = pings_since_last_response[0];
68   return now > (first.sent_time + maximum_time);
69 }
70 
71 // Helper methods for converting string values of log description fields to
72 // enum.
GetCandidateTypeByString(absl::string_view type)73 webrtc::IceCandidateType GetCandidateTypeByString(absl::string_view type) {
74   if (type == LOCAL_PORT_TYPE) {
75     return webrtc::IceCandidateType::kLocal;
76   } else if (type == STUN_PORT_TYPE) {
77     return webrtc::IceCandidateType::kStun;
78   } else if (type == PRFLX_PORT_TYPE) {
79     return webrtc::IceCandidateType::kPrflx;
80   } else if (type == RELAY_PORT_TYPE) {
81     return webrtc::IceCandidateType::kRelay;
82   }
83   return webrtc::IceCandidateType::kUnknown;
84 }
85 
GetProtocolByString(absl::string_view protocol)86 webrtc::IceCandidatePairProtocol GetProtocolByString(
87     absl::string_view protocol) {
88   if (protocol == UDP_PROTOCOL_NAME) {
89     return webrtc::IceCandidatePairProtocol::kUdp;
90   } else if (protocol == TCP_PROTOCOL_NAME) {
91     return webrtc::IceCandidatePairProtocol::kTcp;
92   } else if (protocol == SSLTCP_PROTOCOL_NAME) {
93     return webrtc::IceCandidatePairProtocol::kSsltcp;
94   } else if (protocol == TLS_PROTOCOL_NAME) {
95     return webrtc::IceCandidatePairProtocol::kTls;
96   }
97   return webrtc::IceCandidatePairProtocol::kUnknown;
98 }
99 
GetAddressFamilyByInt(int address_family)100 webrtc::IceCandidatePairAddressFamily GetAddressFamilyByInt(
101     int address_family) {
102   if (address_family == AF_INET) {
103     return webrtc::IceCandidatePairAddressFamily::kIpv4;
104   } else if (address_family == AF_INET6) {
105     return webrtc::IceCandidatePairAddressFamily::kIpv6;
106   }
107   return webrtc::IceCandidatePairAddressFamily::kUnknown;
108 }
109 
ConvertNetworkType(rtc::AdapterType type)110 webrtc::IceCandidateNetworkType ConvertNetworkType(rtc::AdapterType type) {
111   switch (type) {
112     case rtc::ADAPTER_TYPE_ETHERNET:
113       return webrtc::IceCandidateNetworkType::kEthernet;
114     case rtc::ADAPTER_TYPE_LOOPBACK:
115       return webrtc::IceCandidateNetworkType::kLoopback;
116     case rtc::ADAPTER_TYPE_WIFI:
117       return webrtc::IceCandidateNetworkType::kWifi;
118     case rtc::ADAPTER_TYPE_VPN:
119       return webrtc::IceCandidateNetworkType::kVpn;
120     case rtc::ADAPTER_TYPE_CELLULAR:
121     case rtc::ADAPTER_TYPE_CELLULAR_2G:
122     case rtc::ADAPTER_TYPE_CELLULAR_3G:
123     case rtc::ADAPTER_TYPE_CELLULAR_4G:
124     case rtc::ADAPTER_TYPE_CELLULAR_5G:
125       return webrtc::IceCandidateNetworkType::kCellular;
126     default:
127       return webrtc::IceCandidateNetworkType::kUnknown;
128   }
129 }
130 
131 // When we don't have any RTT data, we have to pick something reasonable.  We
132 // use a large value just in case the connection is really slow.
133 const int DEFAULT_RTT = 3000;  // 3 seconds
134 
135 // We will restrict RTT estimates (when used for determining state) to be
136 // within a reasonable range.
137 const int MINIMUM_RTT = 100;    // 0.1 seconds
138 const int MAXIMUM_RTT = 60000;  // 60 seconds
139 
140 const int DEFAULT_RTT_ESTIMATE_HALF_TIME_MS = 500;
141 
142 // Computes our estimate of the RTT given the current estimate.
ConservativeRTTEstimate(int rtt)143 inline int ConservativeRTTEstimate(int rtt) {
144   return rtc::SafeClamp(2 * rtt, MINIMUM_RTT, MAXIMUM_RTT);
145 }
146 
147 // Weighting of the old rtt value to new data.
148 const int RTT_RATIO = 3;  // 3 : 1
149 
150 constexpr int64_t kMinExtraPingDelayMs = 100;
151 
152 // Default field trials.
153 const IceFieldTrials kDefaultFieldTrials;
154 
155 constexpr int kSupportGoogPingVersionRequestIndex = static_cast<int>(
156     IceGoogMiscInfoBindingRequestAttributeIndex::SUPPORT_GOOG_PING_VERSION);
157 
158 constexpr int kSupportGoogPingVersionResponseIndex = static_cast<int>(
159     IceGoogMiscInfoBindingResponseAttributeIndex::SUPPORT_GOOG_PING_VERSION);
160 
161 }  // namespace
162 
163 // A ConnectionRequest is a STUN binding used to determine writability.
164 class Connection::ConnectionRequest : public StunRequest {
165  public:
166   ConnectionRequest(StunRequestManager& manager,
167                     Connection* connection,
168                     std::unique_ptr<IceMessage> message);
169   void OnResponse(StunMessage* response) override;
170   void OnErrorResponse(StunMessage* response) override;
171   void OnTimeout() override;
172   void OnSent() override;
173   int resend_delay() override;
174 
175  private:
176   Connection* const connection_;
177 };
178 
ConnectionRequest(StunRequestManager & manager,Connection * connection,std::unique_ptr<IceMessage> message)179 Connection::ConnectionRequest::ConnectionRequest(
180     StunRequestManager& manager,
181     Connection* connection,
182     std::unique_ptr<IceMessage> message)
183     : StunRequest(manager, std::move(message)), connection_(connection) {}
184 
OnResponse(StunMessage * response)185 void Connection::ConnectionRequest::OnResponse(StunMessage* response) {
186   RTC_DCHECK_RUN_ON(connection_->network_thread_);
187   connection_->OnConnectionRequestResponse(this, response);
188 }
189 
OnErrorResponse(StunMessage * response)190 void Connection::ConnectionRequest::OnErrorResponse(StunMessage* response) {
191   RTC_DCHECK_RUN_ON(connection_->network_thread_);
192   connection_->OnConnectionRequestErrorResponse(this, response);
193 }
194 
OnTimeout()195 void Connection::ConnectionRequest::OnTimeout() {
196   RTC_DCHECK_RUN_ON(connection_->network_thread_);
197   connection_->OnConnectionRequestTimeout(this);
198 }
199 
OnSent()200 void Connection::ConnectionRequest::OnSent() {
201   RTC_DCHECK_RUN_ON(connection_->network_thread_);
202   connection_->OnConnectionRequestSent(this);
203   // Each request is sent only once.  After a single delay , the request will
204   // time out.
205   set_timed_out();
206 }
207 
resend_delay()208 int Connection::ConnectionRequest::resend_delay() {
209   return CONNECTION_RESPONSE_TIMEOUT;
210 }
211 
Connection(rtc::WeakPtr<Port> port,size_t index,const Candidate & remote_candidate)212 Connection::Connection(rtc::WeakPtr<Port> port,
213                        size_t index,
214                        const Candidate& remote_candidate)
215     : network_thread_(port->thread()),
216       id_(rtc::CreateRandomId()),
217       port_(std::move(port)),
218       local_candidate_(port_->Candidates()[index]),
219       remote_candidate_(remote_candidate),
220       recv_rate_tracker_(100, 10u),
221       send_rate_tracker_(100, 10u),
222       write_state_(STATE_WRITE_INIT),
223       receiving_(false),
224       connected_(true),
225       pruned_(false),
226       use_candidate_attr_(false),
227       requests_(port_->thread(),
228                 [this](const void* data, size_t size, StunRequest* request) {
229                   OnSendStunPacket(data, size, request);
230                 }),
231       rtt_(DEFAULT_RTT),
232       last_ping_sent_(0),
233       last_ping_received_(0),
234       last_data_received_(0),
235       last_ping_response_received_(0),
236       state_(IceCandidatePairState::WAITING),
237       time_created_ms_(rtc::TimeMillis()),
238       delta_internal_unix_epoch_ms_(rtc::TimeUTCMillis() - rtc::TimeMillis()),
239       field_trials_(&kDefaultFieldTrials),
240       rtt_estimate_(DEFAULT_RTT_ESTIMATE_HALF_TIME_MS) {
241   RTC_DCHECK_RUN_ON(network_thread_);
242   RTC_DCHECK(port_);
243   RTC_LOG(LS_INFO) << ToString() << ": Connection created";
244 }
245 
~Connection()246 Connection::~Connection() {
247   RTC_DCHECK_RUN_ON(network_thread_);
248   RTC_DCHECK(!port_);
249 }
250 
network_thread() const251 webrtc::TaskQueueBase* Connection::network_thread() const {
252   return network_thread_;
253 }
254 
local_candidate() const255 const Candidate& Connection::local_candidate() const {
256   RTC_DCHECK_RUN_ON(network_thread_);
257   return local_candidate_;
258 }
259 
remote_candidate() const260 const Candidate& Connection::remote_candidate() const {
261   return remote_candidate_;
262 }
263 
network() const264 const rtc::Network* Connection::network() const {
265   return port()->Network();
266 }
267 
generation() const268 int Connection::generation() const {
269   return port()->generation();
270 }
271 
priority() const272 uint64_t Connection::priority() const {
273   if (!port_)
274     return 0;
275 
276   uint64_t priority = 0;
277   // RFC 5245 - 5.7.2.  Computing Pair Priority and Ordering Pairs
278   // Let G be the priority for the candidate provided by the controlling
279   // agent.  Let D be the priority for the candidate provided by the
280   // controlled agent.
281   // pair priority = 2^32*MIN(G,D) + 2*MAX(G,D) + (G>D?1:0)
282   IceRole role = port_->GetIceRole();
283   if (role != ICEROLE_UNKNOWN) {
284     uint32_t g = 0;
285     uint32_t d = 0;
286     if (role == ICEROLE_CONTROLLING) {
287       g = local_candidate().priority();
288       d = remote_candidate_.priority();
289     } else {
290       g = remote_candidate_.priority();
291       d = local_candidate().priority();
292     }
293     priority = std::min(g, d);
294     priority = priority << 32;
295     priority += 2 * std::max(g, d) + (g > d ? 1 : 0);
296   }
297   return priority;
298 }
299 
set_write_state(WriteState value)300 void Connection::set_write_state(WriteState value) {
301   RTC_DCHECK_RUN_ON(network_thread_);
302   WriteState old_value = write_state_;
303   write_state_ = value;
304   if (value != old_value) {
305     RTC_LOG(LS_VERBOSE) << ToString() << ": set_write_state from: " << old_value
306                         << " to " << value;
307     SignalStateChange(this);
308   }
309 }
310 
UpdateReceiving(int64_t now)311 void Connection::UpdateReceiving(int64_t now) {
312   RTC_DCHECK_RUN_ON(network_thread_);
313   bool receiving;
314   if (last_ping_sent() < last_ping_response_received()) {
315     // We consider any candidate pair that has its last connectivity check
316     // acknowledged by a response as receiving, particularly for backup
317     // candidate pairs that send checks at a much slower pace than the selected
318     // one. Otherwise, a backup candidate pair constantly becomes not receiving
319     // as a side effect of a long ping interval, since we do not have a separate
320     // receiving timeout for backup candidate pairs. See
321     // IceConfig.ice_backup_candidate_pair_ping_interval,
322     // IceConfig.ice_connection_receiving_timeout and their default value.
323     receiving = true;
324   } else {
325     receiving =
326         last_received() > 0 && now <= last_received() + receiving_timeout();
327   }
328   if (receiving_ == receiving) {
329     return;
330   }
331   RTC_LOG(LS_VERBOSE) << ToString() << ": set_receiving to " << receiving;
332   receiving_ = receiving;
333   receiving_unchanged_since_ = now;
334   SignalStateChange(this);
335 }
336 
set_state(IceCandidatePairState state)337 void Connection::set_state(IceCandidatePairState state) {
338   RTC_DCHECK_RUN_ON(network_thread_);
339   IceCandidatePairState old_state = state_;
340   state_ = state;
341   if (state != old_state) {
342     RTC_LOG(LS_VERBOSE) << ToString() << ": set_state";
343   }
344 }
345 
set_connected(bool value)346 void Connection::set_connected(bool value) {
347   RTC_DCHECK_RUN_ON(network_thread_);
348   bool old_value = connected_;
349   connected_ = value;
350   if (value != old_value) {
351     RTC_LOG(LS_VERBOSE) << ToString() << ": Change connected_ to " << value;
352     SignalStateChange(this);
353   }
354 }
355 
use_candidate_attr() const356 bool Connection::use_candidate_attr() const {
357   RTC_DCHECK_RUN_ON(network_thread_);
358   return use_candidate_attr_;
359 }
360 
set_use_candidate_attr(bool enable)361 void Connection::set_use_candidate_attr(bool enable) {
362   RTC_DCHECK_RUN_ON(network_thread_);
363   use_candidate_attr_ = enable;
364 }
365 
set_nomination(uint32_t value)366 void Connection::set_nomination(uint32_t value) {
367   RTC_DCHECK_RUN_ON(network_thread_);
368   nomination_ = value;
369 }
370 
remote_nomination() const371 uint32_t Connection::remote_nomination() const {
372   RTC_DCHECK_RUN_ON(network_thread_);
373   return remote_nomination_;
374 }
375 
nominated() const376 bool Connection::nominated() const {
377   RTC_DCHECK_RUN_ON(network_thread_);
378   return acked_nomination_ || remote_nomination_;
379 }
380 
unwritable_timeout() const381 int Connection::unwritable_timeout() const {
382   RTC_DCHECK_RUN_ON(network_thread_);
383   return unwritable_timeout_.value_or(CONNECTION_WRITE_CONNECT_TIMEOUT);
384 }
385 
set_unwritable_timeout(const absl::optional<int> & value_ms)386 void Connection::set_unwritable_timeout(const absl::optional<int>& value_ms) {
387   RTC_DCHECK_RUN_ON(network_thread_);
388   unwritable_timeout_ = value_ms;
389 }
390 
unwritable_min_checks() const391 int Connection::unwritable_min_checks() const {
392   RTC_DCHECK_RUN_ON(network_thread_);
393   return unwritable_min_checks_.value_or(CONNECTION_WRITE_CONNECT_FAILURES);
394 }
395 
set_unwritable_min_checks(const absl::optional<int> & value)396 void Connection::set_unwritable_min_checks(const absl::optional<int>& value) {
397   RTC_DCHECK_RUN_ON(network_thread_);
398   unwritable_min_checks_ = value;
399 }
400 
inactive_timeout() const401 int Connection::inactive_timeout() const {
402   RTC_DCHECK_RUN_ON(network_thread_);
403   return inactive_timeout_.value_or(CONNECTION_WRITE_TIMEOUT);
404 }
405 
set_inactive_timeout(const absl::optional<int> & value)406 void Connection::set_inactive_timeout(const absl::optional<int>& value) {
407   RTC_DCHECK_RUN_ON(network_thread_);
408   inactive_timeout_ = value;
409 }
410 
receiving_timeout() const411 int Connection::receiving_timeout() const {
412   RTC_DCHECK_RUN_ON(network_thread_);
413   return receiving_timeout_.value_or(WEAK_CONNECTION_RECEIVE_TIMEOUT);
414 }
415 
set_receiving_timeout(absl::optional<int> receiving_timeout_ms)416 void Connection::set_receiving_timeout(
417     absl::optional<int> receiving_timeout_ms) {
418   RTC_DCHECK_RUN_ON(network_thread_);
419   receiving_timeout_ = receiving_timeout_ms;
420 }
421 
SetIceFieldTrials(const IceFieldTrials * field_trials)422 void Connection::SetIceFieldTrials(const IceFieldTrials* field_trials) {
423   RTC_DCHECK_RUN_ON(network_thread_);
424   field_trials_ = field_trials;
425   rtt_estimate_.SetHalfTime(field_trials->rtt_estimate_halftime_ms);
426 }
427 
OnSendStunPacket(const void * data,size_t size,StunRequest * req)428 void Connection::OnSendStunPacket(const void* data,
429                                   size_t size,
430                                   StunRequest* req) {
431   RTC_DCHECK_RUN_ON(network_thread_);
432   rtc::PacketOptions options(port_->StunDscpValue());
433   options.info_signaled_after_sent.packet_type =
434       rtc::PacketType::kIceConnectivityCheck;
435   auto err =
436       port_->SendTo(data, size, remote_candidate_.address(), options, false);
437   if (err < 0) {
438     RTC_LOG(LS_WARNING) << ToString()
439                         << ": Failed to send STUN ping "
440                            " err="
441                         << err << " id=" << rtc::hex_encode(req->id());
442   }
443 }
444 
OnReadPacket(const char * data,size_t size,int64_t packet_time_us)445 void Connection::OnReadPacket(const char* data,
446                               size_t size,
447                               int64_t packet_time_us) {
448   RTC_DCHECK_RUN_ON(network_thread_);
449   std::unique_ptr<IceMessage> msg;
450   std::string remote_ufrag;
451   const rtc::SocketAddress& addr(remote_candidate_.address());
452   if (!port_->GetStunMessage(data, size, addr, &msg, &remote_ufrag)) {
453     // The packet did not parse as a valid STUN message
454     // This is a data packet, pass it along.
455     last_data_received_ = rtc::TimeMillis();
456     UpdateReceiving(last_data_received_);
457     recv_rate_tracker_.AddSamples(size);
458     stats_.packets_received++;
459     SignalReadPacket(this, data, size, packet_time_us);
460 
461     // If timed out sending writability checks, start up again
462     if (!pruned_ && (write_state_ == STATE_WRITE_TIMEOUT)) {
463       RTC_LOG(LS_WARNING)
464           << "Received a data packet on a timed-out Connection. "
465              "Resetting state to STATE_WRITE_INIT.";
466       set_write_state(STATE_WRITE_INIT);
467     }
468   } else if (!msg) {
469     // The packet was STUN, but failed a check and was handled internally.
470   } else {
471     // The packet is STUN and passed the Port checks.
472     // Perform our own checks to ensure this packet is valid.
473     // If this is a STUN request, then update the receiving bit and respond.
474     // If this is a STUN response, then update the writable bit.
475     // Log at LS_INFO if we receive a ping on an unwritable connection.
476     rtc::LoggingSeverity sev = (!writable() ? rtc::LS_INFO : rtc::LS_VERBOSE);
477     switch (msg->integrity()) {
478       case StunMessage::IntegrityStatus::kNotSet:
479         // This packet did not come through Port processing?
480         // TODO(bugs.webrtc.org/14578): Clean up this situation.
481         msg->ValidateMessageIntegrity(remote_candidate().password());
482         break;
483       case StunMessage::IntegrityStatus::kIntegrityOk:
484         if (remote_candidate().password() != msg->password()) {
485           // TODO(bugs.webrtc.org/14578): Do a better thing
486           RTC_LOG(LS_INFO) << "STUN code error - Different passwords, old = "
487                            << absl::CHexEscape(msg->password()) << ", new "
488                            << absl::CHexEscape(remote_candidate().password());
489         }
490         break;
491       default:
492         // kIntegrityBad and kNoIntegrity.
493         // This shouldn't happen.
494         RTC_DCHECK_NOTREACHED();
495         break;
496     }
497     switch (msg->type()) {
498       case STUN_BINDING_REQUEST:
499         RTC_LOG_V(sev) << ToString() << ": Received "
500                        << StunMethodToString(msg->type())
501                        << ", id=" << rtc::hex_encode(msg->transaction_id());
502         if (remote_ufrag == remote_candidate_.username()) {
503           HandleStunBindingOrGoogPingRequest(msg.get());
504         } else {
505           // The packet had the right local username, but the remote username
506           // was not the right one for the remote address.
507           RTC_LOG(LS_ERROR)
508               << ToString()
509               << ": Received STUN request with bad remote username "
510               << remote_ufrag;
511           port_->SendBindingErrorResponse(msg.get(), addr,
512                                           STUN_ERROR_UNAUTHORIZED,
513                                           STUN_ERROR_REASON_UNAUTHORIZED);
514         }
515         break;
516 
517       // Response from remote peer. Does it match request sent?
518       // This doesn't just check, it makes callbacks if transaction
519       // id's match.
520       case STUN_BINDING_RESPONSE:
521       case STUN_BINDING_ERROR_RESPONSE:
522         if (msg->IntegrityOk()) {
523           requests_.CheckResponse(msg.get());
524         }
525         // Otherwise silently discard the response.
526         break;
527 
528       // Remote end point sent an STUN indication instead of regular binding
529       // request. In this case `last_ping_received_` will be updated but no
530       // response will be sent.
531       case STUN_BINDING_INDICATION:
532         ReceivedPing(msg->transaction_id());
533         break;
534       case GOOG_PING_REQUEST:
535         HandleStunBindingOrGoogPingRequest(msg.get());
536         break;
537       case GOOG_PING_RESPONSE:
538       case GOOG_PING_ERROR_RESPONSE:
539         if (msg->IntegrityOk()) {
540           requests_.CheckResponse(msg.get());
541         }
542         break;
543       default:
544         RTC_DCHECK_NOTREACHED();
545         break;
546     }
547   }
548 }
549 
HandleStunBindingOrGoogPingRequest(IceMessage * msg)550 void Connection::HandleStunBindingOrGoogPingRequest(IceMessage* msg) {
551   RTC_DCHECK_RUN_ON(network_thread_);
552   // This connection should now be receiving.
553   ReceivedPing(msg->transaction_id());
554   if (field_trials_->extra_ice_ping && last_ping_response_received_ == 0) {
555     if (local_candidate().type() == RELAY_PORT_TYPE ||
556         local_candidate().type() == PRFLX_PORT_TYPE ||
557         remote_candidate().type() == RELAY_PORT_TYPE ||
558         remote_candidate().type() == PRFLX_PORT_TYPE) {
559       const int64_t now = rtc::TimeMillis();
560       if (last_ping_sent_ + kMinExtraPingDelayMs <= now) {
561         RTC_LOG(LS_INFO) << ToString()
562                          << "WebRTC-ExtraICEPing/Sending extra ping"
563                             " last_ping_sent_: "
564                          << last_ping_sent_ << " now: " << now
565                          << " (diff: " << (now - last_ping_sent_) << ")";
566         Ping(now);
567       } else {
568         RTC_LOG(LS_INFO) << ToString()
569                          << "WebRTC-ExtraICEPing/Not sending extra ping"
570                             " last_ping_sent_: "
571                          << last_ping_sent_ << " now: " << now
572                          << " (diff: " << (now - last_ping_sent_) << ")";
573       }
574     }
575   }
576 
577   const rtc::SocketAddress& remote_addr = remote_candidate_.address();
578   if (msg->type() == STUN_BINDING_REQUEST) {
579     // Check for role conflicts.
580     const std::string& remote_ufrag = remote_candidate_.username();
581     if (!port_->MaybeIceRoleConflict(remote_addr, msg, remote_ufrag)) {
582       // Received conflicting role from the peer.
583       RTC_LOG(LS_INFO) << "Received conflicting role from the peer.";
584       return;
585     }
586   }
587 
588   stats_.recv_ping_requests++;
589   LogCandidatePairEvent(webrtc::IceCandidatePairEventType::kCheckReceived,
590                         msg->reduced_transaction_id());
591 
592   // This is a validated stun request from remote peer.
593   if (msg->type() == STUN_BINDING_REQUEST) {
594     SendStunBindingResponse(msg);
595   } else {
596     RTC_DCHECK(msg->type() == GOOG_PING_REQUEST);
597     SendGoogPingResponse(msg);
598   }
599 
600   // If it timed out on writing check, start up again
601   if (!pruned_ && write_state_ == STATE_WRITE_TIMEOUT) {
602     set_write_state(STATE_WRITE_INIT);
603   }
604 
605   if (port_->GetIceRole() == ICEROLE_CONTROLLED) {
606     const StunUInt32Attribute* nomination_attr =
607         msg->GetUInt32(STUN_ATTR_NOMINATION);
608     uint32_t nomination = 0;
609     if (nomination_attr) {
610       nomination = nomination_attr->value();
611       if (nomination == 0) {
612         RTC_LOG(LS_ERROR) << "Invalid nomination: " << nomination;
613       }
614     } else {
615       const StunByteStringAttribute* use_candidate_attr =
616           msg->GetByteString(STUN_ATTR_USE_CANDIDATE);
617       if (use_candidate_attr) {
618         nomination = 1;
619       }
620     }
621     // We don't un-nominate a connection, so we only keep a larger nomination.
622     if (nomination > remote_nomination_) {
623       set_remote_nomination(nomination);
624       SignalNominated(this);
625     }
626   }
627   // Set the remote cost if the network_info attribute is available.
628   // Note: If packets are re-ordered, we may get incorrect network cost
629   // temporarily, but it should get the correct value shortly after that.
630   const StunUInt32Attribute* network_attr =
631       msg->GetUInt32(STUN_ATTR_GOOG_NETWORK_INFO);
632   if (network_attr) {
633     uint32_t network_info = network_attr->value();
634     uint16_t network_cost = static_cast<uint16_t>(network_info);
635     if (network_cost != remote_candidate_.network_cost()) {
636       remote_candidate_.set_network_cost(network_cost);
637       // Network cost change will affect the connection ranking, so signal
638       // state change to force a re-sort in P2PTransportChannel.
639       SignalStateChange(this);
640     }
641   }
642 
643   if (field_trials_->piggyback_ice_check_acknowledgement) {
644     HandlePiggybackCheckAcknowledgementIfAny(msg);
645   }
646 }
647 
SendStunBindingResponse(const StunMessage * message)648 void Connection::SendStunBindingResponse(const StunMessage* message) {
649   RTC_DCHECK_RUN_ON(network_thread_);
650   RTC_DCHECK_EQ(message->type(), STUN_BINDING_REQUEST);
651 
652   // Retrieve the username from the `message`.
653   const StunByteStringAttribute* username_attr =
654       message->GetByteString(STUN_ATTR_USERNAME);
655   RTC_DCHECK(username_attr != NULL);
656   if (username_attr == NULL) {
657     // No valid username, skip the response.
658     return;
659   }
660 
661   // Fill in the response.
662   StunMessage response(STUN_BINDING_RESPONSE, message->transaction_id());
663   const StunUInt32Attribute* retransmit_attr =
664       message->GetUInt32(STUN_ATTR_RETRANSMIT_COUNT);
665   if (retransmit_attr) {
666     // Inherit the incoming retransmit value in the response so the other side
667     // can see our view of lost pings.
668     response.AddAttribute(std::make_unique<StunUInt32Attribute>(
669         STUN_ATTR_RETRANSMIT_COUNT, retransmit_attr->value()));
670 
671     if (retransmit_attr->value() > CONNECTION_WRITE_CONNECT_FAILURES) {
672       RTC_LOG(LS_INFO)
673           << ToString()
674           << ": Received a remote ping with high retransmit count: "
675           << retransmit_attr->value();
676     }
677   }
678 
679   response.AddAttribute(std::make_unique<StunXorAddressAttribute>(
680       STUN_ATTR_XOR_MAPPED_ADDRESS, remote_candidate_.address()));
681 
682   if (field_trials_->announce_goog_ping) {
683     // Check if message contains a announce-request.
684     auto goog_misc = message->GetUInt16List(STUN_ATTR_GOOG_MISC_INFO);
685     if (goog_misc != nullptr &&
686         goog_misc->Size() >= kSupportGoogPingVersionRequestIndex &&
687         // Which version can we handle...currently any >= 1
688         goog_misc->GetType(kSupportGoogPingVersionRequestIndex) >= 1) {
689       auto list =
690           StunAttribute::CreateUInt16ListAttribute(STUN_ATTR_GOOG_MISC_INFO);
691       list->AddTypeAtIndex(kSupportGoogPingVersionResponseIndex,
692                            kGoogPingVersion);
693       response.AddAttribute(std::move(list));
694     }
695   }
696 
697   response.AddMessageIntegrity(local_candidate().password());
698   response.AddFingerprint();
699 
700   SendResponseMessage(response);
701 }
702 
SendGoogPingResponse(const StunMessage * message)703 void Connection::SendGoogPingResponse(const StunMessage* message) {
704   RTC_DCHECK_RUN_ON(network_thread_);
705   RTC_DCHECK(message->type() == GOOG_PING_REQUEST);
706 
707   // Fill in the response.
708   StunMessage response(GOOG_PING_RESPONSE, message->transaction_id());
709   response.AddMessageIntegrity32(local_candidate().password());
710   SendResponseMessage(response);
711 }
712 
SendResponseMessage(const StunMessage & response)713 void Connection::SendResponseMessage(const StunMessage& response) {
714   RTC_DCHECK_RUN_ON(network_thread_);
715   // Where I send the response.
716   const rtc::SocketAddress& addr = remote_candidate_.address();
717 
718   // Send the response.
719   rtc::ByteBufferWriter buf;
720   response.Write(&buf);
721   rtc::PacketOptions options(port_->StunDscpValue());
722   options.info_signaled_after_sent.packet_type =
723       rtc::PacketType::kIceConnectivityCheckResponse;
724   auto err = port_->SendTo(buf.Data(), buf.Length(), addr, options, false);
725   if (err < 0) {
726     RTC_LOG(LS_ERROR) << ToString() << ": Failed to send "
727                       << StunMethodToString(response.type())
728                       << ", to=" << addr.ToSensitiveString() << ", err=" << err
729                       << ", id=" << rtc::hex_encode(response.transaction_id());
730   } else {
731     // Log at LS_INFO if we send a stun ping response on an unwritable
732     // connection.
733     rtc::LoggingSeverity sev = (!writable()) ? rtc::LS_INFO : rtc::LS_VERBOSE;
734     RTC_LOG_V(sev) << ToString() << ": Sent "
735                    << StunMethodToString(response.type())
736                    << ", to=" << addr.ToSensitiveString()
737                    << ", id=" << rtc::hex_encode(response.transaction_id());
738 
739     stats_.sent_ping_responses++;
740     LogCandidatePairEvent(webrtc::IceCandidatePairEventType::kCheckResponseSent,
741                           response.reduced_transaction_id());
742   }
743 }
744 
acked_nomination() const745 uint32_t Connection::acked_nomination() const {
746   RTC_DCHECK_RUN_ON(network_thread_);
747   return acked_nomination_;
748 }
749 
set_remote_nomination(uint32_t remote_nomination)750 void Connection::set_remote_nomination(uint32_t remote_nomination) {
751   RTC_DCHECK_RUN_ON(network_thread_);
752   remote_nomination_ = remote_nomination;
753 }
754 
OnReadyToSend()755 void Connection::OnReadyToSend() {
756   RTC_DCHECK_RUN_ON(network_thread_);
757   SignalReadyToSend(this);
758 }
759 
pruned() const760 bool Connection::pruned() const {
761   RTC_DCHECK_RUN_ON(network_thread_);
762   return pruned_;
763 }
764 
Prune()765 void Connection::Prune() {
766   RTC_DCHECK_RUN_ON(network_thread_);
767   if (!pruned_ || active()) {
768     RTC_LOG(LS_INFO) << ToString() << ": Connection pruned";
769     pruned_ = true;
770     requests_.Clear();
771     set_write_state(STATE_WRITE_TIMEOUT);
772   }
773 }
774 
Destroy()775 void Connection::Destroy() {
776   RTC_DCHECK_RUN_ON(network_thread_);
777   RTC_DCHECK(port_) << "Calling Destroy() twice?";
778   if (port_)
779     port_->DestroyConnection(this);
780 }
781 
Shutdown()782 bool Connection::Shutdown() {
783   RTC_DCHECK_RUN_ON(network_thread_);
784   if (!port_)
785     return false;  // already shut down.
786 
787   RTC_DLOG(LS_VERBOSE) << ToString() << ": Connection destroyed";
788 
789   // Fire the 'destroyed' event before deleting the object. This is done
790   // intentionally to avoid a situation whereby the signal might have dangling
791   // pointers to objects that have been deleted by the time the async task
792   // that deletes the connection object runs.
793   auto destroyed_signals = SignalDestroyed;
794   SignalDestroyed.disconnect_all();
795   destroyed_signals(this);
796 
797   LogCandidatePairConfig(webrtc::IceCandidatePairConfigType::kDestroyed);
798 
799   // Reset the `port_` after logging and firing the destroyed signal since
800   // information required for logging needs access to `port_`.
801   port_.reset();
802 
803   return true;
804 }
805 
FailAndPrune()806 void Connection::FailAndPrune() {
807   RTC_DCHECK_RUN_ON(network_thread_);
808 
809   // TODO(bugs.webrtc.org/13865): There's a circular dependency between Port
810   // and Connection. In some cases (Port dtor), a Connection object is deleted
811   // without using the `Destroy` method (port_ won't be nulled and some
812   // functionality won't run as expected), while in other cases
813   // the Connection object is deleted asynchronously and in that case `port_`
814   // will be nulled.
815   // In such a case, there's a chance that the Port object gets
816   // deleted before the Connection object ends up being deleted.
817   if (!port_)
818     return;
819 
820   set_state(IceCandidatePairState::FAILED);
821   Prune();
822 }
823 
PrintPingsSinceLastResponse(std::string * s,size_t max)824 void Connection::PrintPingsSinceLastResponse(std::string* s, size_t max) {
825   RTC_DCHECK_RUN_ON(network_thread_);
826   rtc::StringBuilder oss;
827   if (pings_since_last_response_.size() > max) {
828     for (size_t i = 0; i < max; i++) {
829       const SentPing& ping = pings_since_last_response_[i];
830       oss << rtc::hex_encode(ping.id) << " ";
831     }
832     oss << "... " << (pings_since_last_response_.size() - max) << " more";
833   } else {
834     for (const SentPing& ping : pings_since_last_response_) {
835       oss << rtc::hex_encode(ping.id) << " ";
836     }
837   }
838   *s = oss.str();
839 }
840 
selected() const841 bool Connection::selected() const {
842   RTC_DCHECK_RUN_ON(network_thread_);
843   return selected_;
844 }
845 
set_selected(bool selected)846 void Connection::set_selected(bool selected) {
847   RTC_DCHECK_RUN_ON(network_thread_);
848   selected_ = selected;
849 }
850 
UpdateState(int64_t now)851 void Connection::UpdateState(int64_t now) {
852   RTC_DCHECK_RUN_ON(network_thread_);
853   if (!port_)
854     return;
855 
856   int rtt = ConservativeRTTEstimate(rtt_);
857 
858   if (RTC_LOG_CHECK_LEVEL(LS_VERBOSE)) {
859     std::string pings;
860     PrintPingsSinceLastResponse(&pings, 5);
861     RTC_LOG(LS_VERBOSE) << ToString()
862                         << ": UpdateState()"
863                            ", ms since last received response="
864                         << now - last_ping_response_received_
865                         << ", ms since last received data="
866                         << now - last_data_received_ << ", rtt=" << rtt
867                         << ", pings_since_last_response=" << pings;
868   }
869 
870   // Check the writable state.  (The order of these checks is important.)
871   //
872   // Before becoming unwritable, we allow for a fixed number of pings to fail
873   // (i.e., receive no response).  We also have to give the response time to
874   // get back, so we include a conservative estimate of this.
875   //
876   // Before timing out writability, we give a fixed amount of time.  This is to
877   // allow for changes in network conditions.
878 
879   if ((write_state_ == STATE_WRITABLE) &&
880       TooManyFailures(pings_since_last_response_, unwritable_min_checks(), rtt,
881                       now) &&
882       TooLongWithoutResponse(pings_since_last_response_, unwritable_timeout(),
883                              now)) {
884     uint32_t max_pings = unwritable_min_checks();
885     RTC_LOG(LS_INFO) << ToString() << ": Unwritable after " << max_pings
886                      << " ping failures and "
887                      << now - pings_since_last_response_[0].sent_time
888                      << " ms without a response,"
889                         " ms since last received ping="
890                      << now - last_ping_received_
891                      << " ms since last received data="
892                      << now - last_data_received_ << " rtt=" << rtt;
893     set_write_state(STATE_WRITE_UNRELIABLE);
894   }
895   if ((write_state_ == STATE_WRITE_UNRELIABLE ||
896        write_state_ == STATE_WRITE_INIT) &&
897       TooLongWithoutResponse(pings_since_last_response_, inactive_timeout(),
898                              now)) {
899     RTC_LOG(LS_INFO) << ToString() << ": Timed out after "
900                      << now - pings_since_last_response_[0].sent_time
901                      << " ms without a response, rtt=" << rtt;
902     set_write_state(STATE_WRITE_TIMEOUT);
903   }
904 
905   // Update the receiving state.
906   UpdateReceiving(now);
907   if (dead(now)) {
908     port_->DestroyConnectionAsync(this);
909   }
910 }
911 
UpdateLocalIceParameters(int component,absl::string_view username_fragment,absl::string_view password)912 void Connection::UpdateLocalIceParameters(int component,
913                                           absl::string_view username_fragment,
914                                           absl::string_view password) {
915   RTC_DCHECK_RUN_ON(network_thread_);
916   local_candidate_.set_component(component);
917   local_candidate_.set_username(username_fragment);
918   local_candidate_.set_password(password);
919 }
920 
last_ping_sent() const921 int64_t Connection::last_ping_sent() const {
922   RTC_DCHECK_RUN_ON(network_thread_);
923   return last_ping_sent_;
924 }
925 
Ping(int64_t now)926 void Connection::Ping(int64_t now) {
927   RTC_DCHECK_RUN_ON(network_thread_);
928   if (!port_)
929     return;
930 
931   last_ping_sent_ = now;
932 
933   // If not using renomination, we use "1" to mean "nominated" and "0" to mean
934   // "not nominated". If using renomination, values greater than 1 are used for
935   // re-nominated pairs.
936   int nomination = use_candidate_attr_ ? 1 : 0;
937   if (nomination_ > 0) {
938     nomination = nomination_;
939   }
940 
941   auto req =
942       std::make_unique<ConnectionRequest>(requests_, this, BuildPingRequest());
943 
944   if (ShouldSendGoogPing(req->msg())) {
945     auto message = std::make_unique<IceMessage>(GOOG_PING_REQUEST, req->id());
946     message->AddMessageIntegrity32(remote_candidate_.password());
947     req.reset(new ConnectionRequest(requests_, this, std::move(message)));
948   }
949 
950   pings_since_last_response_.push_back(SentPing(req->id(), now, nomination));
951   RTC_LOG(LS_VERBOSE) << ToString() << ": Sending STUN ping, id="
952                       << rtc::hex_encode(req->id())
953                       << ", nomination=" << nomination_;
954   requests_.Send(req.release());
955   state_ = IceCandidatePairState::IN_PROGRESS;
956   num_pings_sent_++;
957 }
958 
BuildPingRequest()959 std::unique_ptr<IceMessage> Connection::BuildPingRequest() {
960   auto message = std::make_unique<IceMessage>(STUN_BINDING_REQUEST);
961   // Note that the order of attributes does not impact the parsing on the
962   // receiver side. The attribute is retrieved then by iterating and matching
963   // over all parsed attributes. See StunMessage::GetAttribute.
964   message->AddAttribute(std::make_unique<StunByteStringAttribute>(
965       STUN_ATTR_USERNAME,
966       port()->CreateStunUsername(remote_candidate_.username())));
967   message->AddAttribute(std::make_unique<StunUInt32Attribute>(
968       STUN_ATTR_GOOG_NETWORK_INFO,
969       (port_->Network()->id() << 16) | port_->network_cost()));
970 
971   if (field_trials_->piggyback_ice_check_acknowledgement &&
972       last_ping_id_received_) {
973     message->AddAttribute(std::make_unique<StunByteStringAttribute>(
974         STUN_ATTR_GOOG_LAST_ICE_CHECK_RECEIVED, *last_ping_id_received_));
975   }
976 
977   // Adding ICE_CONTROLLED or ICE_CONTROLLING attribute based on the role.
978   IceRole ice_role = port_->GetIceRole();
979   RTC_DCHECK(ice_role == ICEROLE_CONTROLLING || ice_role == ICEROLE_CONTROLLED);
980   message->AddAttribute(std::make_unique<StunUInt64Attribute>(
981       ice_role == ICEROLE_CONTROLLING ? STUN_ATTR_ICE_CONTROLLING
982                                       : STUN_ATTR_ICE_CONTROLLED,
983       port_->IceTiebreaker()));
984 
985   if (ice_role == ICEROLE_CONTROLLING) {
986     // We should have either USE_CANDIDATE attribute or ICE_NOMINATION
987     // attribute but not both. That was enforced in p2ptransportchannel.
988     if (use_candidate_attr()) {
989       message->AddAttribute(
990           std::make_unique<StunByteStringAttribute>(STUN_ATTR_USE_CANDIDATE));
991     }
992     if (nomination_ && nomination_ != acked_nomination()) {
993       message->AddAttribute(std::make_unique<StunUInt32Attribute>(
994           STUN_ATTR_NOMINATION, nomination_));
995     }
996   }
997 
998   message->AddAttribute(std::make_unique<StunUInt32Attribute>(
999       STUN_ATTR_PRIORITY, prflx_priority()));
1000 
1001   if (port()->send_retransmit_count_attribute()) {
1002     message->AddAttribute(std::make_unique<StunUInt32Attribute>(
1003         STUN_ATTR_RETRANSMIT_COUNT, pings_since_last_response_.size()));
1004   }
1005   if (field_trials_->enable_goog_ping &&
1006       !remote_support_goog_ping_.has_value()) {
1007     // Check if remote supports GOOG PING by announcing which version we
1008     // support. This is sent on all STUN_BINDING_REQUEST until we get a
1009     // STUN_BINDING_RESPONSE.
1010     auto list =
1011         StunAttribute::CreateUInt16ListAttribute(STUN_ATTR_GOOG_MISC_INFO);
1012     list->AddTypeAtIndex(kSupportGoogPingVersionRequestIndex, kGoogPingVersion);
1013     message->AddAttribute(std::move(list));
1014   }
1015   message->AddMessageIntegrity(remote_candidate_.password());
1016   message->AddFingerprint();
1017 
1018   return message;
1019 }
1020 
last_ping_response_received() const1021 int64_t Connection::last_ping_response_received() const {
1022   RTC_DCHECK_RUN_ON(network_thread_);
1023   return last_ping_response_received_;
1024 }
1025 
last_ping_id_received() const1026 const absl::optional<std::string>& Connection::last_ping_id_received() const {
1027   RTC_DCHECK_RUN_ON(network_thread_);
1028   return last_ping_id_received_;
1029 }
1030 
1031 // Used to check if any STUN ping response has been received.
rtt_samples() const1032 int Connection::rtt_samples() const {
1033   RTC_DCHECK_RUN_ON(network_thread_);
1034   return rtt_samples_;
1035 }
1036 
1037 // Called whenever a valid ping is received on this connection.  This is
1038 // public because the connection intercepts the first ping for us.
last_ping_received() const1039 int64_t Connection::last_ping_received() const {
1040   RTC_DCHECK_RUN_ON(network_thread_);
1041   return last_ping_received_;
1042 }
1043 
ReceivedPing(const absl::optional<std::string> & request_id)1044 void Connection::ReceivedPing(const absl::optional<std::string>& request_id) {
1045   RTC_DCHECK_RUN_ON(network_thread_);
1046   last_ping_received_ = rtc::TimeMillis();
1047   last_ping_id_received_ = request_id;
1048   UpdateReceiving(last_ping_received_);
1049 }
1050 
HandlePiggybackCheckAcknowledgementIfAny(StunMessage * msg)1051 void Connection::HandlePiggybackCheckAcknowledgementIfAny(StunMessage* msg) {
1052   RTC_DCHECK_RUN_ON(network_thread_);
1053   RTC_DCHECK(msg->type() == STUN_BINDING_REQUEST ||
1054              msg->type() == GOOG_PING_REQUEST);
1055   const StunByteStringAttribute* last_ice_check_received_attr =
1056       msg->GetByteString(STUN_ATTR_GOOG_LAST_ICE_CHECK_RECEIVED);
1057   if (last_ice_check_received_attr) {
1058     const absl::string_view request_id =
1059         last_ice_check_received_attr->string_view();
1060     auto iter = absl::c_find_if(
1061         pings_since_last_response_,
1062         [&request_id](const SentPing& ping) { return ping.id == request_id; });
1063     if (iter != pings_since_last_response_.end()) {
1064       rtc::LoggingSeverity sev = !writable() ? rtc::LS_INFO : rtc::LS_VERBOSE;
1065       RTC_LOG_V(sev) << ToString()
1066                      << ": Received piggyback STUN ping response, id="
1067                      << rtc::hex_encode(request_id);
1068       const int64_t rtt = rtc::TimeMillis() - iter->sent_time;
1069       ReceivedPingResponse(rtt, request_id, iter->nomination);
1070     }
1071   }
1072 }
1073 
last_send_data() const1074 int64_t Connection::last_send_data() const {
1075   RTC_DCHECK_RUN_ON(network_thread_);
1076   return last_send_data_;
1077 }
1078 
last_data_received() const1079 int64_t Connection::last_data_received() const {
1080   RTC_DCHECK_RUN_ON(network_thread_);
1081   return last_data_received_;
1082 }
1083 
ReceivedPingResponse(int rtt,absl::string_view request_id,const absl::optional<uint32_t> & nomination)1084 void Connection::ReceivedPingResponse(
1085     int rtt,
1086     absl::string_view request_id,
1087     const absl::optional<uint32_t>& nomination) {
1088   RTC_DCHECK_RUN_ON(network_thread_);
1089   RTC_DCHECK_GE(rtt, 0);
1090   // We've already validated that this is a STUN binding response with
1091   // the correct local and remote username for this connection.
1092   // So if we're not already, become writable. We may be bringing a pruned
1093   // connection back to life, but if we don't really want it, we can always
1094   // prune it again.
1095   if (nomination && nomination.value() > acked_nomination_) {
1096     acked_nomination_ = nomination.value();
1097   }
1098 
1099   int64_t now = rtc::TimeMillis();
1100   total_round_trip_time_ms_ += rtt;
1101   current_round_trip_time_ms_ = static_cast<uint32_t>(rtt);
1102   rtt_estimate_.AddSample(now, rtt);
1103 
1104   pings_since_last_response_.clear();
1105   last_ping_response_received_ = now;
1106   UpdateReceiving(last_ping_response_received_);
1107   set_write_state(STATE_WRITABLE);
1108   set_state(IceCandidatePairState::SUCCEEDED);
1109   if (rtt_samples_ > 0) {
1110     rtt_ = rtc::GetNextMovingAverage(rtt_, rtt, RTT_RATIO);
1111   } else {
1112     rtt_ = rtt;
1113   }
1114   rtt_samples_++;
1115 }
1116 
write_state() const1117 Connection::WriteState Connection::write_state() const {
1118   RTC_DCHECK_RUN_ON(network_thread_);
1119   return write_state_;
1120 }
1121 
writable() const1122 bool Connection::writable() const {
1123   RTC_DCHECK_RUN_ON(network_thread_);
1124   return write_state_ == STATE_WRITABLE;
1125 }
1126 
receiving() const1127 bool Connection::receiving() const {
1128   RTC_DCHECK_RUN_ON(network_thread_);
1129   return receiving_;
1130 }
1131 
1132 // Determines whether the connection has finished connecting.  This can only
1133 // be false for TCP connections.
connected() const1134 bool Connection::connected() const {
1135   RTC_DCHECK_RUN_ON(network_thread_);
1136   return connected_;
1137 }
1138 
weak() const1139 bool Connection::weak() const {
1140   return !(writable() && receiving() && connected());
1141 }
1142 
active() const1143 bool Connection::active() const {
1144   RTC_DCHECK_RUN_ON(network_thread_);
1145   return write_state_ != STATE_WRITE_TIMEOUT;
1146 }
1147 
dead(int64_t now) const1148 bool Connection::dead(int64_t now) const {
1149   RTC_DCHECK_RUN_ON(network_thread_);
1150   if (last_received() > 0) {
1151     // If it has ever received anything, we keep it alive
1152     // - if it has recevied last DEAD_CONNECTION_RECEIVE_TIMEOUT (30s)
1153     // - if it has a ping outstanding shorter than
1154     // DEAD_CONNECTION_RECEIVE_TIMEOUT (30s)
1155     // - else if IDLE let it live field_trials_->dead_connection_timeout_ms
1156     //
1157     // This covers the normal case of a successfully used connection that stops
1158     // working. This also allows a remote peer to continue pinging over a
1159     // locally inactive (pruned) connection. This also allows the local agent to
1160     // ping with longer interval than 30s as long as it shorter than
1161     // `dead_connection_timeout_ms`.
1162     if (now <= (last_received() + DEAD_CONNECTION_RECEIVE_TIMEOUT)) {
1163       // Not dead since we have received the last 30s.
1164       return false;
1165     }
1166     if (!pings_since_last_response_.empty()) {
1167       // Outstanding pings: let it live until the ping is unreplied for
1168       // DEAD_CONNECTION_RECEIVE_TIMEOUT.
1169       return now > (pings_since_last_response_[0].sent_time +
1170                     DEAD_CONNECTION_RECEIVE_TIMEOUT);
1171     }
1172 
1173     // No outstanding pings: let it live until
1174     // field_trials_->dead_connection_timeout_ms has passed.
1175     return now > (last_received() + field_trials_->dead_connection_timeout_ms);
1176   }
1177 
1178   if (active()) {
1179     // If it has never received anything, keep it alive as long as it is
1180     // actively pinging and not pruned. Otherwise, the connection might be
1181     // deleted before it has a chance to ping. This is the normal case for a
1182     // new connection that is pinging but hasn't received anything yet.
1183     return false;
1184   }
1185 
1186   // If it has never received anything and is not actively pinging (pruned), we
1187   // keep it around for at least MIN_CONNECTION_LIFETIME to prevent connections
1188   // from being pruned too quickly during a network change event when two
1189   // networks would be up simultaneously but only for a brief period.
1190   return now > (time_created_ms_ + MIN_CONNECTION_LIFETIME);
1191 }
1192 
rtt() const1193 int Connection::rtt() const {
1194   RTC_DCHECK_RUN_ON(network_thread_);
1195   return rtt_;
1196 }
1197 
stable(int64_t now) const1198 bool Connection::stable(int64_t now) const {
1199   // A connection is stable if it's RTT has converged and it isn't missing any
1200   // responses.  We should send pings at a higher rate until the RTT converges
1201   // and whenever a ping response is missing (so that we can detect
1202   // unwritability faster)
1203   return rtt_converged() && !missing_responses(now);
1204 }
1205 
ToDebugId() const1206 std::string Connection::ToDebugId() const {
1207   return rtc::ToHex(reinterpret_cast<uintptr_t>(this));
1208 }
1209 
ComputeNetworkCost() const1210 uint32_t Connection::ComputeNetworkCost() const {
1211   // TODO(honghaiz): Will add rtt as part of the network cost.
1212   return port()->network_cost() + remote_candidate_.network_cost();
1213 }
1214 
ToString() const1215 std::string Connection::ToString() const {
1216   RTC_DCHECK_RUN_ON(network_thread_);
1217   constexpr absl::string_view CONNECT_STATE_ABBREV[2] = {
1218       "-",  // not connected (false)
1219       "C",  // connected (true)
1220   };
1221   constexpr absl::string_view RECEIVE_STATE_ABBREV[2] = {
1222       "-",  // not receiving (false)
1223       "R",  // receiving (true)
1224   };
1225   constexpr absl::string_view WRITE_STATE_ABBREV[4] = {
1226       "W",  // STATE_WRITABLE
1227       "w",  // STATE_WRITE_UNRELIABLE
1228       "-",  // STATE_WRITE_INIT
1229       "x",  // STATE_WRITE_TIMEOUT
1230   };
1231   constexpr absl::string_view ICESTATE[4] = {
1232       "W",  // STATE_WAITING
1233       "I",  // STATE_INPROGRESS
1234       "S",  // STATE_SUCCEEDED
1235       "F"   // STATE_FAILED
1236   };
1237   constexpr absl::string_view SELECTED_STATE_ABBREV[2] = {
1238       "-",  // candidate pair not selected (false)
1239       "S",  // selected (true)
1240   };
1241   rtc::StringBuilder ss;
1242   ss << "Conn[" << ToDebugId();
1243 
1244   if (!port_) {
1245     // No content or network names for pending delete. Temporarily substitute
1246     // the names with a hash (rhyming with trash).
1247     ss << ":#:#:";
1248   } else {
1249     ss << ":" << port_->content_name() << ":" << port_->Network()->ToString()
1250        << ":";
1251   }
1252 
1253   const Candidate& local = local_candidate();
1254   const Candidate& remote = remote_candidate();
1255   ss << local.id() << ":" << local.component() << ":" << local.generation()
1256      << ":" << local.type() << ":" << local.protocol() << ":"
1257      << local.address().ToSensitiveString() << "->" << remote.id() << ":"
1258      << remote.component() << ":" << remote.priority() << ":" << remote.type()
1259      << ":" << remote.protocol() << ":" << remote.address().ToSensitiveString()
1260      << "|";
1261 
1262   ss << CONNECT_STATE_ABBREV[connected_] << RECEIVE_STATE_ABBREV[receiving_]
1263      << WRITE_STATE_ABBREV[write_state_] << ICESTATE[static_cast<int>(state_)]
1264      << "|" << SELECTED_STATE_ABBREV[selected_] << "|" << remote_nomination_
1265      << "|" << nomination_ << "|";
1266 
1267   if (port_)
1268     ss << priority() << "|";
1269 
1270   if (rtt_ < DEFAULT_RTT) {
1271     ss << rtt_ << "]";
1272   } else {
1273     ss << "-]";
1274   }
1275 
1276   return ss.Release();
1277 }
1278 
ToSensitiveString() const1279 std::string Connection::ToSensitiveString() const {
1280   return ToString();
1281 }
1282 
ToLogDescription()1283 const webrtc::IceCandidatePairDescription& Connection::ToLogDescription() {
1284   RTC_DCHECK_RUN_ON(network_thread_);
1285   if (log_description_.has_value()) {
1286     return log_description_.value();
1287   }
1288   const Candidate& local = local_candidate();
1289   const Candidate& remote = remote_candidate();
1290   const rtc::Network* network = port()->Network();
1291   log_description_ = webrtc::IceCandidatePairDescription();
1292   log_description_->local_candidate_type =
1293       GetCandidateTypeByString(local.type());
1294   log_description_->local_relay_protocol =
1295       GetProtocolByString(local.relay_protocol());
1296   log_description_->local_network_type = ConvertNetworkType(network->type());
1297   log_description_->local_address_family =
1298       GetAddressFamilyByInt(local.address().family());
1299   log_description_->remote_candidate_type =
1300       GetCandidateTypeByString(remote.type());
1301   log_description_->remote_address_family =
1302       GetAddressFamilyByInt(remote.address().family());
1303   log_description_->candidate_pair_protocol =
1304       GetProtocolByString(local.protocol());
1305   return log_description_.value();
1306 }
1307 
set_ice_event_log(webrtc::IceEventLog * ice_event_log)1308 void Connection::set_ice_event_log(webrtc::IceEventLog* ice_event_log) {
1309   RTC_DCHECK_RUN_ON(network_thread_);
1310   ice_event_log_ = ice_event_log;
1311 }
1312 
LogCandidatePairConfig(webrtc::IceCandidatePairConfigType type)1313 void Connection::LogCandidatePairConfig(
1314     webrtc::IceCandidatePairConfigType type) {
1315   RTC_DCHECK_RUN_ON(network_thread_);
1316   if (ice_event_log_ == nullptr) {
1317     return;
1318   }
1319   ice_event_log_->LogCandidatePairConfig(type, id(), ToLogDescription());
1320 }
1321 
LogCandidatePairEvent(webrtc::IceCandidatePairEventType type,uint32_t transaction_id)1322 void Connection::LogCandidatePairEvent(webrtc::IceCandidatePairEventType type,
1323                                        uint32_t transaction_id) {
1324   RTC_DCHECK_RUN_ON(network_thread_);
1325   if (ice_event_log_ == nullptr) {
1326     return;
1327   }
1328   ice_event_log_->LogCandidatePairEvent(type, id(), transaction_id);
1329 }
1330 
OnConnectionRequestResponse(StunRequest * request,StunMessage * response)1331 void Connection::OnConnectionRequestResponse(StunRequest* request,
1332                                              StunMessage* response) {
1333   RTC_DCHECK_RUN_ON(network_thread_);
1334   // Log at LS_INFO if we receive a ping response on an unwritable
1335   // connection.
1336   rtc::LoggingSeverity sev = !writable() ? rtc::LS_INFO : rtc::LS_VERBOSE;
1337 
1338   int rtt = request->Elapsed();
1339 
1340   if (RTC_LOG_CHECK_LEVEL_V(sev)) {
1341     std::string pings;
1342     PrintPingsSinceLastResponse(&pings, 5);
1343     RTC_LOG_V(sev) << ToString() << ": Received "
1344                    << StunMethodToString(response->type())
1345                    << ", id=" << rtc::hex_encode(request->id())
1346                    << ", code=0"  // Makes logging easier to parse.
1347                       ", rtt="
1348                    << rtt << ", pings_since_last_response=" << pings;
1349   }
1350   absl::optional<uint32_t> nomination;
1351   const std::string request_id = request->id();
1352   auto iter = absl::c_find_if(
1353       pings_since_last_response_,
1354       [&request_id](const SentPing& ping) { return ping.id == request_id; });
1355   if (iter != pings_since_last_response_.end()) {
1356     nomination.emplace(iter->nomination);
1357   }
1358   ReceivedPingResponse(rtt, request_id, nomination);
1359 
1360   stats_.recv_ping_responses++;
1361   LogCandidatePairEvent(
1362       webrtc::IceCandidatePairEventType::kCheckResponseReceived,
1363       response->reduced_transaction_id());
1364 
1365   if (request->msg()->type() == STUN_BINDING_REQUEST) {
1366     if (!remote_support_goog_ping_.has_value()) {
1367       auto goog_misc = response->GetUInt16List(STUN_ATTR_GOOG_MISC_INFO);
1368       if (goog_misc != nullptr &&
1369           goog_misc->Size() >= kSupportGoogPingVersionResponseIndex) {
1370         // The remote peer has indicated that it {does/does not} supports
1371         // GOOG_PING.
1372         remote_support_goog_ping_ =
1373             goog_misc->GetType(kSupportGoogPingVersionResponseIndex) >=
1374             kGoogPingVersion;
1375       } else {
1376         remote_support_goog_ping_ = false;
1377       }
1378     }
1379 
1380     MaybeUpdateLocalCandidate(request, response);
1381 
1382     if (field_trials_->enable_goog_ping && remote_support_goog_ping_) {
1383       cached_stun_binding_ = request->msg()->Clone();
1384     }
1385   }
1386 }
1387 
OnConnectionRequestErrorResponse(ConnectionRequest * request,StunMessage * response)1388 void Connection::OnConnectionRequestErrorResponse(ConnectionRequest* request,
1389                                                   StunMessage* response) {
1390   if (!port_)
1391     return;
1392 
1393   int error_code = response->GetErrorCodeValue();
1394   RTC_LOG(LS_WARNING) << ToString() << ": Received "
1395                       << StunMethodToString(response->type())
1396                       << " id=" << rtc::hex_encode(request->id())
1397                       << " code=" << error_code
1398                       << " rtt=" << request->Elapsed();
1399 
1400   cached_stun_binding_.reset();
1401   if (error_code == STUN_ERROR_UNKNOWN_ATTRIBUTE ||
1402       error_code == STUN_ERROR_SERVER_ERROR ||
1403       error_code == STUN_ERROR_UNAUTHORIZED) {
1404     // Recoverable error, retry
1405   } else if (error_code == STUN_ERROR_ROLE_CONFLICT) {
1406     port_->SignalRoleConflict(port_.get());
1407   } else if (request->msg()->type() == GOOG_PING_REQUEST) {
1408     // Race, retry.
1409   } else {
1410     // This is not a valid connection.
1411     RTC_LOG(LS_ERROR) << ToString()
1412                       << ": Received STUN error response, code=" << error_code
1413                       << "; killing connection";
1414     set_state(IceCandidatePairState::FAILED);
1415     port_->DestroyConnectionAsync(this);
1416   }
1417 }
1418 
OnConnectionRequestTimeout(ConnectionRequest * request)1419 void Connection::OnConnectionRequestTimeout(ConnectionRequest* request) {
1420   // Log at LS_INFO if we miss a ping on a writable connection.
1421   rtc::LoggingSeverity sev = writable() ? rtc::LS_INFO : rtc::LS_VERBOSE;
1422   RTC_LOG_V(sev) << ToString() << ": Timing-out STUN ping "
1423                  << rtc::hex_encode(request->id()) << " after "
1424                  << request->Elapsed() << " ms";
1425 }
1426 
OnConnectionRequestSent(ConnectionRequest * request)1427 void Connection::OnConnectionRequestSent(ConnectionRequest* request) {
1428   RTC_DCHECK_RUN_ON(network_thread_);
1429   // Log at LS_INFO if we send a ping on an unwritable connection.
1430   rtc::LoggingSeverity sev = !writable() ? rtc::LS_INFO : rtc::LS_VERBOSE;
1431   RTC_LOG_V(sev) << ToString() << ": Sent "
1432                  << StunMethodToString(request->msg()->type())
1433                  << ", id=" << rtc::hex_encode(request->id())
1434                  << ", use_candidate=" << use_candidate_attr()
1435                  << ", nomination=" << nomination_;
1436   stats_.sent_ping_requests_total++;
1437   LogCandidatePairEvent(webrtc::IceCandidatePairEventType::kCheckSent,
1438                         request->reduced_transaction_id());
1439   if (stats_.recv_ping_responses == 0) {
1440     stats_.sent_ping_requests_before_first_response++;
1441   }
1442 }
1443 
state() const1444 IceCandidatePairState Connection::state() const {
1445   RTC_DCHECK_RUN_ON(network_thread_);
1446   return state_;
1447 }
1448 
num_pings_sent() const1449 int Connection::num_pings_sent() const {
1450   RTC_DCHECK_RUN_ON(network_thread_);
1451   return num_pings_sent_;
1452 }
1453 
MaybeSetRemoteIceParametersAndGeneration(const IceParameters & ice_params,int generation)1454 void Connection::MaybeSetRemoteIceParametersAndGeneration(
1455     const IceParameters& ice_params,
1456     int generation) {
1457   if (remote_candidate_.username() == ice_params.ufrag &&
1458       remote_candidate_.password().empty()) {
1459     remote_candidate_.set_password(ice_params.pwd);
1460   }
1461   // TODO(deadbeef): A value of '0' for the generation is used for both
1462   // generation 0 and "generation unknown". It should be changed to an
1463   // absl::optional to fix this.
1464   if (remote_candidate_.username() == ice_params.ufrag &&
1465       remote_candidate_.password() == ice_params.pwd &&
1466       remote_candidate_.generation() == 0) {
1467     remote_candidate_.set_generation(generation);
1468   }
1469 }
1470 
MaybeUpdatePeerReflexiveCandidate(const Candidate & new_candidate)1471 void Connection::MaybeUpdatePeerReflexiveCandidate(
1472     const Candidate& new_candidate) {
1473   if (remote_candidate_.type() == PRFLX_PORT_TYPE &&
1474       new_candidate.type() != PRFLX_PORT_TYPE &&
1475       remote_candidate_.protocol() == new_candidate.protocol() &&
1476       remote_candidate_.address() == new_candidate.address() &&
1477       remote_candidate_.username() == new_candidate.username() &&
1478       remote_candidate_.password() == new_candidate.password() &&
1479       remote_candidate_.generation() == new_candidate.generation()) {
1480     remote_candidate_ = new_candidate;
1481   }
1482 }
1483 
last_received() const1484 int64_t Connection::last_received() const {
1485   RTC_DCHECK_RUN_ON(network_thread_);
1486   return std::max(last_data_received_,
1487                   std::max(last_ping_received_, last_ping_response_received_));
1488 }
1489 
receiving_unchanged_since() const1490 int64_t Connection::receiving_unchanged_since() const {
1491   RTC_DCHECK_RUN_ON(network_thread_);
1492   return receiving_unchanged_since_;
1493 }
1494 
prflx_priority() const1495 uint32_t Connection::prflx_priority() const {
1496   RTC_DCHECK_RUN_ON(network_thread_);
1497   // PRIORITY Attribute.
1498   // Changing the type preference to Peer Reflexive and local preference
1499   // and component id information is unchanged from the original priority.
1500   // priority = (2^24)*(type preference) +
1501   //           (2^8)*(local preference) +
1502   //           (2^0)*(256 - component ID)
1503   IcePriorityValue type_preference =
1504       (local_candidate_.protocol() == TCP_PROTOCOL_NAME)
1505           ? ICE_TYPE_PREFERENCE_PRFLX_TCP
1506           : ICE_TYPE_PREFERENCE_PRFLX;
1507   return type_preference << 24 | (local_candidate_.priority() & 0x00FFFFFF);
1508 }
1509 
stats()1510 ConnectionInfo Connection::stats() {
1511   RTC_DCHECK_RUN_ON(network_thread_);
1512   stats_.recv_bytes_second = round(recv_rate_tracker_.ComputeRate());
1513   stats_.recv_total_bytes = recv_rate_tracker_.TotalSampleCount();
1514   stats_.sent_bytes_second = round(send_rate_tracker_.ComputeRate());
1515   stats_.sent_total_bytes = send_rate_tracker_.TotalSampleCount();
1516   stats_.receiving = receiving_;
1517   stats_.writable = write_state_ == STATE_WRITABLE;
1518   stats_.timeout = write_state_ == STATE_WRITE_TIMEOUT;
1519   stats_.rtt = rtt_;
1520   stats_.key = this;
1521   stats_.state = state_;
1522   if (port_) {
1523     stats_.priority = priority();
1524     stats_.local_candidate = local_candidate();
1525   }
1526   stats_.nominated = nominated();
1527   stats_.total_round_trip_time_ms = total_round_trip_time_ms_;
1528   stats_.current_round_trip_time_ms = current_round_trip_time_ms_;
1529   stats_.remote_candidate = remote_candidate();
1530   if (last_data_received_ > 0) {
1531     stats_.last_data_received = webrtc::Timestamp::Millis(
1532         last_data_received_ + delta_internal_unix_epoch_ms_);
1533   }
1534   if (last_send_data_ > 0) {
1535     stats_.last_data_sent = webrtc::Timestamp::Millis(
1536         last_send_data_ + delta_internal_unix_epoch_ms_);
1537   }
1538   return stats_;
1539 }
1540 
MaybeUpdateLocalCandidate(StunRequest * request,StunMessage * response)1541 void Connection::MaybeUpdateLocalCandidate(StunRequest* request,
1542                                            StunMessage* response) {
1543   if (!port_)
1544     return;
1545 
1546   // RFC 5245
1547   // The agent checks the mapped address from the STUN response.  If the
1548   // transport address does not match any of the local candidates that the
1549   // agent knows about, the mapped address represents a new candidate -- a
1550   // peer reflexive candidate.
1551   const StunAddressAttribute* addr =
1552       response->GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
1553   if (!addr) {
1554     RTC_LOG(LS_WARNING)
1555         << "Connection::OnConnectionRequestResponse - "
1556            "No MAPPED-ADDRESS or XOR-MAPPED-ADDRESS found in the "
1557            "stun response message";
1558     return;
1559   }
1560 
1561   for (const Candidate& candidate : port_->Candidates()) {
1562     if (candidate.address() == addr->GetAddress()) {
1563       if (local_candidate_ != candidate) {
1564         RTC_LOG(LS_INFO) << ToString()
1565                          << ": Updating local candidate type to srflx.";
1566         local_candidate_ = candidate;
1567         // SignalStateChange to force a re-sort in P2PTransportChannel as this
1568         // Connection's local candidate has changed.
1569         SignalStateChange(this);
1570       }
1571       return;
1572     }
1573   }
1574 
1575   // RFC 5245
1576   // Its priority is set equal to the value of the PRIORITY attribute
1577   // in the Binding request.
1578   const StunUInt32Attribute* priority_attr =
1579       request->msg()->GetUInt32(STUN_ATTR_PRIORITY);
1580   if (!priority_attr) {
1581     RTC_LOG(LS_WARNING) << "Connection::OnConnectionRequestResponse - "
1582                            "No STUN_ATTR_PRIORITY found in the "
1583                            "stun response message";
1584     return;
1585   }
1586   const uint32_t priority = priority_attr->value();
1587   std::string id = rtc::CreateRandomString(8);
1588 
1589   // Create a peer-reflexive candidate based on the local candidate.
1590   local_candidate_.set_id(id);
1591   local_candidate_.set_type(PRFLX_PORT_TYPE);
1592   // Set the related address and foundation attributes before changing the
1593   // address.
1594   local_candidate_.set_related_address(local_candidate_.address());
1595   local_candidate_.set_foundation(port()->ComputeFoundation(
1596       PRFLX_PORT_TYPE, local_candidate_.protocol(),
1597       local_candidate_.relay_protocol(), local_candidate_.address()));
1598   local_candidate_.set_priority(priority);
1599   local_candidate_.set_address(addr->GetAddress());
1600 
1601   // Change the local candidate of this Connection to the new prflx candidate.
1602   RTC_LOG(LS_INFO) << ToString() << ": Updating local candidate type to prflx.";
1603   port_->AddPrflxCandidate(local_candidate_);
1604 
1605   // SignalStateChange to force a re-sort in P2PTransportChannel as this
1606   // Connection's local candidate has changed.
1607   SignalStateChange(this);
1608 }
1609 
rtt_converged() const1610 bool Connection::rtt_converged() const {
1611   RTC_DCHECK_RUN_ON(network_thread_);
1612   return rtt_samples_ > (RTT_RATIO + 1);
1613 }
1614 
missing_responses(int64_t now) const1615 bool Connection::missing_responses(int64_t now) const {
1616   RTC_DCHECK_RUN_ON(network_thread_);
1617   if (pings_since_last_response_.empty()) {
1618     return false;
1619   }
1620 
1621   int64_t waiting = now - pings_since_last_response_[0].sent_time;
1622   return waiting > 2 * rtt();
1623 }
1624 
TooManyOutstandingPings(const absl::optional<int> & max_outstanding_pings) const1625 bool Connection::TooManyOutstandingPings(
1626     const absl::optional<int>& max_outstanding_pings) const {
1627   RTC_DCHECK_RUN_ON(network_thread_);
1628   if (!max_outstanding_pings.has_value()) {
1629     return false;
1630   }
1631   if (static_cast<int>(pings_since_last_response_.size()) <
1632       *max_outstanding_pings) {
1633     return false;
1634   }
1635   return true;
1636 }
1637 
SetLocalCandidateNetworkCost(uint16_t cost)1638 void Connection::SetLocalCandidateNetworkCost(uint16_t cost) {
1639   RTC_DCHECK_RUN_ON(network_thread_);
1640 
1641   if (cost == local_candidate_.network_cost())
1642     return;
1643 
1644   local_candidate_.set_network_cost(cost);
1645 
1646   // Network cost change will affect the connection selection criteria.
1647   // Signal the connection state change to force a re-sort in
1648   // P2PTransportChannel.
1649   SignalStateChange(this);
1650 }
1651 
ShouldSendGoogPing(const StunMessage * message)1652 bool Connection::ShouldSendGoogPing(const StunMessage* message) {
1653   RTC_DCHECK_RUN_ON(network_thread_);
1654   if (remote_support_goog_ping_ == true && cached_stun_binding_ &&
1655       cached_stun_binding_->EqualAttributes(message, [](int type) {
1656         // Ignore these attributes.
1657         // NOTE: Consider what to do if adding more content to
1658         // STUN_ATTR_GOOG_MISC_INFO
1659         return type != STUN_ATTR_FINGERPRINT &&
1660                type != STUN_ATTR_MESSAGE_INTEGRITY &&
1661                type != STUN_ATTR_RETRANSMIT_COUNT &&
1662                type != STUN_ATTR_GOOG_MISC_INFO;
1663       })) {
1664     return true;
1665   }
1666   return false;
1667 }
1668 
ForgetLearnedState()1669 void Connection::ForgetLearnedState() {
1670   RTC_DCHECK_RUN_ON(network_thread_);
1671   RTC_LOG(LS_INFO) << ToString() << ": Connection forget learned state";
1672   requests_.Clear();
1673   receiving_ = false;
1674   write_state_ = STATE_WRITE_INIT;
1675   rtt_estimate_.Reset();
1676   pings_since_last_response_.clear();
1677 }
1678 
ProxyConnection(rtc::WeakPtr<Port> port,size_t index,const Candidate & remote_candidate)1679 ProxyConnection::ProxyConnection(rtc::WeakPtr<Port> port,
1680                                  size_t index,
1681                                  const Candidate& remote_candidate)
1682     : Connection(std::move(port), index, remote_candidate) {}
1683 
Send(const void * data,size_t size,const rtc::PacketOptions & options)1684 int ProxyConnection::Send(const void* data,
1685                           size_t size,
1686                           const rtc::PacketOptions& options) {
1687   if (!port_)
1688     return SOCKET_ERROR;
1689 
1690   stats_.sent_total_packets++;
1691   int sent =
1692       port_->SendTo(data, size, remote_candidate_.address(), options, true);
1693   int64_t now = rtc::TimeMillis();
1694   if (sent <= 0) {
1695     RTC_DCHECK(sent < 0);
1696     error_ = port_->GetError();
1697     stats_.sent_discarded_packets++;
1698     stats_.sent_discarded_bytes += size;
1699   } else {
1700     send_rate_tracker_.AddSamplesAtTime(now, sent);
1701   }
1702   last_send_data_ = now;
1703   return sent;
1704 }
1705 
GetError()1706 int ProxyConnection::GetError() {
1707   return error_;
1708 }
1709 
1710 }  // namespace cricket
1711