1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright 2004 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/stun_request.h"
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker #include <algorithm>
14*d9f75844SAndroid Build Coastguard Worker #include <memory>
15*d9f75844SAndroid Build Coastguard Worker #include <utility>
16*d9f75844SAndroid Build Coastguard Worker #include <vector>
17*d9f75844SAndroid Build Coastguard Worker
18*d9f75844SAndroid Build Coastguard Worker #include "absl/memory/memory.h"
19*d9f75844SAndroid Build Coastguard Worker #include "api/task_queue/pending_task_safety_flag.h"
20*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
21*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/helpers.h"
22*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
23*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/string_encode.h"
24*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/time_utils.h" // For TimeMillis
25*d9f75844SAndroid Build Coastguard Worker
26*d9f75844SAndroid Build Coastguard Worker namespace cricket {
27*d9f75844SAndroid Build Coastguard Worker using ::webrtc::SafeTask;
28*d9f75844SAndroid Build Coastguard Worker
29*d9f75844SAndroid Build Coastguard Worker // RFC 5389 says SHOULD be 500ms.
30*d9f75844SAndroid Build Coastguard Worker // For years, this was 100ms, but for networks that
31*d9f75844SAndroid Build Coastguard Worker // experience moments of high RTT (such as 2G networks), this doesn't
32*d9f75844SAndroid Build Coastguard Worker // work well.
33*d9f75844SAndroid Build Coastguard Worker const int STUN_INITIAL_RTO = 250; // milliseconds
34*d9f75844SAndroid Build Coastguard Worker
35*d9f75844SAndroid Build Coastguard Worker // The timeout doubles each retransmission, up to this many times
36*d9f75844SAndroid Build Coastguard Worker // RFC 5389 says SHOULD retransmit 7 times.
37*d9f75844SAndroid Build Coastguard Worker // This has been 8 for years (not sure why).
38*d9f75844SAndroid Build Coastguard Worker const int STUN_MAX_RETRANSMISSIONS = 8; // Total sends: 9
39*d9f75844SAndroid Build Coastguard Worker
40*d9f75844SAndroid Build Coastguard Worker // We also cap the doubling, even though the standard doesn't say to.
41*d9f75844SAndroid Build Coastguard Worker // This has been 1.6 seconds for years, but for networks that
42*d9f75844SAndroid Build Coastguard Worker // experience moments of high RTT (such as 2G networks), this doesn't
43*d9f75844SAndroid Build Coastguard Worker // work well.
44*d9f75844SAndroid Build Coastguard Worker const int STUN_MAX_RTO = 8000; // milliseconds, or 5 doublings
45*d9f75844SAndroid Build Coastguard Worker
StunRequestManager(webrtc::TaskQueueBase * thread,std::function<void (const void *,size_t,StunRequest *)> send_packet)46*d9f75844SAndroid Build Coastguard Worker StunRequestManager::StunRequestManager(
47*d9f75844SAndroid Build Coastguard Worker webrtc::TaskQueueBase* thread,
48*d9f75844SAndroid Build Coastguard Worker std::function<void(const void*, size_t, StunRequest*)> send_packet)
49*d9f75844SAndroid Build Coastguard Worker : thread_(thread), send_packet_(std::move(send_packet)) {}
50*d9f75844SAndroid Build Coastguard Worker
51*d9f75844SAndroid Build Coastguard Worker StunRequestManager::~StunRequestManager() = default;
52*d9f75844SAndroid Build Coastguard Worker
Send(StunRequest * request)53*d9f75844SAndroid Build Coastguard Worker void StunRequestManager::Send(StunRequest* request) {
54*d9f75844SAndroid Build Coastguard Worker SendDelayed(request, 0);
55*d9f75844SAndroid Build Coastguard Worker }
56*d9f75844SAndroid Build Coastguard Worker
SendDelayed(StunRequest * request,int delay)57*d9f75844SAndroid Build Coastguard Worker void StunRequestManager::SendDelayed(StunRequest* request, int delay) {
58*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(thread_);
59*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_EQ(this, request->manager());
60*d9f75844SAndroid Build Coastguard Worker auto [iter, was_inserted] =
61*d9f75844SAndroid Build Coastguard Worker requests_.emplace(request->id(), absl::WrapUnique(request));
62*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(was_inserted);
63*d9f75844SAndroid Build Coastguard Worker request->Send(webrtc::TimeDelta::Millis(delay));
64*d9f75844SAndroid Build Coastguard Worker }
65*d9f75844SAndroid Build Coastguard Worker
FlushForTest(int msg_type)66*d9f75844SAndroid Build Coastguard Worker void StunRequestManager::FlushForTest(int msg_type) {
67*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(thread_);
68*d9f75844SAndroid Build Coastguard Worker for (const auto& [unused, request] : requests_) {
69*d9f75844SAndroid Build Coastguard Worker if (msg_type == kAllRequestsForTest || msg_type == request->type()) {
70*d9f75844SAndroid Build Coastguard Worker // Calling `Send` implies starting the send operation which may be posted
71*d9f75844SAndroid Build Coastguard Worker // on a timer and be repeated on a timer until timeout. To make sure that
72*d9f75844SAndroid Build Coastguard Worker // a call to `Send` doesn't conflict with a previously started `Send`
73*d9f75844SAndroid Build Coastguard Worker // operation, we reset the `task_safety_` flag here, which has the effect
74*d9f75844SAndroid Build Coastguard Worker // of canceling any outstanding tasks and prepare a new flag for
75*d9f75844SAndroid Build Coastguard Worker // operations related to this call to `Send`.
76*d9f75844SAndroid Build Coastguard Worker request->ResetTasksForTest();
77*d9f75844SAndroid Build Coastguard Worker request->Send(webrtc::TimeDelta::Zero());
78*d9f75844SAndroid Build Coastguard Worker }
79*d9f75844SAndroid Build Coastguard Worker }
80*d9f75844SAndroid Build Coastguard Worker }
81*d9f75844SAndroid Build Coastguard Worker
HasRequestForTest(int msg_type)82*d9f75844SAndroid Build Coastguard Worker bool StunRequestManager::HasRequestForTest(int msg_type) {
83*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(thread_);
84*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_NE(msg_type, kAllRequestsForTest);
85*d9f75844SAndroid Build Coastguard Worker for (const auto& [unused, request] : requests_) {
86*d9f75844SAndroid Build Coastguard Worker if (msg_type == request->type()) {
87*d9f75844SAndroid Build Coastguard Worker return true;
88*d9f75844SAndroid Build Coastguard Worker }
89*d9f75844SAndroid Build Coastguard Worker }
90*d9f75844SAndroid Build Coastguard Worker return false;
91*d9f75844SAndroid Build Coastguard Worker }
92*d9f75844SAndroid Build Coastguard Worker
Clear()93*d9f75844SAndroid Build Coastguard Worker void StunRequestManager::Clear() {
94*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(thread_);
95*d9f75844SAndroid Build Coastguard Worker requests_.clear();
96*d9f75844SAndroid Build Coastguard Worker }
97*d9f75844SAndroid Build Coastguard Worker
CheckResponse(StunMessage * msg)98*d9f75844SAndroid Build Coastguard Worker bool StunRequestManager::CheckResponse(StunMessage* msg) {
99*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(thread_);
100*d9f75844SAndroid Build Coastguard Worker RequestMap::iterator iter = requests_.find(msg->transaction_id());
101*d9f75844SAndroid Build Coastguard Worker if (iter == requests_.end())
102*d9f75844SAndroid Build Coastguard Worker return false;
103*d9f75844SAndroid Build Coastguard Worker
104*d9f75844SAndroid Build Coastguard Worker StunRequest* request = iter->second.get();
105*d9f75844SAndroid Build Coastguard Worker
106*d9f75844SAndroid Build Coastguard Worker // Now that we know the request, we can see if the response is
107*d9f75844SAndroid Build Coastguard Worker // integrity-protected or not.
108*d9f75844SAndroid Build Coastguard Worker // For some tests, the message integrity is not set in the request.
109*d9f75844SAndroid Build Coastguard Worker // Complain, and then don't check.
110*d9f75844SAndroid Build Coastguard Worker bool skip_integrity_checking =
111*d9f75844SAndroid Build Coastguard Worker (request->msg()->integrity() == StunMessage::IntegrityStatus::kNotSet);
112*d9f75844SAndroid Build Coastguard Worker if (skip_integrity_checking) {
113*d9f75844SAndroid Build Coastguard Worker // This indicates lazy test writing (not adding integrity attribute).
114*d9f75844SAndroid Build Coastguard Worker // Complain, but only in debug mode (while developing).
115*d9f75844SAndroid Build Coastguard Worker RTC_DLOG(LS_ERROR)
116*d9f75844SAndroid Build Coastguard Worker << "CheckResponse called on a passwordless request. Fix test!";
117*d9f75844SAndroid Build Coastguard Worker } else {
118*d9f75844SAndroid Build Coastguard Worker if (msg->integrity() == StunMessage::IntegrityStatus::kNotSet) {
119*d9f75844SAndroid Build Coastguard Worker // Checking status for the first time. Normal.
120*d9f75844SAndroid Build Coastguard Worker msg->ValidateMessageIntegrity(request->msg()->password());
121*d9f75844SAndroid Build Coastguard Worker } else if (msg->integrity() == StunMessage::IntegrityStatus::kIntegrityOk &&
122*d9f75844SAndroid Build Coastguard Worker msg->password() == request->msg()->password()) {
123*d9f75844SAndroid Build Coastguard Worker // Status is already checked, with the same password. This is the case
124*d9f75844SAndroid Build Coastguard Worker // we would want to see happen.
125*d9f75844SAndroid Build Coastguard Worker } else if (msg->integrity() ==
126*d9f75844SAndroid Build Coastguard Worker StunMessage::IntegrityStatus::kIntegrityBad) {
127*d9f75844SAndroid Build Coastguard Worker // This indicates that the original check had the wrong password.
128*d9f75844SAndroid Build Coastguard Worker // Bad design, needs revisiting.
129*d9f75844SAndroid Build Coastguard Worker // TODO(crbug.com/1177125): Fix this.
130*d9f75844SAndroid Build Coastguard Worker msg->RevalidateMessageIntegrity(request->msg()->password());
131*d9f75844SAndroid Build Coastguard Worker } else {
132*d9f75844SAndroid Build Coastguard Worker RTC_CHECK_NOTREACHED();
133*d9f75844SAndroid Build Coastguard Worker }
134*d9f75844SAndroid Build Coastguard Worker }
135*d9f75844SAndroid Build Coastguard Worker
136*d9f75844SAndroid Build Coastguard Worker bool success = true;
137*d9f75844SAndroid Build Coastguard Worker
138*d9f75844SAndroid Build Coastguard Worker if (!msg->GetNonComprehendedAttributes().empty()) {
139*d9f75844SAndroid Build Coastguard Worker // If a response contains unknown comprehension-required attributes, it's
140*d9f75844SAndroid Build Coastguard Worker // simply discarded and the transaction is considered failed. See RFC5389
141*d9f75844SAndroid Build Coastguard Worker // sections 7.3.3 and 7.3.4.
142*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_ERROR) << ": Discarding response due to unknown "
143*d9f75844SAndroid Build Coastguard Worker "comprehension-required attribute.";
144*d9f75844SAndroid Build Coastguard Worker success = false;
145*d9f75844SAndroid Build Coastguard Worker } else if (msg->type() == GetStunSuccessResponseType(request->type())) {
146*d9f75844SAndroid Build Coastguard Worker if (!msg->IntegrityOk() && !skip_integrity_checking) {
147*d9f75844SAndroid Build Coastguard Worker return false;
148*d9f75844SAndroid Build Coastguard Worker }
149*d9f75844SAndroid Build Coastguard Worker request->OnResponse(msg);
150*d9f75844SAndroid Build Coastguard Worker } else if (msg->type() == GetStunErrorResponseType(request->type())) {
151*d9f75844SAndroid Build Coastguard Worker request->OnErrorResponse(msg);
152*d9f75844SAndroid Build Coastguard Worker } else {
153*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_ERROR) << "Received response with wrong type: " << msg->type()
154*d9f75844SAndroid Build Coastguard Worker << " (expecting "
155*d9f75844SAndroid Build Coastguard Worker << GetStunSuccessResponseType(request->type()) << ")";
156*d9f75844SAndroid Build Coastguard Worker return false;
157*d9f75844SAndroid Build Coastguard Worker }
158*d9f75844SAndroid Build Coastguard Worker
159*d9f75844SAndroid Build Coastguard Worker requests_.erase(iter);
160*d9f75844SAndroid Build Coastguard Worker return success;
161*d9f75844SAndroid Build Coastguard Worker }
162*d9f75844SAndroid Build Coastguard Worker
empty() const163*d9f75844SAndroid Build Coastguard Worker bool StunRequestManager::empty() const {
164*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(thread_);
165*d9f75844SAndroid Build Coastguard Worker return requests_.empty();
166*d9f75844SAndroid Build Coastguard Worker }
167*d9f75844SAndroid Build Coastguard Worker
CheckResponse(const char * data,size_t size)168*d9f75844SAndroid Build Coastguard Worker bool StunRequestManager::CheckResponse(const char* data, size_t size) {
169*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(thread_);
170*d9f75844SAndroid Build Coastguard Worker // Check the appropriate bytes of the stream to see if they match the
171*d9f75844SAndroid Build Coastguard Worker // transaction ID of a response we are expecting.
172*d9f75844SAndroid Build Coastguard Worker
173*d9f75844SAndroid Build Coastguard Worker if (size < 20)
174*d9f75844SAndroid Build Coastguard Worker return false;
175*d9f75844SAndroid Build Coastguard Worker
176*d9f75844SAndroid Build Coastguard Worker std::string id;
177*d9f75844SAndroid Build Coastguard Worker id.append(data + kStunTransactionIdOffset, kStunTransactionIdLength);
178*d9f75844SAndroid Build Coastguard Worker
179*d9f75844SAndroid Build Coastguard Worker RequestMap::iterator iter = requests_.find(id);
180*d9f75844SAndroid Build Coastguard Worker if (iter == requests_.end())
181*d9f75844SAndroid Build Coastguard Worker return false;
182*d9f75844SAndroid Build Coastguard Worker
183*d9f75844SAndroid Build Coastguard Worker // Parse the STUN message and continue processing as usual.
184*d9f75844SAndroid Build Coastguard Worker
185*d9f75844SAndroid Build Coastguard Worker rtc::ByteBufferReader buf(data, size);
186*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<StunMessage> response(iter->second->msg_->CreateNew());
187*d9f75844SAndroid Build Coastguard Worker if (!response->Read(&buf)) {
188*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_WARNING) << "Failed to read STUN response "
189*d9f75844SAndroid Build Coastguard Worker << rtc::hex_encode(id);
190*d9f75844SAndroid Build Coastguard Worker return false;
191*d9f75844SAndroid Build Coastguard Worker }
192*d9f75844SAndroid Build Coastguard Worker
193*d9f75844SAndroid Build Coastguard Worker return CheckResponse(response.get());
194*d9f75844SAndroid Build Coastguard Worker }
195*d9f75844SAndroid Build Coastguard Worker
OnRequestTimedOut(StunRequest * request)196*d9f75844SAndroid Build Coastguard Worker void StunRequestManager::OnRequestTimedOut(StunRequest* request) {
197*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(thread_);
198*d9f75844SAndroid Build Coastguard Worker requests_.erase(request->id());
199*d9f75844SAndroid Build Coastguard Worker }
200*d9f75844SAndroid Build Coastguard Worker
SendPacket(const void * data,size_t size,StunRequest * request)201*d9f75844SAndroid Build Coastguard Worker void StunRequestManager::SendPacket(const void* data,
202*d9f75844SAndroid Build Coastguard Worker size_t size,
203*d9f75844SAndroid Build Coastguard Worker StunRequest* request) {
204*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_EQ(this, request->manager());
205*d9f75844SAndroid Build Coastguard Worker send_packet_(data, size, request);
206*d9f75844SAndroid Build Coastguard Worker }
207*d9f75844SAndroid Build Coastguard Worker
StunRequest(StunRequestManager & manager)208*d9f75844SAndroid Build Coastguard Worker StunRequest::StunRequest(StunRequestManager& manager)
209*d9f75844SAndroid Build Coastguard Worker : manager_(manager),
210*d9f75844SAndroid Build Coastguard Worker msg_(new StunMessage(STUN_INVALID_MESSAGE_TYPE)),
211*d9f75844SAndroid Build Coastguard Worker tstamp_(0),
212*d9f75844SAndroid Build Coastguard Worker count_(0),
213*d9f75844SAndroid Build Coastguard Worker timeout_(false) {
214*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread());
215*d9f75844SAndroid Build Coastguard Worker }
216*d9f75844SAndroid Build Coastguard Worker
StunRequest(StunRequestManager & manager,std::unique_ptr<StunMessage> message)217*d9f75844SAndroid Build Coastguard Worker StunRequest::StunRequest(StunRequestManager& manager,
218*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<StunMessage> message)
219*d9f75844SAndroid Build Coastguard Worker : manager_(manager),
220*d9f75844SAndroid Build Coastguard Worker msg_(std::move(message)),
221*d9f75844SAndroid Build Coastguard Worker tstamp_(0),
222*d9f75844SAndroid Build Coastguard Worker count_(0),
223*d9f75844SAndroid Build Coastguard Worker timeout_(false) {
224*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread());
225*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(!msg_->transaction_id().empty());
226*d9f75844SAndroid Build Coastguard Worker }
227*d9f75844SAndroid Build Coastguard Worker
~StunRequest()228*d9f75844SAndroid Build Coastguard Worker StunRequest::~StunRequest() {}
229*d9f75844SAndroid Build Coastguard Worker
type()230*d9f75844SAndroid Build Coastguard Worker int StunRequest::type() {
231*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(msg_ != NULL);
232*d9f75844SAndroid Build Coastguard Worker return msg_->type();
233*d9f75844SAndroid Build Coastguard Worker }
234*d9f75844SAndroid Build Coastguard Worker
msg() const235*d9f75844SAndroid Build Coastguard Worker const StunMessage* StunRequest::msg() const {
236*d9f75844SAndroid Build Coastguard Worker return msg_.get();
237*d9f75844SAndroid Build Coastguard Worker }
238*d9f75844SAndroid Build Coastguard Worker
Elapsed() const239*d9f75844SAndroid Build Coastguard Worker int StunRequest::Elapsed() const {
240*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread());
241*d9f75844SAndroid Build Coastguard Worker return static_cast<int>(rtc::TimeMillis() - tstamp_);
242*d9f75844SAndroid Build Coastguard Worker }
243*d9f75844SAndroid Build Coastguard Worker
SendInternal()244*d9f75844SAndroid Build Coastguard Worker void StunRequest::SendInternal() {
245*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread());
246*d9f75844SAndroid Build Coastguard Worker if (timeout_) {
247*d9f75844SAndroid Build Coastguard Worker OnTimeout();
248*d9f75844SAndroid Build Coastguard Worker manager_.OnRequestTimedOut(this);
249*d9f75844SAndroid Build Coastguard Worker return;
250*d9f75844SAndroid Build Coastguard Worker }
251*d9f75844SAndroid Build Coastguard Worker
252*d9f75844SAndroid Build Coastguard Worker tstamp_ = rtc::TimeMillis();
253*d9f75844SAndroid Build Coastguard Worker
254*d9f75844SAndroid Build Coastguard Worker rtc::ByteBufferWriter buf;
255*d9f75844SAndroid Build Coastguard Worker msg_->Write(&buf);
256*d9f75844SAndroid Build Coastguard Worker manager_.SendPacket(buf.Data(), buf.Length(), this);
257*d9f75844SAndroid Build Coastguard Worker
258*d9f75844SAndroid Build Coastguard Worker OnSent();
259*d9f75844SAndroid Build Coastguard Worker SendDelayed(webrtc::TimeDelta::Millis(resend_delay()));
260*d9f75844SAndroid Build Coastguard Worker }
261*d9f75844SAndroid Build Coastguard Worker
SendDelayed(webrtc::TimeDelta delay)262*d9f75844SAndroid Build Coastguard Worker void StunRequest::SendDelayed(webrtc::TimeDelta delay) {
263*d9f75844SAndroid Build Coastguard Worker network_thread()->PostDelayedTask(
264*d9f75844SAndroid Build Coastguard Worker SafeTask(task_safety_.flag(), [this]() { SendInternal(); }), delay);
265*d9f75844SAndroid Build Coastguard Worker }
266*d9f75844SAndroid Build Coastguard Worker
Send(webrtc::TimeDelta delay)267*d9f75844SAndroid Build Coastguard Worker void StunRequest::Send(webrtc::TimeDelta delay) {
268*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread());
269*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_GE(delay.ms(), 0);
270*d9f75844SAndroid Build Coastguard Worker
271*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(!task_safety_.flag()->alive()) << "Send already called?";
272*d9f75844SAndroid Build Coastguard Worker task_safety_.flag()->SetAlive();
273*d9f75844SAndroid Build Coastguard Worker
274*d9f75844SAndroid Build Coastguard Worker delay.IsZero() ? SendInternal() : SendDelayed(delay);
275*d9f75844SAndroid Build Coastguard Worker }
276*d9f75844SAndroid Build Coastguard Worker
ResetTasksForTest()277*d9f75844SAndroid Build Coastguard Worker void StunRequest::ResetTasksForTest() {
278*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread());
279*d9f75844SAndroid Build Coastguard Worker task_safety_.reset(webrtc::PendingTaskSafetyFlag::CreateDetachedInactive());
280*d9f75844SAndroid Build Coastguard Worker count_ = 0;
281*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(!timeout_);
282*d9f75844SAndroid Build Coastguard Worker }
283*d9f75844SAndroid Build Coastguard Worker
OnSent()284*d9f75844SAndroid Build Coastguard Worker void StunRequest::OnSent() {
285*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread());
286*d9f75844SAndroid Build Coastguard Worker count_ += 1;
287*d9f75844SAndroid Build Coastguard Worker int retransmissions = (count_ - 1);
288*d9f75844SAndroid Build Coastguard Worker if (retransmissions >= STUN_MAX_RETRANSMISSIONS) {
289*d9f75844SAndroid Build Coastguard Worker timeout_ = true;
290*d9f75844SAndroid Build Coastguard Worker }
291*d9f75844SAndroid Build Coastguard Worker RTC_DLOG(LS_VERBOSE) << "Sent STUN request " << count_
292*d9f75844SAndroid Build Coastguard Worker << "; resend delay = " << resend_delay();
293*d9f75844SAndroid Build Coastguard Worker }
294*d9f75844SAndroid Build Coastguard Worker
resend_delay()295*d9f75844SAndroid Build Coastguard Worker int StunRequest::resend_delay() {
296*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread());
297*d9f75844SAndroid Build Coastguard Worker if (count_ == 0) {
298*d9f75844SAndroid Build Coastguard Worker return 0;
299*d9f75844SAndroid Build Coastguard Worker }
300*d9f75844SAndroid Build Coastguard Worker int retransmissions = (count_ - 1);
301*d9f75844SAndroid Build Coastguard Worker int rto = STUN_INITIAL_RTO << retransmissions;
302*d9f75844SAndroid Build Coastguard Worker return std::min(rto, STUN_MAX_RTO);
303*d9f75844SAndroid Build Coastguard Worker }
304*d9f75844SAndroid Build Coastguard Worker
set_timed_out()305*d9f75844SAndroid Build Coastguard Worker void StunRequest::set_timed_out() {
306*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread());
307*d9f75844SAndroid Build Coastguard Worker timeout_ = true;
308*d9f75844SAndroid Build Coastguard Worker }
309*d9f75844SAndroid Build Coastguard Worker
310*d9f75844SAndroid Build Coastguard Worker } // namespace cricket
311