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,
69  Selectors = 9,
70  Nonce = 10,
76  Exclude = 16,
79  Any = 19,
80  MetaInfo = 20,
81  Content = 21,
88  KeyLocator = 28,
89  KeyDigest = 29,
92 
95 };
96 
97 enum SignatureTypeValue : uint16_t {
100  // <Unassigned> = 2,
102 };
103 
104 std::ostream&
105 operator<<(std::ostream& os, SignatureTypeValue signatureType);
106 
110 enum {
112  NotBefore = 254,
113  NotAfter = 255,
114 
119 };
120 
127 
131 
135 
139 };
140 
153 template<typename Iterator>
154 bool
155 readVarNumber(Iterator& begin, const Iterator& end, uint64_t& number);
156 
171 template<typename Iterator>
172 bool
173 readType(Iterator& begin, const Iterator& end, uint32_t& type);
174 
185 template<typename Iterator>
186 uint64_t
187 readVarNumber(Iterator& begin, const Iterator& end);
188 
201 template<typename Iterator>
202 uint32_t
203 readType(Iterator& begin, const Iterator& end);
204 
208 constexpr size_t
209 sizeOfVarNumber(uint64_t number);
210 
215 size_t
216 writeVarNumber(std::ostream& os, uint64_t number);
217 
231 template<typename Iterator>
232 uint64_t
233 readNonNegativeInteger(size_t size, Iterator& begin, const Iterator& end);
234 
238 constexpr size_t
239 sizeOfNonNegativeInteger(uint64_t integer);
240 
245 size_t
246 writeNonNegativeInteger(std::ostream& os, uint64_t integer);
247 
251 
252 // Inline definitions
253 
257 
258 namespace detail {
259 
262 template<typename Iterator>
264 {
265 public:
266  bool
267  operator()(size_t size, Iterator& begin, const Iterator& end, uint64_t& number) const
268  {
269  number = 0;
270  size_t count = 0;
271  for (; begin != end && count < size; ++begin, ++count) {
272  number = (number << 8) | *begin;
273  }
274  return count == size;
275  }
276 };
277 
280 template<typename Iterator>
282 {
283 public:
284  bool
285  operator()(size_t size, Iterator& begin, const Iterator& end, uint64_t& number) const
286  {
287  if (begin + size > end) {
288  return false;
289  }
290 
291  switch (size) {
292  case 1: {
293  number = *begin;
294  ++begin;
295  return true;
296  }
297  case 2: {
298  uint16_t value = 0;
299  std::memcpy(&value, &*begin, 2);
300  begin += 2;
301  number = be16toh(value);
302  return true;
303  }
304  case 4: {
305  uint32_t value = 0;
306  std::memcpy(&value, &*begin, 4);
307  begin += 4;
308  number = be32toh(value);
309  return true;
310  }
311  case 8: {
312  uint64_t value = 0;
313  std::memcpy(&value, &*begin, 8);
314  begin += 8;
315  number = be64toh(value);
316  return true;
317  }
318  default: {
319  BOOST_ASSERT(false);
320  return false;
321  }
322  }
323  }
324 };
325 
331 template<typename Iterator,
332  typename DecayedIterator = typename std::decay<Iterator>::type,
333  typename ValueType = typename std::iterator_traits<DecayedIterator>::value_type>
334 constexpr bool
336 {
337  return (std::is_convertible<DecayedIterator, const ValueType*>::value ||
338  std::is_convertible<DecayedIterator, typename std::basic_string<ValueType>::const_iterator>::value ||
339  std::is_convertible<DecayedIterator, typename std::vector<ValueType>::const_iterator>::value) &&
340  sizeof(ValueType) == 1 &&
341  !std::is_same<ValueType, bool>::value;
342 }
343 
344 template<typename Iterator>
345 class ReadNumber : public std::conditional<shouldSelectContiguousReadNumber<Iterator>(),
346  ReadNumberFast<Iterator>, ReadNumberSlow<Iterator>>::type
347 {
348 };
349 
350 } // namespace detail
351 
352 template<typename Iterator>
353 bool
354 readVarNumber(Iterator& begin, const Iterator& end, uint64_t& number)
355 {
356  if (begin == end)
357  return false;
358 
359  uint8_t firstOctet = *begin;
360  ++begin;
361  if (firstOctet < 253) {
362  number = firstOctet;
363  return true;
364  }
365 
366  size_t size = firstOctet == 253 ? 2 :
367  firstOctet == 254 ? 4 : 8;
368  return detail::ReadNumber<Iterator>()(size, begin, end, number);
369 }
370 
371 template<typename Iterator>
372 bool
373 readType(Iterator& begin, const Iterator& end, uint32_t& type)
374 {
375  uint64_t number = 0;
376  bool isOk = readVarNumber(begin, end, number);
377  if (!isOk || number > std::numeric_limits<uint32_t>::max()) {
378  return false;
379  }
380 
381  type = static_cast<uint32_t>(number);
382  return true;
383 }
384 
385 template<typename Iterator>
386 uint64_t
387 readVarNumber(Iterator& begin, const Iterator& end)
388 {
389  if (begin == end)
390  BOOST_THROW_EXCEPTION(Error("Empty buffer during TLV processing"));
391 
392  uint64_t value = 0;
393  bool isOk = readVarNumber(begin, end, value);
394  if (!isOk) {
395  BOOST_THROW_EXCEPTION(Error("Insufficient data during TLV processing"));
396  }
397 
398  return value;
399 }
400 
401 template<typename Iterator>
402 uint32_t
403 readType(Iterator& begin, const Iterator& end)
404 {
405  uint64_t type = readVarNumber(begin, end);
406  if (type > std::numeric_limits<uint32_t>::max()) {
407  BOOST_THROW_EXCEPTION(Error("TLV-TYPE number exceeds allowed maximum"));
408  }
409 
410  return static_cast<uint32_t>(type);
411 }
412 
413 constexpr size_t
414 sizeOfVarNumber(uint64_t number)
415 {
416  return number < 253 ? 1 :
417  number <= std::numeric_limits<uint16_t>::max() ? 3 :
418  number <= std::numeric_limits<uint32_t>::max() ? 5 : 9;
419 }
420 
421 inline size_t
422 writeVarNumber(std::ostream& os, uint64_t number)
423 {
424  if (number < 253) {
425  os.put(static_cast<char>(number));
426  return 1;
427  }
428  else if (number <= std::numeric_limits<uint16_t>::max()) {
429  os.put(static_cast<char>(253));
430  uint16_t value = htobe16(static_cast<uint16_t>(number));
431  os.write(reinterpret_cast<const char*>(&value), 2);
432  return 3;
433  }
434  else if (number <= std::numeric_limits<uint32_t>::max()) {
435  os.put(static_cast<char>(254));
436  uint32_t value = htobe32(static_cast<uint32_t>(number));
437  os.write(reinterpret_cast<const char*>(&value), 4);
438  return 5;
439  }
440  else {
441  os.put(static_cast<char>(255));
442  uint64_t value = htobe64(number);
443  os.write(reinterpret_cast<const char*>(&value), 8);
444  return 9;
445  }
446 }
447 
448 template<typename Iterator>
449 uint64_t
450 readNonNegativeInteger(size_t size, Iterator& begin, const Iterator& end)
451 {
452  if (size != 1 && size != 2 && size != 4 && size != 8) {
453  BOOST_THROW_EXCEPTION(Error("Invalid length for nonNegativeInteger "
454  "(only 1, 2, 4, and 8 are allowed)"));
455  }
456 
457  uint64_t number = 0;
458  bool isOk = detail::ReadNumber<Iterator>()(size, begin, end, number);
459  if (!isOk) {
460  BOOST_THROW_EXCEPTION(Error("Insufficient data during TLV processing"));
461  }
462 
463  return number;
464 }
465 
466 constexpr size_t
467 sizeOfNonNegativeInteger(uint64_t integer)
468 {
469  return integer <= std::numeric_limits<uint8_t>::max() ? 1 :
470  integer <= std::numeric_limits<uint16_t>::max() ? 2 :
471  integer <= std::numeric_limits<uint32_t>::max() ? 4 : 8;
472 }
473 
474 inline size_t
475 writeNonNegativeInteger(std::ostream& os, uint64_t integer)
476 {
477  if (integer <= std::numeric_limits<uint8_t>::max()) {
478  os.put(static_cast<char>(integer));
479  return 1;
480  }
481  else if (integer <= std::numeric_limits<uint16_t>::max()) {
482  uint16_t value = htobe16(static_cast<uint16_t>(integer));
483  os.write(reinterpret_cast<const char*>(&value), 2);
484  return 2;
485  }
486  else if (integer <= std::numeric_limits<uint32_t>::max()) {
487  uint32_t value = htobe32(static_cast<uint32_t>(integer));
488  os.write(reinterpret_cast<const char*>(&value), 4);
489  return 4;
490  }
491  else {
492  uint64_t value = htobe64(integer);
493  os.write(reinterpret_cast<const char*>(&value), 8);
494  return 8;
495  }
496 }
497 
498 
499 } // namespace tlv
500 } // namespace ndn
501 
502 #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
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
Function object to read a number from InputIterator.
indicates content is a public key
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:37
const size_t MAX_NDN_PACKET_SIZE
practical limit of network layer packet size
Function object to read a number from ContiguousIterator.