blob: 50f5a13db8654ef6466bf5efb89205b5557aaece [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/*
Junxiao Shi4ffbb9d2018-03-31 17:16:35 +00003 * Copyright (c) 2013-2018 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
Alexander Afanasyev09c613f2014-01-29 00:23:58 -080022#include "interest.hpp"
Alexander Afanasyeve9fdb802014-02-05 17:36:51 -080023#include "util/random.hpp"
Junxiao Shiaf8eeea2014-03-31 20:10:56 -070024#include "data.hpp"
Alexander Afanasyev840139f2013-12-28 15:02:50 -080025
Junxiao Shib55e5d32018-07-18 13:32:00 -060026#include <boost/scope_exit.hpp>
27
Davide Pesaventoe1789892017-02-26 15:50:52 -050028#include <cstring>
Junxiao Shib55e5d32018-07-18 13:32:00 -060029#include <iostream>
Davide Pesaventoa84f4642017-08-23 16:14:51 -040030#include <sstream>
Davide Pesaventoe1789892017-02-26 15:50:52 -050031
Jeff Thompsonb7f95562013-07-03 18:36:42 -070032namespace ndn {
Alexander Afanasyev84681982014-01-03 13:26:09 -080033
Junxiao Shic2b8d242014-11-04 08:35:29 -070034BOOST_CONCEPT_ASSERT((boost::EqualityComparable<Interest>));
35BOOST_CONCEPT_ASSERT((WireEncodable<Interest>));
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070036BOOST_CONCEPT_ASSERT((WireEncodableWithEncodingBuffer<Interest>));
Junxiao Shic2b8d242014-11-04 08:35:29 -070037BOOST_CONCEPT_ASSERT((WireDecodable<Interest>));
38static_assert(std::is_base_of<tlv::Error, Interest::Error>::value,
39 "Interest::Error must inherit from tlv::Error");
40
Junxiao Shib55e5d32018-07-18 13:32:00 -060041#ifdef NDN_CXX_HAVE_TESTS
42bool Interest::s_errorIfCanBePrefixUnset = true;
43#endif // NDN_CXX_HAVE_TESTS
44boost::logic::tribool Interest::s_defaultCanBePrefix = boost::logic::indeterminate;
45
Junxiao Shi8d3f8342018-04-04 12:46:37 +000046Interest::Interest(const Name& name, time::milliseconds lifetime)
Junxiao Shi2af905b2014-11-27 13:10:54 -070047 : m_name(name)
Junxiao Shib55e5d32018-07-18 13:32:00 -060048 , m_isCanBePrefixSet(false)
Junxiao Shi8d3f8342018-04-04 12:46:37 +000049 , m_interestLifetime(lifetime)
Junxiao Shi2af905b2014-11-27 13:10:54 -070050{
Junxiao Shi8d3f8342018-04-04 12:46:37 +000051 if (lifetime < time::milliseconds::zero()) {
Junxiao Shi899277a2017-07-07 22:12:12 +000052 BOOST_THROW_EXCEPTION(std::invalid_argument("InterestLifetime must be >= 0"));
53 }
Junxiao Shib55e5d32018-07-18 13:32:00 -060054
55 if (!boost::logic::indeterminate(s_defaultCanBePrefix)) {
56 setCanBePrefix(static_cast<bool>(s_defaultCanBePrefix));
57 }
Junxiao Shi2af905b2014-11-27 13:10:54 -070058}
59
Junxiao Shi2af905b2014-11-27 13:10:54 -070060Interest::Interest(const Block& wire)
Junxiao Shib55e5d32018-07-18 13:32:00 -060061 : m_isCanBePrefixSet(true)
Junxiao Shi2af905b2014-11-27 13:10:54 -070062{
63 wireDecode(wire);
64}
65
Junxiao Shi899277a2017-07-07 22:12:12 +000066// ---- encode and decode ----
Alexander Afanasyev840139f2013-12-28 15:02:50 -080067
Junxiao Shi899277a2017-07-07 22:12:12 +000068template<encoding::Tag TAG>
69size_t
70Interest::wireEncode(EncodingImpl<TAG>& encoder) const
71{
Junxiao Shib55e5d32018-07-18 13:32:00 -060072 static bool hasDefaultCanBePrefixWarning = false;
73 if (!m_isCanBePrefixSet) {
74 if (!hasDefaultCanBePrefixWarning) {
75 std::cerr << "WARNING: Interest.CanBePrefix will be set to 0 in the near future. "
76 << "Please declare a preferred setting via Interest::setDefaultCanBePrefix.";
77 hasDefaultCanBePrefixWarning = true;
78 }
79#ifdef NDN_CXX_HAVE_TESTS
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -070080 if (s_errorIfCanBePrefixUnset) {
81 BOOST_THROW_EXCEPTION(std::logic_error("Interest.CanBePrefix is unset"));
82 }
Junxiao Shib55e5d32018-07-18 13:32:00 -060083#endif // NDN_CXX_HAVE_TESTS
84 }
85
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -070086 if (hasParameters()) {
87 return encode03(encoder);
88 }
89 else {
90 return encode02(encoder);
91 }
92}
93
94template<encoding::Tag TAG>
95size_t
96Interest::encode02(EncodingImpl<TAG>& encoder) const
97{
Junxiao Shi899277a2017-07-07 22:12:12 +000098 size_t totalLength = 0;
99
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700100 // Encode as NDN Packet Format v0.2
Junxiao Shi899277a2017-07-07 22:12:12 +0000101 // Interest ::= INTEREST-TYPE TLV-LENGTH
102 // Name
103 // Selectors?
104 // Nonce
105 // InterestLifetime?
Junxiao Shi9c154cb2017-07-07 22:14:54 +0000106 // ForwardingHint?
Junxiao Shi899277a2017-07-07 22:12:12 +0000107
108 // (reverse encoding)
109
Junxiao Shi9c154cb2017-07-07 22:14:54 +0000110 // ForwardingHint
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700111 if (getForwardingHint().size() > 0) {
112 totalLength += getForwardingHint().wireEncode(encoder);
Junxiao Shi9c154cb2017-07-07 22:14:54 +0000113 }
114
Junxiao Shi899277a2017-07-07 22:12:12 +0000115 // InterestLifetime
116 if (getInterestLifetime() != DEFAULT_INTEREST_LIFETIME) {
117 totalLength += prependNonNegativeIntegerBlock(encoder,
118 tlv::InterestLifetime,
119 getInterestLifetime().count());
120 }
121
122 // Nonce
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700123 uint32_t nonce = getNonce(); // if nonce was unset, getNonce generates a random nonce
124 totalLength += encoder.prependByteArrayBlock(tlv::Nonce, reinterpret_cast<uint8_t*>(&nonce), sizeof(nonce));
Junxiao Shi899277a2017-07-07 22:12:12 +0000125
126 // Selectors
127 if (hasSelectors()) {
128 totalLength += getSelectors().wireEncode(encoder);
129 }
130
131 // Name
132 totalLength += getName().wireEncode(encoder);
133
134 totalLength += encoder.prependVarNumber(totalLength);
135 totalLength += encoder.prependVarNumber(tlv::Interest);
136 return totalLength;
Alexander Afanasyev840139f2013-12-28 15:02:50 -0800137}
138
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700139template<encoding::Tag TAG>
140size_t
141Interest::encode03(EncodingImpl<TAG>& encoder) const
142{
143 size_t totalLength = 0;
144
145 // Encode as NDN Packet Format v0.3
146 // Interest ::= INTEREST-TYPE TLV-LENGTH
147 // Name
148 // CanBePrefix?
149 // MustBeFresh?
150 // ForwardingHint?
151 // Nonce?
152 // InterestLifetime?
153 // HopLimit?
154 // Parameters?
155
156 // (reverse encoding)
157
158 // Parameters
159 if (hasParameters()) {
160 totalLength += encoder.prependBlock(getParameters());
161 }
162
163 // HopLimit: not yet supported
164
165 // InterestLifetime
166 if (getInterestLifetime() != DEFAULT_INTEREST_LIFETIME) {
167 totalLength += prependNonNegativeIntegerBlock(encoder,
168 tlv::InterestLifetime,
169 getInterestLifetime().count());
170 }
171
172 // Nonce
173 uint32_t nonce = getNonce(); // if nonce was unset, getNonce generates a random nonce
174 totalLength += encoder.prependByteArrayBlock(tlv::Nonce, reinterpret_cast<uint8_t*>(&nonce), sizeof(nonce));
175
176 // ForwardingHint
177 if (getForwardingHint().size() > 0) {
178 totalLength += getForwardingHint().wireEncode(encoder);
179 }
180
181 // MustBeFresh
182 if (getMustBeFresh()) {
183 totalLength += prependEmptyBlock(encoder, tlv::MustBeFresh);
184 }
185
186 // CanBePrefix
187 if (getCanBePrefix()) {
188 totalLength += prependEmptyBlock(encoder, tlv::CanBePrefix);
189 }
190
191 // Name
192 totalLength += getName().wireEncode(encoder);
193
194 totalLength += encoder.prependVarNumber(totalLength);
195 totalLength += encoder.prependVarNumber(tlv::Interest);
196 return totalLength;
197}
198
Davide Pesavento88a0d812017-08-19 21:31:42 -0400199NDN_CXX_DEFINE_WIRE_ENCODE_INSTANTIATIONS(Interest);
Junxiao Shi899277a2017-07-07 22:12:12 +0000200
201const Block&
202Interest::wireEncode() const
Alexander Afanasyeve881e932014-06-08 14:47:03 +0300203{
Junxiao Shi899277a2017-07-07 22:12:12 +0000204 if (m_wire.hasWire())
205 return m_wire;
206
207 EncodingEstimator estimator;
208 size_t estimatedSize = wireEncode(estimator);
209
210 EncodingBuffer buffer(estimatedSize, 0);
211 wireEncode(buffer);
212
Junxiao Shi899277a2017-07-07 22:12:12 +0000213 const_cast<Interest*>(this)->wireDecode(buffer.block());
Junxiao Shi899277a2017-07-07 22:12:12 +0000214 return m_wire;
Alexander Afanasyeve881e932014-06-08 14:47:03 +0300215}
Alexander Afanasyev840139f2013-12-28 15:02:50 -0800216
Alexander Afanasyevc3932172014-07-10 18:53:56 -0700217void
Junxiao Shi899277a2017-07-07 22:12:12 +0000218Interest::wireDecode(const Block& wire)
Alexander Afanasyevc3932172014-07-10 18:53:56 -0700219{
Junxiao Shi899277a2017-07-07 22:12:12 +0000220 m_wire = wire;
221 m_wire.parse();
Alexander Afanasyevc3932172014-07-10 18:53:56 -0700222
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000223 if (m_wire.type() != tlv::Interest) {
224 BOOST_THROW_EXCEPTION(Error("expecting Interest element, got " + to_string(m_wire.type())));
225 }
226
227 if (!decode02()) {
228 decode03();
229 if (!hasNonce()) {
230 setNonce(getNonce());
231 }
232 }
Junxiao Shib55e5d32018-07-18 13:32:00 -0600233
234 m_isCanBePrefixSet = true; // don't trigger warning from decoded packet
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000235}
236
237bool
238Interest::decode02()
239{
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700240 auto element = m_wire.elements_begin();
Alexander Afanasyevc3932172014-07-10 18:53:56 -0700241
Junxiao Shi899277a2017-07-07 22:12:12 +0000242 // Name
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700243 if (element != m_wire.elements_end() && element->type() == tlv::Name) {
244 m_name.wireDecode(*element);
245 ++element;
Junxiao Shi899277a2017-07-07 22:12:12 +0000246 }
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000247 else {
248 return false;
249 }
250
251 // Selectors?
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700252 if (element != m_wire.elements_end() && element->type() == tlv::Selectors) {
253 m_selectors.wireDecode(*element);
254 ++element;
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000255 }
256 else {
Junxiao Shi899277a2017-07-07 22:12:12 +0000257 m_selectors = Selectors();
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000258 }
Junxiao Shi899277a2017-07-07 22:12:12 +0000259
260 // Nonce
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700261 if (element != m_wire.elements_end() && element->type() == tlv::Nonce) {
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000262 uint32_t nonce = 0;
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700263 if (element->value_size() != sizeof(nonce)) {
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000264 BOOST_THROW_EXCEPTION(Error("Nonce element is malformed"));
265 }
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700266 std::memcpy(&nonce, element->value(), sizeof(nonce));
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000267 m_nonce = nonce;
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700268 ++element;
Junxiao Shi2dd711d2017-07-21 13:40:52 +0000269 }
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000270 else {
271 return false;
Junxiao Shi2dd711d2017-07-21 13:40:52 +0000272 }
Junxiao Shi899277a2017-07-07 22:12:12 +0000273
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000274 // InterestLifetime?
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700275 if (element != m_wire.elements_end() && element->type() == tlv::InterestLifetime) {
276 m_interestLifetime = time::milliseconds(readNonNegativeInteger(*element));
277 ++element;
Junxiao Shi899277a2017-07-07 22:12:12 +0000278 }
279 else {
280 m_interestLifetime = DEFAULT_INTEREST_LIFETIME;
281 }
282
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000283 // ForwardingHint?
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700284 if (element != m_wire.elements_end() && element->type() == tlv::ForwardingHint) {
285 m_forwardingHint.wireDecode(*element, false);
286 ++element;
Junxiao Shi9c154cb2017-07-07 22:14:54 +0000287 }
288 else {
289 m_forwardingHint = DelegationList();
290 }
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000291
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700292 return element == m_wire.elements_end();
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000293}
294
295void
296Interest::decode03()
297{
298 // Interest ::= INTEREST-TYPE TLV-LENGTH
299 // Name
300 // CanBePrefix?
301 // MustBeFresh?
302 // ForwardingHint?
303 // Nonce?
304 // InterestLifetime?
305 // HopLimit?
306 // Parameters?
307
308 bool hasName = false;
309 m_selectors = Selectors().setMaxSuffixComponents(1); // CanBePrefix=0
310 m_nonce.reset();
311 m_interestLifetime = DEFAULT_INTEREST_LIFETIME;
312 m_forwardingHint = DelegationList();
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700313 m_parameters = Block();
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000314
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700315 int lastElement = 0; // last recognized element index, in spec order
316 for (const Block& element : m_wire.elements()) {
317 switch (element.type()) {
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000318 case tlv::Name: {
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700319 if (lastElement >= 1) {
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000320 BOOST_THROW_EXCEPTION(Error("Name element is out of order"));
321 }
322 hasName = true;
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700323 m_name.wireDecode(element);
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000324 if (m_name.empty()) {
325 BOOST_THROW_EXCEPTION(Error("Name has zero name components"));
326 }
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700327 lastElement = 1;
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000328 break;
329 }
330 case tlv::CanBePrefix: {
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700331 if (lastElement >= 2) {
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000332 BOOST_THROW_EXCEPTION(Error("CanBePrefix element is out of order"));
333 }
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700334 if (element.value_size() != 0) {
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000335 BOOST_THROW_EXCEPTION(Error("CanBePrefix element has non-zero TLV-LENGTH"));
336 }
337 m_selectors.setMaxSuffixComponents(-1);
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700338 lastElement = 2;
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000339 break;
340 }
341 case tlv::MustBeFresh: {
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700342 if (lastElement >= 3) {
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000343 BOOST_THROW_EXCEPTION(Error("MustBeFresh element is out of order"));
344 }
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700345 if (element.value_size() != 0) {
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000346 BOOST_THROW_EXCEPTION(Error("MustBeFresh element has non-zero TLV-LENGTH"));
347 }
348 m_selectors.setMustBeFresh(true);
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700349 lastElement = 3;
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000350 break;
351 }
352 case tlv::ForwardingHint: {
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700353 if (lastElement >= 4) {
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000354 BOOST_THROW_EXCEPTION(Error("ForwardingHint element is out of order"));
355 }
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700356 m_forwardingHint.wireDecode(element);
357 lastElement = 4;
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000358 break;
359 }
360 case tlv::Nonce: {
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700361 if (lastElement >= 5) {
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000362 BOOST_THROW_EXCEPTION(Error("Nonce element is out of order"));
363 }
364 uint32_t nonce = 0;
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700365 if (element.value_size() != sizeof(nonce)) {
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000366 BOOST_THROW_EXCEPTION(Error("Nonce element is malformed"));
367 }
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700368 std::memcpy(&nonce, element.value(), sizeof(nonce));
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000369 m_nonce = nonce;
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700370 lastElement = 5;
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000371 break;
372 }
373 case tlv::InterestLifetime: {
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700374 if (lastElement >= 6) {
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000375 BOOST_THROW_EXCEPTION(Error("InterestLifetime element is out of order"));
376 }
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700377 m_interestLifetime = time::milliseconds(readNonNegativeInteger(element));
378 lastElement = 6;
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000379 break;
380 }
381 case tlv::HopLimit: {
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700382 if (lastElement >= 7) {
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000383 break; // HopLimit is non-critical, ignore out-of-order appearance
384 }
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700385 if (element.value_size() != 1) {
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000386 BOOST_THROW_EXCEPTION(Error("HopLimit element is malformed"));
387 }
388 // TLV-VALUE is ignored
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700389 lastElement = 7;
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000390 break;
391 }
392 case tlv::Parameters: {
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700393 if (lastElement >= 8) {
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000394 BOOST_THROW_EXCEPTION(Error("Parameters element is out of order"));
395 }
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700396 m_parameters = element;
397 lastElement = 8;
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000398 break;
399 }
400 default: {
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700401 if (tlv::isCriticalType(element.type())) {
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000402 BOOST_THROW_EXCEPTION(Error("unrecognized element of critical type " +
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700403 to_string(element.type())));
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000404 }
405 break;
406 }
407 }
408 }
409
410 if (!hasName) {
411 BOOST_THROW_EXCEPTION(Error("Name element is missing"));
412 }
Alexander Afanasyevc3932172014-07-10 18:53:56 -0700413}
414
Davide Pesaventoa84f4642017-08-23 16:14:51 -0400415std::string
416Interest::toUri() const
417{
418 std::ostringstream os;
419 os << *this;
420 return os.str();
421}
422
Junxiao Shi899277a2017-07-07 22:12:12 +0000423// ---- matching ----
424
Alexander Afanasyev84681982014-01-03 13:26:09 -0800425bool
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700426Interest::matchesName(const Name& name) const
Jeff Thompson25b4e612013-10-10 16:03:24 -0700427{
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700428 if (name.size() < m_name.size())
429 return false;
430
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800431 if (!m_name.isPrefixOf(name))
Alexander Afanasyev84681982014-01-03 13:26:09 -0800432 return false;
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700433
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800434 if (getMinSuffixComponents() >= 0 &&
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700435 // name must include implicit digest
436 !(name.size() - m_name.size() >= static_cast<size_t>(getMinSuffixComponents())))
Alexander Afanasyev84681982014-01-03 13:26:09 -0800437 return false;
438
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800439 if (getMaxSuffixComponents() >= 0 &&
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700440 // name must include implicit digest
441 !(name.size() - m_name.size() <= static_cast<size_t>(getMaxSuffixComponents())))
Alexander Afanasyev84681982014-01-03 13:26:09 -0800442 return false;
443
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700444 if (!getExclude().empty() &&
445 name.size() > m_name.size() &&
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800446 getExclude().isExcluded(name[m_name.size()]))
Alexander Afanasyev84681982014-01-03 13:26:09 -0800447 return false;
448
449 return true;
Jeff Thompson25b4e612013-10-10 16:03:24 -0700450}
451
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700452bool
453Interest::matchesData(const Data& data) const
454{
Junxiao Shi42c23622014-07-03 00:55:11 -0700455 size_t interestNameLength = m_name.size();
456 const Name& dataName = data.getName();
457 size_t fullNameLength = dataName.size() + 1;
458
459 // check MinSuffixComponents
460 bool hasMinSuffixComponents = getMinSuffixComponents() >= 0;
461 size_t minSuffixComponents = hasMinSuffixComponents ?
462 static_cast<size_t>(getMinSuffixComponents()) : 0;
463 if (!(interestNameLength + minSuffixComponents <= fullNameLength))
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700464 return false;
Junxiao Shi42c23622014-07-03 00:55:11 -0700465
466 // check MaxSuffixComponents
467 bool hasMaxSuffixComponents = getMaxSuffixComponents() >= 0;
468 if (hasMaxSuffixComponents &&
469 !(interestNameLength + getMaxSuffixComponents() >= fullNameLength))
470 return false;
471
472 // check prefix
473 if (interestNameLength == fullNameLength) {
Alexander Afanasyev56860f52014-11-07 11:51:17 -0800474 if (m_name.get(-1).isImplicitSha256Digest()) {
475 if (m_name != data.getFullName())
Junxiao Shi42c23622014-07-03 00:55:11 -0700476 return false;
477 }
478 else {
479 // Interest Name is same length as Data full Name, but last component isn't digest
480 // so there's no possibility of matching
481 return false;
482 }
483 }
484 else {
485 // Interest Name is a strict prefix of Data full Name
486 if (!m_name.isPrefixOf(dataName))
487 return false;
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700488 }
489
Junxiao Shi42c23622014-07-03 00:55:11 -0700490 // check Exclude
491 // Exclude won't be violated if Interest Name is same as Data full Name
492 if (!getExclude().empty() && fullNameLength > interestNameLength) {
493 if (interestNameLength == fullNameLength - 1) {
494 // component to exclude is the digest
495 if (getExclude().isExcluded(data.getFullName().get(interestNameLength)))
496 return false;
497 // There's opportunity to inspect the Exclude filter and determine whether
498 // the digest would make a difference.
Junxiao Shi4ffbb9d2018-03-31 17:16:35 +0000499 // eg. "<GenericNameComponent>AA</GenericNameComponent><Any/>" doesn't exclude
500 // any digest - fullName not needed;
501 // "<Any/><GenericNameComponent>AA</GenericNameComponent>" and
Junxiao Shi08d07082014-12-03 11:31:44 -0700502 // "<Any/><ImplicitSha256DigestComponent>ffffffffffffffffffffffffffffffff
503 // </ImplicitSha256DigestComponent>"
504 // excludes all digests - fullName not needed;
505 // "<Any/><ImplicitSha256DigestComponent>80000000000000000000000000000000
506 // </ImplicitSha256DigestComponent>"
507 // excludes some digests - fullName required
Junxiao Shi42c23622014-07-03 00:55:11 -0700508 // But Interests that contain the exact Data Name before digest and also
509 // contain Exclude filter is too rare to optimize for, so we request
Junxiao Shi68247832017-07-03 22:06:49 +0000510 // fullName no matter what's in the Exclude filter.
Junxiao Shi42c23622014-07-03 00:55:11 -0700511 }
512 else {
513 // component to exclude is not the digest
514 if (getExclude().isExcluded(dataName.get(interestNameLength)))
515 return false;
516 }
517 }
518
519 // check PublisherPublicKeyLocator
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700520 const KeyLocator& publisherPublicKeyLocator = this->getPublisherPublicKeyLocator();
521 if (!publisherPublicKeyLocator.empty()) {
522 const Signature& signature = data.getSignature();
523 const Block& signatureInfo = signature.getInfo();
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600524 Block::element_const_iterator it = signatureInfo.find(tlv::KeyLocator);
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700525 if (it == signatureInfo.elements_end()) {
526 return false;
527 }
528 if (publisherPublicKeyLocator.wireEncode() != *it) {
529 return false;
530 }
531 }
532
533 return true;
534}
535
Alexander Afanasyev1013fd02017-01-03 13:19:03 -0800536bool
537Interest::matchesInterest(const Interest& other) const
538{
Junxiao Shi2dd711d2017-07-21 13:40:52 +0000539 /// @todo #3162 match ForwardingHint field
Alexander Afanasyev1013fd02017-01-03 13:19:03 -0800540 return (this->getName() == other.getName() &&
541 this->getSelectors() == other.getSelectors());
542}
543
Junxiao Shi899277a2017-07-07 22:12:12 +0000544// ---- field accessors ----
545
546uint32_t
547Interest::getNonce() const
548{
Junxiao Shi2dd711d2017-07-21 13:40:52 +0000549 if (!m_nonce) {
550 m_nonce = random::generateWord32();
Junxiao Shic2ac5d22017-07-17 22:18:31 +0000551 }
Junxiao Shi2dd711d2017-07-21 13:40:52 +0000552 return *m_nonce;
Junxiao Shi899277a2017-07-07 22:12:12 +0000553}
554
555Interest&
556Interest::setNonce(uint32_t nonce)
557{
Junxiao Shi2dd711d2017-07-21 13:40:52 +0000558 m_nonce = nonce;
559 m_wire.reset();
Junxiao Shi899277a2017-07-07 22:12:12 +0000560 return *this;
561}
562
563void
564Interest::refreshNonce()
565{
566 if (!hasNonce())
567 return;
568
569 uint32_t oldNonce = getNonce();
570 uint32_t newNonce = oldNonce;
571 while (newNonce == oldNonce)
572 newNonce = random::generateWord32();
573
574 setNonce(newNonce);
575}
576
Eric Newberryb555b002017-05-17 00:30:44 -0700577Interest&
Junxiao Shi8d3f8342018-04-04 12:46:37 +0000578Interest::setInterestLifetime(time::milliseconds lifetime)
Eric Newberryb555b002017-05-17 00:30:44 -0700579{
Junxiao Shi8d3f8342018-04-04 12:46:37 +0000580 if (lifetime < time::milliseconds::zero()) {
Eric Newberryb555b002017-05-17 00:30:44 -0700581 BOOST_THROW_EXCEPTION(std::invalid_argument("InterestLifetime must be >= 0"));
582 }
Junxiao Shi8d3f8342018-04-04 12:46:37 +0000583 m_interestLifetime = lifetime;
Eric Newberryb555b002017-05-17 00:30:44 -0700584 m_wire.reset();
585 return *this;
586}
587
Junxiao Shi9c154cb2017-07-07 22:14:54 +0000588Interest&
589Interest::setForwardingHint(const DelegationList& value)
590{
591 m_forwardingHint = value;
592 m_wire.reset();
593 return *this;
594}
595
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700596Interest&
597Interest::setParameters(const Block& parameters)
598{
599 if (parameters.type() == tlv::Parameters) {
600 m_parameters = parameters;
601 }
602 else {
603 m_parameters = Block(tlv::Parameters, parameters);
604 }
605 m_wire.reset();
606 return *this;
607}
608
609Interest&
610Interest::setParameters(const uint8_t* buffer, size_t bufferSize)
611{
612 m_parameters = makeBinaryBlock(tlv::Parameters, buffer, bufferSize);
613 m_wire.reset();
614 return *this;
615}
616
617Interest&
618Interest::setParameters(ConstBufferPtr buffer)
619{
620 m_parameters = Block(tlv::Parameters, std::move(buffer));
621 m_wire.reset();
622 return *this;
623}
624
625Interest&
626Interest::unsetParameters()
627{
628 m_parameters = Block();
629 m_wire.reset();
630 return *this;
631}
632
Junxiao Shi899277a2017-07-07 22:12:12 +0000633// ---- operators ----
634
Junxiao Shib55e5d32018-07-18 13:32:00 -0600635bool
636operator==(const Interest& lhs, const Interest& rhs)
637{
638 bool wasCanBePrefixSetOnLhs = lhs.m_isCanBePrefixSet;
639 bool wasCanBePrefixSetOnRhs = rhs.m_isCanBePrefixSet;
640 lhs.m_isCanBePrefixSet = true;
641 rhs.m_isCanBePrefixSet = true;
642 BOOST_SCOPE_EXIT_ALL(&) {
643 lhs.m_isCanBePrefixSet = wasCanBePrefixSetOnLhs;
644 rhs.m_isCanBePrefixSet = wasCanBePrefixSetOnRhs;
645 };
646
647 return lhs.wireEncode() == rhs.wireEncode();
648}
649
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700650std::ostream&
651operator<<(std::ostream& os, const Interest& interest)
Jeff Thompsonfe556862013-07-09 13:52:55 -0700652{
Alexander Afanasyev84681982014-01-03 13:26:09 -0800653 os << interest.getName();
Jeff Thompsonfe556862013-07-09 13:52:55 -0700654
Alexander Afanasyev84681982014-01-03 13:26:09 -0800655 char delim = '?';
656
657 if (interest.getMinSuffixComponents() >= 0) {
658 os << delim << "ndn.MinSuffixComponents=" << interest.getMinSuffixComponents();
659 delim = '&';
Jeff Thompsonfe556862013-07-09 13:52:55 -0700660 }
Alexander Afanasyev84681982014-01-03 13:26:09 -0800661 if (interest.getMaxSuffixComponents() >= 0) {
662 os << delim << "ndn.MaxSuffixComponents=" << interest.getMaxSuffixComponents();
663 delim = '&';
Jeff Thompson37527d62013-08-21 11:15:54 -0700664 }
Eric Newberryb555b002017-05-17 00:30:44 -0700665 if (interest.getChildSelector() != DEFAULT_CHILD_SELECTOR) {
Alexander Afanasyev84681982014-01-03 13:26:09 -0800666 os << delim << "ndn.ChildSelector=" << interest.getChildSelector();
667 delim = '&';
Jeff Thompson13e280b2013-12-03 13:12:23 -0800668 }
Alexander Afanasyev84681982014-01-03 13:26:09 -0800669 if (interest.getMustBeFresh()) {
670 os << delim << "ndn.MustBeFresh=" << interest.getMustBeFresh();
671 delim = '&';
Jeff Thompson13e280b2013-12-03 13:12:23 -0800672 }
Eric Newberryb555b002017-05-17 00:30:44 -0700673 if (interest.getInterestLifetime() != DEFAULT_INTEREST_LIFETIME) {
Alexander Afanasyeva0c5f832014-06-19 13:27:56 -0700674 os << delim << "ndn.InterestLifetime=" << interest.getInterestLifetime().count();
Alexander Afanasyev84681982014-01-03 13:26:09 -0800675 delim = '&';
676 }
677
Alexander Afanasyeve881e932014-06-08 14:47:03 +0300678 if (interest.hasNonce()) {
Alexander Afanasyev84681982014-01-03 13:26:09 -0800679 os << delim << "ndn.Nonce=" << interest.getNonce();
680 delim = '&';
681 }
682 if (!interest.getExclude().empty()) {
683 os << delim << "ndn.Exclude=" << interest.getExclude();
684 delim = '&';
685 }
686
687 return os;
Jeff Thompson13e280b2013-12-03 13:12:23 -0800688}
689
Junxiao Shi08d07082014-12-03 11:31:44 -0700690} // namespace ndn