/* -*- 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 . **/ #include "lsa.hpp" #include "nlsr.hpp" #include "name-prefix-list.hpp" #include "adjacent.hpp" #include "logger.hpp" #include #include #include #include #include #include #include namespace nlsr { INIT_LOGGER("Lsa"); std::string Lsa::getData() const { std::ostringstream os; os << m_origRouter << "|" << getType() << "|" << m_lsSeqNo << "|" << ndn::time::toIsoString(m_expirationTimePoint) << "|"; return os.str(); } const ndn::Name Lsa::getKey() const { return ndn::Name(m_origRouter).append(std::to_string(getType())); } bool Lsa::deserializeCommon(boost::tokenizer>::iterator& iterator) { m_origRouter = ndn::Name(*iterator++); if (m_origRouter.size() <= 0) return false; if (*iterator++ != std::to_string(getType())) return false; m_lsSeqNo = boost::lexical_cast(*iterator++); m_expirationTimePoint = ndn::time::fromIsoString(*iterator++); return true; } 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::serialize() const { std::ostringstream os; os << getData() << m_npl.size(); for (const auto& name : m_npl.getNames()) { os << "|" << name; } os << "|"; return os.str(); } bool NameLsa::deserialize(const std::string& content) noexcept { uint32_t numName = 0; boost::char_separator sep("|"); boost::tokenizer >tokens(content, sep); boost::tokenizer >::iterator tok_iter = tokens.begin(); try { if (!deserializeCommon(tok_iter)) return false; numName = boost::lexical_cast(*tok_iter++); for (uint32_t i = 0; i < numName; i++) { ndn::Name name(*tok_iter++); addName(name); } } catch (const std::exception& e) { NLSR_LOG_ERROR("Could not deserialize from content: " << e.what()); return false; } return true; } bool NameLsa::isEqualContent(const NameLsa& other) const { return m_npl == other.getNpl(); } void NameLsa::writeLog() const { NLSR_LOG_DEBUG(*this); } CoordinateLsa::CoordinateLsa(const ndn::Name& origR, uint32_t lsn, const ndn::time::system_clock::TimePoint& lt, double r, std::vector theta) { m_origRouter = origR; m_lsSeqNo = lsn; m_expirationTimePoint = lt; m_corRad = r; m_angles = theta; } bool CoordinateLsa::isEqualContent(const CoordinateLsa& clsa) { if (clsa.getCorTheta().size() != m_angles.size()) { return false; } std::vector 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::epsilon()) { return false; } } return (std::abs(m_corRad - clsa.getCorRadius()) < std::numeric_limits::epsilon()); } std::string CoordinateLsa::serialize() const { std::ostringstream os; os << getData() << m_corRad << "|" << m_angles.size() << "|"; for (const auto& angle: m_angles) { os << angle << "|"; } return os.str(); } bool CoordinateLsa::deserialize(const std::string& content) noexcept { boost::char_separator sep("|"); boost::tokenizer >tokens(content, sep); boost::tokenizer >::iterator tok_iter = tokens.begin(); try { if (!deserializeCommon(tok_iter)) return false; m_corRad = boost::lexical_cast(*tok_iter++); int numAngles = boost::lexical_cast(*tok_iter++); for (int i = 0; i < numAngles; i++) { m_angles.push_back(boost::lexical_cast(*tok_iter++)); } } catch (const std::exception& e) { NLSR_LOG_ERROR("Could not deserialize from content: " << e.what()); return false; } return true; } void CoordinateLsa::writeLog() const { NLSR_LOG_DEBUG(*this); } 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 al = adl.getAdjList(); for (std::list::iterator it = al.begin(); it != al.end(); it++) { if (it->getStatus() == Adjacent::STATUS_ACTIVE) { addAdjacent((*it)); } } } bool AdjLsa::isEqualContent(AdjLsa& alsa) { return m_adl == alsa.getAdl(); } std::string AdjLsa::serialize() const { std::ostringstream os; os << getData() << m_adl.size(); for (const auto& adjacent : m_adl.getAdjList()) { os << "|" << adjacent.getName() << "|" << adjacent.getFaceUri() << "|" << adjacent.getLinkCost(); } os << "|"; return os.str(); } bool AdjLsa::deserialize(const std::string& content) noexcept { uint32_t numLink = 0; boost::char_separator sep("|"); boost::tokenizer >tokens(content, sep); boost::tokenizer >::iterator tok_iter = tokens.begin(); try { if (!deserializeCommon(tok_iter)) return false; numLink = boost::lexical_cast(*tok_iter++); for (uint32_t i = 0; i < numLink; i++) { ndn::Name adjName(*tok_iter++); std::string connectingFaceUri(*tok_iter++); double linkCost = boost::lexical_cast(*tok_iter++); Adjacent adjacent(adjName, ndn::FaceUri(connectingFaceUri), linkCost, Adjacent::STATUS_INACTIVE, 0, 0); addAdjacent(adjacent); } } catch (const std::exception& e) { NLSR_LOG_ERROR("Could not deserialize from content: " << 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() const { NLSR_LOG_DEBUG(*this); } std::ostream& operator<<(std::ostream& os, const AdjLsa& lsa) { os << lsa.toString(); os << "-Adjacents:"; int adjacencyIndex = 1; for (const Adjacent& adjacency : lsa.m_adl) { 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 CoordinateLsa& lsa) { os << lsa.toString(); os << "--Hyperbolic Radius: " << lsa.m_corRad << "\n"; int i = 0; for (const auto& value : lsa.m_angles) { os << "---Hyperbolic Theta: " << i++ << ": " << value << "\n"; } os << "cor_lsa_end"; return os; } std::ostream& operator<<(std::ostream& os, const NameLsa& lsa) { os << lsa.toString(); os << "--Names:\n"; int i = 0; auto names = lsa.m_npl.getNames(); for (const auto& name : names) { os << "---Name " << i++ << ": " << name << "\n"; } os << "name_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; } std::string Lsa::toString() const { std::ostringstream os; os << "LSA of type " << getType() << ":\n-Origin Router: " << getOrigRouter() << "\n-Sequence Number: " << getLsSeqNo() << "\n-Expiration Point: " << getExpirationTimePoint() << "\n"; return os.str(); } } // 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"; case nlsr::Lsa::Type::MOCK: return "MOCK"; default: return "BASE"; } } } // namespace std