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