NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.3: NDN, CCN, CCNx, content centric networks
API Documentation
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
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 template<encoding::Tag TAG>
216 size_t
218 {
219  size_t totalLength = 0;
220 
221  // Interest ::= INTEREST-TYPE TLV-LENGTH
222  // Name
223  // Selectors?
224  // Nonce
225  // InterestLifetime?
226  // Link?
227  // SelectedDelegation?
228 
229  // (reverse encoding)
230 
231  if (hasLink()) {
232  if (hasSelectedDelegation()) {
233  totalLength += prependNonNegativeIntegerBlock(encoder,
235  m_selectedDelegationIndex);
236  }
237  totalLength += encoder.prependBlock(m_link);
238  }
239  else {
240  BOOST_ASSERT(!hasSelectedDelegation());
241  }
242 
243  // InterestLifetime
244  if (getInterestLifetime() >= time::milliseconds::zero() &&
246  {
247  totalLength += prependNonNegativeIntegerBlock(encoder,
249  getInterestLifetime().count());
250  }
251 
252  // Nonce
253  getNonce(); // to ensure that Nonce is properly set
254  totalLength += encoder.prependBlock(m_nonce);
255 
256  // Selectors
257  if (hasSelectors())
258  {
259  totalLength += getSelectors().wireEncode(encoder);
260  }
261 
262  // Name
263  totalLength += getName().wireEncode(encoder);
264 
265  totalLength += encoder.prependVarNumber(totalLength);
266  totalLength += encoder.prependVarNumber(tlv::Interest);
267  return totalLength;
268 }
269 
270 template size_t
271 Interest::wireEncode<encoding::EncoderTag>(EncodingImpl<encoding::EncoderTag>& encoder) const;
272 
273 template size_t
274 Interest::wireEncode<encoding::EstimatorTag>(EncodingImpl<encoding::EstimatorTag>& encoder) const;
275 
276 const Block&
278 {
279  if (m_wire.hasWire())
280  return m_wire;
281 
282  EncodingEstimator estimator;
283  size_t estimatedSize = wireEncode(estimator);
284 
285  EncodingBuffer buffer(estimatedSize, 0);
286  wireEncode(buffer);
287 
288  // to ensure that Nonce block points to the right memory location
289  const_cast<Interest*>(this)->wireDecode(buffer.block());
290 
291  return m_wire;
292 }
293 
294 void
296 {
297  m_wire = wire;
298  m_wire.parse();
299 
300  // Interest ::= INTEREST-TYPE TLV-LENGTH
301  // Name
302  // Selectors?
303  // Nonce
304  // InterestLifetime?
305  // Link?
306  // SelectedDelegation?
307 
308  if (m_wire.type() != tlv::Interest)
309  BOOST_THROW_EXCEPTION(Error("Unexpected TLV number when decoding Interest"));
310 
311  // Name
312  m_name.wireDecode(m_wire.get(tlv::Name));
313 
314  // Selectors
316  if (val != m_wire.elements_end()) {
317  m_selectors.wireDecode(*val);
318  }
319  else
320  m_selectors = Selectors();
321 
322  // Nonce
323  m_nonce = m_wire.get(tlv::Nonce);
324 
325  // InterestLifetime
326  val = m_wire.find(tlv::InterestLifetime);
327  if (val != m_wire.elements_end()) {
328  m_interestLifetime = time::milliseconds(readNonNegativeInteger(*val));
329  }
330  else {
331  m_interestLifetime = DEFAULT_INTEREST_LIFETIME;
332  }
333 
334  // Link object
335  m_linkCached.reset();
336  val = m_wire.find(tlv::Data);
337  if (val != m_wire.elements_end()) {
338  m_link = (*val);
339  }
340  else {
341  m_link = Block();
342  }
343 
344  // SelectedDelegation
345  val = m_wire.find(tlv::SelectedDelegation);
346  if (val != m_wire.elements_end()) {
347  if (!this->hasLink()) {
348  BOOST_THROW_EXCEPTION(Error("Interest contains SelectedDelegation, but no LINK object"));
349  }
350  uint64_t selectedDelegation = readNonNegativeInteger(*val);
351  if (selectedDelegation < uint64_t(Link::countDelegationsFromWire(m_link))) {
352  m_selectedDelegationIndex = static_cast<size_t>(selectedDelegation);
353  }
354  else {
355  BOOST_THROW_EXCEPTION(Error("Invalid selected delegation index when decoding Interest"));
356  }
357  }
358  else {
359  m_selectedDelegationIndex = INVALID_SELECTED_DELEGATION_INDEX;
360  }
361 }
362 
363 bool
365 {
366  return m_link.hasWire();
367 }
368 
369 const Link&
371 {
372  if (hasLink()) {
373  if (!m_linkCached) {
374  m_linkCached = make_shared<Link>(m_link);
375  }
376  return *m_linkCached;
377  }
378  BOOST_THROW_EXCEPTION(Error("There is no encapsulated link object"));
379 }
380 
381 void
383 {
384  m_link = link;
385  if (!link.hasWire()) {
386  BOOST_THROW_EXCEPTION(Error("The given link does not have a wire format"));
387  }
388  m_wire.reset();
389  m_linkCached.reset();
390  this->unsetSelectedDelegation();
391 }
392 
393 void
395 {
396  m_link.reset();
397  m_wire.reset();
398  m_linkCached.reset();
399  this->unsetSelectedDelegation();
400 }
401 
402 bool
404 {
405  return m_selectedDelegationIndex != INVALID_SELECTED_DELEGATION_INDEX;
406 }
407 
408 Name
410 {
411  if (!hasSelectedDelegation()) {
412  BOOST_THROW_EXCEPTION(Error("There is no encapsulated selected delegation"));
413  }
414  return std::get<1>(Link::getDelegationFromWire(m_link, m_selectedDelegationIndex));
415 }
416 
417 void
418 Interest::setSelectedDelegation(const Name& delegationName)
419 {
420  size_t delegationIndex = Link::findDelegationFromWire(m_link, delegationName);
421  if (delegationIndex != INVALID_SELECTED_DELEGATION_INDEX) {
422  m_selectedDelegationIndex = delegationIndex;
423  }
424  else {
425  BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid selected delegation name"));
426  }
427  m_wire.reset();
428 }
429 
430 void
431 Interest::setSelectedDelegation(size_t delegationIndex)
432 {
433  if (delegationIndex >= Link(m_link).getDelegations().size()) {
434  BOOST_THROW_EXCEPTION(Error("Invalid selected delegation index"));
435  }
436  m_selectedDelegationIndex = delegationIndex;
437  m_wire.reset();
438 }
439 
440 void
442 {
443  m_selectedDelegationIndex = INVALID_SELECTED_DELEGATION_INDEX;
444  m_wire.reset();
445 }
446 
447 std::ostream&
448 operator<<(std::ostream& os, const Interest& interest)
449 {
450  os << interest.getName();
451 
452  char delim = '?';
453 
454  if (interest.getMinSuffixComponents() >= 0) {
455  os << delim << "ndn.MinSuffixComponents=" << interest.getMinSuffixComponents();
456  delim = '&';
457  }
458  if (interest.getMaxSuffixComponents() >= 0) {
459  os << delim << "ndn.MaxSuffixComponents=" << interest.getMaxSuffixComponents();
460  delim = '&';
461  }
462  if (interest.getChildSelector() >= 0) {
463  os << delim << "ndn.ChildSelector=" << interest.getChildSelector();
464  delim = '&';
465  }
466  if (interest.getMustBeFresh()) {
467  os << delim << "ndn.MustBeFresh=" << interest.getMustBeFresh();
468  delim = '&';
469  }
470  if (interest.getInterestLifetime() >= time::milliseconds::zero()
472  os << delim << "ndn.InterestLifetime=" << interest.getInterestLifetime().count();
473  delim = '&';
474  }
475 
476  if (interest.hasNonce()) {
477  os << delim << "ndn.Nonce=" << interest.getNonce();
478  delim = '&';
479  }
480  if (!interest.getExclude().empty()) {
481  os << delim << "ndn.Exclude=" << interest.getExclude();
482  delim = '&';
483  }
484 
485  return os;
486 }
487 
488 } // namespace ndn
void wireDecode(const Block &wire)
Decode the input from wire format.
Definition: selectors.cpp:135
const Block & wireEncode() const
Encode to a wire format.
Definition: interest.cpp:277
bool hasWire() const
Check if the Block has fully encoded wire.
Definition: block.cpp:471
Copyright (c) 2011-2015 Regents of the University of California.
int getChildSelector() const
Definition: interest.hpp:356
size_t prependNonNegativeIntegerBlock(EncodingImpl< TAG > &encoder, uint32_t type, uint64_t value)
Helper to prepend TLV block type type containing non-negative integer value.
const Selectors & getSelectors() const
Definition: interest.hpp:286
void setSelectedDelegation(const Name &delegationName)
Set the selected delegation.
Definition: interest.cpp:418
const Link & getLink() const
Get the link object for this interest.
Definition: interest.cpp:370
int getMustBeFresh() const
Definition: interest.hpp:370
const Component & get(ssize_t i) const
Get the component at the given index.
Definition: name.hpp:411
bool empty() const
Definition: exclude.hpp:317
EncodingImpl< EstimatorTag > EncodingEstimator
void refreshNonce()
Refresh nonce.
Definition: interest.cpp:91
size_t value_size() const
Definition: block.cpp:529
const Name & getName() const
Get name of the Data packet.
Definition: data.hpp:318
std::ostream & operator<<(std::ostream &os, const Data &data)
Definition: data.cpp:320
element_const_iterator elements_end() const
Definition: block.cpp:595
bool matchesName(const Name &name) const
Check if Interest, including selectors, matches the given name.
Definition: interest.cpp:105
void parse() const
Parse wire buffer into subblocks.
Definition: block.cpp:322
Class representing a wire element of NDN-TLV packet format.
Definition: block.hpp:43
represents an Interest packet
Definition: interest.hpp:42
const uint8_t * value() const
Definition: block.cpp:520
uint64_t readNonNegativeInteger(const Block &block)
Helper to read a non-negative integer from a block.
bool hasNonce() const
Check if Nonce set.
Definition: interest.hpp:245
void unsetSelectedDelegation()
Unset the selected delegation.
Definition: interest.cpp:441
int getMaxSuffixComponents() const
Definition: interest.hpp:314
uint32_t generateWord32()
Generate a non-cryptographically-secure random integer in the range [0, 2^32)
Definition: random.cpp:63
Name getSelectedDelegation() const
Get the name of the selected delegation.
Definition: interest.cpp:409
a concept check for TLV abstraction with .wireEncode method
Definition: concepts.hpp:50
const time::milliseconds & getInterestLifetime() const
Definition: interest.hpp:229
Interest()
Create a new Interest with an empty name (ndn:/)
Definition: interest.cpp:36
const KeyLocator & getPublisherPublicKeyLocator() const
Definition: interest.hpp:328
void setLink(const Block &link)
Set the link object for this interest.
Definition: interest.cpp:382
const Block & get(uint32_t type) const
Get the first subelement of the requested type.
Definition: block.cpp:409
EncodingImpl< EncoderTag > EncodingBuffer
element_const_iterator find(uint32_t type) const
Definition: block.cpp:420
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
uint32_t getNonce() const
Get Interest&#39;s nonce.
Definition: interest.cpp:62
const Block & getInfo() const
Get SignatureInfo in the wire format.
Definition: signature.hpp:70
Interest & setNonce(uint32_t nonce)
Set Interest&#39;s nonce.
Definition: interest.cpp:76
bool matchesData(const Data &data) const
Check if Interest can be satisfied by data.
Definition: interest.cpp:132
element_container::const_iterator element_const_iterator
Definition: block.hpp:48
bool isImplicitSha256Digest() const
Check if the component is ImplicitSha256DigestComponent.
void reset()
Reset wire buffer of the element.
Definition: block.cpp:302
Name abstraction to represent an absolute name.
Definition: name.hpp:46
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 Exclude & getExclude() const
Definition: interest.hpp:342
void unsetLink()
Delete the link object for this interest.
Definition: interest.cpp:394
const Name & getFullName() const
Get full name of Data packet, including the implicit digest.
Definition: data.cpp:179
size_t size() const
Get the number of components.
Definition: name.hpp:400
void wireDecode(const Block &wire)
Decode from the wire format.
Definition: interest.cpp:295
size_t wireEncode(EncodingImpl< TAG > &encoder) const
prepend wire encoding
Definition: key-locator.cpp:51
int getMinSuffixComponents() const
Definition: interest.hpp:300
size_t wireEncode(EncodingImpl< TAG > &encoder) const
Fast encoding or block size estimation.
Definition: selectors.cpp:61
bool hasLink() const
Check whether the Interest contains a Link object.
Definition: interest.cpp:364
size_t wireEncode(EncodingImpl< TAG > &encoder) const
Fast encoding or block size estimation.
Definition: name.cpp:122
const time::milliseconds DEFAULT_INTEREST_LIFETIME
default value for InterestLifetime
Definition: interest.hpp:38
bool isExcluded(const name::Component &comp) const
Check if name component is excluded.
Definition: exclude.cpp:217
const Signature & getSignature() const
Definition: data.hpp:348
bool hasSelectedDelegation() const
Check whether the Interest includes a selected delegation.
Definition: interest.cpp:403
void wireDecode(const Block &wire)
Definition: name.cpp:161
a concept check for TLV abstraction with .wireEncode method
Definition: concepts.hpp:34
represents a Data packet
Definition: data.hpp:37
a concept check for TLV abstraction with .wireDecode method and constructible from Block ...
Definition: concepts.hpp:70
uint32_t type() const
Definition: block.hpp:324
const size_t INVALID_SELECTED_DELEGATION_INDEX
Definition: link.hpp:30
bool hasSelectors() const
Definition: interest.hpp:280
const Name & getName() const
Definition: interest.hpp:215
A Signature is storage for the signature-related information (info and value) in a Data packet...
Definition: signature.hpp:33