• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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