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