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