blob: 2f54dcb20e06dde792a5950693a76839ea0b0305 [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 Shi42c23622014-07-03 00:55:11 -070024#include "util/crypto.hpp"
Junxiao Shiaf8eeea2014-03-31 20:10:56 -070025#include "data.hpp"
Alexander Afanasyev840139f2013-12-28 15:02:50 -080026
Davide Pesaventoe1789892017-02-26 15:50:52 -050027#include <cstring>
28
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 Shi899277a2017-07-07 22:12:12 +000038Interest::Interest(const Name& name, time::milliseconds interestLifetime)
Junxiao Shi2af905b2014-11-27 13:10:54 -070039 : m_name(name)
Junxiao Shi2af905b2014-11-27 13:10:54 -070040 , m_interestLifetime(interestLifetime)
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -070041 , m_selectedDelegationIndex(INVALID_SELECTED_DELEGATION_INDEX)
Junxiao Shi2af905b2014-11-27 13:10:54 -070042{
Junxiao Shi899277a2017-07-07 22:12:12 +000043 if (interestLifetime < time::milliseconds::zero()) {
44 BOOST_THROW_EXCEPTION(std::invalid_argument("InterestLifetime must be >= 0"));
45 }
Junxiao Shi2af905b2014-11-27 13:10:54 -070046}
47
Junxiao Shi2af905b2014-11-27 13:10:54 -070048Interest::Interest(const Block& wire)
49{
50 wireDecode(wire);
51}
52
Junxiao Shi899277a2017-07-07 22:12:12 +000053// ---- encode and decode ----
Alexander Afanasyev840139f2013-12-28 15:02:50 -080054
Junxiao Shi899277a2017-07-07 22:12:12 +000055template<encoding::Tag TAG>
56size_t
57Interest::wireEncode(EncodingImpl<TAG>& encoder) const
58{
59 size_t totalLength = 0;
60
61 // Interest ::= INTEREST-TYPE TLV-LENGTH
62 // Name
63 // Selectors?
64 // Nonce
65 // InterestLifetime?
Junxiao Shi9c154cb2017-07-07 22:14:54 +000066 // ForwardingHint?
Junxiao Shi899277a2017-07-07 22:12:12 +000067 // Link?
68 // SelectedDelegation?
69
70 // (reverse encoding)
71
72 // Link and SelectedDelegation
73 if (hasLink()) {
74 if (hasSelectedDelegation()) {
75 totalLength += prependNonNegativeIntegerBlock(encoder,
76 tlv::SelectedDelegation,
77 m_selectedDelegationIndex);
78 }
79 totalLength += encoder.prependBlock(m_link);
Alexander Afanasyeve881e932014-06-08 14:47:03 +030080 }
Junxiao Shi899277a2017-07-07 22:12:12 +000081 else {
82 BOOST_ASSERT(!hasSelectedDelegation());
83 }
84
Junxiao Shi9c154cb2017-07-07 22:14:54 +000085 // ForwardingHint
86 if (m_forwardingHint.size() > 0) {
87 totalLength += m_forwardingHint.wireEncode(encoder);
88 }
89
Junxiao Shi899277a2017-07-07 22:12:12 +000090 // InterestLifetime
91 if (getInterestLifetime() != DEFAULT_INTEREST_LIFETIME) {
92 totalLength += prependNonNegativeIntegerBlock(encoder,
93 tlv::InterestLifetime,
94 getInterestLifetime().count());
95 }
96
97 // Nonce
98 getNonce(); // to ensure that Nonce is properly set
99 totalLength += encoder.prependBlock(m_nonce);
100
101 // Selectors
102 if (hasSelectors()) {
103 totalLength += getSelectors().wireEncode(encoder);
104 }
105
106 // Name
107 totalLength += getName().wireEncode(encoder);
108
109 totalLength += encoder.prependVarNumber(totalLength);
110 totalLength += encoder.prependVarNumber(tlv::Interest);
111 return totalLength;
Alexander Afanasyev840139f2013-12-28 15:02:50 -0800112}
113
Junxiao Shi899277a2017-07-07 22:12:12 +0000114template size_t
115Interest::wireEncode<encoding::EncoderTag>(EncodingImpl<encoding::EncoderTag>& encoder) const;
116
117template size_t
118Interest::wireEncode<encoding::EstimatorTag>(EncodingImpl<encoding::EstimatorTag>& encoder) const;
119
120const Block&
121Interest::wireEncode() const
Alexander Afanasyeve881e932014-06-08 14:47:03 +0300122{
Junxiao Shi899277a2017-07-07 22:12:12 +0000123 if (m_wire.hasWire())
124 return m_wire;
125
126 EncodingEstimator estimator;
127 size_t estimatedSize = wireEncode(estimator);
128
129 EncodingBuffer buffer(estimatedSize, 0);
130 wireEncode(buffer);
131
132 // to ensure that Nonce block points to the right memory location
133 const_cast<Interest*>(this)->wireDecode(buffer.block());
134
135 return m_wire;
Alexander Afanasyeve881e932014-06-08 14:47:03 +0300136}
Alexander Afanasyev840139f2013-12-28 15:02:50 -0800137
Alexander Afanasyevc3932172014-07-10 18:53:56 -0700138void
Junxiao Shi899277a2017-07-07 22:12:12 +0000139Interest::wireDecode(const Block& wire)
Alexander Afanasyevc3932172014-07-10 18:53:56 -0700140{
Junxiao Shi899277a2017-07-07 22:12:12 +0000141 m_wire = wire;
142 m_wire.parse();
Alexander Afanasyevc3932172014-07-10 18:53:56 -0700143
Junxiao Shi899277a2017-07-07 22:12:12 +0000144 if (m_wire.type() != tlv::Interest)
145 BOOST_THROW_EXCEPTION(Error("Unexpected TLV number when decoding Interest"));
Alexander Afanasyevc3932172014-07-10 18:53:56 -0700146
Junxiao Shi899277a2017-07-07 22:12:12 +0000147 // Name
148 m_name.wireDecode(m_wire.get(tlv::Name));
149
150 // Selectors
151 Block::element_const_iterator val = m_wire.find(tlv::Selectors);
152 if (val != m_wire.elements_end()) {
153 m_selectors.wireDecode(*val);
154 }
155 else
156 m_selectors = Selectors();
157
158 // Nonce
159 m_nonce = m_wire.get(tlv::Nonce);
160
161 // InterestLifetime
162 val = m_wire.find(tlv::InterestLifetime);
163 if (val != m_wire.elements_end()) {
164 m_interestLifetime = time::milliseconds(readNonNegativeInteger(*val));
165 }
166 else {
167 m_interestLifetime = DEFAULT_INTEREST_LIFETIME;
168 }
169
Junxiao Shi9c154cb2017-07-07 22:14:54 +0000170 // ForwardingHint
171 val = m_wire.find(tlv::ForwardingHint);
172 if (val != m_wire.elements_end()) {
173 m_forwardingHint.wireDecode(*val, false);
174 }
175 else {
176 m_forwardingHint = DelegationList();
177 }
178
Junxiao Shi899277a2017-07-07 22:12:12 +0000179 // Link
180 m_linkCached.reset();
181 val = m_wire.find(tlv::Data);
182 if (val != m_wire.elements_end()) {
183 m_link = (*val);
184 }
185 else {
186 m_link = Block();
187 }
188
189 // SelectedDelegation
190 val = m_wire.find(tlv::SelectedDelegation);
191 if (val != m_wire.elements_end()) {
192 if (!this->hasLink()) {
193 BOOST_THROW_EXCEPTION(Error("Interest contains SelectedDelegation, but no LINK object"));
194 }
195 uint64_t selectedDelegation = readNonNegativeInteger(*val);
196 if (selectedDelegation < uint64_t(Link::countDelegationsFromWire(m_link))) {
197 m_selectedDelegationIndex = static_cast<size_t>(selectedDelegation);
198 }
199 else {
200 BOOST_THROW_EXCEPTION(Error("Invalid selected delegation index when decoding Interest"));
201 }
202 }
203 else {
204 m_selectedDelegationIndex = INVALID_SELECTED_DELEGATION_INDEX;
205 }
Alexander Afanasyevc3932172014-07-10 18:53:56 -0700206}
207
Junxiao Shi899277a2017-07-07 22:12:12 +0000208// ---- matching ----
209
Alexander Afanasyev84681982014-01-03 13:26:09 -0800210bool
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700211Interest::matchesName(const Name& name) const
Jeff Thompson25b4e612013-10-10 16:03:24 -0700212{
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700213 if (name.size() < m_name.size())
214 return false;
215
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800216 if (!m_name.isPrefixOf(name))
Alexander Afanasyev84681982014-01-03 13:26:09 -0800217 return false;
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700218
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800219 if (getMinSuffixComponents() >= 0 &&
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700220 // name must include implicit digest
221 !(name.size() - m_name.size() >= static_cast<size_t>(getMinSuffixComponents())))
Alexander Afanasyev84681982014-01-03 13:26:09 -0800222 return false;
223
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800224 if (getMaxSuffixComponents() >= 0 &&
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700225 // name must include implicit digest
226 !(name.size() - m_name.size() <= static_cast<size_t>(getMaxSuffixComponents())))
Alexander Afanasyev84681982014-01-03 13:26:09 -0800227 return false;
228
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700229 if (!getExclude().empty() &&
230 name.size() > m_name.size() &&
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800231 getExclude().isExcluded(name[m_name.size()]))
Alexander Afanasyev84681982014-01-03 13:26:09 -0800232 return false;
233
234 return true;
Jeff Thompson25b4e612013-10-10 16:03:24 -0700235}
236
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700237bool
238Interest::matchesData(const Data& data) const
239{
Junxiao Shi42c23622014-07-03 00:55:11 -0700240 size_t interestNameLength = m_name.size();
241 const Name& dataName = data.getName();
242 size_t fullNameLength = dataName.size() + 1;
243
244 // check MinSuffixComponents
245 bool hasMinSuffixComponents = getMinSuffixComponents() >= 0;
246 size_t minSuffixComponents = hasMinSuffixComponents ?
247 static_cast<size_t>(getMinSuffixComponents()) : 0;
248 if (!(interestNameLength + minSuffixComponents <= fullNameLength))
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700249 return false;
Junxiao Shi42c23622014-07-03 00:55:11 -0700250
251 // check MaxSuffixComponents
252 bool hasMaxSuffixComponents = getMaxSuffixComponents() >= 0;
253 if (hasMaxSuffixComponents &&
254 !(interestNameLength + getMaxSuffixComponents() >= fullNameLength))
255 return false;
256
257 // check prefix
258 if (interestNameLength == fullNameLength) {
Alexander Afanasyev56860f52014-11-07 11:51:17 -0800259 if (m_name.get(-1).isImplicitSha256Digest()) {
260 if (m_name != data.getFullName())
Junxiao Shi42c23622014-07-03 00:55:11 -0700261 return false;
262 }
263 else {
264 // Interest Name is same length as Data full Name, but last component isn't digest
265 // so there's no possibility of matching
266 return false;
267 }
268 }
269 else {
270 // Interest Name is a strict prefix of Data full Name
271 if (!m_name.isPrefixOf(dataName))
272 return false;
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700273 }
274
Junxiao Shi42c23622014-07-03 00:55:11 -0700275 // check Exclude
276 // Exclude won't be violated if Interest Name is same as Data full Name
277 if (!getExclude().empty() && fullNameLength > interestNameLength) {
278 if (interestNameLength == fullNameLength - 1) {
279 // component to exclude is the digest
280 if (getExclude().isExcluded(data.getFullName().get(interestNameLength)))
281 return false;
282 // There's opportunity to inspect the Exclude filter and determine whether
283 // the digest would make a difference.
Junxiao Shi08d07082014-12-03 11:31:44 -0700284 // eg. "<NameComponent>AA</NameComponent><Any/>" doesn't exclude any digest -
285 // fullName not needed;
286 // "<Any/><NameComponent>AA</NameComponent>" and
287 // "<Any/><ImplicitSha256DigestComponent>ffffffffffffffffffffffffffffffff
288 // </ImplicitSha256DigestComponent>"
289 // excludes all digests - fullName not needed;
290 // "<Any/><ImplicitSha256DigestComponent>80000000000000000000000000000000
291 // </ImplicitSha256DigestComponent>"
292 // excludes some digests - fullName required
Junxiao Shi42c23622014-07-03 00:55:11 -0700293 // But Interests that contain the exact Data Name before digest and also
294 // contain Exclude filter is too rare to optimize for, so we request
Junxiao Shi68247832017-07-03 22:06:49 +0000295 // fullName no matter what's in the Exclude filter.
Junxiao Shi42c23622014-07-03 00:55:11 -0700296 }
297 else {
298 // component to exclude is not the digest
299 if (getExclude().isExcluded(dataName.get(interestNameLength)))
300 return false;
301 }
302 }
303
304 // check PublisherPublicKeyLocator
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700305 const KeyLocator& publisherPublicKeyLocator = this->getPublisherPublicKeyLocator();
306 if (!publisherPublicKeyLocator.empty()) {
307 const Signature& signature = data.getSignature();
308 const Block& signatureInfo = signature.getInfo();
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600309 Block::element_const_iterator it = signatureInfo.find(tlv::KeyLocator);
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700310 if (it == signatureInfo.elements_end()) {
311 return false;
312 }
313 if (publisherPublicKeyLocator.wireEncode() != *it) {
314 return false;
315 }
316 }
317
318 return true;
319}
320
Alexander Afanasyev1013fd02017-01-03 13:19:03 -0800321bool
322Interest::matchesInterest(const Interest& other) const
323{
324 /// @todo #3162 match Link field
325 return (this->getName() == other.getName() &&
326 this->getSelectors() == other.getSelectors());
327}
328
Junxiao Shi899277a2017-07-07 22:12:12 +0000329// ---- field accessors ----
330
331uint32_t
332Interest::getNonce() const
333{
334 if (!m_nonce.hasWire())
335 const_cast<Interest*>(this)->setNonce(random::generateWord32());
336
337 if (m_nonce.value_size() == sizeof(uint32_t))
338 return *reinterpret_cast<const uint32_t*>(m_nonce.value());
339 else {
340 // for compatibility reasons. Should be removed eventually
341 return readNonNegativeInteger(m_nonce);
342 }
343}
344
345Interest&
346Interest::setNonce(uint32_t nonce)
347{
348 if (m_wire.hasWire() && m_nonce.value_size() == sizeof(uint32_t)) {
349 std::memcpy(const_cast<uint8_t*>(m_nonce.value()), &nonce, sizeof(nonce));
350 }
351 else {
352 m_nonce = makeBinaryBlock(tlv::Nonce,
353 reinterpret_cast<const uint8_t*>(&nonce),
354 sizeof(nonce));
355 m_wire.reset();
356 }
357 return *this;
358}
359
360void
361Interest::refreshNonce()
362{
363 if (!hasNonce())
364 return;
365
366 uint32_t oldNonce = getNonce();
367 uint32_t newNonce = oldNonce;
368 while (newNonce == oldNonce)
369 newNonce = random::generateWord32();
370
371 setNonce(newNonce);
372}
373
Eric Newberryb555b002017-05-17 00:30:44 -0700374Interest&
375Interest::setInterestLifetime(time::milliseconds interestLifetime)
376{
377 if (interestLifetime < time::milliseconds::zero()) {
378 BOOST_THROW_EXCEPTION(std::invalid_argument("InterestLifetime must be >= 0"));
379 }
380 m_interestLifetime = interestLifetime;
381 m_wire.reset();
382 return *this;
383}
384
Junxiao Shi9c154cb2017-07-07 22:14:54 +0000385Interest&
386Interest::setForwardingHint(const DelegationList& value)
387{
388 m_forwardingHint = value;
389 m_wire.reset();
390 return *this;
391}
392
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700393bool
394Interest::hasLink() const
395{
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700396 return m_link.hasWire();
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700397}
398
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700399const Link&
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700400Interest::getLink() const
401{
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700402 if (hasLink()) {
403 if (!m_linkCached) {
404 m_linkCached = make_shared<Link>(m_link);
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700405 }
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700406 return *m_linkCached;
407 }
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700408 BOOST_THROW_EXCEPTION(Error("There is no encapsulated link object"));
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700409}
410
411void
412Interest::setLink(const Block& link)
413{
414 m_link = link;
415 if (!link.hasWire()) {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700416 BOOST_THROW_EXCEPTION(Error("The given link does not have a wire format"));
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700417 }
418 m_wire.reset();
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700419 m_linkCached.reset();
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700420 this->unsetSelectedDelegation();
421}
422
423void
424Interest::unsetLink()
425{
426 m_link.reset();
427 m_wire.reset();
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700428 m_linkCached.reset();
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700429 this->unsetSelectedDelegation();
430}
431
432bool
433Interest::hasSelectedDelegation() const
434{
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700435 return m_selectedDelegationIndex != INVALID_SELECTED_DELEGATION_INDEX;
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700436}
437
438Name
439Interest::getSelectedDelegation() const
440{
441 if (!hasSelectedDelegation()) {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700442 BOOST_THROW_EXCEPTION(Error("There is no encapsulated selected delegation"));
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700443 }
444 return std::get<1>(Link::getDelegationFromWire(m_link, m_selectedDelegationIndex));
445}
446
447void
448Interest::setSelectedDelegation(const Name& delegationName)
449{
450 size_t delegationIndex = Link::findDelegationFromWire(m_link, delegationName);
451 if (delegationIndex != INVALID_SELECTED_DELEGATION_INDEX) {
452 m_selectedDelegationIndex = delegationIndex;
453 }
454 else {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700455 BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid selected delegation name"));
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700456 }
457 m_wire.reset();
458}
459
460void
461Interest::setSelectedDelegation(size_t delegationIndex)
462{
463 if (delegationIndex >= Link(m_link).getDelegations().size()) {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700464 BOOST_THROW_EXCEPTION(Error("Invalid selected delegation index"));
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700465 }
466 m_selectedDelegationIndex = delegationIndex;
467 m_wire.reset();
468}
469
470void
471Interest::unsetSelectedDelegation()
472{
473 m_selectedDelegationIndex = INVALID_SELECTED_DELEGATION_INDEX;
474 m_wire.reset();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700475}
476
Junxiao Shi899277a2017-07-07 22:12:12 +0000477// ---- operators ----
478
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700479std::ostream&
480operator<<(std::ostream& os, const Interest& interest)
Jeff Thompsonfe556862013-07-09 13:52:55 -0700481{
Alexander Afanasyev84681982014-01-03 13:26:09 -0800482 os << interest.getName();
Jeff Thompsonfe556862013-07-09 13:52:55 -0700483
Alexander Afanasyev84681982014-01-03 13:26:09 -0800484 char delim = '?';
485
486 if (interest.getMinSuffixComponents() >= 0) {
487 os << delim << "ndn.MinSuffixComponents=" << interest.getMinSuffixComponents();
488 delim = '&';
Jeff Thompsonfe556862013-07-09 13:52:55 -0700489 }
Alexander Afanasyev84681982014-01-03 13:26:09 -0800490 if (interest.getMaxSuffixComponents() >= 0) {
491 os << delim << "ndn.MaxSuffixComponents=" << interest.getMaxSuffixComponents();
492 delim = '&';
Jeff Thompson37527d62013-08-21 11:15:54 -0700493 }
Eric Newberryb555b002017-05-17 00:30:44 -0700494 if (interest.getChildSelector() != DEFAULT_CHILD_SELECTOR) {
Alexander Afanasyev84681982014-01-03 13:26:09 -0800495 os << delim << "ndn.ChildSelector=" << interest.getChildSelector();
496 delim = '&';
Jeff Thompson13e280b2013-12-03 13:12:23 -0800497 }
Alexander Afanasyev84681982014-01-03 13:26:09 -0800498 if (interest.getMustBeFresh()) {
499 os << delim << "ndn.MustBeFresh=" << interest.getMustBeFresh();
500 delim = '&';
Jeff Thompson13e280b2013-12-03 13:12:23 -0800501 }
Eric Newberryb555b002017-05-17 00:30:44 -0700502 if (interest.getInterestLifetime() != DEFAULT_INTEREST_LIFETIME) {
Alexander Afanasyeva0c5f832014-06-19 13:27:56 -0700503 os << delim << "ndn.InterestLifetime=" << interest.getInterestLifetime().count();
Alexander Afanasyev84681982014-01-03 13:26:09 -0800504 delim = '&';
505 }
506
Alexander Afanasyeve881e932014-06-08 14:47:03 +0300507 if (interest.hasNonce()) {
Alexander Afanasyev84681982014-01-03 13:26:09 -0800508 os << delim << "ndn.Nonce=" << interest.getNonce();
509 delim = '&';
510 }
511 if (!interest.getExclude().empty()) {
512 os << delim << "ndn.Exclude=" << interest.getExclude();
513 delim = '&';
514 }
515
516 return os;
Jeff Thompson13e280b2013-12-03 13:12:23 -0800517}
518
Junxiao Shi08d07082014-12-03 11:31:44 -0700519} // namespace ndn