blob: 4d29e7df9130a34bc345249ed4090e2bee220d02 [file] [log] [blame]
Giulio Grassi624f6c62014-02-18 19:42:14 +01001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyev319f2c82015-01-07 14:56:53 -08003 * Copyright (c) 2014-2015, Regents of the University of California,
4 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology,
9 * The University of Memphis.
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -070010 *
11 * This file is part of NFD (Named Data Networking Forwarding Daemon).
12 * See AUTHORS.md for complete list of NFD authors and contributors.
13 *
14 * NFD is free software: you can redistribute it and/or modify it under the terms
15 * of the GNU General Public License as published by the Free Software Foundation,
16 * either version 3 of the License, or (at your option) any later version.
17 *
18 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20 * PURPOSE. See the GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along with
23 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
Steve DiBenedettoef04f272014-06-04 14:28:31 -060024 */
Giulio Grassi624f6c62014-02-18 19:42:14 +010025
26#include "face/udp-factory.hpp"
Alexander Afanasyev70aaf8a2014-12-13 00:44:22 -080027#include "core/network-interface.hpp"
Junxiao Shi7e2413b2014-03-02 11:15:09 -070028
29#include "tests/test-common.hpp"
Alexander Afanasyev613e2a92014-04-15 13:36:58 -070030#include "tests/limited-io.hpp"
Chengyu Fan4381fb62015-01-14 11:37:04 -070031#include "face-history.hpp"
Giulio Grassi624f6c62014-02-18 19:42:14 +010032
33namespace nfd {
34namespace tests {
35
36BOOST_FIXTURE_TEST_SUITE(FaceUdp, BaseFixture)
37
Steve DiBenedettoef04f272014-06-04 14:28:31 -060038BOOST_AUTO_TEST_CASE(GetChannels)
39{
40 UdpFactory factory;
41 BOOST_REQUIRE_EQUAL(factory.getChannels().empty(), true);
42
43 std::vector<shared_ptr<const Channel> > expectedChannels;
44
45 expectedChannels.push_back(factory.createChannel("127.0.0.1", "20070"));
46 expectedChannels.push_back(factory.createChannel("127.0.0.1", "20071"));
47 expectedChannels.push_back(factory.createChannel("::1", "20071"));
48
49 std::list<shared_ptr<const Channel> > channels = factory.getChannels();
50 for (std::list<shared_ptr<const Channel> >::const_iterator i = channels.begin();
51 i != channels.end(); ++i)
52 {
53 std::vector<shared_ptr<const Channel> >::iterator pos =
54 std::find(expectedChannels.begin(), expectedChannels.end(), *i);
55
56 BOOST_REQUIRE(pos != expectedChannels.end());
57 expectedChannels.erase(pos);
58 }
59
60 BOOST_CHECK_EQUAL(expectedChannels.size(), 0);
61}
62
Giulio Grassi624f6c62014-02-18 19:42:14 +010063class FactoryErrorCheck : protected BaseFixture
64{
65public:
Alexander Afanasyev86bc91a2014-08-28 22:29:16 -070066 bool
67 isTheSameMulticastEndpoint(const UdpFactory::Error& e) {
Giulio Grassi624f6c62014-02-18 19:42:14 +010068 return strcmp(e.what(),
69 "Cannot create the requested UDP unicast channel, local "
70 "endpoint is already allocated for a UDP multicast face") == 0;
71 }
Junxiao Shi7e2413b2014-03-02 11:15:09 -070072
Alexander Afanasyev86bc91a2014-08-28 22:29:16 -070073 bool
74 isNotMulticastAddress(const UdpFactory::Error& e) {
Giulio Grassi624f6c62014-02-18 19:42:14 +010075 return strcmp(e.what(),
76 "Cannot create the requested UDP multicast face, "
77 "the multicast group given as input is not a multicast address") == 0;
78 }
Junxiao Shi7e2413b2014-03-02 11:15:09 -070079
Alexander Afanasyev86bc91a2014-08-28 22:29:16 -070080 bool
81 isTheSameUnicastEndpoint(const UdpFactory::Error& e) {
Giulio Grassi624f6c62014-02-18 19:42:14 +010082 return strcmp(e.what(),
83 "Cannot create the requested UDP multicast face, local "
84 "endpoint is already allocated for a UDP unicast channel") == 0;
85 }
Junxiao Shi7e2413b2014-03-02 11:15:09 -070086
Alexander Afanasyev86bc91a2014-08-28 22:29:16 -070087 bool
88 isLocalEndpointOnDifferentGroup(const UdpFactory::Error& e) {
Giulio Grassi624f6c62014-02-18 19:42:14 +010089 return strcmp(e.what(),
90 "Cannot create the requested UDP multicast face, local "
91 "endpoint is already allocated for a UDP multicast face "
92 "on a different multicast group") == 0;
93 }
94};
Junxiao Shi7e2413b2014-03-02 11:15:09 -070095
Giulio Grassi624f6c62014-02-18 19:42:14 +010096BOOST_FIXTURE_TEST_CASE(ChannelMapUdp, FactoryErrorCheck)
97{
98 using boost::asio::ip::udp;
Junxiao Shi7e2413b2014-03-02 11:15:09 -070099
Giulio Grassi624f6c62014-02-18 19:42:14 +0100100 UdpFactory factory = UdpFactory();
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700101
Giulio Grassi624f6c62014-02-18 19:42:14 +0100102 //to instantiate multicast face on a specific ip address, change interfaceIp
103 std::string interfaceIp = "0.0.0.0";
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700104
Giulio Grassi624f6c62014-02-18 19:42:14 +0100105 shared_ptr<UdpChannel> channel1 = factory.createChannel("127.0.0.1", "20070");
106 shared_ptr<UdpChannel> channel1a = factory.createChannel("127.0.0.1", "20070");
107 BOOST_CHECK_EQUAL(channel1, channel1a);
Junxiao Shi61e3cc52014-03-03 20:40:28 -0700108 BOOST_CHECK_EQUAL(channel1->getUri().toString(), "udp4://127.0.0.1:20070");
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700109
Giulio Grassi624f6c62014-02-18 19:42:14 +0100110 shared_ptr<UdpChannel> channel2 = factory.createChannel("127.0.0.1", "20071");
111 BOOST_CHECK_NE(channel1, channel2);
112
113 shared_ptr<UdpChannel> channel3 = factory.createChannel(interfaceIp, "20070");
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700114
Junxiao Shi61e3cc52014-03-03 20:40:28 -0700115 shared_ptr<UdpChannel> channel4 = factory.createChannel("::1", "20071");
116 BOOST_CHECK_NE(channel2, channel4);
117 BOOST_CHECK_EQUAL(channel4->getUri().toString(), "udp6://[::1]:20071");
118
Giulio Grassi624f6c62014-02-18 19:42:14 +0100119 //same endpoint of a unicast channel
120 BOOST_CHECK_EXCEPTION(factory.createMulticastFace(interfaceIp,
121 "224.0.0.1",
122 "20070"),
123 UdpFactory::Error,
124 isTheSameUnicastEndpoint);
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700125
126
Giulio Grassi624f6c62014-02-18 19:42:14 +0100127 shared_ptr<MulticastUdpFace> multicastFace1 = factory.createMulticastFace(interfaceIp,
128 "224.0.0.1",
129 "20072");
130 shared_ptr<MulticastUdpFace> multicastFace1a = factory.createMulticastFace(interfaceIp,
131 "224.0.0.1",
132 "20072");
133 BOOST_CHECK_EQUAL(multicastFace1, multicastFace1a);
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700134
135
Giulio Grassi624f6c62014-02-18 19:42:14 +0100136 //same endpoint of a multicast face
137 BOOST_CHECK_EXCEPTION(factory.createChannel(interfaceIp, "20072"),
138 UdpFactory::Error,
139 isTheSameMulticastEndpoint);
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700140
Giulio Grassi624f6c62014-02-18 19:42:14 +0100141 //same multicast endpoint, different group
142 BOOST_CHECK_EXCEPTION(factory.createMulticastFace(interfaceIp,
143 "224.0.0.42",
144 "20072"),
145 UdpFactory::Error,
146 isLocalEndpointOnDifferentGroup);
147
148 BOOST_CHECK_EXCEPTION(factory.createMulticastFace(interfaceIp,
149 "192.168.10.15",
150 "20025"),
151 UdpFactory::Error,
152 isNotMulticastAddress);
153
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700154
Giulio Grassi624f6c62014-02-18 19:42:14 +0100155// //Test commented because it required to be run in a machine that can resolve ipv6 query
156// shared_ptr<UdpChannel> channel1v6 = factory.createChannel(//"::1",
157// "fe80::5e96:9dff:fe7d:9c8d%en1",
158// //"fe80::aa54:b2ff:fe08:27b8%wlan0",
159// "20070");
160//
161// //the creation of multicastFace2 works properly. It has been disable because it needs an IP address of
162// //an available network interface (different from the first one used)
163// shared_ptr<MulticastUdpFace> multicastFace2 = factory.createMulticastFace("192.168.1.17",
164// "224.0.0.1",
165// "20073");
166// BOOST_CHECK_NE(multicastFace1, multicastFace2);
167//
168//
169// //ipv6 - work in progress
170// shared_ptr<MulticastUdpFace> multicastFace3 = factory.createMulticastFace("fe80::5e96:9dff:fe7d:9c8d%en1",
171// "FF01:0:0:0:0:0:0:2",
172// "20073");
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700173//
Giulio Grassi624f6c62014-02-18 19:42:14 +0100174// shared_ptr<MulticastUdpFace> multicastFace4 = factory.createMulticastFace("fe80::aa54:b2ff:fe08:27b8%wlan0",
175// "FF01:0:0:0:0:0:0:2",
176// "20073");
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700177//
Giulio Grassi624f6c62014-02-18 19:42:14 +0100178// BOOST_CHECK_EQUAL(multicastFace3, multicastFace4);
179//
180// shared_ptr<MulticastUdpFace> multicastFace5 = factory.createMulticastFace("::1",
181// "FF01:0:0:0:0:0:0:2",
182// "20073");
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700183//
Giulio Grassi624f6c62014-02-18 19:42:14 +0100184// BOOST_CHECK_NE(multicastFace3, multicastFace5);
185//
186// //same local ipv6 endpoint for a different multicast group
187// BOOST_CHECK_THROW(factory.createMulticastFace("fe80::aa54:b2ff:fe08:27b8%wlan0",
188// "FE01:0:0:0:0:0:0:2",
189// "20073"),
190// UdpFactory::Error);
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700191//
Giulio Grassi624f6c62014-02-18 19:42:14 +0100192// //same local ipv6 (expect for th port number) endpoint for a different multicast group
193// BOOST_CHECK_THROW(factory.createMulticastFace("fe80::aa54:b2ff:fe08:27b8%wlan0",
194// "FE01:0:0:0:0:0:0:2",
195// "20075"),
196// UdpFactory::Error);
197//
198// BOOST_CHECK_THROW(factory.createMulticastFace("fa80::20a:9dff:fef6:12ff",
199// "FE12:0:0:0:0:0:0:2",
200// "20075"),
201// UdpFactory::Error);
202//
203// //not a multicast ipv6
204// BOOST_CHECK_THROW(factory.createMulticastFace("fa80::20a:9dff:fef6:12ff",
205// "A112:0:0:0:0:0:0:2",
206// "20075"),
207// UdpFactory::Error);
Giulio Grassi624f6c62014-02-18 19:42:14 +0100208}
209
Alexander Afanasyev86bc91a2014-08-28 22:29:16 -0700210class FaceCreateFixture : protected BaseFixture
211{
212public:
213 void
214 ignore()
215 {
216 }
217
218 void
219 checkError(const std::string& errorActual, const std::string& errorExpected)
220 {
221 BOOST_CHECK_EQUAL(errorActual, errorExpected);
222 }
223
224 void
225 failIfError(const std::string& errorActual)
226 {
227 BOOST_FAIL("No error expected, but got: [" << errorActual << "]");
228 }
229};
230
231BOOST_FIXTURE_TEST_CASE(FaceCreate, FaceCreateFixture)
232{
233 UdpFactory factory = UdpFactory();
234
Chengyu Fan4381fb62015-01-14 11:37:04 -0700235 factory.createFace(FaceUri("udp4://127.0.0.1:6363"),
Alexander Afanasyev86bc91a2014-08-28 22:29:16 -0700236 bind(&FaceCreateFixture::ignore, this),
Chengyu Fan4381fb62015-01-14 11:37:04 -0700237 bind(&FaceCreateFixture::checkError, this, _1,
238 "No channels available to connect to 127.0.0.1:6363"));
Giulio Grassi624f6c62014-02-18 19:42:14 +0100239
Alexander Afanasyeva39b90b2014-03-05 15:31:00 +0000240 factory.createChannel("127.0.0.1", "20071");
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700241
Giulio Grassi624f6c62014-02-18 19:42:14 +0100242 factory.createFace(FaceUri("udp4://127.0.0.1:20070"),
Chengyu Fan4381fb62015-01-14 11:37:04 -0700243 bind(&FaceCreateFixture::ignore, this),
244 bind(&FaceCreateFixture::failIfError, this, _1));
245}
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700246
Chengyu Fan4381fb62015-01-14 11:37:04 -0700247class EndToEndIpv4
248{
249public:
250 static const std::string
251 getScheme()
252 {
253 return "udp4";
254 }
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700255
Chengyu Fan4381fb62015-01-14 11:37:04 -0700256 static const std::string
257 getLocalIp()
258 {
259 return "127.0.0.1";
260 }
Giulio Grassi624f6c62014-02-18 19:42:14 +0100261
Chengyu Fan4381fb62015-01-14 11:37:04 -0700262 static const std::string
263 getPort1()
264 {
265 return "20071";
266 }
267
268 static const std::string
269 getPort2()
270 {
271 return "20072";
272 }
273
274 static const std::string
275 getPort3()
276 {
277 return "20073";
278 }
279
280 static const FaceUri
281 getFaceUri1()
282 {
283 return FaceUri("udp4://127.0.0.1:20071");
284 }
285
286 static const FaceUri
287 getFaceUri2()
288 {
289 return FaceUri("udp4://127.0.0.1:20072");
290 }
291
292 static const FaceUri
293 getFaceUri3()
294 {
295 return FaceUri("udp4://127.0.0.1:20073");
296 }
297};
298
299class EndToEndIpv6
300{
301public:
302 static const std::string
303 getScheme()
304 {
305 return "udp6";
306 }
307
308 static const std::string
309 getLocalIp()
310 {
311 return "::1";
312 }
313
314 static const std::string
315 getPort1()
316 {
317 return "20071";
318 }
319
320 static const std::string
321 getPort2()
322 {
323 return "20072";
324 }
325
326 static const std::string
327 getPort3()
328 {
329 return "20073";
330 }
331
332 static const FaceUri
333 getFaceUri1()
334 {
335 return FaceUri("udp6://[::1]:20071");
336 }
337
338 static const FaceUri
339 getFaceUri2()
340 {
341 return FaceUri("udp6://[::1]:20072");
342 }
343
344 static const FaceUri
345 getFaceUri3()
346 {
347 return FaceUri("udp6://[::1]:20073");
348 }
349};
350
351typedef boost::mpl::list<EndToEndIpv4, EndToEndIpv6> EndToEndAddresses;
352
353// end to end communication
354BOOST_AUTO_TEST_CASE_TEMPLATE(EndToEnd, A, EndToEndAddresses)
355{
356 LimitedIo limitedIo;
357 UdpFactory factory;
358
359 shared_ptr<UdpChannel> channel1 = factory.createChannel(A::getLocalIp(), A::getPort1());
360
361 // face1 (on channel1) connects to face2 (on channel2, to be created)
362 shared_ptr<Face> face1;
363 unique_ptr<FaceHistory> history1;
364 factory.createFace(A::getFaceUri2(),
365 [&] (shared_ptr<Face> newFace) {
366 face1 = newFace;
367 history1.reset(new FaceHistory(*face1, limitedIo));
368 limitedIo.afterOp();
369 },
370 [] (const std::string& reason) { BOOST_ERROR(reason); });
371
372 limitedIo.run(1, time::seconds(1));
373 BOOST_REQUIRE(face1 != nullptr);
374 BOOST_CHECK_EQUAL(face1->getRemoteUri(), A::getFaceUri2());
375 BOOST_CHECK_EQUAL(face1->getLocalUri(), A::getFaceUri1());
376 BOOST_CHECK_EQUAL(face1->isLocal(), false); // UdpFace is never local
377 BOOST_CHECK_EQUAL(face1->getCounters().getNInBytes(), 0);
378 BOOST_CHECK_EQUAL(face1->getCounters().getNOutBytes(), 0);
379
380 // channel2 creation must be after face1 creation,
381 // otherwise channel2's endpoint would be prohibited
382 shared_ptr<UdpChannel> channel2 = factory.createChannel(A::getLocalIp(), A::getPort2());
383 shared_ptr<Face> face2;
384 unique_ptr<FaceHistory> history2;
385 channel2->listen([&] (shared_ptr<Face> newFace) {
386 BOOST_CHECK(face2 == nullptr);
387 face2 = newFace;
388 history2.reset(new FaceHistory(*face2, limitedIo));
389 limitedIo.afterOp();
390 },
391 [] (const std::string& reason) { BOOST_ERROR(reason); });
392
393 limitedIo.run(1, time::seconds(1));
394 BOOST_CHECK(face2 == nullptr); // face2 shouldn't be created until face1 sends something
395
396 shared_ptr<Interest> interest1 = makeInterest("/I1");
397 shared_ptr<Interest> interest2 = makeInterest("/I2");
398 shared_ptr<Data> data1 = makeData("/D1");
399 shared_ptr<Data> data2 = makeData("/D2");
400
401 // face1 sends to channel2, creates face2
402 face1->sendInterest(*interest1);
403 face1->sendData(*data1);
404 face1->sendData(*data1);
405 face1->sendData(*data1);
406 size_t nBytesSent1 = interest1->wireEncode().size() + 3 * data1->wireEncode().size();
407
408 limitedIo.run(5, time::seconds(1)); // 1 accept, 4 receives
409
410 BOOST_REQUIRE(face2 != nullptr);
411 BOOST_CHECK_EQUAL(face2->getRemoteUri(), A::getFaceUri1());
412 BOOST_CHECK_EQUAL(face2->getLocalUri(), A::getFaceUri2());
413 BOOST_CHECK_EQUAL(face2->isLocal(), false); // UdpFace is never local
414 BOOST_CHECK_EQUAL(face2->getCounters().getNInBytes(), nBytesSent1);
Junxiao Shi5dd26c32014-07-20 23:15:14 -0700415 BOOST_CHECK_EQUAL(face2->getCounters().getNOutBytes(), 0);
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700416
Chengyu Fan4381fb62015-01-14 11:37:04 -0700417 BOOST_REQUIRE_EQUAL(history2->receivedInterests.size(), 1);
418 BOOST_CHECK_EQUAL(history2->receivedInterests.front().getName(), interest1->getName());
419 BOOST_REQUIRE_EQUAL(history2->receivedData.size(), 3);
420 BOOST_CHECK_EQUAL(history2->receivedData.front().getName(), data1->getName());
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700421
Chengyu Fan4381fb62015-01-14 11:37:04 -0700422 // face2 sends to face1
423 face2->sendInterest(*interest2);
424 face2->sendInterest(*interest2);
425 face2->sendInterest(*interest2);
426 face2->sendData(*data2);
427 size_t nBytesSent2 = 3 * interest2->wireEncode().size() + data2->wireEncode().size();
Giulio Grassi624f6c62014-02-18 19:42:14 +0100428
Chengyu Fan4381fb62015-01-14 11:37:04 -0700429 limitedIo.run(4, time::seconds(1)); // 4 receives
Giulio Grassi624f6c62014-02-18 19:42:14 +0100430
Chengyu Fan4381fb62015-01-14 11:37:04 -0700431 BOOST_REQUIRE_EQUAL(history1->receivedInterests.size(), 3);
432 BOOST_CHECK_EQUAL(history1->receivedInterests.front().getName(), interest2->getName());
433 BOOST_REQUIRE_EQUAL(history1->receivedData.size(), 1);
434 BOOST_CHECK_EQUAL(history1->receivedData.front().getName(), data2->getName());
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700435
Chengyu Fan4381fb62015-01-14 11:37:04 -0700436 // counters
Junxiao Shi79494162014-04-02 18:25:11 -0700437 const FaceCounters& counters1 = face1->getCounters();
Chengyu Fan4381fb62015-01-14 11:37:04 -0700438 BOOST_CHECK_EQUAL(counters1.getNInInterests(), 3);
439 BOOST_CHECK_EQUAL(counters1.getNInDatas(), 1);
440 BOOST_CHECK_EQUAL(counters1.getNOutInterests(), 1);
441 BOOST_CHECK_EQUAL(counters1.getNOutDatas(), 3);
Junxiao Shi5dd26c32014-07-20 23:15:14 -0700442 BOOST_CHECK_EQUAL(counters1.getNInBytes(), nBytesSent2);
Chengyu Fan4381fb62015-01-14 11:37:04 -0700443 BOOST_CHECK_EQUAL(counters1.getNOutBytes(), nBytesSent1);
Alexander Afanasyev7e698e62014-03-07 16:48:35 +0000444
Junxiao Shi79494162014-04-02 18:25:11 -0700445 const FaceCounters& counters2 = face2->getCounters();
Chengyu Fan4381fb62015-01-14 11:37:04 -0700446 BOOST_CHECK_EQUAL(counters2.getNInInterests(), 1);
447 BOOST_CHECK_EQUAL(counters2.getNInDatas(), 3);
448 BOOST_CHECK_EQUAL(counters2.getNOutInterests(), 3);
449 BOOST_CHECK_EQUAL(counters2.getNOutDatas(), 1);
450 BOOST_CHECK_EQUAL(counters2.getNInBytes(), nBytesSent1);
Junxiao Shi5dd26c32014-07-20 23:15:14 -0700451 BOOST_CHECK_EQUAL(counters2.getNOutBytes(), nBytesSent2);
Alexander Afanasyeva39b90b2014-03-05 15:31:00 +0000452}
Giulio Grassi624f6c62014-02-18 19:42:14 +0100453
Chengyu Fan4381fb62015-01-14 11:37:04 -0700454// channel accepting multiple incoming connections
455BOOST_AUTO_TEST_CASE_TEMPLATE(MultipleAccepts, A, EndToEndAddresses)
Alexander Afanasyeva39b90b2014-03-05 15:31:00 +0000456{
Chengyu Fan4381fb62015-01-14 11:37:04 -0700457 LimitedIo limitedIo;
Alexander Afanasyeva39b90b2014-03-05 15:31:00 +0000458 UdpFactory factory;
459
Chengyu Fan4381fb62015-01-14 11:37:04 -0700460 // channel1 is listening
461 shared_ptr<UdpChannel> channel1 = factory.createChannel(A::getLocalIp(), A::getPort1());
462 std::vector<shared_ptr<Face>> faces1;
463 channel1->listen([&] (shared_ptr<Face> newFace) {
464 faces1.push_back(newFace);
465 limitedIo.afterOp();
466 },
467 [] (const std::string& reason) { BOOST_ERROR(reason); });
Alexander Afanasyeva39b90b2014-03-05 15:31:00 +0000468
Chengyu Fan4381fb62015-01-14 11:37:04 -0700469 // face2 (on channel2) connects to channel1
470 shared_ptr<UdpChannel> channel2 = factory.createChannel(A::getLocalIp(), A::getPort2());
471 BOOST_CHECK_NE(channel1, channel2);
472 shared_ptr<Face> face2;
473 boost::asio::ip::address ipAddress2 = boost::asio::ip::address::from_string(A::getLocalIp());
474 udp::Endpoint endpoint2(ipAddress2, boost::lexical_cast<uint16_t>(A::getPort1()));
475 channel2->connect(endpoint2,
476 [&] (shared_ptr<Face> newFace) {
477 face2 = newFace;
478 limitedIo.afterOp();
479 },
480 [] (const std::string& reason) { BOOST_ERROR(reason); });
Alexander Afanasyeva39b90b2014-03-05 15:31:00 +0000481
Chengyu Fan4381fb62015-01-14 11:37:04 -0700482 limitedIo.run(1, time::seconds(1)); // 1 create (on channel2)
483 BOOST_REQUIRE(face2 != nullptr);
484 BOOST_CHECK_EQUAL(faces1.size(), 0); // channel1 won't create face until face2 sends something
Alexander Afanasyeva39b90b2014-03-05 15:31:00 +0000485
Chengyu Fan4381fb62015-01-14 11:37:04 -0700486 // face3 (on channel3) connects to channel1
487 shared_ptr<UdpChannel> channel3 = factory.createChannel(A::getLocalIp(), A::getPort3());
488 BOOST_CHECK_NE(channel1, channel3);
489 shared_ptr<Face> face3;
490 boost::asio::ip::address ipAddress3 = boost::asio::ip::address::from_string(A::getLocalIp());
491 udp::Endpoint endpoint3(ipAddress3, boost::lexical_cast<uint16_t>(A::getPort1()));
492 channel3->connect(endpoint3,
493 [&] (shared_ptr<Face> newFace) {
494 face3 = newFace;
495 limitedIo.afterOp();
496 },
497 [] (const std::string& reason) { BOOST_ERROR(reason); });
Alexander Afanasyeva39b90b2014-03-05 15:31:00 +0000498
Chengyu Fan4381fb62015-01-14 11:37:04 -0700499 limitedIo.run(1, time::seconds(1)); // 1 create (on channel3)
500 BOOST_REQUIRE(face3 != nullptr);
501 BOOST_CHECK_EQUAL(faces1.size(), 0); // channel1 won't create face until face3 sends something
Alexander Afanasyeva39b90b2014-03-05 15:31:00 +0000502
Chengyu Fan4381fb62015-01-14 11:37:04 -0700503 // face2 sends to channel1
504 shared_ptr<Interest> interest2 = makeInterest("/I2");
505 face2->sendInterest(*interest2);
506 limitedIo.run(1, time::milliseconds(100)); // 1 accept (on channel1)
507 BOOST_REQUIRE_EQUAL(faces1.size(), 1);
508 BOOST_CHECK_EQUAL(channel1->size(), 1);
509 BOOST_CHECK_EQUAL(faces1.at(0)->getRemoteUri(), A::getFaceUri2());
Alexander Afanasyeva39b90b2014-03-05 15:31:00 +0000510
Chengyu Fan4381fb62015-01-14 11:37:04 -0700511 // face3 sends to channel1
512 shared_ptr<Data> data3 = makeData("/D3");
513 face3->sendData(*data3);
514 limitedIo.run(1, time::milliseconds(100)); // 1 accept (on channel1)
515 BOOST_REQUIRE_EQUAL(faces1.size(), 2);
516 BOOST_CHECK_EQUAL(channel1->size(), 2);
517 BOOST_CHECK_EQUAL(faces1.at(1)->getRemoteUri(), A::getFaceUri3());
Giulio Grassi624f6c62014-02-18 19:42:14 +0100518}
519
Chengyu Fan4381fb62015-01-14 11:37:04 -0700520// manually close a face
521BOOST_AUTO_TEST_CASE_TEMPLATE(ManualClose, A, EndToEndAddresses)
Giulio Grassi624f6c62014-02-18 19:42:14 +0100522{
Chengyu Fan4381fb62015-01-14 11:37:04 -0700523 LimitedIo limitedIo;
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700524 UdpFactory factory;
Giulio Grassi624f6c62014-02-18 19:42:14 +0100525
Chengyu Fan4381fb62015-01-14 11:37:04 -0700526 shared_ptr<UdpChannel> channel1 = factory.createChannel(A::getLocalIp(), A::getPort1());
527 shared_ptr<Face> face1;
528 unique_ptr<FaceHistory> history1;
529 factory.createFace(A::getFaceUri2(),
530 [&] (shared_ptr<Face> newFace) {
531 face1 = newFace;
532 history1.reset(new FaceHistory(*face1, limitedIo));
533 limitedIo.afterOp();
534 },
535 [] (const std::string& reason) { BOOST_ERROR(reason); });
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700536
Chengyu Fan4381fb62015-01-14 11:37:04 -0700537 limitedIo.run(1, time::milliseconds(100));
538 BOOST_REQUIRE(face1 != nullptr);
539 BOOST_CHECK_EQUAL(channel1->size(), 1);
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700540
Chengyu Fan4381fb62015-01-14 11:37:04 -0700541 face1->close();
542 getGlobalIoService().poll();
543 BOOST_CHECK_EQUAL(history1->failures.size(), 1);
Giulio Grassi69871f02014-03-09 16:14:44 +0100544 BOOST_CHECK_EQUAL(channel1->size(), 0);
Chengyu Fan4381fb62015-01-14 11:37:04 -0700545}
Junxiao Shi79494162014-04-02 18:25:11 -0700546
Chengyu Fan4381fb62015-01-14 11:37:04 -0700547// automatically close an idle incoming face
548BOOST_AUTO_TEST_CASE_TEMPLATE(IdleClose, A, EndToEndAddresses)
549{
550 LimitedIo limitedIo;
551 UdpFactory factory;
552
553 // channel1 is listening
554 shared_ptr<UdpChannel> channel1 = factory.createChannel(A::getLocalIp(), A::getPort1(),
555 time::seconds(2));
556 shared_ptr<Face> face1;
557 unique_ptr<FaceHistory> history1;
558 channel1->listen([&] (shared_ptr<Face> newFace) {
559 BOOST_CHECK(face1 == nullptr);
560 face1 = newFace;
561 history1.reset(new FaceHistory(*face1, limitedIo));
562 limitedIo.afterOp();
563 },
564 [] (const std::string& reason) { BOOST_ERROR(reason); });
565
566 // face2 (on channel2) connects to channel1
567 shared_ptr<UdpChannel> channel2 = factory.createChannel(A::getLocalIp(), A::getPort2(),
568 time::seconds(2));
569 shared_ptr<Face> face2;
570 unique_ptr<FaceHistory> history2;
571 boost::asio::ip::address ipAddress = boost::asio::ip::address::from_string(A::getLocalIp());
572 udp::Endpoint endpoint(ipAddress, boost::lexical_cast<uint16_t>(A::getPort1()));
573 channel2->connect(endpoint,
574 [&] (shared_ptr<Face> newFace) {
575 face2 = newFace;
576 history2.reset(new FaceHistory(*face2, limitedIo));
577 limitedIo.afterOp();
578 },
579 [] (const std::string& reason) { BOOST_ERROR(reason); });
580
581 limitedIo.run(1, time::milliseconds(100)); // 1 create (on channel2)
582 BOOST_REQUIRE(face2 != nullptr);
583 BOOST_CHECK_EQUAL(face2->isOnDemand(), false);
584
585 // face2 sends to channel1, creates face1
586 shared_ptr<Interest> interest2 = makeInterest("/I2");
587 face2->sendInterest(*interest2);
588
589 limitedIo.run(2, time::seconds(1)); // 1 accept (on channel1), 1 receive (on face1)
Giulio Grassi69871f02014-03-09 16:14:44 +0100590 BOOST_CHECK_EQUAL(channel1->size(), 1);
Chengyu Fan4381fb62015-01-14 11:37:04 -0700591 BOOST_REQUIRE(face1 != nullptr);
592 BOOST_CHECK_EQUAL(face1->isOnDemand(), true);
Junxiao Shi79494162014-04-02 18:25:11 -0700593
Chengyu Fan4381fb62015-01-14 11:37:04 -0700594 limitedIo.defer(time::seconds(1));
595 BOOST_CHECK_EQUAL(history1->failures.size(), 0); // face1 is not idle
596 BOOST_CHECK_EQUAL(history2->failures.size(), 0); // face2 is outgoing face and never closed
Giulio Grassi69871f02014-03-09 16:14:44 +0100597
Chengyu Fan4381fb62015-01-14 11:37:04 -0700598 limitedIo.defer(time::seconds(4));
599 BOOST_CHECK_EQUAL(history1->failures.size(), 1); // face1 is idle and automatically closed
600 BOOST_CHECK_EQUAL(channel1->size(), 0);
601 BOOST_CHECK_EQUAL(history2->failures.size(), 0); // face2 is outgoing face and never closed
Giulio Grassi69871f02014-03-09 16:14:44 +0100602}
603
Alexander Afanasyev70aaf8a2014-12-13 00:44:22 -0800604class FakeNetworkInterfaceFixture : public BaseFixture
605{
606public:
607 FakeNetworkInterfaceFixture()
608 {
609 using namespace boost::asio::ip;
610
611 auto fakeInterfaces = make_shared<std::vector<NetworkInterfaceInfo>>();
612
613 fakeInterfaces->push_back(
614 NetworkInterfaceInfo {0, "eth0",
615 ethernet::Address::fromString("3e:15:c2:8b:65:00"),
616 {address_v4::from_string("0.0.0.0")},
617 {address_v6::from_string("::")},
618 address_v4(),
619 IFF_UP});
620 fakeInterfaces->push_back(
621 NetworkInterfaceInfo {1, "eth0",
622 ethernet::Address::fromString("3e:15:c2:8b:65:00"),
623 {address_v4::from_string("192.168.2.1"), address_v4::from_string("192.168.2.2")},
624 {},
625 address_v4::from_string("192.168.2.255"),
626 0});
627 fakeInterfaces->push_back(
628 NetworkInterfaceInfo {2, "eth1",
629 ethernet::Address::fromString("3e:15:c2:8b:65:00"),
630 {address_v4::from_string("198.51.100.1")},
631 {address_v6::from_string("2001:db8::2"), address_v6::from_string("2001:db8::3")},
632 address_v4::from_string("198.51.100.255"),
633 IFF_MULTICAST | IFF_BROADCAST | IFF_UP});
634
635 setDebugNetworkInterfaces(fakeInterfaces);
636 }
637
638 ~FakeNetworkInterfaceFixture()
639 {
640 setDebugNetworkInterfaces(nullptr);
641 }
642};
643
644BOOST_FIXTURE_TEST_CASE(Bug2292, FakeNetworkInterfaceFixture)
645{
646 using namespace boost::asio::ip;
647
648 UdpFactory factory;
649 factory.prohibitEndpoint(udp::Endpoint(address_v4::from_string("192.168.2.1"), 1024));
650 BOOST_REQUIRE_EQUAL(factory.m_prohibitedEndpoints.size(), 1);
651 BOOST_CHECK((factory.m_prohibitedEndpoints ==
652 std::set<udp::Endpoint> {
653 udp::Endpoint(address_v4::from_string("192.168.2.1"), 1024),
654 }));
655
656 factory.m_prohibitedEndpoints.clear();
657 factory.prohibitEndpoint(udp::Endpoint(address_v6::from_string("2001:db8::1"), 2048));
658 BOOST_REQUIRE_EQUAL(factory.m_prohibitedEndpoints.size(), 1);
659 BOOST_CHECK((factory.m_prohibitedEndpoints ==
660 std::set<udp::Endpoint> {
661 udp::Endpoint(address_v6::from_string("2001:db8::1"), 2048),
662 }));
663
664 factory.m_prohibitedEndpoints.clear();
665 factory.prohibitEndpoint(udp::Endpoint(address_v4(), 1024));
666 BOOST_REQUIRE_EQUAL(factory.m_prohibitedEndpoints.size(), 6);
667 BOOST_CHECK((factory.m_prohibitedEndpoints ==
668 std::set<udp::Endpoint> {
669 udp::Endpoint(address_v4::from_string("192.168.2.1"), 1024),
670 udp::Endpoint(address_v4::from_string("192.168.2.2"), 1024),
671 udp::Endpoint(address_v4::from_string("198.51.100.1"), 1024),
672 udp::Endpoint(address_v4::from_string("198.51.100.255"), 1024),
673 udp::Endpoint(address_v4::from_string("255.255.255.255"), 1024),
674 udp::Endpoint(address_v4::from_string("0.0.0.0"), 1024)
675 }));
676
677 factory.m_prohibitedEndpoints.clear();
678 factory.prohibitEndpoint(udp::Endpoint(address_v6(), 2048));
679 BOOST_REQUIRE_EQUAL(factory.m_prohibitedEndpoints.size(), 3);
680 BOOST_CHECK((factory.m_prohibitedEndpoints ==
681 std::set<udp::Endpoint> {
682 udp::Endpoint(address_v6::from_string("2001:db8::2"), 2048),
683 udp::Endpoint(address_v6::from_string("2001:db8::3"), 2048),
684 udp::Endpoint(address_v6::from_string("::"), 2048),
685 }));
686}
687
Giulio Grassi624f6c62014-02-18 19:42:14 +0100688BOOST_AUTO_TEST_SUITE_END()
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700689
Giulio Grassi624f6c62014-02-18 19:42:14 +0100690} // namespace tests
691} // namespace nfd