publisher: fix encoding bug in routing table publisher

refs: #4453

Change-Id: I03e819e963f0957f3d40ff25e378f2b9b17357b7
diff --git a/src/publisher/dataset-interest-handler.cpp b/src/publisher/dataset-interest-handler.cpp
index 15a1eea..6e2e7d1 100644
--- a/src/publisher/dataset-interest-handler.cpp
+++ b/src/publisher/dataset-interest-handler.cpp
@@ -139,43 +139,51 @@
   context.end();
 }
 
-void
-DatasetInterestHandler::publishRtStatus(const ndn::Name& topPrefix, const ndn::Interest& interest,
-                                        ndn::mgmt::StatusDatasetContext& context)
-{
-  NLSR_LOG_DEBUG("Received interest for routing table:  " << interest);
-  tlv::RoutingTable tlvRoutingTable;
 
+std::vector<tlv::RoutingTable>
+DatasetInterestHandler::getTlvRTEntries()
+{
+  std::vector<tlv::RoutingTable> rtable;
   for (const auto& rte : m_routingTableEntries) {
+    tlv::RoutingTable tlvRoutingTable;
     std::shared_ptr<tlv::Destination> tlvDes = tlv::makeDes(rte);
     tlvRoutingTable.setDestination(*tlvDes);
-
     for (const auto& nh : rte.getNexthopList().getNextHops()) {
       tlv::NextHop tlvNexthop;
       tlvNexthop.setUri(nh.getConnectingFaceUri());
       tlvNexthop.setCost(nh.getRouteCost());
       tlvRoutingTable.addNexthops(tlvNexthop);
     }
-
-    const ndn::Block& wire = tlvRoutingTable.wireEncode();
-    context.append(wire);
+    rtable.push_back(tlvRoutingTable);
   }
   if (!m_dryRoutingTableEntries.empty()) {
-    for (const auto& dry_rte : m_dryRoutingTableEntries ) {
-        std::shared_ptr<tlv::Destination> tlvDes = tlv::makeDes(dry_rte);
-        tlvRoutingTable.setDestination(*tlvDes);
-
-        for (const auto& nh : dry_rte.getNexthopList().getNextHops()) {
-          tlv::NextHop tlvNexthop;
-          tlvNexthop.setUri(nh.getConnectingFaceUri());
-          tlvNexthop.setCost(nh.getRouteCost());
-          tlvRoutingTable.addNexthops(tlvNexthop);
-        }
-        const ndn::Block& wire = tlvRoutingTable.wireEncode();
-        context.append(wire);
+    for (const auto& dryRte : m_dryRoutingTableEntries) {
+      tlv::RoutingTable tlvRoutingTable;
+      std::shared_ptr<tlv::Destination> tlvDes = tlv::makeDes(dryRte);
+      tlvRoutingTable.setDestination(*tlvDes);
+      for (const auto& nh : dryRte.getNexthopList().getNextHops()) {
+        tlv::NextHop tlvNexthop;
+        tlvNexthop.setUri(nh.getConnectingFaceUri());
+        tlvNexthop.setCost(nh.getRouteCost());
+        tlvRoutingTable.addNexthops(tlvNexthop);
       }
+      rtable.push_back(tlvRoutingTable);
+    }
   }
+  return rtable;
+}
 
+void
+DatasetInterestHandler::publishRtStatus(const ndn::Name& topPrefix, const ndn::Interest& interest,
+                                        ndn::mgmt::StatusDatasetContext& context)
+{
+  NLSR_LOG_DEBUG("Received interest:  " << interest);
+  tlv::RoutingTableStatus rtStatus;
+  for (const tlv::RoutingTable& rt : getTlvRTEntries()) {
+    rtStatus.addRoutingTable(rt);
+  }
+  const ndn::Block& wire = rtStatus.wireEncode();
+  context.append(wire);
   context.end();
 }
 
@@ -200,7 +208,6 @@
       tlvAdj.setCost(adj.getLinkCost());
       tlvLsa.addAdjacency(tlvAdj);
     }
-
     lsas.push_back(tlvLsa);
   }
 
diff --git a/src/publisher/dataset-interest-handler.hpp b/src/publisher/dataset-interest-handler.hpp
index 00d8c1d..6e5169d 100644
--- a/src/publisher/dataset-interest-handler.hpp
+++ b/src/publisher/dataset-interest-handler.hpp
@@ -96,6 +96,11 @@
   void
   setDispatcher(ndn::mgmt::Dispatcher& dispatcher);
 
+  /*! \brief generate a TLV-format of routing table entry
+   */
+  std::vector<tlv::RoutingTable>
+  getTlvRTEntries();
+
   /*! \brief provide routing-table dataset
   */
   void
diff --git a/src/tlv/destination.cpp b/src/tlv/destination.cpp
index 6f9f918..a1ea06f 100644
--- a/src/tlv/destination.cpp
+++ b/src/tlv/destination.cpp
@@ -54,13 +54,7 @@
   return totalLength;
 }
 
-NDN_CXX_DECLARE_WIRE_ENCODE_INSTANTIATIONS(Destination);
-
-template size_t
-Destination::wireEncode<ndn::encoding::EncoderTag>(ndn::EncodingImpl<ndn::encoding::EncoderTag>& block) const;
-
-template size_t
-Destination::wireEncode<ndn::encoding::EstimatorTag>(ndn::EncodingImpl<ndn::encoding::EstimatorTag>& block) const;
+NDN_CXX_DEFINE_WIRE_ENCODE_INSTANTIATIONS(Destination);
 
 const ndn::Block&
 Destination::wireEncode() const
diff --git a/src/tlv/destination.hpp b/src/tlv/destination.hpp
index 7c577e8..859c8a8 100644
--- a/src/tlv/destination.hpp
+++ b/src/tlv/destination.hpp
@@ -91,6 +91,8 @@
   mutable ndn::Block m_wire;
 };
 
+NDN_CXX_DECLARE_WIRE_ENCODE_INSTANTIATIONS(Destination);
+
 std::ostream&
 operator<<(std::ostream& os, const Destination& destination);
 
diff --git a/src/tlv/nexthop.cpp b/src/tlv/nexthop.cpp
index 79b6e97..342a02e 100644
--- a/src/tlv/nexthop.cpp
+++ b/src/tlv/nexthop.cpp
@@ -61,13 +61,7 @@
   return totalLength;
 }
 
-NDN_CXX_DECLARE_WIRE_ENCODE_INSTANTIATIONS(NextHop);
-
-template size_t
-NextHop::wireEncode<ndn::encoding::EncoderTag>(ndn::EncodingImpl<ndn::encoding::EncoderTag>& block) const;
-
-template size_t
-NextHop::wireEncode<ndn::encoding::EstimatorTag>(ndn::EncodingImpl<ndn::encoding::EstimatorTag>& block) const;
+NDN_CXX_DEFINE_WIRE_ENCODE_INSTANTIATIONS(NextHop);
 
 const ndn::Block&
 NextHop::wireEncode() const
diff --git a/src/tlv/nexthop.hpp b/src/tlv/nexthop.hpp
index 03666cc..9b0f72c 100644
--- a/src/tlv/nexthop.hpp
+++ b/src/tlv/nexthop.hpp
@@ -103,6 +103,8 @@
   mutable ndn::Block m_wire;
 };
 
+NDN_CXX_DECLARE_WIRE_ENCODE_INSTANTIATIONS(NextHop);
+
 std::ostream&
 operator<<(std::ostream& os, const NextHop& nexthop);
 
diff --git a/src/tlv/routing-table-entry.cpp b/src/tlv/routing-table-entry.cpp
index 39405af..c8e6332 100644
--- a/src/tlv/routing-table-entry.cpp
+++ b/src/tlv/routing-table-entry.cpp
@@ -85,13 +85,7 @@
   return totalLength;
 }
 
-NDN_CXX_DECLARE_WIRE_ENCODE_INSTANTIATIONS(RoutingTable);
-
-template size_t
-RoutingTable::wireEncode<ndn::encoding::EncoderTag>(ndn::EncodingImpl<ndn::encoding::EncoderTag>& encoder) const;
-
-template size_t
-RoutingTable::wireEncode<ndn::encoding::EstimatorTag>(ndn::EncodingImpl<ndn::encoding::EstimatorTag>& encoder) const;
+NDN_CXX_DEFINE_WIRE_ENCODE_INSTANTIATIONS(RoutingTable);
 
 const ndn::Block&
 RoutingTable::wireEncode() const
@@ -155,16 +149,14 @@
 std::ostream&
 operator<<(std::ostream& os, const RoutingTable& routingtable)
 {
-  os << "Routing Table: " << std::endl;
   os << routingtable.getDestination() << std::endl;
-  os << "Nexthops: NexthopList(" << std::endl;
+  os << "NexthopList(" << std::endl;
 
   for (const auto& rtentry : routingtable) {
-    os << rtentry << std::endl;
+    os << rtentry;
   }
 
   os << ")";
-
   return os;
 }
 
diff --git a/src/tlv/routing-table-entry.hpp b/src/tlv/routing-table-entry.hpp
index 176becb..167f63a 100644
--- a/src/tlv/routing-table-entry.hpp
+++ b/src/tlv/routing-table-entry.hpp
@@ -133,6 +133,8 @@
   mutable ndn::Block m_wire;
 };
 
+NDN_CXX_DECLARE_WIRE_ENCODE_INSTANTIATIONS(RoutingTable);
+
 inline RoutingTable::const_iterator
 RoutingTable::begin() const
 {
diff --git a/src/tlv/routing-table-status.cpp b/src/tlv/routing-table-status.cpp
index d2c8a55..6f4bb24 100644
--- a/src/tlv/routing-table-status.cpp
+++ b/src/tlv/routing-table-status.cpp
@@ -31,7 +31,7 @@
 BOOST_CONCEPT_ASSERT((ndn::WireEncodable<RoutingTableStatus>));
 BOOST_CONCEPT_ASSERT((ndn::WireDecodable<RoutingTableStatus>));
 static_assert(std::is_base_of<ndn::tlv::Error, RoutingTableStatus::Error>::value,
-              "RTStatus::Error must inherit from tlv::Error");
+              "RoutingTableStatus::Error must inherit from tlv::Error");
 
 RoutingTableStatus::RoutingTableStatus()
   : m_hasRoutingtable(false)
@@ -83,13 +83,7 @@
   return totalLength;
 }
 
-NDN_CXX_DECLARE_WIRE_ENCODE_INSTANTIATIONS(RoutingTableStatus);
-
-template size_t
-RoutingTableStatus::wireEncode<ndn::encoding::EncoderTag>(ndn::EncodingImpl<ndn::encoding::EncoderTag>& block) const;
-
-template size_t
-RoutingTableStatus::wireEncode<ndn::encoding::EstimatorTag>(ndn::EncodingImpl<ndn::encoding::EstimatorTag>& block) const;
+NDN_CXX_DEFINE_WIRE_ENCODE_INSTANTIATIONS(RoutingTableStatus);
 
 const ndn::Block&
 RoutingTableStatus::wireEncode() const
diff --git a/src/tlv/routing-table-status.hpp b/src/tlv/routing-table-status.hpp
index 1ce3497..97d083f 100644
--- a/src/tlv/routing-table-status.hpp
+++ b/src/tlv/routing-table-status.hpp
@@ -95,6 +95,8 @@
   mutable ndn::Block m_wire;
 };
 
+NDN_CXX_DECLARE_WIRE_ENCODE_INSTANTIATIONS(RoutingTableStatus);
+
 std::ostream&
 operator<<(std::ostream& os, const RoutingTableStatus& rtStatus);
 
diff --git a/tests/publisher/test-dataset-interest-handler.cpp b/tests/publisher/test-dataset-interest-handler.cpp
index ccd3b64..7cc4a84 100644
--- a/tests/publisher/test-dataset-interest-handler.cpp
+++ b/tests/publisher/test-dataset-interest-handler.cpp
@@ -102,7 +102,7 @@
   face.receive(ndn::Interest(ndn::Name("/localhost/nlsr/routing-table")));
   processDatasetInterest(face,
     [] (const ndn::Block& block) {
-      return block.type() == ndn::tlv::nlsr::RouteTableEntry; });
+      return block.type() == ndn::tlv::nlsr::RoutingTable; });
 }
 
 
@@ -147,7 +147,7 @@
   face.receive(ndn::Interest(ndn::Name("/ndn/This/Router/routing-table")));
   processDatasetInterest(face,
     [] (const ndn::Block& block) {
-      return block.type() == ndn::tlv::nlsr::RouteTableEntry; });
+      return block.type() == ndn::tlv::nlsr::RoutingTable; });
 }
 
 BOOST_AUTO_TEST_SUITE_END()
diff --git a/tests/tlv/test-routing-table-entry.cpp b/tests/tlv/test-routing-table-entry.cpp
index 5b882a2..a58918e 100644
--- a/tests/tlv/test-routing-table-entry.cpp
+++ b/tests/tlv/test-routing-table-entry.cpp
@@ -178,11 +178,11 @@
   std::ostringstream os;
   os << rt;
 
-  BOOST_CHECK_EQUAL(os.str(), "Routing Table: \n"
-                                  "Destination: /dest1\n"
-                                  "Nexthops: NexthopList(\n"
-                                  "NextHop(Uri: nexthop1, Cost: 99)\n"
-                                  "\n)");
+  BOOST_CHECK_EQUAL(os.str(),
+                    "Destination: /dest1\n"
+                    "NexthopList(\n"
+                    "NextHop(Uri: nexthop1, Cost: 99)\n"
+                    ")");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
diff --git a/tests/tlv/test-routing-table.cpp b/tests/tlv/test-routing-table.cpp
index c4b798f..c7af5ae 100644
--- a/tests/tlv/test-routing-table.cpp
+++ b/tests/tlv/test-routing-table.cpp
@@ -155,11 +155,10 @@
   os << rtStatus;
 
   BOOST_CHECK_EQUAL(os.str(), "Routing Table Status: \n"
-                                "Routing Table: \n"
                                   "Destination: /dest1\n"
-                                  "Nexthops: NexthopList(\n"
+                                  "NexthopList(\n"
                                   "NextHop(Uri: nexthop, Cost: 99)\n"
-                                  "\n)");
+                                  ")");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
diff --git a/tools/nlsrc.cpp b/tools/nlsrc.cpp
index db2de6a..3db6215 100644
--- a/tools/nlsrc.cpp
+++ b/tools/nlsrc.cpp
@@ -240,8 +240,8 @@
 void
 Nlsrc::fetchRtables()
 {
-  fetchFromRt<nlsr::tlv::RoutingTable>(
-    [this] (const nlsr::tlv::RoutingTable& rts) {
+  fetchFromRt<nlsr::tlv::RoutingTableStatus>(
+    [this] (const nlsr::tlv::RoutingTableStatus& rts) {
       recordRtable(rts);
     });
 }
@@ -322,15 +322,6 @@
   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)
 {
@@ -385,20 +376,13 @@
 }
 
 void
-Nlsrc::recordRtable(const nlsr::tlv::RoutingTable& rt)
+Nlsrc::recordRtable(const nlsr::tlv::RoutingTableStatus& rts)
 {
-  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;
+  for (const auto& rt : rts.getRoutingtable()) {
+    os << rt << std::endl;
   }
-
-  router.rtString = os.str();
+  m_rtString = os.str();
 }
 
 void
@@ -429,15 +413,12 @@
 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;
-    }
+  if (!m_rtString.empty()) {
+    std::cout << "Routing Table" << std::endl;
+    std::cout << m_rtString << std::endl;
+  }
+  else {
+    std::cout << "Routing Table is not calculated yet" << std::endl;
   }
 }
 
@@ -460,17 +441,6 @@
   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 a5c6368..cc5a1f6 100644
--- a/tools/nlsrc.hpp
+++ b/tools/nlsrc.hpp
@@ -123,9 +123,6 @@
   std::string
   getLsaInfoString(const nlsr::tlv::LsaInfo& info);
 
-  std::string
-  getDesString(const nlsr::tlv::Destination& des);
-
   void
   recordAdjacencyLsa(const nlsr::tlv::AdjacencyLsa& lsa);
 
@@ -136,7 +133,7 @@
   recordNameLsa(const nlsr::tlv::NameLsa& lsa);
 
   void
-  recordRtable(const nlsr::tlv::RoutingTable& rts);
+  recordRtable(const nlsr::tlv::RoutingTableStatus& rts);
 
   void
   printLsdb();
@@ -160,15 +157,11 @@
     std::string adjacencyLsaString;
     std::string coordinateLsaString;
     std::string nameLsaString;
-    std::string rtString;
   };
 
   Router&
   getRouterLsdb(const nlsr::tlv::LsaInfo& info);
 
-  Router&
-  getRouterRT(const nlsr::tlv::Destination& des);
-
   typedef std::map<const ndn::Name, Router> RouterMap;
   RouterMap m_routers;
 
@@ -177,6 +170,7 @@
   ndn::Face& m_face;
   ndn::security::ValidatorNull m_validator;
   std::string commandString;
+  std::string m_rtString;
 
   std::deque<std::function<void()>> m_fetchSteps;