lsdb: Segment LSAs larger than max segment size
refs: #2965
Change-Id: I5dd091b663db2cc5e2d925144e57ee55a486b3cd
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()
{