face: send and receive NACK
refs #2930
Change-Id: I70c969ac12b493d2c83fa892beffae936cc23791
diff --git a/src/detail/face-impl.hpp b/src/detail/face-impl.hpp
index fb6642a..98fda53 100644
--- a/src/detail/face-impl.hpp
+++ b/src/detail/face-impl.hpp
@@ -39,6 +39,9 @@
#include "../management/nfd-controller.hpp"
#include "../management/nfd-command-options.hpp"
+#include "../management/nfd-local-control-header.hpp"
+
+#include "../lp/packet.hpp"
namespace ndn {
@@ -74,7 +77,7 @@
satisfyPendingInterests(Data& data)
{
for (auto entry = m_pendingInterestTable.begin(); entry != m_pendingInterestTable.end(); ) {
- if ((*entry)->getInterest().matchesData(data)) {
+ if ((*entry)->getInterest()->matchesData(data)) {
shared_ptr<PendingInterest> matchedEntry = *entry;
entry = m_pendingInterestTable.erase(entry);
@@ -87,6 +90,24 @@
}
void
+ nackPendingInterests(const lp::Nack& nack)
+ {
+ for (auto entry = m_pendingInterestTable.begin(); entry != m_pendingInterestTable.end(); ) {
+ const Interest& pendingInterest = *(*entry)->getInterest();
+ if (pendingInterest == nack.getInterest()) {
+ shared_ptr<PendingInterest> matchedEntry = *entry;
+
+ entry = m_pendingInterestTable.erase(entry);
+
+ matchedEntry->invokeNackCallback(nack);
+ }
+ else {
+ ++entry;
+ }
+ }
+ }
+
+ void
processInterestFilters(Interest& interest)
{
for (const auto& filter : m_interestFilterTable) {
@@ -111,26 +132,32 @@
}
void
- asyncExpressInterest(const shared_ptr<const Interest>& interest,
- const OnData& onData, const OnTimeout& onTimeout)
+ asyncExpressInterest(shared_ptr<const Interest> interest,
+ const DataCallback& afterSatisfied,
+ const NackCallback& afterNacked,
+ const TimeoutCallback& afterTimeout)
{
this->ensureConnected(true);
auto entry =
m_pendingInterestTable.insert(make_shared<PendingInterest>(interest,
- onData, onTimeout,
+ afterSatisfied,
+ afterNacked,
+ afterTimeout,
ref(m_scheduler))).first;
(*entry)->setDeleter([this, entry] { m_pendingInterestTable.erase(entry); });
- if (!interest->getLocalControlHeader().empty(nfd::LocalControlHeader::ENCODE_NEXT_HOP)) {
- // encode only NextHopFaceId towards the forwarder
- m_face.m_transport->send(interest->getLocalControlHeader()
- .wireEncode(*interest, nfd::LocalControlHeader::ENCODE_NEXT_HOP),
- interest->wireEncode());
+ lp::Packet packet;
+
+ nfd::LocalControlHeader localControlHeader = interest->getLocalControlHeader();
+ if (localControlHeader.hasNextHopFaceId()) {
+ packet.add<lp::NextHopFaceIdField>(localControlHeader.getNextHopFaceId());
}
- else {
- m_face.m_transport->send(interest->wireEncode());
- }
+
+ packet.add<lp::FragmentField>(std::make_pair(interest->wireEncode().begin(),
+ interest->wireEncode().end()));
+
+ m_face.m_transport->send(packet.wireEncode());
}
void
@@ -144,15 +171,40 @@
{
this->ensureConnected(true);
- if (!data->getLocalControlHeader().empty(nfd::LocalControlHeader::ENCODE_CACHING_POLICY)) {
- m_face.m_transport->send(
- data->getLocalControlHeader().wireEncode(*data,
- nfd::LocalControlHeader::ENCODE_CACHING_POLICY),
- data->wireEncode());
+ lp::Packet packet;
+
+ nfd::LocalControlHeader localControlHeader = data->getLocalControlHeader();
+ if (localControlHeader.hasCachingPolicy()) {
+ switch (localControlHeader.getCachingPolicy()) {
+ case nfd::LocalControlHeader::CachingPolicy::NO_CACHE: {
+ lp::CachePolicy cachePolicy;
+ cachePolicy.setPolicy(lp::CachePolicyType::NO_CACHE);
+ packet.add<lp::CachePolicyField>(cachePolicy);
+ break;
+ }
+ default:
+ break;
+ }
}
- else {
- m_face.m_transport->send(data->wireEncode());
- }
+
+ packet.add<lp::FragmentField>(std::make_pair(data->wireEncode().begin(),
+ data->wireEncode().end()));
+
+ m_face.m_transport->send(packet.wireEncode());
+ }
+
+ void
+ asyncPutNack(shared_ptr<const lp::Nack> nack)
+ {
+ this->ensureConnected(true);
+
+ lp::Packet packet;
+ packet.add<lp::NackField>(nack->getHeader());
+
+ Block interest = nack->getInterest().wireEncode();
+ packet.add<lp::FragmentField>(std::make_pair(interest.begin(), interest.end()));
+
+ m_face.m_transport->send(packet.wireEncode());
}
/////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/detail/pending-interest.hpp b/src/detail/pending-interest.hpp
index 41f6b37..bac5836 100644
--- a/src/detail/pending-interest.hpp
+++ b/src/detail/pending-interest.hpp
@@ -28,31 +28,32 @@
#include "../util/time.hpp"
#include "../util/scheduler.hpp"
#include "../util/scheduler-scoped-event-id.hpp"
+#include "../lp/nack.hpp"
namespace ndn {
class PendingInterest : noncopyable
{
public:
- typedef function<void(const Interest&, Data&)> OnData;
- typedef function<void(const Interest&)> OnTimeout;
-
/**
* @brief Create a new PitEntry and set the timeout based on the current time and
- * the interest lifetime.
- *
- * @param interest A shared_ptr for the interest
- * @param onData A function object to call when a matching data packet is received.
- * @param onTimeout A function object to call if the interest times out.
- * If onTimeout is an empty OnTimeout(), this does not use it.
- * @param scheduler Scheduler instance to use to schedule a timeout event. The scheduled
- * event will be automatically cancelled when pending interest is destroyed.
+ * the Interest lifetime.
+ * @param interest shared_ptr for the Interest
+ * @param dataCallback function to call when matching Data packet is received
+ * @param nackCallback function to call when Nack matching Interest is received
+ * @param timeoutCallback function to call if Interest times out
+ * @param scheduler Scheduler instance to use to schedule a timeout event. The scheduled
+ * event will be automatically cancelled when pending Interest is destroyed.
*/
- PendingInterest(shared_ptr<const Interest> interest, const OnData& onData,
- const OnTimeout& onTimeout, Scheduler& scheduler)
+ PendingInterest(shared_ptr<const Interest> interest,
+ const DataCallback& dataCallback,
+ const NackCallback& nackCallback,
+ const TimeoutCallback& timeoutCallback,
+ Scheduler& scheduler)
: m_interest(interest)
- , m_onData(onData)
- , m_onTimeout(onTimeout)
+ , m_dataCallback(dataCallback)
+ , m_nackCallback(nackCallback)
+ , m_timeoutCallback(timeoutCallback)
, m_timeoutEvent(scheduler)
{
m_timeoutEvent =
@@ -65,10 +66,10 @@
/**
* @return the Interest
*/
- const Interest&
+ shared_ptr<const Interest>
getInterest() const
{
- return *m_interest;
+ return m_interest;
}
/**
@@ -76,9 +77,19 @@
* @note If the DataCallback is an empty function, this method does nothing.
*/
void
- invokeDataCallback(Data& data)
+ invokeDataCallback(const Data& data)
{
- m_onData(*m_interest, data);
+ m_dataCallback(*m_interest, data);
+ }
+
+ /**
+ * @brief invokes the NackCallback
+ * @note If the NackCallback is an empty function, this method does nothing.
+ */
+ void
+ invokeNackCallback(const lp::Nack& nack)
+ {
+ m_nackCallback(*m_interest, nack);
}
/**
@@ -98,8 +109,8 @@
void
invokeTimeoutCallback()
{
- if (m_onTimeout) {
- m_onTimeout(*m_interest);
+ if (m_timeoutCallback) {
+ m_timeoutCallback(*m_interest);
}
BOOST_ASSERT(m_deleter);
@@ -108,8 +119,9 @@
private:
shared_ptr<const Interest> m_interest;
- const OnData m_onData;
- const OnTimeout m_onTimeout;
+ DataCallback m_dataCallback;
+ NackCallback m_nackCallback;
+ TimeoutCallback m_timeoutCallback;
util::scheduler::ScopedEventId m_timeoutEvent;
std::function<void()> m_deleter;
};
@@ -133,7 +145,7 @@
operator()(const shared_ptr<const PendingInterest>& pendingInterest) const
{
return (reinterpret_cast<const PendingInterestId*>(
- &pendingInterest->getInterest()) == m_id);
+ pendingInterest->getInterest().get()) == m_id);
}
private:
const PendingInterestId* m_id;