publisher: implement routing table dataset publisher

refs: #3631, #3634

Change-Id: I7e961fdd0857690bee65d2bdfa4cf3de90ccac06
diff --git a/tools/nlsrc.cpp b/tools/nlsrc.cpp
index 103fa26..db2de6a 100644
--- a/tools/nlsrc.cpp
+++ b/tools/nlsrc.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2017,  The University of Memphis,
+ * Copyright (c) 2014-2018,  The University of Memphis,
  *                           Regents of the University of California,
  *                           Arizona Board of Regents.
  *
@@ -22,7 +22,7 @@
 #include "nlsrc.hpp"
 
 #include "version.hpp"
-#include "src/publisher/lsdb-dataset-interest-handler.hpp"
+#include "src/publisher/dataset-interest-handler.hpp"
 
 #include <ndn-cxx/face.hpp>
 #include <ndn-cxx/data.hpp>
@@ -42,6 +42,8 @@
 const ndn::Name Nlsrc::LSDB_PREFIX = ndn::Name(Nlsrc::LOCALHOST_PREFIX).append("lsdb");
 const ndn::Name Nlsrc::NAME_UPDATE_PREFIX = ndn::Name(Nlsrc::LOCALHOST_PREFIX).append("prefix-update");
 
+const ndn::Name Nlsrc::RT_PREFIX = ndn::Name(Nlsrc::LOCALHOST_PREFIX).append("routing-table");
+
 const uint32_t Nlsrc::ERROR_CODE_TIMEOUT = 10060;
 const uint32_t Nlsrc::RESPONSE_CODE_SUCCESS = 200;
 
@@ -58,8 +60,12 @@
     "       -V print version and exit\n"
     "\n"
     "   COMMAND can be one of the following:\n"
+    "       lsdb\n"
+    "           display NLSR lsdb status\n"
+    "       routing\n"
+    "           display routing table status\n"
     "       status\n"
-    "           display NLSR status\n"
+    "           display all NLSR status (lsdb & routingtable)\n"
     "       advertise name\n"
     "           advertise a name prefix through NLSR\n"
     "       withdraw name\n"
@@ -68,13 +74,25 @@
 }
 
 void
-Nlsrc::getStatus()
+Nlsrc::getStatus(const std::string& command)
 {
-  m_fetchSteps.push_back(std::bind(&Nlsrc::fetchAdjacencyLsas, this));
-  m_fetchSteps.push_back(std::bind(&Nlsrc::fetchCoordinateLsas, this));
-  m_fetchSteps.push_back(std::bind(&Nlsrc::fetchNameLsas, this));
-  m_fetchSteps.push_back(std::bind(&Nlsrc::printLsdb, this));
-
+  if (command == "lsdb") {
+    m_fetchSteps.push_back(std::bind(&Nlsrc::fetchAdjacencyLsas, this));
+    m_fetchSteps.push_back(std::bind(&Nlsrc::fetchCoordinateLsas, this));
+    m_fetchSteps.push_back(std::bind(&Nlsrc::fetchNameLsas, this));
+    m_fetchSteps.push_back(std::bind(&Nlsrc::printLsdb, this));
+  }
+  else if (command == "routing") {
+    m_fetchSteps.push_back(std::bind(&Nlsrc::fetchRtables, this));
+    m_fetchSteps.push_back(std::bind(&Nlsrc::printRT, this));
+  }
+  else if(command == "status") {
+    m_fetchSteps.push_back(std::bind(&Nlsrc::fetchAdjacencyLsas, this));
+    m_fetchSteps.push_back(std::bind(&Nlsrc::fetchCoordinateLsas, this));
+    m_fetchSteps.push_back(std::bind(&Nlsrc::fetchNameLsas, this));
+    m_fetchSteps.push_back(std::bind(&Nlsrc::fetchRtables, this));
+    m_fetchSteps.push_back(std::bind(&Nlsrc::printAll, this));
+  }
   runNextStep();
 }
 
@@ -97,12 +115,13 @@
     withdrawName();
     return true;
   }
-  else if (command == "status") {
+  else if ((command == "lsdb")|| (command == "routing")||(command == "status")) {
     if (nOptions != 0) {
       return false;
     }
+    commandString = command;
 
-    getStatus();
+    getStatus(command);
     return true;
   }
 
@@ -218,6 +237,15 @@
                                     std::bind(&Nlsrc::recordNameLsa, this, _1));
 }
 
+void
+Nlsrc::fetchRtables()
+{
+  fetchFromRt<nlsr::tlv::RoutingTable>(
+    [this] (const nlsr::tlv::RoutingTable& rts) {
+      recordRtable(rts);
+    });
+}
+
 template <class T>
 void
 Nlsrc::fetchFromLsdb(const ndn::Name::Component& datasetType,
@@ -238,8 +266,24 @@
 
 template <class T>
 void
+Nlsrc::fetchFromRt(const std::function<void(const T&)>& recordDataset)
+{
+  ndn::Name command = RT_PREFIX;
+
+  ndn::Interest interest(command);
+
+  ndn::util::SegmentFetcher::fetch(m_face,
+                                   interest,
+                                   m_validator,
+                                   std::bind(&Nlsrc::onFetchSuccess<T>,
+                                             this, _1, recordDataset),
+                                   std::bind(&Nlsrc::onTimeout, this, _1, _2));
+}
+
+template <class T>
+void
 Nlsrc::onFetchSuccess(const ndn::ConstBufferPtr& data,
-                      const std::function<void(const T&)>& recordLsa)
+                      const std::function<void(const T&)>& recordDataset)
 {
   ndn::Block block;
   size_t offset = 0;
@@ -255,8 +299,8 @@
 
     offset += block.size();
 
-    T lsa(block);
-    recordLsa(lsa);
+    T data(block);
+    recordDataset(data);
   }
 
   runNextStep();
@@ -278,10 +322,19 @@
   return os.str();
 }
 
+std::string
+Nlsrc::getDesString(const nlsr::tlv::Destination& des)
+{
+  std::ostringstream os;
+  os << "    " << des;
+
+  return os.str();
+}
+
 void
 Nlsrc::recordAdjacencyLsa(const nlsr::tlv::AdjacencyLsa& lsa)
 {
-  Router& router = getRouter(lsa.getLsaInfo());
+  Router& router = getRouterLsdb(lsa.getLsaInfo());
 
   std::ostringstream os;
   os << "    AdjacencyLsa:" << std::endl;
@@ -298,7 +351,7 @@
 void
 Nlsrc::recordCoordinateLsa(const nlsr::tlv::CoordinateLsa& lsa)
 {
-  Router& router = getRouter(lsa.getLsaInfo());
+  Router& router = getRouterLsdb(lsa.getLsaInfo());
 
   std::ostringstream os;
   os << "    Coordinate LSA:" << std::endl;
@@ -317,7 +370,7 @@
 void
 Nlsrc::recordNameLsa(const nlsr::tlv::NameLsa& lsa)
 {
-  Router& router = getRouter(lsa.getLsaInfo());
+  Router& router = getRouterLsdb(lsa.getLsaInfo());
 
   std::ostringstream os;
   os << "    Name LSA:" << std::endl;
@@ -332,9 +385,25 @@
 }
 
 void
+Nlsrc::recordRtable(const nlsr::tlv::RoutingTable& rt)
+{
+  Router& router = getRouterRT(rt.getDestination());
+
+  std::ostringstream os;
+
+  os << getDesString(rt.getDestination()) << std::endl;
+
+  os << "    NextHopList: " <<std::endl;
+  for (const auto& nhs : rt.getNextHops()) {
+    os << "      " << nhs;
+  }
+
+  router.rtString = os.str();
+}
+
+void
 Nlsrc::printLsdb()
 {
-  std::cout << "NLSR Status" << std::endl;
   std::cout << "LSDB:" << std::endl;
 
   for (const auto& item : m_routers) {
@@ -357,8 +426,31 @@
   }
 }
 
+void
+Nlsrc::printRT()
+{
+  std::cout << "Routing Table Status:" << std::endl;
+
+  for (const auto& item : m_routers) {
+
+    const Router& router = item.second;
+
+    if (!router.rtString.empty()) {
+      std::cout << router.rtString << std::endl;
+    }
+  }
+}
+
+void
+Nlsrc::printAll()
+{
+  std::cout << "NLSR Status" << std::endl;
+  printLsdb();
+  printRT();
+}
+
 Nlsrc::Router&
-Nlsrc::getRouter(const nlsr::tlv::LsaInfo& info)
+Nlsrc::getRouterLsdb(const nlsr::tlv::LsaInfo& info)
 {
   const ndn::Name& originRouterName = info.getOriginRouter();
 
@@ -368,6 +460,17 @@
   return pair.first->second;
 }
 
+Nlsrc::Router&
+Nlsrc::getRouterRT(const nlsr::tlv::Destination& des)
+{
+  const ndn::Name& desName = des.getName();
+
+  const auto& pair =
+    m_routers.insert(std::make_pair(desName, Router()));
+
+  return pair.first->second;
+}
+
 } // namespace nlsrc
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/tools/nlsrc.hpp b/tools/nlsrc.hpp
index 3dd44d6..a5c6368 100644
--- a/tools/nlsrc.hpp
+++ b/tools/nlsrc.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2017,  The University of Memphis,
+ * Copyright (c) 2014-2018,  The University of Memphis,
  *                           Regents of the University of California,
  *                           Arizona Board of Regents.
  *
@@ -22,6 +22,8 @@
 #include "tlv/adjacency-lsa.hpp"
 #include "tlv/coordinate-lsa.hpp"
 #include "tlv/name-lsa.hpp"
+#include "tlv/routing-table-status.hpp"
+
 
 #include <boost/noncopyable.hpp>
 #include <ndn-cxx/face.hpp>
@@ -47,7 +49,7 @@
   printUsage();
 
   void
-  getStatus();
+  getStatus(const std::string& command);
 
   bool
   dispatch(const std::string& cmd);
@@ -89,6 +91,12 @@
   fetchAdjacencyLsas();
 
   void
+  fetchRtables();
+
+  void
+  fetchHRRtables();
+
+  void
   fetchCoordinateLsas();
 
   void
@@ -101,6 +109,10 @@
 
   template <class T>
   void
+  fetchFromRt(const std::function<void(const T&)>& recordLsa);
+
+  template <class T>
+  void
   onFetchSuccess(const ndn::ConstBufferPtr& data,
                  const std::function<void(const T&)>& recordLsa);
 
@@ -111,6 +123,9 @@
   std::string
   getLsaInfoString(const nlsr::tlv::LsaInfo& info);
 
+  std::string
+  getDesString(const nlsr::tlv::Destination& des);
+
   void
   recordAdjacencyLsa(const nlsr::tlv::AdjacencyLsa& lsa);
 
@@ -121,8 +136,17 @@
   recordNameLsa(const nlsr::tlv::NameLsa& lsa);
 
   void
+  recordRtable(const nlsr::tlv::RoutingTable& rts);
+
+  void
   printLsdb();
 
+  void
+  printRT();
+
+  void
+  printAll();
+
 public:
   const char* programName;
 
@@ -136,10 +160,14 @@
     std::string adjacencyLsaString;
     std::string coordinateLsaString;
     std::string nameLsaString;
+    std::string rtString;
   };
 
   Router&
-  getRouter(const nlsr::tlv::LsaInfo& info);
+  getRouterLsdb(const nlsr::tlv::LsaInfo& info);
+
+  Router&
+  getRouterRT(const nlsr::tlv::Destination& des);
 
   typedef std::map<const ndn::Name, Router> RouterMap;
   RouterMap m_routers;
@@ -148,6 +176,7 @@
   ndn::KeyChain m_keyChain;
   ndn::Face& m_face;
   ndn::security::ValidatorNull m_validator;
+  std::string commandString;
 
   std::deque<std::function<void()>> m_fetchSteps;
 
@@ -155,6 +184,8 @@
   static const ndn::Name LSDB_PREFIX;
   static const ndn::Name NAME_UPDATE_PREFIX;
 
+  static const ndn::Name RT_PREFIX;
+
   static const uint32_t ERROR_CODE_TIMEOUT;
   static const uint32_t RESPONSE_CODE_SUCCESS;
 };