Home | History | Annotate | Download | only in base
      1 /*
      2  *  Copyright 2004 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/base/gunit.h"
     14 #include "webrtc/base/logging.h"
     15 #include "webrtc/base/natserver.h"
     16 #include "webrtc/base/natsocketfactory.h"
     17 #include "webrtc/base/nethelpers.h"
     18 #include "webrtc/base/network.h"
     19 #include "webrtc/base/physicalsocketserver.h"
     20 #include "webrtc/base/testclient.h"
     21 #include "webrtc/base/virtualsocketserver.h"
     22 #include "webrtc/test/testsupport/gtest_disable.h"
     23 
     24 using namespace rtc;
     25 
     26 bool CheckReceive(
     27     TestClient* client, bool should_receive, const char* buf, size_t size) {
     28   return (should_receive) ?
     29       client->CheckNextPacket(buf, size, 0) :
     30       client->CheckNoPacket();
     31 }
     32 
     33 TestClient* CreateTestClient(
     34       SocketFactory* factory, const SocketAddress& local_addr) {
     35   AsyncUDPSocket* socket = AsyncUDPSocket::Create(factory, local_addr);
     36   return new TestClient(socket);
     37 }
     38 
     39 // Tests that when sending from internal_addr to external_addrs through the
     40 // NAT type specified by nat_type, all external addrs receive the sent packet
     41 // and, if exp_same is true, all use the same mapped-address on the NAT.
     42 void TestSend(
     43       SocketServer* internal, const SocketAddress& internal_addr,
     44       SocketServer* external, const SocketAddress external_addrs[4],
     45       NATType nat_type, bool exp_same) {
     46   Thread th_int(internal);
     47   Thread th_ext(external);
     48 
     49   SocketAddress server_addr = internal_addr;
     50   server_addr.SetPort(0);  // Auto-select a port
     51   NATServer* nat = new NATServer(
     52       nat_type, internal, server_addr, external, external_addrs[0]);
     53   NATSocketFactory* natsf = new NATSocketFactory(internal,
     54                                                  nat->internal_address());
     55 
     56   TestClient* in = CreateTestClient(natsf, internal_addr);
     57   TestClient* out[4];
     58   for (int i = 0; i < 4; i++)
     59     out[i] = CreateTestClient(external, external_addrs[i]);
     60 
     61   th_int.Start();
     62   th_ext.Start();
     63 
     64   const char* buf = "filter_test";
     65   size_t len = strlen(buf);
     66 
     67   in->SendTo(buf, len, out[0]->address());
     68   SocketAddress trans_addr;
     69   EXPECT_TRUE(out[0]->CheckNextPacket(buf, len, &trans_addr));
     70 
     71   for (int i = 1; i < 4; i++) {
     72     in->SendTo(buf, len, out[i]->address());
     73     SocketAddress trans_addr2;
     74     EXPECT_TRUE(out[i]->CheckNextPacket(buf, len, &trans_addr2));
     75     bool are_same = (trans_addr == trans_addr2);
     76     ASSERT_EQ(are_same, exp_same) << "same translated address";
     77     ASSERT_NE(AF_UNSPEC, trans_addr.family());
     78     ASSERT_NE(AF_UNSPEC, trans_addr2.family());
     79   }
     80 
     81   th_int.Stop();
     82   th_ext.Stop();
     83 
     84   delete nat;
     85   delete natsf;
     86   delete in;
     87   for (int i = 0; i < 4; i++)
     88     delete out[i];
     89 }
     90 
     91 // Tests that when sending from external_addrs to internal_addr, the packet
     92 // is delivered according to the specified filter_ip and filter_port rules.
     93 void TestRecv(
     94       SocketServer* internal, const SocketAddress& internal_addr,
     95       SocketServer* external, const SocketAddress external_addrs[4],
     96       NATType nat_type, bool filter_ip, bool filter_port) {
     97   Thread th_int(internal);
     98   Thread th_ext(external);
     99 
    100   SocketAddress server_addr = internal_addr;
    101   server_addr.SetPort(0);  // Auto-select a port
    102   NATServer* nat = new NATServer(
    103       nat_type, internal, server_addr, external, external_addrs[0]);
    104   NATSocketFactory* natsf = new NATSocketFactory(internal,
    105                                                  nat->internal_address());
    106 
    107   TestClient* in = CreateTestClient(natsf, internal_addr);
    108   TestClient* out[4];
    109   for (int i = 0; i < 4; i++)
    110     out[i] = CreateTestClient(external, external_addrs[i]);
    111 
    112   th_int.Start();
    113   th_ext.Start();
    114 
    115   const char* buf = "filter_test";
    116   size_t len = strlen(buf);
    117 
    118   in->SendTo(buf, len, out[0]->address());
    119   SocketAddress trans_addr;
    120   EXPECT_TRUE(out[0]->CheckNextPacket(buf, len, &trans_addr));
    121 
    122   out[1]->SendTo(buf, len, trans_addr);
    123   EXPECT_TRUE(CheckReceive(in, !filter_ip, buf, len));
    124 
    125   out[2]->SendTo(buf, len, trans_addr);
    126   EXPECT_TRUE(CheckReceive(in, !filter_port, buf, len));
    127 
    128   out[3]->SendTo(buf, len, trans_addr);
    129   EXPECT_TRUE(CheckReceive(in, !filter_ip && !filter_port, buf, len));
    130 
    131   th_int.Stop();
    132   th_ext.Stop();
    133 
    134   delete nat;
    135   delete natsf;
    136   delete in;
    137   for (int i = 0; i < 4; i++)
    138     delete out[i];
    139 }
    140 
    141 // Tests that NATServer allocates bindings properly.
    142 void TestBindings(
    143     SocketServer* internal, const SocketAddress& internal_addr,
    144     SocketServer* external, const SocketAddress external_addrs[4]) {
    145   TestSend(internal, internal_addr, external, external_addrs,
    146            NAT_OPEN_CONE, true);
    147   TestSend(internal, internal_addr, external, external_addrs,
    148            NAT_ADDR_RESTRICTED, true);
    149   TestSend(internal, internal_addr, external, external_addrs,
    150            NAT_PORT_RESTRICTED, true);
    151   TestSend(internal, internal_addr, external, external_addrs,
    152            NAT_SYMMETRIC, false);
    153 }
    154 
    155 // Tests that NATServer filters packets properly.
    156 void TestFilters(
    157     SocketServer* internal, const SocketAddress& internal_addr,
    158     SocketServer* external, const SocketAddress external_addrs[4]) {
    159   TestRecv(internal, internal_addr, external, external_addrs,
    160            NAT_OPEN_CONE, false, false);
    161   TestRecv(internal, internal_addr, external, external_addrs,
    162            NAT_ADDR_RESTRICTED, true, false);
    163   TestRecv(internal, internal_addr, external, external_addrs,
    164            NAT_PORT_RESTRICTED, true, true);
    165   TestRecv(internal, internal_addr, external, external_addrs,
    166            NAT_SYMMETRIC, true, true);
    167 }
    168 
    169 bool TestConnectivity(const SocketAddress& src, const IPAddress& dst) {
    170   // The physical NAT tests require connectivity to the selected ip from the
    171   // internal address used for the NAT. Things like firewalls can break that, so
    172   // check to see if it's worth even trying with this ip.
    173   scoped_ptr<PhysicalSocketServer> pss(new PhysicalSocketServer());
    174   scoped_ptr<AsyncSocket> client(pss->CreateAsyncSocket(src.family(),
    175                                                         SOCK_DGRAM));
    176   scoped_ptr<AsyncSocket> server(pss->CreateAsyncSocket(src.family(),
    177                                                         SOCK_DGRAM));
    178   if (client->Bind(SocketAddress(src.ipaddr(), 0)) != 0 ||
    179       server->Bind(SocketAddress(dst, 0)) != 0) {
    180     return false;
    181   }
    182   const char* buf = "hello other socket";
    183   size_t len = strlen(buf);
    184   int sent = client->SendTo(buf, len, server->GetLocalAddress());
    185   SocketAddress addr;
    186   const size_t kRecvBufSize = 64;
    187   char recvbuf[kRecvBufSize];
    188   Thread::Current()->SleepMs(100);
    189   int received = server->RecvFrom(recvbuf, kRecvBufSize, &addr);
    190   return received == sent && ::memcmp(buf, recvbuf, len) == 0;
    191 }
    192 
    193 void TestPhysicalInternal(const SocketAddress& int_addr) {
    194   BasicNetworkManager network_manager;
    195   network_manager.set_ipv6_enabled(true);
    196   network_manager.StartUpdating();
    197   // Process pending messages so the network list is updated.
    198   Thread::Current()->ProcessMessages(0);
    199 
    200   std::vector<Network*> networks;
    201   network_manager.GetNetworks(&networks);
    202   if (networks.empty()) {
    203     LOG(LS_WARNING) << "Not enough network adapters for test.";
    204     return;
    205   }
    206 
    207   SocketAddress ext_addr1(int_addr);
    208   SocketAddress ext_addr2;
    209   // Find an available IP with matching family. The test breaks if int_addr
    210   // can't talk to ip, so check for connectivity as well.
    211   for (std::vector<Network*>::iterator it = networks.begin();
    212       it != networks.end(); ++it) {
    213     const IPAddress& ip = (*it)->GetBestIP();
    214     if (ip.family() == int_addr.family() && TestConnectivity(int_addr, ip)) {
    215       ext_addr2.SetIP(ip);
    216       break;
    217     }
    218   }
    219   if (ext_addr2.IsNil()) {
    220     LOG(LS_WARNING) << "No available IP of same family as " << int_addr;
    221     return;
    222   }
    223 
    224   LOG(LS_INFO) << "selected ip " << ext_addr2.ipaddr();
    225 
    226   SocketAddress ext_addrs[4] = {
    227       SocketAddress(ext_addr1),
    228       SocketAddress(ext_addr2),
    229       SocketAddress(ext_addr1),
    230       SocketAddress(ext_addr2)
    231   };
    232 
    233   scoped_ptr<PhysicalSocketServer> int_pss(new PhysicalSocketServer());
    234   scoped_ptr<PhysicalSocketServer> ext_pss(new PhysicalSocketServer());
    235 
    236   TestBindings(int_pss.get(), int_addr, ext_pss.get(), ext_addrs);
    237   TestFilters(int_pss.get(), int_addr, ext_pss.get(), ext_addrs);
    238 }
    239 
    240 TEST(NatTest, DISABLED_ON_MAC(TestPhysicalIPv4)) {
    241   TestPhysicalInternal(SocketAddress("127.0.0.1", 0));
    242 }
    243 
    244 TEST(NatTest, DISABLED_ON_MAC(TestPhysicalIPv6)) {
    245   if (HasIPv6Enabled()) {
    246     TestPhysicalInternal(SocketAddress("::1", 0));
    247   } else {
    248     LOG(LS_WARNING) << "No IPv6, skipping";
    249   }
    250 }
    251 
    252 class TestVirtualSocketServer : public VirtualSocketServer {
    253  public:
    254   explicit TestVirtualSocketServer(SocketServer* ss)
    255       : VirtualSocketServer(ss),
    256         ss_(ss) {}
    257   // Expose this publicly
    258   IPAddress GetNextIP(int af) { return VirtualSocketServer::GetNextIP(af); }
    259 
    260  private:
    261   scoped_ptr<SocketServer> ss_;
    262 };
    263 
    264 void TestVirtualInternal(int family) {
    265   scoped_ptr<TestVirtualSocketServer> int_vss(new TestVirtualSocketServer(
    266       new PhysicalSocketServer()));
    267   scoped_ptr<TestVirtualSocketServer> ext_vss(new TestVirtualSocketServer(
    268       new PhysicalSocketServer()));
    269 
    270   SocketAddress int_addr;
    271   SocketAddress ext_addrs[4];
    272   int_addr.SetIP(int_vss->GetNextIP(family));
    273   ext_addrs[0].SetIP(ext_vss->GetNextIP(int_addr.family()));
    274   ext_addrs[1].SetIP(ext_vss->GetNextIP(int_addr.family()));
    275   ext_addrs[2].SetIP(ext_addrs[0].ipaddr());
    276   ext_addrs[3].SetIP(ext_addrs[1].ipaddr());
    277 
    278   TestBindings(int_vss.get(), int_addr, ext_vss.get(), ext_addrs);
    279   TestFilters(int_vss.get(), int_addr, ext_vss.get(), ext_addrs);
    280 }
    281 
    282 TEST(NatTest, DISABLED_ON_MAC(TestVirtualIPv4)) {
    283   TestVirtualInternal(AF_INET);
    284 }
    285 
    286 TEST(NatTest, DISABLED_ON_MAC(TestVirtualIPv6)) {
    287   if (HasIPv6Enabled()) {
    288     TestVirtualInternal(AF_INET6);
    289   } else {
    290     LOG(LS_WARNING) << "No IPv6, skipping";
    291   }
    292 }
    293 
    294 // TODO: Finish this test
    295 class NatTcpTest : public testing::Test, public sigslot::has_slots<> {
    296  public:
    297   NatTcpTest() : connected_(false) {}
    298   virtual void SetUp() {
    299     int_vss_ = new TestVirtualSocketServer(new PhysicalSocketServer());
    300     ext_vss_ = new TestVirtualSocketServer(new PhysicalSocketServer());
    301     nat_ = new NATServer(NAT_OPEN_CONE, int_vss_, SocketAddress(),
    302                          ext_vss_, SocketAddress());
    303     natsf_ = new NATSocketFactory(int_vss_, nat_->internal_address());
    304   }
    305   void OnConnectEvent(AsyncSocket* socket) {
    306     connected_ = true;
    307   }
    308   void OnAcceptEvent(AsyncSocket* socket) {
    309     accepted_ = server_->Accept(NULL);
    310   }
    311   void OnCloseEvent(AsyncSocket* socket, int error) {
    312   }
    313   void ConnectEvents() {
    314     server_->SignalReadEvent.connect(this, &NatTcpTest::OnAcceptEvent);
    315     client_->SignalConnectEvent.connect(this, &NatTcpTest::OnConnectEvent);
    316   }
    317   TestVirtualSocketServer* int_vss_;
    318   TestVirtualSocketServer* ext_vss_;
    319   NATServer* nat_;
    320   NATSocketFactory* natsf_;
    321   AsyncSocket* client_;
    322   AsyncSocket* server_;
    323   AsyncSocket* accepted_;
    324   bool connected_;
    325 };
    326 
    327 TEST_F(NatTcpTest, DISABLED_TestConnectOut) {
    328   server_ = ext_vss_->CreateAsyncSocket(SOCK_STREAM);
    329   server_->Bind(SocketAddress());
    330   server_->Listen(5);
    331 
    332   client_ = int_vss_->CreateAsyncSocket(SOCK_STREAM);
    333   EXPECT_GE(0, client_->Bind(SocketAddress()));
    334   EXPECT_GE(0, client_->Connect(server_->GetLocalAddress()));
    335 
    336 
    337   ConnectEvents();
    338 
    339   EXPECT_TRUE_WAIT(connected_, 1000);
    340   EXPECT_EQ(client_->GetRemoteAddress(), server_->GetLocalAddress());
    341   EXPECT_EQ(client_->GetRemoteAddress(), accepted_->GetLocalAddress());
    342   EXPECT_EQ(client_->GetLocalAddress(), accepted_->GetRemoteAddress());
    343 
    344   client_->Close();
    345 }
    346 //#endif
    347