1 /*
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "p2p/base/stun_request.h"
12
13 #include <algorithm>
14 #include <memory>
15 #include <vector>
16
17 #include "rtc_base/checks.h"
18 #include "rtc_base/helpers.h"
19 #include "rtc_base/logging.h"
20 #include "rtc_base/string_encode.h"
21 #include "rtc_base/time_utils.h" // For TimeMillis
22 #include "system_wrappers/include/field_trial.h"
23
24 namespace cricket {
25
26 const uint32_t MSG_STUN_SEND = 1;
27
28 // RFC 5389 says SHOULD be 500ms.
29 // For years, this was 100ms, but for networks that
30 // experience moments of high RTT (such as 2G networks), this doesn't
31 // work well.
32 const int STUN_INITIAL_RTO = 250; // milliseconds
33
34 // The timeout doubles each retransmission, up to this many times
35 // RFC 5389 says SHOULD retransmit 7 times.
36 // This has been 8 for years (not sure why).
37 const int STUN_MAX_RETRANSMISSIONS = 8; // Total sends: 9
38 const int STUN_MAX_RETRANSMISSIONS_RFC_5389 = 6; // Total sends: 7
39
40 // We also cap the doubling, even though the standard doesn't say to.
41 // This has been 1.6 seconds for years, but for networks that
42 // experience moments of high RTT (such as 2G networks), this doesn't
43 // work well.
44 const int STUN_MAX_RTO = 8000; // milliseconds, or 5 doublings
45
46 namespace {
47 const char kRfc5389StunRetransmissions[] = "WebRTC-Rfc5389StunRetransmissions";
48 } // namespace
49
StunRequestManager(rtc::Thread * thread)50 StunRequestManager::StunRequestManager(rtc::Thread* thread) : thread_(thread) {}
51
~StunRequestManager()52 StunRequestManager::~StunRequestManager() {
53 while (requests_.begin() != requests_.end()) {
54 StunRequest* request = requests_.begin()->second;
55 requests_.erase(requests_.begin());
56 delete request;
57 }
58 }
59
Send(StunRequest * request)60 void StunRequestManager::Send(StunRequest* request) {
61 SendDelayed(request, 0);
62 }
63
SendDelayed(StunRequest * request,int delay)64 void StunRequestManager::SendDelayed(StunRequest* request, int delay) {
65 request->set_manager(this);
66 RTC_DCHECK(requests_.find(request->id()) == requests_.end());
67 request->set_origin(origin_);
68 request->Construct();
69 requests_[request->id()] = request;
70 if (delay > 0) {
71 thread_->PostDelayed(RTC_FROM_HERE, delay, request, MSG_STUN_SEND, NULL);
72 } else {
73 thread_->Send(RTC_FROM_HERE, request, MSG_STUN_SEND, NULL);
74 }
75 }
76
Flush(int msg_type)77 void StunRequestManager::Flush(int msg_type) {
78 for (const auto& kv : requests_) {
79 StunRequest* request = kv.second;
80 if (msg_type == kAllRequests || msg_type == request->type()) {
81 thread_->Clear(request, MSG_STUN_SEND);
82 thread_->Send(RTC_FROM_HERE, request, MSG_STUN_SEND, NULL);
83 }
84 }
85 }
86
HasRequest(int msg_type)87 bool StunRequestManager::HasRequest(int msg_type) {
88 for (const auto& kv : requests_) {
89 StunRequest* request = kv.second;
90 if (msg_type == kAllRequests || msg_type == request->type()) {
91 return true;
92 }
93 }
94 return false;
95 }
96
Remove(StunRequest * request)97 void StunRequestManager::Remove(StunRequest* request) {
98 RTC_DCHECK(request->manager() == this);
99 RequestMap::iterator iter = requests_.find(request->id());
100 if (iter != requests_.end()) {
101 RTC_DCHECK(iter->second == request);
102 requests_.erase(iter);
103 thread_->Clear(request);
104 }
105 }
106
Clear()107 void StunRequestManager::Clear() {
108 std::vector<StunRequest*> requests;
109 for (RequestMap::iterator i = requests_.begin(); i != requests_.end(); ++i)
110 requests.push_back(i->second);
111
112 for (uint32_t i = 0; i < requests.size(); ++i) {
113 // StunRequest destructor calls Remove() which deletes requests
114 // from |requests_|.
115 delete requests[i];
116 }
117 }
118
CheckResponse(StunMessage * msg)119 bool StunRequestManager::CheckResponse(StunMessage* msg) {
120 RequestMap::iterator iter = requests_.find(msg->transaction_id());
121 if (iter == requests_.end()) {
122 // TODO(pthatcher): Log unknown responses without being too spammy
123 // in the logs.
124 return false;
125 }
126
127 StunRequest* request = iter->second;
128 if (!msg->GetNonComprehendedAttributes().empty()) {
129 // If a response contains unknown comprehension-required attributes, it's
130 // simply discarded and the transaction is considered failed. See RFC5389
131 // sections 7.3.3 and 7.3.4.
132 RTC_LOG(LS_ERROR) << ": Discarding response due to unknown "
133 "comprehension-required attribute.";
134 delete request;
135 return false;
136 } else if (msg->type() == GetStunSuccessResponseType(request->type())) {
137 request->OnResponse(msg);
138 } else if (msg->type() == GetStunErrorResponseType(request->type())) {
139 request->OnErrorResponse(msg);
140 } else {
141 RTC_LOG(LERROR) << "Received response with wrong type: " << msg->type()
142 << " (expecting "
143 << GetStunSuccessResponseType(request->type()) << ")";
144 return false;
145 }
146
147 delete request;
148 return true;
149 }
150
CheckResponse(const char * data,size_t size)151 bool StunRequestManager::CheckResponse(const char* data, size_t size) {
152 // Check the appropriate bytes of the stream to see if they match the
153 // transaction ID of a response we are expecting.
154
155 if (size < 20)
156 return false;
157
158 std::string id;
159 id.append(data + kStunTransactionIdOffset, kStunTransactionIdLength);
160
161 RequestMap::iterator iter = requests_.find(id);
162 if (iter == requests_.end()) {
163 // TODO(pthatcher): Log unknown responses without being too spammy
164 // in the logs.
165 return false;
166 }
167
168 // Parse the STUN message and continue processing as usual.
169
170 rtc::ByteBufferReader buf(data, size);
171 std::unique_ptr<StunMessage> response(iter->second->msg_->CreateNew());
172 if (!response->Read(&buf)) {
173 RTC_LOG(LS_WARNING) << "Failed to read STUN response "
174 << rtc::hex_encode(id);
175 return false;
176 }
177
178 return CheckResponse(response.get());
179 }
180
StunRequest()181 StunRequest::StunRequest()
182 : count_(0),
183 timeout_(false),
184 manager_(0),
185 msg_(new StunMessage()),
186 tstamp_(0),
187 in_rfc5389_retransmission_experiment_(
188 webrtc::field_trial::IsEnabled(kRfc5389StunRetransmissions)) {
189 msg_->SetTransactionID(rtc::CreateRandomString(kStunTransactionIdLength));
190 }
191
StunRequest(StunMessage * request)192 StunRequest::StunRequest(StunMessage* request)
193 : count_(0),
194 timeout_(false),
195 manager_(0),
196 msg_(request),
197 tstamp_(0),
198 in_rfc5389_retransmission_experiment_(
199 webrtc::field_trial::IsEnabled(kRfc5389StunRetransmissions)) {
200 msg_->SetTransactionID(rtc::CreateRandomString(kStunTransactionIdLength));
201 }
202
~StunRequest()203 StunRequest::~StunRequest() {
204 RTC_DCHECK(manager_ != NULL);
205 if (manager_) {
206 manager_->Remove(this);
207 manager_->thread_->Clear(this);
208 }
209 delete msg_;
210 }
211
Construct()212 void StunRequest::Construct() {
213 if (msg_->type() == 0) {
214 if (!origin_.empty()) {
215 msg_->AddAttribute(
216 std::make_unique<StunByteStringAttribute>(STUN_ATTR_ORIGIN, origin_));
217 }
218 Prepare(msg_);
219 RTC_DCHECK(msg_->type() != 0);
220 }
221 }
222
type()223 int StunRequest::type() {
224 RTC_DCHECK(msg_ != NULL);
225 return msg_->type();
226 }
227
msg() const228 const StunMessage* StunRequest::msg() const {
229 return msg_;
230 }
231
mutable_msg()232 StunMessage* StunRequest::mutable_msg() {
233 return msg_;
234 }
235
Elapsed() const236 int StunRequest::Elapsed() const {
237 return static_cast<int>(rtc::TimeMillis() - tstamp_);
238 }
239
set_manager(StunRequestManager * manager)240 void StunRequest::set_manager(StunRequestManager* manager) {
241 RTC_DCHECK(!manager_);
242 manager_ = manager;
243 }
244
OnMessage(rtc::Message * pmsg)245 void StunRequest::OnMessage(rtc::Message* pmsg) {
246 RTC_DCHECK(manager_ != NULL);
247 RTC_DCHECK(pmsg->message_id == MSG_STUN_SEND);
248
249 if (timeout_) {
250 OnTimeout();
251 delete this;
252 return;
253 }
254
255 tstamp_ = rtc::TimeMillis();
256
257 rtc::ByteBufferWriter buf;
258 msg_->Write(&buf);
259 manager_->SignalSendPacket(buf.Data(), buf.Length(), this);
260
261 OnSent();
262 manager_->thread_->PostDelayed(RTC_FROM_HERE, resend_delay(), this,
263 MSG_STUN_SEND, NULL);
264 }
265
OnSent()266 void StunRequest::OnSent() {
267 count_ += 1;
268 int retransmissions = (count_ - 1);
269 if (retransmissions >= STUN_MAX_RETRANSMISSIONS ||
270 (in_rfc5389_retransmission_experiment_ &&
271 retransmissions >= STUN_MAX_RETRANSMISSIONS_RFC_5389)) {
272 timeout_ = true;
273 }
274 RTC_LOG(LS_VERBOSE) << "Sent STUN request " << count_
275 << "; resend delay = " << resend_delay();
276 }
277
resend_delay()278 int StunRequest::resend_delay() {
279 if (count_ == 0) {
280 return 0;
281 }
282 int retransmissions = (count_ - 1);
283 int rto = STUN_INITIAL_RTO << retransmissions;
284 return std::min(rto, STUN_MAX_RTO);
285 }
286
287 } // namespace cricket
288