NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.0: 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
217 Interest::wireEncode(EncodingImpl<TAG>& encoder) const
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  {
318  m_selectors.wireDecode(*val);
319  }
320  else
321  m_selectors = Selectors();
322 
323  // Nonce
324  m_nonce = m_wire.get(tlv::Nonce);
325 
326  // InterestLifetime
327  val = m_wire.find(tlv::InterestLifetime);
328  if (val != m_wire.elements_end())
329  {
330  m_interestLifetime = time::milliseconds(readNonNegativeInteger(*val));
331  }
332  else
333  {
334  m_interestLifetime = DEFAULT_INTEREST_LIFETIME;
335  }
336 
337  // Link object
338  val = m_wire.find(tlv::Data);
339  if (val != m_wire.elements_end())
340  {
341  m_link = (*val);
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 }
359 
360 bool
362 {
363  if (m_link.hasWire())
364  return true;
365  return false;
366 }
367 
368 Link
370 {
371  if (hasLink())
372  {
373  return Link(m_link);
374  }
375  BOOST_THROW_EXCEPTION(Error("There is no encapsulated link object"));
376 }
377 
378 void
380 {
381  m_link = link;
382  if (!link.hasWire()) {
383  BOOST_THROW_EXCEPTION(Error("The given link does not have a wire format"));
384  }
385  m_wire.reset();
386  this->unsetSelectedDelegation();
387 }
388 
389 void
391 {
392  m_link.reset();
393  m_wire.reset();
394  this->unsetSelectedDelegation();
395 }
396 
397 bool
399 {
400  if (m_selectedDelegationIndex != INVALID_SELECTED_DELEGATION_INDEX)
401  {
402  return true;
403  }
404  return false;
405 }
406 
407 Name
409 {
410  if (!hasSelectedDelegation()) {
411  BOOST_THROW_EXCEPTION(Error("There is no encapsulated selected delegation"));
412  }
413  return std::get<1>(Link::getDelegationFromWire(m_link, m_selectedDelegationIndex));
414 }
415 
416 void
417 Interest::setSelectedDelegation(const Name& delegationName)
418 {
419  size_t delegationIndex = Link::findDelegationFromWire(m_link, delegationName);
420  if (delegationIndex != INVALID_SELECTED_DELEGATION_INDEX) {
421  m_selectedDelegationIndex = delegationIndex;
422  }
423  else {
424  BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid selected delegation name"));
425  }
426  m_wire.reset();
427 }
428 
429 void
430 Interest::setSelectedDelegation(size_t delegationIndex)
431 {
432  if (delegationIndex >= Link(m_link).getDelegations().size()) {
433  BOOST_THROW_EXCEPTION(Error("Invalid selected delegation index"));
434  }
435  m_selectedDelegationIndex = delegationIndex;
436  m_wire.reset();
437 }
438 
439 void
441 {
442  m_selectedDelegationIndex = INVALID_SELECTED_DELEGATION_INDEX;
443  m_wire.reset();
444 }
445 
446 std::ostream&
447 operator<<(std::ostream& os, const Interest& interest)
448 {
449  os << interest.getName();
450 
451  char delim = '?';
452 
453  if (interest.getMinSuffixComponents() >= 0) {
454  os << delim << "ndn.MinSuffixComponents=" << interest.getMinSuffixComponents();
455  delim = '&';
456  }
457  if (interest.getMaxSuffixComponents() >= 0) {
458  os << delim << "ndn.MaxSuffixComponents=" << interest.getMaxSuffixComponents();
459  delim = '&';
460  }
461  if (interest.getChildSelector() >= 0) {
462  os << delim << "ndn.ChildSelector=" << interest.getChildSelector();
463  delim = '&';
464  }
465  if (interest.getMustBeFresh()) {
466  os << delim << "ndn.MustBeFresh=" << interest.getMustBeFresh();
467  delim = '&';
468  }
469  if (interest.getInterestLifetime() >= time::milliseconds::zero()
471  os << delim << "ndn.InterestLifetime=" << interest.getInterestLifetime().count();
472  delim = '&';
473  }
474 
475  if (interest.hasNonce()) {
476  os << delim << "ndn.Nonce=" << interest.getNonce();
477  delim = '&';
478  }
479  if (!interest.getExclude().empty()) {
480  os << delim << "ndn.Exclude=" << interest.getExclude();
481  delim = '&';
482  }
483 
484  return os;
485 }
486 
487 } // 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:51
int getMinSuffixComponents() const
Definition: interest.hpp:342
bool hasSelectedDelegation() const
Check whether the Interest includes a selected delegation.
Definition: interest.cpp:398
int getMaxSuffixComponents() const
Definition: interest.hpp:356
const Name & getName() const
Definition: interest.hpp:216
Copyright (c) 2011-2015 Regents of the University of California.
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.
Link getLink() const
Get the link object for this interest.
Definition: interest.cpp:369
void setSelectedDelegation(const Name &delegationName)
Set the selected delegation.
Definition: interest.cpp:417
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:340
bool hasSelectors() const
Definition: interest.hpp:322
const Block & wireEncode() const
Encode to a wire format.
Definition: interest.cpp:277
size_t wireEncode(EncodingImpl< TAG > &encoder) const
Fast encoding or block size estimation.
Definition: name.cpp:69
Class representing a wire element of NDN-TLV packet format.
Definition: block.hpp:43
represents an Interest packet
Definition: interest.hpp:45
const time::milliseconds & getInterestLifetime() const
Definition: interest.hpp:230
int getChildSelector() const
Definition: interest.hpp:398
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:408
uint32_t getNonce() const
Get Interest&#39;s nonce.
Definition: interest.cpp:62
const Name & getName() const
Get name of the Data packet.
Definition: data.hpp:343
void unsetSelectedDelegation()
Unset the selected delegation.
Definition: interest.cpp:440
element_const_iterator elements_end() const
Definition: block.cpp:595
uint32_t generateWord32()
Generate a cryptographically non-secure random integer from the range [0, 2^32)
Definition: random.cpp:73
a concept check for TLV abstraction with .wireEncode method
Definition: concepts.hpp:50
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:159
void setLink(const Block &link)
Set the link object for this interest.
Definition: interest.cpp:379
const Selectors & getSelectors() const
Definition: interest.hpp:328
EncodingImpl< EncoderTag > EncodingBuffer
int getMustBeFresh() const
Definition: interest.hpp:412
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&#39;s nonce.
Definition: interest.cpp:76
const Exclude & getExclude() const
Definition: interest.hpp:384
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:408
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()
Reset the wire format of the given interest and the contained link.
Definition: interest.cpp:390
void parse() const
Parse wire buffer into subblocks.
Definition: block.cpp:322
uint32_t type() const
Definition: block.hpp:346
void wireDecode(const Block &wire)
Decode from the wire format.
Definition: interest.cpp:295
const Signature & getSignature() const
Definition: data.hpp:373
bool hasLink() const
Check whether the Interest contains a Link object.
Definition: interest.cpp:361
bool empty() const
Check if exclude filter is empty.
Definition: exclude.hpp:223
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:320
const uint8_t * value() const
Definition: block.cpp:520
const KeyLocator & getPublisherPublicKeyLocator() const
Definition: interest.hpp:370
const time::milliseconds DEFAULT_INTEREST_LIFETIME
default value for InterestLifetime
Definition: interest.hpp:41
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:108
a concept check for TLV abstraction with .wireEncode method
Definition: concepts.hpp:34
represents a Data packet
Definition: data.hpp:39
a concept check for TLV abstraction with .wireDecode method and constructible from Block ...
Definition: concepts.hpp:70
const Component & get(ssize_t i) const
Get the component at the given index.
Definition: name.hpp:419
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:246