NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.0: 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; -*- */
22 #ifndef NDN_ENCODING_TLV_HPP
23 #define NDN_ENCODING_TLV_HPP
24 
25 #include <stdexcept>
26 #include <iostream>
27 #include <iterator>
28 #include <limits>
29 
30 #include "buffer.hpp"
31 #include "endian.hpp"
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 
60 enum {
61  Interest = 5,
62  Data = 6,
63  Name = 7,
66  Selectors = 9,
67  Nonce = 10,
68  // <Unassigned> = 11,
73  Exclude = 16,
76  Any = 19,
77  MetaInfo = 20,
78  Content = 21,
85  KeyLocator = 28,
86  KeyDigest = 29,
90 
93 };
94 
98  // <Unassigned> = 2,
100 };
101 
105 enum {
106  // SignatureInfo TLVs
108  NotBefore = 254,
109  NotAfter = 255,
110 
115 };
116 
123 
127 
131 
136 };
137 
149 template<class InputIterator>
150 inline bool
151 readVarNumber(InputIterator& begin, const InputIterator& end, uint64_t& number);
152 
165 template<class InputIterator>
166 inline bool
167 readType(InputIterator& begin, const InputIterator& end, uint32_t& type);
168 
169 
177 template<class InputIterator>
178 inline uint64_t
179 readVarNumber(InputIterator& begin, const InputIterator& end);
180 
189 template<class InputIterator>
190 inline uint32_t
191 readType(InputIterator& begin, const InputIterator& end);
192 
196 inline size_t
197 sizeOfVarNumber(uint64_t varNumber);
198 
202 inline size_t
203 writeVarNumber(std::ostream& os, uint64_t varNumber);
204 
215 template<class InputIterator>
216 inline uint64_t
217 readNonNegativeInteger(size_t size, InputIterator& begin, const InputIterator& end);
218 
222 inline size_t
223 sizeOfNonNegativeInteger(uint64_t varNumber);
224 
228 inline size_t
229 writeNonNegativeInteger(std::ostream& os, uint64_t varNumber);
230 
234 
235 // Inline implementations
236 
240 
241 template<class InputIterator>
242 inline bool
243 readVarNumber(InputIterator& begin, const InputIterator& end, uint64_t& number)
244 {
245  if (begin == end)
246  return false;
247 
248  uint8_t firstOctet = *begin;
249  ++begin;
250  if (firstOctet < 253)
251  {
252  number = firstOctet;
253  }
254  else if (firstOctet == 253)
255  {
256  if (end - begin < 2)
257  return false;
258 
259  uint16_t value = *reinterpret_cast<const uint16_t*>(&*begin);
260  begin += 2;
261  number = be16toh(value);
262  }
263  else if (firstOctet == 254)
264  {
265  if (end - begin < 4)
266  return false;
267 
268  uint32_t value = *reinterpret_cast<const uint32_t*>(&*begin);
269  begin += 4;
270  number = be32toh(value);
271  }
272  else // if (firstOctet == 255)
273  {
274  if (end - begin < 8)
275  return false;
276 
277  uint64_t value = *reinterpret_cast<const uint64_t*>(&*begin);
278  begin += 8;
279 
280  number = be64toh(value);
281  }
282 
283  return true;
284 }
285 
286 template<class InputIterator>
287 inline bool
288 readType(InputIterator& begin, const InputIterator& end, uint32_t& type)
289 {
290  uint64_t number = 0;
291  bool isOk = readVarNumber(begin, end, number);
292  if (!isOk || number > std::numeric_limits<uint32_t>::max())
293  {
294  return false;
295  }
296 
297  type = static_cast<uint64_t>(number);
298  return true;
299 }
300 
301 template<class InputIterator>
302 inline uint64_t
303 readVarNumber(InputIterator& begin, const InputIterator& end)
304 {
305  if (begin == end)
306  BOOST_THROW_EXCEPTION(Error("Empty buffer during TLV processing"));
307 
308  uint64_t value;
309  bool isOk = readVarNumber(begin, end, value);
310  if (!isOk)
311  BOOST_THROW_EXCEPTION(Error("Insufficient data during TLV processing"));
312 
313  return value;
314 }
315 
316 template<>
317 inline bool
318 readVarNumber<std::istream_iterator<uint8_t>>(std::istream_iterator<uint8_t>& begin,
319  const std::istream_iterator<uint8_t>& end,
320  uint64_t& value)
321 {
322  if (begin == end)
323  return false;
324 
325  uint8_t firstOctet = *begin;
326  ++begin;
327  if (firstOctet < 253)
328  {
329  value = firstOctet;
330  }
331  else if (firstOctet == 253)
332  {
333  value = 0;
334  size_t count = 0;
335  for (; begin != end && count < 2; ++count)
336  {
337  value = ((value << 8) | *begin);
338  begin++;
339  }
340 
341  if (count != 2)
342  return false;
343  }
344  else if (firstOctet == 254)
345  {
346  value = 0;
347  size_t count = 0;
348  for (; begin != end && count < 4; ++count)
349  {
350  value = ((value << 8) | *begin);
351  begin++;
352  }
353 
354  if (count != 4)
355  return false;
356  }
357  else // if (firstOctet == 255)
358  {
359  value = 0;
360  size_t count = 0;
361  for (; begin != end && count < 8; ++count)
362  {
363  value = ((value << 8) | *begin);
364  begin++;
365  }
366 
367  if (count != 8)
368  return false;
369  }
370 
371  return true;
372 }
373 
374 template<class InputIterator>
375 inline uint32_t
376 readType(InputIterator& begin, const InputIterator& end)
377 {
378  uint64_t type = readVarNumber(begin, end);
379  if (type > std::numeric_limits<uint32_t>::max())
380  {
381  BOOST_THROW_EXCEPTION(Error("TLV type code exceeds allowed maximum"));
382  }
383 
384  return static_cast<uint32_t>(type);
385 }
386 
387 size_t
388 sizeOfVarNumber(uint64_t varNumber)
389 {
390  if (varNumber < 253) {
391  return 1;
392  }
393  else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
394  return 3;
395  }
396  else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
397  return 5;
398  }
399  else {
400  return 9;
401  }
402 }
403 
404 inline size_t
405 writeVarNumber(std::ostream& os, uint64_t varNumber)
406 {
407  if (varNumber < 253) {
408  os.put(static_cast<char>(varNumber));
409  return 1;
410  }
411  else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
412  os.put(static_cast<char>(253));
413  uint16_t value = htobe16(static_cast<uint16_t>(varNumber));
414  os.write(reinterpret_cast<const char*>(&value), 2);
415  return 3;
416  }
417  else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
418  os.put(static_cast<char>(254));
419  uint32_t value = htobe32(static_cast<uint32_t>(varNumber));
420  os.write(reinterpret_cast<const char*>(&value), 4);
421  return 5;
422  }
423  else {
424  os.put(static_cast<char>(255));
425  uint64_t value = htobe64(varNumber);
426  os.write(reinterpret_cast<const char*>(&value), 8);
427  return 9;
428  }
429 }
430 
431 template<class InputIterator>
432 inline uint64_t
433 readNonNegativeInteger(size_t size, InputIterator& begin, const InputIterator& end)
434 {
435  switch (size) {
436  case 1:
437  {
438  if (end - begin < 1)
439  BOOST_THROW_EXCEPTION(Error("Insufficient data during TLV processing"));
440 
441  uint8_t value = *begin;
442  begin++;
443  return value;
444  }
445  case 2:
446  {
447  if (end - begin < 2)
448  BOOST_THROW_EXCEPTION(Error("Insufficient data during TLV processing"));
449 
450  uint16_t value = *reinterpret_cast<const uint16_t*>(&*begin);
451  begin += 2;
452  return be16toh(value);
453  }
454  case 4:
455  {
456  if (end - begin < 4)
457  BOOST_THROW_EXCEPTION(Error("Insufficient data during TLV processing"));
458 
459  uint32_t value = *reinterpret_cast<const uint32_t*>(&*begin);
460  begin += 4;
461  return be32toh(value);
462  }
463  case 8:
464  {
465  if (end - begin < 8)
466  BOOST_THROW_EXCEPTION(Error("Insufficient data during TLV processing"));
467 
468  uint64_t value = *reinterpret_cast<const uint64_t*>(&*begin);
469  begin += 8;
470  return be64toh(value);
471  }
472  }
473  BOOST_THROW_EXCEPTION(Error("Invalid length for nonNegativeInteger (only 1, 2, 4, and 8 are allowed)"));
474 }
475 
476 template<>
477 inline uint64_t
478 readNonNegativeInteger<std::istream_iterator<uint8_t> >(size_t size,
479  std::istream_iterator<uint8_t>& begin,
480  const std::istream_iterator<uint8_t>& end)
481 {
482  switch (size) {
483  case 1:
484  {
485  if (begin == end)
486  BOOST_THROW_EXCEPTION(Error("Insufficient data during TLV processing"));
487 
488  uint64_t value = *begin;
489  begin++;
490  return value;
491  }
492  case 2:
493  {
494  uint64_t value = 0;
495  size_t count = 0;
496  for (; begin != end && count < 2; ++count)
497  {
498  value = ((value << 8) | *begin);
499  begin++;
500  }
501 
502  if (count != 2)
503  BOOST_THROW_EXCEPTION(Error("Insufficient data during TLV processing"));
504 
505  return value;
506  }
507  case 4:
508  {
509  uint64_t value = 0;
510  size_t count = 0;
511  for (; begin != end && count < 4; ++count)
512  {
513  value = ((value << 8) | *begin);
514  begin++;
515  }
516 
517  if (count != 4)
518  BOOST_THROW_EXCEPTION(Error("Insufficient data during TLV processing"));
519 
520  return value;
521  }
522  case 8:
523  {
524  uint64_t value = 0;
525  size_t count = 0;
526  for (; begin != end && count < 8; ++count)
527  {
528  value = ((value << 8) | *begin);
529  begin++;
530  }
531 
532  if (count != 8)
533  BOOST_THROW_EXCEPTION(Error("Insufficient data during TLV processing"));
534 
535  return value;
536  }
537  }
538  BOOST_THROW_EXCEPTION(Error("Invalid length for nonNegativeInteger (only 1, 2, 4, and 8 are allowed)"));
539 }
540 
541 inline size_t
542 sizeOfNonNegativeInteger(uint64_t varNumber)
543 {
544  if (varNumber < 253) {
545  return 1;
546  }
547  else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
548  return 2;
549  }
550  else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
551  return 4;
552  }
553  else {
554  return 8;
555  }
556 }
557 
558 
559 inline size_t
560 writeNonNegativeInteger(std::ostream& os, uint64_t varNumber)
561 {
562  if (varNumber < 253) {
563  os.put(static_cast<char>(varNumber));
564  return 1;
565  }
566  else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
567  uint16_t value = htobe16(static_cast<uint16_t>(varNumber));
568  os.write(reinterpret_cast<const char*>(&value), 2);
569  return 2;
570  }
571  else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
572  uint32_t value = htobe32(static_cast<uint32_t>(varNumber));
573  os.write(reinterpret_cast<const char*>(&value), 4);
574  return 4;
575  }
576  else {
577  uint64_t value = htobe64(varNumber);
578  os.write(reinterpret_cast<const char*>(&value), 8);
579  return 8;
580  }
581 }
582 
583 
584 } // namespace tlv
585 } // namespace ndn
586 
587 #endif // NDN_ENCODING_TLV_HPP
Represent a SHA256-with-RSA signature.
Copyright (c) 2011-2015 Regents of the University of California.
Error(const std::string &what)
Definition: tlv.hpp:54
indicates a producer generated NACK
Definition: tlv.hpp:135
Represent a SHA256 digest.
STL namespace.
represents an Interest packet
Definition: interest.hpp:45
bool readType(InputIterator &begin, const InputIterator &end, uint32_t &type)
Read TLV Type.
Definition: tlv.hpp:288
size_t sizeOfNonNegativeInteger(uint64_t varNumber)
Get number of bytes necessary to hold value of nonNegativeInteger.
Definition: tlv.hpp:542
size_t writeVarNumber(std::ostream &os, uint64_t varNumber)
Write VAR-NUMBER to the specified stream.
Definition: tlv.hpp:405
bool readVarNumber(InputIterator &begin, const InputIterator &end, uint64_t &number)
Read VAR-NUMBER in NDN-TLV encoding.
Definition: tlv.hpp:243
size_t writeNonNegativeInteger(std::ostream &os, uint64_t varNumber)
Write nonNegativeInteger to the specified stream.
Definition: tlv.hpp:560
represents a Sha256WithEcdsa signature.
An MetaInfo holds the meta info which is signed inside the data packet.
Definition: meta-info.hpp:56
Abstraction implementing Interest selectors.
Definition: selectors.hpp:34
uint64_t readNonNegativeInteger(size_t size, InputIterator &begin, const InputIterator &end)
Read nonNegativeInteger in NDN-TLV encoding.
Definition: tlv.hpp:433
Name abstraction to represent an absolute name.
Definition: name.hpp:46
ContentTypeValue
indicates a possible value of ContentType field
Definition: tlv.hpp:119
indicates content is the actual data bits
Definition: tlv.hpp:122
SignatureTypeValue
Definition: tlv.hpp:95
indicates content is a public key
Definition: tlv.hpp:130
represents a Data packet
Definition: data.hpp:39
indicates content is another name which identifies actual data content
Definition: tlv.hpp:126
represents an error in TLV encoding or decoding
Definition: tlv.hpp:50
size_t sizeOfVarNumber(uint64_t varNumber)
Get number of bytes necessary to hold value of VAR-NUMBER.
Definition: tlv.hpp:388
Class to represent Exclude component in NDN interests.
Definition: exclude.hpp:38
const size_t MAX_NDN_PACKET_SIZE
practical limit of network layer packet size
Definition: tlv.hpp:39