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
diff --git a/tests/publisher/publisher-fixture.hpp b/tests/publisher/publisher-fixture.hpp
new file mode 100644
index 0000000..07da594
--- /dev/null
+++ b/tests/publisher/publisher-fixture.hpp
@@ -0,0 +1,144 @@
+/* -*- 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 "nlsr.hpp"
+
+#include "../boost-test.hpp"
+#include "../test-common.hpp"
+
+#include <ndn-cxx/util/dummy-client-face.hpp>
+
+namespace nlsr {
+namespace test {
+
+class PublisherFixture : public BaseFixture
+{
+public:
+ PublisherFixture()
+ : face(ndn::util::makeDummyClientFace())
+ , nlsr(g_ioService, g_scheduler, ndn::ref(*face))
+ , lsdb(nlsr, g_scheduler, nlsr.getSyncLogicHandler())
+ {
+ }
+
+ void
+ addAdjacency(AdjLsa& lsa, const std::string& name, const std::string& faceUri, double cost)
+ {
+ Adjacent adjacency(name, faceUri, cost, Adjacent::STATUS_ACTIVE, 0, 0);
+ lsa.addAdjacent(adjacency);
+ }
+
+ void
+ checkTlvLsaInfo(const tlv::LsaInfo& info, Lsa& lsa)
+ {
+ BOOST_CHECK_EQUAL(info.getOriginRouter(), lsa.getOrigRouter());
+ BOOST_CHECK_EQUAL(info.getSequenceNumber(), lsa.getLsSeqNo());
+ BOOST_CHECK_LE(info.getExpirationPeriod(), ndn::time::milliseconds(0));
+ }
+
+ void
+ checkTlvAdjLsa(const ndn::Block& block, AdjLsa& lsa)
+ {
+ BOOST_CHECK_EQUAL(block.type(), ndn::tlv::nlsr::AdjacencyLsa);
+
+ tlv::AdjacencyLsa tlvLsa;
+ BOOST_REQUIRE_NO_THROW(tlvLsa.wireDecode(block));
+
+ checkTlvAdjLsa(tlvLsa, lsa);
+ }
+
+ void
+ checkTlvAdjLsa(const tlv::AdjacencyLsa& tlvLsa, AdjLsa& lsa)
+ {
+ checkTlvLsaInfo(tlvLsa.getLsaInfo(), lsa);
+
+ std::list<tlv::Adjacency>::const_iterator it = tlvLsa.getAdjacencies().begin();
+
+ for (const Adjacent& adjacency : lsa.getAdl().getAdjList()) {
+ BOOST_CHECK_EQUAL(it->getName(), adjacency.getName());
+ BOOST_CHECK_EQUAL(it->getUri(), adjacency.getConnectingFaceUri());
+ BOOST_CHECK_EQUAL(it->getCost(), adjacency.getLinkCost());
+ ++it;
+ }
+ }
+
+ CoordinateLsa
+ createCoordinateLsa(const std::string& origin, double radius, double angle)
+ {
+ CoordinateLsa lsa(origin, CoordinateLsa::TYPE_STRING, 1, ndn::time::system_clock::now(),
+ radius, angle);
+
+ return std::move(lsa);
+ }
+
+ void
+ checkTlvCoordinateLsa(const ndn::Block& block, CoordinateLsa& lsa)
+ {
+ BOOST_CHECK_EQUAL(block.type(), ndn::tlv::nlsr::CoordinateLsa);
+
+ tlv::CoordinateLsa tlvLsa;
+ BOOST_REQUIRE_NO_THROW(tlvLsa.wireDecode(block));
+
+ checkTlvCoordinateLsa(tlvLsa, lsa);
+ }
+
+ void
+ checkTlvCoordinateLsa(const tlv::CoordinateLsa& tlvLsa, CoordinateLsa& lsa)
+ {
+ checkTlvLsaInfo(tlvLsa.getLsaInfo(), lsa);
+
+ BOOST_CHECK_EQUAL(tlvLsa.getHyperbolicRadius(), lsa.getCorRadius());
+ BOOST_CHECK_EQUAL(tlvLsa.getHyperbolicAngle(), lsa.getCorTheta());
+ }
+
+ void
+ checkTlvNameLsa(const ndn::Block& block, NameLsa& lsa)
+ {
+ BOOST_CHECK_EQUAL(block.type(), ndn::tlv::nlsr::NameLsa);
+
+ tlv::NameLsa tlvLsa;
+ BOOST_REQUIRE_NO_THROW(tlvLsa.wireDecode(block));
+
+ checkTlvNameLsa(tlvLsa, lsa);
+ }
+
+ void
+ checkTlvNameLsa(const tlv::NameLsa& tlvLsa, NameLsa& lsa)
+ {
+ checkTlvLsaInfo(tlvLsa.getLsaInfo(), lsa);
+
+ std::list<ndn::Name>::const_iterator it = tlvLsa.getNames().begin();
+
+ for (const ndn::Name& name : lsa.getNpl().getNameList()) {
+ BOOST_CHECK_EQUAL(*it, name);
+ ++it;
+ }
+ }
+
+public:
+ shared_ptr<ndn::util::DummyClientFace> face;
+ Nlsr nlsr;
+ Lsdb lsdb;
+ ndn::KeyChain keyChain;
+};
+
+} // namespace test
+} // namespace nlsr
diff --git a/tests/publisher/test-lsa-publisher.cpp b/tests/publisher/test-lsa-publisher.cpp
new file mode 100644
index 0000000..aa7922c
--- /dev/null
+++ b/tests/publisher/test-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 "publisher/lsa-publisher.hpp"
+#include "tlv/adjacency.hpp"
+#include "tlv/adjacency-lsa.hpp"
+#include "tlv/tlv-nlsr.hpp"
+
+#include "publisher-fixture.hpp"
+#include "../boost-test.hpp"
+
+namespace nlsr {
+namespace test {
+
+BOOST_FIXTURE_TEST_SUITE(PublisherTestLsaPublisher, PublisherFixture)
+
+BOOST_AUTO_TEST_CASE(AdjacencyLsaPublisherBasic)
+{
+ // Adjacency LSA for RouterA
+ AdjLsa routerALsa;
+ routerALsa.setOrigRouter("/RouterA");
+ addAdjacency(routerALsa, "/RouterA/adjacency1", "udp://face-1", 10);
+ lsdb.installAdjLsa(routerALsa);
+
+ // Adjacency LSA for RouterB
+ AdjLsa routerBLsa;
+ routerBLsa.setOrigRouter("/RouterB");
+ routerBLsa.setLsSeqNo(5);
+ addAdjacency(routerBLsa, "/RouterB/adjacency1", "udp://face-1", 10);
+ addAdjacency(routerBLsa, "/RouterB/adjacency2", "udp://face-2", 20);
+ addAdjacency(routerBLsa, "/RouterB/adjacency3", "udp://face-3", 30);
+ lsdb.installAdjLsa(routerBLsa);
+
+ AdjacencyLsaPublisher publisher(lsdb, *face, "/RouterA", keyChain);
+
+ publisher.publish();
+ face->processEvents(ndn::time::milliseconds(1));
+
+ BOOST_REQUIRE_EQUAL(face->sentDatas.size(), 1);
+ ndn::Block parser = face->sentDatas[0].getContent();
+ parser.parse();
+
+ // Check RouterB LSA
+ ndn::Block::element_const_iterator it = parser.elements_begin();
+ checkTlvAdjLsa(*it, routerBLsa);
+
+ // Check RouterA LSA
+ it++;
+ checkTlvAdjLsa(*it, routerALsa);
+}
+
+BOOST_AUTO_TEST_CASE(CoordinateLsaBasic)
+{
+ CoordinateLsa routerALsa = createCoordinateLsa("/RouterA", 10.0, 20.0);
+ lsdb.installCoordinateLsa(routerALsa);
+
+ CoordinateLsa routerBLsa = createCoordinateLsa("/RouterB", 123.45, 543.21);
+ lsdb.installCoordinateLsa(routerBLsa);
+
+ CoordinateLsa routerCLsa = createCoordinateLsa("/RouterC", 0.01, 0.02);
+ lsdb.installCoordinateLsa(routerCLsa);
+
+ CoordinateLsaPublisher publisher(lsdb, *face, "/RouterA", keyChain);
+
+ publisher.publish();
+ face->processEvents(ndn::time::milliseconds(1));
+
+ BOOST_REQUIRE_EQUAL(face->sentDatas.size(), 1);
+ ndn::Block parser = face->sentDatas[0].getContent();
+ parser.parse();
+
+ // Check RouterC LSA
+ ndn::Block::element_const_iterator it = parser.elements_begin();
+ checkTlvCoordinateLsa(*it, routerCLsa);
+
+ // Check RouterB LSA
+ ++it;
+ checkTlvCoordinateLsa(*it, routerBLsa);
+
+ // Check RouterA LSA
+ ++it;
+ checkTlvCoordinateLsa(*it, routerALsa);
+}
+
+BOOST_AUTO_TEST_CASE(NameLsaBasic)
+{
+ // Name LSA for RouterA
+ NameLsa routerALsa;
+ routerALsa.setOrigRouter("/RouterA");
+ routerALsa.addName("/RouterA/name1");
+ lsdb.installNameLsa(routerALsa);
+
+ // Name LSA for RouterB
+ NameLsa routerBLsa;
+ routerBLsa.setOrigRouter("/RouterB");
+ routerBLsa.addName("/RouterB/name1");
+ routerBLsa.addName("/RouterB/name2");
+ routerBLsa.addName("/RouterB/name3");
+ lsdb.installNameLsa(routerBLsa);
+
+ NameLsaPublisher publisher(lsdb, *face, "/RouterA", keyChain);
+
+ publisher.publish();
+ face->processEvents(ndn::time::milliseconds(1));
+
+ BOOST_REQUIRE_EQUAL(face->sentDatas.size(), 1);
+ ndn::Block parser = face->sentDatas[0].getContent();
+ parser.parse();
+
+ // Check RouterB LSA
+ ndn::Block::element_const_iterator it = parser.elements_begin();
+ checkTlvNameLsa(*it, routerBLsa);
+
+ // Check RouterA LSA
+ it++;
+ checkTlvNameLsa(*it, routerALsa);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace test
+} // namespace nlsr
diff --git a/tests/publisher/test-lsdb-dataset-interest-handler.cpp b/tests/publisher/test-lsdb-dataset-interest-handler.cpp
new file mode 100644
index 0000000..22b2819
--- /dev/null
+++ b/tests/publisher/test-lsdb-dataset-interest-handler.cpp
@@ -0,0 +1,145 @@
+/* -*- 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 "publisher/lsdb-dataset-interest-handler.hpp"
+#include "tlv/tlv-nlsr.hpp"
+
+#include "publisher-fixture.hpp"
+#include "../boost-test.hpp"
+
+#include <ndn-cxx/management/nfd-control-response.hpp>
+
+namespace nlsr {
+namespace test {
+
+void
+processDatasetInterest(shared_ptr<ndn::util::DummyClientFace> face,
+ std::function<bool(const ndn::Block&)> isSameType)
+{
+ face->processEvents(ndn::time::milliseconds(1));
+
+ BOOST_REQUIRE_EQUAL(face->sentDatas.size(), 1);
+ ndn::Block parser(face->sentDatas[0].getContent());
+ parser.parse();
+
+ ndn::Block::element_const_iterator it = parser.elements_begin();
+ BOOST_CHECK_EQUAL(isSameType(*it), true);
+ ++it;
+
+ BOOST_CHECK(it == parser.elements_end());
+
+ face->sentDatas.clear();
+}
+
+void
+checkErrorResponse(shared_ptr<ndn::util::DummyClientFace> face, uint64_t expectedCode)
+{
+ BOOST_REQUIRE_EQUAL(face->sentDatas.size(), 1);
+
+ ndn::nfd::ControlResponse response(face->sentDatas[0].getContent().blockFromValue());
+ BOOST_CHECK_EQUAL(response.getCode(), expectedCode);
+
+ face->sentDatas.clear();
+}
+
+BOOST_FIXTURE_TEST_SUITE(PublisherTestLsdbDatasetInterestHandler, PublisherFixture)
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+ // Install adjacency LSA
+ AdjLsa adjLsa;
+ adjLsa.setOrigRouter("/RouterA");
+ addAdjacency(adjLsa, "/RouterA/adjacency1", "udp://face-1", 10);
+ lsdb.installAdjLsa(adjLsa);
+
+ // Install coordinate LSA
+ CoordinateLsa coordinateLsa = createCoordinateLsa("/RouterA", 10.0, 20.0);
+ lsdb.installCoordinateLsa(coordinateLsa);
+
+ // Install Name LSA
+ NameLsa nameLsa;
+ nameLsa.setOrigRouter("/RouterA");
+ nameLsa.addName("/RouterA/name1");
+ lsdb.installNameLsa(nameLsa);
+
+ ndn::Name thisRouter("/This/Router");
+ LsdbDatasetInterestHandler publisher(lsdb, *face, thisRouter, keyChain);
+
+ face->processEvents(ndn::time::milliseconds(10));
+
+ ndn::Name commandPrefix(thisRouter);
+ commandPrefix.append("lsdb");
+
+ // Request adjacency LSAs
+ face->receive(ndn::Interest(ndn::Name(commandPrefix).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")));
+ 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")));
+ 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")));
+ processDatasetInterest(face,
+ [] (const ndn::Block& block) { return block.type() == ndn::tlv::nlsr::LsdbStatus; });
+}
+
+BOOST_AUTO_TEST_CASE(InvalidCommand)
+{
+ ndn::Name thisRouter("/This/Router");
+ LsdbDatasetInterestHandler publisher(lsdb, *face, thisRouter, keyChain);
+
+ face->processEvents(ndn::time::milliseconds(10));
+
+ ndn::Name commandPrefix(thisRouter);
+ commandPrefix.append("lsdb");
+
+ // Unsupported command
+ face->receive(ndn::Interest(ndn::Name(commandPrefix).append("unsupported")));
+ face->processEvents(ndn::time::milliseconds(1));
+
+ checkErrorResponse(face, 501);
+
+ // Long malformed command
+ face->receive(ndn::Interest(ndn::Name(commandPrefix).append("extra").append("malformed")));
+ face->processEvents(ndn::time::milliseconds(1));
+
+ checkErrorResponse(face, 400);
+
+ // Short malformed command
+ face->receive(ndn::Interest(ndn::Name(thisRouter).append("malformed")));
+ face->processEvents(ndn::time::milliseconds(1));
+
+ BOOST_CHECK_EQUAL(face->sentDatas.size(), 0);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace test
+} // namespace nlsr
diff --git a/tests/publisher/test-lsdb-status-publisher.cpp b/tests/publisher/test-lsdb-status-publisher.cpp
new file mode 100644
index 0000000..50d48da
--- /dev/null
+++ b/tests/publisher/test-lsdb-status-publisher.cpp
@@ -0,0 +1,133 @@
+/* -*- 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 "publisher/lsdb-status-publisher.hpp"
+#include "tlv/lsdb-status.hpp"
+#include "tlv/tlv-nlsr.hpp"
+
+#include "publisher-fixture.hpp"
+#include "../boost-test.hpp"
+
+namespace nlsr {
+namespace test {
+
+BOOST_FIXTURE_TEST_SUITE(PublisherTestLsdbStatusPublisher, PublisherFixture)
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+ // Install adjacency LSAs
+ // Adjacency LSA for RouterA
+ AdjLsa routerAAdjLsa;
+ routerAAdjLsa.setOrigRouter("/RouterA");
+ addAdjacency(routerAAdjLsa, "/RouterA/adjacency1", "udp://face-1", 10);
+ lsdb.installAdjLsa(routerAAdjLsa);
+
+ // Adjacency LSA for RouterB
+ AdjLsa routerBAdjLsa;
+ routerBAdjLsa.setOrigRouter("/RouterB");
+ routerBAdjLsa.setLsSeqNo(5);
+ addAdjacency(routerBAdjLsa, "/RouterB/adjacency1", "udp://face-1", 10);
+ addAdjacency(routerBAdjLsa, "/RouterB/adjacency2", "udp://face-2", 20);
+ addAdjacency(routerBAdjLsa, "/RouterB/adjacency3", "udp://face-3", 30);
+ lsdb.installAdjLsa(routerBAdjLsa);
+
+ // Install coordinate LSAs
+ CoordinateLsa routerACorLsa = createCoordinateLsa("/RouterA", 10.0, 20.0);
+ lsdb.installCoordinateLsa(routerACorLsa);
+
+ CoordinateLsa routerBCorLsa = createCoordinateLsa("/RouterB", 123.45, 543.21);
+ lsdb.installCoordinateLsa(routerBCorLsa);
+
+ CoordinateLsa routerCCorLsa = createCoordinateLsa("/RouterC", 0.01, 0.02);
+ lsdb.installCoordinateLsa(routerCCorLsa);
+
+ // Install Name LSAs
+ // Name LSA for RouterA
+ NameLsa routerANameLsa;
+ routerANameLsa.setOrigRouter("/RouterA");
+ routerANameLsa.addName("/RouterA/name1");
+ lsdb.installNameLsa(routerANameLsa);
+
+ // Name LSA for RouterB
+ NameLsa routerBNameLsa;
+ routerBNameLsa.setOrigRouter("/RouterB");
+ routerBNameLsa.addName("/RouterB/name1");
+ routerBNameLsa.addName("/RouterB/name2");
+ routerBNameLsa.addName("/RouterB/name3");
+ 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);
+
+ LsdbStatusPublisher publisher(lsdb, *face, thisRouter, keyChain,
+ adjacencyLsaPublisher,
+ coordinateLsaPublisher,
+ nameLsaPublisher);
+
+ publisher.publish();
+ face->processEvents(ndn::time::milliseconds(1));
+
+ BOOST_REQUIRE_EQUAL(face->sentDatas.size(), 1);
+
+ ndn::Block parser = face->sentDatas[0].getContent();
+ parser.parse();
+
+ ndn::Block::element_const_iterator it = parser.elements_begin();
+
+ BOOST_CHECK_EQUAL(it->type(), ndn::tlv::nlsr::LsdbStatus);
+
+ tlv::LsdbStatus lsdbStatusTlv;
+ BOOST_REQUIRE_NO_THROW(lsdbStatusTlv.wireDecode(*it));
+
+ BOOST_CHECK_EQUAL(lsdbStatusTlv.hasAdjacencyLsas(), true);
+
+ // Check adjacency LSAs
+ std::list<tlv::AdjacencyLsa>::const_iterator adjLsaIt = lsdbStatusTlv.getAdjacencyLsas().begin();
+ checkTlvAdjLsa(*adjLsaIt, routerAAdjLsa);
+
+ ++adjLsaIt;
+ checkTlvAdjLsa(*adjLsaIt, routerBAdjLsa);
+
+ // Check coordinate LSAs
+ std::list<tlv::CoordinateLsa>::const_iterator corLsaIt =
+ lsdbStatusTlv.getCoordinateLsas().begin();
+ checkTlvCoordinateLsa(*corLsaIt, routerACorLsa);
+
+ ++corLsaIt;
+ checkTlvCoordinateLsa(*corLsaIt, routerBCorLsa);
+
+ ++corLsaIt;
+ checkTlvCoordinateLsa(*corLsaIt, routerCCorLsa);
+
+ // Check Name LSAs
+ std::list<tlv::NameLsa>::const_iterator nameLsaIt = lsdbStatusTlv.getNameLsas().begin();
+ checkTlvNameLsa(*nameLsaIt, routerANameLsa);
+
+ ++nameLsaIt;
+ checkTlvNameLsa(*nameLsaIt, routerBNameLsa);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace test
+} // namespace nlsr
diff --git a/tests/publisher/test-segment-publisher.cpp b/tests/publisher/test-segment-publisher.cpp
new file mode 100644
index 0000000..8cc8dde
--- /dev/null
+++ b/tests/publisher/test-segment-publisher.cpp
@@ -0,0 +1,170 @@
+/* -*- 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/>.
+ */
+
+#include "publisher/segment-publisher.hpp"
+
+#include "../boost-test.hpp"
+
+#include <ndn-cxx/encoding/tlv.hpp>
+#include <ndn-cxx/util/dummy-client-face.hpp>
+
+#include <boost/mpl/int.hpp>
+#include <boost/mpl/vector.hpp>
+
+namespace nlsr {
+namespace tests {
+
+template<int64_t N=10000>
+class TestSegmentPublisher : public SegmentPublisher<ndn::util::DummyClientFace>
+{
+public:
+ TestSegmentPublisher(ndn::util::DummyClientFace& face,
+ const ndn::Name& prefix,
+ ndn::KeyChain& keyChain,
+ const ndn::time::milliseconds freshnessPeriod)
+ : SegmentPublisher(face, prefix, keyChain, freshnessPeriod)
+ , m_totalPayloadLength(0)
+ {
+
+ }
+
+ virtual
+ ~TestSegmentPublisher()
+ {
+ }
+
+ uint16_t
+ getLimit() const
+ {
+ return N;
+ }
+
+ size_t
+ getTotalPayloadLength() const
+ {
+ return m_totalPayloadLength;
+ }
+
+protected:
+
+ virtual size_t
+ generate(ndn::EncodingBuffer& outBuffer)
+ {
+ size_t totalLength = 0;
+ for (int64_t i = 0; i < N; i++)
+ {
+ totalLength += ndn::prependNonNegativeIntegerBlock(outBuffer, ndn::tlv::Content, i);
+ }
+ m_totalPayloadLength += totalLength;
+ return totalLength;
+ }
+
+protected:
+ size_t m_totalPayloadLength;
+};
+
+template<int64_t N>
+class SegmentPublisherFixture
+{
+public:
+ SegmentPublisherFixture()
+ : m_face(ndn::util::makeDummyClientFace())
+ , m_expectedFreshnessPeriod(ndn::time::milliseconds(111))
+ , m_publisher(*m_face, "/localhost/nfd/SegmentPublisherFixture",
+ m_keyChain, m_expectedFreshnessPeriod)
+ {
+ }
+
+ void
+ validate(const ndn::Data& data)
+ {
+ BOOST_CHECK_EQUAL(data.getFreshnessPeriod(), m_expectedFreshnessPeriod);
+
+ ndn::Block payload = data.getContent();
+
+ m_buffer.appendByteArray(payload.value(), payload.value_size());
+
+ // uint64_t segmentNo = data.getName()[-1].toSegment();
+ if (data.getFinalBlockId() != data.getName()[-1])
+ {
+ return;
+ }
+
+ // wrap data in a single Content TLV for easy parsing
+ m_buffer.prependVarNumber(m_buffer.size());
+ m_buffer.prependVarNumber(ndn::tlv::Content);
+
+ BOOST_TEST_CHECKPOINT("creating parser");
+ ndn::Block parser(m_buffer.buf(), m_buffer.size());
+ BOOST_TEST_CHECKPOINT("parsing aggregated response");
+ parser.parse();
+
+ BOOST_REQUIRE_EQUAL(parser.elements_size(), m_publisher.getLimit());
+
+ uint64_t expectedNo = m_publisher.getLimit() - 1;
+ for (ndn::Block::element_const_iterator i = parser.elements_begin();
+ i != parser.elements_end();
+ ++i)
+ {
+ uint64_t number = readNonNegativeInteger(*i);
+ BOOST_REQUIRE_EQUAL(number, expectedNo);
+ --expectedNo;
+ }
+ }
+
+protected:
+ ndn::shared_ptr<ndn::util::DummyClientFace> m_face;
+ const ndn::time::milliseconds m_expectedFreshnessPeriod;
+ TestSegmentPublisher<N> m_publisher;
+ ndn::EncodingBuffer m_buffer;
+ ndn::KeyChain m_keyChain;
+};
+
+using boost::mpl::int_;
+typedef boost::mpl::vector<int_<10000>, int_<100>, int_<10>, int_<0> > DatasetSizes;
+
+BOOST_AUTO_TEST_SUITE(PublisherTestSegmentPublisher)
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(Generate, T, DatasetSizes, SegmentPublisherFixture<T::value>)
+{
+ this->m_publisher.publish();
+ this->m_face->processEvents();
+
+ size_t nSegments = this->m_publisher.getTotalPayloadLength() /
+ this->m_publisher.getMaxSegmentSize();
+ if (this->m_publisher.getTotalPayloadLength() % this->m_publisher.getMaxSegmentSize() != 0 ||
+ nSegments == 0)
+ ++nSegments;
+
+ BOOST_CHECK_EQUAL(this->m_face->sentDatas.size(), nSegments);
+ for (const ndn::Data& data : this->m_face->sentDatas) {
+ this->validate(data);
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace tests
+} // namespace nlsr
diff --git a/tests/tlv/test-lsa-info.cpp b/tests/tlv/test-lsa-info.cpp
index dff4458..0e6d906 100644
--- a/tests/tlv/test-lsa-info.cpp
+++ b/tests/tlv/test-lsa-info.cpp
@@ -123,6 +123,19 @@
"ExpirationPeriod: 10000 milliseconds)");
}
+BOOST_AUTO_TEST_CASE(LsaInfoMake)
+{
+ Lsa lsa;
+ lsa.setOrigRouter("/test/lsa/info/tlv");
+ lsa.setLsSeqNo(128);
+ lsa.setExpirationTimePoint(ndn::time::system_clock::now());
+
+ std::shared_ptr<LsaInfo> lsaInfo = makeLsaInfo(lsa);
+ BOOST_CHECK_EQUAL(lsaInfo->getOriginRouter(), lsa.getOrigRouter());
+ BOOST_CHECK_EQUAL(lsaInfo->getSequenceNumber(), lsa.getLsSeqNo());
+ BOOST_CHECK_LE(lsaInfo->getExpirationPeriod(), ndn::time::milliseconds(0));
+}
+
BOOST_AUTO_TEST_SUITE_END()
} // namespace test
diff --git a/tests/wscript b/tests/wscript
index 4ef346f..9d8973b 100644
--- a/tests/wscript
+++ b/tests/wscript
@@ -28,7 +28,7 @@
target='unit-tests-main',
name='unit-tests-main',
features='cxx',
- source=bld.path.ant_glob(['*.cpp', 'utility/*.cpp', 'tlv/*.cpp']),
+ source=bld.path.ant_glob(['*.cpp', 'utility/*.cpp', 'tlv/*.cpp', 'publisher/*.cpp']),
use='nlsr-objects',
)