blob: 5f9b2d2e11f9d475d3ef3563c7f513cf72c133c2 [file] [log] [blame]
Eric Newberry261dbc22015-07-22 23:18:18 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Junxiao Shib6e276f2017-08-14 20:10:04 +00002/*
Teng Liang5b323d12018-01-31 18:50:45 -07003 * Copyright (c) 2013-2018 Regents of the University of California.
Eric Newberry261dbc22015-07-22 23:18:18 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6 *
7 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20 */
21
22#include "lp/packet.hpp"
Teng Liang5b323d12018-01-31 18:50:45 -070023#include "security/signature-sha256-with-rsa.hpp"
Eric Newberry261dbc22015-07-22 23:18:18 -070024
25#include "boost-test.hpp"
26
27namespace ndn {
28namespace lp {
29namespace tests {
30
Davide Pesaventoeee3e822016-11-26 19:19:34 +010031BOOST_AUTO_TEST_SUITE(Lp)
32BOOST_AUTO_TEST_SUITE(TestPacket)
Eric Newberry261dbc22015-07-22 23:18:18 -070033
34BOOST_AUTO_TEST_CASE(FieldAccess)
35{
36 Packet packet;
37
Junxiao Shib6e276f2017-08-14 20:10:04 +000038 BOOST_CHECK(packet.empty());
Eric Newberry261dbc22015-07-22 23:18:18 -070039 BOOST_CHECK(!packet.has<FragIndexField>());
40 BOOST_CHECK_EQUAL(0, packet.count<FragIndexField>());
Junxiao Shib6e276f2017-08-14 20:10:04 +000041
42 packet.set<FragIndexField>(1234);
43 BOOST_CHECK(!packet.empty());
Eric Newberry261dbc22015-07-22 23:18:18 -070044 BOOST_CHECK(packet.has<FragIndexField>());
45 BOOST_CHECK_THROW(packet.add<FragIndexField>(5678), std::length_error);
46 BOOST_CHECK_EQUAL(1, packet.count<FragIndexField>());
47 BOOST_CHECK_EQUAL(1234, packet.get<FragIndexField>(0));
48 BOOST_CHECK_THROW(packet.get<FragIndexField>(1), std::out_of_range);
49 BOOST_CHECK_THROW(packet.remove<FragIndexField>(1), std::out_of_range);
Junxiao Shib6e276f2017-08-14 20:10:04 +000050
51 packet.remove<FragIndexField>(0);
Eric Newberry261dbc22015-07-22 23:18:18 -070052 BOOST_CHECK_EQUAL(0, packet.count<FragIndexField>());
Junxiao Shib6e276f2017-08-14 20:10:04 +000053
54 packet.add<FragIndexField>(832);
55 std::vector<uint64_t> fragIndexes = packet.list<FragIndexField>();
Eric Newberry261dbc22015-07-22 23:18:18 -070056 BOOST_CHECK_EQUAL(1, fragIndexes.size());
57 BOOST_CHECK_EQUAL(832, fragIndexes.at(0));
Junxiao Shib6e276f2017-08-14 20:10:04 +000058
59 packet.clear<FragIndexField>();
Eric Newberry261dbc22015-07-22 23:18:18 -070060 BOOST_CHECK_EQUAL(0, packet.count<FragIndexField>());
Junxiao Shib6e276f2017-08-14 20:10:04 +000061 BOOST_CHECK(packet.empty());
Eric Newberry261dbc22015-07-22 23:18:18 -070062}
63
64/// \todo test field access methods with a REPEATABLE field
65
66BOOST_AUTO_TEST_CASE(EncodeFragment)
67{
68 static const uint8_t expectedBlock[] = {
Junxiao Shi974b81a2018-04-21 01:37:03 +000069 0x64, 0x0e, // LpPacket
70 0x51, 0x08, // Sequence
71 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe8,
Eric Newberry261dbc22015-07-22 23:18:18 -070072 0x50, 0x02, // Fragment
73 0x03, 0xe8,
74 };
75
76 Buffer buf(2);
77 buf[0] = 0x03;
78 buf[1] = 0xe8;
79
80 Packet packet;
Junxiao Shi974b81a2018-04-21 01:37:03 +000081 packet.add<FragmentField>(std::make_pair(buf.begin(), buf.end()));
82 packet.add<SequenceField>(1000);
83 Block wire = packet.wireEncode();
Eric Newberry261dbc22015-07-22 23:18:18 -070084 BOOST_CHECK_EQUAL_COLLECTIONS(expectedBlock, expectedBlock + sizeof(expectedBlock),
85 wire.begin(), wire.end());
86}
87
88BOOST_AUTO_TEST_CASE(EncodeSubTlv)
89{
90 static const uint8_t expectedBlock[] = {
91 0x64, 0x09, // LpPacket
92 0xfd, 0x03, 0x20, 0x05, // Nack
93 0xfd, 0x03, 0x21, 0x01, // NackReason
94 0x64,
95 };
96
97 NackHeader nack;
98 nack.setReason(NackReason::DUPLICATE);
99
100 Packet packet;
101 BOOST_CHECK_NO_THROW(packet.add<NackField>(nack));
102 Block wire;
103 BOOST_REQUIRE_NO_THROW(wire = packet.wireEncode());
104 BOOST_CHECK_EQUAL_COLLECTIONS(expectedBlock, expectedBlock + sizeof(expectedBlock),
105 wire.begin(), wire.end());
106}
107
Teng Liang02960742017-10-24 00:36:45 -0700108BOOST_AUTO_TEST_CASE(EncodeZeroLengthTlv)
109{
110 static const uint8_t expectedBlock[] = {
111 0x64, 0x04, // LpPacket
112 0xfd, 0x03, 0x4c, 0x00, // NonDiscovery
113 };
114
115 Packet packet1, packet2;
116 BOOST_CHECK_NO_THROW(packet1.set<NonDiscoveryField>(EmptyValue{}));
117 Block wire;
118 BOOST_REQUIRE_NO_THROW(wire = packet1.wireEncode());
119 BOOST_CHECK_EQUAL_COLLECTIONS(expectedBlock, expectedBlock + sizeof(expectedBlock),
120 wire.begin(), wire.end());
121
122 BOOST_CHECK_NO_THROW(packet2.add<NonDiscoveryField>(EmptyValue{}));
123 BOOST_REQUIRE_NO_THROW(wire = packet2.wireEncode());
124 BOOST_CHECK_EQUAL_COLLECTIONS(expectedBlock, expectedBlock + sizeof(expectedBlock),
125 wire.begin(), wire.end());
126}
127
Eric Newberry261dbc22015-07-22 23:18:18 -0700128BOOST_AUTO_TEST_CASE(EncodeSortOrder)
129{
130 static const uint8_t expectedBlock[] = {
Junxiao Shi974b81a2018-04-21 01:37:03 +0000131 0x64, 0x2e, // LpPacket
Eric Newberry261dbc22015-07-22 23:18:18 -0700132 0x52, 0x01, // FragIndex
133 0x00,
134 0x53, 0x01, // FragCount
135 0x01,
Junxiao Shi974b81a2018-04-21 01:37:03 +0000136 0xfd, 0x03, 0x44, 0x08, // Ack
137 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
138 0xfd, 0x03, 0x44, 0x08, // Ack
139 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
140 0xfd, 0x03, 0x44, 0x08, // Ack
141 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
Eric Newberry261dbc22015-07-22 23:18:18 -0700142 0x50, 0x02, // Fragment
143 0x03, 0xe8,
144 };
145
146 Buffer frag(2);
147 frag[0] = 0x03;
148 frag[1] = 0xe8;
149
150 Packet packet;
151 BOOST_CHECK_NO_THROW(packet.add<FragmentField>(std::make_pair(frag.begin(), frag.end())));
152 BOOST_CHECK_NO_THROW(packet.add<FragIndexField>(0));
Eric Newberry8422f572017-02-04 21:53:58 -0700153 BOOST_CHECK_NO_THROW(packet.add<AckField>(2));
Eric Newberry2a890772017-06-26 12:06:15 -0700154 BOOST_REQUIRE_NO_THROW(packet.wireEncode());
Eric Newberry261dbc22015-07-22 23:18:18 -0700155 BOOST_CHECK_NO_THROW(packet.add<FragCountField>(1));
Eric Newberry2a890772017-06-26 12:06:15 -0700156 BOOST_REQUIRE_NO_THROW(packet.wireEncode());
Eric Newberry8422f572017-02-04 21:53:58 -0700157 BOOST_CHECK_NO_THROW(packet.add<AckField>(4));
Eric Newberry2a890772017-06-26 12:06:15 -0700158 BOOST_REQUIRE_NO_THROW(packet.wireEncode());
Eric Newberry8422f572017-02-04 21:53:58 -0700159 BOOST_CHECK_NO_THROW(packet.add<AckField>(3));
Eric Newberry2a890772017-06-26 12:06:15 -0700160 BOOST_REQUIRE_NO_THROW(packet.wireEncode());
Eric Newberry261dbc22015-07-22 23:18:18 -0700161 Block wire;
162 BOOST_REQUIRE_NO_THROW(wire = packet.wireEncode());
163 BOOST_CHECK_EQUAL_COLLECTIONS(expectedBlock, expectedBlock + sizeof(expectedBlock),
164 wire.begin(), wire.end());
165}
166
167BOOST_AUTO_TEST_CASE(DecodeNormal)
168{
169 static const uint8_t inputBlock[] = {
170 0x64, 0x0a, // LpPacket
171 0x52, 0x01, // FragIndex
172 0x00,
173 0x53, 0x01, // FragCount
174 0x01,
175 0x50, 0x02, // Fragment
176 0x03, 0xe8,
177 };
178
179 Packet packet;
180 Block wire(inputBlock, sizeof(inputBlock));
181 BOOST_CHECK_NO_THROW(packet.wireDecode(wire));
182 BOOST_CHECK_EQUAL(1, packet.count<FragmentField>());
183 BOOST_CHECK_EQUAL(1, packet.count<FragIndexField>());
184 BOOST_CHECK_EQUAL(1, packet.count<FragCountField>());
185 Buffer::const_iterator first, last;
186 BOOST_REQUIRE_NO_THROW(std::tie(first, last) = packet.get<FragmentField>(0));
187 BOOST_CHECK_EQUAL(2, last - first);
188 BOOST_CHECK_EQUAL(0x03, *first);
189 BOOST_CHECK_EQUAL(0xe8, *(last - 1));
190 BOOST_CHECK_EQUAL(0, packet.get<FragIndexField>(0));
191 BOOST_CHECK_EQUAL(1, packet.get<FragCountField>(0));
192}
193
194BOOST_AUTO_TEST_CASE(DecodeIdle)
195{
196 static const uint8_t inputBlock[] = {
197 0x64, 0x06, // LpPacket
198 0x52, 0x01, // FragIndex
199 0x00,
200 0x53, 0x01, // FragCount
201 0x01,
202 };
203
204 Packet packet;
205 Block wire(inputBlock, sizeof(inputBlock));
206 BOOST_CHECK_NO_THROW(packet.wireDecode(wire));
207 BOOST_CHECK_EQUAL(0, packet.count<FragmentField>());
208 BOOST_CHECK_EQUAL(1, packet.count<FragIndexField>());
209 BOOST_CHECK_EQUAL(1, packet.count<FragCountField>());
210 BOOST_CHECK_EQUAL(0, packet.get<FragIndexField>(0));
211 BOOST_CHECK_EQUAL(1, packet.get<FragCountField>(0));
212}
213
214BOOST_AUTO_TEST_CASE(DecodeFragment)
215{
216 static const uint8_t inputBlock[] = {
217 0x64, 0x04, // LpPacket
218 0x50, 0x02, // Fragment
219 0x03, 0xe8,
220 };
221
222 Packet packet;
223 Block wire(inputBlock, sizeof(inputBlock));
224 BOOST_CHECK_NO_THROW(packet.wireDecode(wire));
225 BOOST_CHECK_EQUAL(1, packet.count<FragmentField>());
226 BOOST_CHECK_EQUAL(0, packet.count<FragIndexField>());
227 Buffer::const_iterator first, last;
228 BOOST_REQUIRE_NO_THROW(std::tie(first, last) = packet.get<FragmentField>(0));
229 BOOST_CHECK_EQUAL(2, last - first);
230 BOOST_CHECK_EQUAL(0x03, *first);
231 BOOST_CHECK_EQUAL(0xe8, *(last - 1));
232}
233
Teng Liang02960742017-10-24 00:36:45 -0700234BOOST_AUTO_TEST_CASE(DecodeNonDiscoveryHeader)
235{
236 static const uint8_t inputBlock[] = {
237 0x64, 0x04, // LpPacket
238 0xfd, 0x03, 0x4c, 0x00, // NonDiscovery
239 };
240
241 Packet packet;
242 Block wire(inputBlock, sizeof(inputBlock));
243 BOOST_CHECK_NO_THROW(packet.wireDecode(wire));
244 BOOST_CHECK_EQUAL(true, packet.has<NonDiscoveryField>());
245 BOOST_CHECK_NO_THROW(packet.get<NonDiscoveryField>());
246}
247
Eric Newberry261dbc22015-07-22 23:18:18 -0700248BOOST_AUTO_TEST_CASE(DecodeEmpty)
249{
250 static const uint8_t inputBlock[] = {
251 0x64, 0x00, // LpPacket
252 };
253
254 Packet packet;
255 Block wire(inputBlock, sizeof(inputBlock));
256 BOOST_CHECK_NO_THROW(packet.wireDecode(wire));
257 BOOST_CHECK_EQUAL(0, packet.count<FragmentField>());
258 BOOST_CHECK_EQUAL(0, packet.count<FragIndexField>());
Teng Liang02960742017-10-24 00:36:45 -0700259 BOOST_CHECK_EQUAL(false, packet.has<NonDiscoveryField>());
Eric Newberry261dbc22015-07-22 23:18:18 -0700260}
261
262BOOST_AUTO_TEST_CASE(DecodeRepeatedNonRepeatableHeader)
263{
264 static const uint8_t inputBlock[] = {
265 0x64, 0x06, // LpPacket
266 0x52, 0x01, // FragIndex
267 0x00,
268 0x52, 0x01, // FragIndex
269 0x01,
270 };
271
272 Packet packet;
273 Block wire(inputBlock, sizeof(inputBlock));
274 BOOST_CHECK_THROW(packet.wireDecode(wire), Packet::Error);
275}
276
Eric Newberry8422f572017-02-04 21:53:58 -0700277BOOST_AUTO_TEST_CASE(DecodeRepeatedRepeatableHeader)
278{
279 static const uint8_t inputBlock[] = {
280 0x64, 0x0f, // LpPacket
281 0xfd, 0x03, 0x44, 0x01, // Ack
282 0x01,
283 0xfd, 0x03, 0x44, 0x01, // Ack
284 0x03,
285 0xfd, 0x03, 0x44, 0x01, // Ack
286 0x02,
287 };
288
289 Packet packet;
290 Block wire(inputBlock, sizeof(inputBlock));
291 BOOST_CHECK_NO_THROW(packet.wireDecode(wire));
292 BOOST_REQUIRE_EQUAL(packet.count<AckField>(), 3);
293 BOOST_CHECK_EQUAL(packet.get<AckField>(), 1);
294 BOOST_CHECK_EQUAL(packet.get<AckField>(0), 1);
295 BOOST_CHECK_EQUAL(packet.get<AckField>(1), 3);
296 BOOST_CHECK_EQUAL(packet.get<AckField>(2), 2);
297}
298
Eric Newberry261dbc22015-07-22 23:18:18 -0700299BOOST_AUTO_TEST_CASE(DecodeRepeatedFragment)
300{
301 static const uint8_t inputBlock[] = {
302 0x64, 0x08, // LpPacket
303 0x50, 0x02, // Fragment
304 0x03, 0xe8,
305 0x50, 0x02, // Fragment
306 0x03, 0xe9,
307 };
308
309 Packet packet;
310 Block wire(inputBlock, sizeof(inputBlock));
311 BOOST_CHECK_THROW(packet.wireDecode(wire), Packet::Error);
312}
313
314BOOST_AUTO_TEST_CASE(DecodeWrongOrderAmongHeaders)
315{
316 static const uint8_t inputBlock[] = {
317 0x64, 0x0a, // LpPacket
318 0x53, 0x01, // FragCount
319 0x01,
320 0x52, 0x01, // FragIndex
321 0x00,
322 0x50, 0x02, // Fragment
323 0x03, 0xe8,
324 };
325
326 Packet packet;
327 Block wire(inputBlock, sizeof(inputBlock));
328 BOOST_CHECK_THROW(packet.wireDecode(wire), Packet::Error);
329}
330
331BOOST_AUTO_TEST_CASE(DecodeWrongOrderFragment)
332{
333 static const uint8_t inputBlock[] = {
334 0x64, 0x0a, // LpPacket
335 0x52, 0x01, // FragIndex
336 0x00,
337 0x50, 0x02, // Fragment
338 0x03, 0xe8,
339 0x53, 0x01, // FragCount
340 0x01,
341 };
342
343 Packet packet;
344 Block wire(inputBlock, sizeof(inputBlock));
345 BOOST_CHECK_THROW(packet.wireDecode(wire), Packet::Error);
346}
347
348BOOST_AUTO_TEST_CASE(DecodeIgnoredHeader)
349{
350 static const uint8_t inputBlock[] = {
351 0x64, 0x0c, // LpPacket
352 0x52, 0x01, // FragIndex
353 0x00,
Eric Newberry3ed62472016-12-11 22:11:38 -0700354 0xfd, 0x03, 0x24, 0x01, // unknown TLV-TYPE 804 (ignored)
Eric Newberry261dbc22015-07-22 23:18:18 -0700355 0x02,
356 0x50, 0x02, // Fragment
357 0x03, 0xe8,
358 };
359
360 Packet packet;
361 Block wire(inputBlock, sizeof(inputBlock));
362 BOOST_CHECK_NO_THROW(packet.wireDecode(wire));
363 BOOST_CHECK_EQUAL(1, packet.count<FragmentField>());
364 BOOST_CHECK_EQUAL(1, packet.count<FragIndexField>());
365}
366
367BOOST_AUTO_TEST_CASE(DecodeUnrecognizedHeader)
368{
369 static const uint8_t inputBlock[] = {
370 0x64, 0x0c, // LpPacket
371 0x52, 0x01, // FragIndex
372 0x00,
373 0xfd, 0x03, 0x22, 0x01, // unknown TLV-TYPE 802 (cannot ignore)
374 0x02,
375 0x50, 0x02, // Fragment
376 0x03, 0xe8,
377 };
378
379 Packet packet;
380 Block wire(inputBlock, sizeof(inputBlock));
381 BOOST_CHECK_THROW(packet.wireDecode(wire), Packet::Error);
382}
383
384BOOST_AUTO_TEST_CASE(DecodeBareNetworkLayerPacket)
385{
386 static const uint8_t inputBlock[] = {
387 0x05, 0x0a, // Interest
388 0x07, 0x02, // Name
389 0x03, 0xe8,
390 0x0a, 0x04, // Nonce
391 0x01, 0x02, 0x03, 0x04,
392 };
393
394 Packet packet;
395 Block wire(inputBlock, sizeof(inputBlock));
396 BOOST_CHECK_NO_THROW(packet.wireDecode(wire));
397 BOOST_CHECK_EQUAL(1, packet.count<FragmentField>());
398
Eric Newberry261dbc22015-07-22 23:18:18 -0700399 Block encoded;
400 BOOST_CHECK_NO_THROW(encoded = packet.wireEncode());
Eric Newberry83872fd2015-08-06 17:01:24 -0700401 BOOST_CHECK_EQUAL_COLLECTIONS(inputBlock, inputBlock + sizeof(inputBlock),
Eric Newberry261dbc22015-07-22 23:18:18 -0700402 encoded.begin(), encoded.end());
403}
404
Teng Liang5b323d12018-01-31 18:50:45 -0700405BOOST_AUTO_TEST_CASE(DecodePrefixAnnouncement)
406{
407 static const uint8_t inputBlock[] = {
408 0x64, 0x70, // LpPacket
409 0xfd, 0x03, 0x50, 0x3a, // PrefixAnnouncement
410 0x06, 0x38, // Data
411 0x07, 0x29, 0x08, 0x0d, 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x6c,
412 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x08, 0x03, 0x65,
413 0x64, 0x75, 0x08, 0x02, 0x75, 0x61, 0x08, 0x02, 0x63, 0x73,
414 0x08, 0x04, 0x6e, 0x65, 0x77, 0x73, 0x08, 0x05, 0xfd, 0x00,
415 0x03, 0xa5, 0xfe, 0x14, 0x00, 0x15, 0x00, 0x16, 0x05, 0x1b,
416 0x01, 0x01, 0x1c, 0x00, 0x17, 0x00,
417 0x50, 0x30, // Fragment
418 0x06, 0x2e, // Data
419 0x07, 0x1f, 0x08, 0x03, 0x65, 0x64, 0x75, 0x08, 0x02, 0x75,
420 0x61, 0x08, 0x02, 0x63, 0x73, 0x08, 0x04, 0x6e, 0x65, 0x77,
421 0x73, 0x08, 0x0a, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68,
422 0x74, 0x6d, 0x6c, 0x14, 0x00, 0x15, 0x00, 0x16, 0x05, 0x1b,
423 0x01, 0x01, 0x1c, 0x00, 0x17, 0x00,
424 };
425
426 Data data1("/edu/ua/cs/news/index.html");
427 ndn::SignatureSha256WithRsa fakeSignature;
428 fakeSignature.setValue(ndn::encoding::makeEmptyBlock(ndn::tlv::SignatureValue));
429 data1.setSignature(fakeSignature);
430
431 Block wire;
432 wire = data1.wireEncode();
433 Packet packet;
434 BOOST_CHECK_NO_THROW(packet.wireDecode(wire));
435
436 Name name("/self-learning/edu/ua/cs/news");
437 name.appendVersion(239102);
438 Data data2(name);
439 fakeSignature.setValue(ndn::encoding::makeEmptyBlock(ndn::tlv::SignatureValue));
440 data2.setSignature(fakeSignature);
441 data2.wireEncode();
442
443 PrefixAnnouncement pa;
444 pa.setData(make_shared<Data>(data2));
445
446 BOOST_CHECK_NO_THROW(packet.add<PrefixAnnouncementField>(pa));
447 Block encoded;
448 BOOST_CHECK_NO_THROW(encoded = packet.wireEncode());
449 BOOST_CHECK_EQUAL_COLLECTIONS(inputBlock, inputBlock + sizeof(inputBlock),
450 encoded.begin(), encoded.end());
451}
452
Eric Newberry43bf6bb2015-10-09 16:12:09 -0700453BOOST_AUTO_TEST_CASE(DecodeUnrecognizedTlvType)
454{
455 Packet packet;
456 Block wire = encoding::makeEmptyBlock(ndn::tlv::Name);
457 BOOST_CHECK_THROW(packet.wireDecode(wire), Packet::Error);
458}
459
Davide Pesaventoeee3e822016-11-26 19:19:34 +0100460BOOST_AUTO_TEST_SUITE_END() // TestPacket
461BOOST_AUTO_TEST_SUITE_END() // Lp
Eric Newberry261dbc22015-07-22 23:18:18 -0700462
463} // namespace tests
464} // namespace lp
Davide Pesaventoeee3e822016-11-26 19:19:34 +0100465} // namespace ndn