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-2023 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 <limits>
30 #include <vector>
31 
32 #include <boost/endian/conversion.hpp>
33 
34 namespace ndn {
35 
41 inline constexpr size_t MAX_NDN_PACKET_SIZE = 8800;
42 
46 namespace tlv {
47 
53 class Error : public std::runtime_error
54 {
55 public:
56  using std::runtime_error::runtime_error;
57 
58  Error(const char* expectedType, uint32_t actualType);
59 };
60 
66 enum : uint32_t {
67  Invalid = 0,
68  Interest = 5,
69  Data = 6,
70 
71  Name = 7,
81 
85  Nonce = 10,
87  HopLimit = 34,
91 
92  MetaInfo = 20,
93  Content = 21,
99 
102  KeyDigest = 29,
106 
108  NotBefore = 254,
109  NotAfter = 255,
114 
117 
120 };
121 
127 enum SignatureTypeValue : uint16_t {
134 };
135 
136 std::ostream&
137 operator<<(std::ostream& os, SignatureTypeValue st);
138 
144 enum ContentTypeValue : uint32_t {
152 };
153 
154 std::ostream&
155 operator<<(std::ostream& os, ContentTypeValue ct);
156 
161 constexpr bool
162 isCriticalType(uint32_t type) noexcept
163 {
164  return type <= 31 || (type & 0x01);
165 }
166 
178 template<typename Iterator>
179 [[nodiscard]] constexpr bool
180 readVarNumber(Iterator& begin, Iterator end, uint64_t& number) noexcept;
181 
195 template<typename Iterator>
196 [[nodiscard]] constexpr bool
197 readType(Iterator& begin, Iterator end, uint32_t& type) noexcept;
198 
209 template<typename Iterator>
210 constexpr uint64_t
211 readVarNumber(Iterator& begin, Iterator end);
212 
225 template<typename Iterator>
226 constexpr uint32_t
227 readType(Iterator& begin, Iterator end);
228 
232 [[nodiscard]] constexpr size_t
233 sizeOfVarNumber(uint64_t number) noexcept;
234 
239 size_t
240 writeVarNumber(std::ostream& os, uint64_t number);
241 
255 template<typename Iterator>
256 constexpr uint64_t
257 readNonNegativeInteger(size_t size, Iterator& begin, Iterator end);
258 
262 [[nodiscard]] constexpr size_t
263 sizeOfNonNegativeInteger(uint64_t integer) noexcept;
264 
269 size_t
270 writeNonNegativeInteger(std::ostream& os, uint64_t integer);
271 
273 // Inline definitions
275 
276 namespace detail {
277 
284 template<typename Iterator,
285  typename DecayedIterator = std::decay_t<Iterator>,
286  typename ValueType = typename std::iterator_traits<DecayedIterator>::value_type>
287 inline constexpr bool IsContiguousIterator =
288  (std::is_convertible_v<DecayedIterator, const ValueType*> ||
289  std::is_convertible_v<DecayedIterator, typename std::basic_string<ValueType>::const_iterator> ||
290  std::is_convertible_v<DecayedIterator, typename std::vector<ValueType>::const_iterator>) &&
291  sizeof(ValueType) == 1 && !std::is_same_v<ValueType, bool>;
292 
293 template<typename Iterator>
294 constexpr bool
295 readNumber(size_t size, Iterator& begin, Iterator end, uint64_t& number) noexcept
296 {
297  if constexpr (IsContiguousIterator<Iterator>) {
298  // fast path
299  if (begin + size > end) {
300  return false;
301  }
302  switch (size) {
303  case 1: {
304  number = *begin;
305  ++begin;
306  return true;
307  }
308  case 2: {
309  uint16_t value = 0;
310  std::memcpy(&value, &*begin, 2);
311  begin += 2;
312  number = boost::endian::big_to_native(value);
313  return true;
314  }
315  case 4: {
316  uint32_t value = 0;
317  std::memcpy(&value, &*begin, 4);
318  begin += 4;
319  number = boost::endian::big_to_native(value);
320  return true;
321  }
322  case 8: {
323  uint64_t value = 0;
324  std::memcpy(&value, &*begin, 8);
325  begin += 8;
326  number = boost::endian::big_to_native(value);
327  return true;
328  }
329  default: {
331  }
332  }
333  }
334  else {
335  // slow path
336  number = 0;
337  size_t count = 0;
338  for (; begin != end && count < size; ++begin, ++count) {
339  number = (number << 8) | *begin;
340  }
341  return count == size;
342  }
343 }
344 
345 } // namespace detail
346 
347 template<typename Iterator>
348 constexpr bool
349 readVarNumber(Iterator& begin, Iterator end, uint64_t& number) noexcept
350 {
351  if (begin == end)
352  return false;
353 
354  uint8_t firstOctet = *begin;
355  ++begin;
356  if (firstOctet < 253) {
357  number = firstOctet;
358  return true;
359  }
360 
361  size_t len = 1U << (firstOctet & 0b11);
362  return detail::readNumber(len, begin, end, number);
363 }
364 
365 template<typename Iterator>
366 constexpr bool
367 readType(Iterator& begin, Iterator end, uint32_t& type) noexcept
368 {
369  uint64_t number = 0;
370  bool isOk = readVarNumber(begin, end, number);
371  if (!isOk || number == Invalid || number > std::numeric_limits<uint32_t>::max()) {
372  return false;
373  }
374 
375  type = static_cast<uint32_t>(number);
376  return true;
377 }
378 
379 template<typename Iterator>
380 constexpr uint64_t
381 readVarNumber(Iterator& begin, Iterator end)
382 {
383  uint64_t number = 0;
384  bool isOk = readVarNumber(begin, end, number);
385  if (!isOk) {
386  NDN_THROW(Error("Insufficient data during TLV parsing"));
387  }
388 
389  return number;
390 }
391 
392 template<typename Iterator>
393 constexpr uint32_t
394 readType(Iterator& begin, Iterator end)
395 {
396  uint64_t type = readVarNumber(begin, end);
397  if (type == Invalid || type > std::numeric_limits<uint32_t>::max()) {
398  NDN_THROW(Error("Illegal TLV-TYPE " + to_string(type)));
399  }
400 
401  return static_cast<uint32_t>(type);
402 }
403 
404 constexpr size_t
405 sizeOfVarNumber(uint64_t number) noexcept
406 {
407  return number < 253 ? 1 :
408  number <= std::numeric_limits<uint16_t>::max() ? 3 :
409  number <= std::numeric_limits<uint32_t>::max() ? 5 : 9;
410 }
411 
412 template<typename Iterator>
413 constexpr uint64_t
414 readNonNegativeInteger(size_t len, Iterator& begin, Iterator end)
415 {
416  if (len != 1 && len != 2 && len != 4 && len != 8) {
417  NDN_THROW(Error("Invalid NonNegativeInteger length " + to_string(len)));
418  }
419 
420  uint64_t number = 0;
421  bool isOk = detail::readNumber(len, begin, end, number);
422  if (!isOk) {
423  NDN_THROW(Error("Insufficient data during NonNegativeInteger parsing"));
424  }
425 
426  return number;
427 }
428 
429 constexpr size_t
430 sizeOfNonNegativeInteger(uint64_t integer) noexcept
431 {
432  return integer <= std::numeric_limits<uint8_t>::max() ? 1 :
433  integer <= std::numeric_limits<uint16_t>::max() ? 2 :
434  integer <= std::numeric_limits<uint32_t>::max() ? 4 : 8;
435 }
436 
437 } // namespace tlv
438 } // namespace ndn
439 
440 #endif // NDN_CXX_ENCODING_TLV_HPP
#define NDN_CXX_UNREACHABLE
Definition: backports.hpp:57
Represents a Data packet.
Definition: data.hpp:39
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:62
Represents an absolute name.
Definition: name.hpp:45
Represents a SignatureInfo or InterestSignatureInfo TLV element.
Represents an error in TLV encoding or decoding.
Definition: tlv.hpp:54
Error(const char *expectedType, uint32_t actualType)
Definition: tlv.cpp:28
Common includes and macros used throughout the library.
#define NDN_THROW(e)
Definition: exception.hpp:56
std::string to_string(const errinfo_stacktrace &x)
Definition: exception.cpp:30
constexpr bool readNumber(size_t size, Iterator &begin, Iterator end, uint64_t &number) noexcept
Definition: tlv.hpp:295
constexpr bool IsContiguousIterator
Determine whether to select the readNumber() implementation for ContiguousIterator.
Definition: tlv.hpp:287
@ SignatureSeqNum
Definition: tlv.hpp:105
@ KeyDigest
Definition: tlv.hpp:102
@ TimestampNameComponent
Definition: tlv.hpp:79
@ FinalBlockId
Definition: tlv.hpp:98
@ GenericNameComponent
Definition: tlv.hpp:72
@ DescriptionValue
Definition: tlv.hpp:113
@ SignatureNonce
Definition: tlv.hpp:103
@ InterestLifetime
Definition: tlv.hpp:86
@ HopLimit
Definition: tlv.hpp:87
@ DescriptionKey
Definition: tlv.hpp:112
@ AppPrivateBlock2
Definition: tlv.hpp:119
@ InterestSignatureInfo
Definition: tlv.hpp:89
@ ApplicationParameters
Definition: tlv.hpp:88
@ ByteOffsetNameComponent
Definition: tlv.hpp:77
@ ForwardingHint
Definition: tlv.hpp:84
@ AdditionalDescription
Definition: tlv.hpp:110
@ SignatureType
Definition: tlv.hpp:100
@ NameComponentMin
Definition: tlv.hpp:115
@ InterestSignatureValue
Definition: tlv.hpp:90
@ SignatureTime
Definition: tlv.hpp:104
@ VersionNameComponent
Definition: tlv.hpp:78
@ AppPrivateBlock1
Definition: tlv.hpp:118
@ Content
Definition: tlv.hpp:93
@ CanBePrefix
Definition: tlv.hpp:82
@ Invalid
Definition: tlv.hpp:67
@ DescriptionEntry
Definition: tlv.hpp:111
@ ContentType
Definition: tlv.hpp:96
@ SequenceNumNameComponent
Definition: tlv.hpp:80
@ NameComponentMax
Definition: tlv.hpp:116
@ ValidityPeriod
Definition: tlv.hpp:107
@ NotAfter
Definition: tlv.hpp:109
@ FreshnessPeriod
Definition: tlv.hpp:97
@ KeywordNameComponent
Definition: tlv.hpp:75
@ ParametersSha256DigestComponent
Definition: tlv.hpp:74
@ SignatureValue
Definition: tlv.hpp:95
@ ImplicitSha256DigestComponent
Definition: tlv.hpp:73
@ NotBefore
Definition: tlv.hpp:108
@ SegmentNameComponent
Definition: tlv.hpp:76
@ MustBeFresh
Definition: tlv.hpp:83
@ Nonce
Definition: tlv.hpp:85
constexpr uint64_t readNonNegativeInteger(size_t size, Iterator &begin, Iterator end)
Read a NonNegativeInteger in NDN-TLV encoding.
Definition: tlv.hpp:414
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:405
constexpr bool readVarNumber(Iterator &begin, Iterator end, uint64_t &number) noexcept
Read VAR-NUMBER in NDN-TLV encoding.
Definition: tlv.hpp:349
constexpr bool readType(Iterator &begin, Iterator end, uint32_t &type) noexcept
Read TLV-TYPE.
Definition: tlv.hpp:367
constexpr bool isCriticalType(uint32_t type) noexcept
Determine whether a TLV-TYPE is "critical" for evolvability purpose.
Definition: tlv.hpp:162
ContentTypeValue
ContentType values.
Definition: tlv.hpp:144
@ ContentType_Key
public key, certificate
Definition: tlv.hpp:147
@ ContentType_Manifest
Definition: tlv.hpp:149
@ ContentType_Link
another name that identifies the actual data content
Definition: tlv.hpp:146
@ ContentType_Blob
payload
Definition: tlv.hpp:145
@ ContentType_Flic
File-Like ICN Collection.
Definition: tlv.hpp:151
@ ContentType_PrefixAnn
prefix announcement
Definition: tlv.hpp:150
@ ContentType_Nack
application-level nack
Definition: tlv.hpp:148
size_t writeNonNegativeInteger(std::ostream &os, uint64_t integer)
Write a NonNegativeInteger to the specified stream.
Definition: tlv.cpp:113
std::ostream & operator<<(std::ostream &os, SignatureTypeValue st)
Definition: tlv.cpp:34
size_t writeVarNumber(std::ostream &os, uint64_t number)
Write VAR-NUMBER to the specified stream.
Definition: tlv.cpp:86
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:430
SignatureTypeValue
SignatureType values.
Definition: tlv.hpp:127
@ SignatureSha256WithRsa
Definition: tlv.hpp:129
@ DigestSha256
Definition: tlv.hpp:128
@ SignatureHmacWithSha256
Definition: tlv.hpp:131
@ SignatureEd25519
Definition: tlv.hpp:132
@ SignatureSha256WithEcdsa
Definition: tlv.hpp:130
@ NullSignature
Definition: tlv.hpp:133
Definition: data.cpp:25
constexpr size_t MAX_NDN_PACKET_SIZE
Practical size limit of a network-layer packet.
Definition: tlv.hpp:41