blob: 44772ecd5a73eba35cd901111de2974695fae93e [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
Davide Pesavento94279412015-02-27 01:29:32 +0100120 BOOST_CHECK_EXCEPTION(factory.createMulticastFace(interfaceIp, "224.0.0.1", "20070"),
121 UdpFactory::Error, isTheSameUnicastEndpoint);
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700122
Davide Pesavento94279412015-02-27 01:29:32 +0100123 auto multicastFace1 = factory.createMulticastFace(interfaceIp, "224.0.0.1", "20072");
124 auto multicastFace1a = factory.createMulticastFace(interfaceIp, "224.0.0.1", "20072");
Giulio Grassi624f6c62014-02-18 19:42:14 +0100125 BOOST_CHECK_EQUAL(multicastFace1, multicastFace1a);
Davide Pesavento94279412015-02-27 01:29:32 +0100126 BOOST_CHECK_EQUAL(multicastFace1->isLocal(), false);
127 BOOST_CHECK_EQUAL(multicastFace1->isOnDemand(), false);
128 BOOST_CHECK_EQUAL(multicastFace1->isMultiAccess(), true);
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700129
Giulio Grassi624f6c62014-02-18 19:42:14 +0100130 //same endpoint of a multicast face
131 BOOST_CHECK_EXCEPTION(factory.createChannel(interfaceIp, "20072"),
Davide Pesavento94279412015-02-27 01:29:32 +0100132 UdpFactory::Error, isTheSameMulticastEndpoint);
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700133
Giulio Grassi624f6c62014-02-18 19:42:14 +0100134 //same multicast endpoint, different group
Davide Pesavento94279412015-02-27 01:29:32 +0100135 BOOST_CHECK_EXCEPTION(factory.createMulticastFace(interfaceIp, "224.0.0.42", "20072"),
136 UdpFactory::Error, isLocalEndpointOnDifferentGroup);
Giulio Grassi624f6c62014-02-18 19:42:14 +0100137
Davide Pesavento94279412015-02-27 01:29:32 +0100138 BOOST_CHECK_EXCEPTION(factory.createMulticastFace(interfaceIp, "192.168.10.15", "20025"),
139 UdpFactory::Error, isNotMulticastAddress);
Giulio Grassi624f6c62014-02-18 19:42:14 +0100140
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700141
Giulio Grassi624f6c62014-02-18 19:42:14 +0100142// //Test commented because it required to be run in a machine that can resolve ipv6 query
143// shared_ptr<UdpChannel> channel1v6 = factory.createChannel(//"::1",
144// "fe80::5e96:9dff:fe7d:9c8d%en1",
145// //"fe80::aa54:b2ff:fe08:27b8%wlan0",
146// "20070");
147//
148// //the creation of multicastFace2 works properly. It has been disable because it needs an IP address of
149// //an available network interface (different from the first one used)
150// shared_ptr<MulticastUdpFace> multicastFace2 = factory.createMulticastFace("192.168.1.17",
151// "224.0.0.1",
152// "20073");
153// BOOST_CHECK_NE(multicastFace1, multicastFace2);
154//
155//
156// //ipv6 - work in progress
157// shared_ptr<MulticastUdpFace> multicastFace3 = factory.createMulticastFace("fe80::5e96:9dff:fe7d:9c8d%en1",
158// "FF01:0:0:0:0:0:0:2",
159// "20073");
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700160//
Giulio Grassi624f6c62014-02-18 19:42:14 +0100161// shared_ptr<MulticastUdpFace> multicastFace4 = factory.createMulticastFace("fe80::aa54:b2ff:fe08:27b8%wlan0",
162// "FF01:0:0:0:0:0:0:2",
163// "20073");
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700164//
Giulio Grassi624f6c62014-02-18 19:42:14 +0100165// BOOST_CHECK_EQUAL(multicastFace3, multicastFace4);
166//
167// shared_ptr<MulticastUdpFace> multicastFace5 = factory.createMulticastFace("::1",
168// "FF01:0:0:0:0:0:0:2",
169// "20073");
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700170//
Giulio Grassi624f6c62014-02-18 19:42:14 +0100171// BOOST_CHECK_NE(multicastFace3, multicastFace5);
172//
173// //same local ipv6 endpoint for a different multicast group
174// BOOST_CHECK_THROW(factory.createMulticastFace("fe80::aa54:b2ff:fe08:27b8%wlan0",
175// "FE01:0:0:0:0:0:0:2",
176// "20073"),
177// UdpFactory::Error);
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700178//
Giulio Grassi624f6c62014-02-18 19:42:14 +0100179// //same local ipv6 (expect for th port number) endpoint for a different multicast group
180// BOOST_CHECK_THROW(factory.createMulticastFace("fe80::aa54:b2ff:fe08:27b8%wlan0",
181// "FE01:0:0:0:0:0:0:2",
182// "20075"),
183// UdpFactory::Error);
184//
185// BOOST_CHECK_THROW(factory.createMulticastFace("fa80::20a:9dff:fef6:12ff",
186// "FE12:0:0:0:0:0:0:2",
187// "20075"),
188// UdpFactory::Error);
189//
190// //not a multicast ipv6
191// BOOST_CHECK_THROW(factory.createMulticastFace("fa80::20a:9dff:fef6:12ff",
192// "A112:0:0:0:0:0:0:2",
193// "20075"),
194// UdpFactory::Error);
Giulio Grassi624f6c62014-02-18 19:42:14 +0100195}
196
Alexander Afanasyev86bc91a2014-08-28 22:29:16 -0700197class FaceCreateFixture : protected BaseFixture
198{
199public:
200 void
201 ignore()
202 {
203 }
204
205 void
206 checkError(const std::string& errorActual, const std::string& errorExpected)
207 {
208 BOOST_CHECK_EQUAL(errorActual, errorExpected);
209 }
210
211 void
212 failIfError(const std::string& errorActual)
213 {
214 BOOST_FAIL("No error expected, but got: [" << errorActual << "]");
215 }
216};
217
218BOOST_FIXTURE_TEST_CASE(FaceCreate, FaceCreateFixture)
219{
220 UdpFactory factory = UdpFactory();
221
Chengyu Fan4381fb62015-01-14 11:37:04 -0700222 factory.createFace(FaceUri("udp4://127.0.0.1:6363"),
Alexander Afanasyev86bc91a2014-08-28 22:29:16 -0700223 bind(&FaceCreateFixture::ignore, this),
Chengyu Fan4381fb62015-01-14 11:37:04 -0700224 bind(&FaceCreateFixture::checkError, this, _1,
225 "No channels available to connect to 127.0.0.1:6363"));
Giulio Grassi624f6c62014-02-18 19:42:14 +0100226
Alexander Afanasyeva39b90b2014-03-05 15:31:00 +0000227 factory.createChannel("127.0.0.1", "20071");
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700228
Giulio Grassi624f6c62014-02-18 19:42:14 +0100229 factory.createFace(FaceUri("udp4://127.0.0.1:20070"),
Chengyu Fan4381fb62015-01-14 11:37:04 -0700230 bind(&FaceCreateFixture::ignore, this),
231 bind(&FaceCreateFixture::failIfError, this, _1));
232}
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700233
Chengyu Fan4381fb62015-01-14 11:37:04 -0700234class EndToEndIpv4
235{
236public:
237 static const std::string
238 getScheme()
239 {
240 return "udp4";
241 }
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700242
Chengyu Fan4381fb62015-01-14 11:37:04 -0700243 static const std::string
244 getLocalIp()
245 {
246 return "127.0.0.1";
247 }
Giulio Grassi624f6c62014-02-18 19:42:14 +0100248
Chengyu Fan4381fb62015-01-14 11:37:04 -0700249 static const std::string
250 getPort1()
251 {
252 return "20071";
253 }
254
255 static const std::string
256 getPort2()
257 {
258 return "20072";
259 }
260
261 static const std::string
262 getPort3()
263 {
264 return "20073";
265 }
266
267 static const FaceUri
268 getFaceUri1()
269 {
270 return FaceUri("udp4://127.0.0.1:20071");
271 }
272
273 static const FaceUri
274 getFaceUri2()
275 {
276 return FaceUri("udp4://127.0.0.1:20072");
277 }
278
279 static const FaceUri
280 getFaceUri3()
281 {
282 return FaceUri("udp4://127.0.0.1:20073");
283 }
284};
285
286class EndToEndIpv6
287{
288public:
289 static const std::string
290 getScheme()
291 {
292 return "udp6";
293 }
294
295 static const std::string
296 getLocalIp()
297 {
298 return "::1";
299 }
300
301 static const std::string
302 getPort1()
303 {
304 return "20071";
305 }
306
307 static const std::string
308 getPort2()
309 {
310 return "20072";
311 }
312
313 static const std::string
314 getPort3()
315 {
316 return "20073";
317 }
318
319 static const FaceUri
320 getFaceUri1()
321 {
322 return FaceUri("udp6://[::1]:20071");
323 }
324
325 static const FaceUri
326 getFaceUri2()
327 {
328 return FaceUri("udp6://[::1]:20072");
329 }
330
331 static const FaceUri
332 getFaceUri3()
333 {
334 return FaceUri("udp6://[::1]:20073");
335 }
336};
337
338typedef boost::mpl::list<EndToEndIpv4, EndToEndIpv6> EndToEndAddresses;
339
340// end to end communication
341BOOST_AUTO_TEST_CASE_TEMPLATE(EndToEnd, A, EndToEndAddresses)
342{
343 LimitedIo limitedIo;
344 UdpFactory factory;
345
346 shared_ptr<UdpChannel> channel1 = factory.createChannel(A::getLocalIp(), A::getPort1());
347
348 // face1 (on channel1) connects to face2 (on channel2, to be created)
349 shared_ptr<Face> face1;
350 unique_ptr<FaceHistory> history1;
351 factory.createFace(A::getFaceUri2(),
352 [&] (shared_ptr<Face> newFace) {
353 face1 = newFace;
354 history1.reset(new FaceHistory(*face1, limitedIo));
355 limitedIo.afterOp();
356 },
357 [] (const std::string& reason) { BOOST_ERROR(reason); });
358
359 limitedIo.run(1, time::seconds(1));
360 BOOST_REQUIRE(face1 != nullptr);
361 BOOST_CHECK_EQUAL(face1->getRemoteUri(), A::getFaceUri2());
362 BOOST_CHECK_EQUAL(face1->getLocalUri(), A::getFaceUri1());
363 BOOST_CHECK_EQUAL(face1->isLocal(), false); // UdpFace is never local
364 BOOST_CHECK_EQUAL(face1->getCounters().getNInBytes(), 0);
365 BOOST_CHECK_EQUAL(face1->getCounters().getNOutBytes(), 0);
366
367 // channel2 creation must be after face1 creation,
368 // otherwise channel2's endpoint would be prohibited
369 shared_ptr<UdpChannel> channel2 = factory.createChannel(A::getLocalIp(), A::getPort2());
370 shared_ptr<Face> face2;
371 unique_ptr<FaceHistory> history2;
372 channel2->listen([&] (shared_ptr<Face> newFace) {
373 BOOST_CHECK(face2 == nullptr);
374 face2 = newFace;
375 history2.reset(new FaceHistory(*face2, limitedIo));
376 limitedIo.afterOp();
377 },
378 [] (const std::string& reason) { BOOST_ERROR(reason); });
379
380 limitedIo.run(1, time::seconds(1));
381 BOOST_CHECK(face2 == nullptr); // face2 shouldn't be created until face1 sends something
382
383 shared_ptr<Interest> interest1 = makeInterest("/I1");
384 shared_ptr<Interest> interest2 = makeInterest("/I2");
385 shared_ptr<Data> data1 = makeData("/D1");
386 shared_ptr<Data> data2 = makeData("/D2");
387
388 // face1 sends to channel2, creates face2
389 face1->sendInterest(*interest1);
390 face1->sendData(*data1);
391 face1->sendData(*data1);
392 face1->sendData(*data1);
393 size_t nBytesSent1 = interest1->wireEncode().size() + 3 * data1->wireEncode().size();
394
395 limitedIo.run(5, time::seconds(1)); // 1 accept, 4 receives
396
397 BOOST_REQUIRE(face2 != nullptr);
398 BOOST_CHECK_EQUAL(face2->getRemoteUri(), A::getFaceUri1());
399 BOOST_CHECK_EQUAL(face2->getLocalUri(), A::getFaceUri2());
400 BOOST_CHECK_EQUAL(face2->isLocal(), false); // UdpFace is never local
401 BOOST_CHECK_EQUAL(face2->getCounters().getNInBytes(), nBytesSent1);
Junxiao Shi5dd26c32014-07-20 23:15:14 -0700402 BOOST_CHECK_EQUAL(face2->getCounters().getNOutBytes(), 0);
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700403
Chengyu Fan4381fb62015-01-14 11:37:04 -0700404 BOOST_REQUIRE_EQUAL(history2->receivedInterests.size(), 1);
405 BOOST_CHECK_EQUAL(history2->receivedInterests.front().getName(), interest1->getName());
406 BOOST_REQUIRE_EQUAL(history2->receivedData.size(), 3);
407 BOOST_CHECK_EQUAL(history2->receivedData.front().getName(), data1->getName());
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700408
Chengyu Fan4381fb62015-01-14 11:37:04 -0700409 // face2 sends to face1
410 face2->sendInterest(*interest2);
411 face2->sendInterest(*interest2);
412 face2->sendInterest(*interest2);
413 face2->sendData(*data2);
414 size_t nBytesSent2 = 3 * interest2->wireEncode().size() + data2->wireEncode().size();
Giulio Grassi624f6c62014-02-18 19:42:14 +0100415
Chengyu Fan4381fb62015-01-14 11:37:04 -0700416 limitedIo.run(4, time::seconds(1)); // 4 receives
Giulio Grassi624f6c62014-02-18 19:42:14 +0100417
Chengyu Fan4381fb62015-01-14 11:37:04 -0700418 BOOST_REQUIRE_EQUAL(history1->receivedInterests.size(), 3);
419 BOOST_CHECK_EQUAL(history1->receivedInterests.front().getName(), interest2->getName());
420 BOOST_REQUIRE_EQUAL(history1->receivedData.size(), 1);
421 BOOST_CHECK_EQUAL(history1->receivedData.front().getName(), data2->getName());
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700422
Chengyu Fan4381fb62015-01-14 11:37:04 -0700423 // counters
Junxiao Shi79494162014-04-02 18:25:11 -0700424 const FaceCounters& counters1 = face1->getCounters();
Chengyu Fan4381fb62015-01-14 11:37:04 -0700425 BOOST_CHECK_EQUAL(counters1.getNInInterests(), 3);
426 BOOST_CHECK_EQUAL(counters1.getNInDatas(), 1);
427 BOOST_CHECK_EQUAL(counters1.getNOutInterests(), 1);
428 BOOST_CHECK_EQUAL(counters1.getNOutDatas(), 3);
Junxiao Shi5dd26c32014-07-20 23:15:14 -0700429 BOOST_CHECK_EQUAL(counters1.getNInBytes(), nBytesSent2);
Chengyu Fan4381fb62015-01-14 11:37:04 -0700430 BOOST_CHECK_EQUAL(counters1.getNOutBytes(), nBytesSent1);
Alexander Afanasyev7e698e62014-03-07 16:48:35 +0000431
Junxiao Shi79494162014-04-02 18:25:11 -0700432 const FaceCounters& counters2 = face2->getCounters();
Chengyu Fan4381fb62015-01-14 11:37:04 -0700433 BOOST_CHECK_EQUAL(counters2.getNInInterests(), 1);
434 BOOST_CHECK_EQUAL(counters2.getNInDatas(), 3);
435 BOOST_CHECK_EQUAL(counters2.getNOutInterests(), 3);
436 BOOST_CHECK_EQUAL(counters2.getNOutDatas(), 1);
437 BOOST_CHECK_EQUAL(counters2.getNInBytes(), nBytesSent1);
Junxiao Shi5dd26c32014-07-20 23:15:14 -0700438 BOOST_CHECK_EQUAL(counters2.getNOutBytes(), nBytesSent2);
Alexander Afanasyeva39b90b2014-03-05 15:31:00 +0000439}
Giulio Grassi624f6c62014-02-18 19:42:14 +0100440
Chengyu Fan4381fb62015-01-14 11:37:04 -0700441// channel accepting multiple incoming connections
442BOOST_AUTO_TEST_CASE_TEMPLATE(MultipleAccepts, A, EndToEndAddresses)
Alexander Afanasyeva39b90b2014-03-05 15:31:00 +0000443{
Chengyu Fan4381fb62015-01-14 11:37:04 -0700444 LimitedIo limitedIo;
Alexander Afanasyeva39b90b2014-03-05 15:31:00 +0000445 UdpFactory factory;
446
Chengyu Fan4381fb62015-01-14 11:37:04 -0700447 // channel1 is listening
448 shared_ptr<UdpChannel> channel1 = factory.createChannel(A::getLocalIp(), A::getPort1());
449 std::vector<shared_ptr<Face>> faces1;
450 channel1->listen([&] (shared_ptr<Face> newFace) {
451 faces1.push_back(newFace);
452 limitedIo.afterOp();
453 },
454 [] (const std::string& reason) { BOOST_ERROR(reason); });
Alexander Afanasyeva39b90b2014-03-05 15:31:00 +0000455
Chengyu Fan4381fb62015-01-14 11:37:04 -0700456 // face2 (on channel2) connects to channel1
457 shared_ptr<UdpChannel> channel2 = factory.createChannel(A::getLocalIp(), A::getPort2());
458 BOOST_CHECK_NE(channel1, channel2);
459 shared_ptr<Face> face2;
460 boost::asio::ip::address ipAddress2 = boost::asio::ip::address::from_string(A::getLocalIp());
461 udp::Endpoint endpoint2(ipAddress2, boost::lexical_cast<uint16_t>(A::getPort1()));
462 channel2->connect(endpoint2,
463 [&] (shared_ptr<Face> newFace) {
464 face2 = 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 limitedIo.run(1, time::seconds(1)); // 1 create (on channel2)
470 BOOST_REQUIRE(face2 != nullptr);
471 BOOST_CHECK_EQUAL(faces1.size(), 0); // channel1 won't create face until face2 sends something
Alexander Afanasyeva39b90b2014-03-05 15:31:00 +0000472
Chengyu Fan4381fb62015-01-14 11:37:04 -0700473 // face3 (on channel3) connects to channel1
474 shared_ptr<UdpChannel> channel3 = factory.createChannel(A::getLocalIp(), A::getPort3());
475 BOOST_CHECK_NE(channel1, channel3);
476 shared_ptr<Face> face3;
477 boost::asio::ip::address ipAddress3 = boost::asio::ip::address::from_string(A::getLocalIp());
478 udp::Endpoint endpoint3(ipAddress3, boost::lexical_cast<uint16_t>(A::getPort1()));
479 channel3->connect(endpoint3,
480 [&] (shared_ptr<Face> newFace) {
481 face3 = newFace;
482 limitedIo.afterOp();
483 },
484 [] (const std::string& reason) { BOOST_ERROR(reason); });
Alexander Afanasyeva39b90b2014-03-05 15:31:00 +0000485
Chengyu Fan4381fb62015-01-14 11:37:04 -0700486 limitedIo.run(1, time::seconds(1)); // 1 create (on channel3)
487 BOOST_REQUIRE(face3 != nullptr);
488 BOOST_CHECK_EQUAL(faces1.size(), 0); // channel1 won't create face until face3 sends something
Alexander Afanasyeva39b90b2014-03-05 15:31:00 +0000489
Chengyu Fan4381fb62015-01-14 11:37:04 -0700490 // face2 sends to channel1
491 shared_ptr<Interest> interest2 = makeInterest("/I2");
492 face2->sendInterest(*interest2);
493 limitedIo.run(1, time::milliseconds(100)); // 1 accept (on channel1)
494 BOOST_REQUIRE_EQUAL(faces1.size(), 1);
495 BOOST_CHECK_EQUAL(channel1->size(), 1);
496 BOOST_CHECK_EQUAL(faces1.at(0)->getRemoteUri(), A::getFaceUri2());
Alexander Afanasyeva39b90b2014-03-05 15:31:00 +0000497
Chengyu Fan4381fb62015-01-14 11:37:04 -0700498 // face3 sends to channel1
499 shared_ptr<Data> data3 = makeData("/D3");
500 face3->sendData(*data3);
501 limitedIo.run(1, time::milliseconds(100)); // 1 accept (on channel1)
502 BOOST_REQUIRE_EQUAL(faces1.size(), 2);
503 BOOST_CHECK_EQUAL(channel1->size(), 2);
504 BOOST_CHECK_EQUAL(faces1.at(1)->getRemoteUri(), A::getFaceUri3());
Giulio Grassi624f6c62014-02-18 19:42:14 +0100505}
506
Chengyu Fan4381fb62015-01-14 11:37:04 -0700507// manually close a face
508BOOST_AUTO_TEST_CASE_TEMPLATE(ManualClose, A, EndToEndAddresses)
Giulio Grassi624f6c62014-02-18 19:42:14 +0100509{
Chengyu Fan4381fb62015-01-14 11:37:04 -0700510 LimitedIo limitedIo;
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700511 UdpFactory factory;
Giulio Grassi624f6c62014-02-18 19:42:14 +0100512
Chengyu Fan4381fb62015-01-14 11:37:04 -0700513 shared_ptr<UdpChannel> channel1 = factory.createChannel(A::getLocalIp(), A::getPort1());
514 shared_ptr<Face> face1;
515 unique_ptr<FaceHistory> history1;
516 factory.createFace(A::getFaceUri2(),
517 [&] (shared_ptr<Face> newFace) {
518 face1 = newFace;
519 history1.reset(new FaceHistory(*face1, limitedIo));
520 limitedIo.afterOp();
521 },
522 [] (const std::string& reason) { BOOST_ERROR(reason); });
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700523
Chengyu Fan4381fb62015-01-14 11:37:04 -0700524 limitedIo.run(1, time::milliseconds(100));
525 BOOST_REQUIRE(face1 != nullptr);
526 BOOST_CHECK_EQUAL(channel1->size(), 1);
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700527
Chengyu Fan4381fb62015-01-14 11:37:04 -0700528 face1->close();
529 getGlobalIoService().poll();
530 BOOST_CHECK_EQUAL(history1->failures.size(), 1);
Giulio Grassi69871f02014-03-09 16:14:44 +0100531 BOOST_CHECK_EQUAL(channel1->size(), 0);
Chengyu Fan4381fb62015-01-14 11:37:04 -0700532}
Junxiao Shi79494162014-04-02 18:25:11 -0700533
Chengyu Fan4381fb62015-01-14 11:37:04 -0700534// automatically close an idle incoming face
535BOOST_AUTO_TEST_CASE_TEMPLATE(IdleClose, A, EndToEndAddresses)
536{
537 LimitedIo limitedIo;
538 UdpFactory factory;
539
540 // channel1 is listening
541 shared_ptr<UdpChannel> channel1 = factory.createChannel(A::getLocalIp(), A::getPort1(),
542 time::seconds(2));
543 shared_ptr<Face> face1;
544 unique_ptr<FaceHistory> history1;
545 channel1->listen([&] (shared_ptr<Face> newFace) {
546 BOOST_CHECK(face1 == nullptr);
547 face1 = newFace;
548 history1.reset(new FaceHistory(*face1, limitedIo));
549 limitedIo.afterOp();
550 },
551 [] (const std::string& reason) { BOOST_ERROR(reason); });
552
553 // face2 (on channel2) connects to channel1
554 shared_ptr<UdpChannel> channel2 = factory.createChannel(A::getLocalIp(), A::getPort2(),
555 time::seconds(2));
556 shared_ptr<Face> face2;
557 unique_ptr<FaceHistory> history2;
558 boost::asio::ip::address ipAddress = boost::asio::ip::address::from_string(A::getLocalIp());
559 udp::Endpoint endpoint(ipAddress, boost::lexical_cast<uint16_t>(A::getPort1()));
560 channel2->connect(endpoint,
561 [&] (shared_ptr<Face> newFace) {
562 face2 = newFace;
563 history2.reset(new FaceHistory(*face2, limitedIo));
564 limitedIo.afterOp();
565 },
566 [] (const std::string& reason) { BOOST_ERROR(reason); });
567
568 limitedIo.run(1, time::milliseconds(100)); // 1 create (on channel2)
569 BOOST_REQUIRE(face2 != nullptr);
570 BOOST_CHECK_EQUAL(face2->isOnDemand(), false);
Davide Pesavento94279412015-02-27 01:29:32 +0100571 BOOST_CHECK_EQUAL(face2->isMultiAccess(), false);
Chengyu Fan4381fb62015-01-14 11:37:04 -0700572
573 // face2 sends to channel1, creates face1
574 shared_ptr<Interest> interest2 = makeInterest("/I2");
575 face2->sendInterest(*interest2);
576
577 limitedIo.run(2, time::seconds(1)); // 1 accept (on channel1), 1 receive (on face1)
Giulio Grassi69871f02014-03-09 16:14:44 +0100578 BOOST_CHECK_EQUAL(channel1->size(), 1);
Chengyu Fan4381fb62015-01-14 11:37:04 -0700579 BOOST_REQUIRE(face1 != nullptr);
580 BOOST_CHECK_EQUAL(face1->isOnDemand(), true);
Davide Pesavento94279412015-02-27 01:29:32 +0100581 BOOST_CHECK_EQUAL(face1->isMultiAccess(), false);
Junxiao Shi79494162014-04-02 18:25:11 -0700582
Chengyu Fan4381fb62015-01-14 11:37:04 -0700583 limitedIo.defer(time::seconds(1));
584 BOOST_CHECK_EQUAL(history1->failures.size(), 0); // face1 is not idle
585 BOOST_CHECK_EQUAL(history2->failures.size(), 0); // face2 is outgoing face and never closed
Giulio Grassi69871f02014-03-09 16:14:44 +0100586
Chengyu Fan4381fb62015-01-14 11:37:04 -0700587 limitedIo.defer(time::seconds(4));
588 BOOST_CHECK_EQUAL(history1->failures.size(), 1); // face1 is idle and automatically closed
589 BOOST_CHECK_EQUAL(channel1->size(), 0);
590 BOOST_CHECK_EQUAL(history2->failures.size(), 0); // face2 is outgoing face and never closed
Giulio Grassi69871f02014-03-09 16:14:44 +0100591}
592
Alexander Afanasyev70aaf8a2014-12-13 00:44:22 -0800593class FakeNetworkInterfaceFixture : public BaseFixture
594{
595public:
596 FakeNetworkInterfaceFixture()
597 {
598 using namespace boost::asio::ip;
599
600 auto fakeInterfaces = make_shared<std::vector<NetworkInterfaceInfo>>();
601
602 fakeInterfaces->push_back(
603 NetworkInterfaceInfo {0, "eth0",
604 ethernet::Address::fromString("3e:15:c2:8b:65:00"),
605 {address_v4::from_string("0.0.0.0")},
606 {address_v6::from_string("::")},
607 address_v4(),
608 IFF_UP});
609 fakeInterfaces->push_back(
610 NetworkInterfaceInfo {1, "eth0",
611 ethernet::Address::fromString("3e:15:c2:8b:65:00"),
612 {address_v4::from_string("192.168.2.1"), address_v4::from_string("192.168.2.2")},
613 {},
614 address_v4::from_string("192.168.2.255"),
615 0});
616 fakeInterfaces->push_back(
617 NetworkInterfaceInfo {2, "eth1",
618 ethernet::Address::fromString("3e:15:c2:8b:65:00"),
619 {address_v4::from_string("198.51.100.1")},
620 {address_v6::from_string("2001:db8::2"), address_v6::from_string("2001:db8::3")},
621 address_v4::from_string("198.51.100.255"),
622 IFF_MULTICAST | IFF_BROADCAST | IFF_UP});
623
624 setDebugNetworkInterfaces(fakeInterfaces);
625 }
626
627 ~FakeNetworkInterfaceFixture()
628 {
629 setDebugNetworkInterfaces(nullptr);
630 }
631};
632
633BOOST_FIXTURE_TEST_CASE(Bug2292, FakeNetworkInterfaceFixture)
634{
635 using namespace boost::asio::ip;
636
637 UdpFactory factory;
638 factory.prohibitEndpoint(udp::Endpoint(address_v4::from_string("192.168.2.1"), 1024));
639 BOOST_REQUIRE_EQUAL(factory.m_prohibitedEndpoints.size(), 1);
640 BOOST_CHECK((factory.m_prohibitedEndpoints ==
641 std::set<udp::Endpoint> {
642 udp::Endpoint(address_v4::from_string("192.168.2.1"), 1024),
643 }));
644
645 factory.m_prohibitedEndpoints.clear();
646 factory.prohibitEndpoint(udp::Endpoint(address_v6::from_string("2001:db8::1"), 2048));
647 BOOST_REQUIRE_EQUAL(factory.m_prohibitedEndpoints.size(), 1);
648 BOOST_CHECK((factory.m_prohibitedEndpoints ==
649 std::set<udp::Endpoint> {
650 udp::Endpoint(address_v6::from_string("2001:db8::1"), 2048),
651 }));
652
653 factory.m_prohibitedEndpoints.clear();
654 factory.prohibitEndpoint(udp::Endpoint(address_v4(), 1024));
655 BOOST_REQUIRE_EQUAL(factory.m_prohibitedEndpoints.size(), 6);
656 BOOST_CHECK((factory.m_prohibitedEndpoints ==
657 std::set<udp::Endpoint> {
658 udp::Endpoint(address_v4::from_string("192.168.2.1"), 1024),
659 udp::Endpoint(address_v4::from_string("192.168.2.2"), 1024),
660 udp::Endpoint(address_v4::from_string("198.51.100.1"), 1024),
661 udp::Endpoint(address_v4::from_string("198.51.100.255"), 1024),
662 udp::Endpoint(address_v4::from_string("255.255.255.255"), 1024),
663 udp::Endpoint(address_v4::from_string("0.0.0.0"), 1024)
664 }));
665
666 factory.m_prohibitedEndpoints.clear();
667 factory.prohibitEndpoint(udp::Endpoint(address_v6(), 2048));
668 BOOST_REQUIRE_EQUAL(factory.m_prohibitedEndpoints.size(), 3);
669 BOOST_CHECK((factory.m_prohibitedEndpoints ==
670 std::set<udp::Endpoint> {
671 udp::Endpoint(address_v6::from_string("2001:db8::2"), 2048),
672 udp::Endpoint(address_v6::from_string("2001:db8::3"), 2048),
673 udp::Endpoint(address_v6::from_string("::"), 2048),
674 }));
675}
676
Giulio Grassi624f6c62014-02-18 19:42:14 +0100677BOOST_AUTO_TEST_SUITE_END()
Junxiao Shi7e2413b2014-03-02 11:15:09 -0700678
Giulio Grassi624f6c62014-02-18 19:42:14 +0100679} // namespace tests
680} // namespace nfd