publisher: Serve LSDB dataset on localhost prefix

refs: #2737

Change-Id: I4cc9bd1d07dea583937676dd491ab5c68fd821ea
diff --git a/src/nlsr.cpp b/src/nlsr.cpp
index 2175c93..3923ffe 100644
--- a/src/nlsr.cpp
+++ b/src/nlsr.cpp
@@ -39,6 +39,45 @@
 using namespace ndn;
 using namespace std;
 
+Nlsr::Nlsr(boost::asio::io_service& ioService, ndn::Scheduler& scheduler, ndn::Face& face)
+  : m_nlsrFace(face)
+  , m_scheduler(scheduler)
+  , m_confParam()
+  , m_adjacencyList()
+  , m_namePrefixList()
+  , m_sequencingManager()
+  , m_isDaemonProcess(false)
+  , m_configFileName("nlsr.conf")
+  , m_nlsrLsdb(*this, scheduler, m_syncLogicHandler)
+  , m_adjBuildCount(0)
+  , m_isBuildAdjLsaSheduled(false)
+  , m_isRouteCalculationScheduled(false)
+  , m_isRoutingTableCalculating(false)
+  , m_routingTable(scheduler)
+  , m_fib(m_nlsrFace, scheduler, m_adjacencyList, m_confParam, m_keyChain)
+  , m_namePrefixTable(*this)
+  , m_syncLogicHandler(m_nlsrFace, m_nlsrLsdb, m_confParam, m_sequencingManager)
+  , m_helloProtocol(*this, scheduler)
+  , m_lsdbDatasetHandler(m_nlsrLsdb,
+                         m_nlsrFace,
+                         m_confParam.getRouterPrefix(),
+                         m_keyChain)
+  , m_certificateCache(new ndn::CertificateCacheTtl(ioService))
+  , m_validator(m_nlsrFace, DEFAULT_BROADCAST_PREFIX, m_certificateCache)
+  , m_prefixUpdateProcessor(m_nlsrFace,
+                            m_namePrefixList,
+                            m_nlsrLsdb,
+                            m_syncLogicHandler,
+                            DEFAULT_BROADCAST_PREFIX,
+                            m_keyChain,
+                            m_certificateCache)
+  , m_faceMonitor(m_nlsrFace)
+  , m_firstHelloInterval(FIRST_HELLO_INTERVAL_DEFAULT)
+{
+  m_faceMonitor.onNotification.connect(bind(&Nlsr::onFaceEventNotification, this, _1));
+  m_faceMonitor.start();
+}
+
 void
 Nlsr::registrationFailed(const ndn::Name& name)
 {
@@ -49,12 +88,10 @@
 void
 Nlsr::onRegistrationSuccess(const ndn::Name& name)
 {
+  _LOG_DEBUG("Successfully registered prefix: " << name);
+
   if (name.equals(m_confParam.getRouterPrefix())) {
-    m_lsdbDatasetHandler = std::unique_ptr<LsdbDatasetInterestHandler>(
-      new LsdbDatasetInterestHandler(m_nlsrLsdb,
-                                     m_nlsrFace,
-                                     m_confParam.getRouterPrefix(),
-                                     m_keyChain));
+    m_lsdbDatasetHandler.startListeningOnRouterPrefix();
   }
 }
 
@@ -64,6 +101,7 @@
   _LOG_DEBUG("Successfully registered prefix: " << name);
 
   m_prefixUpdateProcessor.startListening();
+  m_lsdbDatasetHandler.startListeningOnLocalhost();
 }
 
 void
diff --git a/src/nlsr.hpp b/src/nlsr.hpp
index 8893272..dd8a478 100644
--- a/src/nlsr.hpp
+++ b/src/nlsr.hpp
@@ -67,40 +67,7 @@
   };
 
 public:
-  Nlsr(boost::asio::io_service& ioService, ndn::Scheduler& scheduler, ndn::Face& face)
-    : m_nlsrFace(face)
-    , m_scheduler(scheduler)
-    , m_confParam()
-    , m_adjacencyList()
-    , m_namePrefixList()
-    , m_sequencingManager()
-    , m_isDaemonProcess(false)
-    , m_configFileName("nlsr.conf")
-    , m_nlsrLsdb(*this, scheduler, m_syncLogicHandler)
-    , m_adjBuildCount(0)
-    , m_isBuildAdjLsaSheduled(false)
-    , m_isRouteCalculationScheduled(false)
-    , m_isRoutingTableCalculating(false)
-    , m_routingTable(scheduler)
-    , m_fib(m_nlsrFace, scheduler, m_adjacencyList, m_confParam, m_keyChain)
-    , m_namePrefixTable(*this)
-    , m_syncLogicHandler(m_nlsrFace, m_nlsrLsdb, m_confParam, m_sequencingManager)
-    , m_helloProtocol(*this, scheduler)
-    , m_certificateCache(new ndn::CertificateCacheTtl(ioService))
-    , m_validator(m_nlsrFace, DEFAULT_BROADCAST_PREFIX, m_certificateCache)
-    , m_prefixUpdateProcessor(m_nlsrFace,
-                              m_namePrefixList,
-                              m_nlsrLsdb,
-                              m_syncLogicHandler,
-                              DEFAULT_BROADCAST_PREFIX,
-                              m_keyChain,
-                              m_certificateCache)
-    , m_faceMonitor(m_nlsrFace)
-    , m_firstHelloInterval(FIRST_HELLO_INTERVAL_DEFAULT)
-  {
-    m_faceMonitor.onNotification.connect(bind(&Nlsr::onFaceEventNotification, this, _1));
-    m_faceMonitor.start();
-  }
+  Nlsr(boost::asio::io_service& ioService, ndn::Scheduler& scheduler, ndn::Face& face);
 
   void
   registrationFailed(const ndn::Name& name);
@@ -400,7 +367,7 @@
   NamePrefixTable m_namePrefixTable;
   SyncLogicHandler m_syncLogicHandler;
   HelloProtocol m_helloProtocol;
-  std::unique_ptr<LsdbDatasetInterestHandler> m_lsdbDatasetHandler;
+  LsdbDatasetInterestHandler m_lsdbDatasetHandler;
 
 private:
   ndn::shared_ptr<ndn::CertificateCacheTtl> m_certificateCache;
diff --git a/src/publisher/lsa-publisher.cpp b/src/publisher/lsa-publisher.cpp
index 31192fd..a880fba 100644
--- a/src/publisher/lsa-publisher.cpp
+++ b/src/publisher/lsa-publisher.cpp
@@ -32,9 +32,8 @@
 
 AdjacencyLsaPublisher::AdjacencyLsaPublisher(Lsdb& lsdb,
                                              ndn::Face& face,
-                                             const ndn::Name& prefix,
                                              ndn::KeyChain& keyChain)
-  : LsaPublisher(face, prefix, keyChain, DATASET_COMPONENT)
+  : LsaPublisher(face, keyChain)
   , m_adjacencyLsas(lsdb.getAdjLsdb())
 {
 }
@@ -73,9 +72,8 @@
 
 CoordinateLsaPublisher::CoordinateLsaPublisher(Lsdb& lsdb,
                                                ndn::Face& face,
-                                               const ndn::Name& prefix,
                                                ndn::KeyChain& keyChain)
-  : LsaPublisher(face, prefix, keyChain, DATASET_COMPONENT)
+  : LsaPublisher(face, keyChain)
   , m_coordinateLsas(lsdb.getCoordinateLsdb())
 {
 }
@@ -109,9 +107,8 @@
 
 NameLsaPublisher::NameLsaPublisher(Lsdb& lsdb,
                                    ndn::Face& face,
-                                   const ndn::Name& prefix,
                                    ndn::KeyChain& keyChain)
-  : LsaPublisher(face, prefix, keyChain, DATASET_COMPONENT)
+  : LsaPublisher(face, keyChain)
   , m_nameLsas(lsdb.getNameLsdb())
 {
 }
diff --git a/src/publisher/lsa-publisher.hpp b/src/publisher/lsa-publisher.hpp
index 09aec8c..0f38037 100644
--- a/src/publisher/lsa-publisher.hpp
+++ b/src/publisher/lsa-publisher.hpp
@@ -36,11 +36,8 @@
 class LsaPublisher : public SegmentPublisher<ndn::Face>
 {
 public:
-  LsaPublisher(ndn::Face& face,
-                const ndn::Name& prefix,
-                ndn::KeyChain& keyChain,
-                const ndn::Name::Component& datasetComponent)
-  : SegmentPublisher<ndn::Face>(face, ndn::Name(prefix).append(datasetComponent), keyChain)
+  LsaPublisher(ndn::Face& face, ndn::KeyChain& keyChain)
+  : SegmentPublisher<ndn::Face>(face, keyChain)
   {
   }
 
@@ -75,7 +72,6 @@
 public:
   AdjacencyLsaPublisher(Lsdb& lsdb,
                         ndn::Face& face,
-                        const ndn::Name& prefix,
                         ndn::KeyChain& keyChain);
 
   std::list<tlv::AdjacencyLsa>
@@ -97,7 +93,6 @@
 public:
   CoordinateLsaPublisher(Lsdb& lsdb,
                         ndn::Face& face,
-                        const ndn::Name& prefix,
                         ndn::KeyChain& keyChain);
 
   std::list<tlv::CoordinateLsa>
@@ -119,7 +114,6 @@
 public:
   NameLsaPublisher(Lsdb& lsdb,
                    ndn::Face& face,
-                   const ndn::Name& prefix,
                    ndn::KeyChain& keyChain);
 
   std::list<tlv::NameLsa>
diff --git a/src/publisher/lsdb-dataset-interest-handler.cpp b/src/publisher/lsdb-dataset-interest-handler.cpp
index 5285d28..11ddc69 100644
--- a/src/publisher/lsdb-dataset-interest-handler.cpp
+++ b/src/publisher/lsdb-dataset-interest-handler.cpp
@@ -22,6 +22,7 @@
 #include "lsdb-dataset-interest-handler.hpp"
 
 #include "logger.hpp"
+#include "nlsr.hpp"
 
 #include <ndn-cxx/face.hpp>
 #include <ndn-cxx/management/nfd-control-response.hpp>
@@ -31,58 +32,93 @@
 
 INIT_LOGGER("LsdbDatasetInterestHandler");
 
+const uint32_t LsdbDatasetInterestHandler::ERROR_CODE_MALFORMED_COMMAND = 400;
+const uint32_t LsdbDatasetInterestHandler::ERROR_CODE_UNSUPPORTED_COMMAND = 501;
+
 LsdbDatasetInterestHandler::LsdbDatasetInterestHandler(Lsdb& lsdb,
                                                        ndn::Face& face,
                                                        const ndn::Name& routerName,
                                                        ndn::KeyChain& keyChain)
-  : COMMAND_PREFIX(ndn::Name(routerName).append(Lsdb::NAME_COMPONENT))
+  : LOCALHOST_COMMAND_PREFIX(ndn::Name(Nlsr::LOCALHOST_PREFIX).append(Lsdb::NAME_COMPONENT))
+  , ROUTER_NAME_COMMAND_PREFIX(ndn::Name(routerName).append(Lsdb::NAME_COMPONENT))
   , m_face(face)
   , m_keyChain(keyChain)
-  , m_adjacencyLsaPublisher(lsdb, face, COMMAND_PREFIX, keyChain)
-  , m_coordinateLsaPublisher(lsdb, face, COMMAND_PREFIX, keyChain)
-  , m_nameLsaPublisher(lsdb, face, COMMAND_PREFIX, keyChain)
-  , m_lsdbStatusPublisher(lsdb, face, COMMAND_PREFIX, keyChain,
+  , m_adjacencyLsaPublisher(lsdb, face, keyChain)
+  , m_coordinateLsaPublisher(lsdb, face, keyChain)
+  , m_nameLsaPublisher(lsdb, face, keyChain)
+  , m_lsdbStatusPublisher(lsdb, face, keyChain,
                           m_adjacencyLsaPublisher,
                           m_coordinateLsaPublisher,
                           m_nameLsaPublisher)
 
 {
-  _LOG_DEBUG("Setting interest filter for: " << COMMAND_PREFIX);
-  m_face.setInterestFilter(COMMAND_PREFIX,
-                           std::bind(&LsdbDatasetInterestHandler::onInterest, this, _2));
 }
 
 void
-LsdbDatasetInterestHandler::onInterest(const ndn::Interest& interest)
+LsdbDatasetInterestHandler::startListeningOnLocalhost()
 {
-  // Does interest match command prefix with one additional component?
-  if (interest.getName().size() != COMMAND_PREFIX.size() + 1 ||
-      !COMMAND_PREFIX.isPrefixOf(interest.getName()))
+  _LOG_DEBUG("Setting interest filter for: " << LOCALHOST_COMMAND_PREFIX);
+  m_face.setInterestFilter(LOCALHOST_COMMAND_PREFIX,
+                           std::bind(&LsdbDatasetInterestHandler::onInterest, this, _2,
+                                     std::cref(LOCALHOST_COMMAND_PREFIX)));
+}
+
+void
+LsdbDatasetInterestHandler::startListeningOnRouterPrefix()
+{
+  _LOG_DEBUG("Setting interest filter for: " << ROUTER_NAME_COMMAND_PREFIX);
+  m_face.setInterestFilter(ROUTER_NAME_COMMAND_PREFIX,
+                           std::bind(&LsdbDatasetInterestHandler::onInterest, this, _2,
+                                     std::cref(ROUTER_NAME_COMMAND_PREFIX)));
+}
+
+void
+LsdbDatasetInterestHandler::onInterest(const ndn::Interest& interest,
+                                       const ndn::Name& commandPrefix)
+{
+  if (!isValidCommandPrefix(interest, commandPrefix))
   {
     _LOG_DEBUG("Received malformed interest: " << interest.getName());
 
-    sendErrorResponse(interest.getName(), 400, "Malformed command");
+    sendErrorResponse(interest.getName(), ERROR_CODE_MALFORMED_COMMAND, "Malformed command");
     return;
   }
 
-  ndn::Name::Component command = interest.getName().get(COMMAND_PREFIX.size());
+  ndn::Name::Component command = interest.getName().get(commandPrefix.size());
+  processCommand(interest, command);
+}
+
+bool
+LsdbDatasetInterestHandler::isValidCommandPrefix(const ndn::Interest& interest,
+                                                 const ndn::Name& commandPrefix)
+{
+  size_t commandSize = interest.getName().size();
+
+  // Does the Interest match the command prefix with one additional component?
+  return (commandSize == commandPrefix.size() + 1 && commandPrefix.isPrefixOf(interest.getName()));
+}
+
+void
+LsdbDatasetInterestHandler::processCommand(const ndn::Interest& interest,
+                                           const ndn::Name::Component& command)
+{
   _LOG_TRACE("Received interest with command: " << command);
 
   if (command.equals(AdjacencyLsaPublisher::DATASET_COMPONENT)) {
-    m_adjacencyLsaPublisher.publish();
+    m_adjacencyLsaPublisher.publish(interest.getName());
   }
   else if (command.equals(CoordinateLsaPublisher::DATASET_COMPONENT)) {
-    m_coordinateLsaPublisher.publish();
+    m_coordinateLsaPublisher.publish(interest.getName());
   }
   else if (command.equals(NameLsaPublisher::DATASET_COMPONENT)) {
-    m_nameLsaPublisher.publish();
+    m_nameLsaPublisher.publish(interest.getName());
   }
   else if (command.equals(LsdbStatusPublisher::DATASET_COMPONENT)) {
-    m_lsdbStatusPublisher.publish();
+    m_lsdbStatusPublisher.publish(interest.getName());
   }
   else {
     _LOG_DEBUG("Unsupported command: " << command);
-    sendErrorResponse(interest.getName(), 501, "Unsupported command");
+    sendErrorResponse(interest.getName(), ERROR_CODE_UNSUPPORTED_COMMAND, "Unsupported command");
   }
 }
 
diff --git a/src/publisher/lsdb-dataset-interest-handler.hpp b/src/publisher/lsdb-dataset-interest-handler.hpp
index 8f43c87..c56c638 100644
--- a/src/publisher/lsdb-dataset-interest-handler.hpp
+++ b/src/publisher/lsdb-dataset-interest-handler.hpp
@@ -52,13 +52,39 @@
                              ndn::KeyChain& keyChain);
 
   void
-  onInterest(const ndn::Interest& interest);
+  startListeningOnLocalhost();
+
+  void
+  startListeningOnRouterPrefix();
+
+  const ndn::Name&
+  getLocalhostCommandPrefix()
+  {
+    return LOCALHOST_COMMAND_PREFIX;
+  }
+
+  const ndn::Name&
+  getRouterNameCommandPrefix()
+  {
+    return ROUTER_NAME_COMMAND_PREFIX;
+  }
+
+private:
+  void
+  onInterest(const ndn::Interest& interest, const ndn::Name& commandPrefix);
+
+  bool
+  isValidCommandPrefix(const ndn::Interest& interest, const ndn::Name& commandPrefix);
+
+  void
+  processCommand(const ndn::Interest& interest, const ndn::Name::Component& command);
 
   void
   sendErrorResponse(const ndn::Name& name, uint32_t code, const std::string& error);
 
 private:
-  const ndn::Name COMMAND_PREFIX;
+  const ndn::Name LOCALHOST_COMMAND_PREFIX;
+  const ndn::Name ROUTER_NAME_COMMAND_PREFIX;
 
   ndn::Face& m_face;
   ndn::KeyChain& m_keyChain;
@@ -67,6 +93,10 @@
   CoordinateLsaPublisher m_coordinateLsaPublisher;
   NameLsaPublisher m_nameLsaPublisher;
   LsdbStatusPublisher m_lsdbStatusPublisher;
+
+PUBLIC_WITH_TESTS_ELSE_PRIVATE:
+  static const uint32_t ERROR_CODE_MALFORMED_COMMAND;
+  static const uint32_t ERROR_CODE_UNSUPPORTED_COMMAND;
 };
 
 } // namespace nlsr
diff --git a/src/publisher/lsdb-status-publisher.cpp b/src/publisher/lsdb-status-publisher.cpp
index 6905df6..65f570c 100644
--- a/src/publisher/lsdb-status-publisher.cpp
+++ b/src/publisher/lsdb-status-publisher.cpp
@@ -32,12 +32,11 @@
 
 LsdbStatusPublisher::LsdbStatusPublisher(Lsdb& lsdb,
                                          ndn::Face& face,
-                                         const ndn::Name& prefix,
                                          ndn::KeyChain& keyChain,
                                          AdjacencyLsaPublisher& adjacencyLsaPublisher,
                                          CoordinateLsaPublisher& coordinateLsaPublisher,
                                          NameLsaPublisher& nameLsaPublisher)
-  : SegmentPublisher<ndn::Face>(face, ndn::Name(prefix).append(DATASET_COMPONENT), keyChain)
+  : SegmentPublisher<ndn::Face>(face, keyChain)
   , m_adjacencyLsaPublisher(adjacencyLsaPublisher)
   , m_coordinateLsaPublisher(coordinateLsaPublisher)
   , m_nameLsaPublisher(nameLsaPublisher)
diff --git a/src/publisher/lsdb-status-publisher.hpp b/src/publisher/lsdb-status-publisher.hpp
index b8145a8..f9d5841 100644
--- a/src/publisher/lsdb-status-publisher.hpp
+++ b/src/publisher/lsdb-status-publisher.hpp
@@ -39,7 +39,6 @@
 public:
   LsdbStatusPublisher(Lsdb& lsdb,
                       ndn::Face& face,
-                      const ndn::Name& prefix,
                       ndn::KeyChain& keyChain,
                       AdjacencyLsaPublisher& adjacencyLsaPublisher,
                       CoordinateLsaPublisher& coordinateLsaPublisher,
diff --git a/src/publisher/segment-publisher.hpp b/src/publisher/segment-publisher.hpp
index cb311e9..5aefa52 100644
--- a/src/publisher/segment-publisher.hpp
+++ b/src/publisher/segment-publisher.hpp
@@ -39,11 +39,9 @@
 {
 public:
   SegmentPublisher(FaceBase& face,
-                   const ndn::Name& prefix,
                    ndn::KeyChain& keyChain,
                    const ndn::time::milliseconds& freshnessPeriod = getDefaultFreshness())
     : m_face(face)
-    , m_prefix(prefix)
     , m_keyChain(keyChain)
     , m_freshnessPeriod(freshnessPeriod)
   {
@@ -67,8 +65,10 @@
     return ndn::time::milliseconds(1000);
   }
 
+  /** \brief Publish data under provided prefix
+   */
   void
-  publish()
+  publish(const ndn::Name& prefix)
   {
     ndn::EncodingBuffer buffer;
     generate(buffer);
@@ -77,7 +77,7 @@
     const uint8_t* segmentBegin = rawBuffer;
     const uint8_t* end = rawBuffer + buffer.size();
 
-    ndn::Name segmentPrefix(m_prefix);
+    ndn::Name segmentPrefix(prefix);
     segmentPrefix.appendVersion();
 
     uint64_t segmentNo = 0;
@@ -120,7 +120,6 @@
 
 private:
   FaceBase& m_face;
-  const ndn::Name m_prefix;
   ndn::KeyChain& m_keyChain;
   const ndn::time::milliseconds m_freshnessPeriod;
 };
diff --git a/tests/publisher/test-lsa-publisher.cpp b/tests/publisher/test-lsa-publisher.cpp
index aa7922c..4ea6544 100644
--- a/tests/publisher/test-lsa-publisher.cpp
+++ b/tests/publisher/test-lsa-publisher.cpp
@@ -34,9 +34,11 @@
 
 BOOST_AUTO_TEST_CASE(AdjacencyLsaPublisherBasic)
 {
+  ndn::Name thisRouter("/RouterA");
+
   // Adjacency LSA for RouterA
   AdjLsa routerALsa;
-  routerALsa.setOrigRouter("/RouterA");
+  routerALsa.setOrigRouter(thisRouter);
   addAdjacency(routerALsa, "/RouterA/adjacency1", "udp://face-1", 10);
   lsdb.installAdjLsa(routerALsa);
 
@@ -49,9 +51,12 @@
   addAdjacency(routerBLsa, "/RouterB/adjacency3", "udp://face-3", 30);
   lsdb.installAdjLsa(routerBLsa);
 
-  AdjacencyLsaPublisher publisher(lsdb, *face, "/RouterA", keyChain);
+  AdjacencyLsaPublisher publisher(lsdb, *face, keyChain);
 
-  publisher.publish();
+  ndn::Name publishingPrefix = ndn::Name(thisRouter);
+  publishingPrefix.append(Lsdb::NAME_COMPONENT).append(AdjacencyLsaPublisher::DATASET_COMPONENT);
+
+  publisher.publish(publishingPrefix);
   face->processEvents(ndn::time::milliseconds(1));
 
   BOOST_REQUIRE_EQUAL(face->sentDatas.size(), 1);
@@ -69,7 +74,9 @@
 
 BOOST_AUTO_TEST_CASE(CoordinateLsaBasic)
 {
-  CoordinateLsa routerALsa = createCoordinateLsa("/RouterA", 10.0, 20.0);
+  ndn::Name thisRouter("/RouterA");
+
+  CoordinateLsa routerALsa = createCoordinateLsa(thisRouter.toUri(), 10.0, 20.0);
   lsdb.installCoordinateLsa(routerALsa);
 
   CoordinateLsa routerBLsa = createCoordinateLsa("/RouterB", 123.45, 543.21);
@@ -78,9 +85,12 @@
   CoordinateLsa routerCLsa = createCoordinateLsa("/RouterC", 0.01, 0.02);
   lsdb.installCoordinateLsa(routerCLsa);
 
-  CoordinateLsaPublisher publisher(lsdb, *face, "/RouterA", keyChain);
+  CoordinateLsaPublisher publisher(lsdb, *face, keyChain);
 
-  publisher.publish();
+  ndn::Name publishingPrefix = ndn::Name(thisRouter);
+  publishingPrefix.append(Lsdb::NAME_COMPONENT).append(CoordinateLsaPublisher::DATASET_COMPONENT);
+
+  publisher.publish(publishingPrefix);
   face->processEvents(ndn::time::milliseconds(1));
 
   BOOST_REQUIRE_EQUAL(face->sentDatas.size(), 1);
@@ -102,10 +112,12 @@
 
 BOOST_AUTO_TEST_CASE(NameLsaBasic)
 {
+  ndn::Name thisRouter("/RouterA");
+
   // Name LSA for RouterA
   NameLsa routerALsa;
-  routerALsa.setOrigRouter("/RouterA");
-  routerALsa.addName("/RouterA/name1");
+  routerALsa.setOrigRouter(thisRouter.toUri());
+  routerALsa.addName(ndn::Name(thisRouter).append("name1"));
   lsdb.installNameLsa(routerALsa);
 
   // Name LSA for RouterB
@@ -116,9 +128,12 @@
   routerBLsa.addName("/RouterB/name3");
   lsdb.installNameLsa(routerBLsa);
 
-  NameLsaPublisher publisher(lsdb, *face, "/RouterA", keyChain);
+  NameLsaPublisher publisher(lsdb, *face, keyChain);
 
-  publisher.publish();
+  ndn::Name publishingPrefix = ndn::Name(thisRouter);
+  publishingPrefix.append(Lsdb::NAME_COMPONENT).append(NameLsaPublisher::DATASET_COMPONENT);
+
+  publisher.publish(publishingPrefix);
   face->processEvents(ndn::time::milliseconds(1));
 
   BOOST_REQUIRE_EQUAL(face->sentDatas.size(), 1);
diff --git a/tests/publisher/test-lsdb-dataset-interest-handler.cpp b/tests/publisher/test-lsdb-dataset-interest-handler.cpp
index 22b2819..15c6eea 100644
--- a/tests/publisher/test-lsdb-dataset-interest-handler.cpp
+++ b/tests/publisher/test-lsdb-dataset-interest-handler.cpp
@@ -82,30 +82,53 @@
 
   ndn::Name thisRouter("/This/Router");
   LsdbDatasetInterestHandler publisher(lsdb, *face, thisRouter, keyChain);
+  publisher.startListeningOnLocalhost();
 
   face->processEvents(ndn::time::milliseconds(10));
 
-  ndn::Name commandPrefix(thisRouter);
-  commandPrefix.append("lsdb");
+  // Localhost prefix
+  ndn::Name localhostCommandPrefix = publisher.getLocalhostCommandPrefix();
 
   // Request adjacency LSAs
-  face->receive(ndn::Interest(ndn::Name(commandPrefix).append("adjacencies")));
-
+  face->receive(ndn::Interest(ndn::Name(localhostCommandPrefix).append("adjacencies")));
   processDatasetInterest(face,
     [] (const ndn::Block& block) { return block.type() == ndn::tlv::nlsr::AdjacencyLsa; });
 
   // Request coordinate LSAs
-  face->receive(ndn::Interest(ndn::Name(commandPrefix).append("coordinates")));
+  face->receive(ndn::Interest(ndn::Name(localhostCommandPrefix).append("coordinates")));
   processDatasetInterest(face,
     [] (const ndn::Block& block) { return block.type() == ndn::tlv::nlsr::CoordinateLsa; });
 
   // Request Name LSAs
-  face->receive(ndn::Interest(ndn::Name(commandPrefix).append("names")));
+  face->receive(ndn::Interest(ndn::Name(localhostCommandPrefix).append("names")));
   processDatasetInterest(face,
     [] (const ndn::Block& block) { return block.type() == ndn::tlv::nlsr::NameLsa; });
 
   // Request LSDB Status
-  face->receive(ndn::Interest(ndn::Name(commandPrefix).append("list")));
+  face->receive(ndn::Interest(ndn::Name(localhostCommandPrefix).append("list")));
+  processDatasetInterest(face,
+    [] (const ndn::Block& block) { return block.type() == ndn::tlv::nlsr::LsdbStatus; });
+
+  // Router name prefix
+  ndn::Name routerCommandPrefix = publisher.getLocalhostCommandPrefix();
+
+  // Request adjacency LSAs
+  face->receive(ndn::Interest(ndn::Name(routerCommandPrefix).append("adjacencies")));
+  processDatasetInterest(face,
+    [] (const ndn::Block& block) { return block.type() == ndn::tlv::nlsr::AdjacencyLsa; });
+
+  // Request coordinate LSAs
+  face->receive(ndn::Interest(ndn::Name(routerCommandPrefix).append("coordinates")));
+  processDatasetInterest(face,
+    [] (const ndn::Block& block) { return block.type() == ndn::tlv::nlsr::CoordinateLsa; });
+
+  // Request Name LSAs
+  face->receive(ndn::Interest(ndn::Name(routerCommandPrefix).append("names")));
+  processDatasetInterest(face,
+    [] (const ndn::Block& block) { return block.type() == ndn::tlv::nlsr::NameLsa; });
+
+  // Request LSDB Status
+  face->receive(ndn::Interest(ndn::Name(routerCommandPrefix).append("list")));
   processDatasetInterest(face,
     [] (const ndn::Block& block) { return block.type() == ndn::tlv::nlsr::LsdbStatus; });
 }
@@ -115,22 +138,42 @@
   ndn::Name thisRouter("/This/Router");
   LsdbDatasetInterestHandler publisher(lsdb, *face, thisRouter, keyChain);
 
+  // Localhost prefix
+  publisher.startListeningOnLocalhost();
   face->processEvents(ndn::time::milliseconds(10));
 
-  ndn::Name commandPrefix(thisRouter);
-  commandPrefix.append("lsdb");
+  ndn::Name localhostCommandPrefix = publisher.getLocalhostCommandPrefix();
 
   // Unsupported command
-  face->receive(ndn::Interest(ndn::Name(commandPrefix).append("unsupported")));
+  face->receive(ndn::Interest(ndn::Name(localhostCommandPrefix).append("unsupported")));
   face->processEvents(ndn::time::milliseconds(1));
 
-  checkErrorResponse(face, 501);
+  checkErrorResponse(face, LsdbDatasetInterestHandler::ERROR_CODE_UNSUPPORTED_COMMAND);
 
   // Long malformed command
-  face->receive(ndn::Interest(ndn::Name(commandPrefix).append("extra").append("malformed")));
+  face->receive(
+    ndn::Interest(ndn::Name(localhostCommandPrefix).append("extra").append("malformed")));
   face->processEvents(ndn::time::milliseconds(1));
 
-  checkErrorResponse(face, 400);
+  checkErrorResponse(face, LsdbDatasetInterestHandler::ERROR_CODE_MALFORMED_COMMAND);
+
+  // Router name prefix
+  publisher.startListeningOnRouterPrefix();
+  face->processEvents(ndn::time::milliseconds(10));
+
+  ndn::Name remoteCommandPrefix = publisher.getRouterNameCommandPrefix();
+
+  // Unsupported command
+  face->receive(ndn::Interest(ndn::Name(remoteCommandPrefix).append("unsupported")));
+  face->processEvents(ndn::time::milliseconds(1));
+
+  checkErrorResponse(face, LsdbDatasetInterestHandler::ERROR_CODE_UNSUPPORTED_COMMAND);
+
+  // Long malformed command
+  face->receive(ndn::Interest(ndn::Name(remoteCommandPrefix).append("extra").append("malformed")));
+  face->processEvents(ndn::time::milliseconds(1));
+
+  checkErrorResponse(face, LsdbDatasetInterestHandler::ERROR_CODE_MALFORMED_COMMAND);
 
   // Short malformed command
   face->receive(ndn::Interest(ndn::Name(thisRouter).append("malformed")));
diff --git a/tests/publisher/test-lsdb-status-publisher.cpp b/tests/publisher/test-lsdb-status-publisher.cpp
index 50d48da..58c4eff 100644
--- a/tests/publisher/test-lsdb-status-publisher.cpp
+++ b/tests/publisher/test-lsdb-status-publisher.cpp
@@ -75,16 +75,19 @@
   lsdb.installNameLsa(routerBNameLsa);
 
   ndn::Name thisRouter("/This/Router");
-  AdjacencyLsaPublisher adjacencyLsaPublisher(lsdb, *face, thisRouter, keyChain);
-  CoordinateLsaPublisher coordinateLsaPublisher(lsdb, *face, thisRouter, keyChain);
-  NameLsaPublisher nameLsaPublisher(lsdb, *face, thisRouter, keyChain);
+  AdjacencyLsaPublisher adjacencyLsaPublisher(lsdb, *face, keyChain);
+  CoordinateLsaPublisher coordinateLsaPublisher(lsdb, *face, keyChain);
+  NameLsaPublisher nameLsaPublisher(lsdb, *face, keyChain);
 
-  LsdbStatusPublisher publisher(lsdb, *face, thisRouter, keyChain,
+  LsdbStatusPublisher publisher(lsdb, *face, keyChain,
                                 adjacencyLsaPublisher,
                                 coordinateLsaPublisher,
                                 nameLsaPublisher);
 
-  publisher.publish();
+  ndn::Name publishingPrefix = ndn::Name(thisRouter);
+  publishingPrefix.append(Lsdb::NAME_COMPONENT).append(LsdbStatusPublisher::DATASET_COMPONENT);
+
+  publisher.publish(publishingPrefix);
   face->processEvents(ndn::time::milliseconds(1));
 
   BOOST_REQUIRE_EQUAL(face->sentDatas.size(), 1);
diff --git a/tests/publisher/test-segment-publisher.cpp b/tests/publisher/test-segment-publisher.cpp
index 8cc8dde..0855466 100644
--- a/tests/publisher/test-segment-publisher.cpp
+++ b/tests/publisher/test-segment-publisher.cpp
@@ -41,10 +41,9 @@
 {
 public:
   TestSegmentPublisher(ndn::util::DummyClientFace& face,
-                       const ndn::Name& prefix,
                        ndn::KeyChain& keyChain,
                        const ndn::time::milliseconds freshnessPeriod)
-    : SegmentPublisher(face, prefix, keyChain, freshnessPeriod)
+    : SegmentPublisher(face, keyChain, freshnessPeriod)
     , m_totalPayloadLength(0)
   {
 
@@ -92,8 +91,8 @@
   SegmentPublisherFixture()
     : m_face(ndn::util::makeDummyClientFace())
     , m_expectedFreshnessPeriod(ndn::time::milliseconds(111))
-    , m_publisher(*m_face, "/localhost/nfd/SegmentPublisherFixture",
-                  m_keyChain, m_expectedFreshnessPeriod)
+    , m_publisher(*m_face, m_keyChain, m_expectedFreshnessPeriod)
+    , m_publishingPrefix("/localhost/nfd/SegmentPublisherFixture")
   {
   }
 
@@ -140,6 +139,7 @@
   TestSegmentPublisher<N> m_publisher;
   ndn::EncodingBuffer m_buffer;
   ndn::KeyChain m_keyChain;
+  const ndn::Name m_publishingPrefix;
 };
 
 using boost::mpl::int_;
@@ -149,7 +149,7 @@
 
 BOOST_FIXTURE_TEST_CASE_TEMPLATE(Generate, T, DatasetSizes, SegmentPublisherFixture<T::value>)
 {
-  this->m_publisher.publish();
+  this->m_publisher.publish(this->m_publishingPrefix);
   this->m_face->processEvents();
 
   size_t nSegments = this->m_publisher.getTotalPayloadLength() /