Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(26)

Side by Side Diff: webrtc/p2p/stunprober/stunprober.cc

Issue 1173353002: Remove all glue interfaces and use existing webrtc interfaces (Closed) Base URL: https://chromium.googlesource.com/external/webrtc@master
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webrtc/p2p/stunprober/stunprober.h ('k') | webrtc/p2p/stunprober/stunprober_dependencies.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
11 #include <iostream> 11 #include <iostream>
12 #include <map> 12 #include <map>
13 #include <set> 13 #include <set>
14 #include <string> 14 #include <string>
15 15
16 #include "webrtc/base/asyncpacketsocket.h"
17 #include "webrtc/base/asyncresolverinterface.h"
16 #include "webrtc/base/bind.h" 18 #include "webrtc/base/bind.h"
17 #include "webrtc/base/checks.h" 19 #include "webrtc/base/checks.h"
18 #include "webrtc/base/helpers.h" 20 #include "webrtc/base/helpers.h"
21 #include "webrtc/base/logging.h"
19 #include "webrtc/base/timeutils.h" 22 #include "webrtc/base/timeutils.h"
23 #include "webrtc/base/thread.h"
24 #include "webrtc/p2p/base/packetsocketfactory.h"
20 #include "webrtc/p2p/base/stun.h" 25 #include "webrtc/p2p/base/stun.h"
21 #include "webrtc/p2p/stunprober/stunprober.h" 26 #include "webrtc/p2p/stunprober/stunprober.h"
22 27
23 namespace stunprober { 28 namespace stunprober {
24 29
25 namespace { 30 namespace {
26 31
32 const int thread_wake_up_interval_ms = 5;
33
27 template <typename T> 34 template <typename T>
28 void IncrementCounterByAddress(std::map<T, int>* counter_per_ip, const T& ip) { 35 void IncrementCounterByAddress(std::map<T, int>* counter_per_ip, const T& ip) {
29 counter_per_ip->insert(std::make_pair(ip, 0)).first->second++; 36 counter_per_ip->insert(std::make_pair(ip, 0)).first->second++;
30 } 37 }
31 38
32 bool behind_nat(NatType nat_type) {
33 return nat_type > stunprober::NATTYPE_NONE;
34 }
35
36 } // namespace 39 } // namespace
37 40
38 // A requester tracks the requests and responses from a single socket to many 41 // A requester tracks the requests and responses from a single socket to many
39 // STUN servers 42 // STUN servers
40 class StunProber::Requester { 43 class StunProber::Requester : public sigslot::has_slots<> {
41 public: 44 public:
42 // Each Request maps to a request and response. 45 // Each Request maps to a request and response.
43 struct Request { 46 struct Request {
44 // Actual time the STUN bind request was sent. 47 // Actual time the STUN bind request was sent.
45 int64 sent_time_ms = 0; 48 int64 sent_time_ms = 0;
46 // Time the response was received. 49 // Time the response was received.
47 int64 received_time_ms = 0; 50 int64 received_time_ms = 0;
48 51
49 // See whether the observed address returned matches the
50 // local address as in StunProber.local_addr_.
51 bool behind_nat = false;
52
53 // Server reflexive address from STUN response for this given request. 52 // Server reflexive address from STUN response for this given request.
54 rtc::SocketAddress srflx_addr; 53 rtc::SocketAddress srflx_addr;
55 54
56 rtc::IPAddress server_addr; 55 rtc::IPAddress server_addr;
57 56
58 int64 rtt() { return received_time_ms - sent_time_ms; } 57 int64 rtt() { return received_time_ms - sent_time_ms; }
59 void ProcessResponse(rtc::ByteBuffer* message, 58 void ProcessResponse(const char* buf, size_t buf_len);
60 int buf_len,
61 const rtc::IPAddress& local_addr);
62 }; 59 };
63 60
64 // StunProber provides |server_ips| for Requester to probe. For shared 61 // StunProber provides |server_ips| for Requester to probe. For shared
65 // socket mode, it'll be all the resolved IP addresses. For non-shared mode, 62 // socket mode, it'll be all the resolved IP addresses. For non-shared mode,
66 // it'll just be a single address. 63 // it'll just be a single address.
67 Requester(StunProber* prober, 64 Requester(StunProber* prober,
68 ServerSocketInterface* socket, 65 rtc::AsyncPacketSocket* socket,
69 const std::vector<rtc::SocketAddress>& server_ips); 66 const std::vector<rtc::SocketAddress>& server_ips);
70 virtual ~Requester(); 67 virtual ~Requester();
71 68
72 // There is no callback for SendStunRequest as the underneath socket send is 69 // There is no callback for SendStunRequest as the underneath socket send is
73 // expected to be completed immediately. Otherwise, it'll skip this request 70 // expected to be completed immediately. Otherwise, it'll skip this request
74 // and move to the next one. 71 // and move to the next one.
75 void SendStunRequest(); 72 void SendStunRequest();
76 73
77 void ReadStunResponse(); 74 void OnStunResponseReceived(rtc::AsyncPacketSocket* socket,
78 75 const char* buf,
79 // |result| is the positive return value from RecvFrom when data is 76 size_t size,
80 // available. 77 const rtc::SocketAddress& addr,
81 void OnStunResponseReceived(int result); 78 const rtc::PacketTime& time);
82 79
83 const std::vector<Request*>& requests() { return requests_; } 80 const std::vector<Request*>& requests() { return requests_; }
84 81
85 // Whether this Requester has completed all requests. 82 // Whether this Requester has completed all requests.
86 bool Done() { 83 bool Done() {
87 return static_cast<size_t>(num_request_sent_) == server_ips_.size(); 84 return static_cast<size_t>(num_request_sent_) == server_ips_.size();
88 } 85 }
89 86
90 private: 87 private:
91 Request* GetRequestByAddress(const rtc::IPAddress& ip); 88 Request* GetRequestByAddress(const rtc::IPAddress& ip);
92 89
93 StunProber* prober_; 90 StunProber* prober_;
94 91
95 // The socket for this session. 92 // The socket for this session.
96 rtc::scoped_ptr<ServerSocketInterface> socket_; 93 rtc::scoped_ptr<rtc::AsyncPacketSocket> socket_;
97 94
98 // Temporary SocketAddress and buffer for RecvFrom. 95 // Temporary SocketAddress and buffer for RecvFrom.
99 rtc::SocketAddress addr_; 96 rtc::SocketAddress addr_;
100 rtc::scoped_ptr<rtc::ByteBuffer> response_packet_; 97 rtc::scoped_ptr<rtc::ByteBuffer> response_packet_;
101 98
102 std::vector<Request*> requests_; 99 std::vector<Request*> requests_;
103 std::vector<rtc::SocketAddress> server_ips_; 100 std::vector<rtc::SocketAddress> server_ips_;
104 int16 num_request_sent_ = 0; 101 int16 num_request_sent_ = 0;
105 int16 num_response_received_ = 0; 102 int16 num_response_received_ = 0;
106 103
107 rtc::ThreadChecker& thread_checker_; 104 rtc::ThreadChecker& thread_checker_;
108 105
109 DISALLOW_COPY_AND_ASSIGN(Requester); 106 DISALLOW_COPY_AND_ASSIGN(Requester);
110 }; 107 };
111 108
112 StunProber::Requester::Requester( 109 StunProber::Requester::Requester(
113 StunProber* prober, 110 StunProber* prober,
114 ServerSocketInterface* socket, 111 rtc::AsyncPacketSocket* socket,
115 const std::vector<rtc::SocketAddress>& server_ips) 112 const std::vector<rtc::SocketAddress>& server_ips)
116 : prober_(prober), 113 : prober_(prober),
117 socket_(socket), 114 socket_(socket),
118 response_packet_(new rtc::ByteBuffer(nullptr, kMaxUdpBufferSize)), 115 response_packet_(new rtc::ByteBuffer(nullptr, kMaxUdpBufferSize)),
119 server_ips_(server_ips), 116 server_ips_(server_ips),
120 thread_checker_(prober->thread_checker_) { 117 thread_checker_(prober->thread_checker_) {
118 socket_->SignalReadPacket.connect(
119 this, &StunProber::Requester::OnStunResponseReceived);
121 } 120 }
122 121
123 StunProber::Requester::~Requester() { 122 StunProber::Requester::~Requester() {
124 if (socket_) { 123 if (socket_) {
125 socket_->Close(); 124 socket_->Close();
126 } 125 }
127 for (auto req : requests_) { 126 for (auto req : requests_) {
128 if (req) { 127 if (req) {
129 delete req; 128 delete req;
130 } 129 }
131 } 130 }
132 } 131 }
133 132
134 void StunProber::Requester::SendStunRequest() { 133 void StunProber::Requester::SendStunRequest() {
135 DCHECK(thread_checker_.CalledOnValidThread()); 134 DCHECK(thread_checker_.CalledOnValidThread());
136 requests_.push_back(new Request()); 135 requests_.push_back(new Request());
137 Request& request = *(requests_.back()); 136 Request& request = *(requests_.back());
138 cricket::StunMessage message; 137 cricket::StunMessage message;
139 138
140 // Random transaction ID, STUN_BINDING_REQUEST 139 // Random transaction ID, STUN_BINDING_REQUEST
141 message.SetTransactionID( 140 message.SetTransactionID(
142 rtc::CreateRandomString(cricket::kStunTransactionIdLength)); 141 rtc::CreateRandomString(cricket::kStunTransactionIdLength));
143 message.SetType(cricket::STUN_BINDING_REQUEST); 142 message.SetType(cricket::STUN_BINDING_REQUEST);
144 143
145 rtc::scoped_ptr<rtc::ByteBuffer> request_packet( 144 rtc::scoped_ptr<rtc::ByteBuffer> request_packet(
146 new rtc::ByteBuffer(nullptr, kMaxUdpBufferSize)); 145 new rtc::ByteBuffer(nullptr, kMaxUdpBufferSize));
147 if (!message.Write(request_packet.get())) { 146 if (!message.Write(request_packet.get())) {
148 prober_->End(WRITE_FAILED, 0); 147 prober_->End(WRITE_FAILED);
149 return; 148 return;
150 } 149 }
151 150
152 auto addr = server_ips_[num_request_sent_]; 151 auto addr = server_ips_[num_request_sent_];
153 request.server_addr = addr.ipaddr(); 152 request.server_addr = addr.ipaddr();
154 153
155 // The write must succeed immediately. Otherwise, the calculating of the STUN 154 // The write must succeed immediately. Otherwise, the calculating of the STUN
156 // request timing could become too complicated. Callback is ignored by passing 155 // request timing could become too complicated. Callback is ignored by passing
157 // empty AsyncCallback. 156 // empty AsyncCallback.
158 int rv = socket_->SendTo(addr, const_cast<char*>(request_packet->Data()), 157 rtc::PacketOptions options;
159 request_packet->Length(), AsyncCallback()); 158 int rv = socket_->SendTo(const_cast<char*>(request_packet->Data()),
159 request_packet->Length(), addr, options);
160 if (rv < 0) { 160 if (rv < 0) {
161 prober_->End(WRITE_FAILED, rv); 161 prober_->End(WRITE_FAILED);
162 return; 162 return;
163 } 163 }
164 164
165 request.sent_time_ms = rtc::Time(); 165 request.sent_time_ms = rtc::Time();
166 166
167 // Post a read waiting for response. For share mode, the subsequent read will
168 // be posted inside OnStunResponseReceived.
169 if (num_request_sent_ == 0) {
170 ReadStunResponse();
171 }
172
173 num_request_sent_++; 167 num_request_sent_++;
174 DCHECK(static_cast<size_t>(num_request_sent_) <= server_ips_.size()); 168 DCHECK(static_cast<size_t>(num_request_sent_) <= server_ips_.size());
175 } 169 }
176 170
177 void StunProber::Requester::ReadStunResponse() { 171 void StunProber::Requester::Request::ProcessResponse(const char* buf,
178 DCHECK(thread_checker_.CalledOnValidThread()); 172 size_t buf_len) {
179 if (!socket_) {
180 return;
181 }
182
183 int rv = socket_->RecvFrom(
184 response_packet_->ReserveWriteBuffer(kMaxUdpBufferSize),
185 kMaxUdpBufferSize, &addr_,
186 [this](int result) { this->OnStunResponseReceived(result); });
187 if (rv != SocketInterface::IO_PENDING) {
188 OnStunResponseReceived(rv);
189 }
190 }
191
192 void StunProber::Requester::Request::ProcessResponse(
193 rtc::ByteBuffer* message,
194 int buf_len,
195 const rtc::IPAddress& local_addr) {
196 int64 now = rtc::Time(); 173 int64 now = rtc::Time();
197 174 rtc::ByteBuffer message(buf, buf_len);
198 cricket::StunMessage stun_response; 175 cricket::StunMessage stun_response;
199 if (!stun_response.Read(message)) { 176 if (!stun_response.Read(&message)) {
200 // Invalid or incomplete STUN packet. 177 // Invalid or incomplete STUN packet.
201 received_time_ms = 0; 178 received_time_ms = 0;
202 return; 179 return;
203 } 180 }
204 181
205 // Get external address of the socket. 182 // Get external address of the socket.
206 const cricket::StunAddressAttribute* addr_attr = 183 const cricket::StunAddressAttribute* addr_attr =
207 stun_response.GetAddress(cricket::STUN_ATTR_MAPPED_ADDRESS); 184 stun_response.GetAddress(cricket::STUN_ATTR_MAPPED_ADDRESS);
208 if (addr_attr == nullptr) { 185 if (addr_attr == nullptr) {
209 // Addresses not available to detect whether or not behind a NAT. 186 // Addresses not available to detect whether or not behind a NAT.
210 return; 187 return;
211 } 188 }
212 189
213 if (addr_attr->family() != cricket::STUN_ADDRESS_IPV4 && 190 if (addr_attr->family() != cricket::STUN_ADDRESS_IPV4 &&
214 addr_attr->family() != cricket::STUN_ADDRESS_IPV6) { 191 addr_attr->family() != cricket::STUN_ADDRESS_IPV6) {
215 return; 192 return;
216 } 193 }
217 194
218 received_time_ms = now; 195 received_time_ms = now;
219 196
220 srflx_addr = addr_attr->GetAddress(); 197 srflx_addr = addr_attr->GetAddress();
221
222 // Calculate behind_nat.
223 behind_nat = (srflx_addr.ipaddr() != local_addr);
224 } 198 }
225 199
226 void StunProber::Requester::OnStunResponseReceived(int result) { 200 void StunProber::Requester::OnStunResponseReceived(
201 rtc::AsyncPacketSocket* socket,
202 const char* buf,
203 size_t size,
204 const rtc::SocketAddress& addr,
205 const rtc::PacketTime& time) {
227 DCHECK(thread_checker_.CalledOnValidThread()); 206 DCHECK(thread_checker_.CalledOnValidThread());
228 DCHECK(socket_); 207 DCHECK(socket_);
229 208 Request* request = GetRequestByAddress(addr.ipaddr());
230 if (result < 0) {
231 // Something is wrong, finish the test.
232 prober_->End(READ_FAILED, result);
233 return;
234 }
235
236 Request* request = GetRequestByAddress(addr_.ipaddr());
237 if (!request) { 209 if (!request) {
238 // Something is wrong, finish the test. 210 // Something is wrong, finish the test.
239 prober_->End(GENERIC_FAILURE, result); 211 prober_->End(GENERIC_FAILURE);
240 return; 212 return;
241 } 213 }
242 214
243 num_response_received_++; 215 num_response_received_++;
244 216 request->ProcessResponse(buf, size);
245 // Resize will set the end_ to indicate that there are data available in this
246 // ByteBuffer.
247 response_packet_->Resize(result);
248 request->ProcessResponse(response_packet_.get(), result,
249 prober_->local_addr_);
250
251 if (static_cast<size_t>(num_response_received_) < server_ips_.size()) {
252 // Post another read response.
253 ReadStunResponse();
254 }
255 } 217 }
256 218
257 StunProber::Requester::Request* StunProber::Requester::GetRequestByAddress( 219 StunProber::Requester::Request* StunProber::Requester::GetRequestByAddress(
258 const rtc::IPAddress& ipaddr) { 220 const rtc::IPAddress& ipaddr) {
259 DCHECK(thread_checker_.CalledOnValidThread()); 221 DCHECK(thread_checker_.CalledOnValidThread());
260 for (auto request : requests_) { 222 for (auto request : requests_) {
261 if (request->server_addr == ipaddr) { 223 if (request->server_addr == ipaddr) {
262 return request; 224 return request;
263 } 225 }
264 } 226 }
265 227
266 return nullptr; 228 return nullptr;
267 } 229 }
268 230
269 StunProber::StunProber(HostNameResolverInterface* host_name_resolver, 231 StunProber::StunProber(rtc::PacketSocketFactory* socket_factory,
270 SocketFactoryInterface* socket_factory, 232 rtc::Thread* thread,
271 TaskRunnerInterface* task_runner) 233 const rtc::NetworkManager::NetworkList& networks)
272 : interval_ms_(0), 234 : interval_ms_(0),
273 socket_factory_(socket_factory), 235 socket_factory_(socket_factory),
274 resolver_(host_name_resolver), 236 thread_(thread),
275 task_runner_(task_runner) { 237 networks_(networks) {
276 } 238 }
277 239
278 StunProber::~StunProber() { 240 StunProber::~StunProber() {
279 for (auto req : requesters_) { 241 for (auto req : requesters_) {
280 if (req) { 242 if (req) {
281 delete req; 243 delete req;
282 } 244 }
283 } 245 }
246 for (auto s : sockets_) {
247 if (s) {
248 delete s;
249 }
250 }
284 } 251 }
285 252
286 bool StunProber::Start(const std::vector<rtc::SocketAddress>& servers, 253 bool StunProber::Start(const std::vector<rtc::SocketAddress>& servers,
287 bool shared_socket_mode, 254 bool shared_socket_mode,
288 int interval_ms, 255 int interval_ms,
289 int num_request_per_ip, 256 int num_request_per_ip,
290 int timeout_ms, 257 int timeout_ms,
291 const AsyncCallback callback) { 258 const AsyncCallback callback) {
292 DCHECK(thread_checker_.CalledOnValidThread()); 259 DCHECK(thread_checker_.CalledOnValidThread());
293 interval_ms_ = interval_ms; 260 interval_ms_ = interval_ms;
294 shared_socket_mode_ = shared_socket_mode; 261 shared_socket_mode_ = shared_socket_mode;
295 262
296 requests_per_ip_ = num_request_per_ip; 263 requests_per_ip_ = num_request_per_ip;
297 if (requests_per_ip_ == 0 || servers.size() == 0) { 264 if (requests_per_ip_ == 0 || servers.size() == 0) {
298 return false; 265 return false;
299 } 266 }
300 267
301 timeout_ms_ = timeout_ms; 268 timeout_ms_ = timeout_ms;
302 servers_ = servers; 269 servers_ = servers;
303 finished_callback_ = callback; 270 finished_callback_ = callback;
304 resolver_->Resolve(servers_[0], &resolved_ips_, 271 return ResolveServerName(servers_.back());
305 [this](int result) { this->OnServerResolved(0, result); }); 272 }
273
274 bool StunProber::ResolveServerName(const rtc::SocketAddress& addr) {
275 rtc::AsyncResolverInterface* resolver =
276 socket_factory_->CreateAsyncResolver();
277 if (!resolver) {
278 return false;
279 }
280 resolver->SignalDone.connect(this, &StunProber::OnServerResolved);
281 resolver->Start(addr);
306 return true; 282 return true;
307 } 283 }
308 284
309 void StunProber::OnServerResolved(int index, int result) { 285 void StunProber::OnSocketReady(rtc::AsyncPacketSocket* socket,
286 const rtc::SocketAddress& addr) {
287 total_ready_sockets_++;
288 if (total_ready_sockets_ == total_socket_required()) {
289 MaybeScheduleStunRequests();
290 }
291 }
292
293 void StunProber::OnServerResolved(rtc::AsyncResolverInterface* resolver) {
310 DCHECK(thread_checker_.CalledOnValidThread()); 294 DCHECK(thread_checker_.CalledOnValidThread());
311 295
312 if (result == 0) { 296 if (resolver->GetError() == 0) {
313 all_servers_ips_.insert(all_servers_ips_.end(), resolved_ips_.begin(), 297 rtc::SocketAddress addr(resolver->address().ipaddr(),
314 resolved_ips_.end()); 298 resolver->address().port());
315 resolved_ips_.clear(); 299 all_servers_addrs_.push_back(addr);
316 } 300 }
317 301
318 index++; 302 // Deletion of AsyncResolverInterface can't be done in OnResolveResult which
303 // handles SignalDone.
304 invoker_.AsyncInvoke<void>(
305 thread_,
306 rtc::Bind(&rtc::AsyncResolverInterface::Destroy, resolver, false));
307 servers_.pop_back();
319 308
320 if (static_cast<size_t>(index) < servers_.size()) { 309 if (servers_.size()) {
321 resolver_->Resolve( 310 if (!ResolveServerName(servers_.back())) {
322 servers_[index], &resolved_ips_, 311 End(RESOLVE_FAILED);
323 [this, index](int result) { this->OnServerResolved(index, result); }); 312 }
324 return; 313 return;
325 } 314 }
326 315
327 if (all_servers_ips_.size() == 0) { 316 if (all_servers_addrs_.size() == 0) {
328 End(RESOLVE_FAILED, result); 317 End(RESOLVE_FAILED);
329 return; 318 return;
330 } 319 }
331 320
332 // Dedupe. 321 // Dedupe.
333 std::set<rtc::SocketAddress> addrs(all_servers_ips_.begin(), 322 std::set<rtc::SocketAddress> addrs(all_servers_addrs_.begin(),
334 all_servers_ips_.end()); 323 all_servers_addrs_.end());
335 all_servers_ips_.assign(addrs.begin(), addrs.end()); 324 all_servers_addrs_.assign(addrs.begin(), addrs.end());
336 325
337 rtc::IPAddress addr; 326 // Prepare all the sockets beforehand. All of them will bind to "any" address.
338 if (GetLocalAddress(&addr) != 0) { 327 while (sockets_.size() < total_socket_required()) {
339 End(GENERIC_FAILURE, result); 328 rtc::scoped_ptr<rtc::AsyncPacketSocket> socket(
340 return; 329 socket_factory_->CreateUdpSocket(rtc::SocketAddress(INADDR_ANY, 0), 0,
330 0));
331 if (!socket) {
332 End(GENERIC_FAILURE);
333 return;
334 }
335 // Chrome and WebRTC behave differently in terms of the state of a socket
336 // once returned from PacketSocketFactory::CreateUdpSocket.
337 if (socket->GetState() == rtc::AsyncPacketSocket::STATE_BINDING) {
338 socket->SignalAddressReady.connect(this, &StunProber::OnSocketReady);
339 } else {
340 OnSocketReady(socket.get(), rtc::SocketAddress(INADDR_ANY, 0));
341 }
342 sockets_.push_back(socket.release());
341 } 343 }
342
343 socket_factory_->Prepare(GetTotalClientSockets(), GetTotalServerSockets(),
344 [this](int result) {
345 if (result == 0) {
346 this->MaybeScheduleStunRequests();
347 }
348 });
349 }
350
351 int StunProber::GetLocalAddress(rtc::IPAddress* addr) {
352 DCHECK(thread_checker_.CalledOnValidThread());
353 if (local_addr_.family() == AF_UNSPEC) {
354 rtc::SocketAddress sock_addr;
355 rtc::scoped_ptr<ClientSocketInterface> socket(
356 socket_factory_->CreateClientSocket());
357 int rv = socket->Connect(all_servers_ips_[0]);
358 if (rv != SUCCESS) {
359 End(GENERIC_FAILURE, rv);
360 return rv;
361 }
362 rv = socket->GetLocalAddress(&sock_addr);
363 if (rv != SUCCESS) {
364 End(GENERIC_FAILURE, rv);
365 return rv;
366 }
367 local_addr_ = sock_addr.ipaddr();
368 socket->Close();
369 }
370 *addr = local_addr_;
371 return 0;
372 } 344 }
373 345
374 StunProber::Requester* StunProber::CreateRequester() { 346 StunProber::Requester* StunProber::CreateRequester() {
375 DCHECK(thread_checker_.CalledOnValidThread()); 347 DCHECK(thread_checker_.CalledOnValidThread());
376 rtc::scoped_ptr<ServerSocketInterface> socket( 348 if (!sockets_.size()) {
377 socket_factory_->CreateServerSocket(kMaxUdpBufferSize,
378 kMaxUdpBufferSize));
379 if (!socket) {
380 return nullptr; 349 return nullptr;
381 } 350 }
351 StunProber::Requester* requester;
382 if (shared_socket_mode_) { 352 if (shared_socket_mode_) {
383 return new Requester(this, socket.release(), all_servers_ips_); 353 requester = new Requester(this, sockets_.back(), all_servers_addrs_);
384 } else { 354 } else {
385 std::vector<rtc::SocketAddress> server_ip; 355 std::vector<rtc::SocketAddress> server_ip;
386 server_ip.push_back( 356 server_ip.push_back(
387 all_servers_ips_[(num_request_sent_ % all_servers_ips_.size())]); 357 all_servers_addrs_[(num_request_sent_ % all_servers_addrs_.size())]);
388 return new Requester(this, socket.release(), server_ip); 358 requester = new Requester(this, sockets_.back(), server_ip);
389 } 359 }
360
361 sockets_.pop_back();
362 return requester;
390 } 363 }
391 364
392 bool StunProber::SendNextRequest() { 365 bool StunProber::SendNextRequest() {
393 if (!current_requester_ || current_requester_->Done()) { 366 if (!current_requester_ || current_requester_->Done()) {
394 current_requester_ = CreateRequester(); 367 current_requester_ = CreateRequester();
395 requesters_.push_back(current_requester_); 368 requesters_.push_back(current_requester_);
396 } 369 }
397 if (!current_requester_) { 370 if (!current_requester_) {
398 return false; 371 return false;
399 } 372 }
400 current_requester_->SendStunRequest(); 373 current_requester_->SendStunRequest();
401 num_request_sent_++; 374 num_request_sent_++;
402 return true; 375 return true;
403 } 376 }
404 377
405 void StunProber::MaybeScheduleStunRequests() { 378 void StunProber::MaybeScheduleStunRequests() {
406 DCHECK(thread_checker_.CalledOnValidThread()); 379 DCHECK(thread_checker_.CalledOnValidThread());
407 uint32 now = rtc::Time(); 380 uint32 now = rtc::Time();
408 381
409 if (Done()) { 382 if (Done()) {
410 task_runner_->PostTask(rtc::Bind(&StunProber::End, this, SUCCESS, 0), 383 invoker_.AsyncInvokeDelayed<void>(
411 timeout_ms_); 384 thread_, rtc::Bind(&StunProber::End, this, SUCCESS), timeout_ms_);
412 return; 385 return;
413 } 386 }
414 if (now >= next_request_time_ms_) { 387 if ((now + (thread_wake_up_interval_ms / 2)) >= next_request_time_ms_) {
415 if (!SendNextRequest()) { 388 if (!SendNextRequest()) {
416 End(GENERIC_FAILURE, 0); 389 End(GENERIC_FAILURE);
417 return; 390 return;
418 } 391 }
419 next_request_time_ms_ = now + interval_ms_; 392 next_request_time_ms_ = now + interval_ms_;
420 } 393 }
421 task_runner_->PostTask( 394 invoker_.AsyncInvokeDelayed<void>(
422 rtc::Bind(&StunProber::MaybeScheduleStunRequests, this), 1 /* ms */); 395 thread_, rtc::Bind(&StunProber::MaybeScheduleStunRequests, this),
396 thread_wake_up_interval_ms /* ms */);
423 } 397 }
424 398
425 bool StunProber::GetStats(StunProber::Stats* prob_stats) const { 399 bool StunProber::GetStats(StunProber::Stats* prob_stats) const {
426 // No need to be on the same thread. 400 // No need to be on the same thread.
427 if (!prob_stats) { 401 if (!prob_stats) {
428 return false; 402 return false;
429 } 403 }
430 404
431 StunProber::Stats stats; 405 StunProber::Stats stats;
432 406
(...skipping 24 matching lines...) Expand all
457 } 431 }
458 last_sent_time = request->sent_time_ms; 432 last_sent_time = request->sent_time_ms;
459 433
460 if (request->received_time_ms < request->sent_time_ms) { 434 if (request->received_time_ms < request->sent_time_ms) {
461 continue; 435 continue;
462 } 436 }
463 437
464 IncrementCounterByAddress(&num_response_per_server, request->server_addr); 438 IncrementCounterByAddress(&num_response_per_server, request->server_addr);
465 IncrementCounterByAddress(&num_response_per_srflx_addr, 439 IncrementCounterByAddress(&num_response_per_srflx_addr,
466 request->srflx_addr); 440 request->srflx_addr);
467
468 rtt_sum += request->rtt(); 441 rtt_sum += request->rtt();
469 if (nat_type == NATTYPE_INVALID) {
470 nat_type = request->behind_nat ? NATTYPE_UNKNOWN : NATTYPE_NONE;
471 } else if (behind_nat(nat_type) != request->behind_nat) {
472 // Detect the inconsistency in NAT presence.
473 return false;
474 }
475 stats.srflx_addrs.insert(request->srflx_addr.ToString()); 442 stats.srflx_addrs.insert(request->srflx_addr.ToString());
476 srflx_ips.insert(request->srflx_addr.ipaddr()); 443 srflx_ips.insert(request->srflx_addr.ipaddr());
477 } 444 }
478 445
479 // If we're using shared mode and seeing >1 srflx addresses for a single 446 // If we're using shared mode and seeing >1 srflx addresses for a single
480 // requester, it's symmetric NAT. 447 // requester, it's symmetric NAT.
481 if (shared_socket_mode_ && num_response_per_srflx_addr.size() > 1) { 448 if (shared_socket_mode_ && num_response_per_srflx_addr.size() > 1) {
482 nat_type = NATTYPE_SYMMETRIC; 449 nat_type = NATTYPE_SYMMETRIC;
483 } 450 }
484 } 451 }
(...skipping 13 matching lines...) Expand all
498 num_server_ip_with_response++; 465 num_server_ip_with_response++;
499 num_received += kv.second; 466 num_received += kv.second;
500 num_sent += num_request_per_server[kv.first]; 467 num_sent += num_request_per_server[kv.first];
501 } 468 }
502 469
503 // Not receiving any response, the trial is inconclusive. 470 // Not receiving any response, the trial is inconclusive.
504 if (!num_received) { 471 if (!num_received) {
505 return false; 472 return false;
506 } 473 }
507 474
508 stats.nat_type = nat_type;
509
510 // Shared mode is only true if we use the shared socket and there are more 475 // Shared mode is only true if we use the shared socket and there are more
511 // than 1 responding servers. 476 // than 1 responding servers.
512 stats.shared_socket_mode = 477 stats.shared_socket_mode =
513 shared_socket_mode_ && (num_server_ip_with_response > 1); 478 shared_socket_mode_ && (num_server_ip_with_response > 1);
514 479
515 if (stats.shared_socket_mode && nat_type == NATTYPE_UNKNOWN) { 480 if (stats.shared_socket_mode && nat_type == NATTYPE_INVALID) {
516 stats.nat_type = NATTYPE_NON_SYMMETRIC; 481 nat_type = NATTYPE_NON_SYMMETRIC;
517 } 482 }
518 483
519 stats.host_ip = local_addr_.ToString(); 484 // If we could find a local IP matching srflx, we're not behind a NAT.
485 rtc::SocketAddress srflx_addr;
486 if (!srflx_addr.FromString(*(stats.srflx_addrs.begin()))) {
487 return false;
488 }
489 for (const auto& net : networks_) {
490 if (srflx_addr.ipaddr() == net->GetBestIP()) {
491 nat_type = stunprober::NATTYPE_NONE;
492 stats.host_ip = net->GetBestIP().ToString();
493 break;
494 }
495 }
496
497 // Finally, we know we're behind a NAT but can't determine which type it is.
498 if (nat_type == NATTYPE_INVALID) {
499 nat_type = NATTYPE_UNKNOWN;
500 }
501
502 stats.nat_type = nat_type;
520 stats.num_request_sent = num_sent; 503 stats.num_request_sent = num_sent;
521 stats.num_response_received = num_received; 504 stats.num_response_received = num_received;
522 stats.target_request_interval_ns = interval_ms_ * 1000; 505 stats.target_request_interval_ns = interval_ms_ * 1000;
523 506
524 if (num_sent) { 507 if (num_sent) {
525 stats.success_percent = static_cast<int>(100 * num_received / num_sent); 508 stats.success_percent = static_cast<int>(100 * num_received / num_sent);
526 } 509 }
527 510
528 if (num_sent > 1) { 511 if (num_sent > 1) {
529 stats.actual_request_interval_ns = 512 stats.actual_request_interval_ns =
530 (1000 * (last_sent_time - first_sent_time)) / (num_sent - 1); 513 (1000 * (last_sent_time - first_sent_time)) / (num_sent - 1);
531 } 514 }
532 515
533 if (num_received) { 516 if (num_received) {
534 stats.average_rtt_ms = static_cast<int>((rtt_sum / num_received)); 517 stats.average_rtt_ms = static_cast<int>((rtt_sum / num_received));
535 } 518 }
536 519
537 *prob_stats = stats; 520 *prob_stats = stats;
538 return true; 521 return true;
539 } 522 }
540 523
541 void StunProber::End(StunProber::Status status, int result) { 524 void StunProber::End(StunProber::Status status) {
542 DCHECK(thread_checker_.CalledOnValidThread()); 525 DCHECK(thread_checker_.CalledOnValidThread());
543 if (!finished_callback_.empty()) { 526 if (!finished_callback_.empty()) {
544 AsyncCallback callback = finished_callback_; 527 AsyncCallback callback = finished_callback_;
545 finished_callback_ = AsyncCallback(); 528 finished_callback_ = AsyncCallback();
546 529
547 // Callback at the last since the prober might be deleted in the callback. 530 // Callback at the last since the prober might be deleted in the callback.
548 callback(status); 531 callback(this, status);
549 } 532 }
550 } 533 }
551 534
552 } // namespace stunprober 535 } // namespace stunprober
OLDNEW
« no previous file with comments | « webrtc/p2p/stunprober/stunprober.h ('k') | webrtc/p2p/stunprober/stunprober_dependencies.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698