blob: 8959881c018c52f49f22e69872e1e945d829ce3f [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
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 Shi2af905b2014-11-27 13:10:54 -070038Interest::Interest()
Eric Newberryb555b002017-05-17 00:30:44 -070039 : m_interestLifetime(DEFAULT_INTEREST_LIFETIME)
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -070040 , m_selectedDelegationIndex(INVALID_SELECTED_DELEGATION_INDEX)
Junxiao Shi2af905b2014-11-27 13:10:54 -070041{
42}
43
44Interest::Interest(const Name& name)
45 : m_name(name)
Eric Newberryb555b002017-05-17 00:30:44 -070046 , m_interestLifetime(DEFAULT_INTEREST_LIFETIME)
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -070047 , m_selectedDelegationIndex(INVALID_SELECTED_DELEGATION_INDEX)
Junxiao Shi2af905b2014-11-27 13:10:54 -070048{
49}
50
51Interest::Interest(const Name& name, const time::milliseconds& interestLifetime)
52 : m_name(name)
Junxiao Shi2af905b2014-11-27 13:10:54 -070053 , m_interestLifetime(interestLifetime)
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -070054 , m_selectedDelegationIndex(INVALID_SELECTED_DELEGATION_INDEX)
Junxiao Shi2af905b2014-11-27 13:10:54 -070055{
56}
57
Junxiao Shi2af905b2014-11-27 13:10:54 -070058Interest::Interest(const Block& wire)
59{
60 wireDecode(wire);
61}
62
Alexander Afanasyeve881e932014-06-08 14:47:03 +030063uint32_t
Alexander Afanasyev840139f2013-12-28 15:02:50 -080064Interest::getNonce() const
65{
Alexander Afanasyeve881e932014-06-08 14:47:03 +030066 if (!m_nonce.hasWire())
67 const_cast<Interest*>(this)->setNonce(random::generateWord32());
Alexander Afanasyev840139f2013-12-28 15:02:50 -080068
Alexander Afanasyeve881e932014-06-08 14:47:03 +030069 if (m_nonce.value_size() == sizeof(uint32_t))
70 return *reinterpret_cast<const uint32_t*>(m_nonce.value());
71 else {
72 // for compatibility reasons. Should be removed eventually
73 return readNonNegativeInteger(m_nonce);
74 }
Alexander Afanasyev840139f2013-12-28 15:02:50 -080075}
76
Alexander Afanasyeve881e932014-06-08 14:47:03 +030077Interest&
78Interest::setNonce(uint32_t nonce)
79{
80 if (m_wire.hasWire() && m_nonce.value_size() == sizeof(uint32_t)) {
81 std::memcpy(const_cast<uint8_t*>(m_nonce.value()), &nonce, sizeof(nonce));
82 }
83 else {
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070084 m_nonce = makeBinaryBlock(tlv::Nonce,
85 reinterpret_cast<const uint8_t*>(&nonce),
86 sizeof(nonce));
Alexander Afanasyeve881e932014-06-08 14:47:03 +030087 m_wire.reset();
88 }
89 return *this;
90}
Alexander Afanasyev840139f2013-12-28 15:02:50 -080091
Alexander Afanasyevc3932172014-07-10 18:53:56 -070092void
93Interest::refreshNonce()
94{
95 if (!hasNonce())
96 return;
97
98 uint32_t oldNonce = getNonce();
99 uint32_t newNonce = oldNonce;
100 while (newNonce == oldNonce)
101 newNonce = random::generateWord32();
102
103 setNonce(newNonce);
104}
105
Alexander Afanasyev84681982014-01-03 13:26:09 -0800106bool
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700107Interest::matchesName(const Name& name) const
Jeff Thompson25b4e612013-10-10 16:03:24 -0700108{
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700109 if (name.size() < m_name.size())
110 return false;
111
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800112 if (!m_name.isPrefixOf(name))
Alexander Afanasyev84681982014-01-03 13:26:09 -0800113 return false;
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700114
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800115 if (getMinSuffixComponents() >= 0 &&
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700116 // name must include implicit digest
117 !(name.size() - m_name.size() >= static_cast<size_t>(getMinSuffixComponents())))
Alexander Afanasyev84681982014-01-03 13:26:09 -0800118 return false;
119
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800120 if (getMaxSuffixComponents() >= 0 &&
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700121 // name must include implicit digest
122 !(name.size() - m_name.size() <= static_cast<size_t>(getMaxSuffixComponents())))
Alexander Afanasyev84681982014-01-03 13:26:09 -0800123 return false;
124
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700125 if (!getExclude().empty() &&
126 name.size() > m_name.size() &&
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800127 getExclude().isExcluded(name[m_name.size()]))
Alexander Afanasyev84681982014-01-03 13:26:09 -0800128 return false;
129
130 return true;
Jeff Thompson25b4e612013-10-10 16:03:24 -0700131}
132
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700133bool
134Interest::matchesData(const Data& data) const
135{
Junxiao Shi42c23622014-07-03 00:55:11 -0700136 size_t interestNameLength = m_name.size();
137 const Name& dataName = data.getName();
138 size_t fullNameLength = dataName.size() + 1;
139
140 // check MinSuffixComponents
141 bool hasMinSuffixComponents = getMinSuffixComponents() >= 0;
142 size_t minSuffixComponents = hasMinSuffixComponents ?
143 static_cast<size_t>(getMinSuffixComponents()) : 0;
144 if (!(interestNameLength + minSuffixComponents <= fullNameLength))
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700145 return false;
Junxiao Shi42c23622014-07-03 00:55:11 -0700146
147 // check MaxSuffixComponents
148 bool hasMaxSuffixComponents = getMaxSuffixComponents() >= 0;
149 if (hasMaxSuffixComponents &&
150 !(interestNameLength + getMaxSuffixComponents() >= fullNameLength))
151 return false;
152
153 // check prefix
154 if (interestNameLength == fullNameLength) {
Alexander Afanasyev56860f52014-11-07 11:51:17 -0800155 if (m_name.get(-1).isImplicitSha256Digest()) {
156 if (m_name != data.getFullName())
Junxiao Shi42c23622014-07-03 00:55:11 -0700157 return false;
158 }
159 else {
160 // Interest Name is same length as Data full Name, but last component isn't digest
161 // so there's no possibility of matching
162 return false;
163 }
164 }
165 else {
166 // Interest Name is a strict prefix of Data full Name
167 if (!m_name.isPrefixOf(dataName))
168 return false;
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700169 }
170
Junxiao Shi42c23622014-07-03 00:55:11 -0700171 // check Exclude
172 // Exclude won't be violated if Interest Name is same as Data full Name
173 if (!getExclude().empty() && fullNameLength > interestNameLength) {
174 if (interestNameLength == fullNameLength - 1) {
175 // component to exclude is the digest
176 if (getExclude().isExcluded(data.getFullName().get(interestNameLength)))
177 return false;
178 // There's opportunity to inspect the Exclude filter and determine whether
179 // the digest would make a difference.
Junxiao Shi08d07082014-12-03 11:31:44 -0700180 // eg. "<NameComponent>AA</NameComponent><Any/>" doesn't exclude any digest -
181 // fullName not needed;
182 // "<Any/><NameComponent>AA</NameComponent>" and
183 // "<Any/><ImplicitSha256DigestComponent>ffffffffffffffffffffffffffffffff
184 // </ImplicitSha256DigestComponent>"
185 // excludes all digests - fullName not needed;
186 // "<Any/><ImplicitSha256DigestComponent>80000000000000000000000000000000
187 // </ImplicitSha256DigestComponent>"
188 // excludes some digests - fullName required
Junxiao Shi42c23622014-07-03 00:55:11 -0700189 // But Interests that contain the exact Data Name before digest and also
190 // contain Exclude filter is too rare to optimize for, so we request
Junxiao Shi68247832017-07-03 22:06:49 +0000191 // fullName no matter what's in the Exclude filter.
Junxiao Shi42c23622014-07-03 00:55:11 -0700192 }
193 else {
194 // component to exclude is not the digest
195 if (getExclude().isExcluded(dataName.get(interestNameLength)))
196 return false;
197 }
198 }
199
200 // check PublisherPublicKeyLocator
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700201 const KeyLocator& publisherPublicKeyLocator = this->getPublisherPublicKeyLocator();
202 if (!publisherPublicKeyLocator.empty()) {
203 const Signature& signature = data.getSignature();
204 const Block& signatureInfo = signature.getInfo();
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600205 Block::element_const_iterator it = signatureInfo.find(tlv::KeyLocator);
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700206 if (it == signatureInfo.elements_end()) {
207 return false;
208 }
209 if (publisherPublicKeyLocator.wireEncode() != *it) {
210 return false;
211 }
212 }
213
214 return true;
215}
216
Alexander Afanasyev1013fd02017-01-03 13:19:03 -0800217bool
218Interest::matchesInterest(const Interest& other) const
219{
220 /// @todo #3162 match Link field
221 return (this->getName() == other.getName() &&
222 this->getSelectors() == other.getSelectors());
223}
224
Eric Newberryb555b002017-05-17 00:30:44 -0700225Interest&
226Interest::setInterestLifetime(time::milliseconds interestLifetime)
227{
228 if (interestLifetime < time::milliseconds::zero()) {
229 BOOST_THROW_EXCEPTION(std::invalid_argument("InterestLifetime must be >= 0"));
230 }
231 m_interestLifetime = interestLifetime;
232 m_wire.reset();
233 return *this;
234}
235
Alexander Afanasyev74633892015-02-08 18:08:46 -0800236template<encoding::Tag TAG>
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700237size_t
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700238Interest::wireEncode(EncodingImpl<TAG>& encoder) const
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700239{
240 size_t totalLength = 0;
241
242 // Interest ::= INTEREST-TYPE TLV-LENGTH
243 // Name
244 // Selectors?
245 // Nonce
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700246 // InterestLifetime?
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700247 // Link?
248 // SelectedDelegation?
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700249
250 // (reverse encoding)
251
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700252 if (hasLink()) {
253 if (hasSelectedDelegation()) {
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700254 totalLength += prependNonNegativeIntegerBlock(encoder,
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700255 tlv::SelectedDelegation,
256 m_selectedDelegationIndex);
257 }
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700258 totalLength += encoder.prependBlock(m_link);
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700259 }
260 else {
261 BOOST_ASSERT(!hasSelectedDelegation());
262 }
263
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700264 // InterestLifetime
Eric Newberryb555b002017-05-17 00:30:44 -0700265 if (getInterestLifetime() != DEFAULT_INTEREST_LIFETIME) {
266 totalLength += prependNonNegativeIntegerBlock(encoder,
267 tlv::InterestLifetime,
268 getInterestLifetime().count());
269 }
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700270
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700271 // Nonce
272 getNonce(); // to ensure that Nonce is properly set
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700273 totalLength += encoder.prependBlock(m_nonce);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700274
275 // Selectors
Eric Newberryb555b002017-05-17 00:30:44 -0700276 if (hasSelectors()) {
277 totalLength += getSelectors().wireEncode(encoder);
278 }
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700279
280 // Name
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700281 totalLength += getName().wireEncode(encoder);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700282
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700283 totalLength += encoder.prependVarNumber(totalLength);
284 totalLength += encoder.prependVarNumber(tlv::Interest);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700285 return totalLength;
286}
287
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700288template size_t
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700289Interest::wireEncode<encoding::EncoderTag>(EncodingImpl<encoding::EncoderTag>& encoder) const;
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700290
291template size_t
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700292Interest::wireEncode<encoding::EstimatorTag>(EncodingImpl<encoding::EstimatorTag>& encoder) const;
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700293
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700294const Block&
295Interest::wireEncode() const
296{
297 if (m_wire.hasWire())
298 return m_wire;
299
300 EncodingEstimator estimator;
301 size_t estimatedSize = wireEncode(estimator);
302
303 EncodingBuffer buffer(estimatedSize, 0);
304 wireEncode(buffer);
305
306 // to ensure that Nonce block points to the right memory location
307 const_cast<Interest*>(this)->wireDecode(buffer.block());
308
309 return m_wire;
310}
311
312void
313Interest::wireDecode(const Block& wire)
314{
315 m_wire = wire;
316 m_wire.parse();
317
318 // Interest ::= INTEREST-TYPE TLV-LENGTH
319 // Name
320 // Selectors?
321 // Nonce
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700322 // InterestLifetime?
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700323 // Link?
324 // SelectedDelegation?
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700325
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600326 if (m_wire.type() != tlv::Interest)
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700327 BOOST_THROW_EXCEPTION(Error("Unexpected TLV number when decoding Interest"));
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700328
329 // Name
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600330 m_name.wireDecode(m_wire.get(tlv::Name));
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700331
332 // Selectors
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600333 Block::element_const_iterator val = m_wire.find(tlv::Selectors);
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700334 if (val != m_wire.elements_end()) {
335 m_selectors.wireDecode(*val);
336 }
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700337 else
338 m_selectors = Selectors();
339
340 // Nonce
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600341 m_nonce = m_wire.get(tlv::Nonce);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700342
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700343 // InterestLifetime
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600344 val = m_wire.find(tlv::InterestLifetime);
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700345 if (val != m_wire.elements_end()) {
346 m_interestLifetime = time::milliseconds(readNonNegativeInteger(*val));
347 }
348 else {
349 m_interestLifetime = DEFAULT_INTEREST_LIFETIME;
350 }
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700351
352 // Link object
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700353 m_linkCached.reset();
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700354 val = m_wire.find(tlv::Data);
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700355 if (val != m_wire.elements_end()) {
356 m_link = (*val);
357 }
358 else {
359 m_link = Block();
360 }
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700361
362 // SelectedDelegation
363 val = m_wire.find(tlv::SelectedDelegation);
364 if (val != m_wire.elements_end()) {
365 if (!this->hasLink()) {
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700366 BOOST_THROW_EXCEPTION(Error("Interest contains SelectedDelegation, but no LINK object"));
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700367 }
368 uint64_t selectedDelegation = readNonNegativeInteger(*val);
369 if (selectedDelegation < uint64_t(Link::countDelegationsFromWire(m_link))) {
370 m_selectedDelegationIndex = static_cast<size_t>(selectedDelegation);
371 }
372 else {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700373 BOOST_THROW_EXCEPTION(Error("Invalid selected delegation index when decoding Interest"));
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700374 }
375 }
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700376 else {
377 m_selectedDelegationIndex = INVALID_SELECTED_DELEGATION_INDEX;
378 }
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700379}
380
381bool
382Interest::hasLink() const
383{
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700384 return m_link.hasWire();
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700385}
386
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700387const Link&
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700388Interest::getLink() const
389{
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700390 if (hasLink()) {
391 if (!m_linkCached) {
392 m_linkCached = make_shared<Link>(m_link);
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700393 }
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700394 return *m_linkCached;
395 }
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700396 BOOST_THROW_EXCEPTION(Error("There is no encapsulated link object"));
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700397}
398
399void
400Interest::setLink(const Block& link)
401{
402 m_link = link;
403 if (!link.hasWire()) {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700404 BOOST_THROW_EXCEPTION(Error("The given link does not have a wire format"));
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700405 }
406 m_wire.reset();
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700407 m_linkCached.reset();
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700408 this->unsetSelectedDelegation();
409}
410
411void
412Interest::unsetLink()
413{
414 m_link.reset();
415 m_wire.reset();
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700416 m_linkCached.reset();
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700417 this->unsetSelectedDelegation();
418}
419
420bool
421Interest::hasSelectedDelegation() const
422{
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700423 return m_selectedDelegationIndex != INVALID_SELECTED_DELEGATION_INDEX;
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700424}
425
426Name
427Interest::getSelectedDelegation() const
428{
429 if (!hasSelectedDelegation()) {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700430 BOOST_THROW_EXCEPTION(Error("There is no encapsulated selected delegation"));
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700431 }
432 return std::get<1>(Link::getDelegationFromWire(m_link, m_selectedDelegationIndex));
433}
434
435void
436Interest::setSelectedDelegation(const Name& delegationName)
437{
438 size_t delegationIndex = Link::findDelegationFromWire(m_link, delegationName);
439 if (delegationIndex != INVALID_SELECTED_DELEGATION_INDEX) {
440 m_selectedDelegationIndex = delegationIndex;
441 }
442 else {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700443 BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid selected delegation name"));
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700444 }
445 m_wire.reset();
446}
447
448void
449Interest::setSelectedDelegation(size_t delegationIndex)
450{
451 if (delegationIndex >= Link(m_link).getDelegations().size()) {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700452 BOOST_THROW_EXCEPTION(Error("Invalid selected delegation index"));
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700453 }
454 m_selectedDelegationIndex = delegationIndex;
455 m_wire.reset();
456}
457
458void
459Interest::unsetSelectedDelegation()
460{
461 m_selectedDelegationIndex = INVALID_SELECTED_DELEGATION_INDEX;
462 m_wire.reset();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700463}
464
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700465std::ostream&
466operator<<(std::ostream& os, const Interest& interest)
Jeff Thompsonfe556862013-07-09 13:52:55 -0700467{
Alexander Afanasyev84681982014-01-03 13:26:09 -0800468 os << interest.getName();
Jeff Thompsonfe556862013-07-09 13:52:55 -0700469
Alexander Afanasyev84681982014-01-03 13:26:09 -0800470 char delim = '?';
471
472 if (interest.getMinSuffixComponents() >= 0) {
473 os << delim << "ndn.MinSuffixComponents=" << interest.getMinSuffixComponents();
474 delim = '&';
Jeff Thompsonfe556862013-07-09 13:52:55 -0700475 }
Alexander Afanasyev84681982014-01-03 13:26:09 -0800476 if (interest.getMaxSuffixComponents() >= 0) {
477 os << delim << "ndn.MaxSuffixComponents=" << interest.getMaxSuffixComponents();
478 delim = '&';
Jeff Thompson37527d62013-08-21 11:15:54 -0700479 }
Eric Newberryb555b002017-05-17 00:30:44 -0700480 if (interest.getChildSelector() != DEFAULT_CHILD_SELECTOR) {
Alexander Afanasyev84681982014-01-03 13:26:09 -0800481 os << delim << "ndn.ChildSelector=" << interest.getChildSelector();
482 delim = '&';
Jeff Thompson13e280b2013-12-03 13:12:23 -0800483 }
Alexander Afanasyev84681982014-01-03 13:26:09 -0800484 if (interest.getMustBeFresh()) {
485 os << delim << "ndn.MustBeFresh=" << interest.getMustBeFresh();
486 delim = '&';
Jeff Thompson13e280b2013-12-03 13:12:23 -0800487 }
Eric Newberryb555b002017-05-17 00:30:44 -0700488 if (interest.getInterestLifetime() != DEFAULT_INTEREST_LIFETIME) {
Alexander Afanasyeva0c5f832014-06-19 13:27:56 -0700489 os << delim << "ndn.InterestLifetime=" << interest.getInterestLifetime().count();
Alexander Afanasyev84681982014-01-03 13:26:09 -0800490 delim = '&';
491 }
492
Alexander Afanasyeve881e932014-06-08 14:47:03 +0300493 if (interest.hasNonce()) {
Alexander Afanasyev84681982014-01-03 13:26:09 -0800494 os << delim << "ndn.Nonce=" << interest.getNonce();
495 delim = '&';
496 }
497 if (!interest.getExclude().empty()) {
498 os << delim << "ndn.Exclude=" << interest.getExclude();
499 delim = '&';
500 }
501
502 return os;
Jeff Thompson13e280b2013-12-03 13:12:23 -0800503}
504
Junxiao Shi08d07082014-12-03 11:31:44 -0700505} // namespace ndn