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 #include "p2p/stunprober/stun_prober.h"
12 
13 #include <stdint.h>
14 
15 #include <memory>
16 
17 #include "p2p/base/basic_packet_socket_factory.h"
18 #include "p2p/base/test_stun_server.h"
19 #include "rtc_base/gunit.h"
20 #include "rtc_base/ip_address.h"
21 #include "rtc_base/ssl_adapter.h"
22 #include "rtc_base/virtual_socket_server.h"
23 #include "test/gtest.h"
24 
25 using stunprober::AsyncCallback;
26 using stunprober::StunProber;
27 
28 namespace stunprober {
29 
30 namespace {
31 
32 const rtc::SocketAddress kLocalAddr("192.168.0.1", 0);
33 const rtc::SocketAddress kStunAddr1("1.1.1.1", 3478);
34 const rtc::SocketAddress kStunAddr2("1.1.1.2", 3478);
35 const rtc::SocketAddress kFailedStunAddr("1.1.1.3", 3478);
36 const rtc::SocketAddress kStunMappedAddr("77.77.77.77", 0);
37 
38 }  // namespace
39 
40 class StunProberTest : public ::testing::Test {
41  public:
StunProberTest()42   StunProberTest()
43       : ss_(new rtc::VirtualSocketServer()),
44         main_(ss_.get()),
45         result_(StunProber::SUCCESS),
46         stun_server_1_(cricket::TestStunServer::Create(rtc::Thread::Current(),
47                                                        kStunAddr1)),
48         stun_server_2_(cricket::TestStunServer::Create(rtc::Thread::Current(),
49                                                        kStunAddr2)) {
50     stun_server_1_->set_fake_stun_addr(kStunMappedAddr);
51     stun_server_2_->set_fake_stun_addr(kStunMappedAddr);
52     rtc::InitializeSSL();
53   }
54 
set_expected_result(int result)55   void set_expected_result(int result) { result_ = result; }
56 
StartProbing(rtc::PacketSocketFactory * socket_factory,const std::vector<rtc::SocketAddress> & addrs,const rtc::NetworkManager::NetworkList & networks,bool shared_socket,uint16_t interval,uint16_t pings_per_ip)57   void StartProbing(rtc::PacketSocketFactory* socket_factory,
58                     const std::vector<rtc::SocketAddress>& addrs,
59                     const rtc::NetworkManager::NetworkList& networks,
60                     bool shared_socket,
61                     uint16_t interval,
62                     uint16_t pings_per_ip) {
63     prober.reset(
64         new StunProber(socket_factory, rtc::Thread::Current(), networks));
65     prober->Start(addrs, shared_socket, interval, pings_per_ip,
66                   100 /* timeout_ms */, [this](StunProber* prober, int result) {
67                     this->StopCallback(prober, result);
68                   });
69   }
70 
RunProber(bool shared_mode)71   void RunProber(bool shared_mode) {
72     const int pings_per_ip = 3;
73     std::vector<rtc::SocketAddress> addrs;
74     addrs.push_back(kStunAddr1);
75     addrs.push_back(kStunAddr2);
76     // Add a non-existing server. This shouldn't pollute the result.
77     addrs.push_back(kFailedStunAddr);
78 
79     rtc::Network ipv4_network1("test_eth0", "Test Network Adapter 1",
80                                rtc::IPAddress(0x12345600U), 24);
81     ipv4_network1.AddIP(rtc::IPAddress(0x12345678));
82     rtc::NetworkManager::NetworkList networks;
83     networks.push_back(&ipv4_network1);
84 
85     std::unique_ptr<rtc::BasicPacketSocketFactory> socket_factory(
86         new rtc::BasicPacketSocketFactory());
87 
88     // Set up the expected results for verification.
89     std::set<std::string> srflx_addresses;
90     srflx_addresses.insert(kStunMappedAddr.ToString());
91     const uint32_t total_pings_tried =
92         static_cast<uint32_t>(pings_per_ip * addrs.size());
93 
94     // The reported total_pings should not count for pings sent to the
95     // kFailedStunAddr.
96     const uint32_t total_pings_reported = total_pings_tried - pings_per_ip;
97 
98     StartProbing(socket_factory.get(), addrs, networks, shared_mode, 3,
99                  pings_per_ip);
100 
101     WAIT(stopped_, 1000);
102 
103     StunProber::Stats stats;
104     EXPECT_TRUE(prober->GetStats(&stats));
105     EXPECT_EQ(stats.success_percent, 100);
106     EXPECT_TRUE(stats.nat_type > stunprober::NATTYPE_NONE);
107     EXPECT_EQ(stats.srflx_addrs, srflx_addresses);
108     EXPECT_EQ(static_cast<uint32_t>(stats.num_request_sent),
109               total_pings_reported);
110     EXPECT_EQ(static_cast<uint32_t>(stats.num_response_received),
111               total_pings_reported);
112   }
113 
114  private:
StopCallback(StunProber * prober,int result)115   void StopCallback(StunProber* prober, int result) {
116     EXPECT_EQ(result, result_);
117     stopped_ = true;
118   }
119 
120   std::unique_ptr<rtc::VirtualSocketServer> ss_;
121   rtc::AutoSocketServerThread main_;
122   std::unique_ptr<StunProber> prober;
123   int result_ = 0;
124   bool stopped_ = false;
125   std::unique_ptr<cricket::TestStunServer> stun_server_1_;
126   std::unique_ptr<cricket::TestStunServer> stun_server_2_;
127 };
128 
TEST_F(StunProberTest,NonSharedMode)129 TEST_F(StunProberTest, NonSharedMode) {
130   RunProber(false);
131 }
132 
TEST_F(StunProberTest,SharedMode)133 TEST_F(StunProberTest, SharedMode) {
134   RunProber(true);
135 }
136 
137 }  // namespace stunprober
138