blob: f585effdd95337e7313d2e96229f4d84e8d3b1a7 [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
15#include "webrtc/base/gunit.h"
16#include "webrtc/base/logging.h"
17#include "webrtc/base/natserver.h"
18#include "webrtc/base/natsocketfactory.h"
19#include "webrtc/base/nethelpers.h"
20#include "webrtc/base/network.h"
21#include "webrtc/base/physicalsocketserver.h"
22#include "webrtc/base/testclient.h"
deadbeefc5d0d952015-07-16 10:22:21 -070023#include "webrtc/base/asynctcpsocket.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000024#include "webrtc/base/virtualsocketserver.h"
25
26using namespace rtc;
27
28bool CheckReceive(
29 TestClient* client, bool should_receive, const char* buf, size_t size) {
30 return (should_receive) ?
31 client->CheckNextPacket(buf, size, 0) :
32 client->CheckNoPacket();
33}
34
35TestClient* CreateTestClient(
36 SocketFactory* factory, const SocketAddress& local_addr) {
37 AsyncUDPSocket* socket = AsyncUDPSocket::Create(factory, local_addr);
38 return new TestClient(socket);
39}
40
deadbeefc5d0d952015-07-16 10:22:21 -070041TestClient* CreateTCPTestClient(AsyncSocket* socket) {
42 AsyncTCPSocket* packet_socket = new AsyncTCPSocket(socket, false);
43 return new TestClient(packet_socket);
44}
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()) {
218 LOG(LS_WARNING) << "Not enough network adapters for test.";
219 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()) {
235 LOG(LS_WARNING) << "No available IP of same family as " << int_addr;
236 return;
237 }
238
239 LOG(LS_INFO) << "selected ip " << ext_addr2.ipaddr();
240
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 {
263 LOG(LS_WARNING) << "No IPv6, skipping";
264 }
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:
271 explicit TestVirtualSocketServer(SocketServer* ss)
272 : VirtualSocketServer(ss),
273 ss_(ss) {}
274 // Expose this publicly
275 IPAddress GetNextIP(int af) { return VirtualSocketServer::GetNextIP(af); }
276
277 private:
jbauch555604a2016-04-26 03:13:22 -0700278 std::unique_ptr<SocketServer> ss_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000279};
280
Guo-wei Shiehbe508a12015-04-06 12:48:47 -0700281} // namespace
282
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000283void TestVirtualInternal(int family) {
jbauch555604a2016-04-26 03:13:22 -0700284 std::unique_ptr<TestVirtualSocketServer> int_vss(
285 new TestVirtualSocketServer(new PhysicalSocketServer()));
286 std::unique_ptr<TestVirtualSocketServer> ext_vss(
287 new TestVirtualSocketServer(new PhysicalSocketServer()));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000288
289 SocketAddress int_addr;
290 SocketAddress ext_addrs[4];
291 int_addr.SetIP(int_vss->GetNextIP(family));
292 ext_addrs[0].SetIP(ext_vss->GetNextIP(int_addr.family()));
293 ext_addrs[1].SetIP(ext_vss->GetNextIP(int_addr.family()));
294 ext_addrs[2].SetIP(ext_addrs[0].ipaddr());
295 ext_addrs[3].SetIP(ext_addrs[1].ipaddr());
296
297 TestBindings(int_vss.get(), int_addr, ext_vss.get(), ext_addrs);
298 TestFilters(int_vss.get(), int_addr, ext_vss.get(), ext_addrs);
299}
300
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000301TEST(NatTest, TestVirtualIPv4) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000302 TestVirtualInternal(AF_INET);
303}
304
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000305TEST(NatTest, TestVirtualIPv6) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000306 if (HasIPv6Enabled()) {
307 TestVirtualInternal(AF_INET6);
308 } else {
309 LOG(LS_WARNING) << "No IPv6, skipping";
310 }
311}
312
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000313class NatTcpTest : public testing::Test, public sigslot::has_slots<> {
314 public:
deadbeefc5d0d952015-07-16 10:22:21 -0700315 NatTcpTest()
316 : int_addr_("192.168.0.1", 0),
317 ext_addr_("10.0.0.1", 0),
318 connected_(false),
319 int_pss_(new PhysicalSocketServer()),
320 ext_pss_(new PhysicalSocketServer()),
321 int_vss_(new TestVirtualSocketServer(int_pss_)),
322 ext_vss_(new TestVirtualSocketServer(ext_pss_)),
323 int_thread_(new Thread(int_vss_.get())),
324 ext_thread_(new Thread(ext_vss_.get())),
325 nat_(new NATServer(NAT_OPEN_CONE, int_vss_.get(), int_addr_, int_addr_,
326 ext_vss_.get(), ext_addr_)),
327 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
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000334 void OnConnectEvent(AsyncSocket* socket) {
335 connected_ = true;
336 }
deadbeefc5d0d952015-07-16 10:22:21 -0700337
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000338 void OnAcceptEvent(AsyncSocket* socket) {
deadbeef37f5ecf2017-02-27 14:06:41 -0800339 accepted_.reset(server_->Accept(nullptr));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000340 }
deadbeefc5d0d952015-07-16 10:22:21 -0700341
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000342 void OnCloseEvent(AsyncSocket* socket, int error) {
343 }
deadbeefc5d0d952015-07-16 10:22:21 -0700344
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000345 void ConnectEvents() {
346 server_->SignalReadEvent.connect(this, &NatTcpTest::OnAcceptEvent);
347 client_->SignalConnectEvent.connect(this, &NatTcpTest::OnConnectEvent);
348 }
deadbeefc5d0d952015-07-16 10:22:21 -0700349
350 SocketAddress int_addr_;
351 SocketAddress ext_addr_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000352 bool connected_;
deadbeefc5d0d952015-07-16 10:22:21 -0700353 PhysicalSocketServer* int_pss_;
354 PhysicalSocketServer* ext_pss_;
jbauch555604a2016-04-26 03:13:22 -0700355 std::unique_ptr<TestVirtualSocketServer> int_vss_;
356 std::unique_ptr<TestVirtualSocketServer> ext_vss_;
357 std::unique_ptr<Thread> int_thread_;
358 std::unique_ptr<Thread> ext_thread_;
359 std::unique_ptr<NATServer> nat_;
360 std::unique_ptr<NATSocketFactory> natsf_;
361 std::unique_ptr<AsyncSocket> client_;
362 std::unique_ptr<AsyncSocket> server_;
363 std::unique_ptr<AsyncSocket> accepted_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000364};
365
magjed65eb1c32015-07-22 06:28:26 -0700366TEST_F(NatTcpTest, DISABLED_TestConnectOut) {
deadbeefc5d0d952015-07-16 10:22:21 -0700367 server_.reset(ext_vss_->CreateAsyncSocket(SOCK_STREAM));
368 server_->Bind(ext_addr_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000369 server_->Listen(5);
370
deadbeefc5d0d952015-07-16 10:22:21 -0700371 client_.reset(natsf_->CreateAsyncSocket(SOCK_STREAM));
372 EXPECT_GE(0, client_->Bind(int_addr_));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000373 EXPECT_GE(0, client_->Connect(server_->GetLocalAddress()));
374
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000375 ConnectEvents();
376
377 EXPECT_TRUE_WAIT(connected_, 1000);
378 EXPECT_EQ(client_->GetRemoteAddress(), server_->GetLocalAddress());
deadbeefc5d0d952015-07-16 10:22:21 -0700379 EXPECT_EQ(accepted_->GetRemoteAddress().ipaddr(), ext_addr_.ipaddr());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000380
jbauch555604a2016-04-26 03:13:22 -0700381 std::unique_ptr<rtc::TestClient> in(CreateTCPTestClient(client_.release()));
382 std::unique_ptr<rtc::TestClient> out(
deadbeefc5d0d952015-07-16 10:22:21 -0700383 CreateTCPTestClient(accepted_.release()));
384
385 const char* buf = "test_packet";
386 size_t len = strlen(buf);
387
388 in->Send(buf, len);
389 SocketAddress trans_addr;
390 EXPECT_TRUE(out->CheckNextPacket(buf, len, &trans_addr));
391
392 out->Send(buf, len);
393 EXPECT_TRUE(in->CheckNextPacket(buf, len, &trans_addr));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000394}
deadbeefc5d0d952015-07-16 10:22:21 -0700395// #endif