blob: 68f0f1ca2952de42c9fcc2062fa3f99535d3e21b [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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020015#include "rtc_base/asynctcpsocket.h"
16#include "rtc_base/gunit.h"
17#include "rtc_base/logging.h"
18#include "rtc_base/natserver.h"
19#include "rtc_base/natsocketfactory.h"
20#include "rtc_base/nethelpers.h"
21#include "rtc_base/network.h"
22#include "rtc_base/physicalsocketserver.h"
23#include "rtc_base/ptr_util.h"
24#include "rtc_base/testclient.h"
25#include "rtc_base/virtualsocketserver.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000026
27using namespace rtc;
28
29bool CheckReceive(
30 TestClient* client, bool should_receive, const char* buf, size_t size) {
31 return (should_receive) ?
32 client->CheckNextPacket(buf, size, 0) :
33 client->CheckNoPacket();
34}
35
36TestClient* CreateTestClient(
37 SocketFactory* factory, const SocketAddress& local_addr) {
nisse32f25052017-05-08 01:57:18 -070038 return new TestClient(
39 WrapUnique(AsyncUDPSocket::Create(factory, local_addr)));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000040}
41
deadbeefc5d0d952015-07-16 10:22:21 -070042TestClient* CreateTCPTestClient(AsyncSocket* socket) {
nisse32f25052017-05-08 01:57:18 -070043 return new TestClient(MakeUnique<AsyncTCPSocket>(socket, false));
deadbeefc5d0d952015-07-16 10:22:21 -070044}
45
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000046// Tests that when sending from internal_addr to external_addrs through the
47// NAT type specified by nat_type, all external addrs receive the sent packet
48// and, if exp_same is true, all use the same mapped-address on the NAT.
49void TestSend(
50 SocketServer* internal, const SocketAddress& internal_addr,
51 SocketServer* external, const SocketAddress external_addrs[4],
52 NATType nat_type, bool exp_same) {
53 Thread th_int(internal);
54 Thread th_ext(external);
55
56 SocketAddress server_addr = internal_addr;
57 server_addr.SetPort(0); // Auto-select a port
deadbeefc5d0d952015-07-16 10:22:21 -070058 NATServer* nat = new NATServer(nat_type, internal, server_addr, server_addr,
59 external, external_addrs[0]);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000060 NATSocketFactory* natsf = new NATSocketFactory(internal,
deadbeefc5d0d952015-07-16 10:22:21 -070061 nat->internal_udp_address(),
62 nat->internal_tcp_address());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000063
64 TestClient* in = CreateTestClient(natsf, internal_addr);
65 TestClient* out[4];
66 for (int i = 0; i < 4; i++)
67 out[i] = CreateTestClient(external, external_addrs[i]);
68
69 th_int.Start();
70 th_ext.Start();
71
72 const char* buf = "filter_test";
73 size_t len = strlen(buf);
74
75 in->SendTo(buf, len, out[0]->address());
76 SocketAddress trans_addr;
77 EXPECT_TRUE(out[0]->CheckNextPacket(buf, len, &trans_addr));
78
79 for (int i = 1; i < 4; i++) {
80 in->SendTo(buf, len, out[i]->address());
81 SocketAddress trans_addr2;
82 EXPECT_TRUE(out[i]->CheckNextPacket(buf, len, &trans_addr2));
83 bool are_same = (trans_addr == trans_addr2);
84 ASSERT_EQ(are_same, exp_same) << "same translated address";
85 ASSERT_NE(AF_UNSPEC, trans_addr.family());
86 ASSERT_NE(AF_UNSPEC, trans_addr2.family());
87 }
88
89 th_int.Stop();
90 th_ext.Stop();
91
92 delete nat;
93 delete natsf;
94 delete in;
95 for (int i = 0; i < 4; i++)
96 delete out[i];
97}
98
99// Tests that when sending from external_addrs to internal_addr, the packet
100// is delivered according to the specified filter_ip and filter_port rules.
101void TestRecv(
102 SocketServer* internal, const SocketAddress& internal_addr,
103 SocketServer* external, const SocketAddress external_addrs[4],
104 NATType nat_type, bool filter_ip, bool filter_port) {
105 Thread th_int(internal);
106 Thread th_ext(external);
107
108 SocketAddress server_addr = internal_addr;
109 server_addr.SetPort(0); // Auto-select a port
deadbeefc5d0d952015-07-16 10:22:21 -0700110 NATServer* nat = new NATServer(nat_type, internal, server_addr, server_addr,
111 external, external_addrs[0]);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000112 NATSocketFactory* natsf = new NATSocketFactory(internal,
deadbeefc5d0d952015-07-16 10:22:21 -0700113 nat->internal_udp_address(),
114 nat->internal_tcp_address());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000115
116 TestClient* in = CreateTestClient(natsf, internal_addr);
117 TestClient* out[4];
118 for (int i = 0; i < 4; i++)
119 out[i] = CreateTestClient(external, external_addrs[i]);
120
121 th_int.Start();
122 th_ext.Start();
123
124 const char* buf = "filter_test";
125 size_t len = strlen(buf);
126
127 in->SendTo(buf, len, out[0]->address());
128 SocketAddress trans_addr;
129 EXPECT_TRUE(out[0]->CheckNextPacket(buf, len, &trans_addr));
130
131 out[1]->SendTo(buf, len, trans_addr);
132 EXPECT_TRUE(CheckReceive(in, !filter_ip, buf, len));
133
134 out[2]->SendTo(buf, len, trans_addr);
135 EXPECT_TRUE(CheckReceive(in, !filter_port, buf, len));
136
137 out[3]->SendTo(buf, len, trans_addr);
138 EXPECT_TRUE(CheckReceive(in, !filter_ip && !filter_port, buf, len));
139
140 th_int.Stop();
141 th_ext.Stop();
142
143 delete nat;
144 delete natsf;
145 delete in;
146 for (int i = 0; i < 4; i++)
147 delete out[i];
148}
149
150// Tests that NATServer allocates bindings properly.
151void TestBindings(
152 SocketServer* internal, const SocketAddress& internal_addr,
153 SocketServer* external, const SocketAddress external_addrs[4]) {
154 TestSend(internal, internal_addr, external, external_addrs,
155 NAT_OPEN_CONE, true);
156 TestSend(internal, internal_addr, external, external_addrs,
157 NAT_ADDR_RESTRICTED, true);
158 TestSend(internal, internal_addr, external, external_addrs,
159 NAT_PORT_RESTRICTED, true);
160 TestSend(internal, internal_addr, external, external_addrs,
161 NAT_SYMMETRIC, false);
162}
163
164// Tests that NATServer filters packets properly.
165void TestFilters(
166 SocketServer* internal, const SocketAddress& internal_addr,
167 SocketServer* external, const SocketAddress external_addrs[4]) {
168 TestRecv(internal, internal_addr, external, external_addrs,
169 NAT_OPEN_CONE, false, false);
170 TestRecv(internal, internal_addr, external, external_addrs,
171 NAT_ADDR_RESTRICTED, true, false);
172 TestRecv(internal, internal_addr, external, external_addrs,
173 NAT_PORT_RESTRICTED, true, true);
174 TestRecv(internal, internal_addr, external, external_addrs,
175 NAT_SYMMETRIC, true, true);
176}
177
178bool TestConnectivity(const SocketAddress& src, const IPAddress& dst) {
179 // The physical NAT tests require connectivity to the selected ip from the
180 // internal address used for the NAT. Things like firewalls can break that, so
181 // check to see if it's worth even trying with this ip.
jbauch555604a2016-04-26 03:13:22 -0700182 std::unique_ptr<PhysicalSocketServer> pss(new PhysicalSocketServer());
183 std::unique_ptr<AsyncSocket> client(
184 pss->CreateAsyncSocket(src.family(), SOCK_DGRAM));
185 std::unique_ptr<AsyncSocket> server(
186 pss->CreateAsyncSocket(src.family(), SOCK_DGRAM));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000187 if (client->Bind(SocketAddress(src.ipaddr(), 0)) != 0 ||
188 server->Bind(SocketAddress(dst, 0)) != 0) {
189 return false;
190 }
191 const char* buf = "hello other socket";
192 size_t len = strlen(buf);
193 int sent = client->SendTo(buf, len, server->GetLocalAddress());
194 SocketAddress addr;
195 const size_t kRecvBufSize = 64;
196 char recvbuf[kRecvBufSize];
197 Thread::Current()->SleepMs(100);
Stefan Holmer9131efd2016-05-23 18:19:26 +0200198 int received = server->RecvFrom(recvbuf, kRecvBufSize, &addr, nullptr);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000199 return received == sent && ::memcmp(buf, recvbuf, len) == 0;
200}
201
202void TestPhysicalInternal(const SocketAddress& int_addr) {
203 BasicNetworkManager network_manager;
204 network_manager.set_ipv6_enabled(true);
205 network_manager.StartUpdating();
206 // Process pending messages so the network list is updated.
207 Thread::Current()->ProcessMessages(0);
208
209 std::vector<Network*> networks;
210 network_manager.GetNetworks(&networks);
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800211 networks.erase(std::remove_if(networks.begin(), networks.end(),
212 [](rtc::Network* network) {
213 return rtc::kDefaultNetworkIgnoreMask &
214 network->type();
215 }),
216 networks.end());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000217 if (networks.empty()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100218 RTC_LOG(LS_WARNING) << "Not enough network adapters for test.";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000219 return;
220 }
221
222 SocketAddress ext_addr1(int_addr);
223 SocketAddress ext_addr2;
224 // Find an available IP with matching family. The test breaks if int_addr
225 // can't talk to ip, so check for connectivity as well.
226 for (std::vector<Network*>::iterator it = networks.begin();
227 it != networks.end(); ++it) {
guoweis@webrtc.org369a6372014-09-17 22:37:29 +0000228 const IPAddress& ip = (*it)->GetBestIP();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000229 if (ip.family() == int_addr.family() && TestConnectivity(int_addr, ip)) {
230 ext_addr2.SetIP(ip);
231 break;
232 }
233 }
234 if (ext_addr2.IsNil()) {
Jonas Olssonabbe8412018-04-03 13:40:05 +0200235 RTC_LOG(LS_WARNING) << "No available IP of same family as "
236 << int_addr.ToString();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000237 return;
238 }
239
Jonas Olssonabbe8412018-04-03 13:40:05 +0200240 RTC_LOG(LS_INFO) << "selected ip " << ext_addr2.ipaddr().ToString();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000241
242 SocketAddress ext_addrs[4] = {
243 SocketAddress(ext_addr1),
244 SocketAddress(ext_addr2),
245 SocketAddress(ext_addr1),
246 SocketAddress(ext_addr2)
247 };
248
jbauch555604a2016-04-26 03:13:22 -0700249 std::unique_ptr<PhysicalSocketServer> int_pss(new PhysicalSocketServer());
250 std::unique_ptr<PhysicalSocketServer> ext_pss(new PhysicalSocketServer());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000251
252 TestBindings(int_pss.get(), int_addr, ext_pss.get(), ext_addrs);
253 TestFilters(int_pss.get(), int_addr, ext_pss.get(), ext_addrs);
254}
255
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000256TEST(NatTest, TestPhysicalIPv4) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000257 TestPhysicalInternal(SocketAddress("127.0.0.1", 0));
258}
259
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000260TEST(NatTest, TestPhysicalIPv6) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000261 if (HasIPv6Enabled()) {
262 TestPhysicalInternal(SocketAddress("::1", 0));
263 } else {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100264 RTC_LOG(LS_WARNING) << "No IPv6, skipping";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000265 }
266}
267
Guo-wei Shiehbe508a12015-04-06 12:48:47 -0700268namespace {
269
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000270class TestVirtualSocketServer : public VirtualSocketServer {
271 public:
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000272 // Expose this publicly
273 IPAddress GetNextIP(int af) { return VirtualSocketServer::GetNextIP(af); }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000274};
275
Guo-wei Shiehbe508a12015-04-06 12:48:47 -0700276} // namespace
277
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000278void TestVirtualInternal(int family) {
jbauch555604a2016-04-26 03:13:22 -0700279 std::unique_ptr<TestVirtualSocketServer> int_vss(
deadbeef98e186c2017-05-16 18:00:06 -0700280 new TestVirtualSocketServer());
jbauch555604a2016-04-26 03:13:22 -0700281 std::unique_ptr<TestVirtualSocketServer> ext_vss(
deadbeef98e186c2017-05-16 18:00:06 -0700282 new TestVirtualSocketServer());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000283
284 SocketAddress int_addr;
285 SocketAddress ext_addrs[4];
286 int_addr.SetIP(int_vss->GetNextIP(family));
287 ext_addrs[0].SetIP(ext_vss->GetNextIP(int_addr.family()));
288 ext_addrs[1].SetIP(ext_vss->GetNextIP(int_addr.family()));
289 ext_addrs[2].SetIP(ext_addrs[0].ipaddr());
290 ext_addrs[3].SetIP(ext_addrs[1].ipaddr());
291
292 TestBindings(int_vss.get(), int_addr, ext_vss.get(), ext_addrs);
293 TestFilters(int_vss.get(), int_addr, ext_vss.get(), ext_addrs);
294}
295
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000296TEST(NatTest, TestVirtualIPv4) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000297 TestVirtualInternal(AF_INET);
298}
299
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000300TEST(NatTest, TestVirtualIPv6) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000301 if (HasIPv6Enabled()) {
302 TestVirtualInternal(AF_INET6);
303 } else {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100304 RTC_LOG(LS_WARNING) << "No IPv6, skipping";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000305 }
306}
307
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000308class NatTcpTest : public testing::Test, public sigslot::has_slots<> {
309 public:
deadbeefc5d0d952015-07-16 10:22:21 -0700310 NatTcpTest()
311 : int_addr_("192.168.0.1", 0),
312 ext_addr_("10.0.0.1", 0),
313 connected_(false),
deadbeef98e186c2017-05-16 18:00:06 -0700314 int_vss_(new TestVirtualSocketServer()),
315 ext_vss_(new TestVirtualSocketServer()),
deadbeefc5d0d952015-07-16 10:22:21 -0700316 int_thread_(new Thread(int_vss_.get())),
317 ext_thread_(new Thread(ext_vss_.get())),
deadbeef98e186c2017-05-16 18:00:06 -0700318 nat_(new NATServer(NAT_OPEN_CONE,
319 int_vss_.get(),
320 int_addr_,
321 int_addr_,
322 ext_vss_.get(),
323 ext_addr_)),
deadbeefc5d0d952015-07-16 10:22:21 -0700324 natsf_(new NATSocketFactory(int_vss_.get(),
325 nat_->internal_udp_address(),
326 nat_->internal_tcp_address())) {
327 int_thread_->Start();
328 ext_thread_->Start();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000329 }
deadbeefc5d0d952015-07-16 10:22:21 -0700330
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000331 void OnConnectEvent(AsyncSocket* socket) {
332 connected_ = true;
333 }
deadbeefc5d0d952015-07-16 10:22:21 -0700334
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000335 void OnAcceptEvent(AsyncSocket* socket) {
deadbeef37f5ecf2017-02-27 14:06:41 -0800336 accepted_.reset(server_->Accept(nullptr));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000337 }
deadbeefc5d0d952015-07-16 10:22:21 -0700338
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000339 void OnCloseEvent(AsyncSocket* socket, int error) {
340 }
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) {
deadbeefc5d0d952015-07-16 10:22:21 -0700362 server_.reset(ext_vss_->CreateAsyncSocket(SOCK_STREAM));
363 server_->Bind(ext_addr_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000364 server_->Listen(5);
365
deadbeefc5d0d952015-07-16 10:22:21 -0700366 client_.reset(natsf_->CreateAsyncSocket(SOCK_STREAM));
367 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