interest.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2013-2024 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 #include "ndn-cxx/interest.hpp"
23 #include "ndn-cxx/data.hpp"
28 #include "ndn-cxx/util/random.hpp"
29 
30 #include <boost/range/adaptor/reversed.hpp>
31 
32 #include <algorithm>
33 #include <cstring>
34 #include <sstream>
35 
36 namespace ndn {
37 
39 {
40  setName(name);
41  setInterestLifetime(lifetime);
42 }
43 
45 {
46  wireDecode(wire);
47 }
48 
49 // ---- encode and decode ----
50 
51 template<encoding::Tag TAG>
52 size_t
54 {
55  // Interest = INTEREST-TYPE TLV-LENGTH
56  // Name
57  // [CanBePrefix]
58  // [MustBeFresh]
59  // [ForwardingHint]
60  // [Nonce]
61  // [InterestLifetime]
62  // [HopLimit]
63  // [ApplicationParameters [InterestSignature]]
64  // (elements are encoded in reverse order)
65 
66  // sanity check of ApplicationParameters and ParametersSha256DigestComponent
67  ssize_t digestIndex = findParametersDigestComponent(getName());
68  BOOST_ASSERT(digestIndex != -2); // guaranteed by the checks in setName() and wireDecode()
69  if (digestIndex == -1) {
71  NDN_THROW(Error("Interest with parameters must have a ParametersSha256DigestComponent"));
72  }
73  else if (!hasApplicationParameters()) {
74  NDN_THROW(Error("Interest without parameters must not have a ParametersSha256DigestComponent"));
75  }
76 
77  size_t totalLength = 0;
78 
79  // ApplicationParameters and following elements (in reverse order)
80  for (const auto& block : m_parameters | boost::adaptors::reversed) {
81  totalLength += prependBlock(encoder, block);
82  }
83 
84  // HopLimit
85  if (m_hopLimit) {
86  totalLength += prependBinaryBlock(encoder, tlv::HopLimit, {*m_hopLimit});
87  }
88 
89  // InterestLifetime
90  if (m_interestLifetime != DEFAULT_INTEREST_LIFETIME.count()) {
91  totalLength += prependNonNegativeIntegerBlock(encoder, tlv::InterestLifetime, m_interestLifetime);
92  }
93 
94  // Nonce
95  getNonce(); // if nonce was unset, this generates a fresh nonce
96  BOOST_ASSERT(hasNonce());
97  totalLength += prependBinaryBlock(encoder, tlv::Nonce, *m_nonce);
98 
99  // ForwardingHint
100  if (!m_forwardingHint.empty()) {
101  totalLength += prependNestedBlock(encoder, tlv::ForwardingHint,
102  m_forwardingHint.begin(), m_forwardingHint.end());
103  }
104 
105  // MustBeFresh
106  if (getMustBeFresh()) {
107  totalLength += prependEmptyBlock(encoder, tlv::MustBeFresh);
108  }
109 
110  // CanBePrefix
111  if (getCanBePrefix()) {
112  totalLength += prependEmptyBlock(encoder, tlv::CanBePrefix);
113  }
114 
115  // Name
116  totalLength += getName().wireEncode(encoder);
117 
118  totalLength += encoder.prependVarNumber(totalLength);
119  totalLength += encoder.prependVarNumber(tlv::Interest);
120  return totalLength;
121 }
122 
124 
125 const Block&
127 {
128  if (m_wire.hasWire())
129  return m_wire;
130 
131  EncodingEstimator estimator;
132  size_t estimatedSize = wireEncode(estimator);
133 
134  EncodingBuffer encoder(estimatedSize, 0);
135  wireEncode(encoder);
136 
137  const_cast<Interest*>(this)->wireDecode(encoder.block());
138  return m_wire;
139 }
140 
141 void
143 {
144  if (wire.type() != tlv::Interest) {
145  NDN_THROW(Error("Interest", wire.type()));
146  }
147  m_wire = wire;
148  m_wire.parse();
149 
150  // Interest = INTEREST-TYPE TLV-LENGTH
151  // Name
152  // [CanBePrefix]
153  // [MustBeFresh]
154  // [ForwardingHint]
155  // [Nonce]
156  // [InterestLifetime]
157  // [HopLimit]
158  // [ApplicationParameters [InterestSignature]]
159 
160  auto element = m_wire.elements_begin();
161  if (element == m_wire.elements_end() || element->type() != tlv::Name) {
162  NDN_THROW(Error("Name element is missing or out of order"));
163  }
164  // decode into a temporary object until we determine that the name is valid, in order
165  // to maintain class invariants and thus provide a basic form of exception safety
166  Name tempName(*element);
167  if (tempName.empty()) {
168  NDN_THROW(Error("Name has zero name components"));
169  }
170  ssize_t digestIndex = findParametersDigestComponent(tempName);
171  if (digestIndex == -2) {
172  NDN_THROW(Error("Name has more than one ParametersSha256DigestComponent"));
173  }
174  m_name = std::move(tempName);
175 
176  m_canBePrefix = m_mustBeFresh = false;
177  m_forwardingHint.clear();
178  m_nonce.reset();
179  m_interestLifetime = DEFAULT_INTEREST_LIFETIME.count();
180  m_hopLimit.reset();
181  m_parameters.clear();
182 
183  int lastElement = 1; // last recognized element index, in spec order
184  for (++element; element != m_wire.elements_end(); ++element) {
185  switch (element->type()) {
186  case tlv::CanBePrefix: {
187  if (lastElement >= 2) {
188  NDN_THROW(Error("CanBePrefix element is out of order"));
189  }
190  if (element->value_size() != 0) {
191  NDN_THROW(Error("CanBePrefix element has non-zero TLV-LENGTH"));
192  }
193  m_canBePrefix = true;
194  lastElement = 2;
195  break;
196  }
197  case tlv::MustBeFresh: {
198  if (lastElement >= 3) {
199  NDN_THROW(Error("MustBeFresh element is out of order"));
200  }
201  if (element->value_size() != 0) {
202  NDN_THROW(Error("MustBeFresh element has non-zero TLV-LENGTH"));
203  }
204  m_mustBeFresh = true;
205  lastElement = 3;
206  break;
207  }
208  case tlv::ForwardingHint: {
209  if (lastElement >= 4) {
210  NDN_THROW(Error("ForwardingHint element is out of order"));
211  }
212  // Current format:
213  // ForwardingHint = FORWARDING-HINT-TYPE TLV-LENGTH 1*Name
214  // Previous format, partially supported for backward compatibility:
215  // ForwardingHint = FORWARDING-HINT-TYPE TLV-LENGTH 1*Delegation
216  // Delegation = DELEGATION-TYPE TLV-LENGTH Preference Name
217  element->parse();
218  for (const auto& del : element->elements()) {
219  switch (del.type()) {
220  case tlv::Name:
221  try {
222  m_forwardingHint.emplace_back(del);
223  }
224  catch (const tlv::Error&) {
225  NDN_THROW_NESTED(Error("Invalid Name in ForwardingHint"));
226  }
227  break;
228  case 31: // Delegation
229  // old ForwardingHint format, try to parse the nested Name for compatibility
230  try {
231  del.parse();
232  m_forwardingHint.emplace_back(del.get(tlv::Name));
233  }
234  catch (const tlv::Error&) {
235  NDN_THROW_NESTED(Error("Invalid Name in ForwardingHint.Delegation"));
236  }
237  break;
238  default:
239  if (tlv::isCriticalType(del.type())) {
240  NDN_THROW(Error("Unexpected TLV-TYPE " + to_string(del.type()) + " while decoding ForwardingHint"));
241  }
242  break;
243  }
244  }
245  lastElement = 4;
246  break;
247  }
248  case tlv::Nonce: {
249  if (lastElement >= 5) {
250  NDN_THROW(Error("Nonce element is out of order"));
251  }
252  if (element->value_size() != Nonce().size()) {
253  NDN_THROW(Error("Nonce element is malformed"));
254  }
255  m_nonce.emplace();
256  std::memcpy(m_nonce->data(), element->value(), m_nonce->size());
257  lastElement = 5;
258  break;
259  }
260  case tlv::InterestLifetime: {
261  if (lastElement >= 6) {
262  NDN_THROW(Error("InterestLifetime element is out of order"));
263  }
264  m_interestLifetime = readNonNegativeInteger(*element);
265  lastElement = 6;
266  break;
267  }
268  case tlv::HopLimit: {
269  if (lastElement >= 7) {
270  break; // HopLimit is non-critical, ignore out-of-order appearance
271  }
272  if (element->value_size() != 1) {
273  NDN_THROW(Error("HopLimit element is malformed"));
274  }
275  m_hopLimit = *element->value();
276  lastElement = 7;
277  break;
278  }
280  if (lastElement >= 8) {
281  break; // ApplicationParameters is non-critical, ignore out-of-order appearance
282  }
283  BOOST_ASSERT(!hasApplicationParameters());
284  m_parameters.push_back(*element);
285  lastElement = 8;
286  break;
287  }
288  default: { // unrecognized element
289  // if the TLV-TYPE is critical, abort decoding
290  if (tlv::isCriticalType(element->type())) {
291  NDN_THROW(Error("Unrecognized element of critical type " + to_string(element->type())));
292  }
293  // if we already encountered ApplicationParameters, store this element as parameter
294  if (hasApplicationParameters()) {
295  m_parameters.push_back(*element);
296  }
297  // otherwise, ignore it
298  break;
299  }
300  }
301  }
302 
303  if (s_autoCheckParametersDigest && !isParametersDigestValid()) {
304  NDN_THROW(Error("ParametersSha256DigestComponent does not match the SHA-256 of Interest parameters"));
305  }
306 }
307 
308 std::string
310 {
311  std::ostringstream os;
312  os << *this;
313  return os.str();
314 }
315 
316 // ---- matching ----
317 
318 bool
319 Interest::matchesData(const Data& data) const
320 {
321  const Name& dataName = data.getName();
322  size_t fullNameLength = dataName.size() + 1;
323 
324  // check Name and CanBePrefix
325  if (m_name.size() == fullNameLength) {
326  if (m_name.get(-1).isImplicitSha256Digest()) {
327  return m_name == data.getFullName();
328  }
329  else {
330  // the Interest name has the same length as the Data full name, but the last
331  // component is not a digest, so there is no possibility of matching
332  return false;
333  }
334  }
335  else if (m_canBePrefix) {
336  return m_name.isPrefixOf(dataName);
337  }
338  else {
339  return m_name == dataName;
340  }
341 }
342 
343 bool
345 {
346  return getName() == other.getName() &&
347  getCanBePrefix() == other.getCanBePrefix() &&
348  getMustBeFresh() == other.getMustBeFresh();
349 }
350 
351 // ---- field accessors and modifiers ----
352 
353 Interest&
355 {
356  ssize_t digestIndex = findParametersDigestComponent(name);
357  if (digestIndex == -2) {
358  NDN_THROW(std::invalid_argument("Name cannot have more than one ParametersSha256DigestComponent"));
359  }
360 
361  if (name != m_name) {
362  m_name = name;
363  if (hasApplicationParameters()) {
364  addOrReplaceParametersDigestComponent();
365  }
366  m_wire.reset();
367  }
368  return *this;
369 }
370 
371 Interest&
372 Interest::setCanBePrefix(bool canBePrefix)
373 {
374  if (canBePrefix != m_canBePrefix) {
375  m_canBePrefix = canBePrefix;
376  m_wire.reset();
377  }
378  return *this;
379 }
380 
381 Interest&
382 Interest::setMustBeFresh(bool mustBeFresh)
383 {
384  if (mustBeFresh != m_mustBeFresh) {
385  m_mustBeFresh = mustBeFresh;
386  m_wire.reset();
387  }
388  return *this;
389 }
390 
391 Interest&
392 Interest::setForwardingHint(std::vector<Name> value)
393 {
394  m_forwardingHint = std::move(value);
395  m_wire.reset();
396  return *this;
397 }
398 
399 [[nodiscard]] static auto
400 generateNonce()
401 {
402  uint32_t r = random::generateWord32();
403  Interest::Nonce n;
404  std::memcpy(n.data(), &r, sizeof(r));
405  return n;
406 }
407 
410 {
411  if (!hasNonce()) {
412  m_nonce = generateNonce();
413  m_wire.reset();
414  }
415  return *m_nonce;
416 }
417 
418 Interest&
419 Interest::setNonce(std::optional<Interest::Nonce> nonce)
420 {
421  if (nonce != m_nonce) {
422  m_nonce = nonce;
423  m_wire.reset();
424  }
425  return *this;
426 }
427 
428 void
430 {
431  if (!hasNonce())
432  return;
433 
434  auto oldNonce = *m_nonce;
435  while (m_nonce == oldNonce)
436  m_nonce = generateNonce();
437 
438  m_wire.reset();
439 }
440 
443 {
444  if (m_interestLifetime > static_cast<uint64_t>(time::milliseconds::max().count())) {
445  return time::milliseconds::max();
446  }
447  return time::milliseconds(m_interestLifetime);
448 }
449 
450 Interest&
452 {
453  if (lifetime < 0_ms) {
454  NDN_THROW(std::invalid_argument("InterestLifetime must be >= 0"));
455  }
456 
457  uint64_t lifetimeMillis = static_cast<uint64_t>(lifetime.count());
458  if (lifetimeMillis != m_interestLifetime) {
459  m_interestLifetime = lifetimeMillis;
460  m_wire.reset();
461  }
462  return *this;
463 }
464 
465 Interest&
466 Interest::setHopLimit(std::optional<uint8_t> hopLimit)
467 {
468  if (hopLimit != m_hopLimit) {
469  m_hopLimit = hopLimit;
470  m_wire.reset();
471  }
472  return *this;
473 }
474 
475 Interest&
476 Interest::setApplicationParametersInternal(Block parameters)
477 {
478  parameters.encode(); // ensure we have wire encoding needed by computeParametersDigest()
479  if (m_parameters.empty()) {
480  m_parameters.push_back(std::move(parameters));
481  }
482  else {
483  BOOST_ASSERT(m_parameters[0].type() == tlv::ApplicationParameters);
484  m_parameters[0] = std::move(parameters);
485  }
486 
487  addOrReplaceParametersDigestComponent();
488  m_wire.reset();
489  return *this;
490 }
491 
492 Interest&
494 {
495  if (!parameters.isValid()) {
496  NDN_THROW(std::invalid_argument("ApplicationParameters block must be valid"));
497  }
498 
499  if (parameters.type() == tlv::ApplicationParameters) {
500  return setApplicationParametersInternal(parameters);
501  }
502  else {
503  return setApplicationParametersInternal({tlv::ApplicationParameters, parameters});
504  }
505 }
506 
507 Interest&
508 Interest::setApplicationParameters(span<const uint8_t> value)
509 {
510  return setApplicationParametersInternal(makeBinaryBlock(tlv::ApplicationParameters, value));
511 }
512 
513 Interest&
514 Interest::setApplicationParameters(std::string_view value)
515 {
516  return setApplicationParametersInternal(makeStringBlock(tlv::ApplicationParameters, value));
517 }
518 
519 Interest&
521 {
522  if (!value) {
523  NDN_THROW(std::invalid_argument("ApplicationParameters buffer cannot be null"));
524  }
525 
526  return setApplicationParametersInternal({tlv::ApplicationParameters, std::move(value)});
527 }
528 
529 Interest&
531 {
532  m_parameters.clear();
533  ssize_t digestIndex = findParametersDigestComponent(getName());
534  if (digestIndex >= 0) {
535  m_name.erase(digestIndex);
536  }
537  m_wire.reset();
538  return *this;
539 }
540 
541 bool
542 Interest::isSigned() const noexcept
543 {
544  return m_parameters.size() >= 3 &&
545  getSignatureInfo().has_value() &&
547  !m_name.empty() &&
548  m_name[-1].type() == tlv::ParametersSha256DigestComponent;
549 }
550 
551 std::optional<SignatureInfo>
553 {
554  auto blockIt = findFirstParameter(tlv::InterestSignatureInfo);
555  if (blockIt != m_parameters.end()) {
556  return std::make_optional<SignatureInfo>(*blockIt, SignatureInfo::Type::Interest);
557  }
558  return std::nullopt;
559 }
560 
561 Interest&
563 {
564  // Prepend empty ApplicationParameters element if none present
565  if (m_parameters.empty()) {
566  m_parameters.push_back(makeEmptyBlock(tlv::ApplicationParameters));
567  }
568 
569  // Find first existing InterestSignatureInfo (if any)
570  auto infoIt = std::find_if(m_parameters.begin(), m_parameters.end(), [] (const Block& block) {
571  return block.type() == tlv::InterestSignatureInfo;
572  });
573 
574  Block encodedInfo = info.wireEncode(SignatureInfo::Type::Interest);
575  if (infoIt != m_parameters.end()) {
576  if (*infoIt == encodedInfo) {
577  // New InterestSignatureInfo is the same as the old InterestSignatureInfo
578  return *this;
579  }
580 
581  // Replace existing InterestSignatureInfo
582  *infoIt = std::move(encodedInfo);
583  }
584  else {
585  // Place before first InterestSignatureValue element (if any), else at end
586  auto valueIt = findFirstParameter(tlv::InterestSignatureValue);
587  m_parameters.insert(valueIt, std::move(encodedInfo));
588  }
589 
590  addOrReplaceParametersDigestComponent();
591  m_wire.reset();
592  return *this;
593 }
594 
595 Block
597 {
598  auto blockIt = findFirstParameter(tlv::InterestSignatureValue);
599  if (blockIt != m_parameters.end()) {
600  return *blockIt;
601  }
602  return {};
603 }
604 
605 Interest&
606 Interest::setSignatureValueInternal(Block sigValue)
607 {
608  // Ensure presence of InterestSignatureInfo
609  auto infoIt = findFirstParameter(tlv::InterestSignatureInfo);
610  if (infoIt == m_parameters.end()) {
611  NDN_THROW(Error("InterestSignatureInfo must be present to set InterestSignatureValue"));
612  }
613 
614  auto valueIt = std::find_if(m_parameters.begin(), m_parameters.end(), [] (const Block& block) {
615  return block.type() == tlv::InterestSignatureValue;
616  });
617 
618  if (valueIt != m_parameters.end()) {
619  if (*valueIt == sigValue) {
620  // New InterestSignatureValue is the same as the old InterestSignatureValue
621  return *this;
622  }
623 
624  // Replace existing InterestSignatureValue
625  *valueIt = std::move(sigValue);
626  }
627  else {
628  // Place after first InterestSignatureInfo element
629  valueIt = m_parameters.insert(std::next(infoIt), std::move(sigValue));
630  }
631 
632  // computeParametersDigest needs encoded InterestSignatureValue
633  valueIt->encode();
634 
635  addOrReplaceParametersDigestComponent();
636  m_wire.reset();
637  return *this;
638 }
639 
640 Interest&
641 Interest::setSignatureValue(span<const uint8_t> value)
642 {
643  return setSignatureValueInternal(makeBinaryBlock(tlv::InterestSignatureValue, value));
644 }
645 
646 Interest&
648 {
649  if (!value) {
650  NDN_THROW(std::invalid_argument("InterestSignatureValue buffer cannot be null"));
651  }
652 
653  return setSignatureValueInternal({tlv::InterestSignatureValue, std::move(value)});
654 }
655 
656 InputBuffers
658 {
659  InputBuffers bufs;
660  bufs.reserve(2); // For Name range and parameters range
661 
662  wireEncode();
663 
664  // Get Interest name minus any ParametersSha256DigestComponent
665  // Name is guaranteed to be non-empty if wireEncode() does not throw
666  BOOST_ASSERT(!m_name.empty());
667  if (m_name[-1].type() != tlv::ParametersSha256DigestComponent) {
668  NDN_THROW(Error("Interest Name must end with a ParametersSha256DigestComponent"));
669  }
670 
671  bufs.emplace_back(m_name[0].data(), m_name[-1].data());
672 
673  // Ensure InterestSignatureInfo element is present
674  auto sigInfoIt = findFirstParameter(tlv::InterestSignatureInfo);
675  if (sigInfoIt == m_parameters.end()) {
676  NDN_THROW(Error("Interest missing InterestSignatureInfo"));
677  }
678 
679  // Get range from ApplicationParameters to InterestSignatureValue
680  // or end of parameters (whichever is first)
681  BOOST_ASSERT(!m_parameters.empty() && m_parameters.begin()->type() == tlv::ApplicationParameters);
682  auto lastSignedIt = std::prev(findFirstParameter(tlv::InterestSignatureValue));
683  // Note: we assume that both iterators point to the same underlying buffer
684  bufs.emplace_back(m_parameters.front().begin(), lastSignedIt->end());
685 
686  return bufs;
687 }
688 
689 // ---- ParametersSha256DigestComponent support ----
690 
691 bool
693 {
694  ssize_t digestIndex = findParametersDigestComponent(getName());
695  if (digestIndex == -1) {
696  return !hasApplicationParameters();
697  }
698  // cannot be -2 because of the checks in setName() and wireDecode()
699  BOOST_ASSERT(digestIndex >= 0);
700 
701  if (!hasApplicationParameters()) {
702  return false;
703  }
704 
705  const auto& digestComponent = getName()[digestIndex];
706  auto digest = computeParametersDigest();
707 
708  return std::equal(digestComponent.value_begin(), digestComponent.value_end(),
709  digest->begin(), digest->end());
710 }
711 
712 shared_ptr<Buffer>
713 Interest::computeParametersDigest() const
714 {
715  using namespace security::transform;
716 
717  StepSource in;
718  OBufferStream out;
720 
721  for (const auto& block : m_parameters) {
722  in.write(block);
723  }
724  in.end();
725 
726  return out.buf();
727 }
728 
729 void
730 Interest::addOrReplaceParametersDigestComponent()
731 {
732  BOOST_ASSERT(hasApplicationParameters());
733 
734  ssize_t digestIndex = findParametersDigestComponent(getName());
735  name::Component digestComponent(tlv::ParametersSha256DigestComponent, computeParametersDigest());
736 
737  if (digestIndex == -1) {
738  // no existing digest components, append one
739  m_name.append(std::move(digestComponent));
740  }
741  else {
742  // cannot be -2 because of the checks in setName() and wireDecode()
743  BOOST_ASSERT(digestIndex >= 0);
744  // replace the existing digest component
745  m_name.set(digestIndex, std::move(digestComponent));
746  }
747 }
748 
749 ssize_t
750 Interest::findParametersDigestComponent(const Name& name)
751 {
752  ssize_t pos = -1;
753  for (ssize_t i = 0; i < static_cast<ssize_t>(name.size()); i++) {
754  if (name[i].isParametersSha256Digest()) {
755  if (pos != -1)
756  return -2;
757  pos = i;
758  }
759  }
760  return pos;
761 }
762 
763 std::vector<Block>::const_iterator
764 Interest::findFirstParameter(uint32_t type) const
765 {
766  return std::find_if(m_parameters.begin(), m_parameters.end(), [type] (const Block& block) {
767  return block.type() == type;
768  });
769 }
770 
771 // ---- operators ----
772 
773 std::ostream&
774 operator<<(std::ostream& os, const Interest& interest)
775 {
776  os << interest.getName();
777 
778  char delim = '?';
779  auto printOne = [&] (const auto&... args) {
780  os << delim;
781  delim = '&';
782  (os << ... << args);
783  };
784 
785  if (interest.getCanBePrefix()) {
786  printOne("CanBePrefix");
787  }
788  if (interest.getMustBeFresh()) {
789  printOne("MustBeFresh");
790  }
791  if (interest.hasNonce()) {
792  printOne("Nonce=", interest.getNonce());
793  }
795  printOne("Lifetime=", interest.getInterestLifetime().count());
796  }
797  if (interest.getHopLimit()) {
798  printOne("HopLimit=", static_cast<unsigned>(*interest.getHopLimit()));
799  }
800 
801  return os;
802 }
803 
804 } // namespace ndn
Represents a TLV element of the NDN packet format.
Definition: block.hpp:45
element_const_iterator elements_begin() const noexcept
Equivalent to elements().begin().
Definition: block.hpp:433
element_const_iterator elements_end() const noexcept
Equivalent to elements().end().
Definition: block.hpp:442
bool hasWire() const noexcept
Check if the Block contains a fully encoded wire representation.
Definition: block.hpp:205
bool isValid() const noexcept
Check if the Block is valid.
Definition: block.hpp:193
void encode()
Encode sub-elements into TLV-VALUE.
Definition: block.cpp:353
uint32_t type() const noexcept
Return the TLV-TYPE of the Block.
Definition: block.hpp:275
void reset() noexcept
Reset the Block to a default-constructed state.
Definition: block.cpp:293
void parse() const
Parse TLV-VALUE into sub-elements.
Definition: block.cpp:326
Represents a Data packet.
Definition: data.hpp:39
const Name & getFullName() const
Get the full name (including implicit digest).
Definition: data.cpp:200
const Name & getName() const noexcept
Get the Data name.
Definition: data.hpp:137
Represents an Interest packet.
Definition: interest.hpp:50
void wireDecode(const Block &wire)
Decode from wire.
Definition: interest.cpp:142
Interest & setHopLimit(std::optional< uint8_t > hopLimit)
Set the Interest's hop limit.
Definition: interest.cpp:466
std::optional< SignatureInfo > getSignatureInfo() const
Get the InterestSignatureInfo element.
Definition: interest.cpp:552
Interest & setCanBePrefix(bool canBePrefix)
Add or remove CanBePrefix element.
Definition: interest.cpp:372
Interest & setNonce(std::optional< Nonce > nonce)
Set the Interest's nonce.
Definition: interest.cpp:419
const Name & getName() const noexcept
Get the Interest name.
Definition: interest.hpp:179
Nonce getNonce() const
Get nonce value.
Definition: interest.cpp:409
Interest & setSignatureValue(span< const uint8_t > value)
Set InterestSignatureValue by copying from a contiguous sequence of bytes.
Definition: interest.cpp:641
bool matchesInterest(const Interest &other) const
Check if this Interest matches other.
Definition: interest.cpp:344
bool hasApplicationParameters() const noexcept
Return whether this Interest has any ApplicationParameters element.
Definition: interest.hpp:312
time::milliseconds getInterestLifetime() const noexcept
Get the Interest's lifetime.
Definition: interest.cpp:442
bool matchesData(const Data &data) const
Check if this Interest can be satisfied by data.
Definition: interest.cpp:319
Interest & setMustBeFresh(bool mustBeFresh)
Add or remove MustBeFresh element.
Definition: interest.cpp:382
bool getMustBeFresh() const noexcept
Check whether the MustBeFresh element is present.
Definition: interest.hpp:211
Block getSignatureValue() const
Get the InterestSignatureValue element.
Definition: interest.cpp:596
InputBuffers extractSignedRanges() const
Extract ranges of Interest covered by the signature.
Definition: interest.cpp:657
bool hasNonce() const noexcept
Check if the Nonce element is present.
Definition: interest.hpp:244
std::optional< uint8_t > getHopLimit() const noexcept
Get the Interest's hop limit.
Definition: interest.hpp:295
bool getCanBePrefix() const noexcept
Check whether the CanBePrefix element is present.
Definition: interest.hpp:195
void refreshNonce()
Change nonce value.
Definition: interest.cpp:429
bool isSigned() const noexcept
Return whether the Interest is signed.
Definition: interest.cpp:542
Interest & unsetApplicationParameters()
Remove the ApplicationParameters element from this Interest.
Definition: interest.cpp:530
bool isParametersDigestValid() const
Check if the ParametersSha256DigestComponent in the name is valid.
Definition: interest.cpp:692
Interest & setName(const Name &name)
Set the Interest name.
Definition: interest.cpp:354
Interest & setSignatureInfo(const SignatureInfo &info)
Set the InterestSignatureInfo element.
Definition: interest.cpp:562
Interest & setApplicationParameters(const Block &block)
Set ApplicationParameters from a Block.
Definition: interest.cpp:493
Interest & setForwardingHint(std::vector< Name > value)
Set the ForwardingHint delegations (names).
Definition: interest.cpp:392
std::string toUri() const
Return a URI-like string that represents the Interest.
Definition: interest.cpp:309
const Block & wireEncode() const
Encode into a Block.
Definition: interest.cpp:126
Interest(const Name &name={}, time::milliseconds lifetime=DEFAULT_INTEREST_LIFETIME)
Construct an Interest with given name and lifetime.
Definition: interest.cpp:38
Interest & setInterestLifetime(time::milliseconds lifetime)
Set the Interest's lifetime.
Definition: interest.cpp:451
Represents an absolute name.
Definition: name.hpp:45
Name & set(ssize_t i, const Component &component)
Replace the component at the specified index.
Definition: name.cpp:181
size_t size() const noexcept
Returns the number of components.
Definition: name.hpp:180
bool empty() const noexcept
Checks if the name is empty, i.e., has no components.
Definition: name.hpp:171
Name & append(const Component &component)
Append a name component.
Definition: name.hpp:308
size_t wireEncode(EncodingImpl< TAG > &encoder) const
Prepend wire encoding to encoder.
Definition: name.cpp:92
void erase(ssize_t i)
Erase the component at the specified index.
Definition: name.cpp:245
bool isPrefixOf(const Name &other) const noexcept
Check if this name is a prefix of another name.
Definition: name.cpp:275
const Component & get(ssize_t i) const noexcept
Returns an immutable reference to the component at the specified index.
Definition: name.hpp:192
An output stream that writes to a Buffer.
std::shared_ptr< Buffer > buf()
Return a shared pointer to the underlying buffer.
Represents a SignatureInfo or InterestSignatureInfo TLV element.
bool isImplicitSha256Digest() const noexcept
Check if the component is an ImplicitSha256DigestComponent.
Represents an error in TLV encoding or decoding.
Definition: tlv.hpp:54
#define NDN_CXX_DEFINE_WIRE_ENCODE_INSTANTIATIONS(ClassName)
#define NDN_THROW_NESTED(e)
Definition: exception.hpp:65
#define NDN_THROW(e)
Definition: exception.hpp:56
EncodingImpl< EstimatorTag > EncodingEstimator
size_t prependNestedBlock(EncodingImpl< TAG > &encoder, uint32_t type, const U &value)
Prepend a TLV element containing a nested TLV element.
Block makeStringBlock(uint32_t type, std::string_view value)
Create a TLV block containing a string.
uint64_t readNonNegativeInteger(const Block &block)
Read a non-negative integer from a TLV element.
size_t prependNonNegativeIntegerBlock(EncodingImpl< TAG > &encoder, uint32_t type, uint64_t value)
Prepend a TLV element containing a non-negative integer.
Block makeEmptyBlock(uint32_t type)
Create an empty TLV block.
size_t prependEmptyBlock(EncodingImpl< TAG > &encoder, uint32_t type)
Prepend an empty TLV element.
Block makeBinaryBlock(uint32_t type, span< const uint8_t > value)
Create a TLV block copying the TLV-VALUE from a byte range.
size_t prependBinaryBlock(EncodingImpl< TAG > &encoder, uint32_t type, span< const uint8_t > value)
Prepend a TLV element containing a sequence of raw bytes.
EncodingImpl< EncoderTag > EncodingBuffer
size_t prependBlock(EncodingImpl< TAG > &encoder, const Block &block)
Prepend a TLV element.
std::string to_string(const errinfo_stacktrace &x)
Definition: exception.cpp:30
uint32_t generateWord32()
Generate a non-cryptographically-secure random integer in the range [0, 2^32).
Definition: random.cpp:68
unique_ptr< Transform > digestFilter(DigestAlgorithm algo)
unique_ptr< Sink > streamSink(std::ostream &os)
Definition: stream-sink.cpp:51
::boost::chrono::milliseconds milliseconds
Definition: time.hpp:52
@ Name
Definition: tlv.hpp:71
@ InterestLifetime
Definition: tlv.hpp:86
@ HopLimit
Definition: tlv.hpp:87
@ InterestSignatureInfo
Definition: tlv.hpp:89
@ ApplicationParameters
Definition: tlv.hpp:88
@ ForwardingHint
Definition: tlv.hpp:84
@ InterestSignatureValue
Definition: tlv.hpp:90
@ CanBePrefix
Definition: tlv.hpp:82
@ ParametersSha256DigestComponent
Definition: tlv.hpp:74
@ Interest
Definition: tlv.hpp:68
@ MustBeFresh
Definition: tlv.hpp:83
@ Nonce
Definition: tlv.hpp:85
constexpr bool isCriticalType(uint32_t type) noexcept
Determine whether a TLV-TYPE is "critical" for evolvability purpose.
Definition: tlv.hpp:162
Definition: data.cpp:25
std::ostream & operator<<(std::ostream &os, const Data &data)
Definition: data.cpp:377
constexpr time::milliseconds DEFAULT_INTEREST_LIFETIME
Default value of InterestLifetime.
Definition: interest.hpp:43
std::shared_ptr< const Buffer > ConstBufferPtr
Definition: buffer.hpp:140
InputBuffers bufs
SignatureInfo info