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