blob: d68df1d1508ae2331fdac4beebc89d4c45f18e49 [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()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100235 RTC_LOG(LS_WARNING) << "No available IP of same family as " << int_addr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000236 return;
237 }
238
Mirko Bonadei675513b2017-11-09 11:09:25 +0100239 RTC_LOG(LS_INFO) << "selected ip " << ext_addr2.ipaddr();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000240
241 SocketAddress ext_addrs[4] = {
242 SocketAddress(ext_addr1),
243 SocketAddress(ext_addr2),
244 SocketAddress(ext_addr1),
245 SocketAddress(ext_addr2)
246 };
247
jbauch555604a2016-04-26 03:13:22 -0700248 std::unique_ptr<PhysicalSocketServer> int_pss(new PhysicalSocketServer());
249 std::unique_ptr<PhysicalSocketServer> ext_pss(new PhysicalSocketServer());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000250
251 TestBindings(int_pss.get(), int_addr, ext_pss.get(), ext_addrs);
252 TestFilters(int_pss.get(), int_addr, ext_pss.get(), ext_addrs);
253}
254
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000255TEST(NatTest, TestPhysicalIPv4) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000256 TestPhysicalInternal(SocketAddress("127.0.0.1", 0));
257}
258
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000259TEST(NatTest, TestPhysicalIPv6) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000260 if (HasIPv6Enabled()) {
261 TestPhysicalInternal(SocketAddress("::1", 0));
262 } else {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100263 RTC_LOG(LS_WARNING) << "No IPv6, skipping";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000264 }
265}
266
Guo-wei Shiehbe508a12015-04-06 12:48:47 -0700267namespace {
268
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000269class TestVirtualSocketServer : public VirtualSocketServer {
270 public:
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000271 // Expose this publicly
272 IPAddress GetNextIP(int af) { return VirtualSocketServer::GetNextIP(af); }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000273};
274
Guo-wei Shiehbe508a12015-04-06 12:48:47 -0700275} // namespace
276
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000277void TestVirtualInternal(int family) {
jbauch555604a2016-04-26 03:13:22 -0700278 std::unique_ptr<TestVirtualSocketServer> int_vss(
deadbeef98e186c2017-05-16 18:00:06 -0700279 new TestVirtualSocketServer());
jbauch555604a2016-04-26 03:13:22 -0700280 std::unique_ptr<TestVirtualSocketServer> ext_vss(
deadbeef98e186c2017-05-16 18:00:06 -0700281 new TestVirtualSocketServer());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000282
283 SocketAddress int_addr;
284 SocketAddress ext_addrs[4];
285 int_addr.SetIP(int_vss->GetNextIP(family));
286 ext_addrs[0].SetIP(ext_vss->GetNextIP(int_addr.family()));
287 ext_addrs[1].SetIP(ext_vss->GetNextIP(int_addr.family()));
288 ext_addrs[2].SetIP(ext_addrs[0].ipaddr());
289 ext_addrs[3].SetIP(ext_addrs[1].ipaddr());
290
291 TestBindings(int_vss.get(), int_addr, ext_vss.get(), ext_addrs);
292 TestFilters(int_vss.get(), int_addr, ext_vss.get(), ext_addrs);
293}
294
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000295TEST(NatTest, TestVirtualIPv4) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000296 TestVirtualInternal(AF_INET);
297}
298
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000299TEST(NatTest, TestVirtualIPv6) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000300 if (HasIPv6Enabled()) {
301 TestVirtualInternal(AF_INET6);
302 } else {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100303 RTC_LOG(LS_WARNING) << "No IPv6, skipping";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000304 }
305}
306
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000307class NatTcpTest : public testing::Test, public sigslot::has_slots<> {
308 public:
deadbeefc5d0d952015-07-16 10:22:21 -0700309 NatTcpTest()
310 : int_addr_("192.168.0.1", 0),
311 ext_addr_("10.0.0.1", 0),
312 connected_(false),
deadbeef98e186c2017-05-16 18:00:06 -0700313 int_vss_(new TestVirtualSocketServer()),
314 ext_vss_(new TestVirtualSocketServer()),
deadbeefc5d0d952015-07-16 10:22:21 -0700315 int_thread_(new Thread(int_vss_.get())),
316 ext_thread_(new Thread(ext_vss_.get())),
deadbeef98e186c2017-05-16 18:00:06 -0700317 nat_(new NATServer(NAT_OPEN_CONE,
318 int_vss_.get(),
319 int_addr_,
320 int_addr_,
321 ext_vss_.get(),
322 ext_addr_)),
deadbeefc5d0d952015-07-16 10:22:21 -0700323 natsf_(new NATSocketFactory(int_vss_.get(),
324 nat_->internal_udp_address(),
325 nat_->internal_tcp_address())) {
326 int_thread_->Start();
327 ext_thread_->Start();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000328 }
deadbeefc5d0d952015-07-16 10:22:21 -0700329
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000330 void OnConnectEvent(AsyncSocket* socket) {
331 connected_ = true;
332 }
deadbeefc5d0d952015-07-16 10:22:21 -0700333
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000334 void OnAcceptEvent(AsyncSocket* socket) {
deadbeef37f5ecf2017-02-27 14:06:41 -0800335 accepted_.reset(server_->Accept(nullptr));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000336 }
deadbeefc5d0d952015-07-16 10:22:21 -0700337
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000338 void OnCloseEvent(AsyncSocket* socket, int error) {
339 }
deadbeefc5d0d952015-07-16 10:22:21 -0700340
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000341 void ConnectEvents() {
342 server_->SignalReadEvent.connect(this, &NatTcpTest::OnAcceptEvent);
343 client_->SignalConnectEvent.connect(this, &NatTcpTest::OnConnectEvent);
344 }
deadbeefc5d0d952015-07-16 10:22:21 -0700345
346 SocketAddress int_addr_;
347 SocketAddress ext_addr_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000348 bool connected_;
jbauch555604a2016-04-26 03:13:22 -0700349 std::unique_ptr<TestVirtualSocketServer> int_vss_;
350 std::unique_ptr<TestVirtualSocketServer> ext_vss_;
351 std::unique_ptr<Thread> int_thread_;
352 std::unique_ptr<Thread> ext_thread_;
353 std::unique_ptr<NATServer> nat_;
354 std::unique_ptr<NATSocketFactory> natsf_;
355 std::unique_ptr<AsyncSocket> client_;
356 std::unique_ptr<AsyncSocket> server_;
357 std::unique_ptr<AsyncSocket> accepted_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000358};
359
magjed65eb1c32015-07-22 06:28:26 -0700360TEST_F(NatTcpTest, DISABLED_TestConnectOut) {
deadbeefc5d0d952015-07-16 10:22:21 -0700361 server_.reset(ext_vss_->CreateAsyncSocket(SOCK_STREAM));
362 server_->Bind(ext_addr_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000363 server_->Listen(5);
364
deadbeefc5d0d952015-07-16 10:22:21 -0700365 client_.reset(natsf_->CreateAsyncSocket(SOCK_STREAM));
366 EXPECT_GE(0, client_->Bind(int_addr_));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000367 EXPECT_GE(0, client_->Connect(server_->GetLocalAddress()));
368
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000369 ConnectEvents();
370
371 EXPECT_TRUE_WAIT(connected_, 1000);
372 EXPECT_EQ(client_->GetRemoteAddress(), server_->GetLocalAddress());
deadbeefc5d0d952015-07-16 10:22:21 -0700373 EXPECT_EQ(accepted_->GetRemoteAddress().ipaddr(), ext_addr_.ipaddr());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000374
jbauch555604a2016-04-26 03:13:22 -0700375 std::unique_ptr<rtc::TestClient> in(CreateTCPTestClient(client_.release()));
376 std::unique_ptr<rtc::TestClient> out(
deadbeefc5d0d952015-07-16 10:22:21 -0700377 CreateTCPTestClient(accepted_.release()));
378
379 const char* buf = "test_packet";
380 size_t len = strlen(buf);
381
382 in->Send(buf, len);
383 SocketAddress trans_addr;
384 EXPECT_TRUE(out->CheckNextPacket(buf, len, &trans_addr));
385
386 out->Send(buf, len);
387 EXPECT_TRUE(in->CheckNextPacket(buf, len, &trans_addr));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000388}
deadbeefc5d0d952015-07-16 10:22:21 -0700389// #endif