blob: ee944272b70e5289b80fa5a081e9e06747e9a1bc [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001/*
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
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -080011#include <algorithm>
jbauch555604a2016-04-26 03:13:22 -070012#include <memory>
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000013#include <string>
14
Karl Wiberg918f50c2018-07-05 11:40:33 +020015#include "absl/memory/memory.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020016#include "rtc_base/asynctcpsocket.h"
17#include "rtc_base/gunit.h"
18#include "rtc_base/logging.h"
19#include "rtc_base/natserver.h"
20#include "rtc_base/natsocketfactory.h"
21#include "rtc_base/nethelpers.h"
22#include "rtc_base/network.h"
23#include "rtc_base/physicalsocketserver.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020024#include "rtc_base/testclient.h"
25#include "rtc_base/virtualsocketserver.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000026
27using namespace rtc;
28
Yves Gerey665174f2018-06-19 15:03:05 +020029bool CheckReceive(TestClient* client,
30 bool should_receive,
31 const char* buf,
32 size_t size) {
33 return (should_receive) ? client->CheckNextPacket(buf, size, 0)
34 : client->CheckNoPacket();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000035}
36
Yves Gerey665174f2018-06-19 15:03:05 +020037TestClient* CreateTestClient(SocketFactory* factory,
38 const SocketAddress& local_addr) {
nisse32f25052017-05-08 01:57:18 -070039 return new TestClient(
Karl Wiberg918f50c2018-07-05 11:40:33 +020040 absl::WrapUnique(AsyncUDPSocket::Create(factory, local_addr)));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000041}
42
deadbeefc5d0d952015-07-16 10:22:21 -070043TestClient* CreateTCPTestClient(AsyncSocket* socket) {
Karl Wiberg918f50c2018-07-05 11:40:33 +020044 return new TestClient(absl::make_unique<AsyncTCPSocket>(socket, false));
deadbeefc5d0d952015-07-16 10:22:21 -070045}
46
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000047// Tests that when sending from internal_addr to external_addrs through the
48// NAT type specified by nat_type, all external addrs receive the sent packet
49// and, if exp_same is true, all use the same mapped-address on the NAT.
Yves Gerey665174f2018-06-19 15:03:05 +020050void TestSend(SocketServer* internal,
51 const SocketAddress& internal_addr,
52 SocketServer* external,
53 const SocketAddress external_addrs[4],
54 NATType nat_type,
55 bool exp_same) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000056 Thread th_int(internal);
57 Thread th_ext(external);
58
59 SocketAddress server_addr = internal_addr;
60 server_addr.SetPort(0); // Auto-select a port
deadbeefc5d0d952015-07-16 10:22:21 -070061 NATServer* nat = new NATServer(nat_type, internal, server_addr, server_addr,
62 external, external_addrs[0]);
Yves Gerey665174f2018-06-19 15:03:05 +020063 NATSocketFactory* natsf = new NATSocketFactory(
64 internal, nat->internal_udp_address(), nat->internal_tcp_address());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000065
66 TestClient* in = CreateTestClient(natsf, internal_addr);
67 TestClient* out[4];
68 for (int i = 0; i < 4; i++)
69 out[i] = CreateTestClient(external, external_addrs[i]);
70
71 th_int.Start();
72 th_ext.Start();
73
74 const char* buf = "filter_test";
75 size_t len = strlen(buf);
76
77 in->SendTo(buf, len, out[0]->address());
78 SocketAddress trans_addr;
79 EXPECT_TRUE(out[0]->CheckNextPacket(buf, len, &trans_addr));
80
81 for (int i = 1; i < 4; i++) {
82 in->SendTo(buf, len, out[i]->address());
83 SocketAddress trans_addr2;
84 EXPECT_TRUE(out[i]->CheckNextPacket(buf, len, &trans_addr2));
85 bool are_same = (trans_addr == trans_addr2);
86 ASSERT_EQ(are_same, exp_same) << "same translated address";
87 ASSERT_NE(AF_UNSPEC, trans_addr.family());
88 ASSERT_NE(AF_UNSPEC, trans_addr2.family());
89 }
90
91 th_int.Stop();
92 th_ext.Stop();
93
94 delete nat;
95 delete natsf;
96 delete in;
97 for (int i = 0; i < 4; i++)
98 delete out[i];
99}
100
101// Tests that when sending from external_addrs to internal_addr, the packet
102// is delivered according to the specified filter_ip and filter_port rules.
Yves Gerey665174f2018-06-19 15:03:05 +0200103void TestRecv(SocketServer* internal,
104 const SocketAddress& internal_addr,
105 SocketServer* external,
106 const SocketAddress external_addrs[4],
107 NATType nat_type,
108 bool filter_ip,
109 bool filter_port) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000110 Thread th_int(internal);
111 Thread th_ext(external);
112
113 SocketAddress server_addr = internal_addr;
114 server_addr.SetPort(0); // Auto-select a port
deadbeefc5d0d952015-07-16 10:22:21 -0700115 NATServer* nat = new NATServer(nat_type, internal, server_addr, server_addr,
116 external, external_addrs[0]);
Yves Gerey665174f2018-06-19 15:03:05 +0200117 NATSocketFactory* natsf = new NATSocketFactory(
118 internal, nat->internal_udp_address(), nat->internal_tcp_address());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000119
120 TestClient* in = CreateTestClient(natsf, internal_addr);
121 TestClient* out[4];
122 for (int i = 0; i < 4; i++)
123 out[i] = CreateTestClient(external, external_addrs[i]);
124
125 th_int.Start();
126 th_ext.Start();
127
128 const char* buf = "filter_test";
129 size_t len = strlen(buf);
130
131 in->SendTo(buf, len, out[0]->address());
132 SocketAddress trans_addr;
133 EXPECT_TRUE(out[0]->CheckNextPacket(buf, len, &trans_addr));
134
135 out[1]->SendTo(buf, len, trans_addr);
136 EXPECT_TRUE(CheckReceive(in, !filter_ip, buf, len));
137
138 out[2]->SendTo(buf, len, trans_addr);
139 EXPECT_TRUE(CheckReceive(in, !filter_port, buf, len));
140
141 out[3]->SendTo(buf, len, trans_addr);
142 EXPECT_TRUE(CheckReceive(in, !filter_ip && !filter_port, buf, len));
143
144 th_int.Stop();
145 th_ext.Stop();
146
147 delete nat;
148 delete natsf;
149 delete in;
150 for (int i = 0; i < 4; i++)
151 delete out[i];
152}
153
154// Tests that NATServer allocates bindings properly.
Yves Gerey665174f2018-06-19 15:03:05 +0200155void TestBindings(SocketServer* internal,
156 const SocketAddress& internal_addr,
157 SocketServer* external,
158 const SocketAddress external_addrs[4]) {
159 TestSend(internal, internal_addr, external, external_addrs, NAT_OPEN_CONE,
160 true);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000161 TestSend(internal, internal_addr, external, external_addrs,
162 NAT_ADDR_RESTRICTED, true);
163 TestSend(internal, internal_addr, external, external_addrs,
164 NAT_PORT_RESTRICTED, true);
Yves Gerey665174f2018-06-19 15:03:05 +0200165 TestSend(internal, internal_addr, external, external_addrs, NAT_SYMMETRIC,
166 false);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000167}
168
169// Tests that NATServer filters packets properly.
Yves Gerey665174f2018-06-19 15:03:05 +0200170void TestFilters(SocketServer* internal,
171 const SocketAddress& internal_addr,
172 SocketServer* external,
173 const SocketAddress external_addrs[4]) {
174 TestRecv(internal, internal_addr, external, external_addrs, NAT_OPEN_CONE,
175 false, false);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000176 TestRecv(internal, internal_addr, external, external_addrs,
177 NAT_ADDR_RESTRICTED, true, false);
178 TestRecv(internal, internal_addr, external, external_addrs,
179 NAT_PORT_RESTRICTED, true, true);
Yves Gerey665174f2018-06-19 15:03:05 +0200180 TestRecv(internal, internal_addr, external, external_addrs, NAT_SYMMETRIC,
181 true, true);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000182}
183
184bool TestConnectivity(const SocketAddress& src, const IPAddress& dst) {
185 // The physical NAT tests require connectivity to the selected ip from the
186 // internal address used for the NAT. Things like firewalls can break that, so
187 // check to see if it's worth even trying with this ip.
jbauch555604a2016-04-26 03:13:22 -0700188 std::unique_ptr<PhysicalSocketServer> pss(new PhysicalSocketServer());
189 std::unique_ptr<AsyncSocket> client(
190 pss->CreateAsyncSocket(src.family(), SOCK_DGRAM));
191 std::unique_ptr<AsyncSocket> server(
192 pss->CreateAsyncSocket(src.family(), SOCK_DGRAM));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000193 if (client->Bind(SocketAddress(src.ipaddr(), 0)) != 0 ||
194 server->Bind(SocketAddress(dst, 0)) != 0) {
195 return false;
196 }
197 const char* buf = "hello other socket";
198 size_t len = strlen(buf);
199 int sent = client->SendTo(buf, len, server->GetLocalAddress());
200 SocketAddress addr;
201 const size_t kRecvBufSize = 64;
202 char recvbuf[kRecvBufSize];
203 Thread::Current()->SleepMs(100);
Stefan Holmer9131efd2016-05-23 18:19:26 +0200204 int received = server->RecvFrom(recvbuf, kRecvBufSize, &addr, nullptr);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000205 return received == sent && ::memcmp(buf, recvbuf, len) == 0;
206}
207
208void TestPhysicalInternal(const SocketAddress& int_addr) {
209 BasicNetworkManager network_manager;
210 network_manager.set_ipv6_enabled(true);
211 network_manager.StartUpdating();
212 // Process pending messages so the network list is updated.
213 Thread::Current()->ProcessMessages(0);
214
215 std::vector<Network*> networks;
216 network_manager.GetNetworks(&networks);
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800217 networks.erase(std::remove_if(networks.begin(), networks.end(),
218 [](rtc::Network* network) {
219 return rtc::kDefaultNetworkIgnoreMask &
220 network->type();
221 }),
222 networks.end());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000223 if (networks.empty()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100224 RTC_LOG(LS_WARNING) << "Not enough network adapters for test.";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000225 return;
226 }
227
228 SocketAddress ext_addr1(int_addr);
229 SocketAddress ext_addr2;
230 // Find an available IP with matching family. The test breaks if int_addr
231 // can't talk to ip, so check for connectivity as well.
232 for (std::vector<Network*>::iterator it = networks.begin();
Yves Gerey665174f2018-06-19 15:03:05 +0200233 it != networks.end(); ++it) {
guoweis@webrtc.org369a6372014-09-17 22:37:29 +0000234 const IPAddress& ip = (*it)->GetBestIP();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000235 if (ip.family() == int_addr.family() && TestConnectivity(int_addr, ip)) {
236 ext_addr2.SetIP(ip);
237 break;
238 }
239 }
240 if (ext_addr2.IsNil()) {
Jonas Olssonabbe8412018-04-03 13:40:05 +0200241 RTC_LOG(LS_WARNING) << "No available IP of same family as "
242 << int_addr.ToString();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000243 return;
244 }
245
Jonas Olssonabbe8412018-04-03 13:40:05 +0200246 RTC_LOG(LS_INFO) << "selected ip " << ext_addr2.ipaddr().ToString();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000247
248 SocketAddress ext_addrs[4] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200249 SocketAddress(ext_addr1), SocketAddress(ext_addr2),
250 SocketAddress(ext_addr1), SocketAddress(ext_addr2)};
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000251
jbauch555604a2016-04-26 03:13:22 -0700252 std::unique_ptr<PhysicalSocketServer> int_pss(new PhysicalSocketServer());
253 std::unique_ptr<PhysicalSocketServer> ext_pss(new PhysicalSocketServer());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000254
255 TestBindings(int_pss.get(), int_addr, ext_pss.get(), ext_addrs);
256 TestFilters(int_pss.get(), int_addr, ext_pss.get(), ext_addrs);
257}
258
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000259TEST(NatTest, TestPhysicalIPv4) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000260 TestPhysicalInternal(SocketAddress("127.0.0.1", 0));
261}
262
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000263TEST(NatTest, TestPhysicalIPv6) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000264 if (HasIPv6Enabled()) {
265 TestPhysicalInternal(SocketAddress("::1", 0));
266 } else {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100267 RTC_LOG(LS_WARNING) << "No IPv6, skipping";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000268 }
269}
270
Guo-wei Shiehbe508a12015-04-06 12:48:47 -0700271namespace {
272
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000273class TestVirtualSocketServer : public VirtualSocketServer {
274 public:
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000275 // Expose this publicly
276 IPAddress GetNextIP(int af) { return VirtualSocketServer::GetNextIP(af); }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000277};
278
Guo-wei Shiehbe508a12015-04-06 12:48:47 -0700279} // namespace
280
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000281void TestVirtualInternal(int family) {
jbauch555604a2016-04-26 03:13:22 -0700282 std::unique_ptr<TestVirtualSocketServer> int_vss(
deadbeef98e186c2017-05-16 18:00:06 -0700283 new TestVirtualSocketServer());
jbauch555604a2016-04-26 03:13:22 -0700284 std::unique_ptr<TestVirtualSocketServer> ext_vss(
deadbeef98e186c2017-05-16 18:00:06 -0700285 new TestVirtualSocketServer());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000286
287 SocketAddress int_addr;
288 SocketAddress ext_addrs[4];
289 int_addr.SetIP(int_vss->GetNextIP(family));
290 ext_addrs[0].SetIP(ext_vss->GetNextIP(int_addr.family()));
291 ext_addrs[1].SetIP(ext_vss->GetNextIP(int_addr.family()));
292 ext_addrs[2].SetIP(ext_addrs[0].ipaddr());
293 ext_addrs[3].SetIP(ext_addrs[1].ipaddr());
294
295 TestBindings(int_vss.get(), int_addr, ext_vss.get(), ext_addrs);
296 TestFilters(int_vss.get(), int_addr, ext_vss.get(), ext_addrs);
297}
298
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000299TEST(NatTest, TestVirtualIPv4) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000300 TestVirtualInternal(AF_INET);
301}
302
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000303TEST(NatTest, TestVirtualIPv6) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000304 if (HasIPv6Enabled()) {
305 TestVirtualInternal(AF_INET6);
306 } else {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100307 RTC_LOG(LS_WARNING) << "No IPv6, skipping";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000308 }
309}
310
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000311class NatTcpTest : public testing::Test, public sigslot::has_slots<> {
312 public:
deadbeefc5d0d952015-07-16 10:22:21 -0700313 NatTcpTest()
314 : int_addr_("192.168.0.1", 0),
315 ext_addr_("10.0.0.1", 0),
316 connected_(false),
deadbeef98e186c2017-05-16 18:00:06 -0700317 int_vss_(new TestVirtualSocketServer()),
318 ext_vss_(new TestVirtualSocketServer()),
deadbeefc5d0d952015-07-16 10:22:21 -0700319 int_thread_(new Thread(int_vss_.get())),
320 ext_thread_(new Thread(ext_vss_.get())),
deadbeef98e186c2017-05-16 18:00:06 -0700321 nat_(new NATServer(NAT_OPEN_CONE,
322 int_vss_.get(),
323 int_addr_,
324 int_addr_,
325 ext_vss_.get(),
326 ext_addr_)),
deadbeefc5d0d952015-07-16 10:22:21 -0700327 natsf_(new NATSocketFactory(int_vss_.get(),
328 nat_->internal_udp_address(),
329 nat_->internal_tcp_address())) {
330 int_thread_->Start();
331 ext_thread_->Start();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000332 }
deadbeefc5d0d952015-07-16 10:22:21 -0700333
Yves Gerey665174f2018-06-19 15:03:05 +0200334 void OnConnectEvent(AsyncSocket* socket) { connected_ = true; }
deadbeefc5d0d952015-07-16 10:22:21 -0700335
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000336 void OnAcceptEvent(AsyncSocket* socket) {
deadbeef37f5ecf2017-02-27 14:06:41 -0800337 accepted_.reset(server_->Accept(nullptr));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000338 }
deadbeefc5d0d952015-07-16 10:22:21 -0700339
Yves Gerey665174f2018-06-19 15:03:05 +0200340 void OnCloseEvent(AsyncSocket* socket, int error) {}
deadbeefc5d0d952015-07-16 10:22:21 -0700341
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000342 void ConnectEvents() {
343 server_->SignalReadEvent.connect(this, &NatTcpTest::OnAcceptEvent);
344 client_->SignalConnectEvent.connect(this, &NatTcpTest::OnConnectEvent);
345 }
deadbeefc5d0d952015-07-16 10:22:21 -0700346
347 SocketAddress int_addr_;
348 SocketAddress ext_addr_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000349 bool connected_;
jbauch555604a2016-04-26 03:13:22 -0700350 std::unique_ptr<TestVirtualSocketServer> int_vss_;
351 std::unique_ptr<TestVirtualSocketServer> ext_vss_;
352 std::unique_ptr<Thread> int_thread_;
353 std::unique_ptr<Thread> ext_thread_;
354 std::unique_ptr<NATServer> nat_;
355 std::unique_ptr<NATSocketFactory> natsf_;
356 std::unique_ptr<AsyncSocket> client_;
357 std::unique_ptr<AsyncSocket> server_;
358 std::unique_ptr<AsyncSocket> accepted_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000359};
360
magjed65eb1c32015-07-22 06:28:26 -0700361TEST_F(NatTcpTest, DISABLED_TestConnectOut) {
Steve Anton31e5bf52018-05-07 10:42:55 -0700362 server_.reset(ext_vss_->CreateAsyncSocket(AF_INET, SOCK_STREAM));
deadbeefc5d0d952015-07-16 10:22:21 -0700363 server_->Bind(ext_addr_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000364 server_->Listen(5);
365
Steve Anton31e5bf52018-05-07 10:42:55 -0700366 client_.reset(natsf_->CreateAsyncSocket(AF_INET, SOCK_STREAM));
deadbeefc5d0d952015-07-16 10:22:21 -0700367 EXPECT_GE(0, client_->Bind(int_addr_));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000368 EXPECT_GE(0, client_->Connect(server_->GetLocalAddress()));
369
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000370 ConnectEvents();
371
372 EXPECT_TRUE_WAIT(connected_, 1000);
373 EXPECT_EQ(client_->GetRemoteAddress(), server_->GetLocalAddress());
deadbeefc5d0d952015-07-16 10:22:21 -0700374 EXPECT_EQ(accepted_->GetRemoteAddress().ipaddr(), ext_addr_.ipaddr());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000375
jbauch555604a2016-04-26 03:13:22 -0700376 std::unique_ptr<rtc::TestClient> in(CreateTCPTestClient(client_.release()));
377 std::unique_ptr<rtc::TestClient> out(
deadbeefc5d0d952015-07-16 10:22:21 -0700378 CreateTCPTestClient(accepted_.release()));
379
380 const char* buf = "test_packet";
381 size_t len = strlen(buf);
382
383 in->Send(buf, len);
384 SocketAddress trans_addr;
385 EXPECT_TRUE(out->CheckNextPacket(buf, len, &trans_addr));
386
387 out->Send(buf, len);
388 EXPECT_TRUE(in->CheckNextPacket(buf, len, &trans_addr));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000389}
deadbeefc5d0d952015-07-16 10:22:21 -0700390// #endif