blob: 0e845e30c52ff8ca2a2b8235fb36cffca3d026cd [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
Junxiao Shi8b753a22018-10-24 01:51:40 +0000308 auto element = m_wire.elements_begin();
309 if (element == m_wire.elements_end() || element->type() != tlv::Name) {
310 BOOST_THROW_EXCEPTION(Error("Name element is missing or out of order"));
311 }
312 m_name.wireDecode(*element);
313 if (m_name.empty()) {
314 BOOST_THROW_EXCEPTION(Error("Name has zero name components"));
315 }
316 int lastElement = 1; // last recognized element index, in spec order
317
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000318 m_selectors = Selectors().setMaxSuffixComponents(1); // CanBePrefix=0
319 m_nonce.reset();
320 m_interestLifetime = DEFAULT_INTEREST_LIFETIME;
321 m_forwardingHint = DelegationList();
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700322 m_parameters = Block();
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000323
Junxiao Shi8b753a22018-10-24 01:51:40 +0000324 for (++element; element != m_wire.elements_end(); ++element) {
325 switch (element->type()) {
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000326 case tlv::CanBePrefix: {
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700327 if (lastElement >= 2) {
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000328 BOOST_THROW_EXCEPTION(Error("CanBePrefix element is out of order"));
329 }
Junxiao Shi8b753a22018-10-24 01:51:40 +0000330 if (element->value_size() != 0) {
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000331 BOOST_THROW_EXCEPTION(Error("CanBePrefix element has non-zero TLV-LENGTH"));
332 }
333 m_selectors.setMaxSuffixComponents(-1);
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700334 lastElement = 2;
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000335 break;
336 }
337 case tlv::MustBeFresh: {
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700338 if (lastElement >= 3) {
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000339 BOOST_THROW_EXCEPTION(Error("MustBeFresh element is out of order"));
340 }
Junxiao Shi8b753a22018-10-24 01:51:40 +0000341 if (element->value_size() != 0) {
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000342 BOOST_THROW_EXCEPTION(Error("MustBeFresh element has non-zero TLV-LENGTH"));
343 }
344 m_selectors.setMustBeFresh(true);
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700345 lastElement = 3;
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000346 break;
347 }
348 case tlv::ForwardingHint: {
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700349 if (lastElement >= 4) {
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000350 BOOST_THROW_EXCEPTION(Error("ForwardingHint element is out of order"));
351 }
Junxiao Shi8b753a22018-10-24 01:51:40 +0000352 m_forwardingHint.wireDecode(*element);
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700353 lastElement = 4;
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000354 break;
355 }
356 case tlv::Nonce: {
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700357 if (lastElement >= 5) {
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000358 BOOST_THROW_EXCEPTION(Error("Nonce element is out of order"));
359 }
360 uint32_t nonce = 0;
Junxiao Shi8b753a22018-10-24 01:51:40 +0000361 if (element->value_size() != sizeof(nonce)) {
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000362 BOOST_THROW_EXCEPTION(Error("Nonce element is malformed"));
363 }
Junxiao Shi8b753a22018-10-24 01:51:40 +0000364 std::memcpy(&nonce, element->value(), sizeof(nonce));
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000365 m_nonce = nonce;
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700366 lastElement = 5;
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000367 break;
368 }
369 case tlv::InterestLifetime: {
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700370 if (lastElement >= 6) {
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000371 BOOST_THROW_EXCEPTION(Error("InterestLifetime element is out of order"));
372 }
Junxiao Shi8b753a22018-10-24 01:51:40 +0000373 m_interestLifetime = time::milliseconds(readNonNegativeInteger(*element));
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700374 lastElement = 6;
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000375 break;
376 }
377 case tlv::HopLimit: {
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700378 if (lastElement >= 7) {
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000379 break; // HopLimit is non-critical, ignore out-of-order appearance
380 }
Junxiao Shi8b753a22018-10-24 01:51:40 +0000381 if (element->value_size() != 1) {
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000382 BOOST_THROW_EXCEPTION(Error("HopLimit element is malformed"));
383 }
384 // TLV-VALUE is ignored
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700385 lastElement = 7;
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000386 break;
387 }
388 case tlv::Parameters: {
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700389 if (lastElement >= 8) {
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000390 BOOST_THROW_EXCEPTION(Error("Parameters element is out of order"));
391 }
Junxiao Shi8b753a22018-10-24 01:51:40 +0000392 m_parameters = *element;
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700393 lastElement = 8;
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000394 break;
395 }
396 default: {
Junxiao Shi8b753a22018-10-24 01:51:40 +0000397 if (tlv::isCriticalType(element->type())) {
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000398 BOOST_THROW_EXCEPTION(Error("unrecognized element of critical type " +
Junxiao Shi8b753a22018-10-24 01:51:40 +0000399 to_string(element->type())));
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000400 }
401 break;
402 }
403 }
404 }
Alexander Afanasyevc3932172014-07-10 18:53:56 -0700405}
406
Davide Pesaventoa84f4642017-08-23 16:14:51 -0400407std::string
408Interest::toUri() const
409{
410 std::ostringstream os;
411 os << *this;
412 return os.str();
413}
414
Junxiao Shi899277a2017-07-07 22:12:12 +0000415// ---- matching ----
416
Alexander Afanasyev84681982014-01-03 13:26:09 -0800417bool
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700418Interest::matchesName(const Name& name) const
Jeff Thompson25b4e612013-10-10 16:03:24 -0700419{
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700420 if (name.size() < m_name.size())
421 return false;
422
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800423 if (!m_name.isPrefixOf(name))
Alexander Afanasyev84681982014-01-03 13:26:09 -0800424 return false;
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700425
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800426 if (getMinSuffixComponents() >= 0 &&
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700427 // name must include implicit digest
428 !(name.size() - m_name.size() >= static_cast<size_t>(getMinSuffixComponents())))
Alexander Afanasyev84681982014-01-03 13:26:09 -0800429 return false;
430
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800431 if (getMaxSuffixComponents() >= 0 &&
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700432 // name must include implicit digest
433 !(name.size() - m_name.size() <= static_cast<size_t>(getMaxSuffixComponents())))
Alexander Afanasyev84681982014-01-03 13:26:09 -0800434 return false;
435
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700436 if (!getExclude().empty() &&
437 name.size() > m_name.size() &&
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800438 getExclude().isExcluded(name[m_name.size()]))
Alexander Afanasyev84681982014-01-03 13:26:09 -0800439 return false;
440
441 return true;
Jeff Thompson25b4e612013-10-10 16:03:24 -0700442}
443
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700444bool
445Interest::matchesData(const Data& data) const
446{
Junxiao Shi42c23622014-07-03 00:55:11 -0700447 size_t interestNameLength = m_name.size();
448 const Name& dataName = data.getName();
449 size_t fullNameLength = dataName.size() + 1;
450
451 // check MinSuffixComponents
452 bool hasMinSuffixComponents = getMinSuffixComponents() >= 0;
453 size_t minSuffixComponents = hasMinSuffixComponents ?
454 static_cast<size_t>(getMinSuffixComponents()) : 0;
455 if (!(interestNameLength + minSuffixComponents <= fullNameLength))
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700456 return false;
Junxiao Shi42c23622014-07-03 00:55:11 -0700457
458 // check MaxSuffixComponents
459 bool hasMaxSuffixComponents = getMaxSuffixComponents() >= 0;
460 if (hasMaxSuffixComponents &&
461 !(interestNameLength + getMaxSuffixComponents() >= fullNameLength))
462 return false;
463
464 // check prefix
465 if (interestNameLength == fullNameLength) {
Alexander Afanasyev56860f52014-11-07 11:51:17 -0800466 if (m_name.get(-1).isImplicitSha256Digest()) {
467 if (m_name != data.getFullName())
Junxiao Shi42c23622014-07-03 00:55:11 -0700468 return false;
469 }
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 }
476 else {
477 // Interest Name is a strict prefix of Data full Name
478 if (!m_name.isPrefixOf(dataName))
479 return false;
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700480 }
481
Junxiao Shi42c23622014-07-03 00:55:11 -0700482 // check Exclude
483 // Exclude won't be violated if Interest Name is same as Data full Name
484 if (!getExclude().empty() && fullNameLength > interestNameLength) {
485 if (interestNameLength == fullNameLength - 1) {
486 // component to exclude is the digest
487 if (getExclude().isExcluded(data.getFullName().get(interestNameLength)))
488 return false;
489 // There's opportunity to inspect the Exclude filter and determine whether
490 // the digest would make a difference.
Junxiao Shi4ffbb9d2018-03-31 17:16:35 +0000491 // eg. "<GenericNameComponent>AA</GenericNameComponent><Any/>" doesn't exclude
492 // any digest - fullName not needed;
493 // "<Any/><GenericNameComponent>AA</GenericNameComponent>" and
Junxiao Shi08d07082014-12-03 11:31:44 -0700494 // "<Any/><ImplicitSha256DigestComponent>ffffffffffffffffffffffffffffffff
495 // </ImplicitSha256DigestComponent>"
496 // excludes all digests - fullName not needed;
497 // "<Any/><ImplicitSha256DigestComponent>80000000000000000000000000000000
498 // </ImplicitSha256DigestComponent>"
499 // excludes some digests - fullName required
Junxiao Shi42c23622014-07-03 00:55:11 -0700500 // But Interests that contain the exact Data Name before digest and also
501 // contain Exclude filter is too rare to optimize for, so we request
Junxiao Shi68247832017-07-03 22:06:49 +0000502 // fullName no matter what's in the Exclude filter.
Junxiao Shi42c23622014-07-03 00:55:11 -0700503 }
504 else {
505 // component to exclude is not the digest
506 if (getExclude().isExcluded(dataName.get(interestNameLength)))
507 return false;
508 }
509 }
510
511 // check PublisherPublicKeyLocator
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700512 const KeyLocator& publisherPublicKeyLocator = this->getPublisherPublicKeyLocator();
513 if (!publisherPublicKeyLocator.empty()) {
514 const Signature& signature = data.getSignature();
515 const Block& signatureInfo = signature.getInfo();
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600516 Block::element_const_iterator it = signatureInfo.find(tlv::KeyLocator);
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700517 if (it == signatureInfo.elements_end()) {
518 return false;
519 }
520 if (publisherPublicKeyLocator.wireEncode() != *it) {
521 return false;
522 }
523 }
524
525 return true;
526}
527
Alexander Afanasyev1013fd02017-01-03 13:19:03 -0800528bool
529Interest::matchesInterest(const Interest& other) const
530{
Junxiao Shi2dd711d2017-07-21 13:40:52 +0000531 /// @todo #3162 match ForwardingHint field
Alexander Afanasyev1013fd02017-01-03 13:19:03 -0800532 return (this->getName() == other.getName() &&
533 this->getSelectors() == other.getSelectors());
534}
535
Junxiao Shi899277a2017-07-07 22:12:12 +0000536// ---- field accessors ----
537
538uint32_t
539Interest::getNonce() const
540{
Junxiao Shi2dd711d2017-07-21 13:40:52 +0000541 if (!m_nonce) {
542 m_nonce = random::generateWord32();
Junxiao Shic2ac5d22017-07-17 22:18:31 +0000543 }
Junxiao Shi2dd711d2017-07-21 13:40:52 +0000544 return *m_nonce;
Junxiao Shi899277a2017-07-07 22:12:12 +0000545}
546
547Interest&
548Interest::setNonce(uint32_t nonce)
549{
Junxiao Shi2dd711d2017-07-21 13:40:52 +0000550 m_nonce = nonce;
551 m_wire.reset();
Junxiao Shi899277a2017-07-07 22:12:12 +0000552 return *this;
553}
554
555void
556Interest::refreshNonce()
557{
558 if (!hasNonce())
559 return;
560
561 uint32_t oldNonce = getNonce();
562 uint32_t newNonce = oldNonce;
563 while (newNonce == oldNonce)
564 newNonce = random::generateWord32();
565
566 setNonce(newNonce);
567}
568
Eric Newberryb555b002017-05-17 00:30:44 -0700569Interest&
Junxiao Shi8d3f8342018-04-04 12:46:37 +0000570Interest::setInterestLifetime(time::milliseconds lifetime)
Eric Newberryb555b002017-05-17 00:30:44 -0700571{
Junxiao Shi8d3f8342018-04-04 12:46:37 +0000572 if (lifetime < time::milliseconds::zero()) {
Eric Newberryb555b002017-05-17 00:30:44 -0700573 BOOST_THROW_EXCEPTION(std::invalid_argument("InterestLifetime must be >= 0"));
574 }
Junxiao Shi8d3f8342018-04-04 12:46:37 +0000575 m_interestLifetime = lifetime;
Eric Newberryb555b002017-05-17 00:30:44 -0700576 m_wire.reset();
577 return *this;
578}
579
Junxiao Shi9c154cb2017-07-07 22:14:54 +0000580Interest&
581Interest::setForwardingHint(const DelegationList& value)
582{
583 m_forwardingHint = value;
584 m_wire.reset();
585 return *this;
586}
587
Arthi Padmanabhanb38664e2018-07-18 11:13:12 -0700588Interest&
589Interest::setParameters(const Block& parameters)
590{
591 if (parameters.type() == tlv::Parameters) {
592 m_parameters = parameters;
593 }
594 else {
595 m_parameters = Block(tlv::Parameters, parameters);
596 }
597 m_wire.reset();
598 return *this;
599}
600
601Interest&
602Interest::setParameters(const uint8_t* buffer, size_t bufferSize)
603{
604 m_parameters = makeBinaryBlock(tlv::Parameters, buffer, bufferSize);
605 m_wire.reset();
606 return *this;
607}
608
609Interest&
610Interest::setParameters(ConstBufferPtr buffer)
611{
612 m_parameters = Block(tlv::Parameters, std::move(buffer));
613 m_wire.reset();
614 return *this;
615}
616
617Interest&
618Interest::unsetParameters()
619{
620 m_parameters = Block();
621 m_wire.reset();
622 return *this;
623}
624
Junxiao Shi899277a2017-07-07 22:12:12 +0000625// ---- operators ----
626
Junxiao Shib55e5d32018-07-18 13:32:00 -0600627bool
628operator==(const Interest& lhs, const Interest& rhs)
629{
630 bool wasCanBePrefixSetOnLhs = lhs.m_isCanBePrefixSet;
631 bool wasCanBePrefixSetOnRhs = rhs.m_isCanBePrefixSet;
632 lhs.m_isCanBePrefixSet = true;
633 rhs.m_isCanBePrefixSet = true;
634 BOOST_SCOPE_EXIT_ALL(&) {
635 lhs.m_isCanBePrefixSet = wasCanBePrefixSetOnLhs;
636 rhs.m_isCanBePrefixSet = wasCanBePrefixSetOnRhs;
637 };
638
639 return lhs.wireEncode() == rhs.wireEncode();
640}
641
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700642std::ostream&
643operator<<(std::ostream& os, const Interest& interest)
Jeff Thompsonfe556862013-07-09 13:52:55 -0700644{
Alexander Afanasyev84681982014-01-03 13:26:09 -0800645 os << interest.getName();
Jeff Thompsonfe556862013-07-09 13:52:55 -0700646
Alexander Afanasyev84681982014-01-03 13:26:09 -0800647 char delim = '?';
648
649 if (interest.getMinSuffixComponents() >= 0) {
650 os << delim << "ndn.MinSuffixComponents=" << interest.getMinSuffixComponents();
651 delim = '&';
Jeff Thompsonfe556862013-07-09 13:52:55 -0700652 }
Alexander Afanasyev84681982014-01-03 13:26:09 -0800653 if (interest.getMaxSuffixComponents() >= 0) {
654 os << delim << "ndn.MaxSuffixComponents=" << interest.getMaxSuffixComponents();
655 delim = '&';
Jeff Thompson37527d62013-08-21 11:15:54 -0700656 }
Eric Newberryb555b002017-05-17 00:30:44 -0700657 if (interest.getChildSelector() != DEFAULT_CHILD_SELECTOR) {
Alexander Afanasyev84681982014-01-03 13:26:09 -0800658 os << delim << "ndn.ChildSelector=" << interest.getChildSelector();
659 delim = '&';
Jeff Thompson13e280b2013-12-03 13:12:23 -0800660 }
Alexander Afanasyev84681982014-01-03 13:26:09 -0800661 if (interest.getMustBeFresh()) {
662 os << delim << "ndn.MustBeFresh=" << interest.getMustBeFresh();
663 delim = '&';
Jeff Thompson13e280b2013-12-03 13:12:23 -0800664 }
Eric Newberryb555b002017-05-17 00:30:44 -0700665 if (interest.getInterestLifetime() != DEFAULT_INTEREST_LIFETIME) {
Alexander Afanasyeva0c5f832014-06-19 13:27:56 -0700666 os << delim << "ndn.InterestLifetime=" << interest.getInterestLifetime().count();
Alexander Afanasyev84681982014-01-03 13:26:09 -0800667 delim = '&';
668 }
669
Alexander Afanasyeve881e932014-06-08 14:47:03 +0300670 if (interest.hasNonce()) {
Alexander Afanasyev84681982014-01-03 13:26:09 -0800671 os << delim << "ndn.Nonce=" << interest.getNonce();
672 delim = '&';
673 }
674 if (!interest.getExclude().empty()) {
675 os << delim << "ndn.Exclude=" << interest.getExclude();
676 delim = '&';
677 }
678
679 return os;
Jeff Thompson13e280b2013-12-03 13:12:23 -0800680}
681
Junxiao Shi08d07082014-12-03 11:31:44 -0700682} // namespace ndn