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