blob: 1b5e8046aa030977a0f5564b12e0e8aa0f8bd7f2 [file] [log] [blame]
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2017, 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.hpp"
#include "nlsr.hpp"
#include "name-prefix-list.hpp"
#include "adjacent.hpp"
#include "logger.hpp"
#include <string>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <cmath>
#include <limits>
#include <boost/tokenizer.hpp>
#include <boost/algorithm/string.hpp>
namespace nlsr {
INIT_LOGGER("Lsa");
const ndn::Name
NameLsa::getKey() const
{
ndn::Name key = m_origRouter;
key.append(std::to_string(Lsa::Type::NAME));
return key;
}
NameLsa::NameLsa(const ndn::Name& origR, uint32_t lsn,
const ndn::time::system_clock::TimePoint& lt,
NamePrefixList& npl)
{
m_origRouter = origR;
m_lsSeqNo = lsn;
m_expirationTimePoint = lt;
for (const auto& name : npl.getNames()) {
addName(name);
}
}
std::string
NameLsa::getData()
{
std::ostringstream os;
os << m_origRouter << "|" << Lsa::Type::NAME << "|" << m_lsSeqNo << "|"
<< ndn::time::toIsoString(m_expirationTimePoint) << "|" << m_npl.size();
for (const auto& name : m_npl.getNames()) {
os << "|" << name;
}
os << "|";
return os.str();
}
bool
NameLsa::initializeFromContent(const std::string& content)
{
uint32_t numName = 0;
boost::char_separator<char> sep("|");
boost::tokenizer<boost::char_separator<char> >tokens(content, sep);
boost::tokenizer<boost::char_separator<char> >::iterator tok_iter =
tokens.begin();
m_origRouter = ndn::Name(*tok_iter++);
if (!(m_origRouter.size() > 0)) {
return false;
}
try {
if (*tok_iter++ != std::to_string(Lsa::Type::NAME)) {
return false;
}
m_lsSeqNo = boost::lexical_cast<uint32_t>(*tok_iter++);
m_expirationTimePoint = ndn::time::fromIsoString(*tok_iter++);
numName = boost::lexical_cast<uint32_t>(*tok_iter++);
}
catch (const std::exception& e) {
_LOG_ERROR(e.what());
return false;
}
for (uint32_t i = 0; i < numName; i++) {
ndn::Name name(*tok_iter++);
addName(name);
}
return true;
}
bool
NameLsa::isEqualContent(const NameLsa& other) const
{
return m_npl == other.getNpl();
}
void
NameLsa::writeLog()
{
_LOG_DEBUG("Name Lsa: ");
_LOG_DEBUG(" Origination Router: " << m_origRouter);
_LOG_DEBUG(" Ls Type: " << getType());
_LOG_DEBUG(" Ls Seq No: " << m_lsSeqNo);
_LOG_DEBUG(" Ls Lifetime: " << m_expirationTimePoint);
_LOG_DEBUG(" Names: ");
int i = 1;
std::list<ndn::Name> nl = m_npl.getNames();
for (std::list<ndn::Name>::iterator it = nl.begin(); it != nl.end(); it++)
{
_LOG_DEBUG(" Name " << i << ": " << (*it));
}
_LOG_DEBUG("name_lsa_end");
}
CoordinateLsa::CoordinateLsa(const ndn::Name& origR, uint32_t lsn,
const ndn::time::system_clock::TimePoint& lt,
double r, std::vector<double> theta)
{
m_origRouter = origR;
m_lsSeqNo = lsn;
m_expirationTimePoint = lt;
m_corRad = r;
m_angles = theta;
}
const ndn::Name
CoordinateLsa::getKey() const
{
ndn::Name key = m_origRouter;
key.append(std::to_string(Lsa::Type::COORDINATE));
return key;
}
bool
CoordinateLsa::isEqualContent(const CoordinateLsa& clsa)
{
if (clsa.getCorTheta().size() != m_angles.size()) {
return false;
}
std::vector<double> m_angles2 = clsa.getCorTheta();
for (unsigned int i = 0; i < clsa.getCorTheta().size(); i++) {
if (std::abs(m_angles[i] - m_angles2[i]) > std::numeric_limits<double>::epsilon()) {
return false;
}
}
return (std::abs(m_corRad - clsa.getCorRadius()) <
std::numeric_limits<double>::epsilon());
}
std::string
CoordinateLsa::getData()
{
std::ostringstream os;
os << m_origRouter << "|" << Lsa::Type::COORDINATE << "|" << m_lsSeqNo << "|"
<< ndn::time::toIsoString(m_expirationTimePoint) << "|" << m_corRad << "|"
<< m_angles.size() << "|";
for (const auto& angle: m_angles) {
os << angle << "|";
}
return os.str();
}
bool
CoordinateLsa::initializeFromContent(const std::string& content)
{
boost::char_separator<char> sep("|");
boost::tokenizer<boost::char_separator<char> >tokens(content, sep);
boost::tokenizer<boost::char_separator<char> >::iterator tok_iter =
tokens.begin();
m_origRouter = ndn::Name(*tok_iter++);
if (!(m_origRouter.size() > 0)) {
return false;
}
try {
if (*tok_iter++ != std::to_string(Lsa::Type::COORDINATE)) {
return false;
}
m_lsSeqNo = boost::lexical_cast<uint32_t>(*tok_iter++);
m_expirationTimePoint = ndn::time::fromIsoString(*tok_iter++);
m_corRad = boost::lexical_cast<double>(*tok_iter++);
int numAngles = boost::lexical_cast<uint32_t>(*tok_iter++);
for (int i = 0; i < numAngles; i++) {
m_angles.push_back(boost::lexical_cast<double>(*tok_iter++));
}
}
catch (const std::exception& e) {
_LOG_ERROR(e.what());
return false;
}
return true;
}
void
CoordinateLsa::writeLog()
{
_LOG_DEBUG("Cor Lsa: ");
_LOG_DEBUG(" Origination Router: " << m_origRouter);
_LOG_DEBUG(" Ls Type: " << getType());
_LOG_DEBUG(" Ls Seq No: " << m_lsSeqNo);
_LOG_DEBUG(" Ls Lifetime: " << m_expirationTimePoint);
_LOG_DEBUG(" Hyperbolic Radius: " << m_corRad);
int i = 0;
for(auto const& value: m_angles) {
_LOG_DEBUG(" Hyperbolic Theta " << i++ << ": "<< value);
}
}
AdjLsa::AdjLsa(const ndn::Name& origR, uint32_t lsn,
const ndn::time::system_clock::TimePoint& lt,
uint32_t nl , AdjacencyList& adl)
{
m_origRouter = origR;
m_lsSeqNo = lsn;
m_expirationTimePoint = lt;
m_noLink = nl;
std::list<Adjacent> al = adl.getAdjList();
for (std::list<Adjacent>::iterator it = al.begin(); it != al.end(); it++) {
if (it->getStatus() == Adjacent::STATUS_ACTIVE) {
addAdjacent((*it));
}
}
}
const ndn::Name
AdjLsa::getKey() const
{
ndn::Name key = m_origRouter;
key.append(std::to_string(Lsa::Type::ADJACENCY));
return key;
}
bool
AdjLsa::isEqualContent(AdjLsa& alsa)
{
return m_adl == alsa.getAdl();
}
std::string
AdjLsa::getData()
{
std::ostringstream os;
os << m_origRouter << "|" << Lsa::Type::ADJACENCY << "|" << m_lsSeqNo << "|"
<< ndn::time::toIsoString(m_expirationTimePoint) << "|" << m_adl.size();
for (const auto& adjacent : m_adl.getAdjList()) {
os << "|" << adjacent.getName() << "|" << adjacent.getFaceUri()
<< "|" << adjacent.getLinkCost();
}
os << "|";
return os.str();
}
bool
AdjLsa::initializeFromContent(const std::string& content)
{
uint32_t numLink = 0;
boost::char_separator<char> sep("|");
boost::tokenizer<boost::char_separator<char> >tokens(content, sep);
boost::tokenizer<boost::char_separator<char> >::iterator tok_iter =
tokens.begin();
m_origRouter = ndn::Name(*tok_iter++);
if (!(m_origRouter.size() > 0)) {
return false;
}
try {
if (*tok_iter++ != std::to_string(Lsa::Type::ADJACENCY)) {
return false;
}
m_lsSeqNo = boost::lexical_cast<uint32_t>(*tok_iter++);
m_expirationTimePoint = ndn::time::fromIsoString(*tok_iter++);
numLink = boost::lexical_cast<uint32_t>(*tok_iter++);
}
catch (const std::exception& e) {
_LOG_ERROR(e.what());
return false;
}
for (uint32_t i = 0; i < numLink; i++) {
try {
ndn::Name adjName(*tok_iter++);
std::string connectingFaceUri(*tok_iter++);
double linkCost = boost::lexical_cast<double>(*tok_iter++);
Adjacent adjacent(adjName, ndn::util::FaceUri(connectingFaceUri), linkCost,
Adjacent::STATUS_INACTIVE, 0, 0);
addAdjacent(adjacent);
}
catch (const std::exception& e) {
_LOG_ERROR(e.what());
return false;
}
}
return true;
}
void
AdjLsa::addNptEntries(Nlsr& pnlsr)
{
// Only add NPT entries if this is an adj LSA from another router.
if (getOrigRouter() != pnlsr.getConfParameter().getRouterPrefix()) {
// Pass the originating router as both the name to register and
// where it came from.
pnlsr.getNamePrefixTable().addEntry(getOrigRouter(), getOrigRouter());
}
}
void
AdjLsa::removeNptEntries(Nlsr& pnlsr)
{
if (getOrigRouter() != pnlsr.getConfParameter().getRouterPrefix()) {
pnlsr.getNamePrefixTable().removeEntry(getOrigRouter(), getOrigRouter());
}
}
void
AdjLsa::writeLog()
{
_LOG_DEBUG(*this);
}
std::ostream&
operator<<(std::ostream& os, const AdjLsa& adjLsa)
{
os << "Adj Lsa:\n"
<< " Origination Router: " << adjLsa.getOrigRouter() << "\n"
<< " Ls Type: " << adjLsa.getType() << "\n"
<< " Ls Seq No: " << adjLsa.getLsSeqNo() << "\n"
<< " Ls Lifetime: " << adjLsa.getExpirationTimePoint() << "\n"
<< " Adjacents: \n";
int adjacencyIndex = 1;
for (const Adjacent& adjacency : adjLsa) {
os << " Adjacent " << adjacencyIndex++ << ":\n"
<< " Adjacent Name: " << adjacency.getName() << "\n"
<< " Connecting FaceUri: " << adjacency.getFaceUri() << "\n"
<< " Link Cost: " << adjacency.getLinkCost() << "\n";
}
os << "adj_lsa_end";
return os;
}
std::ostream&
operator<<(std::ostream& os, const Lsa::Type& type)
{
os << std::to_string(type);
return os;
}
std::istream&
operator>>(std::istream& is, Lsa::Type& type)
{
std::string typeString;
is >> typeString;
if (typeString == "ADJACENCY") {
type = Lsa::Type::ADJACENCY;
}
else if (typeString == "COORDINATE") {
type = Lsa::Type::COORDINATE;
}
else if (typeString == "NAME") {
type = Lsa::Type::NAME;
}
else {
type = Lsa::Type::BASE;
}
return is;
}
} // namespace nlsr
namespace std {
std::string
to_string(const nlsr::Lsa::Type& type)
{
switch (type) {
case nlsr::Lsa::Type::ADJACENCY:
return "ADJACENCY";
case nlsr::Lsa::Type::COORDINATE:
return "COORDINATE";
case nlsr::Lsa::Type::NAME:
return "NAME";
default:
return "BASE";
}
}
} // namespace std