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 "webrtc/p2p/base/stunrequest.h" 12 13 #include <algorithm> 14 #include "webrtc/base/common.h" 15 #include "webrtc/base/helpers.h" 16 #include "webrtc/base/logging.h" 17 #include "webrtc/base/stringencode.h" 18 19 namespace cricket { 20 21 const uint32_t MSG_STUN_SEND = 1; 22 23 const int MAX_SENDS = 9; 24 const int DELAY_UNIT = 100; // 100 milliseconds 25 const int DELAY_MAX_FACTOR = 16; 26 27 StunRequestManager::StunRequestManager(rtc::Thread* thread) 28 : thread_(thread) { 29 } 30 31 StunRequestManager::~StunRequestManager() { 32 while (requests_.begin() != requests_.end()) { 33 StunRequest *request = requests_.begin()->second; 34 requests_.erase(requests_.begin()); 35 delete request; 36 } 37 } 38 39 void StunRequestManager::Send(StunRequest* request) { 40 SendDelayed(request, 0); 41 } 42 43 void StunRequestManager::SendDelayed(StunRequest* request, int delay) { 44 request->set_manager(this); 45 ASSERT(requests_.find(request->id()) == requests_.end()); 46 request->set_origin(origin_); 47 request->Construct(); 48 requests_[request->id()] = request; 49 if (delay > 0) { 50 thread_->PostDelayed(delay, request, MSG_STUN_SEND, NULL); 51 } else { 52 thread_->Send(request, MSG_STUN_SEND, NULL); 53 } 54 } 55 56 void StunRequestManager::Flush(int msg_type) { 57 for (const auto kv : requests_) { 58 StunRequest* request = kv.second; 59 if (msg_type == kAllRequests || msg_type == request->type()) { 60 thread_->Clear(request, MSG_STUN_SEND); 61 thread_->Send(request, MSG_STUN_SEND, NULL); 62 } 63 } 64 } 65 66 void StunRequestManager::Remove(StunRequest* request) { 67 ASSERT(request->manager() == this); 68 RequestMap::iterator iter = requests_.find(request->id()); 69 if (iter != requests_.end()) { 70 ASSERT(iter->second == request); 71 requests_.erase(iter); 72 thread_->Clear(request); 73 } 74 } 75 76 void StunRequestManager::Clear() { 77 std::vector<StunRequest*> requests; 78 for (RequestMap::iterator i = requests_.begin(); i != requests_.end(); ++i) 79 requests.push_back(i->second); 80 81 for (uint32_t i = 0; i < requests.size(); ++i) { 82 // StunRequest destructor calls Remove() which deletes requests 83 // from |requests_|. 84 delete requests[i]; 85 } 86 } 87 88 bool StunRequestManager::CheckResponse(StunMessage* msg) { 89 RequestMap::iterator iter = requests_.find(msg->transaction_id()); 90 if (iter == requests_.end()) { 91 // TODO(pthatcher): Log unknown responses without being too spammy 92 // in the logs. 93 return false; 94 } 95 96 StunRequest* request = iter->second; 97 if (msg->type() == GetStunSuccessResponseType(request->type())) { 98 request->OnResponse(msg); 99 } else if (msg->type() == GetStunErrorResponseType(request->type())) { 100 request->OnErrorResponse(msg); 101 } else { 102 LOG(LERROR) << "Received response with wrong type: " << msg->type() 103 << " (expecting " 104 << GetStunSuccessResponseType(request->type()) << ")"; 105 return false; 106 } 107 108 delete request; 109 return true; 110 } 111 112 bool StunRequestManager::CheckResponse(const char* data, size_t size) { 113 // Check the appropriate bytes of the stream to see if they match the 114 // transaction ID of a response we are expecting. 115 116 if (size < 20) 117 return false; 118 119 std::string id; 120 id.append(data + kStunTransactionIdOffset, kStunTransactionIdLength); 121 122 RequestMap::iterator iter = requests_.find(id); 123 if (iter == requests_.end()) { 124 // TODO(pthatcher): Log unknown responses without being too spammy 125 // in the logs. 126 return false; 127 } 128 129 // Parse the STUN message and continue processing as usual. 130 131 rtc::ByteBuffer buf(data, size); 132 rtc::scoped_ptr<StunMessage> response(iter->second->msg_->CreateNew()); 133 if (!response->Read(&buf)) { 134 LOG(LS_WARNING) << "Failed to read STUN response " << rtc::hex_encode(id); 135 return false; 136 } 137 138 return CheckResponse(response.get()); 139 } 140 141 StunRequest::StunRequest() 142 : count_(0), timeout_(false), manager_(0), 143 msg_(new StunMessage()), tstamp_(0) { 144 msg_->SetTransactionID( 145 rtc::CreateRandomString(kStunTransactionIdLength)); 146 } 147 148 StunRequest::StunRequest(StunMessage* request) 149 : count_(0), timeout_(false), manager_(0), 150 msg_(request), tstamp_(0) { 151 msg_->SetTransactionID( 152 rtc::CreateRandomString(kStunTransactionIdLength)); 153 } 154 155 StunRequest::~StunRequest() { 156 ASSERT(manager_ != NULL); 157 if (manager_) { 158 manager_->Remove(this); 159 manager_->thread_->Clear(this); 160 } 161 delete msg_; 162 } 163 164 void StunRequest::Construct() { 165 if (msg_->type() == 0) { 166 if (!origin_.empty()) { 167 msg_->AddAttribute(new StunByteStringAttribute(STUN_ATTR_ORIGIN, 168 origin_)); 169 } 170 Prepare(msg_); 171 ASSERT(msg_->type() != 0); 172 } 173 } 174 175 int StunRequest::type() { 176 ASSERT(msg_ != NULL); 177 return msg_->type(); 178 } 179 180 const StunMessage* StunRequest::msg() const { 181 return msg_; 182 } 183 184 uint32_t StunRequest::Elapsed() const { 185 return rtc::TimeSince(tstamp_); 186 } 187 188 189 void StunRequest::set_manager(StunRequestManager* manager) { 190 ASSERT(!manager_); 191 manager_ = manager; 192 } 193 194 void StunRequest::OnMessage(rtc::Message* pmsg) { 195 ASSERT(manager_ != NULL); 196 ASSERT(pmsg->message_id == MSG_STUN_SEND); 197 198 if (timeout_) { 199 OnTimeout(); 200 delete this; 201 return; 202 } 203 204 tstamp_ = rtc::Time(); 205 206 rtc::ByteBuffer buf; 207 msg_->Write(&buf); 208 manager_->SignalSendPacket(buf.Data(), buf.Length(), this); 209 210 OnSent(); 211 manager_->thread_->PostDelayed(resend_delay(), this, MSG_STUN_SEND, NULL); 212 } 213 214 void StunRequest::OnSent() { 215 count_ += 1; 216 if (count_ == MAX_SENDS) 217 timeout_ = true; 218 } 219 220 int StunRequest::resend_delay() { 221 if (count_ == 0) { 222 return 0; 223 } 224 return DELAY_UNIT * std::min(1 << (count_-1), DELAY_MAX_FACTOR); 225 } 226 227 } // namespace cricket 228