blob: 8b9d8a1509fa6b1ecee25d22877365f6cd547cfd [file] [log] [blame]
henrike@webrtc.orgf7795df2014-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"
21#include "webrtc/base/virtualsocketserver.h"
22
23using namespace rtc;
24
25bool CheckReceive(
26 TestClient* client, bool should_receive, const char* buf, size_t size) {
27 return (should_receive) ?
28 client->CheckNextPacket(buf, size, 0) :
29 client->CheckNoPacket();
30}
31
32TestClient* CreateTestClient(
33 SocketFactory* factory, const SocketAddress& local_addr) {
34 AsyncUDPSocket* socket = AsyncUDPSocket::Create(factory, local_addr);
35 return new TestClient(socket);
36}
37
38// Tests that when sending from internal_addr to external_addrs through the
39// NAT type specified by nat_type, all external addrs receive the sent packet
40// and, if exp_same is true, all use the same mapped-address on the NAT.
41void TestSend(
42 SocketServer* internal, const SocketAddress& internal_addr,
43 SocketServer* external, const SocketAddress external_addrs[4],
44 NATType nat_type, bool exp_same) {
45 Thread th_int(internal);
46 Thread th_ext(external);
47
48 SocketAddress server_addr = internal_addr;
49 server_addr.SetPort(0); // Auto-select a port
50 NATServer* nat = new NATServer(
51 nat_type, internal, server_addr, external, external_addrs[0]);
52 NATSocketFactory* natsf = new NATSocketFactory(internal,
53 nat->internal_address());
54
55 TestClient* in = CreateTestClient(natsf, internal_addr);
56 TestClient* out[4];
57 for (int i = 0; i < 4; i++)
58 out[i] = CreateTestClient(external, external_addrs[i]);
59
60 th_int.Start();
61 th_ext.Start();
62
63 const char* buf = "filter_test";
64 size_t len = strlen(buf);
65
66 in->SendTo(buf, len, out[0]->address());
67 SocketAddress trans_addr;
68 EXPECT_TRUE(out[0]->CheckNextPacket(buf, len, &trans_addr));
69
70 for (int i = 1; i < 4; i++) {
71 in->SendTo(buf, len, out[i]->address());
72 SocketAddress trans_addr2;
73 EXPECT_TRUE(out[i]->CheckNextPacket(buf, len, &trans_addr2));
74 bool are_same = (trans_addr == trans_addr2);
75 ASSERT_EQ(are_same, exp_same) << "same translated address";
76 ASSERT_NE(AF_UNSPEC, trans_addr.family());
77 ASSERT_NE(AF_UNSPEC, trans_addr2.family());
78 }
79
80 th_int.Stop();
81 th_ext.Stop();
82
83 delete nat;
84 delete natsf;
85 delete in;
86 for (int i = 0; i < 4; i++)
87 delete out[i];
88}
89
90// Tests that when sending from external_addrs to internal_addr, the packet
91// is delivered according to the specified filter_ip and filter_port rules.
92void TestRecv(
93 SocketServer* internal, const SocketAddress& internal_addr,
94 SocketServer* external, const SocketAddress external_addrs[4],
95 NATType nat_type, bool filter_ip, bool filter_port) {
96 Thread th_int(internal);
97 Thread th_ext(external);
98
99 SocketAddress server_addr = internal_addr;
100 server_addr.SetPort(0); // Auto-select a port
101 NATServer* nat = new NATServer(
102 nat_type, internal, server_addr, external, external_addrs[0]);
103 NATSocketFactory* natsf = new NATSocketFactory(internal,
104 nat->internal_address());
105
106 TestClient* in = CreateTestClient(natsf, internal_addr);
107 TestClient* out[4];
108 for (int i = 0; i < 4; i++)
109 out[i] = CreateTestClient(external, external_addrs[i]);
110
111 th_int.Start();
112 th_ext.Start();
113
114 const char* buf = "filter_test";
115 size_t len = strlen(buf);
116
117 in->SendTo(buf, len, out[0]->address());
118 SocketAddress trans_addr;
119 EXPECT_TRUE(out[0]->CheckNextPacket(buf, len, &trans_addr));
120
121 out[1]->SendTo(buf, len, trans_addr);
122 EXPECT_TRUE(CheckReceive(in, !filter_ip, buf, len));
123
124 out[2]->SendTo(buf, len, trans_addr);
125 EXPECT_TRUE(CheckReceive(in, !filter_port, buf, len));
126
127 out[3]->SendTo(buf, len, trans_addr);
128 EXPECT_TRUE(CheckReceive(in, !filter_ip && !filter_port, buf, len));
129
130 th_int.Stop();
131 th_ext.Stop();
132
133 delete nat;
134 delete natsf;
135 delete in;
136 for (int i = 0; i < 4; i++)
137 delete out[i];
138}
139
140// Tests that NATServer allocates bindings properly.
141void TestBindings(
142 SocketServer* internal, const SocketAddress& internal_addr,
143 SocketServer* external, const SocketAddress external_addrs[4]) {
144 TestSend(internal, internal_addr, external, external_addrs,
145 NAT_OPEN_CONE, true);
146 TestSend(internal, internal_addr, external, external_addrs,
147 NAT_ADDR_RESTRICTED, true);
148 TestSend(internal, internal_addr, external, external_addrs,
149 NAT_PORT_RESTRICTED, true);
150 TestSend(internal, internal_addr, external, external_addrs,
151 NAT_SYMMETRIC, false);
152}
153
154// Tests that NATServer filters packets properly.
155void TestFilters(
156 SocketServer* internal, const SocketAddress& internal_addr,
157 SocketServer* external, const SocketAddress external_addrs[4]) {
158 TestRecv(internal, internal_addr, external, external_addrs,
159 NAT_OPEN_CONE, false, false);
160 TestRecv(internal, internal_addr, external, external_addrs,
161 NAT_ADDR_RESTRICTED, true, false);
162 TestRecv(internal, internal_addr, external, external_addrs,
163 NAT_PORT_RESTRICTED, true, true);
164 TestRecv(internal, internal_addr, external, external_addrs,
165 NAT_SYMMETRIC, true, true);
166}
167
168bool TestConnectivity(const SocketAddress& src, const IPAddress& dst) {
169 // The physical NAT tests require connectivity to the selected ip from the
170 // internal address used for the NAT. Things like firewalls can break that, so
171 // check to see if it's worth even trying with this ip.
172 scoped_ptr<PhysicalSocketServer> pss(new PhysicalSocketServer());
173 scoped_ptr<AsyncSocket> client(pss->CreateAsyncSocket(src.family(),
174 SOCK_DGRAM));
175 scoped_ptr<AsyncSocket> server(pss->CreateAsyncSocket(src.family(),
176 SOCK_DGRAM));
177 if (client->Bind(SocketAddress(src.ipaddr(), 0)) != 0 ||
178 server->Bind(SocketAddress(dst, 0)) != 0) {
179 return false;
180 }
181 const char* buf = "hello other socket";
182 size_t len = strlen(buf);
183 int sent = client->SendTo(buf, len, server->GetLocalAddress());
184 SocketAddress addr;
185 const size_t kRecvBufSize = 64;
186 char recvbuf[kRecvBufSize];
187 Thread::Current()->SleepMs(100);
188 int received = server->RecvFrom(recvbuf, kRecvBufSize, &addr);
189 return received == sent && ::memcmp(buf, recvbuf, len) == 0;
190}
191
192void TestPhysicalInternal(const SocketAddress& int_addr) {
193 BasicNetworkManager network_manager;
194 network_manager.set_ipv6_enabled(true);
195 network_manager.StartUpdating();
196 // Process pending messages so the network list is updated.
197 Thread::Current()->ProcessMessages(0);
198
199 std::vector<Network*> networks;
200 network_manager.GetNetworks(&networks);
201 if (networks.empty()) {
202 LOG(LS_WARNING) << "Not enough network adapters for test.";
203 return;
204 }
205
206 SocketAddress ext_addr1(int_addr);
207 SocketAddress ext_addr2;
208 // Find an available IP with matching family. The test breaks if int_addr
209 // can't talk to ip, so check for connectivity as well.
210 for (std::vector<Network*>::iterator it = networks.begin();
211 it != networks.end(); ++it) {
212 const IPAddress& ip = (*it)->ip();
213 if (ip.family() == int_addr.family() && TestConnectivity(int_addr, ip)) {
214 ext_addr2.SetIP(ip);
215 break;
216 }
217 }
218 if (ext_addr2.IsNil()) {
219 LOG(LS_WARNING) << "No available IP of same family as " << int_addr;
220 return;
221 }
222
223 LOG(LS_INFO) << "selected ip " << ext_addr2.ipaddr();
224
225 SocketAddress ext_addrs[4] = {
226 SocketAddress(ext_addr1),
227 SocketAddress(ext_addr2),
228 SocketAddress(ext_addr1),
229 SocketAddress(ext_addr2)
230 };
231
232 scoped_ptr<PhysicalSocketServer> int_pss(new PhysicalSocketServer());
233 scoped_ptr<PhysicalSocketServer> ext_pss(new PhysicalSocketServer());
234
235 TestBindings(int_pss.get(), int_addr, ext_pss.get(), ext_addrs);
236 TestFilters(int_pss.get(), int_addr, ext_pss.get(), ext_addrs);
237}
238
239TEST(NatTest, TestPhysicalIPv4) {
240 TestPhysicalInternal(SocketAddress("127.0.0.1", 0));
241}
242
243TEST(NatTest, TestPhysicalIPv6) {
244 if (HasIPv6Enabled()) {
245 TestPhysicalInternal(SocketAddress("::1", 0));
246 } else {
247 LOG(LS_WARNING) << "No IPv6, skipping";
248 }
249}
250
251class TestVirtualSocketServer : public VirtualSocketServer {
252 public:
253 explicit TestVirtualSocketServer(SocketServer* ss)
254 : VirtualSocketServer(ss),
255 ss_(ss) {}
256 // Expose this publicly
257 IPAddress GetNextIP(int af) { return VirtualSocketServer::GetNextIP(af); }
258
259 private:
260 scoped_ptr<SocketServer> ss_;
261};
262
263void TestVirtualInternal(int family) {
264 scoped_ptr<TestVirtualSocketServer> int_vss(new TestVirtualSocketServer(
265 new PhysicalSocketServer()));
266 scoped_ptr<TestVirtualSocketServer> ext_vss(new TestVirtualSocketServer(
267 new PhysicalSocketServer()));
268
269 SocketAddress int_addr;
270 SocketAddress ext_addrs[4];
271 int_addr.SetIP(int_vss->GetNextIP(family));
272 ext_addrs[0].SetIP(ext_vss->GetNextIP(int_addr.family()));
273 ext_addrs[1].SetIP(ext_vss->GetNextIP(int_addr.family()));
274 ext_addrs[2].SetIP(ext_addrs[0].ipaddr());
275 ext_addrs[3].SetIP(ext_addrs[1].ipaddr());
276
277 TestBindings(int_vss.get(), int_addr, ext_vss.get(), ext_addrs);
278 TestFilters(int_vss.get(), int_addr, ext_vss.get(), ext_addrs);
279}
280
281TEST(NatTest, TestVirtualIPv4) {
282 TestVirtualInternal(AF_INET);
283}
284
285TEST(NatTest, TestVirtualIPv6) {
286 if (HasIPv6Enabled()) {
287 TestVirtualInternal(AF_INET6);
288 } else {
289 LOG(LS_WARNING) << "No IPv6, skipping";
290 }
291}
292
293// TODO: Finish this test
294class NatTcpTest : public testing::Test, public sigslot::has_slots<> {
295 public:
296 NatTcpTest() : connected_(false) {}
297 virtual void SetUp() {
298 int_vss_ = new TestVirtualSocketServer(new PhysicalSocketServer());
299 ext_vss_ = new TestVirtualSocketServer(new PhysicalSocketServer());
300 nat_ = new NATServer(NAT_OPEN_CONE, int_vss_, SocketAddress(),
301 ext_vss_, SocketAddress());
302 natsf_ = new NATSocketFactory(int_vss_, nat_->internal_address());
303 }
304 void OnConnectEvent(AsyncSocket* socket) {
305 connected_ = true;
306 }
307 void OnAcceptEvent(AsyncSocket* socket) {
308 accepted_ = server_->Accept(NULL);
309 }
310 void OnCloseEvent(AsyncSocket* socket, int error) {
311 }
312 void ConnectEvents() {
313 server_->SignalReadEvent.connect(this, &NatTcpTest::OnAcceptEvent);
314 client_->SignalConnectEvent.connect(this, &NatTcpTest::OnConnectEvent);
315 }
316 TestVirtualSocketServer* int_vss_;
317 TestVirtualSocketServer* ext_vss_;
318 NATServer* nat_;
319 NATSocketFactory* natsf_;
320 AsyncSocket* client_;
321 AsyncSocket* server_;
322 AsyncSocket* accepted_;
323 bool connected_;
324};
325
326TEST_F(NatTcpTest, DISABLED_TestConnectOut) {
327 server_ = ext_vss_->CreateAsyncSocket(SOCK_STREAM);
328 server_->Bind(SocketAddress());
329 server_->Listen(5);
330
331 client_ = int_vss_->CreateAsyncSocket(SOCK_STREAM);
332 EXPECT_GE(0, client_->Bind(SocketAddress()));
333 EXPECT_GE(0, client_->Connect(server_->GetLocalAddress()));
334
335
336 ConnectEvents();
337
338 EXPECT_TRUE_WAIT(connected_, 1000);
339 EXPECT_EQ(client_->GetRemoteAddress(), server_->GetLocalAddress());
340 EXPECT_EQ(client_->GetRemoteAddress(), accepted_->GetLocalAddress());
341 EXPECT_EQ(client_->GetLocalAddress(), accepted_->GetRemoteAddress());
342
343 client_->Close();
344}
345//#endif