Skip to content

Instantly share code, notes, and snippets.

@yoursunny
Last active August 29, 2015 14:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yoursunny/2c1ce576cd23c9b8b817 to your computer and use it in GitHub Desktop.
Save yoursunny/2c1ce576cd23c9b8b817 to your computer and use it in GitHub Desktop.
// # 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