publisher: add LSDB dataset publishers

refs #2280

Change-Id: Ifb1920ef9b807610890b0d0a04f24141d39f011d
diff --git a/src/lsdb.cpp b/src/lsdb.cpp
index 8c41c9f..1374906 100644
--- a/src/lsdb.cpp
+++ b/src/lsdb.cpp
@@ -32,6 +32,7 @@
 
 INIT_LOGGER("Lsdb");
 
+const ndn::Name::Component Lsdb::NAME_COMPONENT = ndn::Name::Component("lsdb");
 const ndn::time::seconds Lsdb::GRACE_PERIOD = ndn::time::seconds(10);
 const steady_clock::TimePoint Lsdb::DEFAULT_LSA_RETRIEVAL_DEADLINE = steady_clock::TimePoint::min();
 
@@ -248,6 +249,12 @@
   }
 }
 
+const std::list<NameLsa>&
+Lsdb::getNameLsdb()
+{
+  return m_nameLsdb;
+}
+
 // Cor LSA and LSDB related Functions start here
 
 static bool
@@ -420,6 +427,12 @@
   }
 }
 
+const std::list<CoordinateLsa>&
+Lsdb::getCoordinateLsdb()
+{
+  return m_corLsdb;
+}
+
 // Adj LSA and LSDB related function starts here
 
 static bool
@@ -625,7 +638,7 @@
   return true;
 }
 
-std::list<AdjLsa>&
+const std::list<AdjLsa>&
 Lsdb::getAdjLsdb()
 {
   return m_adjLsdb;
diff --git a/src/lsdb.hpp b/src/lsdb.hpp
index 34d7562..7ab54e5 100644
--- a/src/lsdb.hpp
+++ b/src/lsdb.hpp
@@ -73,6 +73,9 @@
   void
   writeNameLsdbLog();
 
+  const std::list<NameLsa>&
+  getNameLsdb();
+
   //function related to Cor LSDB
   bool
   buildAndInstallOwnCoordinateLsa();
@@ -92,6 +95,9 @@
   void
   writeCorLsdbLog();
 
+  const std::list<CoordinateLsa>&
+  getCoordinateLsdb();
+
   //function related to Adj LSDB
 
   void
@@ -105,13 +111,14 @@
 
   bool
   isAdjLsaNew(const ndn::Name& key, uint64_t seqNo);
+
   bool
   installAdjLsa(AdjLsa& alsa);
 
   AdjLsa*
   findAdjLsa(const ndn::Name& key);
 
-  std::list<AdjLsa>&
+  const std::list<AdjLsa>&
   getAdjLsdb();
 
   void
@@ -257,6 +264,9 @@
   void
   cancelScheduleLsaExpiringEvent(ndn::EventId eid);
 
+public:
+  static const ndn::Name::Component NAME_COMPONENT;
+
 private:
   Nlsr& m_nlsr;
   ndn::Scheduler& m_scheduler;
diff --git a/src/nlsr.cpp b/src/nlsr.cpp
index c77cbf8..5d40002 100644
--- a/src/nlsr.cpp
+++ b/src/nlsr.cpp
@@ -47,6 +47,13 @@
 void
 Nlsr::onRegistrationSuccess(const ndn::Name& name)
 {
+  if (name.equals(m_confParam.getRouterPrefix())) {
+    m_lsdbDatasetHandler = std::unique_ptr<LsdbDatasetInterestHandler>(
+      new LsdbDatasetInterestHandler(m_nlsrLsdb,
+                                     m_nlsrFace,
+                                     m_confParam.getRouterPrefix(),
+                                     m_keyChain));
+  }
 }
 
 void
diff --git a/src/nlsr.hpp b/src/nlsr.hpp
index 7e73ebc..1b7527d 100644
--- a/src/nlsr.hpp
+++ b/src/nlsr.hpp
@@ -44,6 +44,7 @@
 #include "communication/sync-logic-handler.hpp"
 #include "hello-protocol.hpp"
 #include "test-access-control.hpp"
+#include "publisher/lsdb-dataset-interest-handler.hpp"
 
 #include "validator.hpp"
 
@@ -367,6 +368,7 @@
   NamePrefixTable m_namePrefixTable;
   SyncLogicHandler m_syncLogicHandler;
   HelloProtocol m_helloProtocol;
+  std::unique_ptr<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
new file mode 100644
index 0000000..31192fd
--- /dev/null
+++ b/src/publisher/lsa-publisher.cpp
@@ -0,0 +1,140 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015,  The University of Memphis,
+ *                           Regents of the University of California,
+ *                           Arizona Board of Regents.
+ *
+ * This file is part of NLSR (Named-data Link State Routing).
+ * See AUTHORS.md for complete list of NLSR authors and contributors.
+ *
+ * NLSR is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+#include "lsa-publisher.hpp"
+
+#include "lsa.hpp"
+
+#include <ndn-cxx/face.hpp>
+
+namespace nlsr {
+
+const ndn::Name::Component AdjacencyLsaPublisher::DATASET_COMPONENT =
+  ndn::Name::Component("adjacencies");
+
+AdjacencyLsaPublisher::AdjacencyLsaPublisher(Lsdb& lsdb,
+                                             ndn::Face& face,
+                                             const ndn::Name& prefix,
+                                             ndn::KeyChain& keyChain)
+  : LsaPublisher(face, prefix, keyChain, DATASET_COMPONENT)
+  , m_adjacencyLsas(lsdb.getAdjLsdb())
+{
+}
+
+std::list<tlv::AdjacencyLsa>
+AdjacencyLsaPublisher::getTlvLsas()
+{
+  std::list<tlv::AdjacencyLsa> lsas;
+
+  for (AdjLsa lsa : m_adjacencyLsas) {
+    tlv::AdjacencyLsa tlvLsa;
+
+    std::shared_ptr<tlv::LsaInfo> tlvLsaInfo = tlv::makeLsaInfo(lsa);
+    tlvLsa.setLsaInfo(*tlvLsaInfo);
+
+    for (const Adjacent& adj : lsa.getAdl().getAdjList()) {
+      tlv::Adjacency tlvAdj;
+      tlvAdj.setName(adj.getName());
+      tlvAdj.setUri(adj.getConnectingFaceUri());
+      tlvAdj.setCost(adj.getLinkCost());
+      tlvLsa.addAdjacency(tlvAdj);
+    }
+
+    lsas.push_back(tlvLsa);
+  }
+
+  return lsas;
+}
+
+//////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////
+
+const ndn::Name::Component CoordinateLsaPublisher::DATASET_COMPONENT =
+  ndn::Name::Component("coordinates");
+
+CoordinateLsaPublisher::CoordinateLsaPublisher(Lsdb& lsdb,
+                                               ndn::Face& face,
+                                               const ndn::Name& prefix,
+                                               ndn::KeyChain& keyChain)
+  : LsaPublisher(face, prefix, keyChain, DATASET_COMPONENT)
+  , m_coordinateLsas(lsdb.getCoordinateLsdb())
+{
+}
+
+std::list<tlv::CoordinateLsa>
+CoordinateLsaPublisher::getTlvLsas()
+{
+  std::list<tlv::CoordinateLsa> lsas;
+
+  for (const CoordinateLsa lsa : m_coordinateLsas) {
+    tlv::CoordinateLsa tlvLsa;
+
+    std::shared_ptr<tlv::LsaInfo> tlvLsaInfo = tlv::makeLsaInfo(lsa);
+    tlvLsa.setLsaInfo(*tlvLsaInfo);
+
+    tlvLsa.setHyperbolicRadius(lsa.getCorRadius());
+    tlvLsa.setHyperbolicAngle(lsa.getCorTheta());
+
+    lsas.push_back(tlvLsa);
+  }
+
+  return lsas;
+}
+
+//////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////
+
+const ndn::Name::Component NameLsaPublisher::DATASET_COMPONENT =
+  ndn::Name::Component("names");
+
+NameLsaPublisher::NameLsaPublisher(Lsdb& lsdb,
+                                   ndn::Face& face,
+                                   const ndn::Name& prefix,
+                                   ndn::KeyChain& keyChain)
+  : LsaPublisher(face, prefix, keyChain, DATASET_COMPONENT)
+  , m_nameLsas(lsdb.getNameLsdb())
+{
+}
+
+std::list<tlv::NameLsa>
+NameLsaPublisher::getTlvLsas()
+{
+  std::list<tlv::NameLsa> lsas;
+
+  for (NameLsa lsa : m_nameLsas) {
+    tlv::NameLsa tlvLsa;
+
+    std::shared_ptr<tlv::LsaInfo> tlvLsaInfo = tlv::makeLsaInfo(lsa);
+    tlvLsa.setLsaInfo(*tlvLsaInfo);
+
+    for (const ndn::Name& name : lsa.getNpl().getNameList()) {
+      tlvLsa.addName(name);
+    }
+
+    lsas.push_back(tlvLsa);
+  }
+
+  return lsas;
+}
+
+} // namespace nlsr
diff --git a/src/publisher/lsa-publisher.hpp b/src/publisher/lsa-publisher.hpp
new file mode 100644
index 0000000..09aec8c
--- /dev/null
+++ b/src/publisher/lsa-publisher.hpp
@@ -0,0 +1,137 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015,  The University of Memphis,
+ *                           Regents of the University of California,
+ *                           Arizona Board of Regents.
+ *
+ * This file is part of NLSR (Named-data Link State Routing).
+ * See AUTHORS.md for complete list of NLSR authors and contributors.
+ *
+ * NLSR is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+#ifndef NLSR_PUBLISHER_LSA_PUBLISHER_HPP
+#define NLSR_PUBLISHER_LSA_PUBLISHER_HPP
+
+#include "lsdb.hpp"
+#include "segment-publisher.hpp"
+#include "tlv/adjacency-lsa.hpp"
+#include "tlv/coordinate-lsa.hpp"
+#include "tlv/name-lsa.hpp"
+
+#include <ndn-cxx/face.hpp>
+
+namespace nlsr {
+
+template <class TlvType>
+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)
+  {
+  }
+
+  virtual
+  ~LsaPublisher()
+  {
+  }
+
+protected:
+  virtual size_t
+  generate(ndn::EncodingBuffer& outBuffer)
+  {
+    size_t totalLength = 0;
+
+    for (const TlvType& lsaTlv : getTlvLsas()) {
+      totalLength += lsaTlv.wireEncode(outBuffer);
+    }
+
+    return totalLength;
+  }
+
+  virtual std::list<TlvType>
+  getTlvLsas() = 0;
+};
+
+/**
+ * @brief Abstraction to publish adjacency lsa dataset
+ * \sa http://redmine.named-data.net/projects/nlsr/wiki/LSDB_DataSet
+ */
+class AdjacencyLsaPublisher : public LsaPublisher<tlv::AdjacencyLsa>
+{
+public:
+  AdjacencyLsaPublisher(Lsdb& lsdb,
+                        ndn::Face& face,
+                        const ndn::Name& prefix,
+                        ndn::KeyChain& keyChain);
+
+  std::list<tlv::AdjacencyLsa>
+  getTlvLsas();
+
+public:
+  static const ndn::Name::Component DATASET_COMPONENT;
+
+private:
+  const std::list<AdjLsa>& m_adjacencyLsas;
+};
+
+/**
+ * @brief Abstraction to publish coordinate lsa dataset
+ * \sa http://redmine.named-data.net/projects/nlsr/wiki/LSDB_DataSet
+ */
+class CoordinateLsaPublisher : public LsaPublisher<tlv::CoordinateLsa>
+{
+public:
+  CoordinateLsaPublisher(Lsdb& lsdb,
+                        ndn::Face& face,
+                        const ndn::Name& prefix,
+                        ndn::KeyChain& keyChain);
+
+  std::list<tlv::CoordinateLsa>
+  getTlvLsas();
+
+public:
+  static const ndn::Name::Component DATASET_COMPONENT;
+
+private:
+  const std::list<CoordinateLsa>& m_coordinateLsas;
+};
+
+/**
+ * @brief Abstraction to publish name lsa dataset
+ * \sa http://redmine.named-data.net/projects/nlsr/wiki/LSDB_DataSet
+ */
+class NameLsaPublisher : public LsaPublisher<tlv::NameLsa>
+{
+public:
+  NameLsaPublisher(Lsdb& lsdb,
+                   ndn::Face& face,
+                   const ndn::Name& prefix,
+                   ndn::KeyChain& keyChain);
+
+  std::list<tlv::NameLsa>
+  getTlvLsas();
+
+public:
+  static const ndn::Name::Component DATASET_COMPONENT;
+
+private:
+  const std::list<NameLsa>& m_nameLsas;
+};
+
+} // namespace nlsr
+
+#endif // NLSR_PUBLISHER_LSA_PUBLISHER_HPP
diff --git a/src/publisher/lsdb-dataset-interest-handler.cpp b/src/publisher/lsdb-dataset-interest-handler.cpp
new file mode 100644
index 0000000..5285d28
--- /dev/null
+++ b/src/publisher/lsdb-dataset-interest-handler.cpp
@@ -0,0 +1,103 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015,  The University of Memphis,
+ *                           Regents of the University of California,
+ *                           Arizona Board of Regents.
+ *
+ * This file is part of NLSR (Named-data Link State Routing).
+ * See AUTHORS.md for complete list of NLSR authors and contributors.
+ *
+ * NLSR is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+#include "lsdb-dataset-interest-handler.hpp"
+
+#include "logger.hpp"
+
+#include <ndn-cxx/face.hpp>
+#include <ndn-cxx/management/nfd-control-response.hpp>
+#include <ndn-cxx/util/regex.hpp>
+
+namespace nlsr {
+
+INIT_LOGGER("LsdbDatasetInterestHandler");
+
+LsdbDatasetInterestHandler::LsdbDatasetInterestHandler(Lsdb& lsdb,
+                                                       ndn::Face& face,
+                                                       const ndn::Name& routerName,
+                                                       ndn::KeyChain& keyChain)
+  : 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,
+                          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)
+{
+  // Does interest match command prefix with one additional component?
+  if (interest.getName().size() != COMMAND_PREFIX.size() + 1 ||
+      !COMMAND_PREFIX.isPrefixOf(interest.getName()))
+  {
+    _LOG_DEBUG("Received malformed interest: " << interest.getName());
+
+    sendErrorResponse(interest.getName(), 400, "Malformed command");
+    return;
+  }
+
+  ndn::Name::Component command = interest.getName().get(COMMAND_PREFIX.size());
+  _LOG_TRACE("Received interest with command: " << command);
+
+  if (command.equals(AdjacencyLsaPublisher::DATASET_COMPONENT)) {
+    m_adjacencyLsaPublisher.publish();
+  }
+  else if (command.equals(CoordinateLsaPublisher::DATASET_COMPONENT)) {
+    m_coordinateLsaPublisher.publish();
+  }
+  else if (command.equals(NameLsaPublisher::DATASET_COMPONENT)) {
+    m_nameLsaPublisher.publish();
+  }
+  else if (command.equals(LsdbStatusPublisher::DATASET_COMPONENT)) {
+    m_lsdbStatusPublisher.publish();
+  }
+  else {
+    _LOG_DEBUG("Unsupported command: " << command);
+    sendErrorResponse(interest.getName(), 501, "Unsupported command");
+  }
+}
+
+void
+LsdbDatasetInterestHandler::sendErrorResponse(const ndn::Name& name,
+                                              uint32_t code,
+                                              const std::string& error)
+{
+  ndn::nfd::ControlResponse response(code, error);
+
+  std::shared_ptr<ndn::Data> data = std::make_shared<ndn::Data>(name);
+  data->setContent(response.wireEncode());
+
+  m_keyChain.sign(*data);
+  m_face.put(*data);
+}
+
+} // namespace nlsr
diff --git a/src/publisher/lsdb-dataset-interest-handler.hpp b/src/publisher/lsdb-dataset-interest-handler.hpp
new file mode 100644
index 0000000..8f43c87
--- /dev/null
+++ b/src/publisher/lsdb-dataset-interest-handler.hpp
@@ -0,0 +1,74 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015,  The University of Memphis,
+ *                           Regents of the University of California,
+ *                           Arizona Board of Regents.
+ *
+ * This file is part of NLSR (Named-data Link State Routing).
+ * See AUTHORS.md for complete list of NLSR authors and contributors.
+ *
+ * NLSR is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+#ifndef NLSR_PUBLISHER_LSDB_DATASET_INTEREST_HANDLER_HPP
+#define NLSR_PUBLISHER_LSDB_DATASET_INTEREST_HANDLER_HPP
+
+#include "lsa-publisher.hpp"
+#include "lsdb-status-publisher.hpp"
+
+#include <ndn-cxx/face.hpp>
+
+namespace nlsr {
+
+/**
+ * @brief Abstraction to publish all lsa dataset
+ * \sa http://redmine.named-data.net/projects/nlsr/wiki/LSDB_DataSet
+ */
+class LsdbDatasetInterestHandler
+{
+public:
+  class Error : std::runtime_error
+  {
+  public:
+    explicit
+    Error(const std::string& what)
+      : std::runtime_error(what)
+    {
+    }
+  };
+
+  LsdbDatasetInterestHandler(Lsdb& lsdb,
+                             ndn::Face& face,
+                             const ndn::Name& routerName,
+                             ndn::KeyChain& keyChain);
+
+  void
+  onInterest(const ndn::Interest& interest);
+
+  void
+  sendErrorResponse(const ndn::Name& name, uint32_t code, const std::string& error);
+
+private:
+  const ndn::Name COMMAND_PREFIX;
+
+  ndn::Face& m_face;
+  ndn::KeyChain& m_keyChain;
+
+  AdjacencyLsaPublisher m_adjacencyLsaPublisher;
+  CoordinateLsaPublisher m_coordinateLsaPublisher;
+  NameLsaPublisher m_nameLsaPublisher;
+  LsdbStatusPublisher m_lsdbStatusPublisher;
+};
+
+} // namespace nlsr
+
+#endif // NLSR_PUBLISHER_LSDB_DATASET_INTEREST_HANDLER_HPP
diff --git a/src/publisher/lsdb-status-publisher.cpp b/src/publisher/lsdb-status-publisher.cpp
new file mode 100644
index 0000000..6905df6
--- /dev/null
+++ b/src/publisher/lsdb-status-publisher.cpp
@@ -0,0 +1,70 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015,  The University of Memphis,
+ *                           Regents of the University of California,
+ *                           Arizona Board of Regents.
+ *
+ * This file is part of NLSR (Named-data Link State Routing).
+ * See AUTHORS.md for complete list of NLSR authors and contributors.
+ *
+ * NLSR is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+#include "lsdb-status-publisher.hpp"
+
+#include "lsa.hpp"
+#include "tlv/lsdb-status.hpp"
+
+#include <ndn-cxx/face.hpp>
+
+namespace nlsr {
+
+const ndn::Name::Component LsdbStatusPublisher::DATASET_COMPONENT = ndn::Name::Component("list");
+
+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)
+  , m_adjacencyLsaPublisher(adjacencyLsaPublisher)
+  , m_coordinateLsaPublisher(coordinateLsaPublisher)
+  , m_nameLsaPublisher(nameLsaPublisher)
+{
+}
+
+size_t
+LsdbStatusPublisher::generate(ndn::EncodingBuffer& outBuffer)
+{
+  size_t totalLength = 0;
+
+  tlv::LsdbStatus lsdbStatus;
+  for (const tlv::AdjacencyLsa& tlvLsa : m_adjacencyLsaPublisher.getTlvLsas()) {
+    lsdbStatus.addAdjacencyLsa(tlvLsa);
+  }
+
+  for (const tlv::CoordinateLsa& tlvLsa : m_coordinateLsaPublisher.getTlvLsas()) {
+    lsdbStatus.addCoordinateLsa(tlvLsa);
+  }
+
+  for (const tlv::NameLsa& tlvLsa : m_nameLsaPublisher.getTlvLsas()) {
+    lsdbStatus.addNameLsa(tlvLsa);
+  }
+
+  totalLength += lsdbStatus.wireEncode(outBuffer);
+
+  return totalLength;
+}
+
+} // namespace nlsr
diff --git a/src/publisher/lsdb-status-publisher.hpp b/src/publisher/lsdb-status-publisher.hpp
new file mode 100644
index 0000000..b8145a8
--- /dev/null
+++ b/src/publisher/lsdb-status-publisher.hpp
@@ -0,0 +1,63 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015,  The University of Memphis,
+ *                           Regents of the University of California,
+ *                           Arizona Board of Regents.
+ *
+ * This file is part of NLSR (Named-data Link State Routing).
+ * See AUTHORS.md for complete list of NLSR authors and contributors.
+ *
+ * NLSR is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+#ifndef NLSR_PUBLISHER_LSDB_STATUS_PUBLISHER_HPP
+#define NLSR_PUBLISHER_LSDB_STATUS_PUBLISHER_HPP
+
+#include "lsa-publisher.hpp"
+#include "lsdb.hpp"
+#include "segment-publisher.hpp"
+
+#include <ndn-cxx/face.hpp>
+
+namespace nlsr {
+
+/**
+ * @brief Abstraction to publish lsdb status dataset
+ * \sa http://redmine.named-data.net/projects/nlsr/wiki/LSDB_DataSet
+ */
+class LsdbStatusPublisher : public SegmentPublisher<ndn::Face>
+{
+public:
+  LsdbStatusPublisher(Lsdb& lsdb,
+                      ndn::Face& face,
+                      const ndn::Name& prefix,
+                      ndn::KeyChain& keyChain,
+                      AdjacencyLsaPublisher& adjacencyLsaPublisher,
+                      CoordinateLsaPublisher& coordinateLsaPublisher,
+                      NameLsaPublisher& nameLsaPublisher);
+
+protected:
+  virtual size_t
+  generate(ndn::EncodingBuffer& outBuffer);
+
+private:
+  AdjacencyLsaPublisher& m_adjacencyLsaPublisher;
+  CoordinateLsaPublisher& m_coordinateLsaPublisher;
+  NameLsaPublisher& m_nameLsaPublisher;
+
+public:
+  static const ndn::Name::Component DATASET_COMPONENT;
+};
+
+} // namespace nlsr
+
+#endif // NLSR_PUBLISHER_LSDB_STATUS_PUBLISHER_HPP
diff --git a/src/publisher/segment-publisher.hpp b/src/publisher/segment-publisher.hpp
new file mode 100644
index 0000000..cb311e9
--- /dev/null
+++ b/src/publisher/segment-publisher.hpp
@@ -0,0 +1,130 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015,  Regents of the University of California,
+ *                           Arizona Board of Regents,
+ *                           Colorado State University,
+ *                           University Pierre & Marie Curie, Sorbonne University,
+ *                           Washington University in St. Louis,
+ *                           Beijing Institute of Technology,
+ *                           The University of Memphis.
+ *
+ * This file is part of NFD (Named Data Networking Forwarding Daemon).
+ * See AUTHORS.md for complete list of NFD authors and contributors.
+ *
+ * NFD is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NLSR_PUBLISHER_SEGMENT_PUBLISHER_HPP
+#define NLSR_PUBLISHER_SEGMENT_PUBLISHER_HPP
+
+#include <ndn-cxx/encoding/encoding-buffer.hpp>
+#include <ndn-cxx/security/key-chain.hpp>
+
+namespace nlsr {
+
+/** \brief provides a publisher of Status Dataset or other segmented octet stream
+ *  \sa http://redmine.named-data.net/projects/nfd/wiki/StatusDataset
+ */
+template <class FaceBase>
+class SegmentPublisher : ndn::noncopyable
+{
+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)
+  {
+  }
+
+  virtual
+  ~SegmentPublisher()
+  {
+  }
+
+  static size_t
+  getMaxSegmentSize()
+  {
+    static const size_t MAX_SEGMENT_SIZE = ndn::MAX_NDN_PACKET_SIZE >> 1;
+    return MAX_SEGMENT_SIZE;
+  }
+
+  static constexpr ndn::time::milliseconds
+  getDefaultFreshness()
+  {
+    return ndn::time::milliseconds(1000);
+  }
+
+  void
+  publish()
+  {
+    ndn::EncodingBuffer buffer;
+    generate(buffer);
+
+    const uint8_t* rawBuffer = buffer.buf();
+    const uint8_t* segmentBegin = rawBuffer;
+    const uint8_t* end = rawBuffer + buffer.size();
+
+    ndn::Name segmentPrefix(m_prefix);
+    segmentPrefix.appendVersion();
+
+    uint64_t segmentNo = 0;
+    do {
+      const uint8_t* segmentEnd = segmentBegin + getMaxSegmentSize();
+      if (segmentEnd > end) {
+        segmentEnd = end;
+      }
+
+      ndn::Name segmentName(segmentPrefix);
+      segmentName.appendSegment(segmentNo);
+
+      ndn::shared_ptr<ndn::Data> data = ndn::make_shared<ndn::Data>(segmentName);
+      data->setContent(segmentBegin, segmentEnd - segmentBegin);
+      data->setFreshnessPeriod(m_freshnessPeriod);
+
+      segmentBegin = segmentEnd;
+      if (segmentBegin >= end) {
+        data->setFinalBlockId(segmentName[-1]);
+      }
+
+      publishSegment(data);
+      ++segmentNo;
+    } while (segmentBegin < end);
+  }
+
+protected:
+  /** \brief In a derived class, write the octets into outBuffer.
+   */
+  virtual size_t
+  generate(ndn::EncodingBuffer& outBuffer) = 0;
+
+private:
+  void
+  publishSegment(ndn::shared_ptr<ndn::Data>& data)
+  {
+    m_keyChain.sign(*data);
+    m_face.put(*data);
+  }
+
+private:
+  FaceBase& m_face;
+  const ndn::Name m_prefix;
+  ndn::KeyChain& m_keyChain;
+  const ndn::time::milliseconds m_freshnessPeriod;
+};
+
+} // namespace nlsr
+
+#endif // NLSR_PUBLISHER_SEGMENT_PUBLISHER_HPP
diff --git a/src/tlv/lsa-info.cpp b/src/tlv/lsa-info.cpp
index 5349c31..e81bdc9 100644
--- a/src/tlv/lsa-info.cpp
+++ b/src/tlv/lsa-info.cpp
@@ -170,5 +170,21 @@
   return os;
 }
 
+std::shared_ptr<LsaInfo>
+makeLsaInfo(const Lsa& lsa)
+{
+  std::shared_ptr<LsaInfo> lsaInfo = std::make_shared<LsaInfo>();
+
+  lsaInfo->setOriginRouter(lsa.getOrigRouter());
+  lsaInfo->setSequenceNumber(lsa.getLsSeqNo());
+
+  ndn::time::system_clock::duration duration
+    = lsa.getExpirationTimePoint() - ndn::time::system_clock::now();
+
+  lsaInfo->setExpirationPeriod(ndn::time::duration_cast<ndn::time::milliseconds>(duration));
+
+  return lsaInfo;
+}
+
 } // namespace tlv
 } // namespace nlsr
diff --git a/src/tlv/lsa-info.hpp b/src/tlv/lsa-info.hpp
index a5cf7bf..0cb186c 100644
--- a/src/tlv/lsa-info.hpp
+++ b/src/tlv/lsa-info.hpp
@@ -28,6 +28,8 @@
 #include <ndn-cxx/encoding/tlv.hpp>
 #include <ndn-cxx/name.hpp>
 
+#include "lsa.hpp"
+
 namespace nlsr {
 namespace tlv  {
 
@@ -134,6 +136,9 @@
 std::ostream&
 operator<<(std::ostream& os, const LsaInfo& lsaInfo);
 
+std::shared_ptr<LsaInfo>
+makeLsaInfo(const Lsa& lsa);
+
 } // namespace tlv
 } // namespace nlsr