interest.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
22 #include "interest.hpp"
23 #include "util/random.hpp"
24 #include "util/crypto.hpp"
25 #include "data.hpp"
26 
27 namespace ndn {
28 
29 BOOST_CONCEPT_ASSERT((boost::EqualityComparable<Interest>));
30 BOOST_CONCEPT_ASSERT((WireEncodable<Interest>));
32 BOOST_CONCEPT_ASSERT((WireDecodable<Interest>));
33 static_assert(std::is_base_of<tlv::Error, Interest::Error>::value,
34  "Interest::Error must inherit from tlv::Error");
35 
37  : m_interestLifetime(time::milliseconds::min())
38  , m_selectedDelegationIndex(INVALID_SELECTED_DELEGATION_INDEX)
39 {
40 }
41 
43  : m_name(name)
44  , m_interestLifetime(time::milliseconds::min())
45  , m_selectedDelegationIndex(INVALID_SELECTED_DELEGATION_INDEX)
46 {
47 }
48 
49 Interest::Interest(const Name& name, const time::milliseconds& interestLifetime)
50  : m_name(name)
51  , m_interestLifetime(interestLifetime)
52  , m_selectedDelegationIndex(INVALID_SELECTED_DELEGATION_INDEX)
53 {
54 }
55 
57 {
58  wireDecode(wire);
59 }
60 
61 uint32_t
63 {
64  if (!m_nonce.hasWire())
65  const_cast<Interest*>(this)->setNonce(random::generateWord32());
66 
67  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  }
73 }
74 
75 Interest&
76 Interest::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 {
82  m_nonce = makeBinaryBlock(tlv::Nonce,
83  reinterpret_cast<const uint8_t*>(&nonce),
84  sizeof(nonce));
85  m_wire.reset();
86  }
87  return *this;
88 }
89 
90 void
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 
104 bool
105 Interest::matchesName(const Name& name) const
106 {
107  if (name.size() < m_name.size())
108  return false;
109 
110  if (!m_name.isPrefixOf(name))
111  return false;
112 
113  if (getMinSuffixComponents() >= 0 &&
114  // name must include implicit digest
115  !(name.size() - m_name.size() >= static_cast<size_t>(getMinSuffixComponents())))
116  return false;
117 
118  if (getMaxSuffixComponents() >= 0 &&
119  // name must include implicit digest
120  !(name.size() - m_name.size() <= static_cast<size_t>(getMaxSuffixComponents())))
121  return false;
122 
123  if (!getExclude().empty() &&
124  name.size() > m_name.size() &&
125  getExclude().isExcluded(name[m_name.size()]))
126  return false;
127 
128  return true;
129 }
130 
131 bool
132 Interest::matchesData(const Data& data) const
133 {
134  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))
143  return false;
144 
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) {
153  if (m_name.get(-1).isImplicitSha256Digest()) {
154  if (m_name != data.getFullName())
155  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;
167  }
168 
169  // 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.
178  // 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
187  // 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
199  const KeyLocator& publisherPublicKeyLocator = this->getPublisherPublicKeyLocator();
200  if (!publisherPublicKeyLocator.empty()) {
201  const Signature& signature = data.getSignature();
202  const Block& signatureInfo = signature.getInfo();
204  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 
215 bool
217 {
219  return (this->getName() == other.getName() &&
220  this->getSelectors() == other.getSelectors());
221 }
222 
223 template<encoding::Tag TAG>
224 size_t
225 Interest::wireEncode(EncodingImpl<TAG>& encoder) const
226 {
227  size_t totalLength = 0;
228 
229  // Interest ::= INTEREST-TYPE TLV-LENGTH
230  // Name
231  // Selectors?
232  // Nonce
233  // InterestLifetime?
234  // Link?
235  // SelectedDelegation?
236 
237  // (reverse encoding)
238 
239  if (hasLink()) {
240  if (hasSelectedDelegation()) {
241  totalLength += prependNonNegativeIntegerBlock(encoder,
243  m_selectedDelegationIndex);
244  }
245  totalLength += encoder.prependBlock(m_link);
246  }
247  else {
248  BOOST_ASSERT(!hasSelectedDelegation());
249  }
250 
251  // InterestLifetime
252  if (getInterestLifetime() >= time::milliseconds::zero() &&
254  {
255  totalLength += prependNonNegativeIntegerBlock(encoder,
257  getInterestLifetime().count());
258  }
259 
260  // Nonce
261  getNonce(); // to ensure that Nonce is properly set
262  totalLength += encoder.prependBlock(m_nonce);
263 
264  // Selectors
265  if (hasSelectors())
266  {
267  totalLength += getSelectors().wireEncode(encoder);
268  }
269 
270  // Name
271  totalLength += getName().wireEncode(encoder);
272 
273  totalLength += encoder.prependVarNumber(totalLength);
274  totalLength += encoder.prependVarNumber(tlv::Interest);
275  return totalLength;
276 }
277 
278 template size_t
279 Interest::wireEncode<encoding::EncoderTag>(EncodingImpl<encoding::EncoderTag>& encoder) const;
280 
281 template size_t
282 Interest::wireEncode<encoding::EstimatorTag>(EncodingImpl<encoding::EstimatorTag>& encoder) const;
283 
284 const Block&
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 
302 void
304 {
305  m_wire = wire;
306  m_wire.parse();
307 
308  // Interest ::= INTEREST-TYPE TLV-LENGTH
309  // Name
310  // Selectors?
311  // Nonce
312  // InterestLifetime?
313  // Link?
314  // SelectedDelegation?
315 
316  if (m_wire.type() != tlv::Interest)
317  BOOST_THROW_EXCEPTION(Error("Unexpected TLV number when decoding Interest"));
318 
319  // Name
320  m_name.wireDecode(m_wire.get(tlv::Name));
321 
322  // Selectors
324  if (val != m_wire.elements_end()) {
325  m_selectors.wireDecode(*val);
326  }
327  else
328  m_selectors = Selectors();
329 
330  // Nonce
331  m_nonce = m_wire.get(tlv::Nonce);
332 
333  // InterestLifetime
334  val = m_wire.find(tlv::InterestLifetime);
335  if (val != m_wire.elements_end()) {
336  m_interestLifetime = time::milliseconds(readNonNegativeInteger(*val));
337  }
338  else {
339  m_interestLifetime = DEFAULT_INTEREST_LIFETIME;
340  }
341 
342  // Link object
343  m_linkCached.reset();
344  val = m_wire.find(tlv::Data);
345  if (val != m_wire.elements_end()) {
346  m_link = (*val);
347  }
348  else {
349  m_link = Block();
350  }
351 
352  // SelectedDelegation
353  val = m_wire.find(tlv::SelectedDelegation);
354  if (val != m_wire.elements_end()) {
355  if (!this->hasLink()) {
356  BOOST_THROW_EXCEPTION(Error("Interest contains SelectedDelegation, but no LINK object"));
357  }
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 {
363  BOOST_THROW_EXCEPTION(Error("Invalid selected delegation index when decoding Interest"));
364  }
365  }
366  else {
367  m_selectedDelegationIndex = INVALID_SELECTED_DELEGATION_INDEX;
368  }
369 }
370 
371 bool
373 {
374  return m_link.hasWire();
375 }
376 
377 const Link&
379 {
380  if (hasLink()) {
381  if (!m_linkCached) {
382  m_linkCached = make_shared<Link>(m_link);
383  }
384  return *m_linkCached;
385  }
386  BOOST_THROW_EXCEPTION(Error("There is no encapsulated link object"));
387 }
388 
389 void
391 {
392  m_link = link;
393  if (!link.hasWire()) {
394  BOOST_THROW_EXCEPTION(Error("The given link does not have a wire format"));
395  }
396  m_wire.reset();
397  m_linkCached.reset();
398  this->unsetSelectedDelegation();
399 }
400 
401 void
403 {
404  m_link.reset();
405  m_wire.reset();
406  m_linkCached.reset();
407  this->unsetSelectedDelegation();
408 }
409 
410 bool
412 {
413  return m_selectedDelegationIndex != INVALID_SELECTED_DELEGATION_INDEX;
414 }
415 
416 Name
418 {
419  if (!hasSelectedDelegation()) {
420  BOOST_THROW_EXCEPTION(Error("There is no encapsulated selected delegation"));
421  }
422  return std::get<1>(Link::getDelegationFromWire(m_link, m_selectedDelegationIndex));
423 }
424 
425 void
426 Interest::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 {
433  BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid selected delegation name"));
434  }
435  m_wire.reset();
436 }
437 
438 void
439 Interest::setSelectedDelegation(size_t delegationIndex)
440 {
441  if (delegationIndex >= Link(m_link).getDelegations().size()) {
442  BOOST_THROW_EXCEPTION(Error("Invalid selected delegation index"));
443  }
444  m_selectedDelegationIndex = delegationIndex;
445  m_wire.reset();
446 }
447 
448 void
450 {
451  m_selectedDelegationIndex = INVALID_SELECTED_DELEGATION_INDEX;
452  m_wire.reset();
453 }
454 
455 std::ostream&
456 operator<<(std::ostream& os, const Interest& interest)
457 {
458  os << interest.getName();
459 
460  char delim = '?';
461 
462  if (interest.getMinSuffixComponents() >= 0) {
463  os << delim << "ndn.MinSuffixComponents=" << interest.getMinSuffixComponents();
464  delim = '&';
465  }
466  if (interest.getMaxSuffixComponents() >= 0) {
467  os << delim << "ndn.MaxSuffixComponents=" << interest.getMaxSuffixComponents();
468  delim = '&';
469  }
470  if (interest.getChildSelector() >= 0) {
471  os << delim << "ndn.ChildSelector=" << interest.getChildSelector();
472  delim = '&';
473  }
474  if (interest.getMustBeFresh()) {
475  os << delim << "ndn.MustBeFresh=" << interest.getMustBeFresh();
476  delim = '&';
477  }
478  if (interest.getInterestLifetime() >= time::milliseconds::zero()
480  os << delim << "ndn.InterestLifetime=" << interest.getInterestLifetime().count();
481  delim = '&';
482  }
483 
484  if (interest.hasNonce()) {
485  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;
494 }
495 
496 } // namespace ndn
void wireDecode(const Block &wire)
Decode the input from wire format.
Definition: selectors.cpp:135
size_t wireEncode(EncodingImpl< TAG > &encoder) const
prepend wire encoding
Definition: key-locator.cpp:52
int getMinSuffixComponents() const
Definition: interest.hpp:311
bool hasSelectedDelegation() const
Check whether the Interest includes a selected delegation.
Definition: interest.cpp:411
int getMaxSuffixComponents() const
Definition: interest.hpp:325
const Name & getName() const
Definition: interest.hpp:226
Copyright (c) 2013-2016 Regents of the University of California.
Definition: common.hpp:74
bool matchesName(const Name &name) const
Check if Interest, including selectors, matches the given name.
Definition: interest.cpp:105
size_t prependNonNegativeIntegerBlock(EncodingImpl< TAG > &encoder, uint32_t type, uint64_t value)
Helper to prepend TLV block type type containing non-negative integer value.
void setSelectedDelegation(const Name &delegationName)
Set the selected delegation.
Definition: interest.cpp:426
size_t wireEncode(EncodingImpl< TAG > &encoder) const
Fast encoding or block size estimation.
Definition: selectors.cpp:61
EncodingImpl< EstimatorTag > EncodingEstimator
element_const_iterator find(uint32_t type) const
Definition: block.cpp:420
void refreshNonce()
Refresh nonce.
Definition: interest.cpp:91
std::ostream & operator<<(std::ostream &os, const Data &data)
Definition: data.cpp:320
bool hasSelectors() const
Definition: interest.hpp:291
const Block & wireEncode() const
Encode to a wire format.
Definition: interest.cpp:285
size_t wireEncode(EncodingImpl< TAG > &encoder) const
Fast encoding or block size estimation.
Definition: name.cpp:122
Class representing a wire element of NDN-TLV packet format.
Definition: block.hpp:43
represents an Interest packet
Definition: interest.hpp:42
const time::milliseconds & getInterestLifetime() const
Definition: interest.hpp:240
int getChildSelector() const
Definition: interest.hpp:367
uint64_t readNonNegativeInteger(const Block &block)
Helper to read a non-negative integer from a block.
Name getSelectedDelegation() const
Get the name of the selected delegation.
Definition: interest.cpp:417
uint32_t getNonce() const
Get Interest's nonce.
Definition: interest.cpp:62
const Link & getLink() const
Get the link object for this interest.
Definition: interest.cpp:378
const Name & getName() const
Get name of the Data packet.
Definition: data.hpp:318
void unsetSelectedDelegation()
Unset the selected delegation.
Definition: interest.cpp:449
element_const_iterator elements_end() const
Definition: block.cpp:595
uint32_t generateWord32()
Generate a non-cryptographically-secure random integer in the range [0, 2^32)
Definition: random.cpp:63
a concept check for TLV abstraction with .wireEncode method
Definition: concepts.hpp:56
Interest()
Create a new Interest with an empty name (ndn:/)
Definition: interest.cpp:36
bool isExcluded(const name::Component &comp) const
Check if name component is excluded.
Definition: exclude.cpp:217
void setLink(const Block &link)
Set the link object for this interest.
Definition: interest.cpp:390
const Selectors & getSelectors() const
Definition: interest.hpp:297
EncodingImpl< EncoderTag > EncodingBuffer
int getMustBeFresh() const
Definition: interest.hpp:381
Block makeBinaryBlock(uint32_t type, const uint8_t *value, size_t length)
Create a TLV block type type with value from a buffer value of size length.
bool empty() const
Definition: key-locator.hpp:95
Interest & setNonce(uint32_t nonce)
Set Interest's nonce.
Definition: interest.cpp:76
const Exclude & getExclude() const
Definition: interest.hpp:353
const Block & get(uint32_t type) const
Get the first subelement of the requested type.
Definition: block.cpp:409
element_container::const_iterator element_const_iterator
Definition: block.hpp:48
size_t size() const
Get the number of components.
Definition: name.hpp:400
void reset()
Reset wire buffer of the element.
Definition: block.cpp:302
Name abstraction to represent an absolute name.
Definition: name.hpp:46
size_t value_size() const
Definition: block.cpp:529
bool matchesData(const Data &data) const
Check if Interest can be satisfied by data.
Definition: interest.cpp:132
void unsetLink()
Delete the link object for this interest.
Definition: interest.cpp:402
void parse() const
Parse wire buffer into subblocks.
Definition: block.cpp:322
uint32_t type() const
Definition: block.hpp:324
void wireDecode(const Block &wire)
Decode from the wire format.
Definition: interest.cpp:303
bool matchesInterest(const Interest &other) const
Check if Interest matches other interest.
Definition: interest.cpp:216
const Signature & getSignature() const
Definition: data.hpp:348
bool hasLink() const
Check whether the Interest contains a Link object.
Definition: interest.cpp:372
bool empty() const
Definition: exclude.hpp:317
const Block & getInfo() const
Get SignatureInfo in the wire format.
Definition: signature.hpp:70
bool hasWire() const
Check if the Block has fully encoded wire.
Definition: block.cpp:471
bool isPrefixOf(const Name &name) const
Check if the N components of this name are the same as the first N components of the given name...
Definition: name.cpp:308
const uint8_t * value() const
Definition: block.cpp:520
const KeyLocator & getPublisherPublicKeyLocator() const
Definition: interest.hpp:339
const time::milliseconds DEFAULT_INTEREST_LIFETIME
default value for InterestLifetime
Definition: interest.hpp:38
const Name & getFullName() const
Get full name of Data packet, including the implicit digest.
Definition: data.cpp:179
void wireDecode(const Block &wire)
Definition: name.cpp:161
a concept check for TLV abstraction with .wireEncode method
Definition: concepts.hpp:40
represents a Data packet
Definition: data.hpp:37
a concept check for TLV abstraction with .wireDecode method and constructible from Block ...
Definition: concepts.hpp:76
const Component & get(ssize_t i) const
Get the component at the given index.
Definition: name.hpp:411
const size_t INVALID_SELECTED_DELEGATION_INDEX
Definition: link.hpp:30
bool isImplicitSha256Digest() const
Check if the component is ImplicitSha256DigestComponent.
A Signature is storage for the signature-related information (info and value) in a Data packet...
Definition: signature.hpp:33
bool hasNonce() const
Check if Nonce set.
Definition: interest.hpp:256