encoding/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 
102 std::ostream&
103 operator<<(std::ostream& os, const SignatureTypeValue& signatureType);
104 
108 enum {
109  // SignatureInfo TLVs
111  NotBefore = 254,
112  NotAfter = 255,
113 
118 };
119 
126 
130 
134 
139 };
140 
152 template<class InputIterator>
153 inline bool
154 readVarNumber(InputIterator& begin, const InputIterator& end, uint64_t& number);
155 
168 template<class InputIterator>
169 inline bool
170 readType(InputIterator& begin, const InputIterator& end, uint32_t& type);
171 
172 
180 template<class InputIterator>
181 inline uint64_t
182 readVarNumber(InputIterator& begin, const InputIterator& end);
183 
192 template<class InputIterator>
193 inline uint32_t
194 readType(InputIterator& begin, const InputIterator& end);
195 
199 inline size_t
200 sizeOfVarNumber(uint64_t varNumber);
201 
205 inline size_t
206 writeVarNumber(std::ostream& os, uint64_t varNumber);
207 
218 template<class InputIterator>
219 inline uint64_t
220 readNonNegativeInteger(size_t size, InputIterator& begin, const InputIterator& end);
221 
225 inline size_t
226 sizeOfNonNegativeInteger(uint64_t varNumber);
227 
231 inline size_t
232 writeNonNegativeInteger(std::ostream& os, uint64_t varNumber);
233 
237 
238 // Inline implementations
239 
243 
244 template<class InputIterator>
245 inline bool
246 readVarNumber(InputIterator& begin, const InputIterator& end, uint64_t& number)
247 {
248  if (begin == end)
249  return false;
250 
251  uint8_t firstOctet = *begin;
252  ++begin;
253  if (firstOctet < 253)
254  {
255  number = firstOctet;
256  }
257  else if (firstOctet == 253)
258  {
259  if (end - begin < 2)
260  return false;
261 
262  uint16_t value = *reinterpret_cast<const uint16_t*>(&*begin);
263  begin += 2;
264  number = be16toh(value);
265  }
266  else if (firstOctet == 254)
267  {
268  if (end - begin < 4)
269  return false;
270 
271  uint32_t value = *reinterpret_cast<const uint32_t*>(&*begin);
272  begin += 4;
273  number = be32toh(value);
274  }
275  else // if (firstOctet == 255)
276  {
277  if (end - begin < 8)
278  return false;
279 
280  uint64_t value = *reinterpret_cast<const uint64_t*>(&*begin);
281  begin += 8;
282 
283  number = be64toh(value);
284  }
285 
286  return true;
287 }
288 
289 template<class InputIterator>
290 inline bool
291 readType(InputIterator& begin, const InputIterator& end, uint32_t& type)
292 {
293  uint64_t number = 0;
294  bool isOk = readVarNumber(begin, end, number);
295  if (!isOk || number > std::numeric_limits<uint32_t>::max())
296  {
297  return false;
298  }
299 
300  type = static_cast<uint32_t>(number);
301  return true;
302 }
303 
304 template<class InputIterator>
305 inline uint64_t
306 readVarNumber(InputIterator& begin, const InputIterator& end)
307 {
308  if (begin == end)
309  BOOST_THROW_EXCEPTION(Error("Empty buffer during TLV processing"));
310 
311  uint64_t value;
312  bool isOk = readVarNumber(begin, end, value);
313  if (!isOk)
314  BOOST_THROW_EXCEPTION(Error("Insufficient data during TLV processing"));
315 
316  return value;
317 }
318 
319 template<>
320 inline bool
321 readVarNumber<std::istream_iterator<uint8_t>>(std::istream_iterator<uint8_t>& begin,
322  const std::istream_iterator<uint8_t>& end,
323  uint64_t& value)
324 {
325  if (begin == end)
326  return false;
327 
328  uint8_t firstOctet = *begin;
329  ++begin;
330  if (firstOctet < 253)
331  {
332  value = firstOctet;
333  }
334  else if (firstOctet == 253)
335  {
336  value = 0;
337  size_t count = 0;
338  for (; begin != end && count < 2; ++count)
339  {
340  value = ((value << 8) | *begin);
341  begin++;
342  }
343 
344  if (count != 2)
345  return false;
346  }
347  else if (firstOctet == 254)
348  {
349  value = 0;
350  size_t count = 0;
351  for (; begin != end && count < 4; ++count)
352  {
353  value = ((value << 8) | *begin);
354  begin++;
355  }
356 
357  if (count != 4)
358  return false;
359  }
360  else // if (firstOctet == 255)
361  {
362  value = 0;
363  size_t count = 0;
364  for (; begin != end && count < 8; ++count)
365  {
366  value = ((value << 8) | *begin);
367  begin++;
368  }
369 
370  if (count != 8)
371  return false;
372  }
373 
374  return true;
375 }
376 
377 template<class InputIterator>
378 inline uint32_t
379 readType(InputIterator& begin, const InputIterator& end)
380 {
381  uint64_t type = readVarNumber(begin, end);
382  if (type > std::numeric_limits<uint32_t>::max())
383  {
384  BOOST_THROW_EXCEPTION(Error("TLV type code exceeds allowed maximum"));
385  }
386 
387  return static_cast<uint32_t>(type);
388 }
389 
390 size_t
391 sizeOfVarNumber(uint64_t varNumber)
392 {
393  if (varNumber < 253) {
394  return 1;
395  }
396  else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
397  return 3;
398  }
399  else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
400  return 5;
401  }
402  else {
403  return 9;
404  }
405 }
406 
407 inline size_t
408 writeVarNumber(std::ostream& os, uint64_t varNumber)
409 {
410  if (varNumber < 253) {
411  os.put(static_cast<char>(varNumber));
412  return 1;
413  }
414  else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
415  os.put(static_cast<char>(253));
416  uint16_t value = htobe16(static_cast<uint16_t>(varNumber));
417  os.write(reinterpret_cast<const char*>(&value), 2);
418  return 3;
419  }
420  else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
421  os.put(static_cast<char>(254));
422  uint32_t value = htobe32(static_cast<uint32_t>(varNumber));
423  os.write(reinterpret_cast<const char*>(&value), 4);
424  return 5;
425  }
426  else {
427  os.put(static_cast<char>(255));
428  uint64_t value = htobe64(varNumber);
429  os.write(reinterpret_cast<const char*>(&value), 8);
430  return 9;
431  }
432 }
433 
434 template<class InputIterator>
435 inline uint64_t
436 readNonNegativeInteger(size_t size, InputIterator& begin, const InputIterator& end)
437 {
438  switch (size) {
439  case 1:
440  {
441  if (end - begin < 1)
442  BOOST_THROW_EXCEPTION(Error("Insufficient data during TLV processing"));
443 
444  uint8_t value = *begin;
445  begin++;
446  return value;
447  }
448  case 2:
449  {
450  if (end - begin < 2)
451  BOOST_THROW_EXCEPTION(Error("Insufficient data during TLV processing"));
452 
453  uint16_t value = *reinterpret_cast<const uint16_t*>(&*begin);
454  begin += 2;
455  return be16toh(value);
456  }
457  case 4:
458  {
459  if (end - begin < 4)
460  BOOST_THROW_EXCEPTION(Error("Insufficient data during TLV processing"));
461 
462  uint32_t value = *reinterpret_cast<const uint32_t*>(&*begin);
463  begin += 4;
464  return be32toh(value);
465  }
466  case 8:
467  {
468  if (end - begin < 8)
469  BOOST_THROW_EXCEPTION(Error("Insufficient data during TLV processing"));
470 
471  uint64_t value = *reinterpret_cast<const uint64_t*>(&*begin);
472  begin += 8;
473  return be64toh(value);
474  }
475  }
476  BOOST_THROW_EXCEPTION(Error("Invalid length for nonNegativeInteger (only 1, 2, 4, and 8 are allowed)"));
477 }
478 
479 template<>
480 inline uint64_t
481 readNonNegativeInteger<std::istream_iterator<uint8_t> >(size_t size,
482  std::istream_iterator<uint8_t>& begin,
483  const std::istream_iterator<uint8_t>& end)
484 {
485  switch (size) {
486  case 1:
487  {
488  if (begin == end)
489  BOOST_THROW_EXCEPTION(Error("Insufficient data during TLV processing"));
490 
491  uint64_t value = *begin;
492  begin++;
493  return value;
494  }
495  case 2:
496  {
497  uint64_t value = 0;
498  size_t count = 0;
499  for (; begin != end && count < 2; ++count)
500  {
501  value = ((value << 8) | *begin);
502  begin++;
503  }
504 
505  if (count != 2)
506  BOOST_THROW_EXCEPTION(Error("Insufficient data during TLV processing"));
507 
508  return value;
509  }
510  case 4:
511  {
512  uint64_t value = 0;
513  size_t count = 0;
514  for (; begin != end && count < 4; ++count)
515  {
516  value = ((value << 8) | *begin);
517  begin++;
518  }
519 
520  if (count != 4)
521  BOOST_THROW_EXCEPTION(Error("Insufficient data during TLV processing"));
522 
523  return value;
524  }
525  case 8:
526  {
527  uint64_t value = 0;
528  size_t count = 0;
529  for (; begin != end && count < 8; ++count)
530  {
531  value = ((value << 8) | *begin);
532  begin++;
533  }
534 
535  if (count != 8)
536  BOOST_THROW_EXCEPTION(Error("Insufficient data during TLV processing"));
537 
538  return value;
539  }
540  }
541  BOOST_THROW_EXCEPTION(Error("Invalid length for nonNegativeInteger (only 1, 2, 4, and 8 are allowed)"));
542 }
543 
544 inline size_t
545 sizeOfNonNegativeInteger(uint64_t varNumber)
546 {
547  if (varNumber < 253) {
548  return 1;
549  }
550  else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
551  return 2;
552  }
553  else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
554  return 4;
555  }
556  else {
557  return 8;
558  }
559 }
560 
561 
562 inline size_t
563 writeNonNegativeInteger(std::ostream& os, uint64_t varNumber)
564 {
565  if (varNumber < 253) {
566  os.put(static_cast<char>(varNumber));
567  return 1;
568  }
569  else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
570  uint16_t value = htobe16(static_cast<uint16_t>(varNumber));
571  os.write(reinterpret_cast<const char*>(&value), 2);
572  return 2;
573  }
574  else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
575  uint32_t value = htobe32(static_cast<uint32_t>(varNumber));
576  os.write(reinterpret_cast<const char*>(&value), 4);
577  return 4;
578  }
579  else {
580  uint64_t value = htobe64(varNumber);
581  os.write(reinterpret_cast<const char*>(&value), 8);
582  return 8;
583  }
584 }
585 
586 
587 } // namespace tlv
588 } // namespace ndn
589 
590 #endif // NDN_ENCODING_TLV_HPP
Represent a SHA256-with-RSA signature.
Copyright (c) 2013-2016 Regents of the University of California.
Definition: common.hpp:74
Error(const std::string &what)
indicates a producer generated NACK
Represent a SHA256 digest.
STL namespace.
represents an Interest packet
Definition: interest.hpp:42
bool readType(InputIterator &begin, const InputIterator &end, uint32_t &type)
Read TLV Type.
size_t sizeOfNonNegativeInteger(uint64_t varNumber)
Get number of bytes necessary to hold value of nonNegativeInteger.
size_t writeVarNumber(std::ostream &os, uint64_t varNumber)
Write VAR-NUMBER to the specified stream.
bool readVarNumber(InputIterator &begin, const InputIterator &end, uint64_t &number)
Read VAR-NUMBER in NDN-TLV encoding.
size_t writeNonNegativeInteger(std::ostream &os, uint64_t varNumber)
Write nonNegativeInteger to the specified stream.
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.
Name abstraction to represent an absolute name.
Definition: name.hpp:46
ContentTypeValue
indicates a possible value of ContentType field
indicates content is the actual data bits
indicates content is a public key
represents a Data packet
Definition: data.hpp:37
indicates content is another name which identifies actual data content
std::ostream & operator<<(std::ostream &os, const SignatureTypeValue &signatureType)
Definition: tlv.cpp:28
represents an error in TLV encoding or decoding
size_t sizeOfVarNumber(uint64_t varNumber)
Get number of bytes necessary to hold value of VAR-NUMBER.
Represents Exclude selector in NDN Interest.
Definition: exclude.hpp:38
const size_t MAX_NDN_PACKET_SIZE
practical limit of network layer packet size