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 P2P_STUNPROBER_STUN_PROBER_H_ 12 #define P2P_STUNPROBER_STUN_PROBER_H_ 13 14 #include <set> 15 #include <string> 16 #include <vector> 17 18 #include "rtc_base/async_invoker.h" 19 #include "rtc_base/byte_buffer.h" 20 #include "rtc_base/callback.h" 21 #include "rtc_base/constructor_magic.h" 22 #include "rtc_base/ip_address.h" 23 #include "rtc_base/network.h" 24 #include "rtc_base/socket_address.h" 25 #include "rtc_base/system/rtc_export.h" 26 #include "rtc_base/thread.h" 27 #include "rtc_base/thread_checker.h" 28 29 namespace rtc { 30 class AsyncPacketSocket; 31 class PacketSocketFactory; 32 class Thread; 33 class NetworkManager; 34 class AsyncResolverInterface; 35 } // namespace rtc 36 37 namespace stunprober { 38 39 class StunProber; 40 41 static const int kMaxUdpBufferSize = 1200; 42 43 typedef rtc::Callback2<void, StunProber*, int> AsyncCallback; 44 45 enum NatType { 46 NATTYPE_INVALID, 47 NATTYPE_NONE, // Not behind a NAT. 48 NATTYPE_UNKNOWN, // Behind a NAT but type can't be determine. 49 NATTYPE_SYMMETRIC, // Behind a symmetric NAT. 50 NATTYPE_NON_SYMMETRIC // Behind a non-symmetric NAT. 51 }; 52 53 class RTC_EXPORT StunProber : public sigslot::has_slots<> { 54 public: 55 enum Status { // Used in UMA_HISTOGRAM_ENUMERATION. 56 SUCCESS, // Successfully received bytes from the server. 57 GENERIC_FAILURE, // Generic failure. 58 RESOLVE_FAILED, // Host resolution failed. 59 WRITE_FAILED, // Sending a message to the server failed. 60 READ_FAILED, // Reading the reply from the server failed. 61 }; 62 63 class Observer { 64 public: 65 virtual ~Observer() = default; 66 virtual void OnPrepared(StunProber* prober, StunProber::Status status) = 0; 67 virtual void OnFinished(StunProber* prober, StunProber::Status status) = 0; 68 }; 69 70 struct RTC_EXPORT Stats { 71 Stats(); 72 ~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 ~StunProber() override; 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: 156 ObserverAdapter(); 157 ~ObserverAdapter() override; 158 set_callback(AsyncCallback callback)159 void set_callback(AsyncCallback callback) { callback_ = callback; } 160 void OnPrepared(StunProber* stunprober, Status status) override; 161 void OnFinished(StunProber* stunprober, Status status) override; 162 163 private: 164 AsyncCallback callback_; 165 }; 166 167 bool ResolveServerName(const rtc::SocketAddress& addr); 168 void OnServerResolved(rtc::AsyncResolverInterface* resolver); 169 170 void OnSocketReady(rtc::AsyncPacketSocket* socket, 171 const rtc::SocketAddress& addr); 172 173 void CreateSockets(); 174 Done()175 bool Done() { 176 return num_request_sent_ >= requests_per_ip_ * all_servers_addrs_.size(); 177 } 178 total_socket_required()179 size_t total_socket_required() { 180 return (shared_socket_mode_ ? 1 : all_servers_addrs_.size()) * 181 requests_per_ip_; 182 } 183 184 bool should_send_next_request(int64_t now); 185 int get_wake_up_interval_ms(); 186 187 bool SendNextRequest(); 188 189 // Will be invoked in 1ms intervals and schedule the next request from the 190 // |current_requester_| if the time has passed for another request. 191 void MaybeScheduleStunRequests(); 192 193 void ReportOnPrepared(StunProber::Status status); 194 void ReportOnFinished(StunProber::Status status); 195 196 Requester* CreateRequester(); 197 198 Requester* current_requester_ = nullptr; 199 200 // The time when the next request should go out. 201 int64_t next_request_time_ms_ = 0; 202 203 // Total requests sent so far. 204 uint32_t num_request_sent_ = 0; 205 206 bool shared_socket_mode_ = false; 207 208 // How many requests should be done against each resolved IP. 209 uint32_t requests_per_ip_ = 0; 210 211 // Milliseconds to pause between each STUN request. 212 int interval_ms_; 213 214 // Timeout period after the last request is sent. 215 int timeout_ms_; 216 217 // STUN server name to be resolved. 218 std::vector<rtc::SocketAddress> servers_; 219 220 // Weak references. 221 rtc::PacketSocketFactory* socket_factory_; 222 rtc::Thread* thread_; 223 224 // Accumulate all resolved addresses. 225 std::vector<rtc::SocketAddress> all_servers_addrs_; 226 227 // The set of STUN probe sockets and their state. 228 std::vector<Requester*> requesters_; 229 230 rtc::ThreadChecker thread_checker_; 231 232 // Temporary storage for created sockets. 233 std::vector<rtc::AsyncPacketSocket*> sockets_; 234 // This tracks how many of the sockets are ready. 235 size_t total_ready_sockets_ = 0; 236 237 rtc::AsyncInvoker invoker_; 238 239 Observer* observer_ = nullptr; 240 // TODO(guoweis): Remove this once all dependencies move away from 241 // AsyncCallback. 242 ObserverAdapter observer_adapter_; 243 244 rtc::NetworkManager::NetworkList networks_; 245 246 RTC_DISALLOW_COPY_AND_ASSIGN(StunProber); 247 }; 248 249 } // namespace stunprober 250 251 #endif // P2P_STUNPROBER_STUN_PROBER_H_ 252