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