blob: d6184751e0bd981b46cebe9e389b05e1a8572b6b [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/*
Alexander Afanasyev1013fd02017-01-03 13:19:03 -08003 * Copyright (c) 2013-2017 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>
27
Jeff Thompsonb7f95562013-07-03 18:36:42 -070028namespace ndn {
Alexander Afanasyev84681982014-01-03 13:26:09 -080029
Junxiao Shic2b8d242014-11-04 08:35:29 -070030BOOST_CONCEPT_ASSERT((boost::EqualityComparable<Interest>));
31BOOST_CONCEPT_ASSERT((WireEncodable<Interest>));
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070032BOOST_CONCEPT_ASSERT((WireEncodableWithEncodingBuffer<Interest>));
Junxiao Shic2b8d242014-11-04 08:35:29 -070033BOOST_CONCEPT_ASSERT((WireDecodable<Interest>));
34static_assert(std::is_base_of<tlv::Error, Interest::Error>::value,
35 "Interest::Error must inherit from tlv::Error");
36
Junxiao Shi899277a2017-07-07 22:12:12 +000037Interest::Interest(const Name& name, time::milliseconds interestLifetime)
Junxiao Shi2af905b2014-11-27 13:10:54 -070038 : m_name(name)
Junxiao Shi2af905b2014-11-27 13:10:54 -070039 , m_interestLifetime(interestLifetime)
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -070040 , m_selectedDelegationIndex(INVALID_SELECTED_DELEGATION_INDEX)
Junxiao Shi2af905b2014-11-27 13:10:54 -070041{
Junxiao Shi899277a2017-07-07 22:12:12 +000042 if (interestLifetime < time::milliseconds::zero()) {
43 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 // Link?
67 // SelectedDelegation?
68
69 // (reverse encoding)
70
71 // Link and SelectedDelegation
72 if (hasLink()) {
73 if (hasSelectedDelegation()) {
74 totalLength += prependNonNegativeIntegerBlock(encoder,
75 tlv::SelectedDelegation,
76 m_selectedDelegationIndex);
77 }
78 totalLength += encoder.prependBlock(m_link);
Alexander Afanasyeve881e932014-06-08 14:47:03 +030079 }
Junxiao Shi899277a2017-07-07 22:12:12 +000080 else {
81 BOOST_ASSERT(!hasSelectedDelegation());
82 }
83
Junxiao Shi9c154cb2017-07-07 22:14:54 +000084 // ForwardingHint
85 if (m_forwardingHint.size() > 0) {
86 totalLength += m_forwardingHint.wireEncode(encoder);
87 }
88
Junxiao Shi899277a2017-07-07 22:12:12 +000089 // InterestLifetime
90 if (getInterestLifetime() != DEFAULT_INTEREST_LIFETIME) {
91 totalLength += prependNonNegativeIntegerBlock(encoder,
92 tlv::InterestLifetime,
93 getInterestLifetime().count());
94 }
95
96 // Nonce
Junxiao Shi2dd711d2017-07-21 13:40:52 +000097 uint32_t nonce = this->getNonce(); // assigns random Nonce if needed
98 totalLength += encoder.prependByteArray(reinterpret_cast<uint8_t*>(&nonce), sizeof(nonce));
99 totalLength += encoder.prependVarNumber(sizeof(nonce));
100 totalLength += encoder.prependVarNumber(tlv::Nonce);
Junxiao Shi899277a2017-07-07 22:12:12 +0000101
102 // Selectors
103 if (hasSelectors()) {
104 totalLength += getSelectors().wireEncode(encoder);
105 }
106
107 // Name
108 totalLength += getName().wireEncode(encoder);
109
110 totalLength += encoder.prependVarNumber(totalLength);
111 totalLength += encoder.prependVarNumber(tlv::Interest);
112 return totalLength;
Alexander Afanasyev840139f2013-12-28 15:02:50 -0800113}
114
Junxiao Shi899277a2017-07-07 22:12:12 +0000115template size_t
116Interest::wireEncode<encoding::EncoderTag>(EncodingImpl<encoding::EncoderTag>& encoder) const;
117
118template size_t
119Interest::wireEncode<encoding::EstimatorTag>(EncodingImpl<encoding::EstimatorTag>& encoder) const;
120
121const Block&
122Interest::wireEncode() const
Alexander Afanasyeve881e932014-06-08 14:47:03 +0300123{
Junxiao Shi899277a2017-07-07 22:12:12 +0000124 if (m_wire.hasWire())
125 return m_wire;
126
127 EncodingEstimator estimator;
128 size_t estimatedSize = wireEncode(estimator);
129
130 EncodingBuffer buffer(estimatedSize, 0);
131 wireEncode(buffer);
132
Junxiao Shi2dd711d2017-07-21 13:40:52 +0000133 // to ensure that Link block points to the right memory location
Junxiao Shi899277a2017-07-07 22:12:12 +0000134 const_cast<Interest*>(this)->wireDecode(buffer.block());
135
136 return m_wire;
Alexander Afanasyeve881e932014-06-08 14:47:03 +0300137}
Alexander Afanasyev840139f2013-12-28 15:02:50 -0800138
Alexander Afanasyevc3932172014-07-10 18:53:56 -0700139void
Junxiao Shi899277a2017-07-07 22:12:12 +0000140Interest::wireDecode(const Block& wire)
Alexander Afanasyevc3932172014-07-10 18:53:56 -0700141{
Junxiao Shi899277a2017-07-07 22:12:12 +0000142 m_wire = wire;
143 m_wire.parse();
Alexander Afanasyevc3932172014-07-10 18:53:56 -0700144
Junxiao Shi899277a2017-07-07 22:12:12 +0000145 if (m_wire.type() != tlv::Interest)
146 BOOST_THROW_EXCEPTION(Error("Unexpected TLV number when decoding Interest"));
Alexander Afanasyevc3932172014-07-10 18:53:56 -0700147
Junxiao Shi899277a2017-07-07 22:12:12 +0000148 // Name
149 m_name.wireDecode(m_wire.get(tlv::Name));
150
151 // Selectors
152 Block::element_const_iterator val = m_wire.find(tlv::Selectors);
153 if (val != m_wire.elements_end()) {
154 m_selectors.wireDecode(*val);
155 }
156 else
157 m_selectors = Selectors();
158
159 // Nonce
Junxiao Shi2dd711d2017-07-21 13:40:52 +0000160 val = m_wire.find(tlv::Nonce);
161 if (val == m_wire.elements_end()) {
162 BOOST_THROW_EXCEPTION(Error("Nonce element is missing"));
163 }
164 uint32_t nonce = 0;
165 if (val->value_size() != sizeof(nonce)) {
166 BOOST_THROW_EXCEPTION(Error("Nonce element is malformed"));
167 }
168 std::memcpy(&nonce, val->value(), sizeof(nonce));
169 m_nonce = nonce;
Junxiao Shi899277a2017-07-07 22:12:12 +0000170
171 // InterestLifetime
172 val = m_wire.find(tlv::InterestLifetime);
173 if (val != m_wire.elements_end()) {
174 m_interestLifetime = time::milliseconds(readNonNegativeInteger(*val));
175 }
176 else {
177 m_interestLifetime = DEFAULT_INTEREST_LIFETIME;
178 }
179
Junxiao Shi9c154cb2017-07-07 22:14:54 +0000180 // ForwardingHint
181 val = m_wire.find(tlv::ForwardingHint);
182 if (val != m_wire.elements_end()) {
183 m_forwardingHint.wireDecode(*val, false);
184 }
185 else {
186 m_forwardingHint = DelegationList();
187 }
188
Junxiao Shi899277a2017-07-07 22:12:12 +0000189 // Link
190 m_linkCached.reset();
191 val = m_wire.find(tlv::Data);
192 if (val != m_wire.elements_end()) {
193 m_link = (*val);
194 }
195 else {
196 m_link = Block();
197 }
198
199 // SelectedDelegation
200 val = m_wire.find(tlv::SelectedDelegation);
201 if (val != m_wire.elements_end()) {
202 if (!this->hasLink()) {
203 BOOST_THROW_EXCEPTION(Error("Interest contains SelectedDelegation, but no LINK object"));
204 }
205 uint64_t selectedDelegation = readNonNegativeInteger(*val);
206 if (selectedDelegation < uint64_t(Link::countDelegationsFromWire(m_link))) {
207 m_selectedDelegationIndex = static_cast<size_t>(selectedDelegation);
208 }
209 else {
210 BOOST_THROW_EXCEPTION(Error("Invalid selected delegation index when decoding Interest"));
211 }
212 }
213 else {
214 m_selectedDelegationIndex = INVALID_SELECTED_DELEGATION_INDEX;
215 }
Alexander Afanasyevc3932172014-07-10 18:53:56 -0700216}
217
Junxiao Shi899277a2017-07-07 22:12:12 +0000218// ---- matching ----
219
Alexander Afanasyev84681982014-01-03 13:26:09 -0800220bool
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700221Interest::matchesName(const Name& name) const
Jeff Thompson25b4e612013-10-10 16:03:24 -0700222{
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700223 if (name.size() < m_name.size())
224 return false;
225
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800226 if (!m_name.isPrefixOf(name))
Alexander Afanasyev84681982014-01-03 13:26:09 -0800227 return false;
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700228
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800229 if (getMinSuffixComponents() >= 0 &&
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700230 // name must include implicit digest
231 !(name.size() - m_name.size() >= static_cast<size_t>(getMinSuffixComponents())))
Alexander Afanasyev84681982014-01-03 13:26:09 -0800232 return false;
233
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800234 if (getMaxSuffixComponents() >= 0 &&
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700235 // name must include implicit digest
236 !(name.size() - m_name.size() <= static_cast<size_t>(getMaxSuffixComponents())))
Alexander Afanasyev84681982014-01-03 13:26:09 -0800237 return false;
238
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700239 if (!getExclude().empty() &&
240 name.size() > m_name.size() &&
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800241 getExclude().isExcluded(name[m_name.size()]))
Alexander Afanasyev84681982014-01-03 13:26:09 -0800242 return false;
243
244 return true;
Jeff Thompson25b4e612013-10-10 16:03:24 -0700245}
246
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700247bool
248Interest::matchesData(const Data& data) const
249{
Junxiao Shi42c23622014-07-03 00:55:11 -0700250 size_t interestNameLength = m_name.size();
251 const Name& dataName = data.getName();
252 size_t fullNameLength = dataName.size() + 1;
253
254 // check MinSuffixComponents
255 bool hasMinSuffixComponents = getMinSuffixComponents() >= 0;
256 size_t minSuffixComponents = hasMinSuffixComponents ?
257 static_cast<size_t>(getMinSuffixComponents()) : 0;
258 if (!(interestNameLength + minSuffixComponents <= fullNameLength))
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700259 return false;
Junxiao Shi42c23622014-07-03 00:55:11 -0700260
261 // check MaxSuffixComponents
262 bool hasMaxSuffixComponents = getMaxSuffixComponents() >= 0;
263 if (hasMaxSuffixComponents &&
264 !(interestNameLength + getMaxSuffixComponents() >= fullNameLength))
265 return false;
266
267 // check prefix
268 if (interestNameLength == fullNameLength) {
Alexander Afanasyev56860f52014-11-07 11:51:17 -0800269 if (m_name.get(-1).isImplicitSha256Digest()) {
270 if (m_name != data.getFullName())
Junxiao Shi42c23622014-07-03 00:55:11 -0700271 return false;
272 }
273 else {
274 // Interest Name is same length as Data full Name, but last component isn't digest
275 // so there's no possibility of matching
276 return false;
277 }
278 }
279 else {
280 // Interest Name is a strict prefix of Data full Name
281 if (!m_name.isPrefixOf(dataName))
282 return false;
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700283 }
284
Junxiao Shi42c23622014-07-03 00:55:11 -0700285 // check Exclude
286 // Exclude won't be violated if Interest Name is same as Data full Name
287 if (!getExclude().empty() && fullNameLength > interestNameLength) {
288 if (interestNameLength == fullNameLength - 1) {
289 // component to exclude is the digest
290 if (getExclude().isExcluded(data.getFullName().get(interestNameLength)))
291 return false;
292 // There's opportunity to inspect the Exclude filter and determine whether
293 // the digest would make a difference.
Junxiao Shi08d07082014-12-03 11:31:44 -0700294 // eg. "<NameComponent>AA</NameComponent><Any/>" doesn't exclude any digest -
295 // fullName not needed;
296 // "<Any/><NameComponent>AA</NameComponent>" and
297 // "<Any/><ImplicitSha256DigestComponent>ffffffffffffffffffffffffffffffff
298 // </ImplicitSha256DigestComponent>"
299 // excludes all digests - fullName not needed;
300 // "<Any/><ImplicitSha256DigestComponent>80000000000000000000000000000000
301 // </ImplicitSha256DigestComponent>"
302 // excludes some digests - fullName required
Junxiao Shi42c23622014-07-03 00:55:11 -0700303 // But Interests that contain the exact Data Name before digest and also
304 // contain Exclude filter is too rare to optimize for, so we request
Junxiao Shi68247832017-07-03 22:06:49 +0000305 // fullName no matter what's in the Exclude filter.
Junxiao Shi42c23622014-07-03 00:55:11 -0700306 }
307 else {
308 // component to exclude is not the digest
309 if (getExclude().isExcluded(dataName.get(interestNameLength)))
310 return false;
311 }
312 }
313
314 // check PublisherPublicKeyLocator
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700315 const KeyLocator& publisherPublicKeyLocator = this->getPublisherPublicKeyLocator();
316 if (!publisherPublicKeyLocator.empty()) {
317 const Signature& signature = data.getSignature();
318 const Block& signatureInfo = signature.getInfo();
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600319 Block::element_const_iterator it = signatureInfo.find(tlv::KeyLocator);
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700320 if (it == signatureInfo.elements_end()) {
321 return false;
322 }
323 if (publisherPublicKeyLocator.wireEncode() != *it) {
324 return false;
325 }
326 }
327
328 return true;
329}
330
Alexander Afanasyev1013fd02017-01-03 13:19:03 -0800331bool
332Interest::matchesInterest(const Interest& other) const
333{
Junxiao Shi2dd711d2017-07-21 13:40:52 +0000334 /// @todo #3162 match ForwardingHint field
Alexander Afanasyev1013fd02017-01-03 13:19:03 -0800335 return (this->getName() == other.getName() &&
336 this->getSelectors() == other.getSelectors());
337}
338
Junxiao Shi899277a2017-07-07 22:12:12 +0000339// ---- field accessors ----
340
341uint32_t
342Interest::getNonce() const
343{
Junxiao Shi2dd711d2017-07-21 13:40:52 +0000344 if (!m_nonce) {
345 m_nonce = random::generateWord32();
Junxiao Shic2ac5d22017-07-17 22:18:31 +0000346 }
Junxiao Shi2dd711d2017-07-21 13:40:52 +0000347 return *m_nonce;
Junxiao Shi899277a2017-07-07 22:12:12 +0000348}
349
350Interest&
351Interest::setNonce(uint32_t nonce)
352{
Junxiao Shi2dd711d2017-07-21 13:40:52 +0000353 m_nonce = nonce;
354 m_wire.reset();
Junxiao Shi899277a2017-07-07 22:12:12 +0000355 return *this;
356}
357
358void
359Interest::refreshNonce()
360{
361 if (!hasNonce())
362 return;
363
364 uint32_t oldNonce = getNonce();
365 uint32_t newNonce = oldNonce;
366 while (newNonce == oldNonce)
367 newNonce = random::generateWord32();
368
369 setNonce(newNonce);
370}
371
Eric Newberryb555b002017-05-17 00:30:44 -0700372Interest&
373Interest::setInterestLifetime(time::milliseconds interestLifetime)
374{
375 if (interestLifetime < time::milliseconds::zero()) {
376 BOOST_THROW_EXCEPTION(std::invalid_argument("InterestLifetime must be >= 0"));
377 }
378 m_interestLifetime = interestLifetime;
379 m_wire.reset();
380 return *this;
381}
382
Junxiao Shi9c154cb2017-07-07 22:14:54 +0000383Interest&
384Interest::setForwardingHint(const DelegationList& value)
385{
386 m_forwardingHint = value;
387 m_wire.reset();
388 return *this;
389}
390
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700391bool
392Interest::hasLink() const
393{
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700394 return m_link.hasWire();
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700395}
396
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700397const Link&
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700398Interest::getLink() const
399{
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700400 if (hasLink()) {
401 if (!m_linkCached) {
402 m_linkCached = make_shared<Link>(m_link);
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700403 }
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700404 return *m_linkCached;
405 }
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700406 BOOST_THROW_EXCEPTION(Error("There is no encapsulated link object"));
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700407}
408
409void
410Interest::setLink(const Block& link)
411{
412 m_link = link;
413 if (!link.hasWire()) {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700414 BOOST_THROW_EXCEPTION(Error("The given link does not have a wire format"));
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700415 }
416 m_wire.reset();
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700417 m_linkCached.reset();
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700418 this->unsetSelectedDelegation();
419}
420
421void
422Interest::unsetLink()
423{
424 m_link.reset();
425 m_wire.reset();
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700426 m_linkCached.reset();
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700427 this->unsetSelectedDelegation();
428}
429
430bool
431Interest::hasSelectedDelegation() const
432{
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700433 return m_selectedDelegationIndex != INVALID_SELECTED_DELEGATION_INDEX;
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700434}
435
436Name
437Interest::getSelectedDelegation() const
438{
439 if (!hasSelectedDelegation()) {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700440 BOOST_THROW_EXCEPTION(Error("There is no encapsulated selected delegation"));
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700441 }
442 return std::get<1>(Link::getDelegationFromWire(m_link, m_selectedDelegationIndex));
443}
444
445void
446Interest::setSelectedDelegation(const Name& delegationName)
447{
448 size_t delegationIndex = Link::findDelegationFromWire(m_link, delegationName);
449 if (delegationIndex != INVALID_SELECTED_DELEGATION_INDEX) {
450 m_selectedDelegationIndex = delegationIndex;
451 }
452 else {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700453 BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid selected delegation name"));
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700454 }
455 m_wire.reset();
456}
457
458void
459Interest::setSelectedDelegation(size_t delegationIndex)
460{
461 if (delegationIndex >= Link(m_link).getDelegations().size()) {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700462 BOOST_THROW_EXCEPTION(Error("Invalid selected delegation index"));
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700463 }
464 m_selectedDelegationIndex = delegationIndex;
465 m_wire.reset();
466}
467
468void
469Interest::unsetSelectedDelegation()
470{
471 m_selectedDelegationIndex = INVALID_SELECTED_DELEGATION_INDEX;
472 m_wire.reset();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700473}
474
Junxiao Shi899277a2017-07-07 22:12:12 +0000475// ---- operators ----
476
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700477std::ostream&
478operator<<(std::ostream& os, const Interest& interest)
Jeff Thompsonfe556862013-07-09 13:52:55 -0700479{
Alexander Afanasyev84681982014-01-03 13:26:09 -0800480 os << interest.getName();
Jeff Thompsonfe556862013-07-09 13:52:55 -0700481
Alexander Afanasyev84681982014-01-03 13:26:09 -0800482 char delim = '?';
483
484 if (interest.getMinSuffixComponents() >= 0) {
485 os << delim << "ndn.MinSuffixComponents=" << interest.getMinSuffixComponents();
486 delim = '&';
Jeff Thompsonfe556862013-07-09 13:52:55 -0700487 }
Alexander Afanasyev84681982014-01-03 13:26:09 -0800488 if (interest.getMaxSuffixComponents() >= 0) {
489 os << delim << "ndn.MaxSuffixComponents=" << interest.getMaxSuffixComponents();
490 delim = '&';
Jeff Thompson37527d62013-08-21 11:15:54 -0700491 }
Eric Newberryb555b002017-05-17 00:30:44 -0700492 if (interest.getChildSelector() != DEFAULT_CHILD_SELECTOR) {
Alexander Afanasyev84681982014-01-03 13:26:09 -0800493 os << delim << "ndn.ChildSelector=" << interest.getChildSelector();
494 delim = '&';
Jeff Thompson13e280b2013-12-03 13:12:23 -0800495 }
Alexander Afanasyev84681982014-01-03 13:26:09 -0800496 if (interest.getMustBeFresh()) {
497 os << delim << "ndn.MustBeFresh=" << interest.getMustBeFresh();
498 delim = '&';
Jeff Thompson13e280b2013-12-03 13:12:23 -0800499 }
Eric Newberryb555b002017-05-17 00:30:44 -0700500 if (interest.getInterestLifetime() != DEFAULT_INTEREST_LIFETIME) {
Alexander Afanasyeva0c5f832014-06-19 13:27:56 -0700501 os << delim << "ndn.InterestLifetime=" << interest.getInterestLifetime().count();
Alexander Afanasyev84681982014-01-03 13:26:09 -0800502 delim = '&';
503 }
504
Alexander Afanasyeve881e932014-06-08 14:47:03 +0300505 if (interest.hasNonce()) {
Alexander Afanasyev84681982014-01-03 13:26:09 -0800506 os << delim << "ndn.Nonce=" << interest.getNonce();
507 delim = '&';
508 }
509 if (!interest.getExclude().empty()) {
510 os << delim << "ndn.Exclude=" << interest.getExclude();
511 delim = '&';
512 }
513
514 return os;
Jeff Thompson13e280b2013-12-03 13:12:23 -0800515}
516
Junxiao Shi08d07082014-12-03 11:31:44 -0700517} // namespace ndn