RAVENNAKIT
Loading...
Searching...
No Matches
network_interface_config.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: AGPL-3.0-or-later
2/*
3 * Project: RAVENNAKIT (RAVENNA / AES67 / ST2110-30 SDK)
4 * Copyright (c) 2024-2025 Sound on Digital
5 *
6 * This file is part of RAVENNAKIT.
7 *
8 * RAVENNAKIT is dual-licensed:
9 * 1) Under the terms of the GNU Affero General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version (the "AGPL License"); and
12 * 2) Under a commercial license from Sound on Digital, for customers who
13 * cannot (or do not wish to) comply with the AGPL License terms.
14 *
15 * If you obtained this file under the AGPL License, you may redistribute it
16 * and/or modify it under the terms of the AGPL License. See the LICENSE
17 * file in the project root for details.
18 *
19 * For commercial licensing, support, and other inquiries, please visit:
20 *
21 * https://ravennakit.com
22 *
23 */
24
25#pragma once
26
27#include "network_interface.hpp"
32
33#include <vector>
34
35namespace rav {
36
38 public:
39 std::vector<NetworkInterface::Identifier> interfaces;
40
41 friend bool operator==(const NetworkInterfaceConfig& lhs, const NetworkInterfaceConfig& rhs) {
42 return lhs.interfaces == rhs.interfaces;
43 }
44
45 friend bool operator!=(const NetworkInterfaceConfig& lhs, const NetworkInterfaceConfig& rhs) {
46 return lhs.interfaces != rhs.interfaces;
47 }
48
54 void set_interface(const size_t rank, const NetworkInterface::Identifier& identifier) {
55 if (interfaces.size() < rank + 1) {
56 interfaces.resize(rank + 1);
57 }
58 interfaces[rank] = identifier;
59 }
60
66 [[nodiscard]] const NetworkInterface::Identifier* get_interface_for_rank(const size_t rank) const {
67 if (interfaces.size() < rank + 1) {
68 return nullptr;
69 }
70 return &interfaces[rank];
71 }
72
77 [[nodiscard]] ip_address_v4 get_interface_ipv4_address(const size_t rank) const {
78 auto* id = get_interface_for_rank(rank);
79 if (id == nullptr) {
80 return {};
81 }
82 if (auto* interface = NetworkInterfaceList::get_system_interfaces().get_interface(*id)) {
83 return interface->get_first_ipv4_address();
84 }
85 return {};
86 }
87
92 [[nodiscard]] std::vector<ip_address_v4> get_interface_ipv4_addresses() const {
93 std::vector<ip_address_v4> addresses;
94 for (const auto& id : interfaces) {
95 auto& it = addresses.emplace_back();
96 if (auto* interface = NetworkInterfaceList::get_system_interfaces().get_interface(id)) {
97 it = interface->get_first_ipv4_address();
98 }
99 }
100 return addresses;
101 }
102
107 [[nodiscard]] bool empty() const {
108 return interfaces.empty();
109 }
110
114 [[nodiscard]] std::string to_string() const {
115 std::string output = "Network interface configuration: ";
116 if (interfaces.empty()) {
117 return output + "none";
118 }
119 bool first = true;
120 for (size_t i = 0; i < interfaces.size(); ++i) {
121 if (!first) {
122 output += ", ";
123 }
124 first = false;
125 fmt::format_to(std::back_inserter(output), "{}({})", interfaces[i], i);
126 }
127 return output;
128 }
129
134 template<size_t N>
135 std::array<ip_address_v4, N> get_array_of_interface_addresses() const {
136 std::array<ip_address_v4, N> addresses {};
137 auto addresses_vector = get_interface_ipv4_addresses();
138
139 for (size_t i = 0; i < std::min(addresses.size(), addresses_vector.size()); ++i) {
140 addresses[i] = std::move(addresses_vector[i]);
141 }
142
143 return addresses;
144 }
145
146#if RAV_HAS_BOOST_JSON
150 [[nodiscard]] boost::json::array to_boost_json() const {
151 auto a = boost::json::array();
152
153 for (size_t i = 0; i < interfaces.size(); ++i) {
154 a.push_back(boost::json::object {{"rank", i}, {"identifier", interfaces[i]}});
155 }
156
157 return a;
158 }
159
165 [[nodiscard]] static tl::expected<NetworkInterfaceConfig, std::string> from_boost_json(const boost::json::value& json) {
166 const auto json_array = json.try_as_array();
167 if (json_array.has_error()) {
168 return tl::unexpected("Value is not an array");
169 }
170 NetworkInterfaceConfig config;
171 try {
172 for (auto& object : *json_array) {
173 const auto rank = object.at("rank").to_number<size_t>();
174 const auto identifier = std::string(object.at("identifier").as_string());
175 config.set_interface(rank, identifier);
176 }
177 } catch (const std::exception& e) {
178 return tl::unexpected(fmt::format("Failed to parse NetworkInterfaceConfig: {}", e.what()));
179 }
180 return config;
181 }
182#endif
183};
184
185inline std::optional<NetworkInterfaceConfig>
186parse_network_interface_config_from_string(const std::string& input, const char delimiter = ',') {
187 StringParser parser(input);
189 size_t rank {};
190 for (auto i = 0; i < 10; ++i) {
191 auto section = parser.split(delimiter);
192 if (!section) {
193 return config; // Exhausted
194 }
196 if (!iface) {
197 return std::nullopt;
198 }
199 config.set_interface(rank++, iface->get_identifier());
200 }
201 RAV_ASSERT_FALSE("Loop upper bound reached");
202 return config;
203}
204
205} // namespace rav
#define RAV_ASSERT_FALSE(message)
Asserts with false, entering the RAV_ASSERT procedure as a quick way to assert that a branch is inval...
Definition assert.hpp:189
std::array< ip_address_v4, N > get_array_of_interface_addresses() const
std::vector< NetworkInterface::Identifier > interfaces
friend bool operator==(const NetworkInterfaceConfig &lhs, const NetworkInterfaceConfig &rhs)
std::vector< ip_address_v4 > get_interface_ipv4_addresses() const
ip_address_v4 get_interface_ipv4_address(const size_t rank) const
bool empty() const
Checks if the configuration is empty.
friend bool operator!=(const NetworkInterfaceConfig &lhs, const NetworkInterfaceConfig &rhs)
void set_interface(const size_t rank, const NetworkInterface::Identifier &identifier)
Sets a network interface by its rank.
const NetworkInterface::Identifier * get_interface_for_rank(const size_t rank) const
Gets a network interface by its rank.
std::string Identifier
The identifier of a network interface (e.g. "en0", "eth0").
static const NetworkInterfaceList & get_system_interfaces(bool force_refresh=false)
Retrieves the list of network interfaces on the system.
const NetworkInterface * find_by_string(const std::string_view &search_string) const
Finds a network interface by the given string.
A handy utility class for parsing strings.
std::optional< std::string_view > split(const char delimiter, const bool include_delimiter=false)
Reads until the given delimiter or until the end of the string.
boost::asio::ip::address_v4 ip_address_v4
std::optional< NetworkInterfaceConfig > parse_network_interface_config_from_string(const std::string &input, const char delimiter=',')