lsdb: Segment LSAs larger than max segment size
refs: #2965
Change-Id: I5dd091b663db2cc5e2d925144e57ee55a486b3cd
diff --git a/nlsr.conf b/nlsr.conf
index a370f34..d32a463 100644
--- a/nlsr.conf
+++ b/nlsr.conf
@@ -187,7 +187,8 @@
k-regex ^([^<KEY><NLSR>]*)<NLSR><KEY><ksk-.*><ID-CERT>$
k-expand \\1
h-relation equal
- p-regex ^([^<NLSR><LSA>]*)<NLSR><LSA>(<>*)<><><>$
+ ; the last four components in the prefix should be <lsaType><seqNo><version><segmentNo>
+ p-regex ^([^<NLSR><LSA>]*)<NLSR><LSA>(<>*)<><><><>$
p-expand \\1\\2
}
}
diff --git a/src/lsdb.cpp b/src/lsdb.cpp
index d4b7193..8d7f1ec 100644
--- a/src/lsdb.cpp
+++ b/src/lsdb.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014-2015, The University of Memphis,
+ * Copyright (c) 2014-2016, The University of Memphis,
* Regents of the University of California,
* Arizona Board of Regents.
*
@@ -19,24 +19,114 @@
* NLSR, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
**/
-#include <string>
-#include <utility>
-
#include "lsdb.hpp"
-#include "nlsr.hpp"
-#include "conf-parameter.hpp"
-#include "utility/name-helper.hpp"
+
#include "logger.hpp"
+#include "nlsr.hpp"
+#include "publisher/segment-publisher.hpp"
+#include "utility/name-helper.hpp"
+
+#include <ndn-cxx/security/signing-helpers.hpp>
+#include <ndn-cxx/util/segment-fetcher.hpp>
+
+#include <string>
namespace nlsr {
INIT_LOGGER("Lsdb");
+class LsaContentPublisher : public SegmentPublisher<ndn::Face>
+{
+public:
+ LsaContentPublisher(ndn::Face& face,
+ ndn::KeyChain& keyChain,
+ const ndn::time::milliseconds& freshnessPeriod,
+ const std::string& content)
+ : SegmentPublisher(face, keyChain, freshnessPeriod)
+ , m_content(content)
+ {
+ }
+
+ virtual size_t
+ generate(ndn::EncodingBuffer& outBuffer) {
+ size_t totalLength = 0;
+ totalLength += outBuffer.prependByteArray(reinterpret_cast<const uint8_t*>(m_content.c_str()),
+ m_content.size());
+ return totalLength;
+ }
+
+private:
+ const std::string m_content;
+};
+
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();
-using namespace std;
+Lsdb::Lsdb(Nlsr& nlsr, ndn::Scheduler& scheduler, SyncLogicHandler& sync)
+ : m_nlsr(nlsr)
+ , m_scheduler(scheduler)
+ , m_sync(sync)
+ , m_lsaRefreshTime(0)
+ , m_adjLsaBuildInterval(ADJ_LSA_BUILD_INTERVAL_DEFAULT)
+{
+}
+
+void
+Lsdb::onFetchLsaError(uint32_t errorCode,
+ const std::string& msg,
+ ndn::Name& interestName,
+ uint32_t retransmitNo,
+ const ndn::time::steady_clock::TimePoint& deadline,
+ ndn::Name lsaName,
+ uint64_t seqNo)
+{
+ _LOG_DEBUG("Failed to fetch LSA: " << lsaName << ", Error code: " << errorCode
+ << ", Message: " << msg);
+
+ if (ndn::time::steady_clock::now() < deadline) {
+ SequenceNumberMap::const_iterator it = m_highestSeqNo.find(lsaName);
+
+ if (it != m_highestSeqNo.end() && it->second == seqNo) {
+ // If the SegmentFetcher failed due to an Interest timeout, it is safe to re-express
+ // immediately since at the least the LSA Interest lifetime has elapsed.
+ // Otherwise, it is necessary to delay the Interest re-expression to prevent
+ // the potential for constant Interest flooding.
+ ndn::time::seconds delay = m_nlsr.getConfParameter().getLsaInterestLifetime();
+
+ if (errorCode == ndn::util::SegmentFetcher::ErrorCode::INTEREST_TIMEOUT) {
+ delay = ndn::time::seconds(0);
+ }
+
+ m_scheduler.scheduleEvent(delay, std::bind(&Lsdb::expressInterest, this,
+ interestName, retransmitNo + 1, deadline));
+ }
+ }
+}
+
+void
+Lsdb::afterFetchLsa(const ndn::ConstBufferPtr& bufferPtr, ndn::Name& interestName)
+{
+ shared_ptr<ndn::Data> data = make_shared<ndn::Data>(ndn::Name(interestName));
+ data->setContent(bufferPtr);
+
+ _LOG_DEBUG("Received data for LSA(name): " << data->getName());
+
+ ndn::Name lsaName = interestName.getSubName(0, interestName.size()-1);
+ uint64_t seqNo = interestName[-1].toNumber();
+
+ if (m_highestSeqNo.find(lsaName) == m_highestSeqNo.end()) {
+ m_highestSeqNo[lsaName] = seqNo;
+ }
+ else if (seqNo > m_highestSeqNo[lsaName]) {
+ m_highestSeqNo[lsaName] = seqNo;
+ }
+ else if (seqNo < m_highestSeqNo[lsaName]) {
+ return;
+ }
+
+ onContentValidated(data);
+}
void
Lsdb::cancelScheduleLsaExpiringEvent(ndn::EventId eid)
@@ -50,7 +140,6 @@
return nlsa1.getKey() == key;
}
-
bool
Lsdb::buildAndInstallOwnNameLsa()
{
@@ -640,7 +729,7 @@
}
void
-Lsdb::setThisRouterPrefix(string trp)
+Lsdb::setThisRouterPrefix(std::string trp)
{
m_thisRouterPrefix = trp;
}
@@ -748,7 +837,6 @@
}
}
-
void
Lsdb::expressInterest(const ndn::Name& interestName, uint32_t timeoutCount,
steady_clock::TimePoint deadline)
@@ -758,8 +846,6 @@
}
ndn::Name lsaName = interestName.getSubName(0, interestName.size()-1);
-
- ndn::Interest interest(interestName);
uint64_t seqNo = interestName[-1].toNumber();
if (m_highestSeqNo.find(lsaName) == m_highestSeqNo.end()) {
@@ -772,14 +858,15 @@
return;
}
+ ndn::Interest interest(interestName);
interest.setInterestLifetime(m_nlsr.getConfParameter().getLsaInterestLifetime());
- _LOG_DEBUG("Expressing Interest for LSA: " << interestName << " Seq number: " << seqNo);
- m_nlsr.getNlsrFace().expressInterest(interest,
- ndn::bind(&Lsdb::onContent,
- this, _2, deadline, lsaName, seqNo),
- ndn::bind(&Lsdb::processInterestTimedOut,
- this, _1, timeoutCount, deadline, lsaName, seqNo));
+ _LOG_DEBUG("Fetching Data for LSA: " << interestName << " Seq number: " << seqNo);
+ ndn::util::SegmentFetcher::fetch(m_nlsr.getNlsrFace(), interest,
+ m_nlsr.getValidator(),
+ ndn::bind(&Lsdb::afterFetchLsa, this, _1, interestName),
+ ndn::bind(&Lsdb::onFetchLsaError, this, _1, _2, interestName,
+ timeoutCount, deadline, lsaName, seqNo));
}
void
@@ -788,7 +875,7 @@
const ndn::Name& interestName(interest.getName());
_LOG_DEBUG("Interest received for LSA: " << interestName);
- string chkString("LSA");
+ std::string chkString("LSA");
int32_t lsaPosition = util::getNameComponentPosition(interest.getName(), chkString);
if (lsaPosition >= 0) {
@@ -820,16 +907,12 @@
void
Lsdb::putLsaData(const ndn::Interest& interest, const std::string& content)
{
- ndn::shared_ptr<ndn::Data> data = ndn::make_shared<ndn::Data>();
- data->setName(ndn::Name(interest.getName()).appendVersion());
- data->setFreshnessPeriod(m_lsaRefreshTime);
- data->setContent(reinterpret_cast<const uint8_t*>(content.c_str()), content.size());
- m_nlsr.getKeyChain().sign(*data, m_nlsr.getDefaultCertName());
- ndn::SignatureSha256WithRsa signature(data->getSignature());
- ndn::Name signingCertName = signature.getKeyLocator().getName();
- _LOG_DEBUG("Sending data for LSA(name): " << interest.getName());
- _LOG_DEBUG("Data signed with: " << signingCertName);
- m_nlsr.getNlsrFace().put(*data);
+ LsaContentPublisher publisher(m_nlsr.getNlsrFace(),
+ m_nlsr.getKeyChain(),
+ m_lsaRefreshTime,
+ content);
+ publisher.publish(interest.getName(),
+ ndn::security::signingByCertificate(m_nlsr.getDefaultCertName()));
}
void
@@ -875,58 +958,23 @@
}
void
-Lsdb::onContent(const ndn::Data& data,
- const steady_clock::TimePoint& deadline, ndn::Name lsaName,
- uint64_t seqNo)
-{
- _LOG_DEBUG("Received data for LSA(name): " << data.getName());
- if (data.getSignature().hasKeyLocator()) {
- if (data.getSignature().getKeyLocator().getType() == ndn::KeyLocator::KeyLocator_Name) {
- _LOG_DEBUG("Data signed with: " << data.getSignature().getKeyLocator().getName());
- }
- }
- m_nlsr.getValidator().validate(data,
- ndn::bind(&Lsdb::onContentValidated, this, _1),
- ndn::bind(&Lsdb::onContentValidationFailed, this, _1, _2,
- deadline, lsaName, seqNo));
-
-}
-
-void
-Lsdb::retryContentValidation(const ndn::shared_ptr<const ndn::Data>& data,
- const steady_clock::TimePoint& deadline, ndn::Name lsaName,
- uint64_t seqNo)
-{
- _LOG_DEBUG("Retrying validation of LSA(name): " << data->getName());
- if (data->getSignature().hasKeyLocator()) {
- if (data->getSignature().getKeyLocator().getType() == ndn::KeyLocator::KeyLocator_Name) {
- _LOG_DEBUG("Data signed with: " << data->getSignature().getKeyLocator().getName());
- }
- }
- m_nlsr.getValidator().validate(*data,
- ndn::bind(&Lsdb::onContentValidated, this, _1),
- ndn::bind(&Lsdb::onContentValidationFailed, this, _1, _2,
- deadline, lsaName, seqNo));
-}
-
-void
Lsdb::onContentValidated(const ndn::shared_ptr<const ndn::Data>& data)
{
const ndn::Name& dataName = data->getName();
_LOG_DEBUG("Data validation successful for LSA: " << dataName);
- string chkString("LSA");
+ std::string chkString("LSA");
int32_t lsaPosition = util::getNameComponentPosition(dataName, chkString);
if (lsaPosition >= 0) {
ndn::Name originRouter = m_nlsr.getConfParameter().getNetwork();
- originRouter.append(dataName.getSubName(lsaPosition + 1, dataName.size() - lsaPosition - 4));
+ originRouter.append(dataName.getSubName(lsaPosition + 1, dataName.size() - lsaPosition - 3));
- uint64_t seqNo = dataName[-2].toNumber();
- string dataContent(reinterpret_cast<const char*>(data->getContent().value()));
+ uint64_t seqNo = dataName[-1].toNumber();
+ std::string dataContent(reinterpret_cast<const char*>(data->getContent().value()));
- std::string interestedLsType = dataName[-3].toUri();
+ std::string interestedLsType = dataName[-2].toUri();
if (interestedLsType == NameLsa::TYPE_STRING) {
processContentNameLsa(originRouter.append(interestedLsType), seqNo, dataContent);
@@ -944,32 +992,6 @@
}
void
-Lsdb::onContentValidationFailed(const ndn::shared_ptr<const ndn::Data>& data,
- const std::string& msg,
- const steady_clock::TimePoint& deadline, ndn::Name lsaName,
- uint64_t seqNo)
-{
- _LOG_DEBUG("Validation Error: " << msg);
-
- // Delay re-validation by LSA Interest Lifetime. When error callback will have an error
- // code, re-validation should be done only when some keys from certification chain failed
- // to be fetched. After that change, delaying will no longer be necessary.
-
- // Stop retrying if delayed re-validation will be scheduled pass the deadline
- if (steady_clock::now() + m_nlsr.getConfParameter().getLsaInterestLifetime() < deadline) {
-
- SequenceNumberMap::const_iterator it = m_highestSeqNo.find(lsaName);
-
- if (it != m_highestSeqNo.end() && it->second == seqNo) {
- _LOG_DEBUG("Scheduling revalidation attempt");
- m_scheduler.scheduleEvent(m_nlsr.getConfParameter().getLsaInterestLifetime(),
- ndn::bind(&Lsdb::retryContentValidation, this, data,
- deadline, lsaName, seqNo));
- }
- }
-}
-
-void
Lsdb::processContentNameLsa(const ndn::Name& lsaKey,
uint64_t lsSeqNo, std::string& dataContent)
{
@@ -1014,24 +1036,6 @@
}
}
-void
-Lsdb::processInterestTimedOut(const ndn::Interest& interest, uint32_t retransmitNo,
- const ndn::time::steady_clock::TimePoint& deadline, ndn::Name lsaName,
- uint64_t seqNo)
-{
- const ndn::Name& interestName = interest.getName();
- _LOG_DEBUG("Interest timed out for LSA: " << interestName);
-
- if (ndn::time::steady_clock::now() < deadline) {
-
- SequenceNumberMap::const_iterator it = m_highestSeqNo.find(lsaName);
-
- if (it != m_highestSeqNo.end() && it->second == seqNo) {
- expressInterest(interestName, retransmitNo + 1, deadline);
- }
- }
-}
-
ndn::time::system_clock::TimePoint
Lsdb::getLsaExpirationTimePoint()
{
diff --git a/src/lsdb.hpp b/src/lsdb.hpp
index 417c978..eac7770 100644
--- a/src/lsdb.hpp
+++ b/src/lsdb.hpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014-2015, The University of Memphis,
+ * Copyright (c) 2014-2016, The University of Memphis,
* Regents of the University of California,
* Arizona Board of Regents.
*
@@ -24,6 +24,7 @@
#include <utility>
#include <boost/cstdint.hpp>
+
#include <ndn-cxx/security/key-chain.hpp>
#include <ndn-cxx/util/time.hpp>
@@ -41,19 +42,12 @@
class Lsdb
{
public:
- Lsdb(Nlsr& nlsr, ndn::Scheduler& scheduler, SyncLogicHandler& sync)
- : m_nlsr(nlsr)
- , m_scheduler(scheduler)
- , m_sync(sync)
- , m_lsaRefreshTime(0)
- , m_adjLsaBuildInterval(static_cast<uint32_t>(ADJ_LSA_BUILD_INTERVAL_DEFAULT))
- {
- }
+ Lsdb(Nlsr& nlsr, ndn::Scheduler& scheduler, SyncLogicHandler& sync);
bool
doesLsaExist(const ndn::Name& key, const std::string& lsType);
- // function related to Name LSDB
+ // functions related to Name LSDB
bool
buildAndInstallOwnNameLsa();
@@ -75,7 +69,7 @@
const std::list<NameLsa>&
getNameLsdb();
- //function related to Cor LSDB
+ // functions related to Cor LSDB
bool
buildAndInstallOwnCoordinateLsa();
@@ -97,8 +91,7 @@
const std::list<CoordinateLsa>&
getCoordinateLsdb();
- //function related to Adj LSDB
-
+ // functions related to Adj LSDB
void
scheduleAdjLsaBuild();
@@ -141,6 +134,13 @@
void
setThisRouterPrefix(std::string trp);
+ void
+ expressInterest(const ndn::Name& interestName, uint32_t timeoutCount,
+ steady_clock::TimePoint deadline = DEFAULT_LSA_RETRIEVAL_DEADLINE);
+
+ void
+ processInterest(const ndn::Name& name, const ndn::Interest& interest);
+
private:
bool
addNameLsa(NameLsa& nlsa);
@@ -187,16 +187,8 @@
void
exprireOrRefreshCoordinateLsa(const ndn::Name& lsaKey,
uint64_t seqNo);
-public:
- void
- expressInterest(const ndn::Name& interestName, uint32_t timeoutCount,
- steady_clock::TimePoint deadline = DEFAULT_LSA_RETRIEVAL_DEADLINE);
void
- processInterest(const ndn::Name& name, const ndn::Interest& interest);
-
-private:
- void
putLsaData(const ndn::Interest& interest, const std::string& content);
void
@@ -215,32 +207,9 @@
uint64_t seqNo);
void
- onContent(const ndn::Data& data, const steady_clock::TimePoint& deadline,
- ndn::Name lsaName, uint64_t seqNo);
-
- /**
- * @brief Retry validation after it fails
- *
- * Data packet validation can fail either because the packet does not have
- * valid signature (fatal) or because some of the certificate chain Data packets
- * failed to be fetched (non-fatal). Currently, the library does not provide
- * clear indication (besides plain-text message in error callback) of what is
- * the reason for failure and we will try to re-validate for as long as it the deadline.
- */
- void
- retryContentValidation(const ndn::shared_ptr<const ndn::Data>& data,
- const steady_clock::TimePoint& deadline, ndn::Name lsaName,
- uint64_t seqNo);
-
- void
onContentValidated(const ndn::shared_ptr<const ndn::Data>& data);
void
- onContentValidationFailed(const ndn::shared_ptr<const ndn::Data>& data, const std::string& msg,
- const steady_clock::TimePoint& deadline, ndn::Name lsaName,
- uint64_t seqNo);
-
- void
processContentNameLsa(const ndn::Name& lsaKey,
uint64_t lsSeqNo, std::string& dataContent);
@@ -253,10 +222,37 @@
uint64_t lsSeqNo, std::string& dataContent);
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
+ /**
+ * @brief Error callback when SegmentFetcher fails to return an LSA
+ *
+ * In all error cases, a reattempt to fetch the LSA will be made.
+ *
+ * Segment validation can fail either because the packet does not have a
+ * valid signature (fatal) or because some of the certificates in the trust chain
+ * could not be fetched (non-fatal).
+ *
+ * Currently, the library does not provide clear indication (besides a plain-text message
+ * in the error callback) of the reason for the failure nor the segment that failed
+ * to be validated, thus we will continue to try to fetch the LSA until the deadline
+ * is reached.
+ */
void
- processInterestTimedOut(const ndn::Interest& interest, uint32_t retransmitNo,
- const steady_clock::TimePoint& deadline, ndn::Name lsaName,
- uint64_t seqNo);
+ onFetchLsaError(uint32_t errorCode,
+ const std::string& msg,
+ ndn::Name& interestName,
+ uint32_t retransmitNo,
+ const ndn::time::steady_clock::TimePoint& deadline,
+ ndn::Name lsaName,
+ uint64_t seqNo);
+
+ /**
+ * @brief Success callback when SegmentFetcher returns a valid LSA
+ *
+ * \param The base Interest used to fetch the LSA in the format:
+ * /<network>/NLSR/LSA/<site>/%C1.Router/<router>/<lsa-type>/<seqNo>
+ */
+ void
+ afterFetchLsa(const ndn::ConstBufferPtr& data, ndn::Name& interestName);
private:
system_clock::TimePoint
diff --git a/src/publisher/segment-publisher.hpp b/src/publisher/segment-publisher.hpp
index 5aefa52..7d959e1 100644
--- a/src/publisher/segment-publisher.hpp
+++ b/src/publisher/segment-publisher.hpp
@@ -68,7 +68,8 @@
/** \brief Publish data under provided prefix
*/
void
- publish(const ndn::Name& prefix)
+ publish(const ndn::Name& prefix,
+ const ndn::security::SigningInfo& signingInfo = ndn::security::KeyChain::DEFAULT_SIGNING_INFO)
{
ndn::EncodingBuffer buffer;
generate(buffer);
@@ -99,7 +100,7 @@
data->setFinalBlockId(segmentName[-1]);
}
- publishSegment(data);
+ publishSegment(data, signingInfo);
++segmentNo;
} while (segmentBegin < end);
}
@@ -112,9 +113,9 @@
private:
void
- publishSegment(ndn::shared_ptr<ndn::Data>& data)
+ publishSegment(ndn::shared_ptr<ndn::Data>& data, const ndn::security::SigningInfo& signingInfo)
{
- m_keyChain.sign(*data);
+ m_keyChain.sign(*data, signingInfo);
m_face.put(*data);
}
diff --git a/tests/test-lsdb.cpp b/tests/test-lsdb.cpp
index 7111620..05a71ea 100644
--- a/tests/test-lsdb.cpp
+++ b/tests/test-lsdb.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014-2015, The University of Memphis,
+ * Copyright (c) 2014-2016, The University of Memphis,
* Regents of the University of California,
* Arizona Board of Regents.
*
@@ -28,6 +28,7 @@
#include <boost/test/unit_test.hpp>
#include <ndn-cxx/util/dummy-client-face.hpp>
+#include <ndn-cxx/util/segment-fetcher.hpp>
namespace nlsr {
namespace test {
@@ -38,7 +39,7 @@
{
public:
LsdbFixture()
- : face(make_shared<ndn::util::DummyClientFace>())
+ : face(make_shared<ndn::util::DummyClientFace>(g_ioService))
, nlsr(g_ioService, g_scheduler, ndn::ref(*face))
, sync(*face, nlsr.getLsdb(), nlsr.getConfParameter(), nlsr.getSequencingManager())
, lsdb(nlsr.getLsdb())
@@ -122,10 +123,11 @@
interests.clear();
steady_clock::TimePoint deadline = steady_clock::now() +
- ndn::time::seconds(static_cast<int>(LSA_REFRESH_TIME_MAX));
+ ndn::time::seconds(LSA_REFRESH_TIME_MAX);
// Simulate an LSA interest timeout
- lsdb.processInterestTimedOut(oldInterestName, 0, deadline, interestName, oldSeqNo);
+ lsdb.onFetchLsaError(ndn::util::SegmentFetcher::ErrorCode::INTEREST_TIMEOUT, "Timeout",
+ oldInterestName, 0, deadline, interestName, oldSeqNo);
face->processEvents(ndn::time::milliseconds(1));
BOOST_REQUIRE(interests.size() > 0);
@@ -149,13 +151,81 @@
interests.clear();
// Simulate an LSA interest timeout where the sequence number is outdated
- lsdb.processInterestTimedOut(oldInterestName, 0, deadline, interestName, oldSeqNo);
+ lsdb.onFetchLsaError(ndn::util::SegmentFetcher::ErrorCode::INTEREST_TIMEOUT, "Timeout",
+ oldInterestName, 0, deadline, interestName, oldSeqNo);
face->processEvents(ndn::time::milliseconds(1));
// Interest should not be expressed for outdated sequence number
BOOST_CHECK_EQUAL(interests.size(), 0);
}
+BOOST_AUTO_TEST_CASE(SegmentLsaData)
+{
+ ndn::Name router("/ndn/cs/%C1.Router/router1");
+ uint64_t seqNo = 12;
+ NamePrefixList prefixList;
+
+ NameLsa lsa(router, seqNo, ndn::time::system_clock::now(), prefixList);
+
+ ndn::Name prefix("/ndn/edu/memphis/netlab/research/nlsr/test/prefix/");
+
+ int nPrefixes = 0;
+ while (lsa.getData().size() < ndn::MAX_NDN_PACKET_SIZE) {
+ lsa.addName(ndn::Name(prefix).appendNumber(++nPrefixes));
+ }
+
+ std::string expectedDataContent = lsa.getData();
+ lsdb.installNameLsa(lsa);
+
+ ndn::Name interestName("/ndn/NLSR/LSA/cs/%C1.Router/router1/name/");
+ interestName.appendNumber(seqNo);
+
+ ndn::Interest interest(interestName);
+
+ lsdb.processInterest(ndn::Name(), interest);
+ face->processEvents(ndn::time::milliseconds(1));
+
+ std::vector<ndn::Data> data = face->sentData;
+ std::string recvDataContent;
+ for (unsigned int i = 0; i < data.size(); ++i)
+ {
+ const ndn::Block& nameBlock = data[i].getContent();
+
+ std::string nameBlockContent(reinterpret_cast<char const*>(nameBlock.value()),
+ nameBlock.value_size());
+ recvDataContent += nameBlockContent;
+ }
+
+ BOOST_CHECK_EQUAL(expectedDataContent, recvDataContent);
+}
+
+BOOST_AUTO_TEST_CASE(ReceiveSegmentedLsaData)
+{
+ ndn::Name router("/ndn/cs/%C1.Router/router1");
+ uint64_t seqNo = 12;
+ NamePrefixList prefixList;
+
+ NameLsa lsa(router, seqNo, ndn::time::system_clock::now(), prefixList);
+
+ ndn::Name prefix("/prefix/");
+
+ for (int nPrefixes = 0; nPrefixes < 3; ++nPrefixes) {
+ lsa.addName(ndn::Name(prefix).appendNumber(nPrefixes));
+ }
+
+ ndn::Name interestName("/ndn/NLSR/LSA/cs/%C1.Router/router1/name/");
+ interestName.appendNumber(seqNo);
+
+ const ndn::ConstBufferPtr bufferPtr = make_shared<ndn::Buffer>(lsa.getData().c_str(),
+ lsa.getData().size());
+ lsdb.afterFetchLsa(bufferPtr, interestName);
+
+ NameLsa* foundLsa = lsdb.findNameLsa(lsa.getKey());
+ BOOST_REQUIRE(foundLsa != nullptr);
+
+ BOOST_CHECK_EQUAL(foundLsa->getData(), lsa.getData());
+}
+
BOOST_AUTO_TEST_CASE(LsdbRemoveAndExists)
{
ndn::time::system_clock::TimePoint testTimePoint = ndn::time::system_clock::now();