blob: b14ac15496f6e5536c5489a5ef22e96a171f4328 [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Junxiao Shi899277a2017-07-07 22:12:12 +00002/*
Davide Pesaventofccb2dc2019-02-09 01:02:35 -05003 * Copyright (c) 2013-2019 Regents of the University of California.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07006 *
Alexander Afanasyevc169a812014-05-20 20:37:29 -04007 * 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.
Jeff Thompsonb7f95562013-07-03 18:36:42 -070020 */
21
Davide Pesavento7e780642018-11-24 15:51:34 -050022#include "ndn-cxx/interest.hpp"
23#include "ndn-cxx/data.hpp"
24#include "ndn-cxx/util/random.hpp"
Alexander Afanasyev840139f2013-12-28 15:02:50 -080025
Junxiao Shib55e5d32018-07-18 13:32:00 -060026#include <boost/scope_exit.hpp>
27
Davide Pesavento4bb06bc2019-04-06 13:59:10 -040028#ifdef NDN_CXX_HAVE_STACKTRACE
29#include <boost/stacktrace/stacktrace.hpp>
30#endif
31
Davide Pesaventoe1789892017-02-26 15:50:52 -050032#include <cstring>
Junxiao Shib55e5d32018-07-18 13:32:00 -060033#include <iostream>
Davide Pesaventoa84f4642017-08-23 16:14:51 -040034#include <sstream>
Davide Pesaventoe1789892017-02-26 15:50:52 -050035
Jeff Thompsonb7f95562013-07-03 18:36:42 -070036namespace ndn {
Alexander Afanasyev84681982014-01-03 13:26:09 -080037
Junxiao Shic2b8d242014-11-04 08:35:29 -070038BOOST_CONCEPT_ASSERT((boost::EqualityComparable<Interest>));
39BOOST_CONCEPT_ASSERT((WireEncodable<Interest>));
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070040BOOST_CONCEPT_ASSERT((WireEncodableWithEncodingBuffer<Interest>));
Junxiao Shic2b8d242014-11-04 08:35:29 -070041BOOST_CONCEPT_ASSERT((WireDecodable<Interest>));
42static_assert(std::is_base_of<tlv::Error, Interest::Error>::value,
43 "Interest::Error must inherit from tlv::Error");
44
Junxiao Shib55e5d32018-07-18 13:32:00 -060045#ifdef NDN_CXX_HAVE_TESTS
46bool Interest::s_errorIfCanBePrefixUnset = true;
47#endif // NDN_CXX_HAVE_TESTS
48boost::logic::tribool Interest::s_defaultCanBePrefix = boost::logic::indeterminate;
49
Junxiao Shi8d3f8342018-04-04 12:46:37 +000050Interest::Interest(const Name& name, time::milliseconds lifetime)
Junxiao Shi2af905b2014-11-27 13:10:54 -070051 : m_name(name)
Junxiao Shib55e5d32018-07-18 13:32:00 -060052 , m_isCanBePrefixSet(false)
Junxiao Shi8d3f8342018-04-04 12:46:37 +000053 , m_interestLifetime(lifetime)
Junxiao Shi2af905b2014-11-27 13:10:54 -070054{
Davide Pesaventofccb2dc2019-02-09 01:02:35 -050055 if (lifetime < 0_ms) {
Davide Pesavento923ba442019-02-12 22:00:38 -050056 NDN_THROW(std::invalid_argument("InterestLifetime must be >= 0"));
Junxiao Shi899277a2017-07-07 22:12:12 +000057 }
Junxiao Shib55e5d32018-07-18 13:32:00 -060058
59 if (!boost::logic::indeterminate(s_defaultCanBePrefix)) {
Davide Pesavento4bb06bc2019-04-06 13:59:10 -040060 setCanBePrefix(bool(s_defaultCanBePrefix));
Junxiao Shib55e5d32018-07-18 13:32:00 -060061 }
Junxiao Shi2af905b2014-11-27 13:10:54 -070062}
63
Junxiao Shi2af905b2014-11-27 13:10:54 -070064Interest::Interest(const Block& wire)
Junxiao Shib55e5d32018-07-18 13:32:00 -060065 : m_isCanBePrefixSet(true)
Junxiao Shi2af905b2014-11-27 13:10:54 -070066{
67 wireDecode(wire);
68}
69
Junxiao Shi899277a2017-07-07 22:12:12 +000070// ---- encode and decode ----
Alexander Afanasyev840139f2013-12-28 15:02:50 -080071
Davide Pesavento4bb06bc2019-04-06 13:59:10 -040072static void
73warnOnceCanBePrefixUnset()
74{
75 static bool didWarn = false;
76 if (!didWarn) {
77 didWarn = true;
78 std::cerr << "WARNING: Interest.CanBePrefix will be set to false in the near future. "
79 << "Please declare a preferred setting via Interest::setDefaultCanBePrefix.\n";
80#ifdef NDN_CXX_HAVE_STACKTRACE
81 if (std::getenv("NDN_CXX_VERBOSE_CANBEPREFIX_UNSET_WARNING") != nullptr) {
82 std::cerr << boost::stacktrace::stacktrace(2, 64);
83 }
84#endif
85 }
86}
87
Junxiao Shi899277a2017-07-07 22:12:12 +000088template<encoding::Tag TAG>
89size_t
90Interest::wireEncode(EncodingImpl<TAG>& encoder) const
91{
Junxiao Shib55e5d32018-07-18 13:32:00 -060092 if (!m_isCanBePrefixSet) {
Davide Pesavento4bb06bc2019-04-06 13:59:10 -040093 warnOnceCanBePrefixUnset();
Junxiao Shib55e5d32018-07-18 13:32:00 -060094#ifdef NDN_CXX_HAVE_TESTS
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -070095 if (s_errorIfCanBePrefixUnset) {
Davide Pesavento923ba442019-02-12 22:00:38 -050096 NDN_THROW(std::logic_error("Interest.CanBePrefix is unset"));
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -070097 }
Junxiao Shib55e5d32018-07-18 13:32:00 -060098#endif // NDN_CXX_HAVE_TESTS
99 }
100
Davide Pesavento9c19a392019-04-06 15:07:54 -0400101 if (hasApplicationParameters()) {
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700102 return encode03(encoder);
103 }
104 else {
105 return encode02(encoder);
106 }
107}
108
109template<encoding::Tag TAG>
110size_t
111Interest::encode02(EncodingImpl<TAG>& encoder) const
112{
Junxiao Shi899277a2017-07-07 22:12:12 +0000113 size_t totalLength = 0;
114
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700115 // Encode as NDN Packet Format v0.2
Junxiao Shi899277a2017-07-07 22:12:12 +0000116 // Interest ::= INTEREST-TYPE TLV-LENGTH
117 // Name
118 // Selectors?
119 // Nonce
120 // InterestLifetime?
Junxiao Shi9c154cb2017-07-07 22:14:54 +0000121 // ForwardingHint?
Junxiao Shi899277a2017-07-07 22:12:12 +0000122
123 // (reverse encoding)
124
Junxiao Shi9c154cb2017-07-07 22:14:54 +0000125 // ForwardingHint
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700126 if (getForwardingHint().size() > 0) {
127 totalLength += getForwardingHint().wireEncode(encoder);
Junxiao Shi9c154cb2017-07-07 22:14:54 +0000128 }
129
Junxiao Shi899277a2017-07-07 22:12:12 +0000130 // InterestLifetime
131 if (getInterestLifetime() != DEFAULT_INTEREST_LIFETIME) {
Davide Pesaventofccb2dc2019-02-09 01:02:35 -0500132 totalLength += prependNonNegativeIntegerBlock(encoder, tlv::InterestLifetime,
133 static_cast<uint64_t>(getInterestLifetime().count()));
Junxiao Shi899277a2017-07-07 22:12:12 +0000134 }
135
136 // Nonce
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700137 uint32_t nonce = getNonce(); // if nonce was unset, getNonce generates a random nonce
138 totalLength += encoder.prependByteArrayBlock(tlv::Nonce, reinterpret_cast<uint8_t*>(&nonce), sizeof(nonce));
Junxiao Shi899277a2017-07-07 22:12:12 +0000139
140 // Selectors
141 if (hasSelectors()) {
142 totalLength += getSelectors().wireEncode(encoder);
143 }
144
145 // Name
146 totalLength += getName().wireEncode(encoder);
147
148 totalLength += encoder.prependVarNumber(totalLength);
149 totalLength += encoder.prependVarNumber(tlv::Interest);
150 return totalLength;
Alexander Afanasyev840139f2013-12-28 15:02:50 -0800151}
152
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700153template<encoding::Tag TAG>
154size_t
155Interest::encode03(EncodingImpl<TAG>& encoder) const
156{
157 size_t totalLength = 0;
158
159 // Encode as NDN Packet Format v0.3
160 // Interest ::= INTEREST-TYPE TLV-LENGTH
161 // Name
162 // CanBePrefix?
163 // MustBeFresh?
164 // ForwardingHint?
165 // Nonce?
166 // InterestLifetime?
167 // HopLimit?
Davide Pesavento9c19a392019-04-06 15:07:54 -0400168 // ApplicationParameters?
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700169
170 // (reverse encoding)
171
Davide Pesavento9c19a392019-04-06 15:07:54 -0400172 // ApplicationParameters
173 if (hasApplicationParameters()) {
174 totalLength += encoder.prependBlock(getApplicationParameters());
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700175 }
176
177 // HopLimit: not yet supported
178
179 // InterestLifetime
180 if (getInterestLifetime() != DEFAULT_INTEREST_LIFETIME) {
Davide Pesavento9c19a392019-04-06 15:07:54 -0400181 totalLength += prependNonNegativeIntegerBlock(encoder, tlv::InterestLifetime,
182 static_cast<uint64_t>(getInterestLifetime().count()));
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700183 }
184
185 // Nonce
186 uint32_t nonce = getNonce(); // if nonce was unset, getNonce generates a random nonce
187 totalLength += encoder.prependByteArrayBlock(tlv::Nonce, reinterpret_cast<uint8_t*>(&nonce), sizeof(nonce));
188
189 // ForwardingHint
Davide Pesaventofccb2dc2019-02-09 01:02:35 -0500190 if (!getForwardingHint().empty()) {
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700191 totalLength += getForwardingHint().wireEncode(encoder);
192 }
193
194 // MustBeFresh
195 if (getMustBeFresh()) {
196 totalLength += prependEmptyBlock(encoder, tlv::MustBeFresh);
197 }
198
199 // CanBePrefix
200 if (getCanBePrefix()) {
201 totalLength += prependEmptyBlock(encoder, tlv::CanBePrefix);
202 }
203
204 // Name
205 totalLength += getName().wireEncode(encoder);
206
207 totalLength += encoder.prependVarNumber(totalLength);
208 totalLength += encoder.prependVarNumber(tlv::Interest);
209 return totalLength;
210}
211
Davide Pesavento88a0d812017-08-19 21:31:42 -0400212NDN_CXX_DEFINE_WIRE_ENCODE_INSTANTIATIONS(Interest);
Junxiao Shi899277a2017-07-07 22:12:12 +0000213
214const Block&
215Interest::wireEncode() const
Alexander Afanasyeve881e932014-06-08 14:47:03 +0300216{
Junxiao Shi899277a2017-07-07 22:12:12 +0000217 if (m_wire.hasWire())
218 return m_wire;
219
220 EncodingEstimator estimator;
221 size_t estimatedSize = wireEncode(estimator);
222
223 EncodingBuffer buffer(estimatedSize, 0);
224 wireEncode(buffer);
225
Junxiao Shi899277a2017-07-07 22:12:12 +0000226 const_cast<Interest*>(this)->wireDecode(buffer.block());
Junxiao Shi899277a2017-07-07 22:12:12 +0000227 return m_wire;
Alexander Afanasyeve881e932014-06-08 14:47:03 +0300228}
Alexander Afanasyev840139f2013-12-28 15:02:50 -0800229
Alexander Afanasyevc3932172014-07-10 18:53:56 -0700230void
Junxiao Shi899277a2017-07-07 22:12:12 +0000231Interest::wireDecode(const Block& wire)
Alexander Afanasyevc3932172014-07-10 18:53:56 -0700232{
Junxiao Shi899277a2017-07-07 22:12:12 +0000233 m_wire = wire;
234 m_wire.parse();
Alexander Afanasyevc3932172014-07-10 18:53:56 -0700235
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000236 if (m_wire.type() != tlv::Interest) {
Davide Pesavento923ba442019-02-12 22:00:38 -0500237 NDN_THROW(Error("Interest", m_wire.type()));
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000238 }
239
240 if (!decode02()) {
241 decode03();
242 if (!hasNonce()) {
243 setNonce(getNonce());
244 }
245 }
Junxiao Shib55e5d32018-07-18 13:32:00 -0600246
247 m_isCanBePrefixSet = true; // don't trigger warning from decoded packet
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000248}
249
250bool
251Interest::decode02()
252{
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700253 auto element = m_wire.elements_begin();
Alexander Afanasyevc3932172014-07-10 18:53:56 -0700254
Junxiao Shi899277a2017-07-07 22:12:12 +0000255 // Name
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700256 if (element != m_wire.elements_end() && element->type() == tlv::Name) {
257 m_name.wireDecode(*element);
258 ++element;
Junxiao Shi899277a2017-07-07 22:12:12 +0000259 }
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000260 else {
261 return false;
262 }
263
264 // Selectors?
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700265 if (element != m_wire.elements_end() && element->type() == tlv::Selectors) {
266 m_selectors.wireDecode(*element);
267 ++element;
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000268 }
269 else {
Davide Pesaventofccb2dc2019-02-09 01:02:35 -0500270 m_selectors = {};
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000271 }
Junxiao Shi899277a2017-07-07 22:12:12 +0000272
273 // Nonce
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700274 if (element != m_wire.elements_end() && element->type() == tlv::Nonce) {
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000275 uint32_t nonce = 0;
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700276 if (element->value_size() != sizeof(nonce)) {
Davide Pesavento923ba442019-02-12 22:00:38 -0500277 NDN_THROW(Error("Nonce element is malformed"));
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000278 }
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700279 std::memcpy(&nonce, element->value(), sizeof(nonce));
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000280 m_nonce = nonce;
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700281 ++element;
Junxiao Shi2dd711d2017-07-21 13:40:52 +0000282 }
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000283 else {
284 return false;
Junxiao Shi2dd711d2017-07-21 13:40:52 +0000285 }
Junxiao Shi899277a2017-07-07 22:12:12 +0000286
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000287 // InterestLifetime?
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700288 if (element != m_wire.elements_end() && element->type() == tlv::InterestLifetime) {
289 m_interestLifetime = time::milliseconds(readNonNegativeInteger(*element));
290 ++element;
Junxiao Shi899277a2017-07-07 22:12:12 +0000291 }
292 else {
293 m_interestLifetime = DEFAULT_INTEREST_LIFETIME;
294 }
295
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000296 // ForwardingHint?
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700297 if (element != m_wire.elements_end() && element->type() == tlv::ForwardingHint) {
298 m_forwardingHint.wireDecode(*element, false);
299 ++element;
Junxiao Shi9c154cb2017-07-07 22:14:54 +0000300 }
301 else {
Davide Pesaventofccb2dc2019-02-09 01:02:35 -0500302 m_forwardingHint = {};
Junxiao Shi9c154cb2017-07-07 22:14:54 +0000303 }
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000304
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700305 return element == m_wire.elements_end();
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000306}
307
308void
309Interest::decode03()
310{
311 // Interest ::= INTEREST-TYPE TLV-LENGTH
312 // Name
313 // CanBePrefix?
314 // MustBeFresh?
315 // ForwardingHint?
316 // Nonce?
317 // InterestLifetime?
318 // HopLimit?
Davide Pesavento9c19a392019-04-06 15:07:54 -0400319 // ApplicationParameters?
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000320
Junxiao Shi8b753a22018-10-24 01:51:40 +0000321 auto element = m_wire.elements_begin();
322 if (element == m_wire.elements_end() || element->type() != tlv::Name) {
Davide Pesavento923ba442019-02-12 22:00:38 -0500323 NDN_THROW(Error("Name element is missing or out of order"));
Junxiao Shi8b753a22018-10-24 01:51:40 +0000324 }
325 m_name.wireDecode(*element);
326 if (m_name.empty()) {
Davide Pesavento923ba442019-02-12 22:00:38 -0500327 NDN_THROW(Error("Name has zero name components"));
Junxiao Shi8b753a22018-10-24 01:51:40 +0000328 }
329 int lastElement = 1; // last recognized element index, in spec order
330
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000331 m_selectors = Selectors().setMaxSuffixComponents(1); // CanBePrefix=0
332 m_nonce.reset();
333 m_interestLifetime = DEFAULT_INTEREST_LIFETIME;
Davide Pesaventofccb2dc2019-02-09 01:02:35 -0500334 m_forwardingHint = {};
335 m_parameters = {};
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000336
Junxiao Shi8b753a22018-10-24 01:51:40 +0000337 for (++element; element != m_wire.elements_end(); ++element) {
338 switch (element->type()) {
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000339 case tlv::CanBePrefix: {
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700340 if (lastElement >= 2) {
Davide Pesavento923ba442019-02-12 22:00:38 -0500341 NDN_THROW(Error("CanBePrefix element is out of order"));
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000342 }
Junxiao Shi8b753a22018-10-24 01:51:40 +0000343 if (element->value_size() != 0) {
Davide Pesavento923ba442019-02-12 22:00:38 -0500344 NDN_THROW(Error("CanBePrefix element has non-zero TLV-LENGTH"));
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000345 }
346 m_selectors.setMaxSuffixComponents(-1);
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700347 lastElement = 2;
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000348 break;
349 }
350 case tlv::MustBeFresh: {
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700351 if (lastElement >= 3) {
Davide Pesavento923ba442019-02-12 22:00:38 -0500352 NDN_THROW(Error("MustBeFresh element is out of order"));
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000353 }
Junxiao Shi8b753a22018-10-24 01:51:40 +0000354 if (element->value_size() != 0) {
Davide Pesavento923ba442019-02-12 22:00:38 -0500355 NDN_THROW(Error("MustBeFresh element has non-zero TLV-LENGTH"));
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000356 }
357 m_selectors.setMustBeFresh(true);
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700358 lastElement = 3;
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000359 break;
360 }
361 case tlv::ForwardingHint: {
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700362 if (lastElement >= 4) {
Davide Pesavento923ba442019-02-12 22:00:38 -0500363 NDN_THROW(Error("ForwardingHint element is out of order"));
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000364 }
Junxiao Shi8b753a22018-10-24 01:51:40 +0000365 m_forwardingHint.wireDecode(*element);
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700366 lastElement = 4;
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000367 break;
368 }
369 case tlv::Nonce: {
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700370 if (lastElement >= 5) {
Davide Pesavento923ba442019-02-12 22:00:38 -0500371 NDN_THROW(Error("Nonce element is out of order"));
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000372 }
373 uint32_t nonce = 0;
Junxiao Shi8b753a22018-10-24 01:51:40 +0000374 if (element->value_size() != sizeof(nonce)) {
Davide Pesavento923ba442019-02-12 22:00:38 -0500375 NDN_THROW(Error("Nonce element is malformed"));
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000376 }
Junxiao Shi8b753a22018-10-24 01:51:40 +0000377 std::memcpy(&nonce, element->value(), sizeof(nonce));
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000378 m_nonce = nonce;
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700379 lastElement = 5;
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000380 break;
381 }
382 case tlv::InterestLifetime: {
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700383 if (lastElement >= 6) {
Davide Pesavento923ba442019-02-12 22:00:38 -0500384 NDN_THROW(Error("InterestLifetime element is out of order"));
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000385 }
Junxiao Shi8b753a22018-10-24 01:51:40 +0000386 m_interestLifetime = time::milliseconds(readNonNegativeInteger(*element));
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700387 lastElement = 6;
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000388 break;
389 }
390 case tlv::HopLimit: {
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700391 if (lastElement >= 7) {
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000392 break; // HopLimit is non-critical, ignore out-of-order appearance
393 }
Junxiao Shi8b753a22018-10-24 01:51:40 +0000394 if (element->value_size() != 1) {
Davide Pesavento923ba442019-02-12 22:00:38 -0500395 NDN_THROW(Error("HopLimit element is malformed"));
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000396 }
397 // TLV-VALUE is ignored
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700398 lastElement = 7;
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000399 break;
400 }
Davide Pesavento9c19a392019-04-06 15:07:54 -0400401 case tlv::ApplicationParameters: {
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700402 if (lastElement >= 8) {
Davide Pesavento9c19a392019-04-06 15:07:54 -0400403 break; // ApplicationParameters is non-critical, ignore out-of-order appearance
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000404 }
Junxiao Shi8b753a22018-10-24 01:51:40 +0000405 m_parameters = *element;
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700406 lastElement = 8;
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000407 break;
408 }
409 default: {
Junxiao Shi8b753a22018-10-24 01:51:40 +0000410 if (tlv::isCriticalType(element->type())) {
Davide Pesavento923ba442019-02-12 22:00:38 -0500411 NDN_THROW(Error("Unrecognized element of critical type " + to_string(element->type())));
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000412 }
413 break;
414 }
415 }
416 }
Alexander Afanasyevc3932172014-07-10 18:53:56 -0700417}
418
Davide Pesaventoa84f4642017-08-23 16:14:51 -0400419std::string
420Interest::toUri() const
421{
422 std::ostringstream os;
423 os << *this;
424 return os.str();
425}
426
Junxiao Shi899277a2017-07-07 22:12:12 +0000427// ---- matching ----
428
Alexander Afanasyev84681982014-01-03 13:26:09 -0800429bool
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700430Interest::matchesName(const Name& name) const
Jeff Thompson25b4e612013-10-10 16:03:24 -0700431{
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700432 if (name.size() < m_name.size())
433 return false;
434
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800435 if (!m_name.isPrefixOf(name))
Alexander Afanasyev84681982014-01-03 13:26:09 -0800436 return false;
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700437
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800438 if (getMinSuffixComponents() >= 0 &&
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700439 // name must include implicit digest
440 !(name.size() - m_name.size() >= static_cast<size_t>(getMinSuffixComponents())))
Alexander Afanasyev84681982014-01-03 13:26:09 -0800441 return false;
442
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800443 if (getMaxSuffixComponents() >= 0 &&
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700444 // name must include implicit digest
445 !(name.size() - m_name.size() <= static_cast<size_t>(getMaxSuffixComponents())))
Alexander Afanasyev84681982014-01-03 13:26:09 -0800446 return false;
447
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700448 if (!getExclude().empty() &&
449 name.size() > m_name.size() &&
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800450 getExclude().isExcluded(name[m_name.size()]))
Alexander Afanasyev84681982014-01-03 13:26:09 -0800451 return false;
452
453 return true;
Jeff Thompson25b4e612013-10-10 16:03:24 -0700454}
455
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700456bool
457Interest::matchesData(const Data& data) const
458{
Junxiao Shi42c23622014-07-03 00:55:11 -0700459 size_t interestNameLength = m_name.size();
460 const Name& dataName = data.getName();
461 size_t fullNameLength = dataName.size() + 1;
462
Junxiao Shi2ad2fbe2019-05-24 03:11:05 +0000463 // check Name and CanBePrefix
Junxiao Shi42c23622014-07-03 00:55:11 -0700464 if (interestNameLength == fullNameLength) {
Alexander Afanasyev56860f52014-11-07 11:51:17 -0800465 if (m_name.get(-1).isImplicitSha256Digest()) {
Junxiao Shi2ad2fbe2019-05-24 03:11:05 +0000466 if (m_name != data.getFullName()) {
Junxiao Shi42c23622014-07-03 00:55:11 -0700467 return false;
Junxiao Shi2ad2fbe2019-05-24 03:11:05 +0000468 }
Junxiao Shi42c23622014-07-03 00:55:11 -0700469 }
470 else {
471 // Interest Name is same length as Data full Name, but last component isn't digest
472 // so there's no possibility of matching
473 return false;
474 }
475 }
Junxiao Shi2ad2fbe2019-05-24 03:11:05 +0000476 else if (getCanBePrefix() ? !m_name.isPrefixOf(dataName) : (m_name != dataName)) {
477 return false;
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700478 }
479
Junxiao Shi2ad2fbe2019-05-24 03:11:05 +0000480 // check MustBeFresh
481 if (getMustBeFresh() && data.getFreshnessPeriod() <= 0_ms) {
482 return false;
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700483 }
484
485 return true;
486}
487
Alexander Afanasyev1013fd02017-01-03 13:19:03 -0800488bool
489Interest::matchesInterest(const Interest& other) const
490{
Junxiao Shi2ad2fbe2019-05-24 03:11:05 +0000491 return getName() == other.getName() &&
492 getCanBePrefix() == other.getCanBePrefix() &&
493 getMustBeFresh() == other.getMustBeFresh();
Alexander Afanasyev1013fd02017-01-03 13:19:03 -0800494}
495
Junxiao Shi899277a2017-07-07 22:12:12 +0000496// ---- field accessors ----
497
498uint32_t
499Interest::getNonce() const
500{
Junxiao Shi2dd711d2017-07-21 13:40:52 +0000501 if (!m_nonce) {
502 m_nonce = random::generateWord32();
Junxiao Shic2ac5d22017-07-17 22:18:31 +0000503 }
Junxiao Shi2dd711d2017-07-21 13:40:52 +0000504 return *m_nonce;
Junxiao Shi899277a2017-07-07 22:12:12 +0000505}
506
507Interest&
508Interest::setNonce(uint32_t nonce)
509{
Junxiao Shi2dd711d2017-07-21 13:40:52 +0000510 m_nonce = nonce;
511 m_wire.reset();
Junxiao Shi899277a2017-07-07 22:12:12 +0000512 return *this;
513}
514
515void
516Interest::refreshNonce()
517{
518 if (!hasNonce())
519 return;
520
521 uint32_t oldNonce = getNonce();
522 uint32_t newNonce = oldNonce;
523 while (newNonce == oldNonce)
524 newNonce = random::generateWord32();
525
526 setNonce(newNonce);
527}
528
Eric Newberryb555b002017-05-17 00:30:44 -0700529Interest&
Junxiao Shi8d3f8342018-04-04 12:46:37 +0000530Interest::setInterestLifetime(time::milliseconds lifetime)
Eric Newberryb555b002017-05-17 00:30:44 -0700531{
Davide Pesaventofccb2dc2019-02-09 01:02:35 -0500532 if (lifetime < 0_ms) {
Davide Pesavento923ba442019-02-12 22:00:38 -0500533 NDN_THROW(std::invalid_argument("InterestLifetime must be >= 0"));
Eric Newberryb555b002017-05-17 00:30:44 -0700534 }
Junxiao Shi8d3f8342018-04-04 12:46:37 +0000535 m_interestLifetime = lifetime;
Eric Newberryb555b002017-05-17 00:30:44 -0700536 m_wire.reset();
537 return *this;
538}
539
Junxiao Shi9c154cb2017-07-07 22:14:54 +0000540Interest&
541Interest::setForwardingHint(const DelegationList& value)
542{
543 m_forwardingHint = value;
544 m_wire.reset();
545 return *this;
546}
547
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700548Interest&
Davide Pesavento9c19a392019-04-06 15:07:54 -0400549Interest::setApplicationParameters(const Block& parameters)
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700550{
Davide Pesavento38912442019-04-06 22:03:39 -0400551 if (parameters.empty()) {
552 m_parameters = Block(tlv::ApplicationParameters);
553 }
554 else if (parameters.type() == tlv::ApplicationParameters) {
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700555 m_parameters = parameters;
556 }
557 else {
Davide Pesavento9c19a392019-04-06 15:07:54 -0400558 m_parameters = Block(tlv::ApplicationParameters, parameters);
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700559 }
560 m_wire.reset();
561 return *this;
562}
563
564Interest&
Davide Pesavento9c19a392019-04-06 15:07:54 -0400565Interest::setApplicationParameters(const uint8_t* buffer, size_t bufferSize)
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700566{
Davide Pesavento38912442019-04-06 22:03:39 -0400567 if (buffer == nullptr && bufferSize != 0) {
568 NDN_THROW(std::invalid_argument("ApplicationParameters buffer cannot be nullptr"));
569 }
Davide Pesavento9c19a392019-04-06 15:07:54 -0400570 m_parameters = makeBinaryBlock(tlv::ApplicationParameters, buffer, bufferSize);
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700571 m_wire.reset();
572 return *this;
573}
574
575Interest&
Davide Pesavento9c19a392019-04-06 15:07:54 -0400576Interest::setApplicationParameters(ConstBufferPtr buffer)
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700577{
Davide Pesavento38912442019-04-06 22:03:39 -0400578 if (buffer == nullptr) {
579 NDN_THROW(std::invalid_argument("ApplicationParameters buffer cannot be nullptr"));
580 }
Davide Pesavento9c19a392019-04-06 15:07:54 -0400581 m_parameters = Block(tlv::ApplicationParameters, std::move(buffer));
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700582 m_wire.reset();
583 return *this;
584}
585
586Interest&
Davide Pesavento9c19a392019-04-06 15:07:54 -0400587Interest::unsetApplicationParameters()
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700588{
Davide Pesaventofccb2dc2019-02-09 01:02:35 -0500589 m_parameters = {};
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700590 m_wire.reset();
591 return *this;
592}
593
Junxiao Shi899277a2017-07-07 22:12:12 +0000594// ---- operators ----
595
Junxiao Shib55e5d32018-07-18 13:32:00 -0600596bool
597operator==(const Interest& lhs, const Interest& rhs)
598{
599 bool wasCanBePrefixSetOnLhs = lhs.m_isCanBePrefixSet;
600 bool wasCanBePrefixSetOnRhs = rhs.m_isCanBePrefixSet;
601 lhs.m_isCanBePrefixSet = true;
602 rhs.m_isCanBePrefixSet = true;
603 BOOST_SCOPE_EXIT_ALL(&) {
604 lhs.m_isCanBePrefixSet = wasCanBePrefixSetOnLhs;
605 rhs.m_isCanBePrefixSet = wasCanBePrefixSetOnRhs;
606 };
607
608 return lhs.wireEncode() == rhs.wireEncode();
609}
610
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700611std::ostream&
612operator<<(std::ostream& os, const Interest& interest)
Jeff Thompsonfe556862013-07-09 13:52:55 -0700613{
Alexander Afanasyev84681982014-01-03 13:26:09 -0800614 os << interest.getName();
Jeff Thompsonfe556862013-07-09 13:52:55 -0700615
Alexander Afanasyev84681982014-01-03 13:26:09 -0800616 char delim = '?';
617
618 if (interest.getMinSuffixComponents() >= 0) {
619 os << delim << "ndn.MinSuffixComponents=" << interest.getMinSuffixComponents();
620 delim = '&';
Jeff Thompsonfe556862013-07-09 13:52:55 -0700621 }
Alexander Afanasyev84681982014-01-03 13:26:09 -0800622 if (interest.getMaxSuffixComponents() >= 0) {
623 os << delim << "ndn.MaxSuffixComponents=" << interest.getMaxSuffixComponents();
624 delim = '&';
Jeff Thompson37527d62013-08-21 11:15:54 -0700625 }
Eric Newberryb555b002017-05-17 00:30:44 -0700626 if (interest.getChildSelector() != DEFAULT_CHILD_SELECTOR) {
Alexander Afanasyev84681982014-01-03 13:26:09 -0800627 os << delim << "ndn.ChildSelector=" << interest.getChildSelector();
628 delim = '&';
Jeff Thompson13e280b2013-12-03 13:12:23 -0800629 }
Alexander Afanasyev84681982014-01-03 13:26:09 -0800630 if (interest.getMustBeFresh()) {
631 os << delim << "ndn.MustBeFresh=" << interest.getMustBeFresh();
632 delim = '&';
Jeff Thompson13e280b2013-12-03 13:12:23 -0800633 }
Eric Newberryb555b002017-05-17 00:30:44 -0700634 if (interest.getInterestLifetime() != DEFAULT_INTEREST_LIFETIME) {
Alexander Afanasyeva0c5f832014-06-19 13:27:56 -0700635 os << delim << "ndn.InterestLifetime=" << interest.getInterestLifetime().count();
Alexander Afanasyev84681982014-01-03 13:26:09 -0800636 delim = '&';
637 }
Alexander Afanasyeve881e932014-06-08 14:47:03 +0300638 if (interest.hasNonce()) {
Alexander Afanasyev84681982014-01-03 13:26:09 -0800639 os << delim << "ndn.Nonce=" << interest.getNonce();
640 delim = '&';
641 }
642 if (!interest.getExclude().empty()) {
643 os << delim << "ndn.Exclude=" << interest.getExclude();
644 delim = '&';
645 }
646
647 return os;
Jeff Thompson13e280b2013-12-03 13:12:23 -0800648}
649
Junxiao Shi08d07082014-12-03 11:31:44 -0700650} // namespace ndn