1 /* 2 * Copyright 2015 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef WEBRTC_P2P_STUNPROBER_STUNPROBER_H_ 12 #define WEBRTC_P2P_STUNPROBER_STUNPROBER_H_ 13 14 #include <set> 15 #include <string> 16 #include <vector> 17 18 #include "webrtc/base/asyncinvoker.h" 19 #include "webrtc/base/basictypes.h" 20 #include "webrtc/base/bytebuffer.h" 21 #include "webrtc/base/callback.h" 22 #include "webrtc/base/ipaddress.h" 23 #include "webrtc/base/network.h" 24 #include "webrtc/base/scoped_ptr.h" 25 #include "webrtc/base/socketaddress.h" 26 #include "webrtc/base/thread.h" 27 #include "webrtc/base/thread_checker.h" 28 #include "webrtc/typedefs.h" 29 30 namespace rtc { 31 class AsyncPacketSocket; 32 class PacketSocketFactory; 33 class Thread; 34 class NetworkManager; 35 class AsyncResolverInterface; 36 } // namespace rtc 37 38 namespace stunprober { 39 40 class StunProber; 41 42 static const int kMaxUdpBufferSize = 1200; 43 44 typedef rtc::Callback2<void, StunProber*, int> AsyncCallback; 45 46 enum NatType { 47 NATTYPE_INVALID, 48 NATTYPE_NONE, // Not behind a NAT. 49 NATTYPE_UNKNOWN, // Behind a NAT but type can't be determine. 50 NATTYPE_SYMMETRIC, // Behind a symmetric NAT. 51 NATTYPE_NON_SYMMETRIC // Behind a non-symmetric NAT. 52 }; 53 54 class StunProber : public sigslot::has_slots<> { 55 public: 56 enum Status { // Used in UMA_HISTOGRAM_ENUMERATION. 57 SUCCESS, // Successfully received bytes from the server. 58 GENERIC_FAILURE, // Generic failure. 59 RESOLVE_FAILED, // Host resolution failed. 60 WRITE_FAILED, // Sending a message to the server failed. 61 READ_FAILED, // Reading the reply from the server failed. 62 }; 63 64 class Observer { 65 public: 66 virtual ~Observer() = default; 67 virtual void OnPrepared(StunProber* prober, StunProber::Status status) = 0; 68 virtual void OnFinished(StunProber* prober, StunProber::Status status) = 0; 69 }; 70 71 struct Stats { StatsStats72 Stats() {} 73 74 // |raw_num_request_sent| is the total number of requests 75 // sent. |num_request_sent| is the count of requests against a server where 76 // we see at least one response. |num_request_sent| is designed to protect 77 // against DNS resolution failure or the STUN server is not responsive 78 // which could skew the result. 79 int raw_num_request_sent = 0; 80 int num_request_sent = 0; 81 82 int num_response_received = 0; 83 NatType nat_type = NATTYPE_INVALID; 84 int average_rtt_ms = -1; 85 int success_percent = 0; 86 int target_request_interval_ns = 0; 87 int actual_request_interval_ns = 0; 88 89 // Also report whether this trial can't be considered truly as shared 90 // mode. Share mode only makes sense when we have multiple IP resolved and 91 // successfully probed. 92 bool shared_socket_mode = false; 93 94 std::string host_ip; 95 96 // If the srflx_addrs has more than 1 element, the NAT is symmetric. 97 std::set<std::string> srflx_addrs; 98 }; 99 100 StunProber(rtc::PacketSocketFactory* socket_factory, 101 rtc::Thread* thread, 102 const rtc::NetworkManager::NetworkList& networks); 103 virtual ~StunProber(); 104 105 // Begin performing the probe test against the |servers|. If 106 // |shared_socket_mode| is false, each request will be done with a new socket. 107 // Otherwise, a unique socket will be used for a single round of requests 108 // against all resolved IPs. No single socket will be used against a given IP 109 // more than once. The interval of requests will be as close to the requested 110 // inter-probe interval |stun_ta_interval_ms| as possible. After sending out 111 // the last scheduled request, the probe will wait |timeout_ms| for request 112 // responses and then call |finish_callback|. |requests_per_ip| indicates how 113 // many requests should be tried for each resolved IP address. In shared mode, 114 // (the number of sockets to be created) equals to |requests_per_ip|. In 115 // non-shared mode, (the number of sockets) equals to requests_per_ip * (the 116 // number of resolved IP addresses). TODO(guoweis): Remove this once 117 // everything moved to Prepare() and Run(). 118 bool Start(const std::vector<rtc::SocketAddress>& servers, 119 bool shared_socket_mode, 120 int stun_ta_interval_ms, 121 int requests_per_ip, 122 int timeout_ms, 123 const AsyncCallback finish_callback); 124 125 // TODO(guoweis): The combination of Prepare() and Run() are equivalent to the 126 // Start() above. Remove Start() once everything is migrated. 127 bool Prepare(const std::vector<rtc::SocketAddress>& servers, 128 bool shared_socket_mode, 129 int stun_ta_interval_ms, 130 int requests_per_ip, 131 int timeout_ms, 132 StunProber::Observer* observer); 133 134 // Start to send out the STUN probes. 135 bool Start(StunProber::Observer* observer); 136 137 // Method to retrieve the Stats once |finish_callback| is invoked. Returning 138 // false when the result is inconclusive, for example, whether it's behind a 139 // NAT or not. 140 bool GetStats(Stats* stats) const; 141 estimated_execution_time()142 int estimated_execution_time() { 143 return static_cast<int>(requests_per_ip_ * all_servers_addrs_.size() * 144 interval_ms_); 145 } 146 147 private: 148 // A requester tracks the requests and responses from a single socket to many 149 // STUN servers. 150 class Requester; 151 152 // TODO(guoweis): Remove this once all dependencies move away from 153 // AsyncCallback. 154 class ObserverAdapter : public Observer { 155 public: set_callback(AsyncCallback callback)156 void set_callback(AsyncCallback callback) { callback_ = callback; } OnPrepared(StunProber * stunprober,Status status)157 void OnPrepared(StunProber* stunprober, Status status) { 158 if (status == SUCCESS) { 159 stunprober->Start(this); 160 } else { 161 callback_(stunprober, status); 162 } 163 } OnFinished(StunProber * stunprober,Status status)164 void OnFinished(StunProber* stunprober, Status status) { 165 callback_(stunprober, status); 166 } 167 168 private: 169 AsyncCallback callback_; 170 }; 171 172 bool ResolveServerName(const rtc::SocketAddress& addr); 173 void OnServerResolved(rtc::AsyncResolverInterface* resolver); 174 175 void OnSocketReady(rtc::AsyncPacketSocket* socket, 176 const rtc::SocketAddress& addr); 177 Done()178 bool Done() { 179 return num_request_sent_ >= requests_per_ip_ * all_servers_addrs_.size(); 180 } 181 total_socket_required()182 size_t total_socket_required() { 183 return (shared_socket_mode_ ? 1 : all_servers_addrs_.size()) * 184 requests_per_ip_; 185 } 186 187 bool should_send_next_request(uint32_t now); 188 int get_wake_up_interval_ms(); 189 190 bool SendNextRequest(); 191 192 // Will be invoked in 1ms intervals and schedule the next request from the 193 // |current_requester_| if the time has passed for another request. 194 void MaybeScheduleStunRequests(); 195 196 void ReportOnPrepared(StunProber::Status status); 197 void ReportOnFinished(StunProber::Status status); 198 199 Requester* CreateRequester(); 200 201 Requester* current_requester_ = nullptr; 202 203 // The time when the next request should go out. 204 uint64_t next_request_time_ms_ = 0; 205 206 // Total requests sent so far. 207 uint32_t num_request_sent_ = 0; 208 209 bool shared_socket_mode_ = false; 210 211 // How many requests should be done against each resolved IP. 212 uint32_t requests_per_ip_ = 0; 213 214 // Milliseconds to pause between each STUN request. 215 int interval_ms_; 216 217 // Timeout period after the last request is sent. 218 int timeout_ms_; 219 220 // STUN server name to be resolved. 221 std::vector<rtc::SocketAddress> servers_; 222 223 // Weak references. 224 rtc::PacketSocketFactory* socket_factory_; 225 rtc::Thread* thread_; 226 227 // Accumulate all resolved addresses. 228 std::vector<rtc::SocketAddress> all_servers_addrs_; 229 230 // The set of STUN probe sockets and their state. 231 std::vector<Requester*> requesters_; 232 233 rtc::ThreadChecker thread_checker_; 234 235 // Temporary storage for created sockets. 236 std::vector<rtc::AsyncPacketSocket*> sockets_; 237 // This tracks how many of the sockets are ready. 238 size_t total_ready_sockets_ = 0; 239 240 rtc::AsyncInvoker invoker_; 241 242 Observer* observer_ = nullptr; 243 // TODO(guoweis): Remove this once all dependencies move away from 244 // AsyncCallback. 245 ObserverAdapter observer_adapter_; 246 247 rtc::NetworkManager::NetworkList networks_; 248 249 RTC_DISALLOW_COPY_AND_ASSIGN(StunProber); 250 }; 251 252 } // namespace stunprober 253 254 #endif // WEBRTC_P2P_STUNPROBER_STUNPROBER_H_ 255