blob: fa58a33705707f4d5a7001738ba0703bd1e04175 [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Jeff Thompson47eecfc2013-07-07 22:56:46 -07002/**
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
Jeff Thompsonb7f95562013-07-03 18:36:42 -070027namespace ndn {
Alexander Afanasyev84681982014-01-03 13:26:09 -080028
Junxiao Shic2b8d242014-11-04 08:35:29 -070029BOOST_CONCEPT_ASSERT((boost::EqualityComparable<Interest>));
30BOOST_CONCEPT_ASSERT((WireEncodable<Interest>));
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070031BOOST_CONCEPT_ASSERT((WireEncodableWithEncodingBuffer<Interest>));
Junxiao Shic2b8d242014-11-04 08:35:29 -070032BOOST_CONCEPT_ASSERT((WireDecodable<Interest>));
33static_assert(std::is_base_of<tlv::Error, Interest::Error>::value,
34 "Interest::Error must inherit from tlv::Error");
35
Junxiao Shi2af905b2014-11-27 13:10:54 -070036Interest::Interest()
Alexander Afanasyev117f5ef2015-06-03 15:07:24 -070037 : m_interestLifetime(time::milliseconds::min())
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -070038 , m_selectedDelegationIndex(INVALID_SELECTED_DELEGATION_INDEX)
Junxiao Shi2af905b2014-11-27 13:10:54 -070039{
40}
41
42Interest::Interest(const Name& name)
43 : m_name(name)
Junxiao Shi2af905b2014-11-27 13:10:54 -070044 , m_interestLifetime(time::milliseconds::min())
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -070045 , m_selectedDelegationIndex(INVALID_SELECTED_DELEGATION_INDEX)
Junxiao Shi2af905b2014-11-27 13:10:54 -070046{
47}
48
49Interest::Interest(const Name& name, const time::milliseconds& interestLifetime)
50 : m_name(name)
Junxiao Shi2af905b2014-11-27 13:10:54 -070051 , m_interestLifetime(interestLifetime)
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -070052 , m_selectedDelegationIndex(INVALID_SELECTED_DELEGATION_INDEX)
Junxiao Shi2af905b2014-11-27 13:10:54 -070053{
54}
55
Junxiao Shi2af905b2014-11-27 13:10:54 -070056Interest::Interest(const Block& wire)
57{
58 wireDecode(wire);
59}
60
Alexander Afanasyeve881e932014-06-08 14:47:03 +030061uint32_t
Alexander Afanasyev840139f2013-12-28 15:02:50 -080062Interest::getNonce() const
63{
Alexander Afanasyeve881e932014-06-08 14:47:03 +030064 if (!m_nonce.hasWire())
65 const_cast<Interest*>(this)->setNonce(random::generateWord32());
Alexander Afanasyev840139f2013-12-28 15:02:50 -080066
Alexander Afanasyeve881e932014-06-08 14:47:03 +030067 if (m_nonce.value_size() == sizeof(uint32_t))
68 return *reinterpret_cast<const uint32_t*>(m_nonce.value());
69 else {
70 // for compatibility reasons. Should be removed eventually
71 return readNonNegativeInteger(m_nonce);
72 }
Alexander Afanasyev840139f2013-12-28 15:02:50 -080073}
74
Alexander Afanasyeve881e932014-06-08 14:47:03 +030075Interest&
76Interest::setNonce(uint32_t nonce)
77{
78 if (m_wire.hasWire() && m_nonce.value_size() == sizeof(uint32_t)) {
79 std::memcpy(const_cast<uint8_t*>(m_nonce.value()), &nonce, sizeof(nonce));
80 }
81 else {
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070082 m_nonce = makeBinaryBlock(tlv::Nonce,
83 reinterpret_cast<const uint8_t*>(&nonce),
84 sizeof(nonce));
Alexander Afanasyeve881e932014-06-08 14:47:03 +030085 m_wire.reset();
86 }
87 return *this;
88}
Alexander Afanasyev840139f2013-12-28 15:02:50 -080089
Alexander Afanasyevc3932172014-07-10 18:53:56 -070090void
91Interest::refreshNonce()
92{
93 if (!hasNonce())
94 return;
95
96 uint32_t oldNonce = getNonce();
97 uint32_t newNonce = oldNonce;
98 while (newNonce == oldNonce)
99 newNonce = random::generateWord32();
100
101 setNonce(newNonce);
102}
103
Alexander Afanasyev84681982014-01-03 13:26:09 -0800104bool
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700105Interest::matchesName(const Name& name) const
Jeff Thompson25b4e612013-10-10 16:03:24 -0700106{
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700107 if (name.size() < m_name.size())
108 return false;
109
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800110 if (!m_name.isPrefixOf(name))
Alexander Afanasyev84681982014-01-03 13:26:09 -0800111 return false;
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700112
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800113 if (getMinSuffixComponents() >= 0 &&
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700114 // name must include implicit digest
115 !(name.size() - m_name.size() >= static_cast<size_t>(getMinSuffixComponents())))
Alexander Afanasyev84681982014-01-03 13:26:09 -0800116 return false;
117
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800118 if (getMaxSuffixComponents() >= 0 &&
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700119 // name must include implicit digest
120 !(name.size() - m_name.size() <= static_cast<size_t>(getMaxSuffixComponents())))
Alexander Afanasyev84681982014-01-03 13:26:09 -0800121 return false;
122
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700123 if (!getExclude().empty() &&
124 name.size() > m_name.size() &&
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800125 getExclude().isExcluded(name[m_name.size()]))
Alexander Afanasyev84681982014-01-03 13:26:09 -0800126 return false;
127
128 return true;
Jeff Thompson25b4e612013-10-10 16:03:24 -0700129}
130
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700131bool
132Interest::matchesData(const Data& data) const
133{
Junxiao Shi42c23622014-07-03 00:55:11 -0700134 size_t interestNameLength = m_name.size();
135 const Name& dataName = data.getName();
136 size_t fullNameLength = dataName.size() + 1;
137
138 // check MinSuffixComponents
139 bool hasMinSuffixComponents = getMinSuffixComponents() >= 0;
140 size_t minSuffixComponents = hasMinSuffixComponents ?
141 static_cast<size_t>(getMinSuffixComponents()) : 0;
142 if (!(interestNameLength + minSuffixComponents <= fullNameLength))
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700143 return false;
Junxiao Shi42c23622014-07-03 00:55:11 -0700144
145 // check MaxSuffixComponents
146 bool hasMaxSuffixComponents = getMaxSuffixComponents() >= 0;
147 if (hasMaxSuffixComponents &&
148 !(interestNameLength + getMaxSuffixComponents() >= fullNameLength))
149 return false;
150
151 // check prefix
152 if (interestNameLength == fullNameLength) {
Alexander Afanasyev56860f52014-11-07 11:51:17 -0800153 if (m_name.get(-1).isImplicitSha256Digest()) {
154 if (m_name != data.getFullName())
Junxiao Shi42c23622014-07-03 00:55:11 -0700155 return false;
156 }
157 else {
158 // Interest Name is same length as Data full Name, but last component isn't digest
159 // so there's no possibility of matching
160 return false;
161 }
162 }
163 else {
164 // Interest Name is a strict prefix of Data full Name
165 if (!m_name.isPrefixOf(dataName))
166 return false;
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700167 }
168
Junxiao Shi42c23622014-07-03 00:55:11 -0700169 // check Exclude
170 // Exclude won't be violated if Interest Name is same as Data full Name
171 if (!getExclude().empty() && fullNameLength > interestNameLength) {
172 if (interestNameLength == fullNameLength - 1) {
173 // component to exclude is the digest
174 if (getExclude().isExcluded(data.getFullName().get(interestNameLength)))
175 return false;
176 // There's opportunity to inspect the Exclude filter and determine whether
177 // the digest would make a difference.
Junxiao Shi08d07082014-12-03 11:31:44 -0700178 // eg. "<NameComponent>AA</NameComponent><Any/>" doesn't exclude any digest -
179 // fullName not needed;
180 // "<Any/><NameComponent>AA</NameComponent>" and
181 // "<Any/><ImplicitSha256DigestComponent>ffffffffffffffffffffffffffffffff
182 // </ImplicitSha256DigestComponent>"
183 // excludes all digests - fullName not needed;
184 // "<Any/><ImplicitSha256DigestComponent>80000000000000000000000000000000
185 // </ImplicitSha256DigestComponent>"
186 // excludes some digests - fullName required
Junxiao Shi42c23622014-07-03 00:55:11 -0700187 // But Interests that contain the exact Data Name before digest and also
188 // contain Exclude filter is too rare to optimize for, so we request
189 // fullName no mater what's in the Exclude filter.
190 }
191 else {
192 // component to exclude is not the digest
193 if (getExclude().isExcluded(dataName.get(interestNameLength)))
194 return false;
195 }
196 }
197
198 // check PublisherPublicKeyLocator
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700199 const KeyLocator& publisherPublicKeyLocator = this->getPublisherPublicKeyLocator();
200 if (!publisherPublicKeyLocator.empty()) {
201 const Signature& signature = data.getSignature();
202 const Block& signatureInfo = signature.getInfo();
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600203 Block::element_const_iterator it = signatureInfo.find(tlv::KeyLocator);
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700204 if (it == signatureInfo.elements_end()) {
205 return false;
206 }
207 if (publisherPublicKeyLocator.wireEncode() != *it) {
208 return false;
209 }
210 }
211
212 return true;
213}
214
Alexander Afanasyev1013fd02017-01-03 13:19:03 -0800215bool
216Interest::matchesInterest(const Interest& other) const
217{
218 /// @todo #3162 match Link field
219 return (this->getName() == other.getName() &&
220 this->getSelectors() == other.getSelectors());
221}
222
Alexander Afanasyev74633892015-02-08 18:08:46 -0800223template<encoding::Tag TAG>
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700224size_t
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700225Interest::wireEncode(EncodingImpl<TAG>& encoder) const
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700226{
227 size_t totalLength = 0;
228
229 // Interest ::= INTEREST-TYPE TLV-LENGTH
230 // Name
231 // Selectors?
232 // Nonce
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700233 // InterestLifetime?
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700234 // Link?
235 // SelectedDelegation?
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700236
237 // (reverse encoding)
238
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700239 if (hasLink()) {
240 if (hasSelectedDelegation()) {
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700241 totalLength += prependNonNegativeIntegerBlock(encoder,
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700242 tlv::SelectedDelegation,
243 m_selectedDelegationIndex);
244 }
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700245 totalLength += encoder.prependBlock(m_link);
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700246 }
247 else {
248 BOOST_ASSERT(!hasSelectedDelegation());
249 }
250
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700251 // InterestLifetime
252 if (getInterestLifetime() >= time::milliseconds::zero() &&
253 getInterestLifetime() != DEFAULT_INTEREST_LIFETIME)
254 {
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700255 totalLength += prependNonNegativeIntegerBlock(encoder,
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600256 tlv::InterestLifetime,
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700257 getInterestLifetime().count());
258 }
259
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700260 // Nonce
261 getNonce(); // to ensure that Nonce is properly set
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700262 totalLength += encoder.prependBlock(m_nonce);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700263
264 // Selectors
265 if (hasSelectors())
266 {
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700267 totalLength += getSelectors().wireEncode(encoder);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700268 }
269
270 // Name
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700271 totalLength += getName().wireEncode(encoder);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700272
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700273 totalLength += encoder.prependVarNumber(totalLength);
274 totalLength += encoder.prependVarNumber(tlv::Interest);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700275 return totalLength;
276}
277
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700278template size_t
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700279Interest::wireEncode<encoding::EncoderTag>(EncodingImpl<encoding::EncoderTag>& encoder) const;
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700280
281template size_t
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700282Interest::wireEncode<encoding::EstimatorTag>(EncodingImpl<encoding::EstimatorTag>& encoder) const;
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700283
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700284const Block&
285Interest::wireEncode() const
286{
287 if (m_wire.hasWire())
288 return m_wire;
289
290 EncodingEstimator estimator;
291 size_t estimatedSize = wireEncode(estimator);
292
293 EncodingBuffer buffer(estimatedSize, 0);
294 wireEncode(buffer);
295
296 // to ensure that Nonce block points to the right memory location
297 const_cast<Interest*>(this)->wireDecode(buffer.block());
298
299 return m_wire;
300}
301
302void
303Interest::wireDecode(const Block& wire)
304{
305 m_wire = wire;
306 m_wire.parse();
307
308 // Interest ::= INTEREST-TYPE TLV-LENGTH
309 // Name
310 // Selectors?
311 // Nonce
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700312 // InterestLifetime?
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700313 // Link?
314 // SelectedDelegation?
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700315
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600316 if (m_wire.type() != tlv::Interest)
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700317 BOOST_THROW_EXCEPTION(Error("Unexpected TLV number when decoding Interest"));
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700318
319 // Name
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600320 m_name.wireDecode(m_wire.get(tlv::Name));
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700321
322 // Selectors
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600323 Block::element_const_iterator val = m_wire.find(tlv::Selectors);
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700324 if (val != m_wire.elements_end()) {
325 m_selectors.wireDecode(*val);
326 }
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700327 else
328 m_selectors = Selectors();
329
330 // Nonce
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600331 m_nonce = m_wire.get(tlv::Nonce);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700332
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700333 // InterestLifetime
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600334 val = m_wire.find(tlv::InterestLifetime);
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700335 if (val != m_wire.elements_end()) {
336 m_interestLifetime = time::milliseconds(readNonNegativeInteger(*val));
337 }
338 else {
339 m_interestLifetime = DEFAULT_INTEREST_LIFETIME;
340 }
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700341
342 // Link object
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700343 m_linkCached.reset();
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700344 val = m_wire.find(tlv::Data);
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700345 if (val != m_wire.elements_end()) {
346 m_link = (*val);
347 }
348 else {
349 m_link = Block();
350 }
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700351
352 // SelectedDelegation
353 val = m_wire.find(tlv::SelectedDelegation);
354 if (val != m_wire.elements_end()) {
355 if (!this->hasLink()) {
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700356 BOOST_THROW_EXCEPTION(Error("Interest contains SelectedDelegation, but no LINK object"));
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700357 }
358 uint64_t selectedDelegation = readNonNegativeInteger(*val);
359 if (selectedDelegation < uint64_t(Link::countDelegationsFromWire(m_link))) {
360 m_selectedDelegationIndex = static_cast<size_t>(selectedDelegation);
361 }
362 else {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700363 BOOST_THROW_EXCEPTION(Error("Invalid selected delegation index when decoding Interest"));
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700364 }
365 }
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700366 else {
367 m_selectedDelegationIndex = INVALID_SELECTED_DELEGATION_INDEX;
368 }
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700369}
370
371bool
372Interest::hasLink() const
373{
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700374 return m_link.hasWire();
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700375}
376
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700377const Link&
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700378Interest::getLink() const
379{
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700380 if (hasLink()) {
381 if (!m_linkCached) {
382 m_linkCached = make_shared<Link>(m_link);
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700383 }
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700384 return *m_linkCached;
385 }
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700386 BOOST_THROW_EXCEPTION(Error("There is no encapsulated link object"));
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700387}
388
389void
390Interest::setLink(const Block& link)
391{
392 m_link = link;
393 if (!link.hasWire()) {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700394 BOOST_THROW_EXCEPTION(Error("The given link does not have a wire format"));
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700395 }
396 m_wire.reset();
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700397 m_linkCached.reset();
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700398 this->unsetSelectedDelegation();
399}
400
401void
402Interest::unsetLink()
403{
404 m_link.reset();
405 m_wire.reset();
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700406 m_linkCached.reset();
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700407 this->unsetSelectedDelegation();
408}
409
410bool
411Interest::hasSelectedDelegation() const
412{
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700413 return m_selectedDelegationIndex != INVALID_SELECTED_DELEGATION_INDEX;
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700414}
415
416Name
417Interest::getSelectedDelegation() const
418{
419 if (!hasSelectedDelegation()) {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700420 BOOST_THROW_EXCEPTION(Error("There is no encapsulated selected delegation"));
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700421 }
422 return std::get<1>(Link::getDelegationFromWire(m_link, m_selectedDelegationIndex));
423}
424
425void
426Interest::setSelectedDelegation(const Name& delegationName)
427{
428 size_t delegationIndex = Link::findDelegationFromWire(m_link, delegationName);
429 if (delegationIndex != INVALID_SELECTED_DELEGATION_INDEX) {
430 m_selectedDelegationIndex = delegationIndex;
431 }
432 else {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700433 BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid selected delegation name"));
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700434 }
435 m_wire.reset();
436}
437
438void
439Interest::setSelectedDelegation(size_t delegationIndex)
440{
441 if (delegationIndex >= Link(m_link).getDelegations().size()) {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700442 BOOST_THROW_EXCEPTION(Error("Invalid selected delegation index"));
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700443 }
444 m_selectedDelegationIndex = delegationIndex;
445 m_wire.reset();
446}
447
448void
449Interest::unsetSelectedDelegation()
450{
451 m_selectedDelegationIndex = INVALID_SELECTED_DELEGATION_INDEX;
452 m_wire.reset();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700453}
454
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700455std::ostream&
456operator<<(std::ostream& os, const Interest& interest)
Jeff Thompsonfe556862013-07-09 13:52:55 -0700457{
Alexander Afanasyev84681982014-01-03 13:26:09 -0800458 os << interest.getName();
Jeff Thompsonfe556862013-07-09 13:52:55 -0700459
Alexander Afanasyev84681982014-01-03 13:26:09 -0800460 char delim = '?';
461
462 if (interest.getMinSuffixComponents() >= 0) {
463 os << delim << "ndn.MinSuffixComponents=" << interest.getMinSuffixComponents();
464 delim = '&';
Jeff Thompsonfe556862013-07-09 13:52:55 -0700465 }
Alexander Afanasyev84681982014-01-03 13:26:09 -0800466 if (interest.getMaxSuffixComponents() >= 0) {
467 os << delim << "ndn.MaxSuffixComponents=" << interest.getMaxSuffixComponents();
468 delim = '&';
Jeff Thompson37527d62013-08-21 11:15:54 -0700469 }
Alexander Afanasyev84681982014-01-03 13:26:09 -0800470 if (interest.getChildSelector() >= 0) {
471 os << delim << "ndn.ChildSelector=" << interest.getChildSelector();
472 delim = '&';
Jeff Thompson13e280b2013-12-03 13:12:23 -0800473 }
Alexander Afanasyev84681982014-01-03 13:26:09 -0800474 if (interest.getMustBeFresh()) {
475 os << delim << "ndn.MustBeFresh=" << interest.getMustBeFresh();
476 delim = '&';
Jeff Thompson13e280b2013-12-03 13:12:23 -0800477 }
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700478 if (interest.getInterestLifetime() >= time::milliseconds::zero()
479 && interest.getInterestLifetime() != DEFAULT_INTEREST_LIFETIME) {
Alexander Afanasyeva0c5f832014-06-19 13:27:56 -0700480 os << delim << "ndn.InterestLifetime=" << interest.getInterestLifetime().count();
Alexander Afanasyev84681982014-01-03 13:26:09 -0800481 delim = '&';
482 }
483
Alexander Afanasyeve881e932014-06-08 14:47:03 +0300484 if (interest.hasNonce()) {
Alexander Afanasyev84681982014-01-03 13:26:09 -0800485 os << delim << "ndn.Nonce=" << interest.getNonce();
486 delim = '&';
487 }
488 if (!interest.getExclude().empty()) {
489 os << delim << "ndn.Exclude=" << interest.getExclude();
490 delim = '&';
491 }
492
493 return os;
Jeff Thompson13e280b2013-12-03 13:12:23 -0800494}
495
Junxiao Shi08d07082014-12-03 11:31:44 -0700496} // namespace ndn