Upstream version 11.40.271.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / p2p / client / connectivitychecker_unittest.cc
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) {
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 #ifdef USE_WEBRTC_DEV_BRANCH
225                             network->GetBestIP(),
226 #else  // USE_WEBRTC_DEV_BRANCH
227                             network->ip(),
228 #endif  // USE_WEBRTC_DEV_BRANCH
229                             kMinPort,
230                             kMaxPort,
231                             username,
232                             password,
233                             config->stun_servers);
234   }
235   virtual RelayPort* CreateRelayPort(
236       const std::string& username, const std::string& password,
237       const PortConfiguration* config, rtc::Network* network) {
238     return new FakeRelayPort(worker(),
239                              socket_factory_,
240                              network,
241 #ifdef USE_WEBRTC_DEV_BRANCH
242                              network->GetBestIP(),
243 #else  // USE_WEBRTC_DEV_BRANCH
244                              network->ip(),
245 #endif  // USE_WEBRTC_DEV_BRANCH
246                              kMinPort,
247                              kMaxPort,
248                              username,
249                              password);
250   }
251   virtual void InitiateProxyDetection() {
252     if (!proxy_initiated_) {
253       proxy_initiated_ = true;
254       proxy_info_.address = kProxyAddr;
255       proxy_info_.type = kProxyType;
256       SetProxyInfo(proxy_info_);
257     }
258   }
259
260   virtual rtc::ProxyInfo GetProxyInfo() const {
261     return proxy_info_;
262   }
263
264  private:
265   rtc::BasicPacketSocketFactory* socket_factory_;
266   FakeHttpPortAllocator* fake_port_allocator_;
267   rtc::FakeNetworkManager* network_manager_;
268   rtc::ProxyInfo proxy_info_;
269   bool proxy_initiated_;
270 };
271
272 class ConnectivityCheckerTest : public testing::Test {
273  protected:
274   void VerifyNic(const NicInfo& info,
275                  const rtc::SocketAddress& local_address) {
276     // Verify that the external address has been set.
277     EXPECT_EQ(kExternalAddr, info.external_address);
278
279     // Verify that the stun server address has been set.
280     EXPECT_EQ(1U, info.stun_server_addresses.size());
281     EXPECT_EQ(kStunAddr, *(info.stun_server_addresses.begin()));
282
283     // Verify that the media server address has been set. Don't care
284     // about port since it is different for different protocols.
285     EXPECT_EQ(kRelayAddr.ipaddr(), info.media_server_address.ipaddr());
286
287     // Verify that local ip matches.
288     EXPECT_EQ(local_address.ipaddr(), info.ip);
289
290     // Verify that we have received responses for our
291     // pings. Unsuccessful ping has rtt value -1, successful >= 0.
292     EXPECT_GE(info.stun.rtt, 0);
293     EXPECT_GE(info.udp.rtt, 0);
294     EXPECT_GE(info.tcp.rtt, 0);
295     EXPECT_GE(info.ssltcp.rtt, 0);
296
297     // If proxy has been set, verify address and type.
298     if (!info.proxy_info.address.IsNil()) {
299       EXPECT_EQ(kProxyAddr, info.proxy_info.address);
300       EXPECT_EQ(kProxyType, info.proxy_info.type);
301     }
302   }
303 };
304
305 // Tests a configuration with two network interfaces. Verifies that 4
306 // combinations of ip/proxy are created and that all protocols are
307 // tested on each combination.
308 TEST_F(ConnectivityCheckerTest, TestStart) {
309   ConnectivityCheckerForTest connectivity_checker(rtc::Thread::Current(),
310                                                   kJid,
311                                                   kSessionId,
312                                                   kBrowserAgent,
313                                                   kRelayToken,
314                                                   kConnection);
315   connectivity_checker.Initialize();
316   connectivity_checker.set_stun_address(kStunAddr);
317   connectivity_checker.network_manager()->AddInterface(kClientAddr1);
318   connectivity_checker.network_manager()->AddInterface(kClientAddr2);
319
320   connectivity_checker.Start();
321   rtc::Thread::Current()->ProcessMessages(1000);
322
323   NicMap nics = connectivity_checker.GetResults();
324
325   // There should be 4 nics in our map. 2 for each interface added,
326   // one with proxy set and one without.
327   EXPECT_EQ(4U, nics.size());
328
329   // First verify interfaces without proxy.
330   rtc::SocketAddress nilAddress;
331
332   // First lookup the address of the first nic combined with no proxy.
333   NicMap::iterator i = nics.find(NicId(kClientAddr1.ipaddr(), nilAddress));
334   ASSERT(i != nics.end());
335   NicInfo info = i->second;
336   VerifyNic(info, kClientAddr1);
337
338   // Then make sure the second device has been tested without proxy.
339   i = nics.find(NicId(kClientAddr2.ipaddr(), nilAddress));
340   ASSERT(i != nics.end());
341   info = i->second;
342   VerifyNic(info, kClientAddr2);
343
344   // Now verify both interfaces with proxy.
345   i = nics.find(NicId(kClientAddr1.ipaddr(), kProxyAddr));
346   ASSERT(i != nics.end());
347   info = i->second;
348   VerifyNic(info, kClientAddr1);
349
350   i = nics.find(NicId(kClientAddr2.ipaddr(), kProxyAddr));
351   ASSERT(i != nics.end());
352   info = i->second;
353   VerifyNic(info, kClientAddr2);
354 };
355
356 // Tests that nothing bad happens if thera are no network interfaces
357 // available to check.
358 TEST_F(ConnectivityCheckerTest, TestStartNoNetwork) {
359   ConnectivityCheckerForTest connectivity_checker(rtc::Thread::Current(),
360                                                   kJid,
361                                                   kSessionId,
362                                                   kBrowserAgent,
363                                                   kRelayToken,
364                                                   kConnection);
365   connectivity_checker.Initialize();
366   connectivity_checker.Start();
367   rtc::Thread::Current()->ProcessMessages(1000);
368
369   NicMap nics = connectivity_checker.GetResults();
370
371   // Verify that no nics where checked.
372   EXPECT_EQ(0U, nics.size());
373 }
374
375 }  // namespace cricket