mgmt: add support for FIB enumeration protocol

refs: #1192

Change-Id: If9198c7d90d8882e9590ce93165667923df59a03
diff --git a/daemon/mgmt/command-validator.hpp b/daemon/mgmt/command-validator.hpp
index 97c7c18..290cabd 100644
--- a/daemon/mgmt/command-validator.hpp
+++ b/daemon/mgmt/command-validator.hpp
@@ -36,6 +36,7 @@
   /**
    * \param section "authorizations" section to parse
    * \param isDryRun true if performing a dry run of configuration, false otherwise
+   * \param filename filename of configuration file
    * \throws ConfigFile::Error on parse error
    */
   void
diff --git a/daemon/mgmt/fib-enumeration-publisher.cpp b/daemon/mgmt/fib-enumeration-publisher.cpp
new file mode 100644
index 0000000..89f0956
--- /dev/null
+++ b/daemon/mgmt/fib-enumeration-publisher.cpp
@@ -0,0 +1,69 @@
+/* -*- 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 "fib-enumeration-publisher.hpp"
+
+#include "common.hpp"
+
+#include <ndn-cpp-dev/management/nfd-fib-entry.hpp>
+
+namespace nfd {
+
+NFD_LOG_INIT("FibEnumerationPublisher");
+
+FibEnumerationPublisher::FibEnumerationPublisher(const Fib& fib,
+                                                 shared_ptr<AppFace> face,
+                                                 const Name& prefix)
+  : SegmentPublisher(face, prefix)
+  , m_fib(fib)
+{
+
+}
+
+FibEnumerationPublisher::~FibEnumerationPublisher()
+{
+
+}
+
+size_t
+FibEnumerationPublisher::generate(ndn::EncodingBuffer& outBuffer)
+{
+
+  size_t totalLength = 0;
+  for (Fib::const_iterator i = m_fib.begin(); i != m_fib.end(); ++i)
+    {
+      const fib::Entry& entry = *i;
+      const Name& prefix = entry.getPrefix();
+      size_t fibEntryLength = 0;
+
+      ndn::nfd::FibEntry tlvEntry;
+      const fib::NextHopList& nextHops = entry.getNextHops();
+
+      for (fib::NextHopList::const_iterator j = nextHops.begin();
+           j != nextHops.end();
+           ++j)
+        {
+          const fib::NextHop& next = *j;
+          ndn::nfd::NextHopRecord nextHopRecord;
+          nextHopRecord.setFaceId(next.getFace()->getId());
+          nextHopRecord.setCost(next.getCost());
+
+          tlvEntry.addNextHopRecord(nextHopRecord);
+        }
+
+      tlvEntry.setPrefix(prefix);
+      fibEntryLength += tlvEntry.wireEncode(outBuffer);
+
+      NFD_LOG_DEBUG("generate: fib entry length = " << fibEntryLength);
+
+      totalLength += fibEntryLength;
+    }
+  NFD_LOG_DEBUG("generate: Total length = " << totalLength);
+  return totalLength;
+}
+
+
+} // namespace nfd
diff --git a/daemon/mgmt/fib-enumeration-publisher.hpp b/daemon/mgmt/fib-enumeration-publisher.hpp
new file mode 100644
index 0000000..d9cb5c9
--- /dev/null
+++ b/daemon/mgmt/fib-enumeration-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_FIB_ENUMERATION_PUBLISHER_HPP
+#define NFD_MGMT_FIB_ENUMERATION_PUBLISHER_HPP
+
+#include "table/fib.hpp"
+#include "mgmt/segment-publisher.hpp"
+
+namespace nfd {
+
+class FibEnumerationPublisher : public SegmentPublisher
+{
+public:
+  FibEnumerationPublisher(const Fib& fib,
+                          shared_ptr<AppFace> face,
+                          const Name& prefix);
+
+  virtual
+  ~FibEnumerationPublisher();
+
+protected:
+
+  virtual size_t
+  generate(ndn::EncodingBuffer& outBuffer);
+
+private:
+  const Fib& m_fib;
+};
+
+} // namespace nfd
+
+#endif // NFD_MGMT_FIB_ENUMERATION_PUBLISHER_HPP
diff --git a/daemon/mgmt/fib-manager.cpp b/daemon/mgmt/fib-manager.cpp
index 0ffe333..9ce7a6f 100644
--- a/daemon/mgmt/fib-manager.cpp
+++ b/daemon/mgmt/fib-manager.cpp
@@ -28,30 +28,46 @@
   FibManager::COMMAND_UNSIGNED_NCOMPS +
   4; // (timestamp, nonce, signed info tlv, signature tlv)
 
-const FibManager::VerbAndProcessor FibManager::COMMAND_VERBS[] =
+const FibManager::SignedVerbAndProcessor FibManager::SIGNED_COMMAND_VERBS[] =
   {
 
-    VerbAndProcessor(
-                     Name::Component("add-nexthop"),
-                     &FibManager::addNextHop
-                     ),
+    SignedVerbAndProcessor(
+                           Name::Component("add-nexthop"),
+                           &FibManager::addNextHop
+                           ),
 
-    VerbAndProcessor(
-                     Name::Component("remove-nexthop"),
-                     &FibManager::removeNextHop
-                     ),
+    SignedVerbAndProcessor(
+                           Name::Component("remove-nexthop"),
+                           &FibManager::removeNextHop
+                           ),
 
   };
 
+const FibManager::UnsignedVerbAndProcessor FibManager::UNSIGNED_COMMAND_VERBS[] =
+  {
+    UnsignedVerbAndProcessor(
+                             Name::Component("list"),
+                             &FibManager::listEntries
+                             ),
+  };
+
+const Name FibManager::LIST_COMMAND_PREFIX("/localhost/nfd/fib/list");
+const size_t FibManager::LIST_COMMAND_NCOMPS = LIST_COMMAND_PREFIX.size();
+
+
 FibManager::FibManager(Fib& fib,
                        function<shared_ptr<Face>(FaceId)> getFace,
                        shared_ptr<InternalFace> face)
-  : ManagerBase(face, FIB_PRIVILEGE),
-    m_managedFib(fib),
-    m_getFace(getFace),
-    m_verbDispatch(COMMAND_VERBS,
-                   COMMAND_VERBS +
-                   (sizeof(COMMAND_VERBS) / sizeof(VerbAndProcessor)))
+  : ManagerBase(face, FIB_PRIVILEGE)
+  , m_managedFib(fib)
+  , m_getFace(getFace)
+  , m_fibEnumerationPublisher(fib, 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/fib",
                           bind(&FibManager::onFibRequest, this, _2));
@@ -67,28 +83,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(&FibManager::onValidatedFibRequest,
-                this, _1),
-           bind(&ManagerBase::onCommandValidationFailed,
-                this, _1, _2));
+  else
+    {
+      validate(request,
+               bind(&FibManager::onValidatedFibRequest, this, _1),
+               bind(&ManagerBase::onCommandValidationFailed, this, _1, _2));
+    }
 }
 
 void
@@ -97,8 +117,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())
     {
       FibManagementOptions options;
       if (!extractOptions(*request, options))
@@ -110,7 +130,7 @@
 
       NFD_LOG_INFO("command result: processing verb: " << verb);
       ControlResponse response;
-      (verbProcessor->second)(this, options, response);
+      (signedVerbProcessor->second)(this, options, response);
       sendResponse(command, response);
     }
   else
@@ -214,4 +234,21 @@
     }
 }
 
+void
+FibManager::listEntries(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_fibEnumerationPublisher.publish();
+}
+
 } // namespace nfd
diff --git a/daemon/mgmt/fib-manager.hpp b/daemon/mgmt/fib-manager.hpp
index 1cbc49c..10b4fb2 100644
--- a/daemon/mgmt/fib-manager.hpp
+++ b/daemon/mgmt/fib-manager.hpp
@@ -12,6 +12,7 @@
 #include "mgmt/app-face.hpp"
 #include "fw/strategy.hpp"
 #include "mgmt/manager-base.hpp"
+#include "mgmt/fib-enumeration-publisher.hpp"
 
 #include <ndn-cpp-dev/management/nfd-fib-management-options.hpp>
 
@@ -60,6 +61,9 @@
   removeNextHop(const FibManagementOptions& options,
                 ControlResponse& response);
 
+  void
+  listEntries(const Interest& request);
+
   bool
   extractOptions(const Interest& request,
                  FibManagementOptions& extractedOptions);
@@ -68,18 +72,24 @@
 
   Fib& m_managedFib;
   function<shared_ptr<Face>(FaceId)> m_getFace;
-  std::map<Name, shared_ptr<fw::Strategy> > m_namespaceToStrategyMap;
+  FibEnumerationPublisher m_fibEnumerationPublisher;
 
   typedef function<void(FibManager*,
                         const FibManagementOptions&,
-                        ControlResponse&)> VerbProcessor;
+                        ControlResponse&)> SignedVerbProcessor;
 
-  typedef std::map<Name::Component, VerbProcessor> VerbDispatchTable;
+  typedef std::map<Name::Component, SignedVerbProcessor> SignedVerbDispatchTable;
 
-  typedef std::pair<Name::Component, VerbProcessor> VerbAndProcessor;
+  typedef std::pair<Name::Component, SignedVerbProcessor> SignedVerbAndProcessor;
+
+  typedef function<void(FibManager*, const Interest&)> UnsignedVerbProcessor;
+
+  typedef std::map<Name::Component, UnsignedVerbProcessor> UnsignedVerbDispatchTable;
+  typedef std::pair<Name::Component, UnsignedVerbProcessor> UnsignedVerbAndProcessor;
 
 
-  const VerbDispatchTable m_verbDispatch;
+  const SignedVerbDispatchTable m_signedVerbDispatch;
+  const UnsignedVerbDispatchTable m_unsignedVerbDispatch;
 
   static const Name COMMAND_PREFIX; // /localhost/nfd/fib
 
@@ -91,8 +101,11 @@
   // UNSIGNED_NCOMPS + 4 command Interest components = 9
   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;
 };
 
 } // namespace nfd