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