face: Refactored code to set interest filter
Change-Id: I1f9637a79c03a9e24608403d963bbfc4d9bcab1c
diff --git a/src/management/ndnd-control.cpp b/src/management/ndnd-control.cpp
new file mode 100644
index 0000000..6f48231
--- /dev/null
+++ b/src/management/ndnd-control.cpp
@@ -0,0 +1,264 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * See COPYING for copyright and distribution information.
+ */
+
+#include "common.hpp"
+#include "../node.hpp"
+#include "../security/signature-sha256-with-rsa.hpp"
+#include "../util/random.hpp"
+
+#include "ndnd-forwarding-entry.hpp"
+#include "ndnd-face-instance.hpp"
+#include "ndnd-status-response.hpp"
+
+namespace ndn {
+namespace ndnd {
+
+Control::Control(Node& face)
+ : m_face(face)
+ , m_faceId(-1)
+{
+}
+
+void
+Control::selfRegisterPrefix(const Name& prefixToRegister,
+ const SuccessCallback& onSuccess,
+ const FailCallback& onFail)
+{
+ if (!m_ndndId.hasValue())
+ {
+ if (m_filterRequests.empty())
+ {
+ m_face.expressInterest(Name("/%C1.M.S.localhost/%C1.M.SRV/ndnd/KEY"),
+ bind(&Control::onNdnidFetched, this, _1, _2),
+ bind(onFail));
+ }
+ m_filterRequests.push_back(FilterRequest(prefixToRegister, onSuccess, onFail));
+ }
+ else
+ startPrefixAction(ForwardingEntry("selfreg", prefixToRegister),
+ bind(&Control::recordSelfRegisteredFaceId, this, _1, onSuccess),
+ onFail);
+}
+
+
+void
+Control::selfDeregisterPrefix(const Name& prefixToRegister,
+ const SuccessCallback& onSuccess,
+ const FailCallback& onFail)
+{
+ if (!m_ndndId.hasValue() || m_faceId == -1)
+ {
+ if (static_cast<bool>(onFail))
+ onFail();
+ return;
+ }
+
+ startPrefixAction(ForwardingEntry("unreg", prefixToRegister, m_faceId),
+ bind(onSuccess), onFail);
+}
+
+
+void
+Control::onNdnidFetched(const shared_ptr<const Interest>& interest,
+ const shared_ptr<Data>& data)
+{
+ if (data->getName().size() > interest->getName().size())
+ {
+ m_ndndId = data->getName()[interest->getName().size()];
+
+ for (FilterRequestList::iterator i = m_filterRequests.begin();
+ i != m_filterRequests.end();
+ ++i)
+ {
+ startPrefixAction(ForwardingEntry("selfreg", i->m_prefixToRegister),
+ bind(&Control::recordSelfRegisteredFaceId, this, _1, i->m_onSuccess),
+ i->m_onFailure);
+ }
+ }
+ else
+ {
+ for (FilterRequestList::iterator i = m_filterRequests.begin();
+ i != m_filterRequests.end();
+ ++i)
+ {
+ if (static_cast<bool>(i->m_onFailure))
+ i->m_onFailure();
+ }
+ }
+ m_filterRequests.clear();
+}
+
+void
+Control::recordSelfRegisteredFaceId(const ForwardingEntry& entry,
+ const SuccessCallback& onSuccess)
+{
+ m_faceId = entry.getFaceId();
+ if (static_cast<bool>(onSuccess))
+ onSuccess();
+}
+
+void
+Control::startFaceAction(const FaceInstance& entry,
+ const FaceOperationSucceedCallback& onSuccess,
+ const FailCallback& onFailure)
+{
+ // Set the ForwardingEntry as the content of a Data packet and sign.
+ Data data;
+ data.setName(Name().appendVersion(ndn::random::generateWord32()));
+ data.setContent(entry.wireEncode());
+
+ // Create an empty signature, since nobody going to verify it for now
+ // @todo In the future, we may require real signatures to do the registration
+ SignatureSha256WithRsa signature;
+ signature.setValue(Block(Tlv::SignatureValue));
+ data.setSignature(signature);
+
+ // Create an interest where the name has the encoded Data packet.
+ Name interestName;
+ interestName.append("ndnx");
+ interestName.append(m_ndndId);
+ interestName.append(entry.getAction());
+ interestName.append(data.wireEncode());
+
+ Interest interest(interestName);
+ interest.setScope(1);
+ interest.setInterestLifetime(1000);
+ interest.setMustBeFresh(true);
+
+ m_face.expressInterest(interest,
+ bind(&Control::processFaceActionResponse, this, _2, onSuccess, onFailure),
+ bind(onFailure));
+}
+
+void
+Control::startPrefixAction(const ForwardingEntry& entry,
+ const PrefixOperationSucceedCallback& onSuccess,
+ const FailCallback& onFailure)
+{
+ // Set the ForwardingEntry as the content of a Data packet and sign.
+ Data data;
+ data.setName(Name().appendVersion(random::generateWord32()));
+ data.setContent(entry.wireEncode());
+
+ // Create an empty signature, since nobody going to verify it for now
+ // @todo In the future, we may require real signatures to do the registration
+ SignatureSha256WithRsa signature;
+ signature.setValue(Block(Tlv::SignatureValue));
+ data.setSignature(signature);
+
+ // Create an interest where the name has the encoded Data packet.
+ Name interestName;
+ interestName.append("ndnx");
+ interestName.append(m_ndndId);
+ interestName.append(entry.getAction());
+ interestName.append(data.wireEncode());
+
+ Interest interest(interestName);
+ interest.setScope(1);
+ interest.setInterestLifetime(1000);
+ interest.setMustBeFresh(true);
+
+ m_face.expressInterest(interest,
+ bind(&Control::processPrefixActionResponse, this, _2, onSuccess, onFailure),
+ bind(onFailure));
+}
+
+void
+Control::processFaceActionResponse(const shared_ptr<Data>& data,
+ const FaceOperationSucceedCallback& onSuccess,
+ const FailCallback& onFail)
+{
+ Block content = data->getContent();
+ content.parse();
+
+ if (content.getAll().empty())
+ {
+ if (static_cast<bool>(onFail))
+ onFail();
+ return;
+ }
+
+ Block::element_iterator val = content.getAll().begin();
+
+ switch(val->type())
+ {
+ case Tlv::FaceManagement::FaceInstance:
+ {
+ FaceInstance entry;
+ entry.wireDecode(*val);
+
+ if (static_cast<bool>(onSuccess))
+ onSuccess(entry);
+ return;
+ }
+ case Tlv::FaceManagement::StatusResponse:
+ {
+ StatusResponse resp;
+ resp.wireDecode(*val);
+
+ if (static_cast<bool>(onFail))
+ onFail();
+ return;
+ }
+ default:
+ {
+ if (static_cast<bool>(onFail))
+ onFail();
+ return;
+ }
+ }
+}
+
+void
+Control::processPrefixActionResponse(const shared_ptr<Data>& data,
+ const PrefixOperationSucceedCallback& onSuccess,
+ const FailCallback& onFail)
+{
+ Block content = data->getContent();
+ content.parse();
+
+ if (content.getAll().empty())
+ {
+ if (static_cast<bool>(onFail))
+ onFail();
+ return;
+ }
+
+ Block::element_iterator val = content.getAll().begin();
+
+ switch(val->type())
+ {
+ case Tlv::FaceManagement::ForwardingEntry:
+ {
+ ForwardingEntry entry;
+ entry.wireDecode(*val);
+
+ if (static_cast<bool>(onSuccess))
+ onSuccess(entry);
+ return;
+ }
+ case Tlv::FaceManagement::StatusResponse:
+ {
+ StatusResponse resp;
+ resp.wireDecode(*val);
+
+ // std::cerr << "StatusReponse: " << resp << std::endl;
+
+ if (static_cast<bool>(onFail))
+ onFail();
+ return;
+ }
+ default:
+ {
+ if (static_cast<bool>(onFail))
+ onFail();
+ return;
+ }
+ }
+}
+
+} // namespace ndnd
+} // namespace ndn
diff --git a/src/management/ndnd-control.hpp b/src/management/ndnd-control.hpp
new file mode 100644
index 0000000..fd22f15
--- /dev/null
+++ b/src/management/ndnd-control.hpp
@@ -0,0 +1,109 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef NDN_MANAGEMENT_NDND_CONTROL_HPP
+#define NDN_MANAGEMENT_NDND_CONTROL_HPP
+
+#include "../common.hpp"
+
+namespace ndn {
+
+class Node;
+
+namespace ndnd {
+
+class FaceInstance;
+class ForwardingEntry;
+
+/*
+ * @brief Class implementing Face and Prefix management operations for ndnd-tlv
+ *
+ * ndnd::Control should be used when connecting to ndnd-tlv daemon
+ */
+class Control
+{
+public:
+ typedef function<void()> SuccessCallback;
+ typedef function<void()> FailCallback;
+
+ typedef function<void(const ForwardingEntry&)> PrefixOperationSucceedCallback;
+ typedef function<void(const FaceInstance&)> FaceOperationSucceedCallback;
+
+ /**
+ * @brief Construct ndnd::Control object
+ */
+ Control(Node& face);
+
+ void
+ selfRegisterPrefix(const Name& prefixToRegister,
+ const SuccessCallback& onSuccess,
+ const FailCallback& onFail);
+
+ void
+ selfDeregisterPrefix(const Name& prefixToRegister,
+ const SuccessCallback& onSuccess,
+ const FailCallback& onFail);
+
+protected:
+ void
+ startFaceAction(const FaceInstance& entry,
+ const FaceOperationSucceedCallback& onSuccess,
+ const FailCallback& onFailure);
+
+ void
+ startPrefixAction(const ForwardingEntry& entry,
+ const PrefixOperationSucceedCallback& onSuccess,
+ const FailCallback& onFailure);
+
+private:
+ void
+ onNdnidFetched(const shared_ptr<const Interest>& interest,
+ const shared_ptr<Data>& data);
+
+
+ void
+ recordSelfRegisteredFaceId(const ForwardingEntry& entry,
+ const SuccessCallback& onSuccess);
+
+ void
+ processFaceActionResponse(const shared_ptr<Data>& data,
+ const FaceOperationSucceedCallback& onSuccess,
+ const FailCallback& onFail);
+
+ void
+ processPrefixActionResponse(const shared_ptr<Data>& data,
+ const PrefixOperationSucceedCallback& onSuccess,
+ const FailCallback& onFail);
+
+private:
+ Node& m_face;
+ Block m_ndndId;
+ int64_t m_faceId; // internal face ID (needed for prefix de-registration)
+
+ struct FilterRequest
+ {
+ FilterRequest(const Name& prefixToRegister,
+ const SuccessCallback& onSuccess,
+ const FailCallback& onFailure)
+ : m_prefixToRegister(prefixToRegister)
+ , m_onSuccess(onSuccess)
+ , m_onFailure(onFailure)
+ {
+ }
+
+ Name m_prefixToRegister;
+ SuccessCallback m_onSuccess;
+ FailCallback m_onFailure;
+ };
+
+ typedef std::list<FilterRequest> FilterRequestList;
+ FilterRequestList m_filterRequests;
+};
+
+} // namespace ndnd
+} // namespace ndn
+
+#endif // NDN_MANAGEMENT_NDND_CONTROL_HPP
diff --git a/src/management/ndnd-face-instance.hpp b/src/management/ndnd-face-instance.hpp
new file mode 100644
index 0000000..03a8589
--- /dev/null
+++ b/src/management/ndnd-face-instance.hpp
@@ -0,0 +1,346 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef NDN_MANAGEMENT_NDND_FACE_INSTANCE_HPP
+#define NDN_MANAGEMENT_NDND_FACE_INSTANCE_HPP
+
+#include "../encoding/tlv-face-management.hpp"
+#include "../encoding/block.hpp"
+#include "../name.hpp"
+
+namespace ndn {
+namespace ndnd {
+
+/**
+ * An FaceInstance holds an action and Name prefix and other fields for an forwarding entry.
+ */
+class FaceInstance {
+public:
+ FaceInstance(const std::string &action,
+ int64_t faceId,
+ uint32_t ipProto,
+ const std::string &host,
+ const std::string &port,
+ const std::string &multicastInterface,
+ uint32_t multicastTtl,
+ Milliseconds freshnessPeriod)
+ : action_(action)
+ , faceId_(faceId)
+ , ipProto_(ipProto)
+ , host_(host)
+ , port_(port)
+ , multicastInterface_(multicastInterface)
+ , multicastTtl_(multicastTtl)
+ , freshnessPeriod_(freshnessPeriod)
+ {
+ }
+
+ FaceInstance()
+ : faceId_(-1)
+ , ipProto_(-1)
+ , multicastTtl_(-1)
+ , freshnessPeriod_(-1)
+ {
+ }
+
+ // Action
+ const std::string&
+ getAction() const { return action_; }
+
+ void
+ setAction(const std::string& action) { action_ = action; wire_.reset(); }
+
+ // FaceID
+ int64_t
+ getFaceId() const { return faceId_; }
+
+ void
+ setFaceId(int64_t faceId) { faceId_ = faceId; wire_.reset(); }
+
+ // IPProto
+ int32_t
+ getIpProto() const { return ipProto_; }
+
+ void
+ setIpProto(int32_t ipProto) { ipProto_ = ipProto; wire_.reset(); }
+
+ // Host
+ const std::string&
+ getHost() const { return host_; }
+
+ void
+ setHost(const std::string& host) { host_ = host; wire_.reset(); }
+
+ // Port
+ const std::string&
+ getPort() const { return port_; }
+
+ void
+ setPort(const std::string &port) { port_ = port; wire_.reset(); }
+
+ // MulticastInterface
+ const std::string&
+ getMulticastInterface() const { return multicastInterface_; }
+
+ void
+ setMulticastInterface(const std::string& multicastInterface) { multicastInterface_ = multicastInterface; wire_.reset(); }
+
+ // MulticastTTL
+ int32_t
+ getMulticastTtl() const { return multicastTtl_; }
+
+ void
+ setMulticastTtl(int32_t multicastTtl) { multicastTtl_ = multicastTtl; wire_.reset(); }
+
+ // Freshness
+ int
+ getFreshnessPeriod() const { return freshnessPeriod_; }
+
+ void
+ setFreshnessPeriod(int freshnessPeriod) { freshnessPeriod_ = freshnessPeriod; wire_.reset(); }
+
+ // Wire
+ inline const Block&
+ wireEncode() const;
+
+ inline void
+ wireDecode(const Block &wire);
+
+private:
+ std::string action_;
+ int64_t faceId_;
+ int32_t ipProto_;
+ std::string host_;
+ std::string port_;
+ std::string multicastInterface_;
+ int32_t multicastTtl_;
+ Milliseconds freshnessPeriod_;
+
+ mutable Block wire_;
+};
+
+inline const Block&
+FaceInstance::wireEncode() const
+{
+ if (wire_.hasWire())
+ return wire_;
+
+ // FaceInstance ::= FACE-INSTANCE-TYPE TLV-LENGTH
+ // Action?
+ // FaceID?
+ // IPProto?
+ // Host?
+ // Port?
+ // MulticastInterface?
+ // MulticastTTL?
+ // FreshnessPeriod?
+
+ wire_ = Block(Tlv::FaceManagement::FaceInstance);
+
+ // Action
+ if (!action_.empty())
+ {
+ wire_.push_back
+ (dataBlock(Tlv::FaceManagement::Action, action_.c_str(), action_.size()));
+ }
+
+ // FaceID
+ if (faceId_ >= 0)
+ {
+ wire_.push_back
+ (nonNegativeIntegerBlock(Tlv::FaceManagement::FaceID, faceId_));
+ }
+
+ // IPProto
+ if (ipProto_ >= 0)
+ {
+ wire_.push_back
+ (nonNegativeIntegerBlock(Tlv::FaceManagement::IPProto, ipProto_));
+ }
+
+ // Host
+ if (!host_.empty())
+ {
+ wire_.push_back
+ (dataBlock(Tlv::FaceManagement::Host, host_.c_str(), host_.size()));
+ }
+
+ // Port
+ if (!port_.empty())
+ {
+ wire_.push_back
+ (dataBlock(Tlv::FaceManagement::Port, port_.c_str(), port_.size()));
+ }
+
+ // MulticastInterface
+ if (!multicastInterface_.empty())
+ {
+ wire_.push_back
+ (dataBlock(Tlv::FaceManagement::MulticastInterface, multicastInterface_.c_str(), multicastInterface_.size()));
+ }
+
+ // MulticastTTL
+ if (multicastTtl_ >= 0)
+ {
+ wire_.push_back
+ (nonNegativeIntegerBlock(Tlv::FaceManagement::MulticastTTL, multicastTtl_));
+ }
+
+ // FreshnessPeriod
+ if (freshnessPeriod_ >= 0)
+ {
+ wire_.push_back
+ (nonNegativeIntegerBlock(Tlv::FreshnessPeriod, freshnessPeriod_));
+ }
+
+ wire_.encode();
+ return wire_;
+}
+
+inline void
+FaceInstance::wireDecode(const Block &wire)
+{
+ action_.clear();
+ faceId_ = -1;
+ ipProto_ = -1;
+ host_.clear();
+ port_.clear();
+ multicastInterface_.clear();
+ multicastTtl_ = -1;
+ freshnessPeriod_ = -1;
+
+ wire_ = wire;
+ wire_.parse();
+
+ // FaceInstance ::= FACE-INSTANCE-TYPE TLV-LENGTH
+ // Action?
+ // FaceID?
+ // IPProto?
+ // Host?
+ // Port?
+ // MulticastInterface?
+ // MulticastTTL?
+ // FreshnessPeriod?
+
+ // Action
+ Block::element_iterator val = wire_.find(Tlv::FaceManagement::Action);
+ if (val != wire_.getAll().end())
+ {
+ action_ = std::string(reinterpret_cast<const char*>(val->value()), val->value_size());
+ }
+
+ // FaceID
+ val = wire_.find(Tlv::FaceManagement::FaceID);
+ if (val != wire_.getAll().end())
+ {
+ faceId_ = readNonNegativeInteger(*val);
+ }
+
+ // IPProto
+ val = wire_.find(Tlv::FaceManagement::IPProto);
+ if (val != wire_.getAll().end())
+ {
+ ipProto_ = readNonNegativeInteger(*val);
+ }
+
+ // Host
+ val = wire_.find(Tlv::FaceManagement::Host);
+ if (val != wire_.getAll().end())
+ {
+ host_ = std::string(reinterpret_cast<const char*>(val->value()), val->value_size());
+ }
+
+ // Port
+ val = wire_.find(Tlv::FaceManagement::Port);
+ if (val != wire_.getAll().end())
+ {
+ port_ = std::string(reinterpret_cast<const char*>(val->value()), val->value_size());
+ }
+
+ // MulticastInterface
+ val = wire_.find(Tlv::FaceManagement::MulticastInterface);
+ if (val != wire_.getAll().end())
+ {
+ multicastInterface_ = std::string(reinterpret_cast<const char*>(val->value()), val->value_size());
+ }
+
+ // MulticastTTL
+ val = wire_.find(Tlv::FaceManagement::MulticastTTL);
+ if (val != wire_.getAll().end())
+ {
+ multicastTtl_ = readNonNegativeInteger(*val);
+ }
+
+ // FreshnessPeriod
+ val = wire_.find(Tlv::FreshnessPeriod);
+ if (val != wire_.getAll().end())
+ {
+ freshnessPeriod_ = readNonNegativeInteger(*val);
+ }
+}
+
+inline std::ostream&
+operator << (std::ostream &os, const FaceInstance &entry)
+{
+ os << "FaceInstance(";
+
+ // Action
+ if (!entry.getAction().empty())
+ {
+ os << "Action:" << entry.getAction() << ", ";
+ }
+
+ // FaceID
+ if (entry.getFaceId() >= 0)
+ {
+ os << "FaceID:" << entry.getFaceId() << ", ";
+ }
+
+ // IPProto
+ if (entry.getIpProto() >= 0)
+ {
+ os << "IPProto:" << entry.getIpProto() << ", ";
+ }
+
+ // Host
+ if (!entry.getHost().empty())
+ {
+ os << "Host:" << entry.getHost() << ", ";
+ }
+
+ // Port
+ if (!entry.getPort().empty())
+ {
+ os << "Port:" << entry.getPort() << ", ";
+ }
+
+ // MulticastInterface
+ if (!entry.getMulticastInterface().empty())
+ {
+ os << "MulticastInterface:" << entry.getMulticastInterface() << ", ";
+ }
+
+ // MulticastTTL
+ if (entry.getMulticastTtl() >= 0)
+ {
+ os << "MulticastTTL:" << entry.getMulticastTtl() << ", ";
+ }
+
+ // FreshnessPeriod
+ if (entry.getFreshnessPeriod() >= 0)
+ {
+ os << "FreshnessPeriod:" << entry.getFreshnessPeriod() << ", ";
+ }
+
+ os << ")";
+ return os;
+}
+
+} // namespace ndnd
+} // namespace ndn
+
+#endif // NDN_MANAGEMENT_NDND_FACE_INSTANCE_HPP
+
diff --git a/src/management/ndnd-forwarding-entry.hpp b/src/management/ndnd-forwarding-entry.hpp
new file mode 100644
index 0000000..0a02c7e
--- /dev/null
+++ b/src/management/ndnd-forwarding-entry.hpp
@@ -0,0 +1,228 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef NDN_MANAGEMENT_NDND_FORWARDING_ENTRY_HPP
+#define NDN_MANAGEMENT_NDND_FORWARDING_ENTRY_HPP
+
+#include "../encoding/tlv-face-management.hpp"
+#include "../name.hpp"
+#include "../encoding/block.hpp"
+
+#include "ndnd-forwarding-flags.hpp"
+
+namespace ndn {
+namespace ndnd {
+
+/**
+ * An ForwardingEntry holds an action and Name prefix and other fields for an forwarding entry.
+ */
+class ForwardingEntry {
+public:
+ ForwardingEntry(const std::string& action,
+ const Name& prefix,
+ int faceId = -1,
+ const ForwardingFlags& forwardingFlags = ForwardingFlags(),
+ int freshnessPeriod = -1)
+ : action_(action)
+ , prefix_(prefix)
+ , faceId_(faceId)
+ , forwardingFlags_(forwardingFlags)
+ , freshnessPeriod_(freshnessPeriod)
+ {
+ }
+
+ ForwardingEntry()
+ : faceId_(-1)
+ , freshnessPeriod_(-1)
+ {
+ }
+
+ const std::string&
+ getAction() const { return action_; }
+
+ void
+ setAction(const std::string& action) { action_ = action; wire_.reset(); }
+
+ const Name&
+ getPrefix() const { return prefix_; }
+
+ void
+ setPrefix(const Name &prefix) { prefix_ = prefix; wire_.reset(); }
+
+ int
+ getFaceId() const { return faceId_; }
+
+ void
+ setFaceId(int faceId) { faceId_ = faceId; wire_.reset(); }
+
+ const ForwardingFlags&
+ getForwardingFlags() const { return forwardingFlags_; }
+
+ void
+ setForwardingFlags(const ForwardingFlags& forwardingFlags) { forwardingFlags_ = forwardingFlags; wire_.reset(); }
+
+ int
+ getFreshnessPeriod() const { return freshnessPeriod_; }
+
+ void
+ setFreshnessPeriod(int freshnessPeriod) { freshnessPeriod_ = freshnessPeriod; wire_.reset(); }
+
+ inline const Block&
+ wireEncode() const;
+
+ inline void
+ wireDecode(const Block &wire);
+
+private:
+ std::string action_; /**< empty for none. */
+ Name prefix_;
+ int faceId_; /**< -1 for none. */
+ ForwardingFlags forwardingFlags_;
+ int freshnessPeriod_; /**< -1 for none. */
+
+ mutable Block wire_;
+};
+
+inline const Block&
+ForwardingEntry::wireEncode() const
+{
+ if (wire_.hasWire())
+ return wire_;
+
+ // ForwardingEntry ::= FORWARDING-ENTRY TLV-LENGTH
+ // Action?
+ // Name?
+ // FaceID?
+ // ForwardingFlags?
+ // FreshnessPeriod?
+
+ wire_ = Block(Tlv::FaceManagement::ForwardingEntry);
+
+ // Action
+ if (!action_.empty())
+ {
+ wire_.push_back
+ (dataBlock(Tlv::FaceManagement::Action, action_.c_str(), action_.size()));
+ }
+
+ // Name
+ wire_.push_back
+ (prefix_.wireEncode());
+
+ // FaceID
+ if (faceId_ >= 0)
+ {
+ wire_.push_back
+ (nonNegativeIntegerBlock(Tlv::FaceManagement::FaceID, faceId_));
+ }
+
+ // ForwardingFlags
+ wire_.push_back
+ (forwardingFlags_.wireEncode());
+
+ // FreshnessPeriod
+ if (freshnessPeriod_ >= 0)
+ {
+ wire_.push_back
+ (nonNegativeIntegerBlock(Tlv::FreshnessPeriod, freshnessPeriod_));
+ }
+
+ wire_.encode();
+ return wire_;
+}
+
+inline void
+ForwardingEntry::wireDecode(const Block &wire)
+{
+ action_.clear();
+ prefix_.clear();
+ faceId_ = -1;
+ forwardingFlags_ = ForwardingFlags();
+ freshnessPeriod_ = -1;
+
+ wire_ = wire;
+ wire_.parse();
+
+ // ForwardingEntry ::= FORWARDING-ENTRY TLV-LENGTH
+ // Action?
+ // Name?
+ // FaceID?
+ // ForwardingFlags?
+ // FreshnessPeriod?
+
+ // Action
+ Block::element_iterator val = wire_.find(Tlv::FaceManagement::Action);
+ if (val != wire_.getAll().end())
+ {
+ action_ = std::string(reinterpret_cast<const char*>(val->value()), val->value_size());
+ }
+
+ // Name
+ val = wire_.find(Tlv::Name);
+ if (val != wire_.getAll().end())
+ {
+ prefix_.wireDecode(*val);
+ }
+
+ // FaceID
+ val = wire_.find(Tlv::FaceManagement::FaceID);
+ if (val != wire_.getAll().end())
+ {
+ faceId_ = readNonNegativeInteger(*val);
+ }
+
+ // ForwardingFlags
+ val = wire_.find(Tlv::FaceManagement::ForwardingFlags);
+ if (val != wire_.getAll().end())
+ {
+ forwardingFlags_.wireDecode(*val);
+ }
+
+ // FreshnessPeriod
+ val = wire_.find(Tlv::FreshnessPeriod);
+ if (val != wire_.getAll().end())
+ {
+ freshnessPeriod_ = readNonNegativeInteger(*val);
+ }
+}
+
+inline std::ostream&
+operator << (std::ostream &os, const ForwardingEntry &entry)
+{
+ os << "ForwardingEntry(";
+
+ // Action
+ if (!entry.getAction().empty())
+ {
+ os << "Action:" << entry.getAction() << ", ";
+ }
+
+ // Name
+ os << "Prefix:" << entry.getPrefix() << ", ";
+
+ // FaceID
+ if (entry.getFaceId() >= 0)
+ {
+ os << "FaceID:" << entry.getFaceId() << ", ";
+ }
+
+ // ForwardingFlags
+ os << "ForwardingFlags:" << entry.getForwardingFlags() << ", ";
+
+ // FreshnessPeriod
+ if (entry.getFreshnessPeriod() >= 0)
+ {
+ os << "FreshnessPeriod:" << entry.getFreshnessPeriod() << ", ";
+ }
+
+ os << ")";
+ return os;
+}
+
+} // namespace ndnd
+} // namespace ndn
+
+#endif // NDN_MANAGEMENT_NDND_FORWARDING_ENTRY_HPP
diff --git a/src/management/ndnd-forwarding-flags.hpp b/src/management/ndnd-forwarding-flags.hpp
new file mode 100644
index 0000000..8b4ce78
--- /dev/null
+++ b/src/management/ndnd-forwarding-flags.hpp
@@ -0,0 +1,226 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef NDN_FORWARDING_FLAGS_HPP
+#define NDN_FORWARDING_FLAGS_HPP
+
+#include "../encoding/block.hpp"
+#include "../encoding/tlv-face-management.hpp"
+
+namespace ndn {
+namespace ndnd {
+
+/**
+ * A ForwardingFlags object holds the flags which specify how the forwarding daemon should forward an interest for
+ * a registered prefix. We use a separate ForwardingFlags object to retain future compatibility if the daemon forwarding
+ * bits are changed, amended or deprecated.
+ */
+class ForwardingFlags {
+public:
+ /**
+ * Create a new ForwardingFlags with "active" and "childInherit" set and all other flags cleared.
+ */
+ ForwardingFlags()
+ : active_(true)
+ , childInherit_(true)
+ , advertise_(false)
+ , last_(false)
+ , capture_(false)
+ , local_(false)
+ , tap_(false)
+ , captureOk_(false)
+ {
+ }
+
+ /**
+ * Get the value of the "active" flag.
+ * @return true if the flag is set, false if it is cleared.
+ */
+ bool getActive() const { return active_; }
+
+ /**
+ * Get the value of the "childInherit" flag.
+ * @return true if the flag is set, false if it is cleared.
+ */
+ bool getChildInherit() const { return childInherit_; }
+
+ /**
+ * Get the value of the "advertise" flag.
+ * @return true if the flag is set, false if it is cleared.
+ */
+ bool getAdvertise() const { return advertise_; }
+
+ /**
+ * Get the value of the "last" flag.
+ * @return true if the flag is set, false if it is cleared.
+ */
+ bool getLast() const { return last_; }
+
+ /**
+ * Get the value of the "capture" flag.
+ * @return true if the flag is set, false if it is cleared.
+ */
+ bool getCapture() const { return capture_; }
+
+ /**
+ * Get the value of the "local" flag.
+ * @return true if the flag is set, false if it is cleared.
+ */
+ bool getLocal() const { return local_; }
+
+ /**
+ * Get the value of the "tap" flag.
+ * @return true if the flag is set, false if it is cleared.
+ */
+ bool getTap() const { return tap_; }
+
+ /**
+ * Get the value of the "captureOk" flag.
+ * @return true if the flag is set, false if it is cleared.
+ */
+ bool getCaptureOk() const { return captureOk_; }
+
+ /**
+ * Set the value of the "active" flag
+ * @param active true to set the flag, false to clear it.
+ */
+ void setActive(bool active) { this->active_ = active; wire_.reset(); }
+
+ /**
+ * Set the value of the "childInherit" flag
+ * @param childInherit true to set the flag, false to clear it.
+ */
+ void setChildInherit(bool childInherit) { this->childInherit_ = childInherit; wire_.reset(); }
+
+ /**
+ * Set the value of the "advertise" flag
+ * @param advertise true to set the flag, false to clear it.
+ */
+ void setAdvertise(bool advertise) { this->advertise_ = advertise; wire_.reset(); }
+
+ /**
+ * Set the value of the "last" flag
+ * @param last true to set the flag, false to clear it.
+ */
+ void setLast(bool last) { this->last_ = last; wire_.reset(); }
+
+ /**
+ * Set the value of the "capture" flag
+ * @param capture true to set the flag, false to clear it.
+ */
+ void setCapture(bool capture) { this->capture_ = capture; wire_.reset(); }
+
+ /**
+ * Set the value of the "local" flag
+ * @param local true to set the flag, false to clear it.
+ */
+ void setLocal(bool local) { this->local_ = local; wire_.reset(); }
+
+ /**
+ * Set the value of the "tap" flag
+ * @param tap true to set the flag, false to clear it.
+ */
+ void setTap(bool tap) { this->tap_ = tap; wire_.reset(); }
+
+ /**
+ * Set the value of the "captureOk" flag
+ * @param captureOk true to set the flag, false to clear it.
+ */
+ void setCaptureOk(bool captureOk) { this->captureOk_ = captureOk; wire_.reset(); }
+
+ inline const Block&
+ wireEncode() const;
+
+ inline void
+ wireDecode(const Block &block);
+
+private:
+ bool active_;
+ bool childInherit_;
+ bool advertise_;
+ bool last_;
+ bool capture_;
+ bool local_;
+ bool tap_;
+ bool captureOk_;
+
+ mutable Block wire_;
+};
+
+inline const Block&
+ForwardingFlags::wireEncode() const
+{
+ if (wire_.hasWire())
+ return wire_;
+
+ uint32_t result = 0;
+ if (active_)
+ result |= Tlv::FaceManagement::FORW_ACTIVE;
+ if (childInherit_)
+ result |= Tlv::FaceManagement::FORW_CHILD_INHERIT;
+ if (advertise_)
+ result |= Tlv::FaceManagement::FORW_ADVERTISE;
+ if (last_)
+ result |= Tlv::FaceManagement::FORW_LAST;
+ if (capture_)
+ result |= Tlv::FaceManagement::FORW_CAPTURE;
+ if (local_)
+ result |= Tlv::FaceManagement::FORW_LOCAL;
+ if (tap_)
+ result |= Tlv::FaceManagement::FORW_TAP;
+ if (captureOk_)
+ result |= Tlv::FaceManagement::FORW_CAPTURE_OK;
+
+ wire_ = nonNegativeIntegerBlock(Tlv::FaceManagement::ForwardingFlags, result);
+
+ return wire_;
+}
+
+inline void
+ForwardingFlags::wireDecode(const Block &wire)
+{
+ wire_ = wire;
+
+ uint32_t flags = readNonNegativeInteger(wire_);
+
+ active_ = (flags & Tlv::FaceManagement::FORW_ACTIVE) ? true : false;
+ childInherit_ = (flags & Tlv::FaceManagement::FORW_CHILD_INHERIT) ? true : false;
+ advertise_ = (flags & Tlv::FaceManagement::FORW_ADVERTISE) ? true : false;
+ last_ = (flags & Tlv::FaceManagement::FORW_LAST) ? true : false;
+ capture_ = (flags & Tlv::FaceManagement::FORW_CAPTURE) ? true : false;
+ local_ = (flags & Tlv::FaceManagement::FORW_LOCAL) ? true : false;
+ tap_ = (flags & Tlv::FaceManagement::FORW_TAP) ? true : false;
+ captureOk_ = (flags & Tlv::FaceManagement::FORW_CAPTURE_OK) ? true : false;
+}
+
+inline std::ostream&
+operator << (std::ostream &os, const ForwardingFlags &flags)
+{
+ if (flags.getActive())
+ os << "ACTIVE ";
+ if (flags.getChildInherit())
+ os << "CHILE_INHERIT ";
+ if (flags.getAdvertise())
+ os << "ADVERTISE ";
+ if (flags.getLast())
+ os << "LAST ";
+ if (flags.getCapture())
+ os << "CAPTURE ";
+ if (flags.getLocal())
+ os << "LOCAL ";
+ if (flags.getTap())
+ os << "TAP ";
+ if (flags.getCaptureOk())
+ os << "CAPTURE_OK ";
+
+ return os;
+}
+
+} // namespace ndnd
+} // namespace ndn
+
+#endif
diff --git a/src/management/ndnd-status-response.hpp b/src/management/ndnd-status-response.hpp
new file mode 100644
index 0000000..1543bed
--- /dev/null
+++ b/src/management/ndnd-status-response.hpp
@@ -0,0 +1,126 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef NDN_MANAGEMENT_NDND_STATUS_RESPONSE_HPP
+#define NDN_MANAGEMENT_NDND_STATUS_RESPONSE_HPP
+
+#include "../encoding/block.hpp"
+#include "../encoding/tlv-face-management.hpp"
+
+namespace ndn {
+namespace ndnd {
+
+class StatusResponse {
+public:
+ StatusResponse()
+ : code_(0)
+ {
+ }
+
+ StatusResponse(uint32_t code, const std::string &info)
+ : code_(code)
+ , info_(info)
+ {
+ }
+
+ inline uint32_t
+ getCode() const;
+
+ inline void
+ setCode(uint32_t code);
+
+ inline const std::string &
+ getInfo() const;
+
+ inline void
+ setInfo(const std::string &info);
+
+ inline const Block&
+ wireEncode() const;
+
+ inline void
+ wireDecode(const Block &block);
+
+private:
+ uint32_t code_;
+ std::string info_;
+
+ mutable Block wire_;
+};
+
+inline uint32_t
+StatusResponse::getCode() const
+{
+ return code_;
+}
+
+inline void
+StatusResponse::setCode(uint32_t code)
+{
+ code_ = code;
+ wire_.reset();
+}
+
+inline const std::string &
+StatusResponse::getInfo() const
+{
+ return info_;
+}
+
+inline void
+StatusResponse::setInfo(const std::string &info)
+{
+ info_ = info;
+ wire_.reset();
+}
+
+
+inline const Block&
+StatusResponse::wireEncode() const
+{
+ if (wire_.hasWire())
+ return wire_;
+
+ wire_ = Block(Tlv::FaceManagement::StatusResponse);
+ wire_.push_back
+ (nonNegativeIntegerBlock(Tlv::FaceManagement::StatusCode, code_));
+
+ if (!info_.empty())
+ {
+ wire_.push_back
+ (dataBlock(Tlv::FaceManagement::StatusText, info_.c_str(), info_.size()));
+ }
+
+ wire_.encode();
+ return wire_;
+}
+
+inline void
+StatusResponse::wireDecode(const Block &wire)
+{
+ wire_ = wire;
+ wire_.parse();
+
+ code_ = readNonNegativeInteger(wire_.get(Tlv::FaceManagement::StatusCode));
+
+ Block::element_iterator val = wire_.find(Tlv::FaceManagement::StatusText);
+ if (val != wire_.getAll().end())
+ {
+ info_.assign(reinterpret_cast<const char*>(val->value()), val->value_size());
+ }
+}
+
+inline std::ostream&
+operator << (std::ostream &os, const StatusResponse &status)
+{
+ os << status.getCode() << " " << status.getInfo();
+ return os;
+}
+
+} // namespace ndnd
+} // namespace ndn
+
+#endif // NDN_MANAGEMENT_NDND_STATUS_RESPONSE_HPP
diff --git a/src/management/nfd-control.hpp b/src/management/nfd-control.hpp
new file mode 100644
index 0000000..642afd8
--- /dev/null
+++ b/src/management/nfd-control.hpp
@@ -0,0 +1,14 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef NDN_MANAGEMENT_NFD_CONTROL_HPP
+#define NDN_MANAGEMENT_NFD_CONTROL_HPP
+
+namespace ndn {
+
+} // namespace ndn
+
+#endif // NDN_MANAGEMENT_NFD_CONTROL_HPP