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-2021 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_CXX_ENCODING_TLV_HPP
23 #define NDN_CXX_ENCODING_TLV_HPP
24 
26 
27 #include <cstring>
28 #include <iterator>
29 #include <ostream>
30 #include <vector>
31 
32 #include <boost/endian/conversion.hpp>
33 
34 namespace ndn {
35 
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,
80  MetaInfo = 20,
81  Content = 21,
88  KeyLocator = 28,
89  KeyDigest = 29,
95 
98 
101 };
102 
106 enum : uint32_t {
111  Exclude = 16,
113  Any = 19,
114 };
115 
119 enum : uint32_t {
126 };
127 
132 enum SignatureTypeValue : uint16_t {
138 };
139 
140 std::ostream&
141 operator<<(std::ostream& os, SignatureTypeValue st);
142 
146 enum : uint32_t {
148  NotBefore = 254,
149  NotAfter = 255,
150 
154  DescriptionValue = 514
155 };
156 
160 enum ContentTypeValue : uint32_t {
168 };
169 
170 std::ostream&
171 operator<<(std::ostream& os, ContentTypeValue ct);
172 
177 constexpr bool
178 isCriticalType(uint32_t type)
179 {
180  return type <= 31 || (type & 0x01);
181 }
182 
194 template<typename Iterator>
196 readVarNumber(Iterator& begin, Iterator end, uint64_t& number) noexcept;
197 
211 template<typename Iterator>
213 readType(Iterator& begin, Iterator end, uint32_t& type) noexcept;
214 
225 template<typename Iterator>
226 uint64_t
227 readVarNumber(Iterator& begin, Iterator end);
228 
241 template<typename Iterator>
242 uint32_t
243 readType(Iterator& begin, Iterator end);
244 
248 constexpr size_t
249 sizeOfVarNumber(uint64_t number) noexcept;
250 
255 size_t
256 writeVarNumber(std::ostream& os, uint64_t number);
257 
271 template<typename Iterator>
272 uint64_t
273 readNonNegativeInteger(size_t size, Iterator& begin, Iterator end);
274 
278 constexpr size_t
279 sizeOfNonNegativeInteger(uint64_t integer) noexcept;
280 
285 size_t
286 writeNonNegativeInteger(std::ostream& os, uint64_t integer);
287 
291 
292 // Inline definitions
293 
297 
298 namespace detail {
299 
302 template<typename Iterator>
304 {
305 public:
306  constexpr bool
307  operator()(size_t size, Iterator& begin, Iterator end, uint64_t& number) const noexcept
308  {
309  number = 0;
310  size_t count = 0;
311  for (; begin != end && count < size; ++begin, ++count) {
312  number = (number << 8) | *begin;
313  }
314  return count == size;
315  }
316 };
317 
320 template<typename Iterator>
322 {
323 public:
324  constexpr bool
325  operator()(size_t size, Iterator& begin, Iterator end, uint64_t& number) const noexcept
326  {
327  if (begin + size > end) {
328  return false;
329  }
330 
331  switch (size) {
332  case 1: {
333  number = *begin;
334  ++begin;
335  return true;
336  }
337  case 2: {
338  uint16_t value = 0;
339  std::memcpy(&value, &*begin, 2);
340  begin += 2;
341  number = boost::endian::big_to_native(value);
342  return true;
343  }
344  case 4: {
345  uint32_t value = 0;
346  std::memcpy(&value, &*begin, 4);
347  begin += 4;
348  number = boost::endian::big_to_native(value);
349  return true;
350  }
351  case 8: {
352  uint64_t value = 0;
353  std::memcpy(&value, &*begin, 8);
354  begin += 8;
355  number = boost::endian::big_to_native(value);
356  return true;
357  }
358  default: {
360  }
361  }
362  }
363 };
364 
370 template<typename Iterator,
371  typename DecayedIterator = std::decay_t<Iterator>,
372  typename ValueType = typename std::iterator_traits<DecayedIterator>::value_type>
373 constexpr bool
375 {
376  return (std::is_convertible<DecayedIterator, const ValueType*>::value ||
377  std::is_convertible<DecayedIterator, typename std::basic_string<ValueType>::const_iterator>::value ||
378  std::is_convertible<DecayedIterator, typename std::vector<ValueType>::const_iterator>::value) &&
379  sizeof(ValueType) == 1 &&
380  !std::is_same<ValueType, bool>::value;
381 }
382 
383 template<typename Iterator>
384 class ReadNumber : public std::conditional_t<shouldSelectContiguousReadNumber<Iterator>(),
385  ReadNumberFast<Iterator>, ReadNumberSlow<Iterator>>
386 {
387 };
388 
389 } // namespace detail
390 
391 template<typename Iterator>
392 bool
393 readVarNumber(Iterator& begin, Iterator end, uint64_t& number) noexcept
394 {
395  if (begin == end)
396  return false;
397 
398  uint8_t firstOctet = *begin;
399  ++begin;
400  if (firstOctet < 253) {
401  number = firstOctet;
402  return true;
403  }
404 
405  size_t size = firstOctet == 253 ? 2 :
406  firstOctet == 254 ? 4 : 8;
407  return detail::ReadNumber<Iterator>()(size, begin, end, number);
408 }
409 
410 template<typename Iterator>
411 bool
412 readType(Iterator& begin, Iterator end, uint32_t& type) noexcept
413 {
414  uint64_t number = 0;
415  bool isOk = readVarNumber(begin, end, number);
416  if (!isOk || number == Invalid || number > std::numeric_limits<uint32_t>::max()) {
417  return false;
418  }
419 
420  type = static_cast<uint32_t>(number);
421  return true;
422 }
423 
424 template<typename Iterator>
425 uint64_t
426 readVarNumber(Iterator& begin, Iterator end)
427 {
428  if (begin == end) {
429  NDN_THROW(Error("Empty buffer during TLV parsing"));
430  }
431 
432  uint64_t value = 0;
433  bool isOk = readVarNumber(begin, end, value);
434  if (!isOk) {
435  NDN_THROW(Error("Insufficient data during TLV parsing"));
436  }
437 
438  return value;
439 }
440 
441 template<typename Iterator>
442 uint32_t
443 readType(Iterator& begin, Iterator end)
444 {
445  uint64_t type = readVarNumber(begin, end);
446  if (type == Invalid || type > std::numeric_limits<uint32_t>::max()) {
447  NDN_THROW(Error("Illegal TLV-TYPE " + to_string(type)));
448  }
449 
450  return static_cast<uint32_t>(type);
451 }
452 
453 constexpr size_t
454 sizeOfVarNumber(uint64_t number) noexcept
455 {
456  return number < 253 ? 1 :
457  number <= std::numeric_limits<uint16_t>::max() ? 3 :
458  number <= std::numeric_limits<uint32_t>::max() ? 5 : 9;
459 }
460 
461 inline size_t
462 writeVarNumber(std::ostream& os, uint64_t number)
463 {
464  if (number < 253) {
465  os.put(static_cast<char>(number));
466  return 1;
467  }
468  else if (number <= std::numeric_limits<uint16_t>::max()) {
469  os.put(static_cast<char>(253));
470  uint16_t value = boost::endian::native_to_big(static_cast<uint16_t>(number));
471  os.write(reinterpret_cast<const char*>(&value), 2);
472  return 3;
473  }
474  else if (number <= std::numeric_limits<uint32_t>::max()) {
475  os.put(static_cast<char>(254));
476  uint32_t value = boost::endian::native_to_big(static_cast<uint32_t>(number));
477  os.write(reinterpret_cast<const char*>(&value), 4);
478  return 5;
479  }
480  else {
481  os.put(static_cast<char>(255));
482  uint64_t value = boost::endian::native_to_big(number);
483  os.write(reinterpret_cast<const char*>(&value), 8);
484  return 9;
485  }
486 }
487 
488 template<typename Iterator>
489 uint64_t
490 readNonNegativeInteger(size_t size, Iterator& begin, Iterator end)
491 {
492  if (size != 1 && size != 2 && size != 4 && size != 8) {
493  NDN_THROW(Error("Invalid length " + to_string(size) + " for NonNegativeInteger"));
494  }
495 
496  uint64_t number = 0;
497  bool isOk = detail::ReadNumber<Iterator>()(size, begin, end, number);
498  if (!isOk) {
499  NDN_THROW(Error("Insufficient data during NonNegativeInteger parsing"));
500  }
501 
502  return number;
503 }
504 
505 constexpr size_t
506 sizeOfNonNegativeInteger(uint64_t integer) noexcept
507 {
508  return integer <= std::numeric_limits<uint8_t>::max() ? 1 :
509  integer <= std::numeric_limits<uint16_t>::max() ? 2 :
510  integer <= std::numeric_limits<uint32_t>::max() ? 4 : 8;
511 }
512 
513 inline size_t
514 writeNonNegativeInteger(std::ostream& os, uint64_t integer)
515 {
516  if (integer <= std::numeric_limits<uint8_t>::max()) {
517  os.put(static_cast<char>(integer));
518  return 1;
519  }
520  else if (integer <= std::numeric_limits<uint16_t>::max()) {
521  uint16_t value = boost::endian::native_to_big(static_cast<uint16_t>(integer));
522  os.write(reinterpret_cast<const char*>(&value), 2);
523  return 2;
524  }
525  else if (integer <= std::numeric_limits<uint32_t>::max()) {
526  uint32_t value = boost::endian::native_to_big(static_cast<uint32_t>(integer));
527  os.write(reinterpret_cast<const char*>(&value), 4);
528  return 4;
529  }
530  else {
531  uint64_t value = boost::endian::native_to_big(integer);
532  os.write(reinterpret_cast<const char*>(&value), 8);
533  return 8;
534  }
535 }
536 
537 } // namespace tlv
538 } // namespace ndn
539 
540 #endif // NDN_CXX_ENCODING_TLV_HPP
#define NDN_CXX_NODISCARD
Definition: backports.hpp:68
#define NDN_CXX_UNREACHABLE
Definition: backports.hpp:72
Represents a Data packet.
Definition: data.hpp:38
Represents an Interest packet.
Definition: interest.hpp:50
A MetaInfo holds the meta info which is signed inside the data packet.
Definition: meta-info.hpp:59
Represents an absolute name.
Definition: name.hpp:46
Represents a SignatureInfo or InterestSignatureInfo TLV element.
represents an error in TLV encoding or decoding
Definition: tlv.hpp:53
Error(const char *expectedType, uint32_t actualType)
Definition: tlv.cpp:27
Function object to read a number from ContiguousIterator.
Definition: tlv.hpp:322
constexpr bool operator()(size_t size, Iterator &begin, Iterator end, uint64_t &number) const noexcept
Definition: tlv.hpp:325
Function object to read a number from InputIterator.
Definition: tlv.hpp:304
constexpr bool operator()(size_t size, Iterator &begin, Iterator end, uint64_t &number) const noexcept
Definition: tlv.hpp:307
Common includes and macros used throughout the library.
#define NDN_THROW(e)
Definition: exception.hpp:61
std::string to_string(const errinfo_stacktrace &x)
Definition: exception.cpp:31
constexpr bool shouldSelectContiguousReadNumber()
Determine whether to select ReadNumber implementation for ContiguousIterator.
Definition: tlv.hpp:374
@ DescriptionValue
Definition: tlv.hpp:154
@ DescriptionKey
Definition: tlv.hpp:153
@ AdditionalDescription
Definition: tlv.hpp:151
@ DescriptionEntry
Definition: tlv.hpp:152
@ ValidityPeriod
Definition: tlv.hpp:147
@ NotAfter
Definition: tlv.hpp:149
@ NotBefore
Definition: tlv.hpp:148
@ SignatureSeqNum
Definition: tlv.hpp:92
@ KeyDigest
Definition: tlv.hpp:89
@ FinalBlockId
Definition: tlv.hpp:86
@ GenericNameComponent
Definition: tlv.hpp:68
@ LinkPreference
Definition: tlv.hpp:94
@ SignatureNonce
Definition: tlv.hpp:90
@ InterestLifetime
Definition: tlv.hpp:75
@ HopLimit
Definition: tlv.hpp:76
@ AppPrivateBlock2
Definition: tlv.hpp:100
@ InterestSignatureInfo
Definition: tlv.hpp:78
@ ApplicationParameters
Definition: tlv.hpp:77
@ ForwardingHint
Definition: tlv.hpp:73
@ SignatureType
Definition: tlv.hpp:87
@ NameComponentMin
Definition: tlv.hpp:96
@ InterestSignatureValue
Definition: tlv.hpp:79
@ SignatureTime
Definition: tlv.hpp:91
@ AppPrivateBlock1
Definition: tlv.hpp:99
@ Content
Definition: tlv.hpp:81
@ CanBePrefix
Definition: tlv.hpp:71
@ Invalid
Definition: tlv.hpp:64
@ ContentType
Definition: tlv.hpp:84
@ NameComponentMax
Definition: tlv.hpp:97
@ FreshnessPeriod
Definition: tlv.hpp:85
@ LinkDelegation
Definition: tlv.hpp:93
@ ParametersSha256DigestComponent
Definition: tlv.hpp:70
@ SignatureValue
Definition: tlv.hpp:83
@ ImplicitSha256DigestComponent
Definition: tlv.hpp:69
@ MustBeFresh
Definition: tlv.hpp:72
@ Nonce
Definition: tlv.hpp:74
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:454
bool readVarNumber(Iterator &begin, Iterator end, uint64_t &number) noexcept
Read VAR-NUMBER in NDN-TLV encoding.
Definition: tlv.hpp:393
ContentTypeValue
ContentType values.
Definition: tlv.hpp:160
@ ContentType_Key
public key, certificate
Definition: tlv.hpp:163
@ ContentType_Manifest
Definition: tlv.hpp:165
@ ContentType_Link
another name that identifies the actual data content
Definition: tlv.hpp:162
@ ContentType_Blob
payload
Definition: tlv.hpp:161
@ ContentType_Flic
File-Like ICN Collection.
Definition: tlv.hpp:167
@ ContentType_PrefixAnn
prefix announcement
Definition: tlv.hpp:166
@ ContentType_Nack
application-level nack
Definition: tlv.hpp:164
size_t writeNonNegativeInteger(std::ostream &os, uint64_t integer)
Write a NonNegativeInteger to the specified stream.
Definition: tlv.hpp:514
bool readType(Iterator &begin, Iterator end, uint32_t &type) noexcept
Read TLV-TYPE.
Definition: tlv.hpp:412
constexpr bool isCriticalType(uint32_t type)
Determine whether a TLV-TYPE is "critical" for evolvability purpose.
Definition: tlv.hpp:178
@ TimestampNameComponent
Definition: tlv.hpp:124
@ ByteOffsetNameComponent
Definition: tlv.hpp:122
@ VersionNameComponent
Definition: tlv.hpp:123
@ SequenceNumNameComponent
Definition: tlv.hpp:125
@ KeywordNameComponent
Definition: tlv.hpp:120
@ SegmentNameComponent
Definition: tlv.hpp:121
std::ostream & operator<<(std::ostream &os, SignatureTypeValue st)
Definition: tlv.cpp:33
size_t writeVarNumber(std::ostream &os, uint64_t number)
Write VAR-NUMBER to the specified stream.
Definition: tlv.hpp:462
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:506
SignatureTypeValue
SignatureType values.
Definition: tlv.hpp:132
@ SignatureSha256WithRsa
Definition: tlv.hpp:134
@ DigestSha256
Definition: tlv.hpp:133
@ SignatureHmacWithSha256
Definition: tlv.hpp:136
@ SignatureSha256WithEcdsa
Definition: tlv.hpp:135
@ NullSignature
Definition: tlv.hpp:137
@ Selectors
Definition: tlv.hpp:107
@ Any
Definition: tlv.hpp:113
@ MaxSuffixComponents
Definition: tlv.hpp:109
@ MinSuffixComponents
Definition: tlv.hpp:108
@ Exclude
Definition: tlv.hpp:111
@ ChildSelector
Definition: tlv.hpp:112
@ PublisherPublicKeyLocator
Definition: tlv.hpp:110
uint64_t readNonNegativeInteger(size_t size, Iterator &begin, Iterator end)
Read a NonNegativeInteger in NDN-TLV encoding.
Definition: tlv.hpp:490
Definition: data.cpp:25
const size_t MAX_NDN_PACKET_SIZE
Practical size limit of a network-layer packet.
Definition: tlv.hpp:41