1 /* 2 * Copyright 2011 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_CLIENT_CONNECTIVITYCHECKER_H_ 12 #define WEBRTC_P2P_CLIENT_CONNECTIVITYCHECKER_H_ 13 14 #include <map> 15 #include <string> 16 17 #include "webrtc/p2p/base/basicpacketsocketfactory.h" 18 #include "webrtc/p2p/client/httpportallocator.h" 19 #include "webrtc/base/basictypes.h" 20 #include "webrtc/base/messagehandler.h" 21 #include "webrtc/base/network.h" 22 #include "webrtc/base/proxyinfo.h" 23 #include "webrtc/base/scoped_ptr.h" 24 #include "webrtc/base/sigslot.h" 25 #include "webrtc/base/socketaddress.h" 26 27 namespace rtc { 28 class AsyncHttpRequest; 29 class AutoDetectProxy; 30 class BasicPacketSocketFactory; 31 class NetworkManager; 32 class PacketSocketFactory; 33 class SignalThread; 34 class TestHttpPortAllocatorSession; 35 class Thread; 36 } 37 38 namespace cricket { 39 class HttpPortAllocator; 40 class Port; 41 class PortAllocatorSession; 42 struct PortConfiguration; 43 class RelayPort; 44 class StunPort; 45 46 // Contains details about a discovered firewall that are of interest 47 // when debugging call failures. 48 struct FirewallInfo { 49 std::string brand; 50 std::string model; 51 52 // TODO: List of current port mappings. 53 }; 54 55 // Contains details about a specific connect attempt. 56 struct ConnectInfo { 57 ConnectInfo() 58 : rtt(-1), error(0) {} 59 // Time when the connection was initiated. Needed for calculating 60 // the round trip time. 61 uint32 start_time_ms; 62 // Round trip time in milliseconds or -1 for failed connection. 63 int32 rtt; 64 // Error code representing low level errors like socket errors. 65 int error; 66 }; 67 68 // Identifier for a network interface and proxy address pair. 69 struct NicId { 70 NicId(const rtc::IPAddress& ip, 71 const rtc::SocketAddress& proxy_address) 72 : ip(ip), 73 proxy_address(proxy_address) { 74 } 75 rtc::IPAddress ip; 76 rtc::SocketAddress proxy_address; 77 }; 78 79 // Comparator implementation identifying unique network interface and 80 // proxy address pairs. 81 class NicIdComparator { 82 public: 83 int compare(const NicId &first, const NicId &second) const { 84 if (first.ip == second.ip) { 85 // Compare proxy address. 86 if (first.proxy_address == second.proxy_address) { 87 return 0; 88 } else { 89 return first.proxy_address < second.proxy_address? -1 : 1; 90 } 91 } 92 return first.ip < second.ip ? -1 : 1; 93 } 94 95 bool operator()(const NicId &first, const NicId &second) const { 96 return (compare(first, second) < 0); 97 } 98 }; 99 100 // Contains information of a network interface and proxy address pair. 101 struct NicInfo { 102 NicInfo() {} 103 rtc::IPAddress ip; 104 rtc::ProxyInfo proxy_info; 105 rtc::SocketAddress external_address; 106 ServerAddresses stun_server_addresses; 107 rtc::SocketAddress media_server_address; 108 ConnectInfo stun; 109 ConnectInfo http; 110 ConnectInfo https; 111 ConnectInfo udp; 112 ConnectInfo tcp; 113 ConnectInfo ssltcp; 114 FirewallInfo firewall; 115 }; 116 117 // Holds the result of the connectivity check. 118 class NicMap : public std::map<NicId, NicInfo, NicIdComparator> { 119 }; 120 121 class TestHttpPortAllocatorSession : public HttpPortAllocatorSession { 122 public: 123 TestHttpPortAllocatorSession( 124 HttpPortAllocator* allocator, 125 const std::string& content_name, 126 int component, 127 const std::string& ice_ufrag, 128 const std::string& ice_pwd, 129 const std::vector<rtc::SocketAddress>& stun_hosts, 130 const std::vector<std::string>& relay_hosts, 131 const std::string& relay_token, 132 const std::string& user_agent) 133 : HttpPortAllocatorSession( 134 allocator, content_name, component, ice_ufrag, ice_pwd, stun_hosts, 135 relay_hosts, relay_token, user_agent) { 136 } 137 void set_proxy(const rtc::ProxyInfo& proxy) { 138 proxy_ = proxy; 139 } 140 141 void ConfigReady(PortConfiguration* config); 142 143 void OnRequestDone(rtc::SignalThread* data); 144 145 sigslot::signal4<const std::string&, const std::string&, 146 const PortConfiguration*, 147 const rtc::ProxyInfo&> SignalConfigReady; 148 sigslot::signal1<rtc::AsyncHttpRequest*> SignalRequestDone; 149 150 private: 151 rtc::ProxyInfo proxy_; 152 }; 153 154 // Runs a request/response check on all network interface and proxy 155 // address combinations. The check is considered done either when all 156 // checks has been successful or when the check times out. 157 class ConnectivityChecker 158 : public rtc::MessageHandler, public sigslot::has_slots<> { 159 public: 160 ConnectivityChecker(rtc::Thread* worker, 161 const std::string& jid, 162 const std::string& session_id, 163 const std::string& user_agent, 164 const std::string& relay_token, 165 const std::string& connection); 166 virtual ~ConnectivityChecker(); 167 168 // Virtual for gMock. 169 virtual bool Initialize(); 170 virtual void Start(); 171 172 // MessageHandler implementation. 173 virtual void OnMessage(rtc::Message *msg); 174 175 // Instruct checker to stop and wait until that's done. 176 // Virtual for gMock. 177 virtual void Stop() { 178 worker_->Stop(); 179 } 180 181 const NicMap& GetResults() const { 182 return nics_; 183 } 184 185 void set_timeout_ms(uint32 timeout) { 186 timeout_ms_ = timeout; 187 } 188 189 void set_stun_address(const rtc::SocketAddress& stun_address) { 190 stun_address_ = stun_address; 191 } 192 193 const std::string& connection() const { 194 return connection_; 195 } 196 197 const std::string& jid() const { 198 return jid_; 199 } 200 201 const std::string& session_id() const { 202 return session_id_; 203 } 204 205 // Context: Main Thread. Signalled when the connectivity check is complete. 206 sigslot::signal1<ConnectivityChecker*> SignalCheckDone; 207 208 protected: 209 // Can be overridden for test. 210 virtual rtc::NetworkManager* CreateNetworkManager() { 211 return new rtc::BasicNetworkManager(); 212 } 213 virtual rtc::BasicPacketSocketFactory* CreateSocketFactory( 214 rtc::Thread* thread) { 215 return new rtc::BasicPacketSocketFactory(thread); 216 } 217 virtual HttpPortAllocator* CreatePortAllocator( 218 rtc::NetworkManager* network_manager, 219 const std::string& user_agent, 220 const std::string& relay_token); 221 virtual StunPort* CreateStunPort( 222 const std::string& username, const std::string& password, 223 const PortConfiguration* config, rtc::Network* network); 224 virtual RelayPort* CreateRelayPort( 225 const std::string& username, const std::string& password, 226 const PortConfiguration* config, rtc::Network* network); 227 virtual void InitiateProxyDetection(); 228 virtual void SetProxyInfo(const rtc::ProxyInfo& info); 229 virtual rtc::ProxyInfo GetProxyInfo() const; 230 231 rtc::Thread* worker() { 232 return worker_; 233 } 234 235 private: 236 bool AddNic(const rtc::IPAddress& ip, 237 const rtc::SocketAddress& proxy_address); 238 void AllocatePorts(); 239 void AllocateRelayPorts(); 240 void CheckNetworks(); 241 void CreateRelayPorts( 242 const std::string& username, const std::string& password, 243 const PortConfiguration* config, const rtc::ProxyInfo& proxy_info); 244 245 // Must be called by the worker thread. 246 void CleanUp(); 247 248 void OnRequestDone(rtc::AsyncHttpRequest* request); 249 void OnRelayPortComplete(Port* port); 250 void OnStunPortComplete(Port* port); 251 void OnRelayPortError(Port* port); 252 void OnStunPortError(Port* port); 253 void OnNetworksChanged(); 254 void OnProxyDetect(rtc::SignalThread* thread); 255 void OnConfigReady( 256 const std::string& username, const std::string& password, 257 const PortConfiguration* config, const rtc::ProxyInfo& proxy); 258 void OnConfigWithProxyReady(const PortConfiguration*); 259 void RegisterHttpStart(int port); 260 rtc::Thread* worker_; 261 std::string jid_; 262 std::string session_id_; 263 std::string user_agent_; 264 std::string relay_token_; 265 std::string connection_; 266 rtc::AutoDetectProxy* proxy_detect_; 267 rtc::scoped_ptr<rtc::NetworkManager> network_manager_; 268 rtc::scoped_ptr<rtc::BasicPacketSocketFactory> socket_factory_; 269 rtc::scoped_ptr<HttpPortAllocator> port_allocator_; 270 NicMap nics_; 271 std::vector<Port*> ports_; 272 std::vector<PortAllocatorSession*> sessions_; 273 uint32 timeout_ms_; 274 rtc::SocketAddress stun_address_; 275 rtc::Thread* main_; 276 bool started_; 277 }; 278 279 } // namespace cricket 280 281 #endif // WEBRTC_P2P_CLIENT_CONNECTIVITYCHECKER_H_ 282