NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.3: NDN, CCN, CCNx, content centric networks
API Documentation
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-2017 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,
71  // <Unassigned> = 11,
77  Exclude = 16,
80  Any = 19,
81  MetaInfo = 20,
82  Content = 21,
89  KeyLocator = 28,
90  KeyDigest = 29,
94 
97 };
98 
102  // <Unassigned> = 2,
104 };
105 
106 std::ostream&
107 operator<<(std::ostream& os, const SignatureTypeValue& signatureType);
108 
112 enum {
114  NotBefore = 254,
115  NotAfter = 255,
116 
121 };
122 
129 
133 
137 
141 };
142 
155 template<typename Iterator>
156 bool
157 readVarNumber(Iterator& begin, const Iterator& end, uint64_t& number);
158 
173 template<typename Iterator>
174 bool
175 readType(Iterator& begin, const Iterator& end, uint32_t& type);
176 
187 template<typename Iterator>
188 uint64_t
189 readVarNumber(Iterator& begin, const Iterator& end);
190 
203 template<typename Iterator>
204 uint32_t
205 readType(Iterator& begin, const Iterator& end);
206 
210 constexpr size_t
211 sizeOfVarNumber(uint64_t number);
212 
217 size_t
218 writeVarNumber(std::ostream& os, uint64_t number);
219 
233 template<typename Iterator>
234 uint64_t
235 readNonNegativeInteger(size_t size, Iterator& begin, const Iterator& end);
236 
240 constexpr size_t
241 sizeOfNonNegativeInteger(uint64_t integer);
242 
247 size_t
248 writeNonNegativeInteger(std::ostream& os, uint64_t integer);
249 
253 
254 // Inline definitions
255 
259 
260 namespace detail {
261 
264 template<typename Iterator>
266 {
267 public:
268  bool
269  operator()(size_t size, Iterator& begin, const Iterator& end, uint64_t& number) const
270  {
271  number = 0;
272  size_t count = 0;
273  for (; begin != end && count < size; ++begin, ++count) {
274  number = (number << 8) | *begin;
275  }
276  return count == size;
277  }
278 };
279 
282 template<typename Iterator>
284 {
285 public:
286  bool
287  operator()(size_t size, Iterator& begin, const Iterator& end, uint64_t& number) const
288  {
289  if (begin + size > end) {
290  return false;
291  }
292 
293  switch (size) {
294  case 1: {
295  number = *begin;
296  ++begin;
297  return true;
298  }
299  case 2: {
300  uint16_t value = 0;
301  std::memcpy(&value, &*begin, 2);
302  begin += 2;
303  number = be16toh(value);
304  return true;
305  }
306  case 4: {
307  uint32_t value = 0;
308  std::memcpy(&value, &*begin, 4);
309  begin += 4;
310  number = be32toh(value);
311  return true;
312  }
313  case 8: {
314  uint64_t value = 0;
315  std::memcpy(&value, &*begin, 8);
316  begin += 8;
317  number = be64toh(value);
318  return true;
319  }
320  default: {
321  BOOST_ASSERT(false);
322  return false;
323  }
324  }
325  }
326 };
327 
333 template<typename Iterator,
334  typename DecayedIterator = typename std::decay<Iterator>::type,
335  typename ValueType = typename std::iterator_traits<DecayedIterator>::value_type>
336 constexpr bool
338 {
340  std::is_convertible<DecayedIterator, typename std::basic_string<ValueType>::const_iterator>::value ||
341  std::is_convertible<DecayedIterator, typename std::vector<ValueType>::const_iterator>::value) &&
342  sizeof(ValueType) == 1 &&
344 }
345 
346 template<typename Iterator>
347 class ReadNumber : public std::conditional<shouldSelectContiguousReadNumber<Iterator>(),
348  ReadNumberFast<Iterator>, ReadNumberSlow<Iterator>>::type
349 {
350 };
351 
352 } // namespace detail
353 
354 template<typename Iterator>
355 bool
356 readVarNumber(Iterator& begin, const Iterator& end, uint64_t& number)
357 {
358  if (begin == end)
359  return false;
360 
361  uint8_t firstOctet = *begin;
362  ++begin;
363  if (firstOctet < 253) {
364  number = firstOctet;
365  return true;
366  }
367 
368  size_t size = firstOctet == 253 ? 2 :
369  firstOctet == 254 ? 4 : 8;
370  return detail::ReadNumber<Iterator>()(size, begin, end, number);
371 }
372 
373 template<typename Iterator>
374 bool
375 readType(Iterator& begin, const Iterator& end, uint32_t& type)
376 {
377  uint64_t number = 0;
378  bool isOk = readVarNumber(begin, end, number);
379  if (!isOk || number > std::numeric_limits<uint32_t>::max()) {
380  return false;
381  }
382 
383  type = static_cast<uint32_t>(number);
384  return true;
385 }
386 
387 template<typename Iterator>
388 uint64_t
389 readVarNumber(Iterator& begin, const Iterator& end)
390 {
391  if (begin == end)
392  BOOST_THROW_EXCEPTION(Error("Empty buffer during TLV processing"));
393 
394  uint64_t value = 0;
395  bool isOk = readVarNumber(begin, end, value);
396  if (!isOk) {
397  BOOST_THROW_EXCEPTION(Error("Insufficient data during TLV processing"));
398  }
399 
400  return value;
401 }
402 
403 template<typename Iterator>
404 uint32_t
405 readType(Iterator& begin, const Iterator& end)
406 {
407  uint64_t type = readVarNumber(begin, end);
408  if (type > std::numeric_limits<uint32_t>::max()) {
409  BOOST_THROW_EXCEPTION(Error("TLV-TYPE number exceeds allowed maximum"));
410  }
411 
412  return static_cast<uint32_t>(type);
413 }
414 
415 constexpr size_t
416 sizeOfVarNumber(uint64_t number)
417 {
418  return number < 253 ? 1 :
419  number <= std::numeric_limits<uint16_t>::max() ? 3 :
420  number <= std::numeric_limits<uint32_t>::max() ? 5 : 9;
421 }
422 
423 inline size_t
424 writeVarNumber(std::ostream& os, uint64_t number)
425 {
426  if (number < 253) {
427  os.put(static_cast<char>(number));
428  return 1;
429  }
430  else if (number <= std::numeric_limits<uint16_t>::max()) {
431  os.put(static_cast<char>(253));
432  uint16_t value = htobe16(static_cast<uint16_t>(number));
433  os.write(reinterpret_cast<const char*>(&value), 2);
434  return 3;
435  }
436  else if (number <= std::numeric_limits<uint32_t>::max()) {
437  os.put(static_cast<char>(254));
438  uint32_t value = htobe32(static_cast<uint32_t>(number));
439  os.write(reinterpret_cast<const char*>(&value), 4);
440  return 5;
441  }
442  else {
443  os.put(static_cast<char>(255));
444  uint64_t value = htobe64(number);
445  os.write(reinterpret_cast<const char*>(&value), 8);
446  return 9;
447  }
448 }
449 
450 template<typename Iterator>
451 uint64_t
452 readNonNegativeInteger(size_t size, Iterator& begin, const Iterator& end)
453 {
454  if (size != 1 && size != 2 && size != 4 && size != 8) {
455  BOOST_THROW_EXCEPTION(Error("Invalid length for nonNegativeInteger "
456  "(only 1, 2, 4, and 8 are allowed)"));
457  }
458 
459  uint64_t number = 0;
460  bool isOk = detail::ReadNumber<Iterator>()(size, begin, end, number);
461  if (!isOk) {
462  BOOST_THROW_EXCEPTION(Error("Insufficient data during TLV processing"));
463  }
464 
465  return number;
466 }
467 
468 constexpr size_t
469 sizeOfNonNegativeInteger(uint64_t integer)
470 {
471  return integer <= std::numeric_limits<uint8_t>::max() ? 1 :
472  integer <= std::numeric_limits<uint16_t>::max() ? 2 :
473  integer <= std::numeric_limits<uint32_t>::max() ? 4 : 8;
474 }
475 
476 inline size_t
477 writeNonNegativeInteger(std::ostream& os, uint64_t integer)
478 {
479  if (integer <= std::numeric_limits<uint8_t>::max()) {
480  os.put(static_cast<char>(integer));
481  return 1;
482  }
483  else if (integer <= std::numeric_limits<uint16_t>::max()) {
484  uint16_t value = htobe16(static_cast<uint16_t>(integer));
485  os.write(reinterpret_cast<const char*>(&value), 2);
486  return 2;
487  }
488  else if (integer <= std::numeric_limits<uint32_t>::max()) {
489  uint32_t value = htobe32(static_cast<uint32_t>(integer));
490  os.write(reinterpret_cast<const char*>(&value), 4);
491  return 4;
492  }
493  else {
494  uint64_t value = htobe64(integer);
495  os.write(reinterpret_cast<const char*>(&value), 8);
496  return 8;
497  }
498 }
499 
500 
501 } // namespace tlv
502 } // namespace ndn
503 
504 #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
Definition: tlv.hpp:287
Copyright (c) 2011-2015 Regents of the University of California.
Error(const std::string &what)
Definition: tlv.hpp:54
bool readType(Iterator &begin, const Iterator &end, uint32_t &type)
Read TLV-TYPE.
Definition: tlv.hpp:375
Represents a SignatureInfo TLV element.
indicates a producer generated NACK
Definition: tlv.hpp:140
Represents a signature of DigestSha256 type.
STL namespace.
represents an Interest packet
Definition: interest.hpp:42
size_t writeNonNegativeInteger(std::ostream &os, uint64_t integer)
Write nonNegativeInteger to the specified stream.
Definition: tlv.hpp:477
bool readVarNumber(Iterator &begin, const Iterator &end, uint64_t &number)
Read VAR-NUMBER in NDN-TLV encoding.
Definition: tlv.hpp:356
size_t writeVarNumber(std::ostream &os, uint64_t number)
Write VAR-NUMBER to the specified stream.
Definition: tlv.hpp:424
uint64_t readNonNegativeInteger(size_t size, Iterator &begin, const Iterator &end)
Read nonNegativeInteger in NDN-TLV encoding.
Definition: tlv.hpp:452
Represents a signature of Sha256WithEcdsa type.
constexpr size_t sizeOfNonNegativeInteger(uint64_t integer)
Get number of bytes necessary to hold value of nonNegativeInteger.
Definition: tlv.hpp:469
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.
Definition: tlv.hpp:337
Represents an absolute name.
Definition: name.hpp:42
ContentTypeValue
indicates a possible value of ContentType field
Definition: tlv.hpp:125
indicates content is the actual data bits
Definition: tlv.hpp:128
SignatureTypeValue
Definition: tlv.hpp:99
Function object to read a number from InputIterator.
Definition: tlv.hpp:265
indicates content is a public key
Definition: tlv.hpp:136
constexpr size_t sizeOfVarNumber(uint64_t number)
Get number of bytes necessary to hold value of VAR-NUMBER.
Definition: tlv.hpp:416
Represents a Data packet.
Definition: data.hpp:35
bool operator()(size_t size, Iterator &begin, const Iterator &end, uint64_t &number) const
Definition: tlv.hpp:269
indicates content is another name which identifies actual data content
Definition: tlv.hpp:132
std::ostream & operator<<(std::ostream &os, const SignatureTypeValue &signatureType)
Definition: tlv.cpp:28
represents an error in TLV encoding or decoding
Definition: tlv.hpp:50
Represents Exclude selector in NDN Interest.
Definition: exclude.hpp:37
const size_t MAX_NDN_PACKET_SIZE
practical limit of network layer packet size
Definition: tlv.hpp:39
Function object to read a number from ContiguousIterator.
Definition: tlv.hpp:283