blob: 03b1cd12571772d882f7ee6900694c822fc4df93 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
2 * libjingle
3 * Copyright 2004, Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include <string>
29
30#include "talk/base/gunit.h"
31#include "talk/base/host.h"
32#include "talk/base/logging.h"
33#include "talk/base/natserver.h"
34#include "talk/base/natsocketfactory.h"
35#include "talk/base/nethelpers.h"
36#include "talk/base/network.h"
37#include "talk/base/physicalsocketserver.h"
38#include "talk/base/testclient.h"
39#include "talk/base/virtualsocketserver.h"
40
41using namespace talk_base;
42
43bool CheckReceive(
44 TestClient* client, bool should_receive, const char* buf, size_t size) {
45 return (should_receive) ?
46 client->CheckNextPacket(buf, size, 0) :
47 client->CheckNoPacket();
48}
49
50TestClient* CreateTestClient(
51 SocketFactory* factory, const SocketAddress& local_addr) {
52 AsyncUDPSocket* socket = AsyncUDPSocket::Create(factory, local_addr);
53 return new TestClient(socket);
54}
55
56// Tests that when sending from internal_addr to external_addrs through the
57// NAT type specified by nat_type, all external addrs receive the sent packet
58// and, if exp_same is true, all use the same mapped-address on the NAT.
59void TestSend(
60 SocketServer* internal, const SocketAddress& internal_addr,
61 SocketServer* external, const SocketAddress external_addrs[4],
62 NATType nat_type, bool exp_same) {
63 Thread th_int(internal);
64 Thread th_ext(external);
65
66 SocketAddress server_addr = internal_addr;
67 server_addr.SetPort(0); // Auto-select a port
68 NATServer* nat = new NATServer(
69 nat_type, internal, server_addr, external, external_addrs[0]);
70 NATSocketFactory* natsf = new NATSocketFactory(internal,
71 nat->internal_address());
72
73 TestClient* in = CreateTestClient(natsf, internal_addr);
74 TestClient* out[4];
75 for (int i = 0; i < 4; i++)
76 out[i] = CreateTestClient(external, external_addrs[i]);
77
78 th_int.Start();
79 th_ext.Start();
80
81 const char* buf = "filter_test";
82 size_t len = strlen(buf);
83
84 in->SendTo(buf, len, out[0]->address());
85 SocketAddress trans_addr;
86 EXPECT_TRUE(out[0]->CheckNextPacket(buf, len, &trans_addr));
87
88 for (int i = 1; i < 4; i++) {
89 in->SendTo(buf, len, out[i]->address());
90 SocketAddress trans_addr2;
91 EXPECT_TRUE(out[i]->CheckNextPacket(buf, len, &trans_addr2));
92 bool are_same = (trans_addr == trans_addr2);
93 ASSERT_EQ(are_same, exp_same) << "same translated address";
94 ASSERT_NE(AF_UNSPEC, trans_addr.family());
95 ASSERT_NE(AF_UNSPEC, trans_addr2.family());
96 }
97
98 th_int.Stop();
99 th_ext.Stop();
100
101 delete nat;
102 delete natsf;
103 delete in;
104 for (int i = 0; i < 4; i++)
105 delete out[i];
106}
107
108// Tests that when sending from external_addrs to internal_addr, the packet
109// is delivered according to the specified filter_ip and filter_port rules.
110void TestRecv(
111 SocketServer* internal, const SocketAddress& internal_addr,
112 SocketServer* external, const SocketAddress external_addrs[4],
113 NATType nat_type, bool filter_ip, bool filter_port) {
114 Thread th_int(internal);
115 Thread th_ext(external);
116
117 SocketAddress server_addr = internal_addr;
118 server_addr.SetPort(0); // Auto-select a port
119 NATServer* nat = new NATServer(
120 nat_type, internal, server_addr, external, external_addrs[0]);
121 NATSocketFactory* natsf = new NATSocketFactory(internal,
122 nat->internal_address());
123
124 TestClient* in = CreateTestClient(natsf, internal_addr);
125 TestClient* out[4];
126 for (int i = 0; i < 4; i++)
127 out[i] = CreateTestClient(external, external_addrs[i]);
128
129 th_int.Start();
130 th_ext.Start();
131
132 const char* buf = "filter_test";
133 size_t len = strlen(buf);
134
135 in->SendTo(buf, len, out[0]->address());
136 SocketAddress trans_addr;
137 EXPECT_TRUE(out[0]->CheckNextPacket(buf, len, &trans_addr));
138
139 out[1]->SendTo(buf, len, trans_addr);
140 EXPECT_TRUE(CheckReceive(in, !filter_ip, buf, len));
141
142 out[2]->SendTo(buf, len, trans_addr);
143 EXPECT_TRUE(CheckReceive(in, !filter_port, buf, len));
144
145 out[3]->SendTo(buf, len, trans_addr);
146 EXPECT_TRUE(CheckReceive(in, !filter_ip && !filter_port, buf, len));
147
148 th_int.Stop();
149 th_ext.Stop();
150
151 delete nat;
152 delete natsf;
153 delete in;
154 for (int i = 0; i < 4; i++)
155 delete out[i];
156}
157
158// Tests that NATServer allocates bindings properly.
159void TestBindings(
160 SocketServer* internal, const SocketAddress& internal_addr,
161 SocketServer* external, const SocketAddress external_addrs[4]) {
162 TestSend(internal, internal_addr, external, external_addrs,
163 NAT_OPEN_CONE, true);
164 TestSend(internal, internal_addr, external, external_addrs,
165 NAT_ADDR_RESTRICTED, true);
166 TestSend(internal, internal_addr, external, external_addrs,
167 NAT_PORT_RESTRICTED, true);
168 TestSend(internal, internal_addr, external, external_addrs,
169 NAT_SYMMETRIC, false);
170}
171
172// Tests that NATServer filters packets properly.
173void TestFilters(
174 SocketServer* internal, const SocketAddress& internal_addr,
175 SocketServer* external, const SocketAddress external_addrs[4]) {
176 TestRecv(internal, internal_addr, external, external_addrs,
177 NAT_OPEN_CONE, false, false);
178 TestRecv(internal, internal_addr, external, external_addrs,
179 NAT_ADDR_RESTRICTED, true, false);
180 TestRecv(internal, internal_addr, external, external_addrs,
181 NAT_PORT_RESTRICTED, true, true);
182 TestRecv(internal, internal_addr, external, external_addrs,
183 NAT_SYMMETRIC, true, true);
184}
185
186bool TestConnectivity(const SocketAddress& src, const IPAddress& dst) {
187 // The physical NAT tests require connectivity to the selected ip from the
188 // internal address used for the NAT. Things like firewalls can break that, so
189 // check to see if it's worth even trying with this ip.
190 scoped_ptr<PhysicalSocketServer> pss(new PhysicalSocketServer());
191 scoped_ptr<AsyncSocket> client(pss->CreateAsyncSocket(src.family(),
192 SOCK_DGRAM));
193 scoped_ptr<AsyncSocket> server(pss->CreateAsyncSocket(src.family(),
194 SOCK_DGRAM));
195 if (client->Bind(SocketAddress(src.ipaddr(), 0)) != 0 ||
196 server->Bind(SocketAddress(dst, 0)) != 0) {
197 return false;
198 }
199 const char* buf = "hello other socket";
200 size_t len = strlen(buf);
201 int sent = client->SendTo(buf, len, server->GetLocalAddress());
202 SocketAddress addr;
203 const size_t kRecvBufSize = 64;
204 char recvbuf[kRecvBufSize];
205 Thread::Current()->SleepMs(100);
206 int received = server->RecvFrom(recvbuf, kRecvBufSize, &addr);
207 return received == sent && ::memcmp(buf, recvbuf, len) == 0;
208}
209
210void TestPhysicalInternal(const SocketAddress& int_addr) {
211 BasicNetworkManager network_manager;
212 network_manager.set_ipv6_enabled(true);
213 network_manager.StartUpdating();
214 // Process pending messages so the network list is updated.
215 Thread::Current()->ProcessMessages(0);
216
217 std::vector<Network*> networks;
218 network_manager.GetNetworks(&networks);
219 if (networks.empty()) {
220 LOG(LS_WARNING) << "Not enough network adapters for test.";
221 return;
222 }
223
224 SocketAddress ext_addr1(int_addr);
225 SocketAddress ext_addr2;
226 // Find an available IP with matching family. The test breaks if int_addr
227 // can't talk to ip, so check for connectivity as well.
228 for (std::vector<Network*>::iterator it = networks.begin();
229 it != networks.end(); ++it) {
230 const IPAddress& ip = (*it)->ip();
231 if (ip.family() == int_addr.family() && TestConnectivity(int_addr, ip)) {
232 ext_addr2.SetIP(ip);
233 break;
234 }
235 }
236 if (ext_addr2.IsNil()) {
237 LOG(LS_WARNING) << "No available IP of same family as " << int_addr;
238 return;
239 }
240
241 LOG(LS_INFO) << "selected ip " << ext_addr2.ipaddr();
242
243 SocketAddress ext_addrs[4] = {
244 SocketAddress(ext_addr1),
245 SocketAddress(ext_addr2),
246 SocketAddress(ext_addr1),
247 SocketAddress(ext_addr2)
248 };
249
250 PhysicalSocketServer* int_pss = new PhysicalSocketServer();
251 PhysicalSocketServer* ext_pss = new PhysicalSocketServer();
252
253 TestBindings(int_pss, int_addr, ext_pss, ext_addrs);
254 TestFilters(int_pss, int_addr, ext_pss, ext_addrs);
255}
256
257TEST(NatTest, TestPhysicalIPv4) {
258 TestPhysicalInternal(SocketAddress("127.0.0.1", 0));
259}
260
261TEST(NatTest, TestPhysicalIPv6) {
262 if (HasIPv6Enabled()) {
263 TestPhysicalInternal(SocketAddress("::1", 0));
264 } else {
265 LOG(LS_WARNING) << "No IPv6, skipping";
266 }
267}
268
269class TestVirtualSocketServer : public VirtualSocketServer {
270 public:
271 explicit TestVirtualSocketServer(SocketServer* ss)
272 : VirtualSocketServer(ss) {}
273 // Expose this publicly
274 IPAddress GetNextIP(int af) { return VirtualSocketServer::GetNextIP(af); }
275};
276
277void TestVirtualInternal(int family) {
278 TestVirtualSocketServer* int_vss = new TestVirtualSocketServer(
279 new PhysicalSocketServer());
280 TestVirtualSocketServer* ext_vss = new TestVirtualSocketServer(
281 new PhysicalSocketServer());
282
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, int_addr, ext_vss, ext_addrs);
292 TestFilters(int_vss, int_addr, ext_vss, ext_addrs);
293}
294
295TEST(NatTest, TestVirtualIPv4) {
296 TestVirtualInternal(AF_INET);
297}
298
299TEST(NatTest, TestVirtualIPv6) {
300 if (HasIPv6Enabled()) {
301 TestVirtualInternal(AF_INET6);
302 } else {
303 LOG(LS_WARNING) << "No IPv6, skipping";
304 }
305}
306
307// TODO: Finish this test
308class NatTcpTest : public testing::Test, public sigslot::has_slots<> {
309 public:
310 NatTcpTest() : connected_(false) {}
311 virtual void SetUp() {
312 int_vss_ = new TestVirtualSocketServer(new PhysicalSocketServer());
313 ext_vss_ = new TestVirtualSocketServer(new PhysicalSocketServer());
314 nat_ = new NATServer(NAT_OPEN_CONE, int_vss_, SocketAddress(),
315 ext_vss_, SocketAddress());
316 natsf_ = new NATSocketFactory(int_vss_, nat_->internal_address());
317 }
318 void OnConnectEvent(AsyncSocket* socket) {
319 connected_ = true;
320 }
321 void OnAcceptEvent(AsyncSocket* socket) {
322 accepted_ = server_->Accept(NULL);
323 }
324 void OnCloseEvent(AsyncSocket* socket, int error) {
325 }
326 void ConnectEvents() {
327 server_->SignalReadEvent.connect(this, &NatTcpTest::OnAcceptEvent);
328 client_->SignalConnectEvent.connect(this, &NatTcpTest::OnConnectEvent);
329 }
330 TestVirtualSocketServer* int_vss_;
331 TestVirtualSocketServer* ext_vss_;
332 NATServer* nat_;
333 NATSocketFactory* natsf_;
334 AsyncSocket* client_;
335 AsyncSocket* server_;
336 AsyncSocket* accepted_;
337 bool connected_;
338};
339
340TEST_F(NatTcpTest, DISABLED_TestConnectOut) {
341 server_ = ext_vss_->CreateAsyncSocket(SOCK_STREAM);
342 server_->Bind(SocketAddress());
343 server_->Listen(5);
344
345 client_ = int_vss_->CreateAsyncSocket(SOCK_STREAM);
346 EXPECT_GE(0, client_->Bind(SocketAddress()));
347 EXPECT_GE(0, client_->Connect(server_->GetLocalAddress()));
348
349
350 ConnectEvents();
351
352 EXPECT_TRUE_WAIT(connected_, 1000);
353 EXPECT_EQ(client_->GetRemoteAddress(), server_->GetLocalAddress());
354 EXPECT_EQ(client_->GetRemoteAddress(), accepted_->GetLocalAddress());
355 EXPECT_EQ(client_->GetLocalAddress(), accepted_->GetRemoteAddress());
356
357 client_->Close();
358}
359//#endif