blob: f08eeb20e6554ef66267fcb1bec1e20fc5551a51 [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
Davide Pesaventoe1789892017-02-26 15:50:52 -050026#include <cstring>
Davide Pesaventoa84f4642017-08-23 16:14:51 -040027#include <sstream>
Davide Pesaventoe1789892017-02-26 15:50:52 -050028
Jeff Thompsonb7f95562013-07-03 18:36:42 -070029namespace ndn {
Alexander Afanasyev84681982014-01-03 13:26:09 -080030
Junxiao Shic2b8d242014-11-04 08:35:29 -070031BOOST_CONCEPT_ASSERT((boost::EqualityComparable<Interest>));
32BOOST_CONCEPT_ASSERT((WireEncodable<Interest>));
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070033BOOST_CONCEPT_ASSERT((WireEncodableWithEncodingBuffer<Interest>));
Junxiao Shic2b8d242014-11-04 08:35:29 -070034BOOST_CONCEPT_ASSERT((WireDecodable<Interest>));
35static_assert(std::is_base_of<tlv::Error, Interest::Error>::value,
36 "Interest::Error must inherit from tlv::Error");
37
Junxiao Shi8d3f8342018-04-04 12:46:37 +000038Interest::Interest(const Name& name, time::milliseconds lifetime)
Junxiao Shi2af905b2014-11-27 13:10:54 -070039 : m_name(name)
Junxiao Shi8d3f8342018-04-04 12:46:37 +000040 , m_interestLifetime(lifetime)
Junxiao Shi2af905b2014-11-27 13:10:54 -070041{
Junxiao Shi8d3f8342018-04-04 12:46:37 +000042 if (lifetime < time::milliseconds::zero()) {
Junxiao Shi899277a2017-07-07 22:12:12 +000043 BOOST_THROW_EXCEPTION(std::invalid_argument("InterestLifetime must be >= 0"));
44 }
Junxiao Shi2af905b2014-11-27 13:10:54 -070045}
46
Junxiao Shi2af905b2014-11-27 13:10:54 -070047Interest::Interest(const Block& wire)
48{
49 wireDecode(wire);
50}
51
Junxiao Shi899277a2017-07-07 22:12:12 +000052// ---- encode and decode ----
Alexander Afanasyev840139f2013-12-28 15:02:50 -080053
Junxiao Shi899277a2017-07-07 22:12:12 +000054template<encoding::Tag TAG>
55size_t
56Interest::wireEncode(EncodingImpl<TAG>& encoder) const
57{
58 size_t totalLength = 0;
59
60 // Interest ::= INTEREST-TYPE TLV-LENGTH
61 // Name
62 // Selectors?
63 // Nonce
64 // InterestLifetime?
Junxiao Shi9c154cb2017-07-07 22:14:54 +000065 // ForwardingHint?
Junxiao Shi899277a2017-07-07 22:12:12 +000066
67 // (reverse encoding)
68
Junxiao Shi9c154cb2017-07-07 22:14:54 +000069 // ForwardingHint
70 if (m_forwardingHint.size() > 0) {
71 totalLength += m_forwardingHint.wireEncode(encoder);
72 }
73
Junxiao Shi899277a2017-07-07 22:12:12 +000074 // InterestLifetime
75 if (getInterestLifetime() != DEFAULT_INTEREST_LIFETIME) {
76 totalLength += prependNonNegativeIntegerBlock(encoder,
77 tlv::InterestLifetime,
78 getInterestLifetime().count());
79 }
80
81 // Nonce
Junxiao Shi2dd711d2017-07-21 13:40:52 +000082 uint32_t nonce = this->getNonce(); // assigns random Nonce if needed
83 totalLength += encoder.prependByteArray(reinterpret_cast<uint8_t*>(&nonce), sizeof(nonce));
84 totalLength += encoder.prependVarNumber(sizeof(nonce));
85 totalLength += encoder.prependVarNumber(tlv::Nonce);
Junxiao Shi899277a2017-07-07 22:12:12 +000086
87 // Selectors
88 if (hasSelectors()) {
89 totalLength += getSelectors().wireEncode(encoder);
90 }
91
92 // Name
93 totalLength += getName().wireEncode(encoder);
94
95 totalLength += encoder.prependVarNumber(totalLength);
96 totalLength += encoder.prependVarNumber(tlv::Interest);
97 return totalLength;
Alexander Afanasyev840139f2013-12-28 15:02:50 -080098}
99
Davide Pesavento88a0d812017-08-19 21:31:42 -0400100NDN_CXX_DEFINE_WIRE_ENCODE_INSTANTIATIONS(Interest);
Junxiao Shi899277a2017-07-07 22:12:12 +0000101
102const Block&
103Interest::wireEncode() const
Alexander Afanasyeve881e932014-06-08 14:47:03 +0300104{
Junxiao Shi899277a2017-07-07 22:12:12 +0000105 if (m_wire.hasWire())
106 return m_wire;
107
108 EncodingEstimator estimator;
109 size_t estimatedSize = wireEncode(estimator);
110
111 EncodingBuffer buffer(estimatedSize, 0);
112 wireEncode(buffer);
113
Junxiao Shi899277a2017-07-07 22:12:12 +0000114 const_cast<Interest*>(this)->wireDecode(buffer.block());
Junxiao Shi899277a2017-07-07 22:12:12 +0000115 return m_wire;
Alexander Afanasyeve881e932014-06-08 14:47:03 +0300116}
Alexander Afanasyev840139f2013-12-28 15:02:50 -0800117
Alexander Afanasyevc3932172014-07-10 18:53:56 -0700118void
Junxiao Shi899277a2017-07-07 22:12:12 +0000119Interest::wireDecode(const Block& wire)
Alexander Afanasyevc3932172014-07-10 18:53:56 -0700120{
Junxiao Shi899277a2017-07-07 22:12:12 +0000121 m_wire = wire;
122 m_wire.parse();
Alexander Afanasyevc3932172014-07-10 18:53:56 -0700123
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000124 if (m_wire.type() != tlv::Interest) {
125 BOOST_THROW_EXCEPTION(Error("expecting Interest element, got " + to_string(m_wire.type())));
126 }
127
128 if (!decode02()) {
129 decode03();
130 if (!hasNonce()) {
131 setNonce(getNonce());
132 }
133 }
134}
135
136bool
137Interest::decode02()
138{
139 auto ele = m_wire.elements_begin();
Alexander Afanasyevc3932172014-07-10 18:53:56 -0700140
Junxiao Shi899277a2017-07-07 22:12:12 +0000141 // Name
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000142 if (ele != m_wire.elements_end() && ele->type() == tlv::Name) {
143 m_name.wireDecode(*ele);
144 ++ele;
Junxiao Shi899277a2017-07-07 22:12:12 +0000145 }
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000146 else {
147 return false;
148 }
149
150 // Selectors?
151 if (ele != m_wire.elements_end() && ele->type() == tlv::Selectors) {
152 m_selectors.wireDecode(*ele);
153 ++ele;
154 }
155 else {
Junxiao Shi899277a2017-07-07 22:12:12 +0000156 m_selectors = Selectors();
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000157 }
Junxiao Shi899277a2017-07-07 22:12:12 +0000158
159 // Nonce
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000160 if (ele != m_wire.elements_end() && ele->type() == tlv::Nonce) {
161 uint32_t nonce = 0;
162 if (ele->value_size() != sizeof(nonce)) {
163 BOOST_THROW_EXCEPTION(Error("Nonce element is malformed"));
164 }
165 std::memcpy(&nonce, ele->value(), sizeof(nonce));
166 m_nonce = nonce;
167 ++ele;
Junxiao Shi2dd711d2017-07-21 13:40:52 +0000168 }
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000169 else {
170 return false;
Junxiao Shi2dd711d2017-07-21 13:40:52 +0000171 }
Junxiao Shi899277a2017-07-07 22:12:12 +0000172
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000173 // InterestLifetime?
174 if (ele != m_wire.elements_end() && ele->type() == tlv::InterestLifetime) {
175 m_interestLifetime = time::milliseconds(readNonNegativeInteger(*ele));
176 ++ele;
Junxiao Shi899277a2017-07-07 22:12:12 +0000177 }
178 else {
179 m_interestLifetime = DEFAULT_INTEREST_LIFETIME;
180 }
181
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000182 // ForwardingHint?
183 if (ele != m_wire.elements_end() && ele->type() == tlv::ForwardingHint) {
184 m_forwardingHint.wireDecode(*ele, false);
185 ++ele;
Junxiao Shi9c154cb2017-07-07 22:14:54 +0000186 }
187 else {
188 m_forwardingHint = DelegationList();
189 }
Junxiao Shi6efa3b72018-04-14 15:54:08 +0000190
191 return ele == m_wire.elements_end();
192}
193
194void
195Interest::decode03()
196{
197 // Interest ::= INTEREST-TYPE TLV-LENGTH
198 // Name
199 // CanBePrefix?
200 // MustBeFresh?
201 // ForwardingHint?
202 // Nonce?
203 // InterestLifetime?
204 // HopLimit?
205 // Parameters?
206
207 bool hasName = false;
208 m_selectors = Selectors().setMaxSuffixComponents(1); // CanBePrefix=0
209 m_nonce.reset();
210 m_interestLifetime = DEFAULT_INTEREST_LIFETIME;
211 m_forwardingHint = DelegationList();
212
213 int lastEle = 0; // last recognized element index, in spec order
214 for (const Block& ele : m_wire.elements()) {
215 switch (ele.type()) {
216 case tlv::Name: {
217 if (lastEle >= 1) {
218 BOOST_THROW_EXCEPTION(Error("Name element is out of order"));
219 }
220 hasName = true;
221 m_name.wireDecode(ele);
222 if (m_name.empty()) {
223 BOOST_THROW_EXCEPTION(Error("Name has zero name components"));
224 }
225 lastEle = 1;
226 break;
227 }
228 case tlv::CanBePrefix: {
229 if (lastEle >= 2) {
230 BOOST_THROW_EXCEPTION(Error("CanBePrefix element is out of order"));
231 }
232 if (ele.value_size() != 0) {
233 BOOST_THROW_EXCEPTION(Error("CanBePrefix element has non-zero TLV-LENGTH"));
234 }
235 m_selectors.setMaxSuffixComponents(-1);
236 lastEle = 2;
237 break;
238 }
239 case tlv::MustBeFresh: {
240 if (lastEle >= 3) {
241 BOOST_THROW_EXCEPTION(Error("MustBeFresh element is out of order"));
242 }
243 if (ele.value_size() != 0) {
244 BOOST_THROW_EXCEPTION(Error("MustBeFresh element has non-zero TLV-LENGTH"));
245 }
246 m_selectors.setMustBeFresh(true);
247 lastEle = 3;
248 break;
249 }
250 case tlv::ForwardingHint: {
251 if (lastEle >= 4) {
252 BOOST_THROW_EXCEPTION(Error("ForwardingHint element is out of order"));
253 }
254 m_forwardingHint.wireDecode(ele);
255 lastEle = 4;
256 break;
257 }
258 case tlv::Nonce: {
259 if (lastEle >= 5) {
260 BOOST_THROW_EXCEPTION(Error("Nonce element is out of order"));
261 }
262 uint32_t nonce = 0;
263 if (ele.value_size() != sizeof(nonce)) {
264 BOOST_THROW_EXCEPTION(Error("Nonce element is malformed"));
265 }
266 std::memcpy(&nonce, ele.value(), sizeof(nonce));
267 m_nonce = nonce;
268 lastEle = 5;
269 break;
270 }
271 case tlv::InterestLifetime: {
272 if (lastEle >= 6) {
273 BOOST_THROW_EXCEPTION(Error("InterestLifetime element is out of order"));
274 }
275 m_interestLifetime = time::milliseconds(readNonNegativeInteger(ele));
276 lastEle = 6;
277 break;
278 }
279 case tlv::HopLimit: {
280 if (lastEle >= 7) {
281 break; // HopLimit is non-critical, ignore out-of-order appearance
282 }
283 if (ele.value_size() != 1) {
284 BOOST_THROW_EXCEPTION(Error("HopLimit element is malformed"));
285 }
286 // TLV-VALUE is ignored
287 lastEle = 7;
288 break;
289 }
290 case tlv::Parameters: {
291 if (lastEle >= 8) {
292 BOOST_THROW_EXCEPTION(Error("Parameters element is out of order"));
293 }
294 // TLV-VALUE is ignored
295 lastEle = 8;
296 break;
297 }
298 default: {
299 if (tlv::isCriticalType(ele.type())) {
300 BOOST_THROW_EXCEPTION(Error("unrecognized element of critical type " +
301 to_string(ele.type())));
302 }
303 break;
304 }
305 }
306 }
307
308 if (!hasName) {
309 BOOST_THROW_EXCEPTION(Error("Name element is missing"));
310 }
Alexander Afanasyevc3932172014-07-10 18:53:56 -0700311}
312
Davide Pesaventoa84f4642017-08-23 16:14:51 -0400313std::string
314Interest::toUri() const
315{
316 std::ostringstream os;
317 os << *this;
318 return os.str();
319}
320
Junxiao Shi899277a2017-07-07 22:12:12 +0000321// ---- matching ----
322
Alexander Afanasyev84681982014-01-03 13:26:09 -0800323bool
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700324Interest::matchesName(const Name& name) const
Jeff Thompson25b4e612013-10-10 16:03:24 -0700325{
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700326 if (name.size() < m_name.size())
327 return false;
328
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800329 if (!m_name.isPrefixOf(name))
Alexander Afanasyev84681982014-01-03 13:26:09 -0800330 return false;
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700331
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800332 if (getMinSuffixComponents() >= 0 &&
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700333 // name must include implicit digest
334 !(name.size() - m_name.size() >= static_cast<size_t>(getMinSuffixComponents())))
Alexander Afanasyev84681982014-01-03 13:26:09 -0800335 return false;
336
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800337 if (getMaxSuffixComponents() >= 0 &&
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700338 // name must include implicit digest
339 !(name.size() - m_name.size() <= static_cast<size_t>(getMaxSuffixComponents())))
Alexander Afanasyev84681982014-01-03 13:26:09 -0800340 return false;
341
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700342 if (!getExclude().empty() &&
343 name.size() > m_name.size() &&
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800344 getExclude().isExcluded(name[m_name.size()]))
Alexander Afanasyev84681982014-01-03 13:26:09 -0800345 return false;
346
347 return true;
Jeff Thompson25b4e612013-10-10 16:03:24 -0700348}
349
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700350bool
351Interest::matchesData(const Data& data) const
352{
Junxiao Shi42c23622014-07-03 00:55:11 -0700353 size_t interestNameLength = m_name.size();
354 const Name& dataName = data.getName();
355 size_t fullNameLength = dataName.size() + 1;
356
357 // check MinSuffixComponents
358 bool hasMinSuffixComponents = getMinSuffixComponents() >= 0;
359 size_t minSuffixComponents = hasMinSuffixComponents ?
360 static_cast<size_t>(getMinSuffixComponents()) : 0;
361 if (!(interestNameLength + minSuffixComponents <= fullNameLength))
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700362 return false;
Junxiao Shi42c23622014-07-03 00:55:11 -0700363
364 // check MaxSuffixComponents
365 bool hasMaxSuffixComponents = getMaxSuffixComponents() >= 0;
366 if (hasMaxSuffixComponents &&
367 !(interestNameLength + getMaxSuffixComponents() >= fullNameLength))
368 return false;
369
370 // check prefix
371 if (interestNameLength == fullNameLength) {
Alexander Afanasyev56860f52014-11-07 11:51:17 -0800372 if (m_name.get(-1).isImplicitSha256Digest()) {
373 if (m_name != data.getFullName())
Junxiao Shi42c23622014-07-03 00:55:11 -0700374 return false;
375 }
376 else {
377 // Interest Name is same length as Data full Name, but last component isn't digest
378 // so there's no possibility of matching
379 return false;
380 }
381 }
382 else {
383 // Interest Name is a strict prefix of Data full Name
384 if (!m_name.isPrefixOf(dataName))
385 return false;
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700386 }
387
Junxiao Shi42c23622014-07-03 00:55:11 -0700388 // check Exclude
389 // Exclude won't be violated if Interest Name is same as Data full Name
390 if (!getExclude().empty() && fullNameLength > interestNameLength) {
391 if (interestNameLength == fullNameLength - 1) {
392 // component to exclude is the digest
393 if (getExclude().isExcluded(data.getFullName().get(interestNameLength)))
394 return false;
395 // There's opportunity to inspect the Exclude filter and determine whether
396 // the digest would make a difference.
Junxiao Shi4ffbb9d2018-03-31 17:16:35 +0000397 // eg. "<GenericNameComponent>AA</GenericNameComponent><Any/>" doesn't exclude
398 // any digest - fullName not needed;
399 // "<Any/><GenericNameComponent>AA</GenericNameComponent>" and
Junxiao Shi08d07082014-12-03 11:31:44 -0700400 // "<Any/><ImplicitSha256DigestComponent>ffffffffffffffffffffffffffffffff
401 // </ImplicitSha256DigestComponent>"
402 // excludes all digests - fullName not needed;
403 // "<Any/><ImplicitSha256DigestComponent>80000000000000000000000000000000
404 // </ImplicitSha256DigestComponent>"
405 // excludes some digests - fullName required
Junxiao Shi42c23622014-07-03 00:55:11 -0700406 // But Interests that contain the exact Data Name before digest and also
407 // contain Exclude filter is too rare to optimize for, so we request
Junxiao Shi68247832017-07-03 22:06:49 +0000408 // fullName no matter what's in the Exclude filter.
Junxiao Shi42c23622014-07-03 00:55:11 -0700409 }
410 else {
411 // component to exclude is not the digest
412 if (getExclude().isExcluded(dataName.get(interestNameLength)))
413 return false;
414 }
415 }
416
417 // check PublisherPublicKeyLocator
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700418 const KeyLocator& publisherPublicKeyLocator = this->getPublisherPublicKeyLocator();
419 if (!publisherPublicKeyLocator.empty()) {
420 const Signature& signature = data.getSignature();
421 const Block& signatureInfo = signature.getInfo();
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600422 Block::element_const_iterator it = signatureInfo.find(tlv::KeyLocator);
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700423 if (it == signatureInfo.elements_end()) {
424 return false;
425 }
426 if (publisherPublicKeyLocator.wireEncode() != *it) {
427 return false;
428 }
429 }
430
431 return true;
432}
433
Alexander Afanasyev1013fd02017-01-03 13:19:03 -0800434bool
435Interest::matchesInterest(const Interest& other) const
436{
Junxiao Shi2dd711d2017-07-21 13:40:52 +0000437 /// @todo #3162 match ForwardingHint field
Alexander Afanasyev1013fd02017-01-03 13:19:03 -0800438 return (this->getName() == other.getName() &&
439 this->getSelectors() == other.getSelectors());
440}
441
Junxiao Shi899277a2017-07-07 22:12:12 +0000442// ---- field accessors ----
443
444uint32_t
445Interest::getNonce() const
446{
Junxiao Shi2dd711d2017-07-21 13:40:52 +0000447 if (!m_nonce) {
448 m_nonce = random::generateWord32();
Junxiao Shic2ac5d22017-07-17 22:18:31 +0000449 }
Junxiao Shi2dd711d2017-07-21 13:40:52 +0000450 return *m_nonce;
Junxiao Shi899277a2017-07-07 22:12:12 +0000451}
452
453Interest&
454Interest::setNonce(uint32_t nonce)
455{
Junxiao Shi2dd711d2017-07-21 13:40:52 +0000456 m_nonce = nonce;
457 m_wire.reset();
Junxiao Shi899277a2017-07-07 22:12:12 +0000458 return *this;
459}
460
461void
462Interest::refreshNonce()
463{
464 if (!hasNonce())
465 return;
466
467 uint32_t oldNonce = getNonce();
468 uint32_t newNonce = oldNonce;
469 while (newNonce == oldNonce)
470 newNonce = random::generateWord32();
471
472 setNonce(newNonce);
473}
474
Eric Newberryb555b002017-05-17 00:30:44 -0700475Interest&
Junxiao Shi8d3f8342018-04-04 12:46:37 +0000476Interest::setInterestLifetime(time::milliseconds lifetime)
Eric Newberryb555b002017-05-17 00:30:44 -0700477{
Junxiao Shi8d3f8342018-04-04 12:46:37 +0000478 if (lifetime < time::milliseconds::zero()) {
Eric Newberryb555b002017-05-17 00:30:44 -0700479 BOOST_THROW_EXCEPTION(std::invalid_argument("InterestLifetime must be >= 0"));
480 }
Junxiao Shi8d3f8342018-04-04 12:46:37 +0000481 m_interestLifetime = lifetime;
Eric Newberryb555b002017-05-17 00:30:44 -0700482 m_wire.reset();
483 return *this;
484}
485
Junxiao Shi9c154cb2017-07-07 22:14:54 +0000486Interest&
487Interest::setForwardingHint(const DelegationList& value)
488{
489 m_forwardingHint = value;
490 m_wire.reset();
491 return *this;
492}
493
Junxiao Shi899277a2017-07-07 22:12:12 +0000494// ---- operators ----
495
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700496std::ostream&
497operator<<(std::ostream& os, const Interest& interest)
Jeff Thompsonfe556862013-07-09 13:52:55 -0700498{
Alexander Afanasyev84681982014-01-03 13:26:09 -0800499 os << interest.getName();
Jeff Thompsonfe556862013-07-09 13:52:55 -0700500
Alexander Afanasyev84681982014-01-03 13:26:09 -0800501 char delim = '?';
502
503 if (interest.getMinSuffixComponents() >= 0) {
504 os << delim << "ndn.MinSuffixComponents=" << interest.getMinSuffixComponents();
505 delim = '&';
Jeff Thompsonfe556862013-07-09 13:52:55 -0700506 }
Alexander Afanasyev84681982014-01-03 13:26:09 -0800507 if (interest.getMaxSuffixComponents() >= 0) {
508 os << delim << "ndn.MaxSuffixComponents=" << interest.getMaxSuffixComponents();
509 delim = '&';
Jeff Thompson37527d62013-08-21 11:15:54 -0700510 }
Eric Newberryb555b002017-05-17 00:30:44 -0700511 if (interest.getChildSelector() != DEFAULT_CHILD_SELECTOR) {
Alexander Afanasyev84681982014-01-03 13:26:09 -0800512 os << delim << "ndn.ChildSelector=" << interest.getChildSelector();
513 delim = '&';
Jeff Thompson13e280b2013-12-03 13:12:23 -0800514 }
Alexander Afanasyev84681982014-01-03 13:26:09 -0800515 if (interest.getMustBeFresh()) {
516 os << delim << "ndn.MustBeFresh=" << interest.getMustBeFresh();
517 delim = '&';
Jeff Thompson13e280b2013-12-03 13:12:23 -0800518 }
Eric Newberryb555b002017-05-17 00:30:44 -0700519 if (interest.getInterestLifetime() != DEFAULT_INTEREST_LIFETIME) {
Alexander Afanasyeva0c5f832014-06-19 13:27:56 -0700520 os << delim << "ndn.InterestLifetime=" << interest.getInterestLifetime().count();
Alexander Afanasyev84681982014-01-03 13:26:09 -0800521 delim = '&';
522 }
523
Alexander Afanasyeve881e932014-06-08 14:47:03 +0300524 if (interest.hasNonce()) {
Alexander Afanasyev84681982014-01-03 13:26:09 -0800525 os << delim << "ndn.Nonce=" << interest.getNonce();
526 delim = '&';
527 }
528 if (!interest.getExclude().empty()) {
529 os << delim << "ndn.Exclude=" << interest.getExclude();
530 delim = '&';
531 }
532
533 return os;
Jeff Thompson13e280b2013-12-03 13:12:23 -0800534}
535
Junxiao Shi08d07082014-12-03 11:31:44 -0700536} // namespace ndn