mgmt: add face/list support and general purpose data segementer
refs: #1245
Change-Id: I3769941022b7ed6e2a8d39622032e4e16909f645
diff --git a/daemon/mgmt/face-manager.cpp b/daemon/mgmt/face-manager.cpp
index 701bddd..bf31a10 100644
--- a/daemon/mgmt/face-manager.cpp
+++ b/daemon/mgmt/face-manager.cpp
@@ -9,7 +9,6 @@
#include "core/face-uri.hpp"
#include "core/network-interface.hpp"
#include "fw/face-table.hpp"
-
#include "face/tcp-factory.hpp"
#include "face/udp-factory.hpp"
@@ -25,7 +24,7 @@
NFD_LOG_INIT("FaceManager");
-const Name FaceManager::COMMAND_PREFIX = "/localhost/nfd/faces";
+const Name FaceManager::COMMAND_PREFIX("/localhost/nfd/faces");
const size_t FaceManager::COMMAND_UNSIGNED_NCOMPS =
FaceManager::COMMAND_PREFIX.size() +
@@ -36,28 +35,44 @@
FaceManager::COMMAND_UNSIGNED_NCOMPS +
4; // (timestamp, nonce, signed info tlv, signature tlv)
-const FaceManager::VerbAndProcessor FaceManager::COMMAND_VERBS[] =
+const FaceManager::SignedVerbAndProcessor FaceManager::SIGNED_COMMAND_VERBS[] =
{
- VerbAndProcessor(
+ SignedVerbAndProcessor(
Name::Component("create"),
&FaceManager::createFace
),
- VerbAndProcessor(
+ SignedVerbAndProcessor(
Name::Component("destroy"),
&FaceManager::destroyFace
),
};
+const FaceManager::UnsignedVerbAndProcessor FaceManager::UNSIGNED_COMMAND_VERBS[] =
+ {
+ UnsignedVerbAndProcessor(
+ Name::Component("list"),
+ &FaceManager::listFaces
+ ),
+ };
+
+const Name FaceManager::LIST_COMMAND_PREFIX("/localhost/nfd/faces/list");
+const size_t FaceManager::LIST_COMMAND_NCOMPS = LIST_COMMAND_PREFIX.size();
+
FaceManager::FaceManager(FaceTable& faceTable,
shared_ptr<InternalFace> face)
: ManagerBase(face, FACE_MANAGER_PRIVILEGE)
, m_faceTable(faceTable)
- , m_verbDispatch(COMMAND_VERBS,
- COMMAND_VERBS +
- (sizeof(COMMAND_VERBS) / sizeof(VerbAndProcessor)))
+ , m_statusPublisher(m_faceTable, m_face, LIST_COMMAND_PREFIX)
+ , m_signedVerbDispatch(SIGNED_COMMAND_VERBS,
+ SIGNED_COMMAND_VERBS +
+ (sizeof(SIGNED_COMMAND_VERBS) / sizeof(SignedVerbAndProcessor)))
+ , m_unsignedVerbDispatch(UNSIGNED_COMMAND_VERBS,
+ UNSIGNED_COMMAND_VERBS +
+ (sizeof(UNSIGNED_COMMAND_VERBS) / sizeof(UnsignedVerbAndProcessor)))
+
{
face->setInterestFilter("/localhost/nfd/faces",
bind(&FaceManager::onFaceRequest, this, _2));
@@ -487,26 +502,32 @@
{
const Name& command = request.getName();
const size_t commandNComps = command.size();
+ const Name::Component& verb = command.get(COMMAND_PREFIX.size());
- if (COMMAND_UNSIGNED_NCOMPS <= commandNComps &&
+ UnsignedVerbDispatchTable::const_iterator unsignedVerbProcessor = m_unsignedVerbDispatch.find(verb);
+ if (unsignedVerbProcessor != m_unsignedVerbDispatch.end())
+ {
+ NFD_LOG_INFO("command result: processing verb: " << verb);
+ (unsignedVerbProcessor->second)(this, boost::cref(request));
+ }
+ else if (COMMAND_UNSIGNED_NCOMPS <= commandNComps &&
commandNComps < COMMAND_SIGNED_NCOMPS)
{
NFD_LOG_INFO("command result: unsigned verb: " << command);
sendResponse(command, 401, "Signature required");
-
- return;
}
else if (commandNComps < COMMAND_SIGNED_NCOMPS ||
!COMMAND_PREFIX.isPrefixOf(command))
{
NFD_LOG_INFO("command result: malformed");
sendResponse(command, 400, "Malformed command");
- return;
}
-
- validate(request,
- bind(&FaceManager::onValidatedFaceRequest, this, _1),
- bind(&ManagerBase::onCommandValidationFailed, this, _1, _2));
+ else
+ {
+ validate(request,
+ bind(&FaceManager::onValidatedFaceRequest, this, _1),
+ bind(&ManagerBase::onCommandValidationFailed, this, _1, _2));
+ }
}
void
@@ -515,8 +536,8 @@
const Name& command = request->getName();
const Name::Component& verb = command.get(COMMAND_PREFIX.size());
- VerbDispatchTable::const_iterator verbProcessor = m_verbDispatch.find (verb);
- if (verbProcessor != m_verbDispatch.end())
+ SignedVerbDispatchTable::const_iterator signedVerbProcessor = m_signedVerbDispatch.find(verb);
+ if (signedVerbProcessor != m_signedVerbDispatch.end())
{
ndn::nfd::FaceManagementOptions options;
if (!extractOptions(*request, options))
@@ -526,7 +547,7 @@
}
NFD_LOG_INFO("command result: processing verb: " << verb);
- (verbProcessor->second)(this, command, options);
+ (signedVerbProcessor->second)(this, command, options);
}
else
{
@@ -617,6 +638,21 @@
sendResponse(requestName, 200, "Success");
}
+void
+FaceManager::listFaces(const Interest& request)
+{
+ const Name& command = request.getName();
+ const size_t commandNComps = command.size();
+ if (commandNComps < LIST_COMMAND_NCOMPS ||
+ !LIST_COMMAND_PREFIX.isPrefixOf(command))
+ {
+ NFD_LOG_INFO("command result: malformed");
+ sendResponse(command, 400, "Malformed command");
+ return;
+ }
+
+ m_statusPublisher.publish();
+}
} // namespace nfd
diff --git a/daemon/mgmt/face-manager.hpp b/daemon/mgmt/face-manager.hpp
index 55e4df4..4139152 100644
--- a/daemon/mgmt/face-manager.hpp
+++ b/daemon/mgmt/face-manager.hpp
@@ -12,6 +12,8 @@
#include "mgmt/app-face.hpp"
#include "mgmt/manager-base.hpp"
#include "mgmt/config-file.hpp"
+#include "mgmt/face-status-publisher.hpp"
+#include "fw/face-table.hpp"
#include <ndn-cpp-dev/management/nfd-face-management-options.hpp>
#include <ndn-cpp-dev/management/nfd-control-response.hpp>
@@ -19,15 +21,16 @@
namespace nfd {
const std::string FACE_MANAGER_PRIVILEGE = "faces";
-class FaceTable;
+
class ProtocolFactory;
class NetworkInterfaceInfo;
class FaceManager : public ManagerBase
{
public:
- struct Error : public ManagerBase::Error
+ class Error : public ManagerBase::Error
{
+ public:
Error(const std::string& what) : ManagerBase::Error(what) {}
};
@@ -49,6 +52,10 @@
void
onFaceRequest(const Interest& request);
+PUBLIC_WITH_TESTS_ELSE_PRIVATE:
+ void
+ listFaces(const Interest& request);
+
PROTECTED_WITH_TESTS_ELSE_PRIVATE:
void
@@ -107,28 +114,39 @@
typedef std::map< std::string/*protocol*/, shared_ptr<ProtocolFactory> > FactoryMap;
FactoryMap m_factories;
FaceTable& m_faceTable;
+ FaceStatusPublisher m_statusPublisher;
typedef function<void(FaceManager*,
const Name&,
- ndn::nfd::FaceManagementOptions&)> VerbProcessor;
+ ndn::nfd::FaceManagementOptions&)> SignedVerbProcessor;
- typedef std::map<Name::Component, VerbProcessor> VerbDispatchTable;
+ typedef std::map<Name::Component, SignedVerbProcessor> SignedVerbDispatchTable;
+ typedef std::pair<Name::Component, SignedVerbProcessor> SignedVerbAndProcessor;
- typedef std::pair<Name::Component, VerbProcessor> VerbAndProcessor;
+ typedef function<void(FaceManager*, const Interest&)> UnsignedVerbProcessor;
- const VerbDispatchTable m_verbDispatch;
+ typedef std::map<Name::Component, UnsignedVerbProcessor> UnsignedVerbDispatchTable;
+ typedef std::pair<Name::Component, UnsignedVerbProcessor> UnsignedVerbAndProcessor;
- static const Name COMMAND_PREFIX; // /localhost/nfd/fib
- // number of components in an invalid, but not malformed, unsigned command.
- // (/localhost/nfd/fib + verb + options) = 5
+ const SignedVerbDispatchTable m_signedVerbDispatch;
+ const UnsignedVerbDispatchTable m_unsignedVerbDispatch;
+
+ static const Name COMMAND_PREFIX; // /localhost/nfd/faces
+
+ // number of components in an invalid signed command (i.e. should be signed, but isn't)
+ // (/localhost/nfd/faces + verb + options) = 5
static const size_t COMMAND_UNSIGNED_NCOMPS;
- // number of components in a valid signed Interest.
+ // number of components in a valid signed command.
// (see UNSIGNED_NCOMPS), 9 with signed Interest support.
static const size_t COMMAND_SIGNED_NCOMPS;
- static const VerbAndProcessor COMMAND_VERBS[];
+ static const SignedVerbAndProcessor SIGNED_COMMAND_VERBS[];
+ static const UnsignedVerbAndProcessor UNSIGNED_COMMAND_VERBS[];
+
+ static const Name LIST_COMMAND_PREFIX;
+ static const size_t LIST_COMMAND_NCOMPS;
};
inline bool
diff --git a/daemon/mgmt/face-status-publisher.cpp b/daemon/mgmt/face-status-publisher.cpp
new file mode 100644
index 0000000..2cf2603
--- /dev/null
+++ b/daemon/mgmt/face-status-publisher.cpp
@@ -0,0 +1,76 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (C) 2014 Named Data Networking Project
+ * See COPYING for copyright and distribution information.
+ */
+#include "face-status-publisher.hpp"
+
+namespace nfd {
+
+NFD_LOG_INIT("FaceStatusPublisher");
+
+
+FaceStatusPublisher::FaceStatusPublisher(const FaceTable& faceTable,
+ shared_ptr<AppFace> face,
+ const Name& prefix)
+ : SegmentPublisher(face, prefix)
+ , m_faceTable(faceTable)
+{
+
+}
+
+
+FaceStatusPublisher::~FaceStatusPublisher()
+{
+
+}
+
+size_t
+FaceStatusPublisher::generate(ndn::EncodingBuffer& outBuffer)
+{
+ size_t totalLength = 0;
+
+ for (FaceTable::const_iterator i = m_faceTable.begin();
+ i != m_faceTable.end();
+ ++i)
+ {
+ const shared_ptr<Face>& face = *i;
+ const FaceCounters& counters = face->getCounters();
+ const std::string uri = face->getUri().toString();
+
+ size_t statusLength = 0;
+
+ statusLength += prependNonNegativeIntegerBlock(outBuffer,
+ ndn::tlv::nfd::TotalOutgoingDataCounter,
+ counters.getOutData());
+
+ statusLength += prependNonNegativeIntegerBlock(outBuffer,
+ ndn::tlv::nfd::TotalOutgoingInterestCounter,
+ counters.getOutInterest());
+
+ statusLength += prependNonNegativeIntegerBlock(outBuffer,
+ ndn::tlv::nfd::TotalIncomingDataCounter,
+ counters.getInData());
+
+ statusLength += prependNonNegativeIntegerBlock(outBuffer,
+ ndn::tlv::nfd::TotalIncomingInterestCounter,
+ counters.getInInterest());
+
+ statusLength += prependByteArrayBlock(outBuffer,
+ ndn::tlv::nfd::Uri,
+ reinterpret_cast<const uint8_t*>(uri.c_str()),
+ uri.size());
+
+ statusLength += prependNonNegativeIntegerBlock(outBuffer,
+ ndn::tlv::nfd::FaceId,
+ face->getId());
+
+ statusLength += outBuffer.prependVarNumber(statusLength);
+ statusLength += outBuffer.prependVarNumber(ndn::tlv::nfd::FaceStatus);
+
+ totalLength += statusLength;
+ }
+ return totalLength;
+}
+
+} // namespace nfd
diff --git a/daemon/mgmt/face-status-publisher.hpp b/daemon/mgmt/face-status-publisher.hpp
new file mode 100644
index 0000000..2006462
--- /dev/null
+++ b/daemon/mgmt/face-status-publisher.hpp
@@ -0,0 +1,36 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (C) 2014 Named Data Networking Project
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef NFD_MGMT_FACE_STATUS_PUBLISHER_HPP
+#define NFD_MGMT_FACE_STATUS_PUBLISHER_HPP
+
+#include "fw/face-table.hpp"
+#include "mgmt/segment-publisher.hpp"
+
+namespace nfd {
+
+class FaceStatusPublisher : public SegmentPublisher
+{
+public:
+ FaceStatusPublisher(const FaceTable& faceTable,
+ shared_ptr<AppFace> face,
+ const Name& prefix);
+
+ virtual
+ ~FaceStatusPublisher();
+
+protected:
+
+ virtual size_t
+ generate(ndn::EncodingBuffer& outBuffer);
+
+private:
+ const FaceTable& m_faceTable;
+};
+
+} // namespace nfd
+
+#endif // NFD_MGMT_FACE_STATUS_PUBLISHER_HPP
diff --git a/daemon/mgmt/segment-publisher.cpp b/daemon/mgmt/segment-publisher.cpp
new file mode 100644
index 0000000..bd7d971
--- /dev/null
+++ b/daemon/mgmt/segment-publisher.cpp
@@ -0,0 +1,83 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (C) 2014 Named Data Networking Project
+ * See COPYING for copyright and distribution information.
+ */
+
+#include "segment-publisher.hpp"
+
+#include "common.hpp"
+#include "face/face.hpp"
+
+#include <ndn-cpp-dev/util/time.hpp>
+
+namespace nfd {
+
+NFD_LOG_INIT("SegmentPublisher");
+
+SegmentPublisher::SegmentPublisher(shared_ptr<AppFace> face,
+ const Name& prefix)
+ : m_face(face)
+ , m_prefix(prefix)
+{
+
+}
+
+
+SegmentPublisher::~SegmentPublisher()
+{
+
+}
+
+void
+SegmentPublisher::publish()
+{
+ Name segmentPrefix(m_prefix);
+ segmentPrefix.appendSegment(ndn::ndn_getNowMilliseconds());
+
+ static const size_t MAX_SEGMENT_SIZE = MAX_NDN_PACKET_SIZE >> 1;
+
+ ndn::EncodingBuffer buffer;
+
+ generate(buffer);
+
+ const uint8_t* rawBuffer = buffer.buf();
+ const uint8_t* segmentBegin = rawBuffer;
+ const uint8_t* end = rawBuffer + buffer.size();
+
+ uint64_t segmentNo = 0;
+ while (segmentBegin < end)
+ {
+ const uint8_t* segmentEnd = segmentBegin + MAX_SEGMENT_SIZE;
+ if (segmentEnd > end)
+ {
+ segmentEnd = end;
+ }
+
+ Name segmentName(segmentPrefix);
+ segmentName.appendSegment(segmentNo);
+
+ shared_ptr<Data> data(make_shared<Data>(segmentName));
+ data->setContent(segmentBegin, segmentEnd - segmentBegin);
+
+ segmentBegin = segmentEnd;
+ if (segmentBegin >= end)
+ {
+ NFD_LOG_DEBUG("final block is " << segmentNo);
+ data->setFinalBlockId(segmentName[-1]);
+ }
+
+ NFD_LOG_DEBUG("publishing segment #" << segmentNo);
+ publishSegment(data);
+ segmentNo++;
+ }
+}
+
+void
+SegmentPublisher::publishSegment(shared_ptr<Data>& data)
+{
+ m_face->sign(*data);
+ m_face->put(*data);
+}
+
+} // namespace nfd
diff --git a/daemon/mgmt/segment-publisher.hpp b/daemon/mgmt/segment-publisher.hpp
new file mode 100644
index 0000000..4b5dc4f
--- /dev/null
+++ b/daemon/mgmt/segment-publisher.hpp
@@ -0,0 +1,47 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (C) 2014 Named Data Networking Project
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef NFD_MGMT_SEGMENT_PUBLISHER_HPP
+#define NFD_MGMT_SEGMENT_PUBLISHER_HPP
+
+#include "common.hpp"
+#include "mgmt/app-face.hpp"
+
+#include <ndn-cpp-dev/encoding/encoding-buffer.hpp>
+
+namespace nfd {
+
+class AppFace;
+
+class SegmentPublisher : noncopyable
+{
+public:
+ SegmentPublisher(shared_ptr<AppFace> face,
+ const Name& prefix);
+
+ virtual
+ ~SegmentPublisher();
+
+ void
+ publish();
+
+protected:
+
+ virtual size_t
+ generate(ndn::EncodingBuffer& outBuffer) =0;
+
+private:
+ void
+ publishSegment(shared_ptr<Data>& data);
+
+private:
+ shared_ptr<AppFace> m_face;
+ const Name m_prefix;
+};
+
+} // namespace nfd
+
+#endif // NFD_MGMT_SEGMENT_PUBLISHER_HPP