235 lines
9.3 KiB
C++
235 lines
9.3 KiB
C++
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
|
/**
|
|
* Copyright (c) 2014-2017, The University of Memphis,
|
|
* Regents of the University of California
|
|
*
|
|
* 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 "hello-protocol.hpp"
|
|
|
|
#include "hello-protocol.hpp"
|
|
#include "nlsr.hpp"
|
|
#include "lsdb.hpp"
|
|
#include "utility/name-helper.hpp"
|
|
#include "logger.hpp"
|
|
|
|
namespace nlsr {
|
|
|
|
INIT_LOGGER("HelloProtocol");
|
|
|
|
const std::string HelloProtocol::INFO_COMPONENT = "INFO";
|
|
const std::string HelloProtocol::NLSR_COMPONENT = "NLSR";
|
|
|
|
HelloProtocol::HelloProtocol(Nlsr& nlsr, ndn::Scheduler& scheduler)
|
|
: m_nlsr(nlsr)
|
|
, m_scheduler(scheduler)
|
|
{
|
|
}
|
|
|
|
void
|
|
HelloProtocol::expressInterest(const ndn::Name& interestName, uint32_t seconds)
|
|
{
|
|
NLSR_LOG_DEBUG("Expressing Interest :" << interestName);
|
|
ndn::Interest i(interestName);
|
|
i.setInterestLifetime(ndn::time::seconds(seconds));
|
|
i.setMustBeFresh(true);
|
|
m_nlsr.getNlsrFace().expressInterest(i,
|
|
std::bind(&HelloProtocol::onContent,
|
|
this,
|
|
_1, _2),
|
|
std::bind(&HelloProtocol::processInterestTimedOut, // Nack
|
|
this, _1),
|
|
std::bind(&HelloProtocol::processInterestTimedOut,
|
|
this, _1));
|
|
|
|
// increment SENT_HELLO_INTEREST
|
|
hpIncrementSignal(Statistics::PacketType::SENT_HELLO_INTEREST);
|
|
}
|
|
|
|
void
|
|
HelloProtocol::sendScheduledInterest(uint32_t seconds)
|
|
{
|
|
std::list<Adjacent> adjList = m_nlsr.getAdjacencyList().getAdjList();
|
|
for (std::list<Adjacent>::iterator it = adjList.begin(); it != adjList.end();
|
|
++it) {
|
|
// If this adjacency has a Face, just proceed as usual.
|
|
if((*it).getFaceId() != 0) {
|
|
// interest name: /<neighbor>/NLSR/INFO/<router>
|
|
ndn::Name interestName = (*it).getName() ;
|
|
interestName.append(NLSR_COMPONENT);
|
|
interestName.append(INFO_COMPONENT);
|
|
interestName.append(m_nlsr.getConfParameter().getRouterPrefix().wireEncode());
|
|
expressInterest(interestName,
|
|
m_nlsr.getConfParameter().getInterestResendTime());
|
|
NLSR_LOG_DEBUG("Sending scheduled interest: " << interestName);
|
|
}
|
|
}
|
|
scheduleInterest(m_nlsr.getConfParameter().getInfoInterestInterval());
|
|
}
|
|
|
|
void
|
|
HelloProtocol::scheduleInterest(uint32_t seconds)
|
|
{
|
|
NLSR_LOG_DEBUG("Scheduling HELLO Interests in " << ndn::time::seconds(seconds));
|
|
|
|
m_scheduler.scheduleEvent(ndn::time::seconds(seconds),
|
|
std::bind(&HelloProtocol::sendScheduledInterest, this, seconds));
|
|
}
|
|
|
|
void
|
|
HelloProtocol::processInterest(const ndn::Name& name,
|
|
const ndn::Interest& interest)
|
|
{
|
|
// interest name: /<neighbor>/NLSR/INFO/<router>
|
|
const ndn::Name interestName = interest.getName();
|
|
|
|
// increment RCV_HELLO_INTEREST
|
|
hpIncrementSignal(Statistics::PacketType::RCV_HELLO_INTEREST);
|
|
|
|
NLSR_LOG_DEBUG("Interest Received for Name: " << interestName);
|
|
if (interestName.get(-2).toUri() != INFO_COMPONENT) {
|
|
NLSR_LOG_DEBUG("INFO_COMPONENT not found or interestName: " << interestName
|
|
<< " does not match expression");
|
|
return;
|
|
}
|
|
|
|
ndn::Name neighbor;
|
|
neighbor.wireDecode(interestName.get(-1).blockFromValue());
|
|
NLSR_LOG_DEBUG("Neighbor: " << neighbor);
|
|
if (m_nlsr.getAdjacencyList().isNeighbor(neighbor)) {
|
|
std::shared_ptr<ndn::Data> data = std::make_shared<ndn::Data>();
|
|
data->setName(ndn::Name(interest.getName()).appendVersion());
|
|
data->setFreshnessPeriod(ndn::time::seconds(10)); // 10 sec
|
|
data->setContent(reinterpret_cast<const uint8_t*>(INFO_COMPONENT.c_str()),
|
|
INFO_COMPONENT.size());
|
|
m_nlsr.getKeyChain().sign(*data, m_nlsr.getDefaultCertName());
|
|
NLSR_LOG_DEBUG("Sending out data for name: " << interest.getName());
|
|
m_nlsr.getNlsrFace().put(*data);
|
|
// increment SENT_HELLO_DATA
|
|
hpIncrementSignal(Statistics::PacketType::SENT_HELLO_DATA);
|
|
|
|
auto adjacent = m_nlsr.getAdjacencyList().findAdjacent(neighbor);
|
|
// If this neighbor was previously inactive, send our own hello interest, too
|
|
if (adjacent->getStatus() == Adjacent::STATUS_INACTIVE) {
|
|
// We can only do that if the neighbor currently has a face.
|
|
if(adjacent->getFaceId() != 0){
|
|
// interest name: /<neighbor>/NLSR/INFO/<router>
|
|
ndn::Name interestName(neighbor);
|
|
interestName.append(NLSR_COMPONENT);
|
|
interestName.append(INFO_COMPONENT);
|
|
interestName.append(m_nlsr.getConfParameter().getRouterPrefix().wireEncode());
|
|
expressInterest(interestName,
|
|
m_nlsr.getConfParameter().getInterestResendTime());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
HelloProtocol::processInterestTimedOut(const ndn::Interest& interest)
|
|
{
|
|
// interest name: /<neighbor>/NLSR/INFO/<router>
|
|
const ndn::Name interestName(interest.getName());
|
|
NLSR_LOG_DEBUG("Interest timed out for Name: " << interestName);
|
|
if (interestName.get(-2).toUri() != INFO_COMPONENT) {
|
|
return;
|
|
}
|
|
ndn::Name neighbor = interestName.getPrefix(-3);
|
|
NLSR_LOG_DEBUG("Neighbor: " << neighbor);
|
|
m_nlsr.getAdjacencyList().incrementTimedOutInterestCount(neighbor);
|
|
|
|
Adjacent::Status status = m_nlsr.getAdjacencyList().getStatusOfNeighbor(neighbor);
|
|
|
|
uint32_t infoIntTimedOutCount =
|
|
m_nlsr.getAdjacencyList().getTimedOutInterestCount(neighbor);
|
|
NLSR_LOG_DEBUG("Status: " << status);
|
|
NLSR_LOG_DEBUG("Info Interest Timed out: " << infoIntTimedOutCount);
|
|
if (infoIntTimedOutCount < m_nlsr.getConfParameter().getInterestRetryNumber()) {
|
|
// interest name: /<neighbor>/NLSR/INFO/<router>
|
|
ndn::Name interestName(neighbor);
|
|
interestName.append(NLSR_COMPONENT);
|
|
interestName.append(INFO_COMPONENT);
|
|
interestName.append(m_nlsr.getConfParameter().getRouterPrefix().wireEncode());
|
|
NLSR_LOG_DEBUG("Resending interest: " << interestName);
|
|
expressInterest(interestName,
|
|
m_nlsr.getConfParameter().getInterestResendTime());
|
|
}
|
|
else if ((status == Adjacent::STATUS_ACTIVE) &&
|
|
(infoIntTimedOutCount == m_nlsr.getConfParameter().getInterestRetryNumber())) {
|
|
m_nlsr.getAdjacencyList().setStatusOfNeighbor(neighbor, Adjacent::STATUS_INACTIVE);
|
|
|
|
NLSR_LOG_DEBUG("Neighbor: " << neighbor << " status changed to INACTIVE");
|
|
|
|
m_nlsr.getLsdb().scheduleAdjLsaBuild();
|
|
}
|
|
}
|
|
|
|
// This is the first function that incoming Hello data will
|
|
// see. This checks if the data appears to be signed, and passes it
|
|
// on to validate the content of the data.
|
|
void
|
|
HelloProtocol::onContent(const ndn::Interest& interest, const ndn::Data& data)
|
|
{
|
|
NLSR_LOG_DEBUG("Received data for INFO(name): " << data.getName());
|
|
if (data.getSignature().hasKeyLocator()) {
|
|
if (data.getSignature().getKeyLocator().getType() == ndn::KeyLocator::KeyLocator_Name) {
|
|
NLSR_LOG_DEBUG("Data signed with: " << data.getSignature().getKeyLocator().getName());
|
|
}
|
|
}
|
|
m_nlsr.getValidator().validate(data,
|
|
std::bind(&HelloProtocol::onContentValidated, this, _1),
|
|
std::bind(&HelloProtocol::onContentValidationFailed,
|
|
this, _1, _2));
|
|
}
|
|
|
|
void
|
|
HelloProtocol::onContentValidated(const std::shared_ptr<const ndn::Data>& data)
|
|
{
|
|
// data name: /<neighbor>/NLSR/INFO/<router>/<version>
|
|
ndn::Name dataName = data->getName();
|
|
NLSR_LOG_DEBUG("Data validation successful for INFO(name): " << dataName);
|
|
if (dataName.get(-3).toUri() == INFO_COMPONENT) {
|
|
ndn::Name neighbor = dataName.getPrefix(-4);
|
|
|
|
Adjacent::Status oldStatus = m_nlsr.getAdjacencyList().getStatusOfNeighbor(neighbor);
|
|
m_nlsr.getAdjacencyList().setStatusOfNeighbor(neighbor, Adjacent::STATUS_ACTIVE);
|
|
m_nlsr.getAdjacencyList().setTimedOutInterestCount(neighbor, 0);
|
|
Adjacent::Status newStatus = m_nlsr.getAdjacencyList().getStatusOfNeighbor(neighbor);
|
|
|
|
NLSR_LOG_DEBUG("Neighbor : " << neighbor);
|
|
NLSR_LOG_DEBUG("Old Status: " << oldStatus << " New Status: " << newStatus);
|
|
// change in Adjacency list
|
|
if ((oldStatus - newStatus) != 0) {
|
|
if (m_nlsr.getConfParameter().getHyperbolicState() == HYPERBOLIC_STATE_ON) {
|
|
m_nlsr.getRoutingTable().scheduleRoutingTableCalculation(m_nlsr);
|
|
}
|
|
else {
|
|
m_nlsr.getLsdb().scheduleAdjLsaBuild();
|
|
}
|
|
}
|
|
}
|
|
// increment RCV_HELLO_DATA
|
|
hpIncrementSignal(Statistics::PacketType::RCV_HELLO_DATA);
|
|
}
|
|
|
|
void
|
|
HelloProtocol::onContentValidationFailed(const std::shared_ptr<const ndn::Data>& data,
|
|
const std::string& msg)
|
|
{
|
|
NLSR_LOG_DEBUG("Validation Error: " << msg);
|
|
}
|
|
|
|
} // namespace nlsr
|