xref: /aosp_15_r20/external/webrtc/rtc_base/nat_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker 
11*d9f75844SAndroid Build Coastguard Worker #include <string.h>
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker #include <algorithm>
14*d9f75844SAndroid Build Coastguard Worker #include <memory>
15*d9f75844SAndroid Build Coastguard Worker #include <string>
16*d9f75844SAndroid Build Coastguard Worker #include <vector>
17*d9f75844SAndroid Build Coastguard Worker 
18*d9f75844SAndroid Build Coastguard Worker #include "absl/memory/memory.h"
19*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/async_packet_socket.h"
20*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/async_tcp_socket.h"
21*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/async_udp_socket.h"
22*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/gunit.h"
23*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/ip_address.h"
24*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
25*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/nat_server.h"
26*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/nat_socket_factory.h"
27*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/nat_types.h"
28*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/net_helpers.h"
29*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/network.h"
30*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/physical_socket_server.h"
31*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/socket.h"
32*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/socket_address.h"
33*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/socket_factory.h"
34*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/socket_server.h"
35*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/test_client.h"
36*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/third_party/sigslot/sigslot.h"
37*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/thread.h"
38*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/virtual_socket_server.h"
39*d9f75844SAndroid Build Coastguard Worker #include "test/gtest.h"
40*d9f75844SAndroid Build Coastguard Worker #include "test/scoped_key_value_config.h"
41*d9f75844SAndroid Build Coastguard Worker 
42*d9f75844SAndroid Build Coastguard Worker namespace rtc {
43*d9f75844SAndroid Build Coastguard Worker namespace {
44*d9f75844SAndroid Build Coastguard Worker 
CheckReceive(TestClient * client,bool should_receive,const char * buf,size_t size)45*d9f75844SAndroid Build Coastguard Worker bool CheckReceive(TestClient* client,
46*d9f75844SAndroid Build Coastguard Worker                   bool should_receive,
47*d9f75844SAndroid Build Coastguard Worker                   const char* buf,
48*d9f75844SAndroid Build Coastguard Worker                   size_t size) {
49*d9f75844SAndroid Build Coastguard Worker   return (should_receive) ? client->CheckNextPacket(buf, size, 0)
50*d9f75844SAndroid Build Coastguard Worker                           : client->CheckNoPacket();
51*d9f75844SAndroid Build Coastguard Worker }
52*d9f75844SAndroid Build Coastguard Worker 
CreateTestClient(SocketFactory * factory,const SocketAddress & local_addr)53*d9f75844SAndroid Build Coastguard Worker TestClient* CreateTestClient(SocketFactory* factory,
54*d9f75844SAndroid Build Coastguard Worker                              const SocketAddress& local_addr) {
55*d9f75844SAndroid Build Coastguard Worker   return new TestClient(
56*d9f75844SAndroid Build Coastguard Worker       absl::WrapUnique(AsyncUDPSocket::Create(factory, local_addr)));
57*d9f75844SAndroid Build Coastguard Worker }
58*d9f75844SAndroid Build Coastguard Worker 
CreateTCPTestClient(Socket * socket)59*d9f75844SAndroid Build Coastguard Worker TestClient* CreateTCPTestClient(Socket* socket) {
60*d9f75844SAndroid Build Coastguard Worker   return new TestClient(std::make_unique<AsyncTCPSocket>(socket));
61*d9f75844SAndroid Build Coastguard Worker }
62*d9f75844SAndroid Build Coastguard Worker 
63*d9f75844SAndroid Build Coastguard Worker // Tests that when sending from internal_addr to external_addrs through the
64*d9f75844SAndroid Build Coastguard Worker // NAT type specified by nat_type, all external addrs receive the sent packet
65*d9f75844SAndroid Build Coastguard Worker // and, if exp_same is true, all use the same mapped-address on the NAT.
TestSend(SocketServer * internal,const SocketAddress & internal_addr,SocketServer * external,const SocketAddress external_addrs[4],NATType nat_type,bool exp_same)66*d9f75844SAndroid Build Coastguard Worker void TestSend(SocketServer* internal,
67*d9f75844SAndroid Build Coastguard Worker               const SocketAddress& internal_addr,
68*d9f75844SAndroid Build Coastguard Worker               SocketServer* external,
69*d9f75844SAndroid Build Coastguard Worker               const SocketAddress external_addrs[4],
70*d9f75844SAndroid Build Coastguard Worker               NATType nat_type,
71*d9f75844SAndroid Build Coastguard Worker               bool exp_same) {
72*d9f75844SAndroid Build Coastguard Worker   Thread th_int(internal);
73*d9f75844SAndroid Build Coastguard Worker   Thread th_ext(external);
74*d9f75844SAndroid Build Coastguard Worker 
75*d9f75844SAndroid Build Coastguard Worker   SocketAddress server_addr = internal_addr;
76*d9f75844SAndroid Build Coastguard Worker   server_addr.SetPort(0);  // Auto-select a port
77*d9f75844SAndroid Build Coastguard Worker   NATServer* nat = new NATServer(nat_type, internal, server_addr, server_addr,
78*d9f75844SAndroid Build Coastguard Worker                                  external, external_addrs[0]);
79*d9f75844SAndroid Build Coastguard Worker   NATSocketFactory* natsf = new NATSocketFactory(
80*d9f75844SAndroid Build Coastguard Worker       internal, nat->internal_udp_address(), nat->internal_tcp_address());
81*d9f75844SAndroid Build Coastguard Worker 
82*d9f75844SAndroid Build Coastguard Worker   TestClient* in = CreateTestClient(natsf, internal_addr);
83*d9f75844SAndroid Build Coastguard Worker   TestClient* out[4];
84*d9f75844SAndroid Build Coastguard Worker   for (int i = 0; i < 4; i++)
85*d9f75844SAndroid Build Coastguard Worker     out[i] = CreateTestClient(external, external_addrs[i]);
86*d9f75844SAndroid Build Coastguard Worker 
87*d9f75844SAndroid Build Coastguard Worker   th_int.Start();
88*d9f75844SAndroid Build Coastguard Worker   th_ext.Start();
89*d9f75844SAndroid Build Coastguard Worker 
90*d9f75844SAndroid Build Coastguard Worker   const char* buf = "filter_test";
91*d9f75844SAndroid Build Coastguard Worker   size_t len = strlen(buf);
92*d9f75844SAndroid Build Coastguard Worker 
93*d9f75844SAndroid Build Coastguard Worker   in->SendTo(buf, len, out[0]->address());
94*d9f75844SAndroid Build Coastguard Worker   SocketAddress trans_addr;
95*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(out[0]->CheckNextPacket(buf, len, &trans_addr));
96*d9f75844SAndroid Build Coastguard Worker 
97*d9f75844SAndroid Build Coastguard Worker   for (int i = 1; i < 4; i++) {
98*d9f75844SAndroid Build Coastguard Worker     in->SendTo(buf, len, out[i]->address());
99*d9f75844SAndroid Build Coastguard Worker     SocketAddress trans_addr2;
100*d9f75844SAndroid Build Coastguard Worker     EXPECT_TRUE(out[i]->CheckNextPacket(buf, len, &trans_addr2));
101*d9f75844SAndroid Build Coastguard Worker     bool are_same = (trans_addr == trans_addr2);
102*d9f75844SAndroid Build Coastguard Worker     ASSERT_EQ(are_same, exp_same) << "same translated address";
103*d9f75844SAndroid Build Coastguard Worker     ASSERT_NE(AF_UNSPEC, trans_addr.family());
104*d9f75844SAndroid Build Coastguard Worker     ASSERT_NE(AF_UNSPEC, trans_addr2.family());
105*d9f75844SAndroid Build Coastguard Worker   }
106*d9f75844SAndroid Build Coastguard Worker 
107*d9f75844SAndroid Build Coastguard Worker   th_int.Stop();
108*d9f75844SAndroid Build Coastguard Worker   th_ext.Stop();
109*d9f75844SAndroid Build Coastguard Worker 
110*d9f75844SAndroid Build Coastguard Worker   delete nat;
111*d9f75844SAndroid Build Coastguard Worker   delete natsf;
112*d9f75844SAndroid Build Coastguard Worker   delete in;
113*d9f75844SAndroid Build Coastguard Worker   for (int i = 0; i < 4; i++)
114*d9f75844SAndroid Build Coastguard Worker     delete out[i];
115*d9f75844SAndroid Build Coastguard Worker }
116*d9f75844SAndroid Build Coastguard Worker 
117*d9f75844SAndroid Build Coastguard Worker // Tests that when sending from external_addrs to internal_addr, the packet
118*d9f75844SAndroid Build Coastguard Worker // is delivered according to the specified filter_ip and filter_port rules.
TestRecv(SocketServer * internal,const SocketAddress & internal_addr,SocketServer * external,const SocketAddress external_addrs[4],NATType nat_type,bool filter_ip,bool filter_port)119*d9f75844SAndroid Build Coastguard Worker void TestRecv(SocketServer* internal,
120*d9f75844SAndroid Build Coastguard Worker               const SocketAddress& internal_addr,
121*d9f75844SAndroid Build Coastguard Worker               SocketServer* external,
122*d9f75844SAndroid Build Coastguard Worker               const SocketAddress external_addrs[4],
123*d9f75844SAndroid Build Coastguard Worker               NATType nat_type,
124*d9f75844SAndroid Build Coastguard Worker               bool filter_ip,
125*d9f75844SAndroid Build Coastguard Worker               bool filter_port) {
126*d9f75844SAndroid Build Coastguard Worker   Thread th_int(internal);
127*d9f75844SAndroid Build Coastguard Worker   Thread th_ext(external);
128*d9f75844SAndroid Build Coastguard Worker 
129*d9f75844SAndroid Build Coastguard Worker   SocketAddress server_addr = internal_addr;
130*d9f75844SAndroid Build Coastguard Worker   server_addr.SetPort(0);  // Auto-select a port
131*d9f75844SAndroid Build Coastguard Worker   NATServer* nat = new NATServer(nat_type, internal, server_addr, server_addr,
132*d9f75844SAndroid Build Coastguard Worker                                  external, external_addrs[0]);
133*d9f75844SAndroid Build Coastguard Worker   NATSocketFactory* natsf = new NATSocketFactory(
134*d9f75844SAndroid Build Coastguard Worker       internal, nat->internal_udp_address(), nat->internal_tcp_address());
135*d9f75844SAndroid Build Coastguard Worker 
136*d9f75844SAndroid Build Coastguard Worker   TestClient* in = CreateTestClient(natsf, internal_addr);
137*d9f75844SAndroid Build Coastguard Worker   TestClient* out[4];
138*d9f75844SAndroid Build Coastguard Worker   for (int i = 0; i < 4; i++)
139*d9f75844SAndroid Build Coastguard Worker     out[i] = CreateTestClient(external, external_addrs[i]);
140*d9f75844SAndroid Build Coastguard Worker 
141*d9f75844SAndroid Build Coastguard Worker   th_int.Start();
142*d9f75844SAndroid Build Coastguard Worker   th_ext.Start();
143*d9f75844SAndroid Build Coastguard Worker 
144*d9f75844SAndroid Build Coastguard Worker   const char* buf = "filter_test";
145*d9f75844SAndroid Build Coastguard Worker   size_t len = strlen(buf);
146*d9f75844SAndroid Build Coastguard Worker 
147*d9f75844SAndroid Build Coastguard Worker   in->SendTo(buf, len, out[0]->address());
148*d9f75844SAndroid Build Coastguard Worker   SocketAddress trans_addr;
149*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(out[0]->CheckNextPacket(buf, len, &trans_addr));
150*d9f75844SAndroid Build Coastguard Worker 
151*d9f75844SAndroid Build Coastguard Worker   out[1]->SendTo(buf, len, trans_addr);
152*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CheckReceive(in, !filter_ip, buf, len));
153*d9f75844SAndroid Build Coastguard Worker 
154*d9f75844SAndroid Build Coastguard Worker   out[2]->SendTo(buf, len, trans_addr);
155*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CheckReceive(in, !filter_port, buf, len));
156*d9f75844SAndroid Build Coastguard Worker 
157*d9f75844SAndroid Build Coastguard Worker   out[3]->SendTo(buf, len, trans_addr);
158*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(CheckReceive(in, !filter_ip && !filter_port, buf, len));
159*d9f75844SAndroid Build Coastguard Worker 
160*d9f75844SAndroid Build Coastguard Worker   th_int.Stop();
161*d9f75844SAndroid Build Coastguard Worker   th_ext.Stop();
162*d9f75844SAndroid Build Coastguard Worker 
163*d9f75844SAndroid Build Coastguard Worker   delete nat;
164*d9f75844SAndroid Build Coastguard Worker   delete natsf;
165*d9f75844SAndroid Build Coastguard Worker   delete in;
166*d9f75844SAndroid Build Coastguard Worker   for (int i = 0; i < 4; i++)
167*d9f75844SAndroid Build Coastguard Worker     delete out[i];
168*d9f75844SAndroid Build Coastguard Worker }
169*d9f75844SAndroid Build Coastguard Worker 
170*d9f75844SAndroid Build Coastguard Worker // Tests that NATServer allocates bindings properly.
TestBindings(SocketServer * internal,const SocketAddress & internal_addr,SocketServer * external,const SocketAddress external_addrs[4])171*d9f75844SAndroid Build Coastguard Worker void TestBindings(SocketServer* internal,
172*d9f75844SAndroid Build Coastguard Worker                   const SocketAddress& internal_addr,
173*d9f75844SAndroid Build Coastguard Worker                   SocketServer* external,
174*d9f75844SAndroid Build Coastguard Worker                   const SocketAddress external_addrs[4]) {
175*d9f75844SAndroid Build Coastguard Worker   TestSend(internal, internal_addr, external, external_addrs, NAT_OPEN_CONE,
176*d9f75844SAndroid Build Coastguard Worker            true);
177*d9f75844SAndroid Build Coastguard Worker   TestSend(internal, internal_addr, external, external_addrs,
178*d9f75844SAndroid Build Coastguard Worker            NAT_ADDR_RESTRICTED, true);
179*d9f75844SAndroid Build Coastguard Worker   TestSend(internal, internal_addr, external, external_addrs,
180*d9f75844SAndroid Build Coastguard Worker            NAT_PORT_RESTRICTED, true);
181*d9f75844SAndroid Build Coastguard Worker   TestSend(internal, internal_addr, external, external_addrs, NAT_SYMMETRIC,
182*d9f75844SAndroid Build Coastguard Worker            false);
183*d9f75844SAndroid Build Coastguard Worker }
184*d9f75844SAndroid Build Coastguard Worker 
185*d9f75844SAndroid Build Coastguard Worker // Tests that NATServer filters packets properly.
TestFilters(SocketServer * internal,const SocketAddress & internal_addr,SocketServer * external,const SocketAddress external_addrs[4])186*d9f75844SAndroid Build Coastguard Worker void TestFilters(SocketServer* internal,
187*d9f75844SAndroid Build Coastguard Worker                  const SocketAddress& internal_addr,
188*d9f75844SAndroid Build Coastguard Worker                  SocketServer* external,
189*d9f75844SAndroid Build Coastguard Worker                  const SocketAddress external_addrs[4]) {
190*d9f75844SAndroid Build Coastguard Worker   TestRecv(internal, internal_addr, external, external_addrs, NAT_OPEN_CONE,
191*d9f75844SAndroid Build Coastguard Worker            false, false);
192*d9f75844SAndroid Build Coastguard Worker   TestRecv(internal, internal_addr, external, external_addrs,
193*d9f75844SAndroid Build Coastguard Worker            NAT_ADDR_RESTRICTED, true, false);
194*d9f75844SAndroid Build Coastguard Worker   TestRecv(internal, internal_addr, external, external_addrs,
195*d9f75844SAndroid Build Coastguard Worker            NAT_PORT_RESTRICTED, true, true);
196*d9f75844SAndroid Build Coastguard Worker   TestRecv(internal, internal_addr, external, external_addrs, NAT_SYMMETRIC,
197*d9f75844SAndroid Build Coastguard Worker            true, true);
198*d9f75844SAndroid Build Coastguard Worker }
199*d9f75844SAndroid Build Coastguard Worker 
TestConnectivity(const SocketAddress & src,const IPAddress & dst)200*d9f75844SAndroid Build Coastguard Worker bool TestConnectivity(const SocketAddress& src, const IPAddress& dst) {
201*d9f75844SAndroid Build Coastguard Worker   // The physical NAT tests require connectivity to the selected ip from the
202*d9f75844SAndroid Build Coastguard Worker   // internal address used for the NAT. Things like firewalls can break that, so
203*d9f75844SAndroid Build Coastguard Worker   // check to see if it's worth even trying with this ip.
204*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<PhysicalSocketServer> pss(new PhysicalSocketServer());
205*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<Socket> client(pss->CreateSocket(src.family(), SOCK_DGRAM));
206*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<Socket> server(pss->CreateSocket(src.family(), SOCK_DGRAM));
207*d9f75844SAndroid Build Coastguard Worker   if (client->Bind(SocketAddress(src.ipaddr(), 0)) != 0 ||
208*d9f75844SAndroid Build Coastguard Worker       server->Bind(SocketAddress(dst, 0)) != 0) {
209*d9f75844SAndroid Build Coastguard Worker     return false;
210*d9f75844SAndroid Build Coastguard Worker   }
211*d9f75844SAndroid Build Coastguard Worker   const char* buf = "hello other socket";
212*d9f75844SAndroid Build Coastguard Worker   size_t len = strlen(buf);
213*d9f75844SAndroid Build Coastguard Worker   int sent = client->SendTo(buf, len, server->GetLocalAddress());
214*d9f75844SAndroid Build Coastguard Worker   SocketAddress addr;
215*d9f75844SAndroid Build Coastguard Worker   const size_t kRecvBufSize = 64;
216*d9f75844SAndroid Build Coastguard Worker   char recvbuf[kRecvBufSize];
217*d9f75844SAndroid Build Coastguard Worker   Thread::Current()->SleepMs(100);
218*d9f75844SAndroid Build Coastguard Worker   int received = server->RecvFrom(recvbuf, kRecvBufSize, &addr, nullptr);
219*d9f75844SAndroid Build Coastguard Worker   return received == sent && ::memcmp(buf, recvbuf, len) == 0;
220*d9f75844SAndroid Build Coastguard Worker }
221*d9f75844SAndroid Build Coastguard Worker 
TestPhysicalInternal(const SocketAddress & int_addr)222*d9f75844SAndroid Build Coastguard Worker void TestPhysicalInternal(const SocketAddress& int_addr) {
223*d9f75844SAndroid Build Coastguard Worker   webrtc::test::ScopedKeyValueConfig field_trials;
224*d9f75844SAndroid Build Coastguard Worker   rtc::AutoThread main_thread;
225*d9f75844SAndroid Build Coastguard Worker   PhysicalSocketServer socket_server;
226*d9f75844SAndroid Build Coastguard Worker   BasicNetworkManager network_manager(nullptr, &socket_server, &field_trials);
227*d9f75844SAndroid Build Coastguard Worker   network_manager.StartUpdating();
228*d9f75844SAndroid Build Coastguard Worker   // Process pending messages so the network list is updated.
229*d9f75844SAndroid Build Coastguard Worker   Thread::Current()->ProcessMessages(0);
230*d9f75844SAndroid Build Coastguard Worker 
231*d9f75844SAndroid Build Coastguard Worker   std::vector<const Network*> networks = network_manager.GetNetworks();
232*d9f75844SAndroid Build Coastguard Worker   networks.erase(std::remove_if(networks.begin(), networks.end(),
233*d9f75844SAndroid Build Coastguard Worker                                 [](const rtc::Network* network) {
234*d9f75844SAndroid Build Coastguard Worker                                   return rtc::kDefaultNetworkIgnoreMask &
235*d9f75844SAndroid Build Coastguard Worker                                          network->type();
236*d9f75844SAndroid Build Coastguard Worker                                 }),
237*d9f75844SAndroid Build Coastguard Worker                  networks.end());
238*d9f75844SAndroid Build Coastguard Worker   if (networks.empty()) {
239*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << "Not enough network adapters for test.";
240*d9f75844SAndroid Build Coastguard Worker     return;
241*d9f75844SAndroid Build Coastguard Worker   }
242*d9f75844SAndroid Build Coastguard Worker 
243*d9f75844SAndroid Build Coastguard Worker   SocketAddress ext_addr1(int_addr);
244*d9f75844SAndroid Build Coastguard Worker   SocketAddress ext_addr2;
245*d9f75844SAndroid Build Coastguard Worker   // Find an available IP with matching family. The test breaks if int_addr
246*d9f75844SAndroid Build Coastguard Worker   // can't talk to ip, so check for connectivity as well.
247*d9f75844SAndroid Build Coastguard Worker   for (const Network* const network : networks) {
248*d9f75844SAndroid Build Coastguard Worker     const IPAddress& ip = network->GetBestIP();
249*d9f75844SAndroid Build Coastguard Worker     if (ip.family() == int_addr.family() && TestConnectivity(int_addr, ip)) {
250*d9f75844SAndroid Build Coastguard Worker       ext_addr2.SetIP(ip);
251*d9f75844SAndroid Build Coastguard Worker       break;
252*d9f75844SAndroid Build Coastguard Worker     }
253*d9f75844SAndroid Build Coastguard Worker   }
254*d9f75844SAndroid Build Coastguard Worker   if (ext_addr2.IsNil()) {
255*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << "No available IP of same family as "
256*d9f75844SAndroid Build Coastguard Worker                         << int_addr.ToString();
257*d9f75844SAndroid Build Coastguard Worker     return;
258*d9f75844SAndroid Build Coastguard Worker   }
259*d9f75844SAndroid Build Coastguard Worker 
260*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << "selected ip " << ext_addr2.ipaddr().ToString();
261*d9f75844SAndroid Build Coastguard Worker 
262*d9f75844SAndroid Build Coastguard Worker   SocketAddress ext_addrs[4] = {
263*d9f75844SAndroid Build Coastguard Worker       SocketAddress(ext_addr1), SocketAddress(ext_addr2),
264*d9f75844SAndroid Build Coastguard Worker       SocketAddress(ext_addr1), SocketAddress(ext_addr2)};
265*d9f75844SAndroid Build Coastguard Worker 
266*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<PhysicalSocketServer> int_pss(new PhysicalSocketServer());
267*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<PhysicalSocketServer> ext_pss(new PhysicalSocketServer());
268*d9f75844SAndroid Build Coastguard Worker 
269*d9f75844SAndroid Build Coastguard Worker   TestBindings(int_pss.get(), int_addr, ext_pss.get(), ext_addrs);
270*d9f75844SAndroid Build Coastguard Worker   TestFilters(int_pss.get(), int_addr, ext_pss.get(), ext_addrs);
271*d9f75844SAndroid Build Coastguard Worker }
272*d9f75844SAndroid Build Coastguard Worker 
TEST(NatTest,TestPhysicalIPv4)273*d9f75844SAndroid Build Coastguard Worker TEST(NatTest, TestPhysicalIPv4) {
274*d9f75844SAndroid Build Coastguard Worker   TestPhysicalInternal(SocketAddress("127.0.0.1", 0));
275*d9f75844SAndroid Build Coastguard Worker }
276*d9f75844SAndroid Build Coastguard Worker 
TEST(NatTest,TestPhysicalIPv6)277*d9f75844SAndroid Build Coastguard Worker TEST(NatTest, TestPhysicalIPv6) {
278*d9f75844SAndroid Build Coastguard Worker   if (HasIPv6Enabled()) {
279*d9f75844SAndroid Build Coastguard Worker     TestPhysicalInternal(SocketAddress("::1", 0));
280*d9f75844SAndroid Build Coastguard Worker   } else {
281*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << "No IPv6, skipping";
282*d9f75844SAndroid Build Coastguard Worker   }
283*d9f75844SAndroid Build Coastguard Worker }
284*d9f75844SAndroid Build Coastguard Worker 
285*d9f75844SAndroid Build Coastguard Worker namespace {
286*d9f75844SAndroid Build Coastguard Worker 
287*d9f75844SAndroid Build Coastguard Worker class TestVirtualSocketServer : public VirtualSocketServer {
288*d9f75844SAndroid Build Coastguard Worker  public:
289*d9f75844SAndroid Build Coastguard Worker   // Expose this publicly
GetNextIP(int af)290*d9f75844SAndroid Build Coastguard Worker   IPAddress GetNextIP(int af) { return VirtualSocketServer::GetNextIP(af); }
291*d9f75844SAndroid Build Coastguard Worker };
292*d9f75844SAndroid Build Coastguard Worker 
293*d9f75844SAndroid Build Coastguard Worker }  // namespace
294*d9f75844SAndroid Build Coastguard Worker 
TestVirtualInternal(int family)295*d9f75844SAndroid Build Coastguard Worker void TestVirtualInternal(int family) {
296*d9f75844SAndroid Build Coastguard Worker   rtc::AutoThread main_thread;
297*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<TestVirtualSocketServer> int_vss(
298*d9f75844SAndroid Build Coastguard Worker       new TestVirtualSocketServer());
299*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<TestVirtualSocketServer> ext_vss(
300*d9f75844SAndroid Build Coastguard Worker       new TestVirtualSocketServer());
301*d9f75844SAndroid Build Coastguard Worker 
302*d9f75844SAndroid Build Coastguard Worker   SocketAddress int_addr;
303*d9f75844SAndroid Build Coastguard Worker   SocketAddress ext_addrs[4];
304*d9f75844SAndroid Build Coastguard Worker   int_addr.SetIP(int_vss->GetNextIP(family));
305*d9f75844SAndroid Build Coastguard Worker   ext_addrs[0].SetIP(ext_vss->GetNextIP(int_addr.family()));
306*d9f75844SAndroid Build Coastguard Worker   ext_addrs[1].SetIP(ext_vss->GetNextIP(int_addr.family()));
307*d9f75844SAndroid Build Coastguard Worker   ext_addrs[2].SetIP(ext_addrs[0].ipaddr());
308*d9f75844SAndroid Build Coastguard Worker   ext_addrs[3].SetIP(ext_addrs[1].ipaddr());
309*d9f75844SAndroid Build Coastguard Worker 
310*d9f75844SAndroid Build Coastguard Worker   TestBindings(int_vss.get(), int_addr, ext_vss.get(), ext_addrs);
311*d9f75844SAndroid Build Coastguard Worker   TestFilters(int_vss.get(), int_addr, ext_vss.get(), ext_addrs);
312*d9f75844SAndroid Build Coastguard Worker }
313*d9f75844SAndroid Build Coastguard Worker 
TEST(NatTest,TestVirtualIPv4)314*d9f75844SAndroid Build Coastguard Worker TEST(NatTest, TestVirtualIPv4) {
315*d9f75844SAndroid Build Coastguard Worker   TestVirtualInternal(AF_INET);
316*d9f75844SAndroid Build Coastguard Worker }
317*d9f75844SAndroid Build Coastguard Worker 
TEST(NatTest,TestVirtualIPv6)318*d9f75844SAndroid Build Coastguard Worker TEST(NatTest, TestVirtualIPv6) {
319*d9f75844SAndroid Build Coastguard Worker   if (HasIPv6Enabled()) {
320*d9f75844SAndroid Build Coastguard Worker     TestVirtualInternal(AF_INET6);
321*d9f75844SAndroid Build Coastguard Worker   } else {
322*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << "No IPv6, skipping";
323*d9f75844SAndroid Build Coastguard Worker   }
324*d9f75844SAndroid Build Coastguard Worker }
325*d9f75844SAndroid Build Coastguard Worker 
326*d9f75844SAndroid Build Coastguard Worker class NatTcpTest : public ::testing::Test, public sigslot::has_slots<> {
327*d9f75844SAndroid Build Coastguard Worker  public:
NatTcpTest()328*d9f75844SAndroid Build Coastguard Worker   NatTcpTest()
329*d9f75844SAndroid Build Coastguard Worker       : int_addr_("192.168.0.1", 0),
330*d9f75844SAndroid Build Coastguard Worker         ext_addr_("10.0.0.1", 0),
331*d9f75844SAndroid Build Coastguard Worker         connected_(false),
332*d9f75844SAndroid Build Coastguard Worker         int_vss_(new TestVirtualSocketServer()),
333*d9f75844SAndroid Build Coastguard Worker         ext_vss_(new TestVirtualSocketServer()),
334*d9f75844SAndroid Build Coastguard Worker         int_thread_(new Thread(int_vss_.get())),
335*d9f75844SAndroid Build Coastguard Worker         ext_thread_(new Thread(ext_vss_.get())),
336*d9f75844SAndroid Build Coastguard Worker         nat_(new NATServer(NAT_OPEN_CONE,
337*d9f75844SAndroid Build Coastguard Worker                            int_vss_.get(),
338*d9f75844SAndroid Build Coastguard Worker                            int_addr_,
339*d9f75844SAndroid Build Coastguard Worker                            int_addr_,
340*d9f75844SAndroid Build Coastguard Worker                            ext_vss_.get(),
341*d9f75844SAndroid Build Coastguard Worker                            ext_addr_)),
342*d9f75844SAndroid Build Coastguard Worker         natsf_(new NATSocketFactory(int_vss_.get(),
343*d9f75844SAndroid Build Coastguard Worker                                     nat_->internal_udp_address(),
344*d9f75844SAndroid Build Coastguard Worker                                     nat_->internal_tcp_address())) {
345*d9f75844SAndroid Build Coastguard Worker     int_thread_->Start();
346*d9f75844SAndroid Build Coastguard Worker     ext_thread_->Start();
347*d9f75844SAndroid Build Coastguard Worker   }
348*d9f75844SAndroid Build Coastguard Worker 
OnConnectEvent(Socket * socket)349*d9f75844SAndroid Build Coastguard Worker   void OnConnectEvent(Socket* socket) { connected_ = true; }
350*d9f75844SAndroid Build Coastguard Worker 
OnAcceptEvent(Socket * socket)351*d9f75844SAndroid Build Coastguard Worker   void OnAcceptEvent(Socket* socket) {
352*d9f75844SAndroid Build Coastguard Worker     accepted_.reset(server_->Accept(nullptr));
353*d9f75844SAndroid Build Coastguard Worker   }
354*d9f75844SAndroid Build Coastguard Worker 
OnCloseEvent(Socket * socket,int error)355*d9f75844SAndroid Build Coastguard Worker   void OnCloseEvent(Socket* socket, int error) {}
356*d9f75844SAndroid Build Coastguard Worker 
ConnectEvents()357*d9f75844SAndroid Build Coastguard Worker   void ConnectEvents() {
358*d9f75844SAndroid Build Coastguard Worker     server_->SignalReadEvent.connect(this, &NatTcpTest::OnAcceptEvent);
359*d9f75844SAndroid Build Coastguard Worker     client_->SignalConnectEvent.connect(this, &NatTcpTest::OnConnectEvent);
360*d9f75844SAndroid Build Coastguard Worker   }
361*d9f75844SAndroid Build Coastguard Worker 
362*d9f75844SAndroid Build Coastguard Worker   SocketAddress int_addr_;
363*d9f75844SAndroid Build Coastguard Worker   SocketAddress ext_addr_;
364*d9f75844SAndroid Build Coastguard Worker   bool connected_;
365*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<TestVirtualSocketServer> int_vss_;
366*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<TestVirtualSocketServer> ext_vss_;
367*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<Thread> int_thread_;
368*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<Thread> ext_thread_;
369*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<NATServer> nat_;
370*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<NATSocketFactory> natsf_;
371*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<Socket> client_;
372*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<Socket> server_;
373*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<Socket> accepted_;
374*d9f75844SAndroid Build Coastguard Worker };
375*d9f75844SAndroid Build Coastguard Worker 
TEST_F(NatTcpTest,DISABLED_TestConnectOut)376*d9f75844SAndroid Build Coastguard Worker TEST_F(NatTcpTest, DISABLED_TestConnectOut) {
377*d9f75844SAndroid Build Coastguard Worker   server_.reset(ext_vss_->CreateSocket(AF_INET, SOCK_STREAM));
378*d9f75844SAndroid Build Coastguard Worker   server_->Bind(ext_addr_);
379*d9f75844SAndroid Build Coastguard Worker   server_->Listen(5);
380*d9f75844SAndroid Build Coastguard Worker 
381*d9f75844SAndroid Build Coastguard Worker   client_.reset(natsf_->CreateSocket(AF_INET, SOCK_STREAM));
382*d9f75844SAndroid Build Coastguard Worker   EXPECT_GE(0, client_->Bind(int_addr_));
383*d9f75844SAndroid Build Coastguard Worker   EXPECT_GE(0, client_->Connect(server_->GetLocalAddress()));
384*d9f75844SAndroid Build Coastguard Worker 
385*d9f75844SAndroid Build Coastguard Worker   ConnectEvents();
386*d9f75844SAndroid Build Coastguard Worker 
387*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE_WAIT(connected_, 1000);
388*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(client_->GetRemoteAddress(), server_->GetLocalAddress());
389*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(accepted_->GetRemoteAddress().ipaddr(), ext_addr_.ipaddr());
390*d9f75844SAndroid Build Coastguard Worker 
391*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<rtc::TestClient> in(CreateTCPTestClient(client_.release()));
392*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<rtc::TestClient> out(
393*d9f75844SAndroid Build Coastguard Worker       CreateTCPTestClient(accepted_.release()));
394*d9f75844SAndroid Build Coastguard Worker 
395*d9f75844SAndroid Build Coastguard Worker   const char* buf = "test_packet";
396*d9f75844SAndroid Build Coastguard Worker   size_t len = strlen(buf);
397*d9f75844SAndroid Build Coastguard Worker 
398*d9f75844SAndroid Build Coastguard Worker   in->Send(buf, len);
399*d9f75844SAndroid Build Coastguard Worker   SocketAddress trans_addr;
400*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(out->CheckNextPacket(buf, len, &trans_addr));
401*d9f75844SAndroid Build Coastguard Worker 
402*d9f75844SAndroid Build Coastguard Worker   out->Send(buf, len);
403*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(in->CheckNextPacket(buf, len, &trans_addr));
404*d9f75844SAndroid Build Coastguard Worker }
405*d9f75844SAndroid Build Coastguard Worker 
406*d9f75844SAndroid Build Coastguard Worker }  // namespace
407*d9f75844SAndroid Build Coastguard Worker }  // namespace rtc
408