OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2015 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2015 The WebRTC Project Authors. All rights reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
(...skipping 10 matching lines...) Expand all Loading... |
21 #include "webrtc/base/timeutils.h" | 21 #include "webrtc/base/timeutils.h" |
22 #include "webrtc/base/thread.h" | 22 #include "webrtc/base/thread.h" |
23 #include "webrtc/p2p/base/packetsocketfactory.h" | 23 #include "webrtc/p2p/base/packetsocketfactory.h" |
24 #include "webrtc/p2p/base/stun.h" | 24 #include "webrtc/p2p/base/stun.h" |
25 #include "webrtc/p2p/stunprober/stunprober.h" | 25 #include "webrtc/p2p/stunprober/stunprober.h" |
26 | 26 |
27 namespace stunprober { | 27 namespace stunprober { |
28 | 28 |
29 namespace { | 29 namespace { |
30 | 30 |
31 const int thread_wake_up_interval_ms = 5; | 31 const int THREAD_WAKE_UP_INTERVAL_MS = 5; |
32 | 32 |
33 template <typename T> | 33 template <typename T> |
34 void IncrementCounterByAddress(std::map<T, int>* counter_per_ip, const T& ip) { | 34 void IncrementCounterByAddress(std::map<T, int>* counter_per_ip, const T& ip) { |
35 counter_per_ip->insert(std::make_pair(ip, 0)).first->second++; | 35 counter_per_ip->insert(std::make_pair(ip, 0)).first->second++; |
36 } | 36 } |
37 | 37 |
38 } // namespace | 38 } // namespace |
39 | 39 |
40 // A requester tracks the requests and responses from a single socket to many | 40 // A requester tracks the requests and responses from a single socket to many |
41 // STUN servers | 41 // STUN servers |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
136 cricket::StunMessage message; | 136 cricket::StunMessage message; |
137 | 137 |
138 // Random transaction ID, STUN_BINDING_REQUEST | 138 // Random transaction ID, STUN_BINDING_REQUEST |
139 message.SetTransactionID( | 139 message.SetTransactionID( |
140 rtc::CreateRandomString(cricket::kStunTransactionIdLength)); | 140 rtc::CreateRandomString(cricket::kStunTransactionIdLength)); |
141 message.SetType(cricket::STUN_BINDING_REQUEST); | 141 message.SetType(cricket::STUN_BINDING_REQUEST); |
142 | 142 |
143 rtc::scoped_ptr<rtc::ByteBuffer> request_packet( | 143 rtc::scoped_ptr<rtc::ByteBuffer> request_packet( |
144 new rtc::ByteBuffer(nullptr, kMaxUdpBufferSize)); | 144 new rtc::ByteBuffer(nullptr, kMaxUdpBufferSize)); |
145 if (!message.Write(request_packet.get())) { | 145 if (!message.Write(request_packet.get())) { |
146 prober_->End(WRITE_FAILED); | 146 prober_->ReportOnFinished(WRITE_FAILED); |
147 return; | 147 return; |
148 } | 148 } |
149 | 149 |
150 auto addr = server_ips_[num_request_sent_]; | 150 auto addr = server_ips_[num_request_sent_]; |
151 request.server_addr = addr.ipaddr(); | 151 request.server_addr = addr.ipaddr(); |
152 | 152 |
153 // The write must succeed immediately. Otherwise, the calculating of the STUN | 153 // The write must succeed immediately. Otherwise, the calculating of the STUN |
154 // request timing could become too complicated. Callback is ignored by passing | 154 // request timing could become too complicated. Callback is ignored by passing |
155 // empty AsyncCallback. | 155 // empty AsyncCallback. |
156 rtc::PacketOptions options; | 156 rtc::PacketOptions options; |
157 int rv = socket_->SendTo(const_cast<char*>(request_packet->Data()), | 157 int rv = socket_->SendTo(const_cast<char*>(request_packet->Data()), |
158 request_packet->Length(), addr, options); | 158 request_packet->Length(), addr, options); |
159 if (rv < 0) { | 159 if (rv < 0) { |
160 prober_->End(WRITE_FAILED); | 160 prober_->ReportOnFinished(WRITE_FAILED); |
161 return; | 161 return; |
162 } | 162 } |
163 | 163 |
164 request.sent_time_ms = rtc::Time(); | 164 request.sent_time_ms = rtc::Time(); |
165 | 165 |
166 num_request_sent_++; | 166 num_request_sent_++; |
167 RTC_DCHECK(static_cast<size_t>(num_request_sent_) <= server_ips_.size()); | 167 RTC_DCHECK(static_cast<size_t>(num_request_sent_) <= server_ips_.size()); |
168 } | 168 } |
169 | 169 |
170 void StunProber::Requester::Request::ProcessResponse(const char* buf, | 170 void StunProber::Requester::Request::ProcessResponse(const char* buf, |
(...skipping 29 matching lines...) Expand all Loading... |
200 rtc::AsyncPacketSocket* socket, | 200 rtc::AsyncPacketSocket* socket, |
201 const char* buf, | 201 const char* buf, |
202 size_t size, | 202 size_t size, |
203 const rtc::SocketAddress& addr, | 203 const rtc::SocketAddress& addr, |
204 const rtc::PacketTime& time) { | 204 const rtc::PacketTime& time) { |
205 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 205 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
206 RTC_DCHECK(socket_); | 206 RTC_DCHECK(socket_); |
207 Request* request = GetRequestByAddress(addr.ipaddr()); | 207 Request* request = GetRequestByAddress(addr.ipaddr()); |
208 if (!request) { | 208 if (!request) { |
209 // Something is wrong, finish the test. | 209 // Something is wrong, finish the test. |
210 prober_->End(GENERIC_FAILURE); | 210 prober_->ReportOnFinished(GENERIC_FAILURE); |
211 return; | 211 return; |
212 } | 212 } |
213 | 213 |
214 num_response_received_++; | 214 num_response_received_++; |
215 request->ProcessResponse(buf, size); | 215 request->ProcessResponse(buf, size); |
216 } | 216 } |
217 | 217 |
218 StunProber::Requester::Request* StunProber::Requester::GetRequestByAddress( | 218 StunProber::Requester::Request* StunProber::Requester::GetRequestByAddress( |
219 const rtc::IPAddress& ipaddr) { | 219 const rtc::IPAddress& ipaddr) { |
220 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 220 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
(...skipping 27 matching lines...) Expand all Loading... |
248 } | 248 } |
249 } | 249 } |
250 } | 250 } |
251 | 251 |
252 bool StunProber::Start(const std::vector<rtc::SocketAddress>& servers, | 252 bool StunProber::Start(const std::vector<rtc::SocketAddress>& servers, |
253 bool shared_socket_mode, | 253 bool shared_socket_mode, |
254 int interval_ms, | 254 int interval_ms, |
255 int num_request_per_ip, | 255 int num_request_per_ip, |
256 int timeout_ms, | 256 int timeout_ms, |
257 const AsyncCallback callback) { | 257 const AsyncCallback callback) { |
| 258 observer_adapter_.set_callback(callback); |
| 259 return Prepare(servers, shared_socket_mode, interval_ms, num_request_per_ip, |
| 260 timeout_ms, &observer_adapter_); |
| 261 } |
| 262 |
| 263 bool StunProber::Prepare(const std::vector<rtc::SocketAddress>& servers, |
| 264 bool shared_socket_mode, |
| 265 int interval_ms, |
| 266 int num_request_per_ip, |
| 267 int timeout_ms, |
| 268 StunProber::Observer* observer) { |
258 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 269 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
259 interval_ms_ = interval_ms; | 270 interval_ms_ = interval_ms; |
260 shared_socket_mode_ = shared_socket_mode; | 271 shared_socket_mode_ = shared_socket_mode; |
261 | 272 |
262 requests_per_ip_ = num_request_per_ip; | 273 requests_per_ip_ = num_request_per_ip; |
263 if (requests_per_ip_ == 0 || servers.size() == 0) { | 274 if (requests_per_ip_ == 0 || servers.size() == 0) { |
264 return false; | 275 return false; |
265 } | 276 } |
266 | 277 |
267 timeout_ms_ = timeout_ms; | 278 timeout_ms_ = timeout_ms; |
268 servers_ = servers; | 279 servers_ = servers; |
269 finished_callback_ = callback; | 280 observer_ = observer; |
270 return ResolveServerName(servers_.back()); | 281 return ResolveServerName(servers_.back()); |
271 } | 282 } |
272 | 283 |
| 284 bool StunProber::Run(StunProber::Observer* observer) { |
| 285 observer_ = observer; |
| 286 if (total_ready_sockets_ != total_socket_required()) { |
| 287 return false; |
| 288 } |
| 289 MaybeScheduleStunRequests(); |
| 290 return true; |
| 291 } |
| 292 |
273 bool StunProber::ResolveServerName(const rtc::SocketAddress& addr) { | 293 bool StunProber::ResolveServerName(const rtc::SocketAddress& addr) { |
274 rtc::AsyncResolverInterface* resolver = | 294 rtc::AsyncResolverInterface* resolver = |
275 socket_factory_->CreateAsyncResolver(); | 295 socket_factory_->CreateAsyncResolver(); |
276 if (!resolver) { | 296 if (!resolver) { |
277 return false; | 297 return false; |
278 } | 298 } |
279 resolver->SignalDone.connect(this, &StunProber::OnServerResolved); | 299 resolver->SignalDone.connect(this, &StunProber::OnServerResolved); |
280 resolver->Start(addr); | 300 resolver->Start(addr); |
281 return true; | 301 return true; |
282 } | 302 } |
283 | 303 |
284 void StunProber::OnSocketReady(rtc::AsyncPacketSocket* socket, | 304 void StunProber::OnSocketReady(rtc::AsyncPacketSocket* socket, |
285 const rtc::SocketAddress& addr) { | 305 const rtc::SocketAddress& addr) { |
286 total_ready_sockets_++; | 306 total_ready_sockets_++; |
287 if (total_ready_sockets_ == total_socket_required()) { | 307 if (total_ready_sockets_ == total_socket_required()) { |
288 MaybeScheduleStunRequests(); | 308 ReportOnPrepared(SUCCESS); |
289 } | 309 } |
290 } | 310 } |
291 | 311 |
292 void StunProber::OnServerResolved(rtc::AsyncResolverInterface* resolver) { | 312 void StunProber::OnServerResolved(rtc::AsyncResolverInterface* resolver) { |
293 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 313 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
294 | 314 |
295 if (resolver->GetError() == 0) { | 315 if (resolver->GetError() == 0) { |
296 rtc::SocketAddress addr(resolver->address().ipaddr(), | 316 rtc::SocketAddress addr(resolver->address().ipaddr(), |
297 resolver->address().port()); | 317 resolver->address().port()); |
298 all_servers_addrs_.push_back(addr); | 318 all_servers_addrs_.push_back(addr); |
299 } | 319 } |
300 | 320 |
301 // Deletion of AsyncResolverInterface can't be done in OnResolveResult which | 321 // Deletion of AsyncResolverInterface can't be done in OnResolveResult which |
302 // handles SignalDone. | 322 // handles SignalDone. |
303 invoker_.AsyncInvoke<void>( | 323 invoker_.AsyncInvoke<void>( |
304 thread_, | 324 thread_, |
305 rtc::Bind(&rtc::AsyncResolverInterface::Destroy, resolver, false)); | 325 rtc::Bind(&rtc::AsyncResolverInterface::Destroy, resolver, false)); |
306 servers_.pop_back(); | 326 servers_.pop_back(); |
307 | 327 |
308 if (servers_.size()) { | 328 if (servers_.size()) { |
309 if (!ResolveServerName(servers_.back())) { | 329 if (!ResolveServerName(servers_.back())) { |
310 End(RESOLVE_FAILED); | 330 ReportOnPrepared(RESOLVE_FAILED); |
311 } | 331 } |
312 return; | 332 return; |
313 } | 333 } |
314 | 334 |
315 if (all_servers_addrs_.size() == 0) { | 335 if (all_servers_addrs_.size() == 0) { |
316 End(RESOLVE_FAILED); | 336 ReportOnPrepared(RESOLVE_FAILED); |
317 return; | 337 return; |
318 } | 338 } |
319 | 339 |
320 // Dedupe. | 340 // Dedupe. |
321 std::set<rtc::SocketAddress> addrs(all_servers_addrs_.begin(), | 341 std::set<rtc::SocketAddress> addrs(all_servers_addrs_.begin(), |
322 all_servers_addrs_.end()); | 342 all_servers_addrs_.end()); |
323 all_servers_addrs_.assign(addrs.begin(), addrs.end()); | 343 all_servers_addrs_.assign(addrs.begin(), addrs.end()); |
324 | 344 |
325 // Prepare all the sockets beforehand. All of them will bind to "any" address. | 345 // Prepare all the sockets beforehand. All of them will bind to "any" address. |
326 while (sockets_.size() < total_socket_required()) { | 346 while (sockets_.size() < total_socket_required()) { |
327 rtc::scoped_ptr<rtc::AsyncPacketSocket> socket( | 347 rtc::scoped_ptr<rtc::AsyncPacketSocket> socket( |
328 socket_factory_->CreateUdpSocket(rtc::SocketAddress(INADDR_ANY, 0), 0, | 348 socket_factory_->CreateUdpSocket(rtc::SocketAddress(INADDR_ANY, 0), 0, |
329 0)); | 349 0)); |
330 if (!socket) { | 350 if (!socket) { |
331 End(GENERIC_FAILURE); | 351 ReportOnPrepared(GENERIC_FAILURE); |
332 return; | 352 return; |
333 } | 353 } |
334 // Chrome and WebRTC behave differently in terms of the state of a socket | 354 // Chrome and WebRTC behave differently in terms of the state of a socket |
335 // once returned from PacketSocketFactory::CreateUdpSocket. | 355 // once returned from PacketSocketFactory::CreateUdpSocket. |
336 if (socket->GetState() == rtc::AsyncPacketSocket::STATE_BINDING) { | 356 if (socket->GetState() == rtc::AsyncPacketSocket::STATE_BINDING) { |
337 socket->SignalAddressReady.connect(this, &StunProber::OnSocketReady); | 357 socket->SignalAddressReady.connect(this, &StunProber::OnSocketReady); |
338 } else { | 358 } else { |
339 OnSocketReady(socket.get(), rtc::SocketAddress(INADDR_ANY, 0)); | 359 OnSocketReady(socket.get(), rtc::SocketAddress(INADDR_ANY, 0)); |
340 } | 360 } |
341 sockets_.push_back(socket.release()); | 361 sockets_.push_back(socket.release()); |
(...skipping 25 matching lines...) Expand all Loading... |
367 requesters_.push_back(current_requester_); | 387 requesters_.push_back(current_requester_); |
368 } | 388 } |
369 if (!current_requester_) { | 389 if (!current_requester_) { |
370 return false; | 390 return false; |
371 } | 391 } |
372 current_requester_->SendStunRequest(); | 392 current_requester_->SendStunRequest(); |
373 num_request_sent_++; | 393 num_request_sent_++; |
374 return true; | 394 return true; |
375 } | 395 } |
376 | 396 |
| 397 bool StunProber::should_send_next_request(uint32_t now) { |
| 398 if (interval_ms_ < THREAD_WAKE_UP_INTERVAL_MS) { |
| 399 return now >= next_request_time_ms_; |
| 400 } else { |
| 401 return (now + (THREAD_WAKE_UP_INTERVAL_MS / 2)) >= next_request_time_ms_; |
| 402 } |
| 403 } |
| 404 |
| 405 int StunProber::get_wake_up_interval_ms() { |
| 406 if (interval_ms_ < THREAD_WAKE_UP_INTERVAL_MS) { |
| 407 return 1; |
| 408 } else { |
| 409 return THREAD_WAKE_UP_INTERVAL_MS; |
| 410 } |
| 411 } |
| 412 |
377 void StunProber::MaybeScheduleStunRequests() { | 413 void StunProber::MaybeScheduleStunRequests() { |
378 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 414 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
379 uint32_t now = rtc::Time(); | 415 uint32_t now = rtc::Time(); |
380 | 416 |
381 if (Done()) { | 417 if (Done()) { |
382 invoker_.AsyncInvokeDelayed<void>( | 418 invoker_.AsyncInvokeDelayed<void>( |
383 thread_, rtc::Bind(&StunProber::End, this, SUCCESS), timeout_ms_); | 419 thread_, rtc::Bind(&StunProber::ReportOnFinished, this, SUCCESS), |
| 420 timeout_ms_); |
384 return; | 421 return; |
385 } | 422 } |
386 if ((now + (thread_wake_up_interval_ms / 2)) >= next_request_time_ms_) { | 423 if (should_send_next_request(now)) { |
387 if (!SendNextRequest()) { | 424 if (!SendNextRequest()) { |
388 End(GENERIC_FAILURE); | 425 ReportOnFinished(GENERIC_FAILURE); |
389 return; | 426 return; |
390 } | 427 } |
391 next_request_time_ms_ = now + interval_ms_; | 428 next_request_time_ms_ = now + interval_ms_; |
392 } | 429 } |
393 invoker_.AsyncInvokeDelayed<void>( | 430 invoker_.AsyncInvokeDelayed<void>( |
394 thread_, rtc::Bind(&StunProber::MaybeScheduleStunRequests, this), | 431 thread_, rtc::Bind(&StunProber::MaybeScheduleStunRequests, this), |
395 thread_wake_up_interval_ms /* ms */); | 432 get_wake_up_interval_ms()); |
396 } | 433 } |
397 | 434 |
398 bool StunProber::GetStats(StunProber::Stats* prob_stats) const { | 435 bool StunProber::GetStats(StunProber::Stats* prob_stats) const { |
399 // No need to be on the same thread. | 436 // No need to be on the same thread. |
400 if (!prob_stats) { | 437 if (!prob_stats) { |
401 return false; | 438 return false; |
402 } | 439 } |
403 | 440 |
404 StunProber::Stats stats; | 441 StunProber::Stats stats; |
405 | 442 |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
513 } | 550 } |
514 | 551 |
515 if (num_received) { | 552 if (num_received) { |
516 stats.average_rtt_ms = static_cast<int>((rtt_sum / num_received)); | 553 stats.average_rtt_ms = static_cast<int>((rtt_sum / num_received)); |
517 } | 554 } |
518 | 555 |
519 *prob_stats = stats; | 556 *prob_stats = stats; |
520 return true; | 557 return true; |
521 } | 558 } |
522 | 559 |
523 void StunProber::End(StunProber::Status status) { | 560 void StunProber::ReportOnPrepared(StunProber::Status status) { |
524 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 561 if (observer_) { |
525 if (!finished_callback_.empty()) { | 562 observer_->OnPrepared(this, status); |
526 AsyncCallback callback = finished_callback_; | |
527 finished_callback_ = AsyncCallback(); | |
528 | |
529 // Callback at the last since the prober might be deleted in the callback. | |
530 callback(this, status); | |
531 } | 563 } |
532 } | 564 } |
533 | 565 |
| 566 void StunProber::ReportOnFinished(StunProber::Status status) { |
| 567 if (observer_) { |
| 568 observer_->OnFinished(this, status); |
| 569 } |
| 570 } |
| 571 |
534 } // namespace stunprober | 572 } // namespace stunprober |
OLD | NEW |