nodeinfo.cpp
1 // SPDX-FileCopyrightText: Copyright (C) 2024-2025 Marek Küthe <m.k@mk16.de> 2 // 3 // SPDX-License-Identifier: GPL-3.0-or-later 4 5 #include "nodeinfo.hpp" 6 7 using namespace crazytrace; 8 9 crazytrace::NodeInfo::NodeInfo() : 10 _hoplimit(64), 11 _randomgenerator(0), 12 _addressadded(false) 13 { 14 } 15 16 uint8_t crazytrace::NodeInfo::get_hoplimit() const noexcept 17 { 18 return this->_hoplimit; 19 } 20 21 void crazytrace::NodeInfo::set_mac_address( 22 Tins::HWAddress<6> mac_address) noexcept 23 { 24 this->_mac_address = mac_address; 25 } 26 27 const Tins::HWAddress<6>& crazytrace::NodeInfo::get_mac_address() const noexcept 28 { 29 return this->_mac_address; 30 } 31 32 bool crazytrace::NodeInfo::has_address(const Tins::IPv6Address& address) 33 { 34 return std::ranges::binary_search(this->_addresses, address); 35 } 36 37 void crazytrace::NodeInfo::set_hoplimit(uint8_t hoplimit) 38 { 39 static_assert(std::numeric_limits<decltype(this->_hoplimit)>::min() == 0); 40 static_assert(std::numeric_limits<decltype(this->_hoplimit)>::max() == 255); 41 this->_hoplimit = hoplimit; 42 } 43 44 void crazytrace::NodeInfo::add_node(std::shared_ptr<NodeInfo> node) 45 { 46 this->_nodes.push_back(node); 47 } 48 49 void crazytrace::NodeInfo::add_address(Tins::IPv6Address address) 50 { 51 this->_addressadded = true; 52 this->_addresses.push_back(address); 53 } 54 55 const Tins::IPv6Address& crazytrace::NodeInfo::get_address() 56 { 57 if (this->_addressadded) 58 { 59 /* Is called up each time the number of addresses is changed. However, 60 it is not called after each address is added to allow multiple 61 addresses to be added quickly. */ 62 std::size_t max_address = this->_addresses.size(); 63 if (max_address == 0) 64 throw std::invalid_argument( 65 "Despite adding an address, none is available."); 66 max_address--; 67 68 this->_randomgenerator = RandomGenerator(max_address); 69 std::ranges::sort(this->_addresses); 70 this->_addressadded = false; 71 } 72 const std::size_t address_number = this->_randomgenerator.generate(); 73 return this->_addresses.at(address_number); 74 } 75 76 std::size_t crazytrace::NodeInfo::max_depth() const 77 { 78 std::size_t max = 0; 79 for (const auto& node : this->_nodes) 80 { 81 const std::size_t node_depth = node->max_depth(); 82 max = std::max(max, node_depth); 83 } 84 return max + 1; 85 } 86 87 std::vector<std::shared_ptr<NodeInfo>> crazytrace::NodeInfo::get_route_to( 88 const Tins::IPv6Address& destination_address) const 89 { 90 for (const auto& node : this->_nodes) 91 { 92 if (node->has_address(destination_address)) 93 { 94 std::vector<std::shared_ptr<NodeInfo>> result; 95 result.push_back(node); 96 return result; 97 } 98 99 std::vector<std::shared_ptr<NodeInfo>> result = 100 node->get_route_to(destination_address); 101 if (!result.empty()) 102 { 103 result.push_back(node); 104 return result; 105 } 106 } 107 108 return {}; 109 } 110 111 void crazytrace::NodeInfo::print(std::ostream& os, unsigned int layer) const 112 { 113 const std::string tabs(layer, '\t'); 114 115 os << tabs << *this << std::endl; 116 if (!this->_nodes.empty()) 117 { 118 os << tabs << "Childs:" << std::endl; 119 for (const auto& node : this->_nodes) 120 { 121 node->print(os, layer + 1); 122 } 123 } 124 } 125 126 bool crazytrace::NodeInfo::operator==(const NodeInfo& other) const 127 { 128 return this->_addresses == other._addresses && 129 this->_mac_address == other._mac_address && 130 this->_hoplimit == other._hoplimit && 131 std::ranges::equal(this->_nodes, // flawfinder: ignore 132 other._nodes, 133 [](const auto& a, const auto& b) 134 { 135 return *a == *b; 136 }); 137 } 138 139 std::ostream& crazytrace::operator<<(std::ostream& os, 140 NodeInfo const & nodeinfo) 141 { 142 os << "NodeInfo: hoplimit=" << static_cast<unsigned>(nodeinfo._hoplimit); 143 for (const auto& address : nodeinfo._addresses) 144 { 145 os << " " << address; 146 } 147 if (nodeinfo._mac_address != Tins::HWAddress<6>()) 148 { 149 /* Is not empty address? */ 150 os << " " << nodeinfo._mac_address; 151 } 152 153 return os; 154 }