All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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, Regents of the University of California
4  *
5  * BSD license, See the LICENSE file for more information
6  *
7  * Author: Alexander Afanasyev <[email protected]>
8  */
9 
10 #ifndef NDN_TLV_HPP
11 #define NDN_TLV_HPP
12 
13 #include <stdexcept>
14 #include <iterator>
15 #include "buffer.hpp"
16 #include "endian.hpp"
17 
18 namespace ndn {
19 
23 namespace Tlv {
24 
25 class Error : public std::runtime_error
26 {
27 public:
28  explicit
29  Error(const std::string& what)
30  : std::runtime_error(what)
31  {
32  }
33 };
34 
35 enum {
36  Interest = 5,
37  Data = 6,
38  Name = 7,
40  Selectors = 9,
41  Nonce = 10,
42  Scope = 11, // deprecated
47  Exclude = 16,
50  Any = 19,
51  MetaInfo = 20,
52  Content = 21,
59  KeyLocator = 28,
61 
64 };
65 
69 };
70 
71 enum ConentType {
75 };
76 
88 template<class InputIterator>
89 inline bool
90 readVarNumber(InputIterator& begin, const InputIterator& end, uint64_t& number);
91 
104 template<class InputIterator>
105 inline bool
106 readType(InputIterator& begin, const InputIterator& end, uint32_t& type);
107 
108 
116 template<class InputIterator>
117 inline uint64_t
118 readVarNumber(InputIterator& begin, const InputIterator& end);
119 
128 template<class InputIterator>
129 inline uint32_t
130 readType(InputIterator& begin, const InputIterator& end);
131 
135 inline size_t
136 sizeOfVarNumber(uint64_t varNumber);
137 
141 inline size_t
142 writeVarNumber(std::ostream& os, uint64_t varNumber);
143 
154 template<class InputIterator>
155 inline uint64_t
156 readNonNegativeInteger(size_t size, InputIterator& begin, const InputIterator& end);
157 
161 inline size_t
162 sizeOfNonNegativeInteger(uint64_t varNumber);
163 
167 inline size_t
168 writeNonNegativeInteger(std::ostream& os, uint64_t varNumber);
169 
173 
174 // Inline implementations
175 
179 
180 template<class InputIterator>
181 inline bool
182 readVarNumber(InputIterator& begin, const InputIterator& end, uint64_t& number)
183 {
184  if (begin == end)
185  return false;
186 
187  uint8_t firstOctet = *begin;
188  ++begin;
189  if (firstOctet < 253)
190  {
191  number = firstOctet;
192  }
193  else if (firstOctet == 253)
194  {
195  if (end - begin < 2)
196  return false;
197 
198  uint16_t value = *reinterpret_cast<const uint16_t*>(&*begin);
199  begin += 2;
200  number = be16toh(value);
201  }
202  else if (firstOctet == 254)
203  {
204  if (end - begin < 4)
205  return false;
206 
207  uint32_t value = *reinterpret_cast<const uint32_t*>(&*begin);
208  begin += 4;
209  number = be32toh(value);
210  }
211  else // if (firstOctet == 255)
212  {
213  if (end - begin < 8)
214  return false;
215 
216  uint64_t value = *reinterpret_cast<const uint64_t*>(&*begin);
217  begin += 8;
218 
219  number = be64toh(value);
220  }
221 
222  return true;
223 }
224 
225 template<class InputIterator>
226 inline bool
227 readType(InputIterator& begin, const InputIterator& end, uint32_t& type)
228 {
229  uint64_t number = 0;
230  bool isOk = readVarNumber(begin, end, number);
231  if (!isOk || number > std::numeric_limits<uint32_t>::max())
232  {
233  return false;
234  }
235 
236  type = static_cast<uint64_t>(number);
237  return true;
238 }
239 
240 template<class InputIterator>
241 inline uint64_t
242 readVarNumber(InputIterator& begin, const InputIterator& end)
243 {
244  if (begin == end)
245  throw Error("Empty buffer during TLV processing");
246 
247  uint64_t value;
248  bool isOk = readVarNumber(begin, end, value);
249  if (!isOk)
250  throw Error("Insufficient data during TLV processing");
251 
252  return value;
253 }
254 
255 template<>
256 inline bool
257 readVarNumber<std::istream_iterator<uint8_t> >(std::istream_iterator<uint8_t>& begin,
258  const std::istream_iterator<uint8_t>& end,
259  uint64_t& value)
260 {
261  if (begin == end)
262  return false;
263 
264  uint8_t firstOctet = *begin;
265  ++begin;
266  if (firstOctet < 253)
267  {
268  value = firstOctet;
269  }
270  else if (firstOctet == 253)
271  {
272  value = 0;
273  size_t count = 0;
274  for (; begin != end && count < 2; ++count)
275  {
276  value = ((value << 8) | *begin);
277  begin++;
278  }
279 
280  if (count != 2)
281  return false;
282  }
283  else if (firstOctet == 254)
284  {
285  value = 0;
286  size_t count = 0;
287  for (; begin != end && count < 4; ++count)
288  {
289  value = ((value << 8) | *begin);
290  begin++;
291  }
292 
293  if (count != 4)
294  return false;
295  }
296  else // if (firstOctet == 255)
297  {
298  value = 0;
299  size_t count = 0;
300  for (; begin != end && count < 8; ++count)
301  {
302  value = ((value << 8) | *begin);
303  begin++;
304  }
305 
306  if (count != 8)
307  return false;
308  }
309 
310  return true;
311 }
312 
313 template<class InputIterator>
314 inline uint32_t
315 readType(InputIterator& begin, const InputIterator& end)
316 {
317  uint64_t type = readVarNumber(begin, end);
318  if (type > std::numeric_limits<uint32_t>::max())
319  {
320  throw Error("TLV type code exceeds allowed maximum");
321  }
322 
323  return static_cast<uint32_t>(type);
324 }
325 
326 size_t
327 sizeOfVarNumber(uint64_t varNumber)
328 {
329  if (varNumber < 253) {
330  return 1;
331  }
332  else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
333  return 3;
334  }
335  else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
336  return 5;
337  }
338  else {
339  return 9;
340  }
341 }
342 
343 inline size_t
344 writeVarNumber(std::ostream& os, uint64_t varNumber)
345 {
346  if (varNumber < 253) {
347  os.put(static_cast<char>(varNumber));
348  return 1;
349  }
350  else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
351  os.put(static_cast<char>(253));
352  uint16_t value = htobe16(static_cast<uint16_t>(varNumber));
353  os.write(reinterpret_cast<const char*>(&value), 2);
354  return 3;
355  }
356  else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
357  os.put(static_cast<char>(254));
358  uint32_t value = htobe32(static_cast<uint32_t>(varNumber));
359  os.write(reinterpret_cast<const char*>(&value), 4);
360  return 5;
361  }
362  else {
363  os.put(static_cast<char>(255));
364  uint64_t value = htobe64(varNumber);
365  os.write(reinterpret_cast<const char*>(&value), 8);
366  return 9;
367  }
368 }
369 
370 template<class InputIterator>
371 inline uint64_t
372 readNonNegativeInteger(size_t size, InputIterator& begin, const InputIterator& end)
373 {
374  switch (size) {
375  case 1:
376  {
377  if (end - begin < 1)
378  throw Error("Insufficient data during TLV processing");
379 
380  uint8_t value = *begin;
381  begin++;
382  return value;
383  }
384  case 2:
385  {
386  if (end - begin < 2)
387  throw Error("Insufficient data during TLV processing");
388 
389  uint16_t value = *reinterpret_cast<const uint16_t*>(&*begin);
390  begin += 2;
391  return be16toh(value);
392  }
393  case 4:
394  {
395  if (end - begin < 4)
396  throw Error("Insufficient data during TLV processing");
397 
398  uint32_t value = *reinterpret_cast<const uint32_t*>(&*begin);
399  begin += 4;
400  return be32toh(value);
401  }
402  case 8:
403  {
404  if (end - begin < 8)
405  throw Error("Insufficient data during TLV processing");
406 
407  uint64_t value = *reinterpret_cast<const uint64_t*>(&*begin);
408  begin += 8;
409  return be64toh(value);
410  }
411  }
412  throw Error("Invalid length for nonNegativeInteger (only 1, 2, 4, and 8 are allowed)");
413 }
414 
415 template<>
416 inline uint64_t
417 readNonNegativeInteger<std::istream_iterator<uint8_t> >(size_t size,
418  std::istream_iterator<uint8_t>& begin,
419  const std::istream_iterator<uint8_t>& end)
420 {
421  switch (size) {
422  case 1:
423  {
424  if (begin == end)
425  throw Error("Insufficient data during TLV processing");
426 
427  uint64_t value = *begin;
428  begin++;
429  return value;
430  }
431  case 2:
432  {
433  uint64_t value = 0;
434  size_t count = 0;
435  for (; begin != end && count < 2; ++count)
436  {
437  value = ((value << 8) | *begin);
438  begin++;
439  }
440 
441  if (count != 2)
442  throw Error("Insufficient data during TLV processing");
443 
444  return value;
445  }
446  case 4:
447  {
448  uint64_t value = 0;
449  size_t count = 0;
450  for (; begin != end && count < 4; ++count)
451  {
452  value = ((value << 8) | *begin);
453  begin++;
454  }
455 
456  if (count != 4)
457  throw Error("Insufficient data during TLV processing");
458 
459  return value;
460  }
461  case 8:
462  {
463  uint64_t value = 0;
464  size_t count = 0;
465  for (; begin != end && count < 8; ++count)
466  {
467  value = ((value << 8) | *begin);
468  begin++;
469  }
470 
471  if (count != 8)
472  throw Error("Insufficient data during TLV processing");
473 
474  return value;
475  }
476  }
477  throw Error("Invalid length for nonNegativeInteger (only 1, 2, 4, and 8 are allowed)");
478 }
479 
480 inline size_t
481 sizeOfNonNegativeInteger(uint64_t varNumber)
482 {
483  if (varNumber < 253) {
484  return 1;
485  }
486  else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
487  return 2;
488  }
489  else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
490  return 4;
491  }
492  else {
493  return 8;
494  }
495 }
496 
497 
498 inline size_t
499 writeNonNegativeInteger(std::ostream& os, uint64_t varNumber)
500 {
501  if (varNumber < 253) {
502  os.put(static_cast<char>(varNumber));
503  return 1;
504  }
505  else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
506  uint16_t value = htobe16(static_cast<uint16_t>(varNumber));
507  os.write(reinterpret_cast<const char*>(&value), 2);
508  return 2;
509  }
510  else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
511  uint32_t value = htobe32(static_cast<uint32_t>(varNumber));
512  os.write(reinterpret_cast<const char*>(&value), 4);
513  return 4;
514  }
515  else {
516  uint64_t value = htobe64(varNumber);
517  os.write(reinterpret_cast<const char*>(&value), 8);
518  return 8;
519  }
520 }
521 
522 
523 } // namespace Tlv
524 
525 } // namespace ndn
526 
527 #endif // NDN_TLV_HPP
uint64_t readNonNegativeInteger(size_t size, InputIterator &begin, const InputIterator &end)
Read nonNegativeInteger in NDN-TLV encoding.
Definition: tlv.hpp:372
Representing of SHA256-with-RSA signature in a data packet.
size_t writeVarNumber(std::ostream &os, uint64_t varNumber)
Write VAR-NUMBER to the specified stream.
Definition: tlv.hpp:344
size_t sizeOfVarNumber(uint64_t varNumber)
Get number of bytes necessary to hold value of VAR-NUMBER.
Definition: tlv.hpp:327
bool readVarNumber(InputIterator &begin, const InputIterator &end, uint64_t &number)
Read VAR-NUMBER in NDN-TLV encoding.
Definition: tlv.hpp:182
size_t sizeOfNonNegativeInteger(uint64_t varNumber)
Get number of bytes necessary to hold value of nonNegativeInteger.
Definition: tlv.hpp:481
An Interest holds a Name and other fields for an interest.
Definition: interest.hpp:24
size_t writeNonNegativeInteger(std::ostream &os, uint64_t varNumber)
Write nonNegativeInteger to the specified stream.
Definition: tlv.hpp:499
Error(const std::string &what)
Definition: tlv.hpp:29
An MetaInfo holds the meta info which is signed inside the data packet.
Definition: meta-info.hpp:17
Abstraction implementing Interest selectors.
Definition: selectors.hpp:20
A Name holds an array of Name::Component and represents an NDN name.
Definition: name.hpp:26
SignatureType
Definition: tlv.hpp:66
bool readType(InputIterator &begin, const InputIterator &end, uint32_t &type)
Read TLV Type.
Definition: tlv.hpp:227
ConentType
Definition: tlv.hpp:71
Class to represent Exclude component in NDN interests.
Definition: exclude.hpp:21