NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.5: NDN, CCN, CCNx, content centric networks
API Documentation
tlv.hpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2013-2018 Regents of the University of California.
4  *
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 #ifndef NDN_ENCODING_TLV_HPP
23 #define NDN_ENCODING_TLV_HPP
24 
26 
27 #include <cstring>
28 #include <iterator>
29 #include <ostream>
30 #include <type_traits>
31 #include <vector>
32 
33 #include <boost/endian/conversion.hpp>
34 
35 namespace ndn {
36 
41 const size_t MAX_NDN_PACKET_SIZE = 8800;
42 
46 namespace tlv {
47 
52 class Error : public std::runtime_error
53 {
54 public:
55  using std::runtime_error::runtime_error;
56 };
57 
61 enum {
62  Interest = 5,
63  Data = 6,
64  Name = 7,
71  Nonce = 10,
73  HopLimit = 34,
74  Parameters = 35,
75  MetaInfo = 20,
76  Content = 21,
83  KeyLocator = 28,
84  KeyDigest = 29,
87 
90 
93 };
94 
98 enum {
99  Selectors = 9,
103  Exclude = 16,
105  Any = 19,
106 };
107 
108 [[deprecated("use GenericNameComponent")]]
110 
114 enum {
121 };
122 
126 enum SignatureTypeValue : uint16_t {
131 };
132 
133 std::ostream&
134 operator<<(std::ostream& os, SignatureTypeValue st);
135 
139 enum {
141  NotBefore = 254,
142  NotAfter = 255,
143 
148 };
149 
153 enum ContentTypeValue : uint32_t {
161 };
162 
163 std::ostream&
164 operator<<(std::ostream& os, ContentTypeValue ct);
165 
170 constexpr bool
171 isCriticalType(uint32_t type)
172 {
173  return type <= 31 || (type & 0x01);
174 }
175 
187 template<typename Iterator>
188 bool
189 readVarNumber(Iterator& begin, Iterator end, uint64_t& number) noexcept;
190 
204 template<typename Iterator>
205 bool
206 readType(Iterator& begin, Iterator end, uint32_t& type) noexcept;
207 
218 template<typename Iterator>
219 uint64_t
220 readVarNumber(Iterator& begin, Iterator end);
221 
234 template<typename Iterator>
235 uint32_t
236 readType(Iterator& begin, Iterator end);
237 
241 constexpr size_t
242 sizeOfVarNumber(uint64_t number) noexcept;
243 
248 size_t
249 writeVarNumber(std::ostream& os, uint64_t number);
250 
264 template<typename Iterator>
265 uint64_t
266 readNonNegativeInteger(size_t size, Iterator& begin, Iterator end);
267 
271 constexpr size_t
272 sizeOfNonNegativeInteger(uint64_t integer) noexcept;
273 
278 size_t
279 writeNonNegativeInteger(std::ostream& os, uint64_t integer);
280 
284 
285 // Inline definitions
286 
290 
291 namespace detail {
292 
295 template<typename Iterator>
297 {
298 public:
299  constexpr bool
300  operator()(size_t size, Iterator& begin, Iterator end, uint64_t& number) const noexcept
301  {
302  number = 0;
303  size_t count = 0;
304  for (; begin != end && count < size; ++begin, ++count) {
305  number = (number << 8) | *begin;
306  }
307  return count == size;
308  }
309 };
310 
313 template<typename Iterator>
315 {
316 public:
317  constexpr bool
318  operator()(size_t size, Iterator& begin, Iterator end, uint64_t& number) const noexcept
319  {
320  if (begin + size > end) {
321  return false;
322  }
323 
324  switch (size) {
325  case 1: {
326  number = *begin;
327  ++begin;
328  return true;
329  }
330  case 2: {
331  uint16_t value = 0;
332  std::memcpy(&value, &*begin, 2);
333  begin += 2;
334  number = boost::endian::big_to_native(value);
335  return true;
336  }
337  case 4: {
338  uint32_t value = 0;
339  std::memcpy(&value, &*begin, 4);
340  begin += 4;
341  number = boost::endian::big_to_native(value);
342  return true;
343  }
344  case 8: {
345  uint64_t value = 0;
346  std::memcpy(&value, &*begin, 8);
347  begin += 8;
348  number = boost::endian::big_to_native(value);
349  return true;
350  }
351  default: {
352  BOOST_ASSERT(false);
353  return false;
354  }
355  }
356  }
357 };
358 
364 template<typename Iterator,
365  typename DecayedIterator = std::decay_t<Iterator>,
366  typename ValueType = typename std::iterator_traits<DecayedIterator>::value_type>
367 constexpr bool
369 {
370  return (std::is_convertible<DecayedIterator, const ValueType*>::value ||
371  std::is_convertible<DecayedIterator, typename std::basic_string<ValueType>::const_iterator>::value ||
372  std::is_convertible<DecayedIterator, typename std::vector<ValueType>::const_iterator>::value) &&
373  sizeof(ValueType) == 1 &&
374  !std::is_same<ValueType, bool>::value;
375 }
376 
377 template<typename Iterator>
378 class ReadNumber : public std::conditional_t<shouldSelectContiguousReadNumber<Iterator>(),
379  ReadNumberFast<Iterator>, ReadNumberSlow<Iterator>>
380 {
381 };
382 
383 } // namespace detail
384 
385 template<typename Iterator>
386 bool
387 readVarNumber(Iterator& begin, Iterator end, uint64_t& number) noexcept
388 {
389  if (begin == end)
390  return false;
391 
392  uint8_t firstOctet = *begin;
393  ++begin;
394  if (firstOctet < 253) {
395  number = firstOctet;
396  return true;
397  }
398 
399  size_t size = firstOctet == 253 ? 2 :
400  firstOctet == 254 ? 4 : 8;
401  return detail::ReadNumber<Iterator>()(size, begin, end, number);
402 }
403 
404 template<typename Iterator>
405 bool
406 readType(Iterator& begin, Iterator end, uint32_t& type) noexcept
407 {
408  uint64_t number = 0;
409  bool isOk = readVarNumber(begin, end, number);
410  if (!isOk || number > std::numeric_limits<uint32_t>::max()) {
411  return false;
412  }
413 
414  type = static_cast<uint32_t>(number);
415  return true;
416 }
417 
418 template<typename Iterator>
419 uint64_t
420 readVarNumber(Iterator& begin, Iterator end)
421 {
422  if (begin == end) {
423  BOOST_THROW_EXCEPTION(Error("Empty buffer during TLV parsing"));
424  }
425 
426  uint64_t value = 0;
427  bool isOk = readVarNumber(begin, end, value);
428  if (!isOk) {
429  BOOST_THROW_EXCEPTION(Error("Insufficient data during TLV parsing"));
430  }
431 
432  return value;
433 }
434 
435 template<typename Iterator>
436 uint32_t
437 readType(Iterator& begin, Iterator end)
438 {
439  uint64_t type = readVarNumber(begin, end);
440  if (type > std::numeric_limits<uint32_t>::max()) {
441  BOOST_THROW_EXCEPTION(Error("TLV-TYPE number exceeds allowed maximum"));
442  }
443 
444  return static_cast<uint32_t>(type);
445 }
446 
447 constexpr size_t
448 sizeOfVarNumber(uint64_t number) noexcept
449 {
450  return number < 253 ? 1 :
451  number <= std::numeric_limits<uint16_t>::max() ? 3 :
452  number <= std::numeric_limits<uint32_t>::max() ? 5 : 9;
453 }
454 
455 inline size_t
456 writeVarNumber(std::ostream& os, uint64_t number)
457 {
458  if (number < 253) {
459  os.put(static_cast<char>(number));
460  return 1;
461  }
462  else if (number <= std::numeric_limits<uint16_t>::max()) {
463  os.put(static_cast<char>(253));
464  uint16_t value = boost::endian::native_to_big(static_cast<uint16_t>(number));
465  os.write(reinterpret_cast<const char*>(&value), 2);
466  return 3;
467  }
468  else if (number <= std::numeric_limits<uint32_t>::max()) {
469  os.put(static_cast<char>(254));
470  uint32_t value = boost::endian::native_to_big(static_cast<uint32_t>(number));
471  os.write(reinterpret_cast<const char*>(&value), 4);
472  return 5;
473  }
474  else {
475  os.put(static_cast<char>(255));
476  uint64_t value = boost::endian::native_to_big(number);
477  os.write(reinterpret_cast<const char*>(&value), 8);
478  return 9;
479  }
480 }
481 
482 template<typename Iterator>
483 uint64_t
484 readNonNegativeInteger(size_t size, Iterator& begin, Iterator end)
485 {
486  if (size != 1 && size != 2 && size != 4 && size != 8) {
487  BOOST_THROW_EXCEPTION(Error("Invalid length for nonNegativeInteger "
488  "(only 1, 2, 4, and 8 are allowed)"));
489  }
490 
491  uint64_t number = 0;
492  bool isOk = detail::ReadNumber<Iterator>()(size, begin, end, number);
493  if (!isOk) {
494  BOOST_THROW_EXCEPTION(Error("Insufficient data during TLV parsing"));
495  }
496 
497  return number;
498 }
499 
500 constexpr size_t
501 sizeOfNonNegativeInteger(uint64_t integer) noexcept
502 {
503  return integer <= std::numeric_limits<uint8_t>::max() ? 1 :
504  integer <= std::numeric_limits<uint16_t>::max() ? 2 :
505  integer <= std::numeric_limits<uint32_t>::max() ? 4 : 8;
506 }
507 
508 inline size_t
509 writeNonNegativeInteger(std::ostream& os, uint64_t integer)
510 {
511  if (integer <= std::numeric_limits<uint8_t>::max()) {
512  os.put(static_cast<char>(integer));
513  return 1;
514  }
515  else if (integer <= std::numeric_limits<uint16_t>::max()) {
516  uint16_t value = boost::endian::native_to_big(static_cast<uint16_t>(integer));
517  os.write(reinterpret_cast<const char*>(&value), 2);
518  return 2;
519  }
520  else if (integer <= std::numeric_limits<uint32_t>::max()) {
521  uint32_t value = boost::endian::native_to_big(static_cast<uint32_t>(integer));
522  os.write(reinterpret_cast<const char*>(&value), 4);
523  return 4;
524  }
525  else {
526  uint64_t value = boost::endian::native_to_big(integer);
527  os.write(reinterpret_cast<const char*>(&value), 8);
528  return 8;
529  }
530 }
531 
532 } // namespace tlv
533 } // namespace ndn
534 
535 #endif // NDN_ENCODING_TLV_HPP
Represents a signature of Sha256WithRsa type.
Copyright (c) 2011-2015 Regents of the University of California.
constexpr size_t sizeOfNonNegativeInteger(uint64_t integer) noexcept
Get the number of bytes necessary to hold the value of integer encoded as nonNegativeInteger.
Definition: tlv.hpp:501
Represents a SignatureInfo TLV element.
std::ostream & operator<<(std::ostream &os, SignatureTypeValue st)
Definition: tlv.cpp:28
constexpr bool operator()(size_t size, Iterator &begin, Iterator end, uint64_t &number) const noexcept
Definition: tlv.hpp:318
constexpr bool operator()(size_t size, Iterator &begin, Iterator end, uint64_t &number) const noexcept
Definition: tlv.hpp:300
constexpr bool isCriticalType(uint32_t type)
Determine whether a TLV-TYPE is "critical" for evolvability purpose.
Definition: tlv.hpp:171
public key, certificate
Definition: tlv.hpp:156
Represents a signature of DigestSha256 type.
prefix announcement
Definition: tlv.hpp:159
Represents an Interest packet.
Definition: interest.hpp:44
uint64_t readNonNegativeInteger(size_t size, Iterator &begin, Iterator end)
Read nonNegativeInteger in NDN-TLV encoding.
Definition: tlv.hpp:484
File-Like ICN Collection.
Definition: tlv.hpp:160
another name that identifies the actual data content
Definition: tlv.hpp:155
size_t writeNonNegativeInteger(std::ostream &os, uint64_t integer)
Write nonNegativeInteger to the specified stream.
Definition: tlv.hpp:509
import common constructs for ndn-cxx library internal use
size_t writeVarNumber(std::ostream &os, uint64_t number)
Write VAR-NUMBER to the specified stream.
Definition: tlv.hpp:456
Represents a signature of Sha256WithEcdsa type.
constexpr size_t sizeOfVarNumber(uint64_t number) noexcept
Get the number of bytes necessary to hold the value of number encoded as VAR-NUMBER.
Definition: tlv.hpp:448
bool readType(Iterator &begin, Iterator end, uint32_t &type) noexcept
Read TLV-TYPE.
Definition: tlv.hpp:406
A MetaInfo holds the meta info which is signed inside the data packet.
Definition: meta-info.hpp:58
Abstraction implementing Interest selectors.
Definition: selectors.hpp:35
constexpr bool shouldSelectContiguousReadNumber()
Determine whether to select ReadNumber implementation for ContiguousIterator.
Definition: tlv.hpp:368
Represents an absolute name.
Definition: name.hpp:43
ContentTypeValue
ContentType values.
Definition: tlv.hpp:153
SignatureTypeValue
SignatureType values.
Definition: tlv.hpp:126
constexpr int NameComponent
Definition: tlv.hpp:109
application-level nack
Definition: tlv.hpp:157
Function object to read a number from InputIterator.
Definition: tlv.hpp:296
Represents a Data packet.
Definition: data.hpp:35
represents an error in TLV encoding or decoding
Definition: tlv.hpp:52
bool readVarNumber(Iterator &begin, Iterator end, uint64_t &number) noexcept
Read VAR-NUMBER in NDN-TLV encoding.
Definition: tlv.hpp:387
Represents Exclude selector in NDN Interest.
Definition: exclude.hpp:43
const size_t MAX_NDN_PACKET_SIZE
practical limit of network layer packet size
Definition: tlv.hpp:41
Function object to read a number from ContiguousIterator.
Definition: tlv.hpp:314