forwarder.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
26 #include "forwarder.hpp"
27 #include "pit-algorithm.hpp"
28 #include "core/logger.hpp"
29 #include "core/random.hpp"
30 #include "strategy.hpp"
31 #include "table/cleanup.hpp"
32 #include <ndn-cxx/lp/tags.hpp>
33 #include <boost/random/uniform_int_distribution.hpp>
34 
35 namespace nfd {
36 
37 NFD_LOG_INIT("Forwarder");
38 
40  : m_unsolicitedDataPolicy(new fw::DefaultUnsolicitedDataPolicy())
41  , m_fib(m_nameTree)
42  , m_pit(m_nameTree)
43  , m_measurements(m_nameTree)
44  , m_strategyChoice(m_nameTree, fw::makeDefaultStrategy(*this))
45 {
46  fw::installStrategies(*this);
47 
48  m_faceTable.afterAdd.connect([this] (Face& face) {
49  face.afterReceiveInterest.connect(
50  [this, &face] (const Interest& interest) {
51  this->startProcessInterest(face, interest);
52  });
53  face.afterReceiveData.connect(
54  [this, &face] (const Data& data) {
55  this->startProcessData(face, data);
56  });
57  face.afterReceiveNack.connect(
58  [this, &face] (const lp::Nack& nack) {
59  this->startProcessNack(face, nack);
60  });
61  });
62 
63  m_faceTable.beforeRemove.connect([this] (Face& face) {
64  cleanupOnFaceRemoval(m_nameTree, m_fib, m_pit, face);
65  });
66 }
67 
68 Forwarder::~Forwarder() = default;
69 
70 void
71 Forwarder::startProcessInterest(Face& face, const Interest& interest)
72 {
73  // check fields used by forwarding are well-formed
74  try {
75  if (interest.hasLink()) {
76  interest.getLink();
77  }
78  }
79  catch (const tlv::Error&) {
80  NFD_LOG_DEBUG("startProcessInterest face=" << face.getId() <<
81  " interest=" << interest.getName() << " malformed");
82  // It's safe to call interest.getName() because Name has been fully parsed
83  return;
84  }
85 
86  this->onIncomingInterest(face, interest);
87 }
88 
89 void
90 Forwarder::startProcessData(Face& face, const Data& data)
91 {
92  // check fields used by forwarding are well-formed
93  // (none needed)
94 
95  this->onIncomingData(face, data);
96 }
97 
98 void
99 Forwarder::startProcessNack(Face& face, const lp::Nack& nack)
100 {
101  // check fields used by forwarding are well-formed
102  try {
103  if (nack.getInterest().hasLink()) {
104  nack.getInterest().getLink();
105  }
106  }
107  catch (const tlv::Error&) {
108  NFD_LOG_DEBUG("startProcessNack face=" << face.getId() <<
109  " nack=" << nack.getInterest().getName() <<
110  "~" << nack.getReason() << " malformed");
111  return;
112  }
113 
114  this->onIncomingNack(face, nack);
115 }
116 
117 void
118 Forwarder::onIncomingInterest(Face& inFace, const Interest& interest)
119 {
120  // receive Interest
121  NFD_LOG_DEBUG("onIncomingInterest face=" << inFace.getId() <<
122  " interest=" << interest.getName());
123  interest.setTag(make_shared<lp::IncomingFaceIdTag>(inFace.getId()));
124  ++m_counters.nInInterests;
125 
126  // /localhost scope control
127  bool isViolatingLocalhost = inFace.getScope() == ndn::nfd::FACE_SCOPE_NON_LOCAL &&
128  scope_prefix::LOCALHOST.isPrefixOf(interest.getName());
129  if (isViolatingLocalhost) {
130  NFD_LOG_DEBUG("onIncomingInterest face=" << inFace.getId() <<
131  " interest=" << interest.getName() << " violates /localhost");
132  // (drop)
133  return;
134  }
135 
136  // detect duplicate Nonce with Dead Nonce List
137  bool hasDuplicateNonceInDnl = m_deadNonceList.has(interest.getName(), interest.getNonce());
138  if (hasDuplicateNonceInDnl) {
139  // goto Interest loop pipeline
140  this->onInterestLoop(inFace, interest);
141  return;
142  }
143 
144  // PIT insert
145  shared_ptr<pit::Entry> pitEntry = m_pit.insert(interest).first;
146 
147  // detect duplicate Nonce in PIT entry
148  bool hasDuplicateNonceInPit = fw::findDuplicateNonce(*pitEntry, interest.getNonce(), inFace) !=
150  if (hasDuplicateNonceInPit) {
151  // goto Interest loop pipeline
152  this->onInterestLoop(inFace, interest);
153  return;
154  }
155 
156  // cancel unsatisfy & straggler timer
157  this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
158 
159  // is pending?
160  if (!pitEntry->hasInRecords()) {
161  m_cs.find(interest,
162  bind(&Forwarder::onContentStoreHit, this, ref(inFace), pitEntry, _1, _2),
163  bind(&Forwarder::onContentStoreMiss, this, ref(inFace), pitEntry, _1));
164  }
165  else {
166  this->onContentStoreMiss(inFace, pitEntry, interest);
167  }
168 }
169 
170 void
171 Forwarder::onInterestLoop(Face& inFace, const Interest& interest)
172 {
173  // if multi-access face, drop
174  if (inFace.getLinkType() == ndn::nfd::LINK_TYPE_MULTI_ACCESS) {
175  NFD_LOG_DEBUG("onInterestLoop face=" << inFace.getId() <<
176  " interest=" << interest.getName() <<
177  " drop");
178  return;
179  }
180 
181  NFD_LOG_DEBUG("onInterestLoop face=" << inFace.getId() <<
182  " interest=" << interest.getName() <<
183  " send-Nack-duplicate");
184 
185  // send Nack with reason=DUPLICATE
186  // note: Don't enter outgoing Nack pipeline because it needs an in-record.
187  lp::Nack nack(interest);
188  nack.setReason(lp::NackReason::DUPLICATE);
189  inFace.sendNack(nack);
190 }
191 
192 void
193 Forwarder::onContentStoreMiss(const Face& inFace, const shared_ptr<pit::Entry>& pitEntry,
194  const Interest& interest)
195 {
196  NFD_LOG_DEBUG("onContentStoreMiss interest=" << interest.getName());
197 
198  // insert in-record
199  pitEntry->insertOrUpdateInRecord(const_cast<Face&>(inFace), interest);
200 
201  // set PIT unsatisfy timer
202  this->setUnsatisfyTimer(pitEntry);
203 
204  // has NextHopFaceId?
205  shared_ptr<lp::NextHopFaceIdTag> nextHopTag = interest.getTag<lp::NextHopFaceIdTag>();
206  if (nextHopTag != nullptr) {
207  // chosen NextHop face exists?
208  Face* nextHopFace = m_faceTable.get(*nextHopTag);
209  if (nextHopFace != nullptr) {
210  // go to outgoing Interest pipeline
211  this->onOutgoingInterest(pitEntry, *nextHopFace);
212  }
213  return;
214  }
215 
216  // dispatch to strategy: after incoming Interest
217  this->dispatchToStrategy(*pitEntry,
218  [&] (fw::Strategy& strategy) { strategy.afterReceiveInterest(inFace, interest, pitEntry); });
219 }
220 
221 void
222 Forwarder::onContentStoreHit(const Face& inFace, const shared_ptr<pit::Entry>& pitEntry,
223  const Interest& interest, const Data& data)
224 {
225  NFD_LOG_DEBUG("onContentStoreHit interest=" << interest.getName());
226 
227  data.setTag(make_shared<lp::IncomingFaceIdTag>(face::FACEID_CONTENT_STORE));
228  // XXX should we lookup PIT for other Interests that also match csMatch?
229 
230  // set PIT straggler timer
231  this->setStragglerTimer(pitEntry, true, data.getFreshnessPeriod());
232 
233  // goto outgoing Data pipeline
234  this->onOutgoingData(data, *const_pointer_cast<Face>(inFace.shared_from_this()));
235 }
236 
237 void
238 Forwarder::onOutgoingInterest(const shared_ptr<pit::Entry>& pitEntry, Face& outFace,
239  bool wantNewNonce)
240 {
241  if (outFace.getId() == face::INVALID_FACEID) {
242  NFD_LOG_WARN("onOutgoingInterest face=invalid interest=" << pitEntry->getName());
243  return;
244  }
245  NFD_LOG_DEBUG("onOutgoingInterest face=" << outFace.getId() <<
246  " interest=" << pitEntry->getName());
247 
248  // scope control
249  if (fw::violatesScope(*pitEntry, outFace)) {
250  NFD_LOG_DEBUG("onOutgoingInterest face=" << outFace.getId() <<
251  " interest=" << pitEntry->getName() << " violates scope");
252  return;
253  }
254 
255  // pick Interest
256  // The outgoing Interest picked is the last incoming Interest that does not come from outFace.
257  // If all in-records come from outFace, it's fine to pick that.
258  // This happens when there's only one in-record that comes from outFace.
259  // The legit use is for vehicular network; otherwise, strategy shouldn't send to the sole inFace.
260  pit::InRecordCollection::iterator pickedInRecord = std::max_element(
261  pitEntry->in_begin(), pitEntry->in_end(),
262  [&outFace] (const pit::InRecord& a, const pit::InRecord& b) {
263  bool isOutFaceA = &a.getFace() == &outFace;
264  bool isOutFaceB = &b.getFace() == &outFace;
265  return (isOutFaceA > isOutFaceB) ||
266  (isOutFaceA == isOutFaceB && a.getLastRenewed() < b.getLastRenewed());
267  });
268  BOOST_ASSERT(pickedInRecord != pitEntry->in_end());
269  auto interest = const_pointer_cast<Interest>(pickedInRecord->getInterest().shared_from_this());
270 
271  if (wantNewNonce) {
272  interest = make_shared<Interest>(*interest);
273  static boost::random::uniform_int_distribution<uint32_t> dist;
274  interest->setNonce(dist(getGlobalRng()));
275  }
276 
277  // insert out-record
278  pitEntry->insertOrUpdateOutRecord(outFace, *interest);
279 
280  // send Interest
281  outFace.sendInterest(*interest);
282  ++m_counters.nOutInterests;
283 }
284 
285 void
286 Forwarder::onInterestReject(const shared_ptr<pit::Entry>& pitEntry)
287 {
288  if (fw::hasPendingOutRecords(*pitEntry)) {
289  NFD_LOG_ERROR("onInterestReject interest=" << pitEntry->getName() <<
290  " cannot reject forwarded Interest");
291  return;
292  }
293  NFD_LOG_DEBUG("onInterestReject interest=" << pitEntry->getName());
294 
295  // cancel unsatisfy & straggler timer
296  this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
297 
298  // set PIT straggler timer
299  this->setStragglerTimer(pitEntry, false);
300 }
301 
302 void
303 Forwarder::onInterestUnsatisfied(const shared_ptr<pit::Entry>& pitEntry)
304 {
305  NFD_LOG_DEBUG("onInterestUnsatisfied interest=" << pitEntry->getName());
306 
307  // invoke PIT unsatisfied callback
308  this->dispatchToStrategy(*pitEntry,
309  [&] (fw::Strategy& strategy) { strategy.beforeExpirePendingInterest(pitEntry); });
310 
311  // goto Interest Finalize pipeline
312  this->onInterestFinalize(pitEntry, false);
313 }
314 
315 void
316 Forwarder::onInterestFinalize(const shared_ptr<pit::Entry>& pitEntry, bool isSatisfied,
317  time::milliseconds dataFreshnessPeriod)
318 {
319  NFD_LOG_DEBUG("onInterestFinalize interest=" << pitEntry->getName() <<
320  (isSatisfied ? " satisfied" : " unsatisfied"));
321 
322  // Dead Nonce List insert if necessary
323  this->insertDeadNonceList(*pitEntry, isSatisfied, dataFreshnessPeriod, 0);
324 
325  // PIT delete
326  this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
327  m_pit.erase(pitEntry.get());
328 }
329 
330 void
331 Forwarder::onIncomingData(Face& inFace, const Data& data)
332 {
333  // receive Data
334  NFD_LOG_DEBUG("onIncomingData face=" << inFace.getId() << " data=" << data.getName());
335  data.setTag(make_shared<lp::IncomingFaceIdTag>(inFace.getId()));
336  ++m_counters.nInData;
337 
338  // /localhost scope control
339  bool isViolatingLocalhost = inFace.getScope() == ndn::nfd::FACE_SCOPE_NON_LOCAL &&
340  scope_prefix::LOCALHOST.isPrefixOf(data.getName());
341  if (isViolatingLocalhost) {
342  NFD_LOG_DEBUG("onIncomingData face=" << inFace.getId() <<
343  " data=" << data.getName() << " violates /localhost");
344  // (drop)
345  return;
346  }
347 
348  // PIT match
349  pit::DataMatchResult pitMatches = m_pit.findAllDataMatches(data);
350  if (pitMatches.begin() == pitMatches.end()) {
351  // goto Data unsolicited pipeline
352  this->onDataUnsolicited(inFace, data);
353  return;
354  }
355 
356  // CS insert
357  m_cs.insert(data);
358 
359  std::set<Face*> pendingDownstreams;
360  // foreach PitEntry
361  auto now = time::steady_clock::now();
362  for (const shared_ptr<pit::Entry>& pitEntry : pitMatches) {
363  NFD_LOG_DEBUG("onIncomingData matching=" << pitEntry->getName());
364 
365  // cancel unsatisfy & straggler timer
366  this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
367 
368  // remember pending downstreams
369  for (const pit::InRecord& inRecord : pitEntry->getInRecords()) {
370  if (inRecord.getExpiry() > now) {
371  pendingDownstreams.insert(&inRecord.getFace());
372  }
373  }
374 
375  // invoke PIT satisfy callback
376  this->dispatchToStrategy(*pitEntry,
377  [&] (fw::Strategy& strategy) { strategy.beforeSatisfyInterest(pitEntry, inFace, data); });
378 
379  // Dead Nonce List insert if necessary (for out-record of inFace)
380  this->insertDeadNonceList(*pitEntry, true, data.getFreshnessPeriod(), &inFace);
381 
382  // mark PIT satisfied
383  pitEntry->clearInRecords();
384  pitEntry->deleteOutRecord(inFace);
385 
386  // set PIT straggler timer
387  this->setStragglerTimer(pitEntry, true, data.getFreshnessPeriod());
388  }
389 
390  // foreach pending downstream
391  for (Face* pendingDownstream : pendingDownstreams) {
392  if (pendingDownstream == &inFace) {
393  continue;
394  }
395  // goto outgoing Data pipeline
396  this->onOutgoingData(data, *pendingDownstream);
397  }
398 }
399 
400 void
401 Forwarder::onDataUnsolicited(Face& inFace, const Data& data)
402 {
403  // accept to cache?
404  fw::UnsolicitedDataDecision decision = m_unsolicitedDataPolicy->decide(inFace, data);
405  if (decision == fw::UnsolicitedDataDecision::CACHE) {
406  // CS insert
407  m_cs.insert(data, true);
408  }
409 
410  NFD_LOG_DEBUG("onDataUnsolicited face=" << inFace.getId() <<
411  " data=" << data.getName() <<
412  " decision=" << decision);
413 }
414 
415 void
416 Forwarder::onOutgoingData(const Data& data, Face& outFace)
417 {
418  if (outFace.getId() == face::INVALID_FACEID) {
419  NFD_LOG_WARN("onOutgoingData face=invalid data=" << data.getName());
420  return;
421  }
422  NFD_LOG_DEBUG("onOutgoingData face=" << outFace.getId() << " data=" << data.getName());
423 
424  // /localhost scope control
425  bool isViolatingLocalhost = outFace.getScope() == ndn::nfd::FACE_SCOPE_NON_LOCAL &&
426  scope_prefix::LOCALHOST.isPrefixOf(data.getName());
427  if (isViolatingLocalhost) {
428  NFD_LOG_DEBUG("onOutgoingData face=" << outFace.getId() <<
429  " data=" << data.getName() << " violates /localhost");
430  // (drop)
431  return;
432  }
433 
434  // TODO traffic manager
435 
436  // send Data
437  outFace.sendData(data);
438  ++m_counters.nOutData;
439 }
440 
441 void
442 Forwarder::onIncomingNack(Face& inFace, const lp::Nack& nack)
443 {
444  // receive Nack
445  nack.setTag(make_shared<lp::IncomingFaceIdTag>(inFace.getId()));
446  ++m_counters.nInNacks;
447 
448  // if multi-access face, drop
449  if (inFace.getLinkType() == ndn::nfd::LINK_TYPE_MULTI_ACCESS) {
450  NFD_LOG_DEBUG("onIncomingNack face=" << inFace.getId() <<
451  " nack=" << nack.getInterest().getName() <<
452  "~" << nack.getReason() << " face-is-multi-access");
453  return;
454  }
455 
456  // PIT match
457  shared_ptr<pit::Entry> pitEntry = m_pit.find(nack.getInterest());
458  // if no PIT entry found, drop
459  if (pitEntry == nullptr) {
460  NFD_LOG_DEBUG("onIncomingNack face=" << inFace.getId() <<
461  " nack=" << nack.getInterest().getName() <<
462  "~" << nack.getReason() << " no-PIT-entry");
463  return;
464  }
465 
466  // has out-record?
467  pit::OutRecordCollection::iterator outRecord = pitEntry->getOutRecord(inFace);
468  // if no out-record found, drop
469  if (outRecord == pitEntry->out_end()) {
470  NFD_LOG_DEBUG("onIncomingNack face=" << inFace.getId() <<
471  " nack=" << nack.getInterest().getName() <<
472  "~" << nack.getReason() << " no-out-record");
473  return;
474  }
475 
476  // if out-record has different Nonce, drop
477  if (nack.getInterest().getNonce() != outRecord->getLastNonce()) {
478  NFD_LOG_DEBUG("onIncomingNack face=" << inFace.getId() <<
479  " nack=" << nack.getInterest().getName() <<
480  "~" << nack.getReason() << " wrong-Nonce " <<
481  nack.getInterest().getNonce() << "!=" << outRecord->getLastNonce());
482  return;
483  }
484 
485  NFD_LOG_DEBUG("onIncomingNack face=" << inFace.getId() <<
486  " nack=" << nack.getInterest().getName() <<
487  "~" << nack.getReason() << " OK");
488 
489  // record Nack on out-record
490  outRecord->setIncomingNack(nack);
491 
492  // trigger strategy: after receive NACK
493  this->dispatchToStrategy(*pitEntry,
494  [&] (fw::Strategy& strategy) { strategy.afterReceiveNack(inFace, nack, pitEntry); });
495 }
496 
497 void
498 Forwarder::onOutgoingNack(const shared_ptr<pit::Entry>& pitEntry, const Face& outFace,
499  const lp::NackHeader& nack)
500 {
501  if (outFace.getId() == face::INVALID_FACEID) {
502  NFD_LOG_WARN("onOutgoingNack face=invalid" <<
503  " nack=" << pitEntry->getInterest().getName() <<
504  "~" << nack.getReason() << " no-in-record");
505  return;
506  }
507 
508  // has in-record?
509  pit::InRecordCollection::iterator inRecord = pitEntry->getInRecord(outFace);
510 
511  // if no in-record found, drop
512  if (inRecord == pitEntry->in_end()) {
513  NFD_LOG_DEBUG("onOutgoingNack face=" << outFace.getId() <<
514  " nack=" << pitEntry->getInterest().getName() <<
515  "~" << nack.getReason() << " no-in-record");
516  return;
517  }
518 
519  // if multi-access face, drop
520  if (outFace.getLinkType() == ndn::nfd::LINK_TYPE_MULTI_ACCESS) {
521  NFD_LOG_DEBUG("onOutgoingNack face=" << outFace.getId() <<
522  " nack=" << pitEntry->getInterest().getName() <<
523  "~" << nack.getReason() << " face-is-multi-access");
524  return;
525  }
526 
527  NFD_LOG_DEBUG("onOutgoingNack face=" << outFace.getId() <<
528  " nack=" << pitEntry->getInterest().getName() <<
529  "~" << nack.getReason() << " OK");
530 
531  // create Nack packet with the Interest from in-record
532  lp::Nack nackPkt(inRecord->getInterest());
533  nackPkt.setHeader(nack);
534 
535  // erase in-record
536  pitEntry->deleteInRecord(outFace);
537 
538  // send Nack on face
539  const_cast<Face&>(outFace).sendNack(nackPkt);
540  ++m_counters.nOutNacks;
541 }
542 
543 static inline bool
545 {
546  return a.getExpiry() < b.getExpiry();
547 }
548 
549 void
550 Forwarder::setUnsatisfyTimer(const shared_ptr<pit::Entry>& pitEntry)
551 {
552  pit::InRecordCollection::iterator lastExpiring =
553  std::max_element(pitEntry->in_begin(), pitEntry->in_end(), &compare_InRecord_expiry);
554 
555  time::steady_clock::TimePoint lastExpiry = lastExpiring->getExpiry();
556  time::nanoseconds lastExpiryFromNow = lastExpiry - time::steady_clock::now();
557  if (lastExpiryFromNow <= time::seconds::zero()) {
558  // TODO all in-records are already expired; will this happen?
559  }
560 
561  scheduler::cancel(pitEntry->m_unsatisfyTimer);
562  pitEntry->m_unsatisfyTimer = scheduler::schedule(lastExpiryFromNow,
563  bind(&Forwarder::onInterestUnsatisfied, this, pitEntry));
564 }
565 
566 void
567 Forwarder::setStragglerTimer(const shared_ptr<pit::Entry>& pitEntry, bool isSatisfied,
568  time::milliseconds dataFreshnessPeriod)
569 {
570  time::nanoseconds stragglerTime = time::milliseconds(100);
571 
572  scheduler::cancel(pitEntry->m_stragglerTimer);
573  pitEntry->m_stragglerTimer = scheduler::schedule(stragglerTime,
574  bind(&Forwarder::onInterestFinalize, this, pitEntry, isSatisfied, dataFreshnessPeriod));
575 }
576 
577 void
578 Forwarder::cancelUnsatisfyAndStragglerTimer(pit::Entry& pitEntry)
579 {
580  scheduler::cancel(pitEntry.m_unsatisfyTimer);
581  scheduler::cancel(pitEntry.m_stragglerTimer);
582 }
583 
584 static inline void
586  const pit::OutRecord& outRecord)
587 {
588  dnl.add(pitEntry.getName(), outRecord.getLastNonce());
589 }
590 
591 void
592 Forwarder::insertDeadNonceList(pit::Entry& pitEntry, bool isSatisfied,
593  time::milliseconds dataFreshnessPeriod, Face* upstream)
594 {
595  // need Dead Nonce List insert?
596  bool needDnl = false;
597  if (isSatisfied) {
598  bool hasFreshnessPeriod = dataFreshnessPeriod >= time::milliseconds::zero();
599  // Data never becomes stale if it doesn't have FreshnessPeriod field
600  needDnl = static_cast<bool>(pitEntry.getInterest().getMustBeFresh()) &&
601  (hasFreshnessPeriod && dataFreshnessPeriod < m_deadNonceList.getLifetime());
602  }
603  else {
604  needDnl = true;
605  }
606 
607  if (!needDnl) {
608  return;
609  }
610 
611  // Dead Nonce List insert
612  if (upstream == 0) {
613  // insert all outgoing Nonces
614  const pit::OutRecordCollection& outRecords = pitEntry.getOutRecords();
615  std::for_each(outRecords.begin(), outRecords.end(),
616  bind(&insertNonceToDnl, ref(m_deadNonceList), cref(pitEntry), _1));
617  }
618  else {
619  // insert outgoing Nonce of a specific face
620  pit::OutRecordCollection::iterator outRecord = pitEntry.getOutRecord(*upstream);
621  if (outRecord != pitEntry.getOutRecords().end()) {
622  m_deadNonceList.add(pitEntry.getName(), outRecord->getLastNonce());
623  }
624  }
625 }
626 
627 } // namespace nfd
unique_ptr< Strategy > makeDefaultStrategy(Forwarder &forwarder)
void cleanupOnFaceRemoval(NameTree &nt, Fib &fib, Pit &pit, const Face &face)
cleanup tables when a face is destroyed
Definition: cleanup.cpp:31
Copyright (c) 2014-2016, Regents of the University of California, Arizona Board of Regents...
#define NFD_LOG_DEBUG(expression)
Definition: logger.hpp:161
void cancel(const EventId &eventId)
cancel a scheduled event
Definition: scheduler.cpp:53
void installStrategies(Forwarder &forwarder)
contains information about an Interest toward an outgoing face
time::steady_clock::TimePoint getExpiry() const
gives the time point this record expires
Face * get(FaceId id) const
get face by FaceId
Definition: face-table.cpp:42
#define NFD_LOG_ERROR(expression)
Definition: logger.hpp:164
const time::nanoseconds & getLifetime() const
void add(const Name &name, uint32_t nonce)
records name+nonce
static bool compare_InRecord_expiry(const pit::InRecord &a, const pit::InRecord &b)
Definition: forwarder.cpp:544
bool has(const Name &name, uint32_t nonce) const
determines if name+nonce exists
DropAllUnsolicitedDataPolicy DefaultUnsolicitedDataPolicy
the default UnsolicitedDataPolicy
Table::const_iterator iterator
Definition: cs-internal.hpp:41
#define NFD_LOG_WARN(expression)
Definition: logger.hpp:163
an Interest table entry
Definition: pit-entry.hpp:57
static void insertNonceToDnl(DeadNonceList &dnl, const pit::Entry &pitEntry, const pit::OutRecord &outRecord)
Definition: forwarder.cpp:585
bool violatesScope(const pit::Entry &pitEntry, const Face &outFace)
determine whether forwarding the Interest in pitEntry to outFace would violate scope ...
Copyright (c) 2014-2015, Regents of the University of California, Arizona Board of Regents...
Definition: algorithm.hpp:32
contains information about an Interest from an incoming face
signal::Signal< FaceTable, Face & > beforeRemove
fires before a face is removed
Definition: face-table.hpp:91
void startProcessInterest(Face &face, const Interest &interest)
start incoming Interest processing
Definition: forwarder.cpp:71
represents the Dead Nonce list
signal::Signal< FaceTable, Face & > afterAdd
fires after a face is added
Definition: face-table.hpp:85
boost::random::mt19937 & getGlobalRng()
Definition: random.cpp:34
bool hasPendingOutRecords(const pit::Entry &pitEntry)
determine whether pitEntry has any pending out-records
const Name LOCALHOST
ndn:/localhost
no duplicate Nonce is found
int findDuplicateNonce(const pit::Entry &pitEntry, uint32_t nonce, const Face &face)
determine whether pitEntry has duplicate Nonce nonce
std::list< OutRecord > OutRecordCollection
an unordered collection of out-records
Definition: pit-entry.hpp:47
#define NFD_LOG_INIT(name)
Definition: logger.hpp:122
EventId schedule(const time::nanoseconds &after, const Scheduler::Event &event)
schedule an event
Definition: scheduler.cpp:47
UnsolicitedDataDecision
a decision made by UnsolicitedDataPolicy
the Data should be cached in the ContentStore
uint32_t getLastNonce() const
void startProcessData(Face &face, const Data &data)
start incoming Data processing
Definition: forwarder.cpp:90
const FaceId FACEID_CONTENT_STORE
identifies a packet comes from the ContentStore
Definition: face.hpp:46
std::vector< shared_ptr< Entry > > DataMatchResult
Definition: pit.hpp:42
const FaceId INVALID_FACEID
indicates an invalid FaceId
Definition: face.hpp:42
const Name & getName() const
Definition: pit-entry.hpp:77
void startProcessNack(Face &face, const lp::Nack &nack)
start incoming Nack processing
Definition: forwarder.cpp:99