blob: af691e40bdda79ba4b33a7daae5c2869ddba1bad [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
11#include <string>
12
13#include "webrtc/base/gunit.h"
14#include "webrtc/base/logging.h"
15#include "webrtc/base/natserver.h"
16#include "webrtc/base/natsocketfactory.h"
17#include "webrtc/base/nethelpers.h"
18#include "webrtc/base/network.h"
19#include "webrtc/base/physicalsocketserver.h"
20#include "webrtc/base/testclient.h"
deadbeefc5d0d952015-07-16 10:22:21 -070021#include "webrtc/base/asynctcpsocket.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000022#include "webrtc/base/virtualsocketserver.h"
henrike@webrtc.orgfded02c2014-09-19 13:10:10 +000023#include "webrtc/test/testsupport/gtest_disable.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000024
25using namespace rtc;
26
27bool CheckReceive(
28 TestClient* client, bool should_receive, const char* buf, size_t size) {
29 return (should_receive) ?
30 client->CheckNextPacket(buf, size, 0) :
31 client->CheckNoPacket();
32}
33
34TestClient* CreateTestClient(
35 SocketFactory* factory, const SocketAddress& local_addr) {
36 AsyncUDPSocket* socket = AsyncUDPSocket::Create(factory, local_addr);
37 return new TestClient(socket);
38}
39
deadbeefc5d0d952015-07-16 10:22:21 -070040TestClient* CreateTCPTestClient(AsyncSocket* socket) {
41 AsyncTCPSocket* packet_socket = new AsyncTCPSocket(socket, false);
42 return new TestClient(packet_socket);
43}
44
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000045// Tests that when sending from internal_addr to external_addrs through the
46// NAT type specified by nat_type, all external addrs receive the sent packet
47// and, if exp_same is true, all use the same mapped-address on the NAT.
48void TestSend(
49 SocketServer* internal, const SocketAddress& internal_addr,
50 SocketServer* external, const SocketAddress external_addrs[4],
51 NATType nat_type, bool exp_same) {
52 Thread th_int(internal);
53 Thread th_ext(external);
54
55 SocketAddress server_addr = internal_addr;
56 server_addr.SetPort(0); // Auto-select a port
deadbeefc5d0d952015-07-16 10:22:21 -070057 NATServer* nat = new NATServer(nat_type, internal, server_addr, server_addr,
58 external, external_addrs[0]);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000059 NATSocketFactory* natsf = new NATSocketFactory(internal,
deadbeefc5d0d952015-07-16 10:22:21 -070060 nat->internal_udp_address(),
61 nat->internal_tcp_address());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000062
63 TestClient* in = CreateTestClient(natsf, internal_addr);
64 TestClient* out[4];
65 for (int i = 0; i < 4; i++)
66 out[i] = CreateTestClient(external, external_addrs[i]);
67
68 th_int.Start();
69 th_ext.Start();
70
71 const char* buf = "filter_test";
72 size_t len = strlen(buf);
73
74 in->SendTo(buf, len, out[0]->address());
75 SocketAddress trans_addr;
76 EXPECT_TRUE(out[0]->CheckNextPacket(buf, len, &trans_addr));
77
78 for (int i = 1; i < 4; i++) {
79 in->SendTo(buf, len, out[i]->address());
80 SocketAddress trans_addr2;
81 EXPECT_TRUE(out[i]->CheckNextPacket(buf, len, &trans_addr2));
82 bool are_same = (trans_addr == trans_addr2);
83 ASSERT_EQ(are_same, exp_same) << "same translated address";
84 ASSERT_NE(AF_UNSPEC, trans_addr.family());
85 ASSERT_NE(AF_UNSPEC, trans_addr2.family());
86 }
87
88 th_int.Stop();
89 th_ext.Stop();
90
91 delete nat;
92 delete natsf;
93 delete in;
94 for (int i = 0; i < 4; i++)
95 delete out[i];
96}
97
98// Tests that when sending from external_addrs to internal_addr, the packet
99// is delivered according to the specified filter_ip and filter_port rules.
100void TestRecv(
101 SocketServer* internal, const SocketAddress& internal_addr,
102 SocketServer* external, const SocketAddress external_addrs[4],
103 NATType nat_type, bool filter_ip, bool filter_port) {
104 Thread th_int(internal);
105 Thread th_ext(external);
106
107 SocketAddress server_addr = internal_addr;
108 server_addr.SetPort(0); // Auto-select a port
deadbeefc5d0d952015-07-16 10:22:21 -0700109 NATServer* nat = new NATServer(nat_type, internal, server_addr, server_addr,
110 external, external_addrs[0]);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000111 NATSocketFactory* natsf = new NATSocketFactory(internal,
deadbeefc5d0d952015-07-16 10:22:21 -0700112 nat->internal_udp_address(),
113 nat->internal_tcp_address());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000114
115 TestClient* in = CreateTestClient(natsf, internal_addr);
116 TestClient* out[4];
117 for (int i = 0; i < 4; i++)
118 out[i] = CreateTestClient(external, external_addrs[i]);
119
120 th_int.Start();
121 th_ext.Start();
122
123 const char* buf = "filter_test";
124 size_t len = strlen(buf);
125
126 in->SendTo(buf, len, out[0]->address());
127 SocketAddress trans_addr;
128 EXPECT_TRUE(out[0]->CheckNextPacket(buf, len, &trans_addr));
129
130 out[1]->SendTo(buf, len, trans_addr);
131 EXPECT_TRUE(CheckReceive(in, !filter_ip, buf, len));
132
133 out[2]->SendTo(buf, len, trans_addr);
134 EXPECT_TRUE(CheckReceive(in, !filter_port, buf, len));
135
136 out[3]->SendTo(buf, len, trans_addr);
137 EXPECT_TRUE(CheckReceive(in, !filter_ip && !filter_port, buf, len));
138
139 th_int.Stop();
140 th_ext.Stop();
141
142 delete nat;
143 delete natsf;
144 delete in;
145 for (int i = 0; i < 4; i++)
146 delete out[i];
147}
148
149// Tests that NATServer allocates bindings properly.
150void TestBindings(
151 SocketServer* internal, const SocketAddress& internal_addr,
152 SocketServer* external, const SocketAddress external_addrs[4]) {
153 TestSend(internal, internal_addr, external, external_addrs,
154 NAT_OPEN_CONE, true);
155 TestSend(internal, internal_addr, external, external_addrs,
156 NAT_ADDR_RESTRICTED, true);
157 TestSend(internal, internal_addr, external, external_addrs,
158 NAT_PORT_RESTRICTED, true);
159 TestSend(internal, internal_addr, external, external_addrs,
160 NAT_SYMMETRIC, false);
161}
162
163// Tests that NATServer filters packets properly.
164void TestFilters(
165 SocketServer* internal, const SocketAddress& internal_addr,
166 SocketServer* external, const SocketAddress external_addrs[4]) {
167 TestRecv(internal, internal_addr, external, external_addrs,
168 NAT_OPEN_CONE, false, false);
169 TestRecv(internal, internal_addr, external, external_addrs,
170 NAT_ADDR_RESTRICTED, true, false);
171 TestRecv(internal, internal_addr, external, external_addrs,
172 NAT_PORT_RESTRICTED, true, true);
173 TestRecv(internal, internal_addr, external, external_addrs,
174 NAT_SYMMETRIC, true, true);
175}
176
177bool TestConnectivity(const SocketAddress& src, const IPAddress& dst) {
178 // The physical NAT tests require connectivity to the selected ip from the
179 // internal address used for the NAT. Things like firewalls can break that, so
180 // check to see if it's worth even trying with this ip.
181 scoped_ptr<PhysicalSocketServer> pss(new PhysicalSocketServer());
182 scoped_ptr<AsyncSocket> client(pss->CreateAsyncSocket(src.family(),
183 SOCK_DGRAM));
184 scoped_ptr<AsyncSocket> server(pss->CreateAsyncSocket(src.family(),
185 SOCK_DGRAM));
186 if (client->Bind(SocketAddress(src.ipaddr(), 0)) != 0 ||
187 server->Bind(SocketAddress(dst, 0)) != 0) {
188 return false;
189 }
190 const char* buf = "hello other socket";
191 size_t len = strlen(buf);
192 int sent = client->SendTo(buf, len, server->GetLocalAddress());
193 SocketAddress addr;
194 const size_t kRecvBufSize = 64;
195 char recvbuf[kRecvBufSize];
196 Thread::Current()->SleepMs(100);
197 int received = server->RecvFrom(recvbuf, kRecvBufSize, &addr);
198 return received == sent && ::memcmp(buf, recvbuf, len) == 0;
199}
200
201void TestPhysicalInternal(const SocketAddress& int_addr) {
202 BasicNetworkManager network_manager;
203 network_manager.set_ipv6_enabled(true);
204 network_manager.StartUpdating();
205 // Process pending messages so the network list is updated.
206 Thread::Current()->ProcessMessages(0);
207
208 std::vector<Network*> networks;
209 network_manager.GetNetworks(&networks);
210 if (networks.empty()) {
211 LOG(LS_WARNING) << "Not enough network adapters for test.";
212 return;
213 }
214
215 SocketAddress ext_addr1(int_addr);
216 SocketAddress ext_addr2;
217 // Find an available IP with matching family. The test breaks if int_addr
218 // can't talk to ip, so check for connectivity as well.
219 for (std::vector<Network*>::iterator it = networks.begin();
220 it != networks.end(); ++it) {
guoweis@webrtc.org369a6372014-09-17 22:37:29 +0000221 const IPAddress& ip = (*it)->GetBestIP();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000222 if (ip.family() == int_addr.family() && TestConnectivity(int_addr, ip)) {
223 ext_addr2.SetIP(ip);
224 break;
225 }
226 }
227 if (ext_addr2.IsNil()) {
228 LOG(LS_WARNING) << "No available IP of same family as " << int_addr;
229 return;
230 }
231
232 LOG(LS_INFO) << "selected ip " << ext_addr2.ipaddr();
233
234 SocketAddress ext_addrs[4] = {
235 SocketAddress(ext_addr1),
236 SocketAddress(ext_addr2),
237 SocketAddress(ext_addr1),
238 SocketAddress(ext_addr2)
239 };
240
241 scoped_ptr<PhysicalSocketServer> int_pss(new PhysicalSocketServer());
242 scoped_ptr<PhysicalSocketServer> ext_pss(new PhysicalSocketServer());
243
244 TestBindings(int_pss.get(), int_addr, ext_pss.get(), ext_addrs);
245 TestFilters(int_pss.get(), int_addr, ext_pss.get(), ext_addrs);
246}
247
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000248TEST(NatTest, TestPhysicalIPv4) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000249 TestPhysicalInternal(SocketAddress("127.0.0.1", 0));
250}
251
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000252TEST(NatTest, TestPhysicalIPv6) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000253 if (HasIPv6Enabled()) {
254 TestPhysicalInternal(SocketAddress("::1", 0));
255 } else {
256 LOG(LS_WARNING) << "No IPv6, skipping";
257 }
258}
259
Guo-wei Shiehbe508a12015-04-06 12:48:47 -0700260namespace {
261
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000262class TestVirtualSocketServer : public VirtualSocketServer {
263 public:
264 explicit TestVirtualSocketServer(SocketServer* ss)
265 : VirtualSocketServer(ss),
266 ss_(ss) {}
267 // Expose this publicly
268 IPAddress GetNextIP(int af) { return VirtualSocketServer::GetNextIP(af); }
269
270 private:
271 scoped_ptr<SocketServer> ss_;
272};
273
Guo-wei Shiehbe508a12015-04-06 12:48:47 -0700274} // namespace
275
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000276void TestVirtualInternal(int family) {
277 scoped_ptr<TestVirtualSocketServer> int_vss(new TestVirtualSocketServer(
278 new PhysicalSocketServer()));
279 scoped_ptr<TestVirtualSocketServer> ext_vss(new TestVirtualSocketServer(
280 new PhysicalSocketServer()));
281
282 SocketAddress int_addr;
283 SocketAddress ext_addrs[4];
284 int_addr.SetIP(int_vss->GetNextIP(family));
285 ext_addrs[0].SetIP(ext_vss->GetNextIP(int_addr.family()));
286 ext_addrs[1].SetIP(ext_vss->GetNextIP(int_addr.family()));
287 ext_addrs[2].SetIP(ext_addrs[0].ipaddr());
288 ext_addrs[3].SetIP(ext_addrs[1].ipaddr());
289
290 TestBindings(int_vss.get(), int_addr, ext_vss.get(), ext_addrs);
291 TestFilters(int_vss.get(), int_addr, ext_vss.get(), ext_addrs);
292}
293
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000294TEST(NatTest, TestVirtualIPv4) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000295 TestVirtualInternal(AF_INET);
296}
297
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000298TEST(NatTest, TestVirtualIPv6) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000299 if (HasIPv6Enabled()) {
300 TestVirtualInternal(AF_INET6);
301 } else {
302 LOG(LS_WARNING) << "No IPv6, skipping";
303 }
304}
305
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000306class NatTcpTest : public testing::Test, public sigslot::has_slots<> {
307 public:
deadbeefc5d0d952015-07-16 10:22:21 -0700308 NatTcpTest()
309 : int_addr_("192.168.0.1", 0),
310 ext_addr_("10.0.0.1", 0),
311 connected_(false),
312 int_pss_(new PhysicalSocketServer()),
313 ext_pss_(new PhysicalSocketServer()),
314 int_vss_(new TestVirtualSocketServer(int_pss_)),
315 ext_vss_(new TestVirtualSocketServer(ext_pss_)),
316 int_thread_(new Thread(int_vss_.get())),
317 ext_thread_(new Thread(ext_vss_.get())),
318 nat_(new NATServer(NAT_OPEN_CONE, int_vss_.get(), int_addr_, int_addr_,
319 ext_vss_.get(), ext_addr_)),
320 natsf_(new NATSocketFactory(int_vss_.get(),
321 nat_->internal_udp_address(),
322 nat_->internal_tcp_address())) {
323 int_thread_->Start();
324 ext_thread_->Start();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000325 }
deadbeefc5d0d952015-07-16 10:22:21 -0700326
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000327 void OnConnectEvent(AsyncSocket* socket) {
328 connected_ = true;
329 }
deadbeefc5d0d952015-07-16 10:22:21 -0700330
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000331 void OnAcceptEvent(AsyncSocket* socket) {
deadbeefc5d0d952015-07-16 10:22:21 -0700332 accepted_.reset(server_->Accept(NULL));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000333 }
deadbeefc5d0d952015-07-16 10:22:21 -0700334
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000335 void OnCloseEvent(AsyncSocket* socket, int error) {
336 }
deadbeefc5d0d952015-07-16 10:22:21 -0700337
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000338 void ConnectEvents() {
339 server_->SignalReadEvent.connect(this, &NatTcpTest::OnAcceptEvent);
340 client_->SignalConnectEvent.connect(this, &NatTcpTest::OnConnectEvent);
341 }
deadbeefc5d0d952015-07-16 10:22:21 -0700342
343 SocketAddress int_addr_;
344 SocketAddress ext_addr_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000345 bool connected_;
deadbeefc5d0d952015-07-16 10:22:21 -0700346 PhysicalSocketServer* int_pss_;
347 PhysicalSocketServer* ext_pss_;
348 rtc::scoped_ptr<TestVirtualSocketServer> int_vss_;
349 rtc::scoped_ptr<TestVirtualSocketServer> ext_vss_;
350 rtc::scoped_ptr<Thread> int_thread_;
351 rtc::scoped_ptr<Thread> ext_thread_;
352 rtc::scoped_ptr<NATServer> nat_;
353 rtc::scoped_ptr<NATSocketFactory> natsf_;
354 rtc::scoped_ptr<AsyncSocket> client_;
355 rtc::scoped_ptr<AsyncSocket> server_;
356 rtc::scoped_ptr<AsyncSocket> accepted_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000357};
358
deadbeefc5d0d952015-07-16 10:22:21 -0700359TEST_F(NatTcpTest, TestConnectOut) {
360 server_.reset(ext_vss_->CreateAsyncSocket(SOCK_STREAM));
361 server_->Bind(ext_addr_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000362 server_->Listen(5);
363
deadbeefc5d0d952015-07-16 10:22:21 -0700364 client_.reset(natsf_->CreateAsyncSocket(SOCK_STREAM));
365 EXPECT_GE(0, client_->Bind(int_addr_));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000366 EXPECT_GE(0, client_->Connect(server_->GetLocalAddress()));
367
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000368 ConnectEvents();
369
370 EXPECT_TRUE_WAIT(connected_, 1000);
371 EXPECT_EQ(client_->GetRemoteAddress(), server_->GetLocalAddress());
deadbeefc5d0d952015-07-16 10:22:21 -0700372 EXPECT_EQ(accepted_->GetRemoteAddress().ipaddr(), ext_addr_.ipaddr());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000373
deadbeefc5d0d952015-07-16 10:22:21 -0700374 rtc::scoped_ptr<rtc::TestClient> in(CreateTCPTestClient(client_.release()));
375 rtc::scoped_ptr<rtc::TestClient> out(
376 CreateTCPTestClient(accepted_.release()));
377
378 const char* buf = "test_packet";
379 size_t len = strlen(buf);
380
381 in->Send(buf, len);
382 SocketAddress trans_addr;
383 EXPECT_TRUE(out->CheckNextPacket(buf, len, &trans_addr));
384
385 out->Send(buf, len);
386 EXPECT_TRUE(in->CheckNextPacket(buf, len, &trans_addr));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000387}
deadbeefc5d0d952015-07-16 10:22:21 -0700388// #endif