OLD | NEW |
| (Empty) |
1 /* | |
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 <algorithm> | |
12 #include <memory> | |
13 #include <string> | |
14 | |
15 #include "webrtc/base/asynctcpsocket.h" | |
16 #include "webrtc/base/gunit.h" | |
17 #include "webrtc/base/logging.h" | |
18 #include "webrtc/base/natserver.h" | |
19 #include "webrtc/base/natsocketfactory.h" | |
20 #include "webrtc/base/nethelpers.h" | |
21 #include "webrtc/base/network.h" | |
22 #include "webrtc/base/physicalsocketserver.h" | |
23 #include "webrtc/base/ptr_util.h" | |
24 #include "webrtc/base/testclient.h" | |
25 #include "webrtc/base/virtualsocketserver.h" | |
26 | |
27 using namespace rtc; | |
28 | |
29 bool 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 | |
36 TestClient* CreateTestClient( | |
37 SocketFactory* factory, const SocketAddress& local_addr) { | |
38 return new TestClient( | |
39 WrapUnique(AsyncUDPSocket::Create(factory, local_addr))); | |
40 } | |
41 | |
42 TestClient* CreateTCPTestClient(AsyncSocket* socket) { | |
43 return new TestClient(MakeUnique<AsyncTCPSocket>(socket, false)); | |
44 } | |
45 | |
46 // 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. | |
49 void 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 | |
58 NATServer* nat = new NATServer(nat_type, internal, server_addr, server_addr, | |
59 external, external_addrs[0]); | |
60 NATSocketFactory* natsf = new NATSocketFactory(internal, | |
61 nat->internal_udp_address(), | |
62 nat->internal_tcp_address()); | |
63 | |
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. | |
101 void 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 | |
110 NATServer* nat = new NATServer(nat_type, internal, server_addr, server_addr, | |
111 external, external_addrs[0]); | |
112 NATSocketFactory* natsf = new NATSocketFactory(internal, | |
113 nat->internal_udp_address(), | |
114 nat->internal_tcp_address()); | |
115 | |
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. | |
151 void 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. | |
165 void 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 | |
178 bool 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. | |
182 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)); | |
187 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); | |
198 int received = server->RecvFrom(recvbuf, kRecvBufSize, &addr, nullptr); | |
199 return received == sent && ::memcmp(buf, recvbuf, len) == 0; | |
200 } | |
201 | |
202 void 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); | |
211 networks.erase(std::remove_if(networks.begin(), networks.end(), | |
212 [](rtc::Network* network) { | |
213 return rtc::kDefaultNetworkIgnoreMask & | |
214 network->type(); | |
215 }), | |
216 networks.end()); | |
217 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) { | |
228 const IPAddress& ip = (*it)->GetBestIP(); | |
229 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 | |
248 std::unique_ptr<PhysicalSocketServer> int_pss(new PhysicalSocketServer()); | |
249 std::unique_ptr<PhysicalSocketServer> ext_pss(new PhysicalSocketServer()); | |
250 | |
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 | |
255 TEST(NatTest, TestPhysicalIPv4) { | |
256 TestPhysicalInternal(SocketAddress("127.0.0.1", 0)); | |
257 } | |
258 | |
259 TEST(NatTest, TestPhysicalIPv6) { | |
260 if (HasIPv6Enabled()) { | |
261 TestPhysicalInternal(SocketAddress("::1", 0)); | |
262 } else { | |
263 LOG(LS_WARNING) << "No IPv6, skipping"; | |
264 } | |
265 } | |
266 | |
267 namespace { | |
268 | |
269 class TestVirtualSocketServer : public VirtualSocketServer { | |
270 public: | |
271 // Expose this publicly | |
272 IPAddress GetNextIP(int af) { return VirtualSocketServer::GetNextIP(af); } | |
273 }; | |
274 | |
275 } // namespace | |
276 | |
277 void TestVirtualInternal(int family) { | |
278 std::unique_ptr<TestVirtualSocketServer> int_vss( | |
279 new TestVirtualSocketServer()); | |
280 std::unique_ptr<TestVirtualSocketServer> ext_vss( | |
281 new TestVirtualSocketServer()); | |
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.get(), int_addr, ext_vss.get(), ext_addrs); | |
292 TestFilters(int_vss.get(), int_addr, ext_vss.get(), ext_addrs); | |
293 } | |
294 | |
295 TEST(NatTest, TestVirtualIPv4) { | |
296 TestVirtualInternal(AF_INET); | |
297 } | |
298 | |
299 TEST(NatTest, TestVirtualIPv6) { | |
300 if (HasIPv6Enabled()) { | |
301 TestVirtualInternal(AF_INET6); | |
302 } else { | |
303 LOG(LS_WARNING) << "No IPv6, skipping"; | |
304 } | |
305 } | |
306 | |
307 class NatTcpTest : public testing::Test, public sigslot::has_slots<> { | |
308 public: | |
309 NatTcpTest() | |
310 : int_addr_("192.168.0.1", 0), | |
311 ext_addr_("10.0.0.1", 0), | |
312 connected_(false), | |
313 int_vss_(new TestVirtualSocketServer()), | |
314 ext_vss_(new TestVirtualSocketServer()), | |
315 int_thread_(new Thread(int_vss_.get())), | |
316 ext_thread_(new Thread(ext_vss_.get())), | |
317 nat_(new NATServer(NAT_OPEN_CONE, | |
318 int_vss_.get(), | |
319 int_addr_, | |
320 int_addr_, | |
321 ext_vss_.get(), | |
322 ext_addr_)), | |
323 natsf_(new NATSocketFactory(int_vss_.get(), | |
324 nat_->internal_udp_address(), | |
325 nat_->internal_tcp_address())) { | |
326 int_thread_->Start(); | |
327 ext_thread_->Start(); | |
328 } | |
329 | |
330 void OnConnectEvent(AsyncSocket* socket) { | |
331 connected_ = true; | |
332 } | |
333 | |
334 void OnAcceptEvent(AsyncSocket* socket) { | |
335 accepted_.reset(server_->Accept(nullptr)); | |
336 } | |
337 | |
338 void OnCloseEvent(AsyncSocket* socket, int error) { | |
339 } | |
340 | |
341 void ConnectEvents() { | |
342 server_->SignalReadEvent.connect(this, &NatTcpTest::OnAcceptEvent); | |
343 client_->SignalConnectEvent.connect(this, &NatTcpTest::OnConnectEvent); | |
344 } | |
345 | |
346 SocketAddress int_addr_; | |
347 SocketAddress ext_addr_; | |
348 bool connected_; | |
349 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_; | |
358 }; | |
359 | |
360 TEST_F(NatTcpTest, DISABLED_TestConnectOut) { | |
361 server_.reset(ext_vss_->CreateAsyncSocket(SOCK_STREAM)); | |
362 server_->Bind(ext_addr_); | |
363 server_->Listen(5); | |
364 | |
365 client_.reset(natsf_->CreateAsyncSocket(SOCK_STREAM)); | |
366 EXPECT_GE(0, client_->Bind(int_addr_)); | |
367 EXPECT_GE(0, client_->Connect(server_->GetLocalAddress())); | |
368 | |
369 ConnectEvents(); | |
370 | |
371 EXPECT_TRUE_WAIT(connected_, 1000); | |
372 EXPECT_EQ(client_->GetRemoteAddress(), server_->GetLocalAddress()); | |
373 EXPECT_EQ(accepted_->GetRemoteAddress().ipaddr(), ext_addr_.ipaddr()); | |
374 | |
375 std::unique_ptr<rtc::TestClient> in(CreateTCPTestClient(client_.release())); | |
376 std::unique_ptr<rtc::TestClient> out( | |
377 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)); | |
388 } | |
389 // #endif | |
OLD | NEW |