encoding/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 
25 #include "buffer.hpp"
26 #include "endian.hpp"
27 
28 #include <cstring>
29 #include <iterator>
30 #include <ostream>
31 #include <type_traits>
32 
33 namespace ndn {
34 
39 const size_t MAX_NDN_PACKET_SIZE = 8800;
40 
44 namespace tlv {
45 
50 class Error : public std::runtime_error
51 {
52 public:
53  explicit
54  Error(const std::string& what)
55  : std::runtime_error(what)
56  {
57  }
58 };
59 
63 enum {
64  Interest = 5,
65  Data = 6,
66  Name = 7,
72  Nonce = 10,
74  HopLimit = 34,
75  Parameters = 35,
76  MetaInfo = 20,
77  Content = 21,
84  KeyLocator = 28,
85  KeyDigest = 29,
88 
91 
94 };
95 
99 enum {
104  Exclude = 16,
106  Any = 19,
107 };
108 
110 
111 enum SignatureTypeValue : uint16_t {
114  // <Unassigned> = 2,
116 };
117 
118 std::ostream&
119 operator<<(std::ostream& os, SignatureTypeValue signatureType);
120 
124 enum {
126  NotBefore = 254,
127  NotAfter = 255,
128 
133 };
134 
141 
145 
149 
153 };
154 
159 constexpr bool
160 isCriticalType(uint32_t type)
161 {
162  return type <= 31 || (type & 0x01);
163 }
164 
177 template<typename Iterator>
178 bool
179 readVarNumber(Iterator& begin, const Iterator& end, uint64_t& number);
180 
195 template<typename Iterator>
196 bool
197 readType(Iterator& begin, const Iterator& end, uint32_t& type);
198 
209 template<typename Iterator>
210 uint64_t
211 readVarNumber(Iterator& begin, const Iterator& end);
212 
225 template<typename Iterator>
226 uint32_t
227 readType(Iterator& begin, const Iterator& end);
228 
232 constexpr size_t
233 sizeOfVarNumber(uint64_t number);
234 
239 size_t
240 writeVarNumber(std::ostream& os, uint64_t number);
241 
255 template<typename Iterator>
256 uint64_t
257 readNonNegativeInteger(size_t size, Iterator& begin, const Iterator& end);
258 
262 constexpr size_t
263 sizeOfNonNegativeInteger(uint64_t integer);
264 
269 size_t
270 writeNonNegativeInteger(std::ostream& os, uint64_t integer);
271 
275 
276 // Inline definitions
277 
281 
282 namespace detail {
283 
286 template<typename Iterator>
288 {
289 public:
290  bool
291  operator()(size_t size, Iterator& begin, const Iterator& end, uint64_t& number) const
292  {
293  number = 0;
294  size_t count = 0;
295  for (; begin != end && count < size; ++begin, ++count) {
296  number = (number << 8) | *begin;
297  }
298  return count == size;
299  }
300 };
301 
304 template<typename Iterator>
306 {
307 public:
308  bool
309  operator()(size_t size, Iterator& begin, const Iterator& end, uint64_t& number) const
310  {
311  if (begin + size > end) {
312  return false;
313  }
314 
315  switch (size) {
316  case 1: {
317  number = *begin;
318  ++begin;
319  return true;
320  }
321  case 2: {
322  uint16_t value = 0;
323  std::memcpy(&value, &*begin, 2);
324  begin += 2;
325  number = be16toh(value);
326  return true;
327  }
328  case 4: {
329  uint32_t value = 0;
330  std::memcpy(&value, &*begin, 4);
331  begin += 4;
332  number = be32toh(value);
333  return true;
334  }
335  case 8: {
336  uint64_t value = 0;
337  std::memcpy(&value, &*begin, 8);
338  begin += 8;
339  number = be64toh(value);
340  return true;
341  }
342  default: {
343  BOOST_ASSERT(false);
344  return false;
345  }
346  }
347  }
348 };
349 
355 template<typename Iterator,
356  typename DecayedIterator = typename std::decay<Iterator>::type,
357  typename ValueType = typename std::iterator_traits<DecayedIterator>::value_type>
358 constexpr bool
360 {
361  return (std::is_convertible<DecayedIterator, const ValueType*>::value ||
362  std::is_convertible<DecayedIterator, typename std::basic_string<ValueType>::const_iterator>::value ||
363  std::is_convertible<DecayedIterator, typename std::vector<ValueType>::const_iterator>::value) &&
364  sizeof(ValueType) == 1 &&
365  !std::is_same<ValueType, bool>::value;
366 }
367 
368 template<typename Iterator>
369 class ReadNumber : public std::conditional<shouldSelectContiguousReadNumber<Iterator>(),
370  ReadNumberFast<Iterator>, ReadNumberSlow<Iterator>>::type
371 {
372 };
373 
374 } // namespace detail
375 
376 template<typename Iterator>
377 bool
378 readVarNumber(Iterator& begin, const Iterator& end, uint64_t& number)
379 {
380  if (begin == end)
381  return false;
382 
383  uint8_t firstOctet = *begin;
384  ++begin;
385  if (firstOctet < 253) {
386  number = firstOctet;
387  return true;
388  }
389 
390  size_t size = firstOctet == 253 ? 2 :
391  firstOctet == 254 ? 4 : 8;
392  return detail::ReadNumber<Iterator>()(size, begin, end, number);
393 }
394 
395 template<typename Iterator>
396 bool
397 readType(Iterator& begin, const Iterator& end, uint32_t& type)
398 {
399  uint64_t number = 0;
400  bool isOk = readVarNumber(begin, end, number);
401  if (!isOk || number > std::numeric_limits<uint32_t>::max()) {
402  return false;
403  }
404 
405  type = static_cast<uint32_t>(number);
406  return true;
407 }
408 
409 template<typename Iterator>
410 uint64_t
411 readVarNumber(Iterator& begin, const Iterator& end)
412 {
413  if (begin == end)
414  BOOST_THROW_EXCEPTION(Error("Empty buffer during TLV processing"));
415 
416  uint64_t value = 0;
417  bool isOk = readVarNumber(begin, end, value);
418  if (!isOk) {
419  BOOST_THROW_EXCEPTION(Error("Insufficient data during TLV processing"));
420  }
421 
422  return value;
423 }
424 
425 template<typename Iterator>
426 uint32_t
427 readType(Iterator& begin, const Iterator& end)
428 {
429  uint64_t type = readVarNumber(begin, end);
430  if (type > std::numeric_limits<uint32_t>::max()) {
431  BOOST_THROW_EXCEPTION(Error("TLV-TYPE number exceeds allowed maximum"));
432  }
433 
434  return static_cast<uint32_t>(type);
435 }
436 
437 constexpr size_t
438 sizeOfVarNumber(uint64_t number)
439 {
440  return number < 253 ? 1 :
441  number <= std::numeric_limits<uint16_t>::max() ? 3 :
442  number <= std::numeric_limits<uint32_t>::max() ? 5 : 9;
443 }
444 
445 inline size_t
446 writeVarNumber(std::ostream& os, uint64_t number)
447 {
448  if (number < 253) {
449  os.put(static_cast<char>(number));
450  return 1;
451  }
452  else if (number <= std::numeric_limits<uint16_t>::max()) {
453  os.put(static_cast<char>(253));
454  uint16_t value = htobe16(static_cast<uint16_t>(number));
455  os.write(reinterpret_cast<const char*>(&value), 2);
456  return 3;
457  }
458  else if (number <= std::numeric_limits<uint32_t>::max()) {
459  os.put(static_cast<char>(254));
460  uint32_t value = htobe32(static_cast<uint32_t>(number));
461  os.write(reinterpret_cast<const char*>(&value), 4);
462  return 5;
463  }
464  else {
465  os.put(static_cast<char>(255));
466  uint64_t value = htobe64(number);
467  os.write(reinterpret_cast<const char*>(&value), 8);
468  return 9;
469  }
470 }
471 
472 template<typename Iterator>
473 uint64_t
474 readNonNegativeInteger(size_t size, Iterator& begin, const Iterator& end)
475 {
476  if (size != 1 && size != 2 && size != 4 && size != 8) {
477  BOOST_THROW_EXCEPTION(Error("Invalid length for nonNegativeInteger "
478  "(only 1, 2, 4, and 8 are allowed)"));
479  }
480 
481  uint64_t number = 0;
482  bool isOk = detail::ReadNumber<Iterator>()(size, begin, end, number);
483  if (!isOk) {
484  BOOST_THROW_EXCEPTION(Error("Insufficient data during TLV processing"));
485  }
486 
487  return number;
488 }
489 
490 constexpr size_t
491 sizeOfNonNegativeInteger(uint64_t integer)
492 {
493  return integer <= std::numeric_limits<uint8_t>::max() ? 1 :
494  integer <= std::numeric_limits<uint16_t>::max() ? 2 :
495  integer <= std::numeric_limits<uint32_t>::max() ? 4 : 8;
496 }
497 
498 inline size_t
499 writeNonNegativeInteger(std::ostream& os, uint64_t integer)
500 {
501  if (integer <= std::numeric_limits<uint8_t>::max()) {
502  os.put(static_cast<char>(integer));
503  return 1;
504  }
505  else if (integer <= std::numeric_limits<uint16_t>::max()) {
506  uint16_t value = htobe16(static_cast<uint16_t>(integer));
507  os.write(reinterpret_cast<const char*>(&value), 2);
508  return 2;
509  }
510  else if (integer <= std::numeric_limits<uint32_t>::max()) {
511  uint32_t value = htobe32(static_cast<uint32_t>(integer));
512  os.write(reinterpret_cast<const char*>(&value), 4);
513  return 4;
514  }
515  else {
516  uint64_t value = htobe64(integer);
517  os.write(reinterpret_cast<const char*>(&value), 8);
518  return 8;
519  }
520 }
521 
522 
523 } // namespace tlv
524 } // namespace ndn
525 
526 #endif // NDN_ENCODING_TLV_HPP
Represents a signature of Sha256WithRsa type.
bool operator()(size_t size, Iterator &begin, const Iterator &end, uint64_t &number) const
Copyright (c) 2013-2017 Regents of the University of California.
Definition: common.hpp:66
Error(const std::string &what)
bool readType(Iterator &begin, const Iterator &end, uint32_t &type)
Read TLV-TYPE.
Represents a SignatureInfo TLV element.
indicates a producer generated NACK
constexpr bool isCriticalType(uint32_t type)
Determine whether a TLV-TYPE is "critical" for evolvability purpose.
Represents a signature of DigestSha256 type.
STL namespace.
Represents an Interest packet.
Definition: interest.hpp:42
std::ostream & operator<<(std::ostream &os, SignatureTypeValue signatureType)
Definition: tlv.cpp:28
size_t writeNonNegativeInteger(std::ostream &os, uint64_t integer)
Write nonNegativeInteger to the specified stream.
bool readVarNumber(Iterator &begin, const Iterator &end, uint64_t &number)
Read VAR-NUMBER in NDN-TLV encoding.
size_t writeVarNumber(std::ostream &os, uint64_t number)
Write VAR-NUMBER to the specified stream.
uint64_t readNonNegativeInteger(size_t size, Iterator &begin, const Iterator &end)
Read nonNegativeInteger in NDN-TLV encoding.
Represents a signature of Sha256WithEcdsa type.
constexpr size_t sizeOfNonNegativeInteger(uint64_t integer)
Get number of bytes necessary to hold value of nonNegativeInteger.
An MetaInfo holds the meta info which is signed inside the data packet.
Definition: meta-info.hpp:58
Abstraction implementing Interest selectors.
Definition: selectors.hpp:36
constexpr bool shouldSelectContiguousReadNumber()
Determine whether to select ReadNumber implementation for ContiguousIterator.
Represents an absolute name.
Definition: name.hpp:42
ContentTypeValue
indicates a possible value of ContentType field
indicates content is the actual data bits
constexpr int NameComponent
Function object to read a number from InputIterator.
indicates content is a public key
#define NDN_CXX_DEPRECATED
Mark a type, variable, or function as deprecated.
Definition: backports.hpp:75
constexpr size_t sizeOfVarNumber(uint64_t number)
Get number of bytes necessary to hold value of VAR-NUMBER.
Represents a Data packet.
Definition: data.hpp:35
bool operator()(size_t size, Iterator &begin, const Iterator &end, uint64_t &number) const
indicates content is another name which identifies actual data content
represents an error in TLV encoding or decoding
Represents Exclude selector in NDN Interest.
Definition: exclude.hpp:42
const size_t MAX_NDN_PACKET_SIZE
practical limit of network layer packet size
Function object to read a number from ContiguousIterator.