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 #ifndef WEBRTC_P2P_STUNPROBER_STUNPROBER_H_ | 11 #ifndef WEBRTC_P2P_STUNPROBER_STUNPROBER_H_ |
12 #define WEBRTC_P2P_STUNPROBER_STUNPROBER_H_ | 12 #define WEBRTC_P2P_STUNPROBER_STUNPROBER_H_ |
13 | 13 |
14 #include <set> | 14 #include <set> |
15 #include <string> | 15 #include <string> |
16 #include <vector> | 16 #include <vector> |
17 | 17 |
| 18 #include "webrtc/base/asyncinvoker.h" |
18 #include "webrtc/base/basictypes.h" | 19 #include "webrtc/base/basictypes.h" |
19 #include "webrtc/base/bytebuffer.h" | 20 #include "webrtc/base/bytebuffer.h" |
20 #include "webrtc/base/callback.h" | 21 #include "webrtc/base/callback.h" |
21 #include "webrtc/base/ipaddress.h" | 22 #include "webrtc/base/ipaddress.h" |
| 23 #include "webrtc/base/network.h" |
22 #include "webrtc/base/scoped_ptr.h" | 24 #include "webrtc/base/scoped_ptr.h" |
23 #include "webrtc/base/socketaddress.h" | 25 #include "webrtc/base/socketaddress.h" |
| 26 #include "webrtc/base/thread.h" |
24 #include "webrtc/base/thread_checker.h" | 27 #include "webrtc/base/thread_checker.h" |
25 #include "webrtc/typedefs.h" | 28 #include "webrtc/typedefs.h" |
26 | 29 |
| 30 namespace rtc { |
| 31 class AsyncPacketSocket; |
| 32 class PacketSocketFactory; |
| 33 class Thread; |
| 34 class NetworkManager; |
| 35 } // namespace rtc |
| 36 |
27 namespace stunprober { | 37 namespace stunprober { |
28 | 38 |
| 39 class StunProber; |
| 40 |
29 static const int kMaxUdpBufferSize = 1200; | 41 static const int kMaxUdpBufferSize = 1200; |
30 | 42 |
31 typedef rtc::Callback1<void, int> AsyncCallback; | 43 typedef rtc::Callback2<void, StunProber*, int> AsyncCallback; |
32 | 44 |
33 enum NatType { | 45 enum NatType { |
34 NATTYPE_INVALID, | 46 NATTYPE_INVALID, |
35 NATTYPE_NONE, // Not behind a NAT. | 47 NATTYPE_NONE, // Not behind a NAT. |
36 NATTYPE_UNKNOWN, // Behind a NAT but type can't be determine. | 48 NATTYPE_UNKNOWN, // Behind a NAT but type can't be determine. |
37 NATTYPE_SYMMETRIC, // Behind a symmetric NAT. | 49 NATTYPE_SYMMETRIC, // Behind a symmetric NAT. |
38 NATTYPE_NON_SYMMETRIC // Behind a non-symmetric NAT. | 50 NATTYPE_NON_SYMMETRIC // Behind a non-symmetric NAT. |
39 }; | 51 }; |
40 | 52 |
41 class HostNameResolverInterface { | 53 class StunProber : public sigslot::has_slots<> { |
42 public: | |
43 HostNameResolverInterface() {} | |
44 | |
45 // Resolve should allow re-entry as |callback| could trigger another | |
46 // Resolve(). | |
47 virtual void Resolve(const rtc::SocketAddress& addr, | |
48 std::vector<rtc::SocketAddress>* addresses, | |
49 AsyncCallback callback) = 0; | |
50 | |
51 virtual ~HostNameResolverInterface() {} | |
52 | |
53 private: | |
54 DISALLOW_COPY_AND_ASSIGN(HostNameResolverInterface); | |
55 }; | |
56 | |
57 // Chrome has client and server socket. Client socket supports Connect but not | |
58 // Bind. Server is opposite. | |
59 class SocketInterface { | |
60 public: | |
61 enum { | |
62 IO_PENDING = -1, | |
63 FAILED = -2, | |
64 }; | |
65 SocketInterface() {} | |
66 virtual void Close() = 0; | |
67 virtual ~SocketInterface() {} | |
68 | |
69 private: | |
70 DISALLOW_COPY_AND_ASSIGN(SocketInterface); | |
71 }; | |
72 | |
73 class ClientSocketInterface : public SocketInterface { | |
74 public: | |
75 ClientSocketInterface() {} | |
76 // Even though we have SendTo and RecvFrom, if Connect is not called first, | |
77 // getsockname will only return 0.0.0.0. | |
78 virtual int Connect(const rtc::SocketAddress& addr) = 0; | |
79 | |
80 virtual int GetLocalAddress(rtc::SocketAddress* local_address) = 0; | |
81 | |
82 private: | |
83 DISALLOW_COPY_AND_ASSIGN(ClientSocketInterface); | |
84 }; | |
85 | |
86 class ServerSocketInterface : public SocketInterface { | |
87 public: | |
88 ServerSocketInterface() {} | |
89 | |
90 virtual int SendTo(const rtc::SocketAddress& addr, | |
91 char* buf, | |
92 size_t buf_len, | |
93 AsyncCallback callback) = 0; | |
94 | |
95 // If the returned value is positive, it means that buf has been | |
96 // sent. Otherwise, it should return IO_PENDING. Callback will be invoked | |
97 // after the data is successfully read into buf. | |
98 virtual int RecvFrom(char* buf, | |
99 size_t buf_len, | |
100 rtc::SocketAddress* addr, | |
101 AsyncCallback callback) = 0; | |
102 | |
103 private: | |
104 DISALLOW_COPY_AND_ASSIGN(ServerSocketInterface); | |
105 }; | |
106 | |
107 class SocketFactoryInterface { | |
108 public: | |
109 SocketFactoryInterface() {} | |
110 // To provide a chance to prepare the sockets that we need. This is | |
111 // implemented for chrome renderer process as the socket needs to be ready to | |
112 // use in browser process. | |
113 virtual void Prepare(size_t total_client_socket, | |
114 size_t total_server_socket, | |
115 AsyncCallback callback) { | |
116 callback(0); | |
117 } | |
118 virtual ClientSocketInterface* CreateClientSocket() = 0; | |
119 virtual ServerSocketInterface* CreateServerSocket( | |
120 size_t send_buffer_size, | |
121 size_t receive_buffer_size) = 0; | |
122 virtual ~SocketFactoryInterface() {} | |
123 | |
124 private: | |
125 DISALLOW_COPY_AND_ASSIGN(SocketFactoryInterface); | |
126 }; | |
127 | |
128 class TaskRunnerInterface { | |
129 public: | |
130 TaskRunnerInterface() {} | |
131 virtual void PostTask(rtc::Callback0<void>, uint32_t delay_ms) = 0; | |
132 virtual ~TaskRunnerInterface() {} | |
133 | |
134 private: | |
135 DISALLOW_COPY_AND_ASSIGN(TaskRunnerInterface); | |
136 }; | |
137 | |
138 class StunProber { | |
139 public: | 54 public: |
140 enum Status { // Used in UMA_HISTOGRAM_ENUMERATION. | 55 enum Status { // Used in UMA_HISTOGRAM_ENUMERATION. |
141 SUCCESS, // Successfully received bytes from the server. | 56 SUCCESS, // Successfully received bytes from the server. |
142 GENERIC_FAILURE, // Generic failure. | 57 GENERIC_FAILURE, // Generic failure. |
143 RESOLVE_FAILED, // Host resolution failed. | 58 RESOLVE_FAILED, // Host resolution failed. |
144 WRITE_FAILED, // Sending a message to the server failed. | 59 WRITE_FAILED, // Sending a message to the server failed. |
145 READ_FAILED, // Reading the reply from the server failed. | 60 READ_FAILED, // Reading the reply from the server failed. |
146 }; | 61 }; |
147 | 62 |
148 struct Stats { | 63 struct Stats { |
(...skipping 11 matching lines...) Expand all Loading... |
160 // mode. Share mode only makes sense when we have multiple IP resolved and | 75 // mode. Share mode only makes sense when we have multiple IP resolved and |
161 // successfully probed. | 76 // successfully probed. |
162 bool shared_socket_mode = false; | 77 bool shared_socket_mode = false; |
163 | 78 |
164 std::string host_ip; | 79 std::string host_ip; |
165 | 80 |
166 // If the srflx_addrs has more than 1 element, the NAT is symmetric. | 81 // If the srflx_addrs has more than 1 element, the NAT is symmetric. |
167 std::set<std::string> srflx_addrs; | 82 std::set<std::string> srflx_addrs; |
168 }; | 83 }; |
169 | 84 |
170 // StunProber is not thread safe. It's task_runner's responsibility to ensure | 85 StunProber(rtc::PacketSocketFactory* socket_factory, |
171 // all calls happen sequentially. | 86 rtc::Thread* thread, |
172 StunProber(HostNameResolverInterface* host_name_resolver, | 87 const rtc::NetworkManager::NetworkList& networks); |
173 SocketFactoryInterface* socket_factory, | |
174 TaskRunnerInterface* task_runner); | |
175 virtual ~StunProber(); | 88 virtual ~StunProber(); |
176 | 89 |
177 // Begin performing the probe test against the |servers|. If | 90 // Begin performing the probe test against the |servers|. If |
178 // |shared_socket_mode| is false, each request will be done with a new socket. | 91 // |shared_socket_mode| is false, each request will be done with a new socket. |
179 // Otherwise, a unique socket will be used for a single round of requests | 92 // Otherwise, a unique socket will be used for a single round of requests |
180 // against all resolved IPs. No single socket will be used against a given IP | 93 // against all resolved IPs. No single socket will be used against a given IP |
181 // more than once. The interval of requests will be as close to the requested | 94 // more than once. The interval of requests will be as close to the requested |
182 // inter-probe interval |stun_ta_interval_ms| as possible. After sending out | 95 // inter-probe interval |stun_ta_interval_ms| as possible. After sending out |
183 // the last scheduled request, the probe will wait |timeout_ms| for request | 96 // the last scheduled request, the probe will wait |timeout_ms| for request |
184 // responses and then call |finish_callback|. |requests_per_ip| indicates how | 97 // responses and then call |finish_callback|. |requests_per_ip| indicates how |
(...skipping 11 matching lines...) Expand all Loading... |
196 // Method to retrieve the Stats once |finish_callback| is invoked. Returning | 109 // Method to retrieve the Stats once |finish_callback| is invoked. Returning |
197 // false when the result is inconclusive, for example, whether it's behind a | 110 // false when the result is inconclusive, for example, whether it's behind a |
198 // NAT or not. | 111 // NAT or not. |
199 bool GetStats(Stats* stats) const; | 112 bool GetStats(Stats* stats) const; |
200 | 113 |
201 private: | 114 private: |
202 // A requester tracks the requests and responses from a single socket to many | 115 // A requester tracks the requests and responses from a single socket to many |
203 // STUN servers. | 116 // STUN servers. |
204 class Requester; | 117 class Requester; |
205 | 118 |
206 void OnServerResolved(int index, int result); | 119 bool ResolveServerName(const rtc::SocketAddress& addr); |
| 120 void OnServerResolved(rtc::AsyncResolverInterface* resolver); |
| 121 |
| 122 void OnSocketReady(rtc::AsyncPacketSocket* socket, |
| 123 const rtc::SocketAddress& addr); |
207 | 124 |
208 bool Done() { | 125 bool Done() { |
209 return num_request_sent_ >= requests_per_ip_ * all_servers_ips_.size(); | 126 return num_request_sent_ >= requests_per_ip_ * all_servers_addrs_.size(); |
210 } | 127 } |
211 | 128 |
212 int GetTotalClientSockets() { return 1; } | 129 size_t total_socket_required() { |
213 int GetTotalServerSockets() { | 130 return (shared_socket_mode_ ? 1 : all_servers_addrs_.size()) * |
214 return static_cast<int>( | 131 requests_per_ip_; |
215 (shared_socket_mode_ ? 1 : all_servers_ips_.size()) * requests_per_ip_); | |
216 } | 132 } |
217 | 133 |
218 bool SendNextRequest(); | 134 bool SendNextRequest(); |
219 | 135 |
220 // Will be invoked in 1ms intervals and schedule the next request from the | 136 // Will be invoked in 1ms intervals and schedule the next request from the |
221 // |current_requester_| if the time has passed for another request. | 137 // |current_requester_| if the time has passed for another request. |
222 void MaybeScheduleStunRequests(); | 138 void MaybeScheduleStunRequests(); |
223 | 139 |
224 // End the probe with the given |status|. Invokes |fininsh_callback|, which | 140 // End the probe with the given |status|. Invokes |fininsh_callback|, which |
225 // may destroy the class. | 141 // may destroy the class. |
226 void End(StunProber::Status status, int result); | 142 void End(StunProber::Status status); |
227 | |
228 // Create a socket, connect to the first resolved server, and return the | |
229 // result of getsockname(). All Requesters will bind to this name. We do this | |
230 // because if a socket is not bound nor connected, getsockname will return | |
231 // 0.0.0.0. We can't connect to a single STUN server IP either as that will | |
232 // fail subsequent requests in shared mode. | |
233 int GetLocalAddress(rtc::IPAddress* addr); | |
234 | 143 |
235 Requester* CreateRequester(); | 144 Requester* CreateRequester(); |
236 | 145 |
237 Requester* current_requester_ = nullptr; | 146 Requester* current_requester_ = nullptr; |
238 | 147 |
239 // The time when the next request should go out. | 148 // The time when the next request should go out. |
240 uint64 next_request_time_ms_ = 0; | 149 uint64 next_request_time_ms_ = 0; |
241 | 150 |
242 // Total requests sent so far. | 151 // Total requests sent so far. |
243 uint32 num_request_sent_ = 0; | 152 uint32 num_request_sent_ = 0; |
244 | 153 |
245 bool shared_socket_mode_ = false; | 154 bool shared_socket_mode_ = false; |
246 | 155 |
247 // How many requests should be done against each resolved IP. | 156 // How many requests should be done against each resolved IP. |
248 uint32 requests_per_ip_ = 0; | 157 uint32 requests_per_ip_ = 0; |
249 | 158 |
250 // Milliseconds to pause between each STUN request. | 159 // Milliseconds to pause between each STUN request. |
251 int interval_ms_; | 160 int interval_ms_; |
252 | 161 |
253 // Timeout period after the last request is sent. | 162 // Timeout period after the last request is sent. |
254 int timeout_ms_; | 163 int timeout_ms_; |
255 | 164 |
256 // STUN server name to be resolved. | 165 // STUN server name to be resolved. |
257 std::vector<rtc::SocketAddress> servers_; | 166 std::vector<rtc::SocketAddress> servers_; |
258 | 167 |
259 // The local address that each probing socket will be bound to. | 168 // Weak references. |
260 rtc::IPAddress local_addr_; | 169 rtc::PacketSocketFactory* socket_factory_; |
| 170 rtc::Thread* thread_; |
261 | 171 |
262 // Owned pointers. | 172 // Accumulate all resolved addresses. |
263 rtc::scoped_ptr<SocketFactoryInterface> socket_factory_; | 173 std::vector<rtc::SocketAddress> all_servers_addrs_; |
264 rtc::scoped_ptr<HostNameResolverInterface> resolver_; | |
265 rtc::scoped_ptr<TaskRunnerInterface> task_runner_; | |
266 | |
267 // Addresses filled out by HostNameResolver for a single server. | |
268 std::vector<rtc::SocketAddress> resolved_ips_; | |
269 | |
270 // Accumulate all resolved IPs. | |
271 std::vector<rtc::SocketAddress> all_servers_ips_; | |
272 | 174 |
273 // Caller-supplied callback executed when testing is completed, called by | 175 // Caller-supplied callback executed when testing is completed, called by |
274 // End(). | 176 // End(). |
275 AsyncCallback finished_callback_; | 177 AsyncCallback finished_callback_; |
276 | 178 |
277 // The set of STUN probe sockets and their state. | 179 // The set of STUN probe sockets and their state. |
278 std::vector<Requester*> requesters_; | 180 std::vector<Requester*> requesters_; |
279 | 181 |
280 rtc::ThreadChecker thread_checker_; | 182 rtc::ThreadChecker thread_checker_; |
281 | 183 |
| 184 // Temporary storage for created sockets. |
| 185 std::vector<rtc::AsyncPacketSocket*> sockets_; |
| 186 // This tracks how many of the sockets are ready. |
| 187 size_t total_ready_sockets_ = 0; |
| 188 |
| 189 rtc::AsyncInvoker invoker_; |
| 190 |
| 191 rtc::NetworkManager::NetworkList networks_; |
| 192 |
282 DISALLOW_COPY_AND_ASSIGN(StunProber); | 193 DISALLOW_COPY_AND_ASSIGN(StunProber); |
283 }; | 194 }; |
284 | 195 |
285 } // namespace stunprober | 196 } // namespace stunprober |
286 | 197 |
287 #endif // WEBRTC_P2P_STUNPROBER_STUNPROBER_H_ | 198 #endif // WEBRTC_P2P_STUNPROBER_STUNPROBER_H_ |
OLD | NEW |