| 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 |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |