| OLD | NEW |
| (Empty) |
| 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 #include <string> | |
| 12 | |
| 13 #include "webrtc/p2p/base/basicpacketsocketfactory.h" | |
| 14 #include "webrtc/p2p/base/relayport.h" | |
| 15 #include "webrtc/p2p/base/stunport.h" | |
| 16 #include "webrtc/p2p/client/connectivitychecker.h" | |
| 17 #include "webrtc/p2p/client/httpportallocator.h" | |
| 18 #include "webrtc/base/asynchttprequest.h" | |
| 19 #include "webrtc/base/fakenetwork.h" | |
| 20 #include "webrtc/base/gunit.h" | |
| 21 #include "webrtc/base/scoped_ptr.h" | |
| 22 #include "webrtc/base/socketaddress.h" | |
| 23 | |
| 24 namespace cricket { | |
| 25 | |
| 26 static const rtc::SocketAddress kClientAddr1("11.11.11.11", 0); | |
| 27 static const rtc::SocketAddress kClientAddr2("22.22.22.22", 0); | |
| 28 static const rtc::SocketAddress kExternalAddr("33.33.33.33", 3333); | |
| 29 static const rtc::SocketAddress kStunAddr("44.44.44.44", 4444); | |
| 30 static const rtc::SocketAddress kRelayAddr("55.55.55.55", 5555); | |
| 31 static const rtc::SocketAddress kProxyAddr("66.66.66.66", 6666); | |
| 32 static const rtc::ProxyType kProxyType = rtc::PROXY_HTTPS; | |
| 33 static const char kRelayHost[] = "relay.google.com"; | |
| 34 static const char kRelayToken[] = | |
| 35 "CAESFwoOb2phQGdvb2dsZS5jb20Q043h47MmGhBTB1rbfIXkhuarDCZe+xF6"; | |
| 36 static const char kBrowserAgent[] = "browser_test"; | |
| 37 static const char kJid[] = "a.b@c"; | |
| 38 static const char kUserName[] = "testuser"; | |
| 39 static const char kPassword[] = "testpassword"; | |
| 40 static const char kMagicCookie[] = "testcookie"; | |
| 41 static const char kRelayUdpPort[] = "4444"; | |
| 42 static const char kRelayTcpPort[] = "5555"; | |
| 43 static const char kRelaySsltcpPort[] = "6666"; | |
| 44 static const char kSessionId[] = "testsession"; | |
| 45 static const char kConnection[] = "testconnection"; | |
| 46 static const int kMinPort = 1000; | |
| 47 static const int kMaxPort = 2000; | |
| 48 | |
| 49 // Fake implementation to mock away real network usage. | |
| 50 class FakeRelayPort : public RelayPort { | |
| 51 public: | |
| 52 FakeRelayPort(rtc::Thread* thread, | |
| 53 rtc::PacketSocketFactory* factory, | |
| 54 rtc::Network* network, const rtc::IPAddress& ip, | |
| 55 int min_port, int max_port, | |
| 56 const std::string& username, const std::string& password) | |
| 57 : RelayPort(thread, factory, network, ip, min_port, max_port, | |
| 58 username, password) { | |
| 59 } | |
| 60 | |
| 61 // Just signal that we are done. | |
| 62 virtual void PrepareAddress() { | |
| 63 SignalPortComplete(this); | |
| 64 } | |
| 65 }; | |
| 66 | |
| 67 // Fake implementation to mock away real network usage. | |
| 68 class FakeStunPort : public StunPort { | |
| 69 public: | |
| 70 FakeStunPort(rtc::Thread* thread, | |
| 71 rtc::PacketSocketFactory* factory, | |
| 72 rtc::Network* network, | |
| 73 const rtc::IPAddress& ip, | |
| 74 int min_port, int max_port, | |
| 75 const std::string& username, const std::string& password, | |
| 76 const ServerAddresses& server_addr) | |
| 77 : StunPort(thread, factory, network, ip, min_port, max_port, | |
| 78 username, password, server_addr, std::string()) { | |
| 79 } | |
| 80 | |
| 81 // Just set external address and signal that we are done. | |
| 82 virtual void PrepareAddress() { | |
| 83 AddAddress(kExternalAddr, kExternalAddr, rtc::SocketAddress(), "udp", "", | |
| 84 "", STUN_PORT_TYPE, ICE_TYPE_PREFERENCE_SRFLX, 0, true); | |
| 85 SignalPortComplete(this); | |
| 86 } | |
| 87 }; | |
| 88 | |
| 89 // Fake implementation to mock away real network usage by responding | |
| 90 // to http requests immediately. | |
| 91 class FakeHttpPortAllocatorSession : public TestHttpPortAllocatorSession { | |
| 92 public: | |
| 93 FakeHttpPortAllocatorSession( | |
| 94 HttpPortAllocator* allocator, | |
| 95 const std::string& content_name, | |
| 96 int component, | |
| 97 const std::string& ice_ufrag, const std::string& ice_pwd, | |
| 98 const std::vector<rtc::SocketAddress>& stun_hosts, | |
| 99 const std::vector<std::string>& relay_hosts, | |
| 100 const std::string& relay_token, | |
| 101 const std::string& agent) | |
| 102 : TestHttpPortAllocatorSession(allocator, | |
| 103 content_name, | |
| 104 component, | |
| 105 ice_ufrag, | |
| 106 ice_pwd, | |
| 107 stun_hosts, | |
| 108 relay_hosts, | |
| 109 relay_token, | |
| 110 agent) { | |
| 111 } | |
| 112 virtual void SendSessionRequest(const std::string& host, int port) { | |
| 113 FakeReceiveSessionResponse(host, port); | |
| 114 } | |
| 115 | |
| 116 // Pass results to the real implementation. | |
| 117 void FakeReceiveSessionResponse(const std::string& host, int port) { | |
| 118 rtc::AsyncHttpRequest* response = CreateAsyncHttpResponse(port); | |
| 119 TestHttpPortAllocatorSession::OnRequestDone(response); | |
| 120 response->Destroy(true); | |
| 121 } | |
| 122 | |
| 123 private: | |
| 124 // Helper method for creating a response to a relay session request. | |
| 125 rtc::AsyncHttpRequest* CreateAsyncHttpResponse(int port) { | |
| 126 rtc::AsyncHttpRequest* request = | |
| 127 new rtc::AsyncHttpRequest(kBrowserAgent); | |
| 128 std::stringstream ss; | |
| 129 ss << "username=" << kUserName << std::endl | |
| 130 << "password=" << kPassword << std::endl | |
| 131 << "magic_cookie=" << kMagicCookie << std::endl | |
| 132 << "relay.ip=" << kRelayAddr.ipaddr().ToString() << std::endl | |
| 133 << "relay.udp_port=" << kRelayUdpPort << std::endl | |
| 134 << "relay.tcp_port=" << kRelayTcpPort << std::endl | |
| 135 << "relay.ssltcp_port=" << kRelaySsltcpPort << std::endl; | |
| 136 request->response().document.reset( | |
| 137 new rtc::MemoryStream(ss.str().c_str())); | |
| 138 request->response().set_success(); | |
| 139 request->set_port(port); | |
| 140 request->set_secure(port == rtc::HTTP_SECURE_PORT); | |
| 141 return request; | |
| 142 } | |
| 143 }; | |
| 144 | |
| 145 // Fake implementation for creating fake http sessions. | |
| 146 class FakeHttpPortAllocator : public HttpPortAllocator { | |
| 147 public: | |
| 148 FakeHttpPortAllocator(rtc::NetworkManager* network_manager, | |
| 149 const std::string& user_agent) | |
| 150 : HttpPortAllocator(network_manager, user_agent) { | |
| 151 } | |
| 152 | |
| 153 virtual PortAllocatorSession* CreateSessionInternal( | |
| 154 const std::string& content_name, int component, | |
| 155 const std::string& ice_ufrag, const std::string& ice_pwd) { | |
| 156 std::vector<rtc::SocketAddress> stun_hosts; | |
| 157 stun_hosts.push_back(kStunAddr); | |
| 158 std::vector<std::string> relay_hosts; | |
| 159 relay_hosts.push_back(kRelayHost); | |
| 160 return new FakeHttpPortAllocatorSession(this, | |
| 161 content_name, | |
| 162 component, | |
| 163 ice_ufrag, | |
| 164 ice_pwd, | |
| 165 stun_hosts, | |
| 166 relay_hosts, | |
| 167 kRelayToken, | |
| 168 kBrowserAgent); | |
| 169 } | |
| 170 }; | |
| 171 | |
| 172 class ConnectivityCheckerForTest : public ConnectivityChecker { | |
| 173 public: | |
| 174 ConnectivityCheckerForTest(rtc::Thread* worker, | |
| 175 const std::string& jid, | |
| 176 const std::string& session_id, | |
| 177 const std::string& user_agent, | |
| 178 const std::string& relay_token, | |
| 179 const std::string& connection) | |
| 180 : ConnectivityChecker(worker, | |
| 181 jid, | |
| 182 session_id, | |
| 183 user_agent, | |
| 184 relay_token, | |
| 185 connection), | |
| 186 proxy_initiated_(false) { | |
| 187 } | |
| 188 | |
| 189 rtc::FakeNetworkManager* network_manager() const { | |
| 190 return network_manager_; | |
| 191 } | |
| 192 | |
| 193 FakeHttpPortAllocator* port_allocator() const { | |
| 194 return fake_port_allocator_; | |
| 195 } | |
| 196 | |
| 197 protected: | |
| 198 // Overridden methods for faking a real network. | |
| 199 virtual rtc::NetworkManager* CreateNetworkManager() { | |
| 200 network_manager_ = new rtc::FakeNetworkManager(); | |
| 201 return network_manager_; | |
| 202 } | |
| 203 virtual rtc::BasicPacketSocketFactory* CreateSocketFactory( | |
| 204 rtc::Thread* thread) { | |
| 205 // Create socket factory, for simplicity, let it run on the current thread. | |
| 206 socket_factory_ = | |
| 207 new rtc::BasicPacketSocketFactory(rtc::Thread::Current()); | |
| 208 return socket_factory_; | |
| 209 } | |
| 210 virtual HttpPortAllocator* CreatePortAllocator( | |
| 211 rtc::NetworkManager* network_manager, | |
| 212 const std::string& user_agent, | |
| 213 const std::string& relay_token) { | |
| 214 fake_port_allocator_ = | |
| 215 new FakeHttpPortAllocator(network_manager, user_agent); | |
| 216 return fake_port_allocator_; | |
| 217 } | |
| 218 virtual StunPort* CreateStunPort( | |
| 219 const std::string& username, const std::string& password, | |
| 220 const PortConfiguration* config, rtc::Network* network) { | |
| 221 return new FakeStunPort(worker(), | |
| 222 socket_factory_, | |
| 223 network, | |
| 224 network->GetBestIP(), | |
| 225 kMinPort, | |
| 226 kMaxPort, | |
| 227 username, | |
| 228 password, | |
| 229 config->stun_servers); | |
| 230 } | |
| 231 virtual RelayPort* CreateRelayPort( | |
| 232 const std::string& username, const std::string& password, | |
| 233 const PortConfiguration* config, rtc::Network* network) { | |
| 234 return new FakeRelayPort(worker(), | |
| 235 socket_factory_, | |
| 236 network, | |
| 237 network->GetBestIP(), | |
| 238 kMinPort, | |
| 239 kMaxPort, | |
| 240 username, | |
| 241 password); | |
| 242 } | |
| 243 virtual void InitiateProxyDetection() { | |
| 244 if (!proxy_initiated_) { | |
| 245 proxy_initiated_ = true; | |
| 246 proxy_info_.address = kProxyAddr; | |
| 247 proxy_info_.type = kProxyType; | |
| 248 SetProxyInfo(proxy_info_); | |
| 249 } | |
| 250 } | |
| 251 | |
| 252 virtual rtc::ProxyInfo GetProxyInfo() const { | |
| 253 return proxy_info_; | |
| 254 } | |
| 255 | |
| 256 private: | |
| 257 rtc::BasicPacketSocketFactory* socket_factory_; | |
| 258 FakeHttpPortAllocator* fake_port_allocator_; | |
| 259 rtc::FakeNetworkManager* network_manager_; | |
| 260 rtc::ProxyInfo proxy_info_; | |
| 261 bool proxy_initiated_; | |
| 262 }; | |
| 263 | |
| 264 class ConnectivityCheckerTest : public testing::Test { | |
| 265 protected: | |
| 266 void VerifyNic(const NicInfo& info, | |
| 267 const rtc::SocketAddress& local_address) { | |
| 268 // Verify that the external address has been set. | |
| 269 EXPECT_EQ(kExternalAddr, info.external_address); | |
| 270 | |
| 271 // Verify that the stun server address has been set. | |
| 272 EXPECT_EQ(1U, info.stun_server_addresses.size()); | |
| 273 EXPECT_EQ(kStunAddr, *(info.stun_server_addresses.begin())); | |
| 274 | |
| 275 // Verify that the media server address has been set. Don't care | |
| 276 // about port since it is different for different protocols. | |
| 277 EXPECT_EQ(kRelayAddr.ipaddr(), info.media_server_address.ipaddr()); | |
| 278 | |
| 279 // Verify that local ip matches. | |
| 280 EXPECT_EQ(local_address.ipaddr(), info.ip); | |
| 281 | |
| 282 // Verify that we have received responses for our | |
| 283 // pings. Unsuccessful ping has rtt value -1, successful >= 0. | |
| 284 EXPECT_GE(info.stun.rtt, 0); | |
| 285 EXPECT_GE(info.udp.rtt, 0); | |
| 286 EXPECT_GE(info.tcp.rtt, 0); | |
| 287 EXPECT_GE(info.ssltcp.rtt, 0); | |
| 288 | |
| 289 // If proxy has been set, verify address and type. | |
| 290 if (!info.proxy_info.address.IsNil()) { | |
| 291 EXPECT_EQ(kProxyAddr, info.proxy_info.address); | |
| 292 EXPECT_EQ(kProxyType, info.proxy_info.type); | |
| 293 } | |
| 294 } | |
| 295 }; | |
| 296 | |
| 297 // Tests a configuration with two network interfaces. Verifies that 4 | |
| 298 // combinations of ip/proxy are created and that all protocols are | |
| 299 // tested on each combination. | |
| 300 TEST_F(ConnectivityCheckerTest, TestStart) { | |
| 301 ConnectivityCheckerForTest connectivity_checker(rtc::Thread::Current(), | |
| 302 kJid, | |
| 303 kSessionId, | |
| 304 kBrowserAgent, | |
| 305 kRelayToken, | |
| 306 kConnection); | |
| 307 connectivity_checker.Initialize(); | |
| 308 connectivity_checker.set_stun_address(kStunAddr); | |
| 309 connectivity_checker.network_manager()->AddInterface(kClientAddr1); | |
| 310 connectivity_checker.network_manager()->AddInterface(kClientAddr2); | |
| 311 | |
| 312 connectivity_checker.Start(); | |
| 313 rtc::Thread::Current()->ProcessMessages(1000); | |
| 314 | |
| 315 NicMap nics = connectivity_checker.GetResults(); | |
| 316 | |
| 317 // There should be 4 nics in our map. 2 for each interface added, | |
| 318 // one with proxy set and one without. | |
| 319 EXPECT_EQ(4U, nics.size()); | |
| 320 | |
| 321 // First verify interfaces without proxy. | |
| 322 rtc::SocketAddress nilAddress; | |
| 323 | |
| 324 // First lookup the address of the first nic combined with no proxy. | |
| 325 NicMap::iterator i = nics.find(NicId(kClientAddr1.ipaddr(), nilAddress)); | |
| 326 ASSERT(i != nics.end()); | |
| 327 NicInfo info = i->second; | |
| 328 VerifyNic(info, kClientAddr1); | |
| 329 | |
| 330 // Then make sure the second device has been tested without proxy. | |
| 331 i = nics.find(NicId(kClientAddr2.ipaddr(), nilAddress)); | |
| 332 ASSERT(i != nics.end()); | |
| 333 info = i->second; | |
| 334 VerifyNic(info, kClientAddr2); | |
| 335 | |
| 336 // Now verify both interfaces with proxy. | |
| 337 i = nics.find(NicId(kClientAddr1.ipaddr(), kProxyAddr)); | |
| 338 ASSERT(i != nics.end()); | |
| 339 info = i->second; | |
| 340 VerifyNic(info, kClientAddr1); | |
| 341 | |
| 342 i = nics.find(NicId(kClientAddr2.ipaddr(), kProxyAddr)); | |
| 343 ASSERT(i != nics.end()); | |
| 344 info = i->second; | |
| 345 VerifyNic(info, kClientAddr2); | |
| 346 }; | |
| 347 | |
| 348 // Tests that nothing bad happens if thera are no network interfaces | |
| 349 // available to check. | |
| 350 TEST_F(ConnectivityCheckerTest, TestStartNoNetwork) { | |
| 351 ConnectivityCheckerForTest connectivity_checker(rtc::Thread::Current(), | |
| 352 kJid, | |
| 353 kSessionId, | |
| 354 kBrowserAgent, | |
| 355 kRelayToken, | |
| 356 kConnection); | |
| 357 connectivity_checker.Initialize(); | |
| 358 connectivity_checker.Start(); | |
| 359 rtc::Thread::Current()->ProcessMessages(1000); | |
| 360 | |
| 361 NicMap nics = connectivity_checker.GetResults(); | |
| 362 | |
| 363 // Verify that no nics where checked. | |
| 364 EXPECT_EQ(0U, nics.size()); | |
| 365 } | |
| 366 | |
| 367 } // namespace cricket | |
| OLD | NEW |