Last active
August 29, 2015 14:22
-
-
Save yoursunny/2c1ce576cd23c9b8b817 to your computer and use it in GitHub Desktop.
NDNLPv2 client Face API http://redmine.named-data.net/issues/2883
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// # NDNLPv2 API: NACK in client Face | |
// ## extending ndn::Face class | |
namespace ndn { | |
typedef function<void(const Data&)> DataCallback; | |
typedef function<void(const lp::Nack&)> NackCallback; | |
typedef function<void()> TimeoutCallback; | |
// note: OnData and OnTimeout typedefs were mistakes, because type names should be a noun. | |
// Also, there's no reason to pass 'const Interest&' in those callbacks, because in reality almost every callback is a bound function. | |
// Therefore, this API is using a new set of callbacks. | |
class Face | |
{ | |
public: // consumer | |
/** \brief sends an Interest | |
* \param interest the Interest. | |
* \param afterSatisfied a function to be invoked if a Data is returned | |
* \param afterNacked a function to be invoked if a Network NACK is returned | |
* \param afterTimeout a function to be invoked if neither Data nor Network NACK is returned within InterestLifetime | |
*/ | |
const PendingInterestId* | |
expressInterest(const Interest& interest, | |
const DataCallback& afterSatisfied, | |
const NackCallback& afterNacked, | |
const TimeoutCallback& afterTimeout = nullptr); | |
// note: It's intentional not to support "Interest template", because it's not necessary. | |
public: // producer | |
/** \brief returns a Network NACK | |
*/ | |
void | |
put(shared_ptr<lp::Nack> nack); | |
// note: The parameter is a shared_ptr, because FaceImpl will need it. | |
// It's confusing to accept 'const T&' but at the same time require make_shared. | |
}; | |
} // namespace ndn | |
// ## implementation detail: PendingInterest struct | |
// ### DataCallback and TimeoutCallback | |
// | |
// We focus on NACK in this issue, but we shouldn't repeat the mistakes OnData and OnTimeout in public API, so that DataCallback and TimeoutCallback typedefs are declared. | |
// In this issue, OnData and OnTimeout are unchanged in PendingInterest struct and FaceImpl::asyncExpressInterest. | |
// DataCallback or TimeoutCallback is wrapped in lambda to appear as OnData or OnTimeout. | |
// This conversion should happen within Face::expressInterest overload that takes DataCallback or TimeoutCallback. | |
// | |
// In the future, PendingInterest struct and FaceImpl::asyncExpressInterest will use DataCallback and TimeoutCallback. | |
// OnData or OnTimeout would be bound to appear as DataCallback or TimeoutCallback to pass into FaceImpl::asyncExpressInterest. | |
// ### NackCallback | |
// | |
// NackCallback is stored in PendingInterest struct | |
partial class PendingInterest | |
{ | |
public: | |
void | |
invokeNackCallback(const lp::Nack& nack); | |
private: | |
NackCallback m_nackCallback; | |
}; | |
// ## implementation detail: FaceImpl | |
partial class FaceImpl | |
{ | |
public: | |
void | |
nackPendingInterests(const Nack& nack); | |
// note: The procedure is similar to satisfyPendingInterests. | |
void | |
asyncExpressInterest(shared_ptr<const Interest> interest, | |
const OnData& onData, | |
const NackCallback& afterNacked, | |
const OnTimeout& onTimeout); | |
// note: This replaces old asyncExpressInterest for now. | |
void | |
asyncExpressInterest(shared_ptr<const Interest> interest, | |
const DataCallback& afterSatisfied, | |
const NackCallback& afterNacked, | |
const TimeoutCallback& afterTimeout); | |
// note: This is the eventual API. | |
void | |
asyncPutNack(shared_ptr<const Nack> nack); | |
// note: It's intentional to use shared_ptr<const Nack> instead of const shared_ptr<const Nack>& because that's semantically wrong. | |
}; | |
// asyncExpressInterest, asyncPutData, asyncPutNack should construct lp::Packet from every network layer packet, | |
// and set LocalControlHeader fields into LpPacket. | |
// ## implementation detail: Face | |
// expressInterest is updated to call asyncExpressInterest with afterNacked argument. | |
/** \brief extract local fields from NDNLPv2 packet and tag onto a network layer packet | |
*/ | |
template<typename NETPKT> | |
static void | |
extractLpLocalFields(NETPKT& netPacket, const lp::Packet& lpPacket); | |
// note: This extracts IncomingFaceId field and puts it into LocalControlHeader. | |
// Eventually LocalControlHeader will be deprecated and replaced with a Tag. | |
// This template requires Nack class to be extended with 'nfd::LocalControlHeader& getLocalControlHeader()' API, | |
// but the storage of this field can be redirected to the Interest contained within. | |
void | |
Face::onReceiveElement(const Block& blockFromDaemon) | |
{ | |
lp::Packet lpPacket(blockFromDaemon); // bare Interest/Data is a valid lp::Packet, no need to distinguish | |
Block netPacket = /* extract Fragment as a Block */; | |
switch (netPacket.type()) { | |
case tlv::Interest: | |
shared_ptr<Interest> interest = ..; | |
if (lpPacket.has<lp::NackField>()) { | |
shared_ptr<Nack> nack = ..; | |
extractLpLocalFields(*nack, lpPacket); | |
m_impl->nackPendingInterests(*nack); | |
/* cancel PIT timer if needed */ | |
} | |
else { | |
extractLpLocalFields(*interest, lpPacket); | |
/* incoming Interest processing */ | |
} | |
break; | |
case tlv::Data: | |
shared_ptr<Data> data = ..; | |
extractLpLocalFields(*data, lpPacket); | |
/* incoming Data processing */ | |
break; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment