blob: a00bbc05d90f3a719d4491c61173471aa362f66e [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
22#ifndef NDN_INTEREST_HPP
Jeff Thompson2d27e2f2013-08-09 12:55:00 -070023#define NDN_INTEREST_HPP
Jeff Thompsonb7f95562013-07-03 18:36:42 -070024
Junxiao Shi9c154cb2017-07-07 22:14:54 +000025#include "delegation-list.hpp"
Junxiao Shi899277a2017-07-07 22:12:12 +000026#include "link.hpp"
Jeff Thompson53412192013-08-06 13:35:50 -070027#include "name.hpp"
Alexander Afanasyevc348f832014-02-17 16:35:17 -080028#include "selectors.hpp"
Alexander Afanasyeva3887ae2014-12-29 16:11:57 -080029#include "tag-host.hpp"
Junxiao Shi899277a2017-07-07 22:12:12 +000030#include "util/time.hpp"
Jeff Thompsonb7f95562013-07-03 18:36:42 -070031
32namespace ndn {
Alexander Afanasyevc348f832014-02-17 16:35:17 -080033
Junxiao Shiaf8eeea2014-03-31 20:10:56 -070034class Data;
35
Junxiao Shi7007a3c2014-11-20 22:37:55 -070036/** @var const unspecified_duration_type DEFAULT_INTEREST_LIFETIME;
37 * @brief default value for InterestLifetime
38 */
39const time::milliseconds DEFAULT_INTEREST_LIFETIME = time::milliseconds(4000);
Alexander Afanasyevc348f832014-02-17 16:35:17 -080040
Junxiao Shic2b8d242014-11-04 08:35:29 -070041/** @brief represents an Interest packet
Jeff Thompson8238d002013-07-10 11:56:49 -070042 */
Alexander Afanasyeva3887ae2014-12-29 16:11:57 -080043class Interest : public TagHost, public enable_shared_from_this<Interest>
Alexander Afanasyevc348f832014-02-17 16:35:17 -080044{
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070045public:
Junxiao Shic2b8d242014-11-04 08:35:29 -070046 class Error : public tlv::Error
47 {
48 public:
49 explicit
50 Error(const std::string& what)
51 : tlv::Error(what)
52 {
53 }
54 };
55
Junxiao Shi2af905b2014-11-27 13:10:54 -070056 /** @brief Create a new Interest with the given name and interest lifetime
Junxiao Shi899277a2017-07-07 22:12:12 +000057 * @throw std::invalid_argument InterestLifetime is negative
Junxiao Shi2af905b2014-11-27 13:10:54 -070058 * @warning In certain contexts that use Interest::shared_from_this(), Interest must be created
Junxiao Shi899277a2017-07-07 22:12:12 +000059 * using `make_shared`. Otherwise, .shared_from_this() will trigger undefined behavior.
Alexander Afanasyevc348f832014-02-17 16:35:17 -080060 */
Junxiao Shi909ffef2017-07-07 22:12:27 +000061 explicit
Junxiao Shi899277a2017-07-07 22:12:12 +000062 Interest(const Name& name = Name(), time::milliseconds interestLifetime = DEFAULT_INTEREST_LIFETIME);
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070063
Junxiao Shi2af905b2014-11-27 13:10:54 -070064 /** @brief Create from wire encoding
65 * @warning In certain contexts that use Interest::shared_from_this(), Interest must be created
Junxiao Shi899277a2017-07-07 22:12:12 +000066 * using `make_shared`. Otherwise, .shared_from_this() will trigger undefined behavior.
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070067 */
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -080068 explicit
Junxiao Shi2af905b2014-11-27 13:10:54 -070069 Interest(const Block& wire);
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -080070
Jeff Thompson1b4a7b12013-11-15 12:00:02 -080071 /**
Alexander Afanasyevc348f832014-02-17 16:35:17 -080072 * @brief Fast encoding or block size estimation
Jeff Thompson1b4a7b12013-11-15 12:00:02 -080073 */
Alexander Afanasyev74633892015-02-08 18:08:46 -080074 template<encoding::Tag TAG>
Alexander Afanasyev197e5652014-06-13 16:56:31 -070075 size_t
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070076 wireEncode(EncodingImpl<TAG>& encoder) const;
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -080077
Jeff Thompson1b4a7b12013-11-15 12:00:02 -080078 /**
Alexander Afanasyevc348f832014-02-17 16:35:17 -080079 * @brief Encode to a wire format
Jeff Thompson1b4a7b12013-11-15 12:00:02 -080080 */
Alexander Afanasyev197e5652014-06-13 16:56:31 -070081 const Block&
Alexander Afanasyev1eb961a2014-01-03 13:51:49 -080082 wireEncode() const;
Alexander Afanasyevc348f832014-02-17 16:35:17 -080083
Jeff Thompson1b4a7b12013-11-15 12:00:02 -080084 /**
Alexander Afanasyevc348f832014-02-17 16:35:17 -080085 * @brief Decode from the wire format
Jeff Thompson1b4a7b12013-11-15 12:00:02 -080086 */
Alexander Afanasyev197e5652014-06-13 16:56:31 -070087 void
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070088 wireDecode(const Block& wire);
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -080089
90 /**
91 * @brief Check if already has wire
92 */
Alexander Afanasyev197e5652014-06-13 16:56:31 -070093 bool
Junxiao Shi2af905b2014-11-27 13:10:54 -070094 hasWire() const
95 {
96 return m_wire.hasWire();
97 }
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070098
Jeff Thompsond9e278c2013-07-08 15:20:13 -070099 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700100 * @brief Encode the name according to the NDN URI Scheme
101 *
102 * If there are interest selectors, this method will append "?" and add the selectors as
103 * a query string. For example, "/test/name?ndn.ChildSelector=1"
Jeff Thompson13e280b2013-12-03 13:12:23 -0800104 */
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700105 std::string
Jeff Thompson13e280b2013-12-03 13:12:23 -0800106 toUri() const;
Jeff Thompsonb7f95562013-07-03 18:36:42 -0700107
Junxiao Shi2af905b2014-11-27 13:10:54 -0700108public: // matching
109 /** @brief Check if Interest, including selectors, matches the given @p name
110 * @param name The name to be matched. If this is a Data name, it shall contain the
111 * implicit digest component
Alexander Afanasyev84681982014-01-03 13:26:09 -0800112 */
113 bool
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700114 matchesName(const Name& name) const;
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800115
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700116 /**
117 * @brief Check if Interest can be satisfied by @p data.
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700118 *
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700119 * This method considers Name, MinSuffixComponents, MaxSuffixComponents,
120 * PublisherPublicKeyLocator, and Exclude.
121 * This method does not consider ChildSelector and MustBeFresh.
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700122 */
123 bool
124 matchesData(const Data& data) const;
125
Alexander Afanasyev1013fd02017-01-03 13:19:03 -0800126 /**
127 * @brief Check if Interest matches @p other interest
128 *
129 * Interest matches @p other if both have the same name, selectors, and link. Other fields
130 * (e.g., Nonce) may be different.
131 *
132 * @todo Implement distinguishing interests by link. The current implementation checks only
133 * name+selectors (Issue #3162).
134 */
135 bool
136 matchesInterest(const Interest& other) const;
137
Junxiao Shi899277a2017-07-07 22:12:12 +0000138public: // Name, Nonce, and Guiders
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700139 const Name&
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800140 getName() const
Jeff Thompsonc0486c12013-07-16 14:36:16 -0700141 {
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800142 return m_name;
143 }
144
145 Interest&
146 setName(const Name& name)
147 {
148 m_name = name;
149 m_wire.reset();
150 return *this;
Jeff Thompsonc0486c12013-07-16 14:36:16 -0700151 }
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700152
Junxiao Shi2af905b2014-11-27 13:10:54 -0700153 /** @brief Check if Nonce set
Alexander Afanasyeve881e932014-06-08 14:47:03 +0300154 */
155 bool
156 hasNonce() const
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800157 {
Alexander Afanasyeve881e932014-06-08 14:47:03 +0300158 return m_nonce.hasWire();
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800159 }
160
Junxiao Shi2af905b2014-11-27 13:10:54 -0700161 /** @brief Get Interest's nonce
Alexander Afanasyeve881e932014-06-08 14:47:03 +0300162 *
Junxiao Shi2af905b2014-11-27 13:10:54 -0700163 * If nonce was not set before this call, it will be automatically assigned to a random value
164 */
165 uint32_t
166 getNonce() const;
167
168 /** @brief Set Interest's nonce
169 *
170 * If wire format already exists, this call simply replaces nonce in the
171 * existing wire format, without resetting and recreating it.
Alexander Afanasyeve881e932014-06-08 14:47:03 +0300172 */
173 Interest&
174 setNonce(uint32_t nonce);
175
Junxiao Shi2af905b2014-11-27 13:10:54 -0700176 /** @brief Refresh nonce
Alexander Afanasyevc3932172014-07-10 18:53:56 -0700177 *
Junxiao Shi2af905b2014-11-27 13:10:54 -0700178 * It's guaranteed that new nonce value differs from the existing one.
Alexander Afanasyevc3932172014-07-10 18:53:56 -0700179 *
Junxiao Shi2af905b2014-11-27 13:10:54 -0700180 * If nonce is already set, it will be updated to a different random value.
181 * If nonce is not set, this method does nothing.
Alexander Afanasyevc3932172014-07-10 18:53:56 -0700182 */
183 void
184 refreshNonce();
185
Junxiao Shi899277a2017-07-07 22:12:12 +0000186 time::milliseconds
187 getInterestLifetime() const
188 {
189 return m_interestLifetime;
190 }
191
192 /**
193 * @brief Set Interest's lifetime
194 * @throw std::invalid_argument specified lifetime is < 0
195 */
196 Interest&
197 setInterestLifetime(time::milliseconds interestLifetime);
198
Junxiao Shi9c154cb2017-07-07 22:14:54 +0000199 const DelegationList&
200 getForwardingHint() const
201 {
202 return m_forwardingHint;
203 }
204
205 Interest&
206 setForwardingHint(const DelegationList& value);
207
Junxiao Shib2a70332017-07-07 22:15:03 +0000208 /** @brief modify ForwardingHint in-place
209 * @tparam Modifier a unary function that accepts DelegationList&
210 *
211 * This is equivalent to, but more efficient (avoids copying) than:
212 * @code
213 * auto fh = interest.getForwardingHint();
214 * modifier(fh);
215 * interest.setForwardingHint(fh);
216 * @endcode
217 */
218 template<typename Modifier>
219 Interest&
220 modifyForwardingHint(const Modifier& modifier)
221 {
222 modifier(m_forwardingHint);
223 m_wire.reset();
224 return *this;
225 }
226
Junxiao Shi2af905b2014-11-27 13:10:54 -0700227public: // Selectors
228 /**
229 * @return true if Interest has any selector present
230 */
231 bool
232 hasSelectors() const
233 {
234 return !m_selectors.empty();
235 }
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700236
Junxiao Shi2af905b2014-11-27 13:10:54 -0700237 const Selectors&
238 getSelectors() const
239 {
240 return m_selectors;
241 }
242
243 Interest&
244 setSelectors(const Selectors& selectors)
245 {
246 m_selectors = selectors;
247 m_wire.reset();
248 return *this;
249 }
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700250
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800251 int
252 getMinSuffixComponents() const
253 {
254 return m_selectors.getMinSuffixComponents();
255 }
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700256
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800257 Interest&
258 setMinSuffixComponents(int minSuffixComponents)
259 {
260 m_selectors.setMinSuffixComponents(minSuffixComponents);
261 m_wire.reset();
262 return *this;
263 }
264
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800265 int
266 getMaxSuffixComponents() const
267 {
268 return m_selectors.getMaxSuffixComponents();
269 }
270
271 Interest&
272 setMaxSuffixComponents(int maxSuffixComponents)
273 {
274 m_selectors.setMaxSuffixComponents(maxSuffixComponents);
275 m_wire.reset();
276 return *this;
277 }
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700278
Junxiao Shib332e782014-03-31 14:23:46 -0700279 const KeyLocator&
280 getPublisherPublicKeyLocator() const
281 {
282 return m_selectors.getPublisherPublicKeyLocator();
283 }
284
285 Interest&
286 setPublisherPublicKeyLocator(const KeyLocator& keyLocator)
287 {
288 m_selectors.setPublisherPublicKeyLocator(keyLocator);
289 m_wire.reset();
290 return *this;
291 }
292
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800293 const Exclude&
294 getExclude() const
295 {
296 return m_selectors.getExclude();
297 }
298
299 Interest&
300 setExclude(const Exclude& exclude)
301 {
302 m_selectors.setExclude(exclude);
303 m_wire.reset();
304 return *this;
305 }
306
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700307 int
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800308 getChildSelector() const
309 {
310 return m_selectors.getChildSelector();
311 }
312
313 Interest&
314 setChildSelector(int childSelector)
315 {
316 m_selectors.setChildSelector(childSelector);
317 m_wire.reset();
318 return *this;
319 }
320
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700321 int
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800322 getMustBeFresh() const
323 {
324 return m_selectors.getMustBeFresh();
325 }
326
327 Interest&
328 setMustBeFresh(bool mustBeFresh)
329 {
330 m_selectors.setMustBeFresh(mustBeFresh);
331 m_wire.reset();
332 return *this;
333 }
334
Junxiao Shi899277a2017-07-07 22:12:12 +0000335public: // Link and SelectedDelegation
336 /**
337 * @brief Check whether the Interest contains a Link object
338 * @return True if there is a link object, otherwise false
339 */
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700340 bool
Junxiao Shi899277a2017-07-07 22:12:12 +0000341 hasLink() const;
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700342
Junxiao Shi899277a2017-07-07 22:12:12 +0000343 /**
344 * @brief Get the link object for this interest
345 * @return The link object if there is one contained in this interest
346 * @throws Interest::Error if there is no link object contained in the interest
347 * @throws tlv::Error if the incorporated link object is malformed
348 */
349 const Link&
350 getLink() const;
351
352 /**
353 * @brief Set the link object for this interest
354 * @param link The link object that will be included in this interest (in wire format)
355 * @post !hasSelectedDelegation()
356 */
357 void
358 setLink(const Block& link);
359
360 /**
361 * @brief Delete the link object for this interest
362 * @post !hasLink()
363 */
364 void
365 unsetLink();
366
367 /**
368 * @brief Check whether the Interest includes a selected delegation
369 * @return True if there is a selected delegation, otherwise false
370 */
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700371 bool
Junxiao Shi899277a2017-07-07 22:12:12 +0000372 hasSelectedDelegation() const;
373
374 /**
375 * @brief Get the name of the selected delegation
376 * @return The name of the selected delegation
377 * @throw Error SelectedDelegation is not set.
378 */
379 Name
380 getSelectedDelegation() const;
381
382 /**
383 * @brief Set the selected delegation
384 * @param delegationName The name of the selected delegation
385 * @throw Error Link is not set.
386 * @throw std::invalid_argument @p delegationName does not exist in Link.
387 */
388 void
389 setSelectedDelegation(const Name& delegationName);
390
391 /**
392 * @brief Set the selected delegation
393 * @param delegationIndex The index of the selected delegation
394 * @throw Error Link is not set.
395 * @throw std::out_of_range @p delegationIndex is out of bound in Link.
396 */
397 void
398 setSelectedDelegation(size_t delegationIndex);
399
400 /**
401 * @brief Unset the selected delegation
402 */
403 void
404 unsetSelectedDelegation();
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700405
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800406private:
407 Name m_name;
408 Selectors m_selectors;
Alexander Afanasyeve881e932014-06-08 14:47:03 +0300409 mutable Block m_nonce;
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700410 time::milliseconds m_interestLifetime;
Junxiao Shi9c154cb2017-07-07 22:14:54 +0000411 DelegationList m_forwardingHint;
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800412
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700413 mutable Block m_link;
Alexander Afanasyevcac08382015-09-02 14:52:40 -0700414 mutable shared_ptr<Link> m_linkCached;
Spyridon Mastorakisc8188b32015-04-18 18:33:38 -0700415 size_t m_selectedDelegationIndex;
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800416 mutable Block m_wire;
Jeff Thompsonb7f95562013-07-03 18:36:42 -0700417};
Alexander Afanasyev84681982014-01-03 13:26:09 -0800418
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700419std::ostream&
420operator<<(std::ostream& os, const Interest& interest);
Alexander Afanasyev84681982014-01-03 13:26:09 -0800421
422inline std::string
423Interest::toUri() const
424{
425 std::ostringstream os;
426 os << *this;
427 return os.str();
428}
429
Junxiao Shi899277a2017-07-07 22:12:12 +0000430inline bool
431operator==(const Interest& lhs, const Interest& rhs)
432{
433 return lhs.wireEncode() == rhs.wireEncode();
434}
435
436inline bool
437operator!=(const Interest& lhs, const Interest& rhs)
438{
439 return !(lhs == rhs);
440}
441
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800442} // namespace ndn
443
444#endif // NDN_INTEREST_HPP