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