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
39 // We also cap the doubling, even though the standard doesn't say to.
40 // This has been 1.6 seconds for years, but for networks that
41 // experience moments of high RTT (such as 2G networks), this doesn't
42 // work well.
43 const int STUN_MAX_RTO = 8000; // milliseconds, or 5 doublings
44
StunRequestManager(rtc::Thread * thread)45 StunRequestManager::StunRequestManager(rtc::Thread* thread) : thread_(thread) {}
46
~StunRequestManager()47 StunRequestManager::~StunRequestManager() {
48 while (requests_.begin() != requests_.end()) {
49 StunRequest* request = requests_.begin()->second;
50 requests_.erase(requests_.begin());
51 delete request;
52 }
53 }
54
Send(StunRequest * request)55 void StunRequestManager::Send(StunRequest* request) {
56 SendDelayed(request, 0);
57 }
58
SendDelayed(StunRequest * request,int delay)59 void StunRequestManager::SendDelayed(StunRequest* request, int delay) {
60 request->set_manager(this);
61 RTC_DCHECK(requests_.find(request->id()) == requests_.end());
62 request->set_origin(origin_);
63 request->Construct();
64 requests_[request->id()] = request;
65 if (delay > 0) {
66 thread_->PostDelayed(RTC_FROM_HERE, delay, request, MSG_STUN_SEND, NULL);
67 } else {
68 thread_->Send(RTC_FROM_HERE, request, MSG_STUN_SEND, NULL);
69 }
70 }
71
Flush(int msg_type)72 void StunRequestManager::Flush(int msg_type) {
73 for (const auto& kv : requests_) {
74 StunRequest* request = kv.second;
75 if (msg_type == kAllRequests || msg_type == request->type()) {
76 thread_->Clear(request, MSG_STUN_SEND);
77 thread_->Send(RTC_FROM_HERE, request, MSG_STUN_SEND, NULL);
78 }
79 }
80 }
81
HasRequest(int msg_type)82 bool StunRequestManager::HasRequest(int msg_type) {
83 for (const auto& kv : requests_) {
84 StunRequest* request = kv.second;
85 if (msg_type == kAllRequests || msg_type == request->type()) {
86 return true;
87 }
88 }
89 return false;
90 }
91
Remove(StunRequest * request)92 void StunRequestManager::Remove(StunRequest* request) {
93 RTC_DCHECK(request->manager() == this);
94 RequestMap::iterator iter = requests_.find(request->id());
95 if (iter != requests_.end()) {
96 RTC_DCHECK(iter->second == request);
97 requests_.erase(iter);
98 thread_->Clear(request);
99 }
100 }
101
Clear()102 void StunRequestManager::Clear() {
103 std::vector<StunRequest*> requests;
104 for (RequestMap::iterator i = requests_.begin(); i != requests_.end(); ++i)
105 requests.push_back(i->second);
106
107 for (uint32_t i = 0; i < requests.size(); ++i) {
108 // StunRequest destructor calls Remove() which deletes requests
109 // from |requests_|.
110 delete requests[i];
111 }
112 }
113
CheckResponse(StunMessage * msg)114 bool StunRequestManager::CheckResponse(StunMessage* msg) {
115 RequestMap::iterator iter = requests_.find(msg->transaction_id());
116 if (iter == requests_.end()) {
117 // TODO(pthatcher): Log unknown responses without being too spammy
118 // in the logs.
119 return false;
120 }
121
122 StunRequest* request = iter->second;
123 if (!msg->GetNonComprehendedAttributes().empty()) {
124 // If a response contains unknown comprehension-required attributes, it's
125 // simply discarded and the transaction is considered failed. See RFC5389
126 // sections 7.3.3 and 7.3.4.
127 RTC_LOG(LS_ERROR) << ": Discarding response due to unknown "
128 "comprehension-required attribute.";
129 delete request;
130 return false;
131 } else if (msg->type() == GetStunSuccessResponseType(request->type())) {
132 request->OnResponse(msg);
133 } else if (msg->type() == GetStunErrorResponseType(request->type())) {
134 request->OnErrorResponse(msg);
135 } else {
136 RTC_LOG(LERROR) << "Received response with wrong type: " << msg->type()
137 << " (expecting "
138 << GetStunSuccessResponseType(request->type()) << ")";
139 return false;
140 }
141
142 delete request;
143 return true;
144 }
145
CheckResponse(const char * data,size_t size)146 bool StunRequestManager::CheckResponse(const char* data, size_t size) {
147 // Check the appropriate bytes of the stream to see if they match the
148 // transaction ID of a response we are expecting.
149
150 if (size < 20)
151 return false;
152
153 std::string id;
154 id.append(data + kStunTransactionIdOffset, kStunTransactionIdLength);
155
156 RequestMap::iterator iter = requests_.find(id);
157 if (iter == requests_.end()) {
158 // TODO(pthatcher): Log unknown responses without being too spammy
159 // in the logs.
160 return false;
161 }
162
163 // Parse the STUN message and continue processing as usual.
164
165 rtc::ByteBufferReader buf(data, size);
166 std::unique_ptr<StunMessage> response(iter->second->msg_->CreateNew());
167 if (!response->Read(&buf)) {
168 RTC_LOG(LS_WARNING) << "Failed to read STUN response "
169 << rtc::hex_encode(id);
170 return false;
171 }
172
173 return CheckResponse(response.get());
174 }
175
StunRequest()176 StunRequest::StunRequest()
177 : count_(0),
178 timeout_(false),
179 manager_(0),
180 msg_(new StunMessage()),
181 tstamp_(0) {
182 msg_->SetTransactionID(rtc::CreateRandomString(kStunTransactionIdLength));
183 }
184
StunRequest(StunMessage * request)185 StunRequest::StunRequest(StunMessage* request)
186 : count_(0), timeout_(false), manager_(0), msg_(request), tstamp_(0) {
187 msg_->SetTransactionID(rtc::CreateRandomString(kStunTransactionIdLength));
188 }
189
~StunRequest()190 StunRequest::~StunRequest() {
191 RTC_DCHECK(manager_ != NULL);
192 if (manager_) {
193 manager_->Remove(this);
194 manager_->thread_->Clear(this);
195 }
196 delete msg_;
197 }
198
Construct()199 void StunRequest::Construct() {
200 if (msg_->type() == 0) {
201 if (!origin_.empty()) {
202 msg_->AddAttribute(
203 std::make_unique<StunByteStringAttribute>(STUN_ATTR_ORIGIN, origin_));
204 }
205 Prepare(msg_);
206 RTC_DCHECK(msg_->type() != 0);
207 }
208 }
209
type()210 int StunRequest::type() {
211 RTC_DCHECK(msg_ != NULL);
212 return msg_->type();
213 }
214
msg() const215 const StunMessage* StunRequest::msg() const {
216 return msg_;
217 }
218
mutable_msg()219 StunMessage* StunRequest::mutable_msg() {
220 return msg_;
221 }
222
Elapsed() const223 int StunRequest::Elapsed() const {
224 return static_cast<int>(rtc::TimeMillis() - tstamp_);
225 }
226
set_manager(StunRequestManager * manager)227 void StunRequest::set_manager(StunRequestManager* manager) {
228 RTC_DCHECK(!manager_);
229 manager_ = manager;
230 }
231
OnMessage(rtc::Message * pmsg)232 void StunRequest::OnMessage(rtc::Message* pmsg) {
233 RTC_DCHECK(manager_ != NULL);
234 RTC_DCHECK(pmsg->message_id == MSG_STUN_SEND);
235
236 if (timeout_) {
237 OnTimeout();
238 delete this;
239 return;
240 }
241
242 tstamp_ = rtc::TimeMillis();
243
244 rtc::ByteBufferWriter buf;
245 msg_->Write(&buf);
246 manager_->SignalSendPacket(buf.Data(), buf.Length(), this);
247
248 OnSent();
249 manager_->thread_->PostDelayed(RTC_FROM_HERE, resend_delay(), this,
250 MSG_STUN_SEND, NULL);
251 }
252
OnSent()253 void StunRequest::OnSent() {
254 count_ += 1;
255 int retransmissions = (count_ - 1);
256 if (retransmissions >= STUN_MAX_RETRANSMISSIONS) {
257 timeout_ = true;
258 }
259 RTC_LOG(LS_VERBOSE) << "Sent STUN request " << count_
260 << "; resend delay = " << resend_delay();
261 }
262
resend_delay()263 int StunRequest::resend_delay() {
264 if (count_ == 0) {
265 return 0;
266 }
267 int retransmissions = (count_ - 1);
268 int rto = STUN_INITIAL_RTO << retransmissions;
269 return std::min(rto, STUN_MAX_RTO);
270 }
271
272 } // namespace cricket
273