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-2019 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  Error(const char* expectedType, uint32_t actualType);
58 };
59 
63 enum : uint32_t {
64  Invalid = 0,
65  Interest = 5,
66  Data = 6,
67  Name = 7,
74  Nonce = 10,
76  HopLimit = 34,
78  MetaInfo = 20,
79  Content = 21,
86  KeyLocator = 28,
87  KeyDigest = 29,
90 
93 
96 };
97 
101 enum : uint32_t {
106  Exclude = 16,
108  Any = 19,
109 };
110 
111 [[deprecated("use GenericNameComponent")]]
113 
117 enum : uint32_t {
124 };
125 
129 enum SignatureTypeValue : uint16_t {
134 };
135 
136 std::ostream&
137 operator<<(std::ostream& os, SignatureTypeValue st);
138 
142 enum {
144  NotBefore = 254,
145  NotAfter = 255,
146 
151 };
152 
156 enum ContentTypeValue : uint32_t {
164 };
165 
166 std::ostream&
167 operator<<(std::ostream& os, ContentTypeValue ct);
168 
173 constexpr bool
174 isCriticalType(uint32_t type)
175 {
176  return type <= 31 || (type & 0x01);
177 }
178 
190 template<typename Iterator>
191 bool
192 readVarNumber(Iterator& begin, Iterator end, uint64_t& number) noexcept;
193 
207 template<typename Iterator>
208 bool
209 readType(Iterator& begin, Iterator end, uint32_t& type) noexcept;
210 
221 template<typename Iterator>
222 uint64_t
223 readVarNumber(Iterator& begin, Iterator end);
224 
237 template<typename Iterator>
238 uint32_t
239 readType(Iterator& begin, Iterator end);
240 
244 constexpr size_t
245 sizeOfVarNumber(uint64_t number) noexcept;
246 
251 size_t
252 writeVarNumber(std::ostream& os, uint64_t number);
253 
267 template<typename Iterator>
268 uint64_t
269 readNonNegativeInteger(size_t size, Iterator& begin, Iterator end);
270 
274 constexpr size_t
275 sizeOfNonNegativeInteger(uint64_t integer) noexcept;
276 
281 size_t
282 writeNonNegativeInteger(std::ostream& os, uint64_t integer);
283 
287 
288 // Inline definitions
289 
293 
294 namespace detail {
295 
298 template<typename Iterator>
300 {
301 public:
302  constexpr bool
303  operator()(size_t size, Iterator& begin, Iterator end, uint64_t& number) const noexcept
304  {
305  number = 0;
306  size_t count = 0;
307  for (; begin != end && count < size; ++begin, ++count) {
308  number = (number << 8) | *begin;
309  }
310  return count == size;
311  }
312 };
313 
316 template<typename Iterator>
318 {
319 public:
320  constexpr bool
321  operator()(size_t size, Iterator& begin, Iterator end, uint64_t& number) const noexcept
322  {
323  if (begin + size > end) {
324  return false;
325  }
326 
327  switch (size) {
328  case 1: {
329  number = *begin;
330  ++begin;
331  return true;
332  }
333  case 2: {
334  uint16_t value = 0;
335  std::memcpy(&value, &*begin, 2);
336  begin += 2;
337  number = boost::endian::big_to_native(value);
338  return true;
339  }
340  case 4: {
341  uint32_t value = 0;
342  std::memcpy(&value, &*begin, 4);
343  begin += 4;
344  number = boost::endian::big_to_native(value);
345  return true;
346  }
347  case 8: {
348  uint64_t value = 0;
349  std::memcpy(&value, &*begin, 8);
350  begin += 8;
351  number = boost::endian::big_to_native(value);
352  return true;
353  }
354  default: {
355  BOOST_ASSERT(false);
356  return false;
357  }
358  }
359  }
360 };
361 
367 template<typename Iterator,
368  typename DecayedIterator = std::decay_t<Iterator>,
369  typename ValueType = typename std::iterator_traits<DecayedIterator>::value_type>
370 constexpr bool
372 {
373  return (std::is_convertible<DecayedIterator, const ValueType*>::value ||
374  std::is_convertible<DecayedIterator, typename std::basic_string<ValueType>::const_iterator>::value ||
375  std::is_convertible<DecayedIterator, typename std::vector<ValueType>::const_iterator>::value) &&
376  sizeof(ValueType) == 1 &&
377  !std::is_same<ValueType, bool>::value;
378 }
379 
380 template<typename Iterator>
381 class ReadNumber : public std::conditional_t<shouldSelectContiguousReadNumber<Iterator>(),
382  ReadNumberFast<Iterator>, ReadNumberSlow<Iterator>>
383 {
384 };
385 
386 } // namespace detail
387 
388 template<typename Iterator>
389 bool
390 readVarNumber(Iterator& begin, Iterator end, uint64_t& number) noexcept
391 {
392  if (begin == end)
393  return false;
394 
395  uint8_t firstOctet = *begin;
396  ++begin;
397  if (firstOctet < 253) {
398  number = firstOctet;
399  return true;
400  }
401 
402  size_t size = firstOctet == 253 ? 2 :
403  firstOctet == 254 ? 4 : 8;
404  return detail::ReadNumber<Iterator>()(size, begin, end, number);
405 }
406 
407 template<typename Iterator>
408 bool
409 readType(Iterator& begin, Iterator end, uint32_t& type) noexcept
410 {
411  uint64_t number = 0;
412  bool isOk = readVarNumber(begin, end, number);
413  if (!isOk || number == Invalid || number > std::numeric_limits<uint32_t>::max()) {
414  return false;
415  }
416 
417  type = static_cast<uint32_t>(number);
418  return true;
419 }
420 
421 template<typename Iterator>
422 uint64_t
423 readVarNumber(Iterator& begin, Iterator end)
424 {
425  if (begin == end) {
426  NDN_THROW(Error("Empty buffer during TLV parsing"));
427  }
428 
429  uint64_t value = 0;
430  bool isOk = readVarNumber(begin, end, value);
431  if (!isOk) {
432  NDN_THROW(Error("Insufficient data during TLV parsing"));
433  }
434 
435  return value;
436 }
437 
438 template<typename Iterator>
439 uint32_t
440 readType(Iterator& begin, Iterator end)
441 {
442  uint64_t type = readVarNumber(begin, end);
443  if (type == Invalid || type > std::numeric_limits<uint32_t>::max()) {
444  NDN_THROW(Error("Illegal TLV-TYPE " + to_string(type)));
445  }
446 
447  return static_cast<uint32_t>(type);
448 }
449 
450 constexpr size_t
451 sizeOfVarNumber(uint64_t number) noexcept
452 {
453  return number < 253 ? 1 :
454  number <= std::numeric_limits<uint16_t>::max() ? 3 :
455  number <= std::numeric_limits<uint32_t>::max() ? 5 : 9;
456 }
457 
458 inline size_t
459 writeVarNumber(std::ostream& os, uint64_t number)
460 {
461  if (number < 253) {
462  os.put(static_cast<char>(number));
463  return 1;
464  }
465  else if (number <= std::numeric_limits<uint16_t>::max()) {
466  os.put(static_cast<char>(253));
467  uint16_t value = boost::endian::native_to_big(static_cast<uint16_t>(number));
468  os.write(reinterpret_cast<const char*>(&value), 2);
469  return 3;
470  }
471  else if (number <= std::numeric_limits<uint32_t>::max()) {
472  os.put(static_cast<char>(254));
473  uint32_t value = boost::endian::native_to_big(static_cast<uint32_t>(number));
474  os.write(reinterpret_cast<const char*>(&value), 4);
475  return 5;
476  }
477  else {
478  os.put(static_cast<char>(255));
479  uint64_t value = boost::endian::native_to_big(number);
480  os.write(reinterpret_cast<const char*>(&value), 8);
481  return 9;
482  }
483 }
484 
485 template<typename Iterator>
486 uint64_t
487 readNonNegativeInteger(size_t size, Iterator& begin, Iterator end)
488 {
489  if (size != 1 && size != 2 && size != 4 && size != 8) {
490  NDN_THROW(Error("Invalid length " + to_string(size) + " for nonNegativeInteger"));
491  }
492 
493  uint64_t number = 0;
494  bool isOk = detail::ReadNumber<Iterator>()(size, begin, end, number);
495  if (!isOk) {
496  NDN_THROW(Error("Insufficient data during nonNegativeInteger parsing"));
497  }
498 
499  return number;
500 }
501 
502 constexpr size_t
503 sizeOfNonNegativeInteger(uint64_t integer) noexcept
504 {
505  return integer <= std::numeric_limits<uint8_t>::max() ? 1 :
506  integer <= std::numeric_limits<uint16_t>::max() ? 2 :
507  integer <= std::numeric_limits<uint32_t>::max() ? 4 : 8;
508 }
509 
510 inline size_t
511 writeNonNegativeInteger(std::ostream& os, uint64_t integer)
512 {
513  if (integer <= std::numeric_limits<uint8_t>::max()) {
514  os.put(static_cast<char>(integer));
515  return 1;
516  }
517  else if (integer <= std::numeric_limits<uint16_t>::max()) {
518  uint16_t value = boost::endian::native_to_big(static_cast<uint16_t>(integer));
519  os.write(reinterpret_cast<const char*>(&value), 2);
520  return 2;
521  }
522  else if (integer <= std::numeric_limits<uint32_t>::max()) {
523  uint32_t value = boost::endian::native_to_big(static_cast<uint32_t>(integer));
524  os.write(reinterpret_cast<const char*>(&value), 4);
525  return 4;
526  }
527  else {
528  uint64_t value = boost::endian::native_to_big(integer);
529  os.write(reinterpret_cast<const char*>(&value), 8);
530  return 8;
531  }
532 }
533 
534 } // namespace tlv
535 } // namespace ndn
536 
537 #endif // NDN_ENCODING_TLV_HPP
Represents a signature of Sha256WithRsa type.
Definition: data.cpp:26
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:503
Represents a SignatureInfo TLV element.
std::ostream & operator<<(std::ostream &os, SignatureTypeValue st)
Definition: tlv.cpp:33
constexpr bool operator()(size_t size, Iterator &begin, Iterator end, uint64_t &number) const noexcept
Definition: tlv.hpp:321
constexpr bool operator()(size_t size, Iterator &begin, Iterator end, uint64_t &number) const noexcept
Definition: tlv.hpp:303
constexpr bool isCriticalType(uint32_t type)
Determine whether a TLV-TYPE is "critical" for evolvability purpose.
Definition: tlv.hpp:174
public key, certificate
Definition: tlv.hpp:159
Represents a signature of DigestSha256 type.
prefix announcement
Definition: tlv.hpp:162
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:487
File-Like ICN Collection.
Definition: tlv.hpp:163
another name that identifies the actual data content
Definition: tlv.hpp:158
#define NDN_THROW(e)
Definition: exception.hpp:61
size_t writeNonNegativeInteger(std::ostream &os, uint64_t integer)
Write nonNegativeInteger to the specified stream.
Definition: tlv.hpp:511
size_t writeVarNumber(std::ostream &os, uint64_t number)
Write VAR-NUMBER to the specified stream.
Definition: tlv.hpp:459
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:451
bool readType(Iterator &begin, Iterator end, uint32_t &type) noexcept
Read TLV-TYPE.
Definition: tlv.hpp:409
import common constructs for ndn-cxx library internal use
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:371
Represents an absolute name.
Definition: name.hpp:43
ContentTypeValue
ContentType values.
Definition: tlv.hpp:156
SignatureTypeValue
SignatureType values.
Definition: tlv.hpp:129
constexpr int NameComponent
Definition: tlv.hpp:112
application-level nack
Definition: tlv.hpp:160
Function object to read a number from InputIterator.
Definition: tlv.hpp:299
std::string to_string(const V &v)
Definition: backports.hpp:67
Represents a Data packet.
Definition: data.hpp:35
util::scheduler::EventId deprecated
Definition: scheduler.hpp:228
Error(const char *expectedType, uint32_t actualType)
Definition: tlv.cpp:27
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:390
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:317