SNode.C
Loading...
Searching...
No Matches
ConfigAddress.cpp
Go to the documentation of this file.
1/*
2 * SNode.C - A Slim Toolkit for Network Communication
3 * Copyright (C) Volker Christian <me@vchrist.at>
4 * 2020, 2021, 2022, 2023, 2024, 2025, 2026
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published
8 * by the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20/*
21 * MIT License
22 *
23 * Permission is hereby granted, free of charge, to any person obtaining a copy
24 * of this software and associated documentation files (the "Software"), to deal
25 * in the Software without restriction, including without limitation the rights
26 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
27 * copies of the Software, and to permit persons to whom the Software is
28 * furnished to do so, subject to the following conditions:
29 *
30 * The above copyright notice and this permission notice shall be included in
31 * all copies or substantial portions of the Software.
32 *
33 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
39 * THE SOFTWARE.
40 */
41
42#include "net/in6/config/ConfigAddress.h"
43
44#include "net/config/ConfigAddressBase.hpp" // IWYU pragma: keep
45#include "net/config/ConfigAddressLocal.hpp" // IWYU pragma: keep
46#include "net/config/ConfigAddressRemote.hpp" // IWYU pragma: keep
47#include "net/config/ConfigAddressReverse.hpp" // IWYU pragma: keep
48#include "net/config/ConfigSection.hpp"
49
50#ifndef DOXYGEN_SHOULD_SKIP_THIS
51
52#include "core/system/netdb.h"
53#include "utils/PreserveErrno.h"
54
55#include <limits>
56
57#endif /* DOXYGEN_SHOULD_SKIP_THIS */
58
59#define XSTR(s) STR(s)
60#define STR(s) #s
61
62namespace net::in6::config {
63
64 template <template <typename SocketAddress> typename ConfigAddressType>
66 [[maybe_unused]] const std::string& addressOptionName,
67 [[maybe_unused]] const std::string& addressOptionDescription)
68 : ConfigSection(instance, this)
69 , ConfigAddressType<net::in6::SocketAddress>(this) {
70 numericReverseOpt = addFlag( //
71 "--numeric-reverse",
72 "Suppress reverse host name lookup",
73 "bool",
74 XSTR(IN6_NUMERIC_REVERSE),
75 CLI::IsMember({"true", "false"}));
76 }
77
78 template <template <typename SocketAddress> typename ConfigAddressType>
79 SocketAddress ConfigAddressReverse<ConfigAddressType>::getSocketAddress(const SocketAddress::SockAddr& sockAddr,
80 SocketAddress::SockLen sockAddrLen) {
81 SocketAddress socketAddress;
82 try {
83 socketAddress = SocketAddress(sockAddr, sockAddrLen, numericReverseOpt->as<bool>());
84 } catch ([[maybe_unused]] const SocketAddress::BadSocketAddress& badSocketAddress) {
85 try {
86 socketAddress = Super::getSocketAddress(sockAddr, sockAddrLen);
87 } catch ([[maybe_unused]] const SocketAddress::BadSocketAddress& badSocketAddress) {
88 throw;
89 }
90 }
91
92 return socketAddress;
93 }
94
95 template <template <typename SocketAddress> typename ConfigAddressType>
96 ConfigAddressReverse<ConfigAddressType>& ConfigAddressReverse<ConfigAddressType>::setNumericReverse(bool numeric) {
97 setDefaultValue(numericReverseOpt, numeric ? "true" : "false");
98
99 return *this;
101
102 template <template <typename SocketAddress> typename ConfigAddressType>
103 bool ConfigAddressReverse<ConfigAddressType>::getNumericReverse() const {
104 return numericReverseOpt->as<bool>();
105 }
107 template <template <typename SocketAddress> typename ConfigAddressType>
108 ConfigAddress<ConfigAddressType>::ConfigAddress(net::config::ConfigInstance* instance,
109 [[maybe_unused]] const std::string& addressOptionName,
110 [[maybe_unused]] const std::string& addressOptionDescription)
111 : ConfigSection(instance, this)
112 , ConfigAddressType<net::in6::SocketAddress>(this) {
113 hostOpt = addOption( //
114 "--host",
115 "Host name or IPv6 address",
116 "hostname|IPv6",
117 "::",
118 CLI::TypeValidator<std::string>());
119
120 portOpt = addOption( //
121 "--port",
122 "Port number",
123 "port",
124 0,
125 CLI::Range(std::numeric_limits<uint16_t>::min(), std::numeric_limits<uint16_t>::max()));
127 numericOpt = addFlag( //
128 "--numeric",
129 "Suppress host name lookup",
130 "bool",
131 XSTR(IN6_NUMERIC),
132 CLI::IsMember({"true", "false"}));
134 numericReverseOpt = addFlag( //
135 "--numeric-reverse",
136 "Suppress reverse host name lookup",
137 "bool",
138 XSTR(IN6_NUMERIC_REVERSE),
139 CLI::IsMember({"true", "false"}));
140
141 ipv4MappedOpt = addFlag( //
142 "--ipv4-mapped",
143 "Resolve IPv4-mapped IPv6 addresses also",
144 "bool",
145 XSTR(IN6_IPV4_MAPPED),
146 CLI::IsMember({"true", "false"}));
147 }
148
149 template <template <typename SocketAddress> typename ConfigAddressType>
150 SocketAddress* ConfigAddress<ConfigAddressType>::init() {
151 SocketAddress* socketAddress = new SocketAddress(hostOpt->as<std::string>(), portOpt->as<uint16_t>());
152
153 try {
154 socketAddress->init({.aiFlags = (aiFlags & ~AI_NUMERICHOST) | (numericOpt->as<bool>() ? AI_NUMERICHOST : 0),
155 .aiSockType = aiSockType,
156 .aiProtocol = aiProtocol});
157 } catch (const core::socket::SocketAddress::BadSocketAddress&) {
158 delete socketAddress;
159 socketAddress = nullptr;
160
161 throw;
162 }
163
164 return socketAddress;
165 }
166
167 template <template <typename SocketAddress> typename ConfigAddressType>
168 SocketAddress ConfigAddress<ConfigAddressType>::getSocketAddress(const SocketAddress::SockAddr& sockAddr,
169 SocketAddress::SockLen sockAddrLen) {
170 SocketAddress socketAddress;
171 try {
172 socketAddress = SocketAddress(sockAddr, sockAddrLen, numericReverseOpt->as<bool>());
173 } catch ([[maybe_unused]] const SocketAddress::BadSocketAddress& badSocketAddress) {
174 try {
175 socketAddress = Super::getSocketAddress(sockAddr, sockAddrLen);
176 } catch ([[maybe_unused]] const SocketAddress::BadSocketAddress& badSocketAddress) {
177 throw;
178 }
179 }
180
181 return socketAddress;
182 }
183
184 template <template <typename SocketAddress> typename ConfigAddressType>
185 ConfigAddress<ConfigAddressType>& ConfigAddress<ConfigAddressType>::setSocketAddress(const SocketAddress& socketAddress) {
186 setHost(socketAddress.getHost());
187 setPort(socketAddress.getPort());
188
189 return *this;
190 }
191
192 template <template <typename SocketAddress> typename ConfigAddressType>
193 ConfigAddress<ConfigAddressType>& ConfigAddress<ConfigAddressType>::setHost(const std::string& ipOrHostname) {
194 const utils::PreserveErrno preserveErrno;
195
196 setDefaultValue(hostOpt, ipOrHostname);
197 required(hostOpt, false);
198
199 return *this;
200 }
201
202 template <template <typename SocketAddress> typename ConfigAddressType>
203 std::string ConfigAddress<ConfigAddressType>::getHost() const {
204 return hostOpt->as<std::string>();
205 }
206
207 template <template <typename SocketAddress> typename ConfigAddressType>
208 ConfigAddress<ConfigAddressType>& ConfigAddress<ConfigAddressType>::setPort(uint16_t port) {
209 const utils::PreserveErrno preserveErrno;
210
211 setDefaultValue(portOpt, port);
212 required(portOpt, false);
213
214 return *this;
215 }
216
217 template <template <typename SocketAddress> typename ConfigAddressType>
218 uint16_t ConfigAddress<ConfigAddressType>::getPort() const {
219 return portOpt->as<uint16_t>();
220 }
221
222 template <template <typename SocketAddress> typename ConfigAddressType>
223 ConfigAddress<ConfigAddressType>& ConfigAddress<ConfigAddressType>::setNumeric(bool numeric) {
224 const utils::PreserveErrno preserveErrno;
225
226 setDefaultValue(numericOpt, numeric ? "true" : "false");
227
228 return *this;
229 }
230
231 template <template <typename SocketAddress> typename ConfigAddressType>
232 bool ConfigAddress<ConfigAddressType>::getNumeric() const {
233 return numericOpt->as<bool>();
234 }
235
236 template <template <typename SocketAddressT> typename ConfigAddressTypeT>
237 void ConfigAddress<ConfigAddressTypeT>::configurable(bool configurable) {
238 this->setConfigurable(hostOpt, configurable);
239 this->setConfigurable(portOpt, configurable);
240 }
241
242 template <template <typename SocketAddress> typename ConfigAddressType>
243 ConfigAddress<ConfigAddressType>& ConfigAddress<ConfigAddressType>::setNumericReverse(bool numeric) {
244 const utils::PreserveErrno preserveErrno;
245
246 setDefaultValue(numericReverseOpt, numeric ? "true" : "false");
247
248 return *this;
249 }
250
251 template <template <typename SocketAddress> typename ConfigAddressType>
252 ConfigAddress<ConfigAddressType>& ConfigAddress<ConfigAddressType>::setIpv4Mapped(bool ipv4Mapped) {
253 const utils::PreserveErrno preserveErrno;
254
255 setDefaultValue(ipv4MappedOpt, ipv4Mapped ? "true" : "false");
256
257 return *this;
258 }
259
260 template <template <typename SocketAddress> typename ConfigAddressType>
261 bool ConfigAddress<ConfigAddressType>::getIpv4Mapped() const {
262 return ipv4MappedOpt->as<bool>();
263 }
264
265 template <template <typename SocketAddress> typename ConfigAddressType>
266 ConfigAddress<ConfigAddressType>& ConfigAddress<ConfigAddressType>::setAiFlags(int aiFlags) {
267 this->aiFlags = aiFlags;
268
269 return *this;
270 }
271
272 template <template <typename SocketAddress> typename ConfigAddressType>
273 int ConfigAddress<ConfigAddressType>::getAiFlags() const {
274 return aiFlags;
275 }
276
277 template <template <typename SocketAddress> typename ConfigAddressType>
278 ConfigAddress<ConfigAddressType>& ConfigAddress<ConfigAddressType>::setAiSockType(int aiSockType) {
279 this->aiSockType = aiSockType;
280
281 return *this;
282 }
283
284 template <template <typename SocketAddress> typename ConfigAddressType>
285 int ConfigAddress<ConfigAddressType>::getAiSockType() const {
286 return aiSockType;
287 }
288
289 template <template <typename SocketAddress> typename ConfigAddressType>
290 ConfigAddress<ConfigAddressType>& ConfigAddress<ConfigAddressType>::setAiProtocol(int aiProtocol) {
291 this->aiProtocol = aiProtocol;
292
293 return *this;
294 }
295
296 template <template <typename SocketAddress> typename ConfigAddressType>
297 int ConfigAddress<ConfigAddressType>::getAiProtocol() const {
298 return aiProtocol;
299 }
300
301 template <template <typename SocketAddress> typename ConfigAddressType>
302 ConfigAddress<ConfigAddressType>& ConfigAddress<ConfigAddressType>::setHostRequired(bool required) {
303 this->required(hostOpt, required);
304
305 return *this;
306 }
307
308 template <template <typename SocketAddress> typename ConfigAddressType>
309 ConfigAddress<ConfigAddressType>& ConfigAddress<ConfigAddressType>::setPortRequired(bool required) {
310 this->required(portOpt, required);
311
312 return *this;
313 }
314
315} // namespace net::in6::config
316
317template class net::config::ConfigAddress<net::in6::SocketAddress>;
318template class net::config::ConfigAddressLocal<net::in6::SocketAddress>;
319template class net::config::ConfigAddressRemote<net::in6::SocketAddress>;
320template class net::config::ConfigAddressReverse<net::in6::SocketAddress>;
321template class net::config::ConfigAddressBase<net::in6::SocketAddress>;
322template class net::in6::config::ConfigAddress<net::config::ConfigAddressLocal>;
323template class net::in6::config::ConfigAddress<net::config::ConfigAddressRemote>;
324template class net::in6::config::ConfigAddressReverse<net::config::ConfigAddressReverse>;
#define XSTR(s)
void init(const Hints &hints={.aiFlags=0,.aiSockType=0,.aiProtocol=0})
std::string getHost() const
SocketAddress(const std::string &ipOrHostname, uint16_t port)
SocketAddress(const SockAddr &sockAddr, SockLen sockAddrLen, bool numeric=true)
ConfigAddressReverse(net::config::ConfigInstance *instance, const std::string &addressOptionName, const std::string &addressOptionDescription)
ConfigAddressTypeT< SocketAddress > Super
ConfigAddressReverse & setNumericReverse(bool numeric=true)
SocketAddress getSocketAddress(const SocketAddress::SockAddr &sockAddr, SocketAddress::SockLen sockAddrLen)
ConfigAddress & setIpv4Mapped(bool ipv4Mapped=true)
ConfigAddress & setNumericReverse(bool numeric=true)
ConfigAddress & setAiFlags(int aiFlags)
ConfigAddress & setPortRequired(bool required=true)
SocketAddress getSocketAddress(const SocketAddress::SockAddr &sockAddr, SocketAddress::SockLen sockAddrLen)
ConfigAddress(net::config::ConfigInstance *instance, const std::string &addressOptionName, const std::string &addressOptionDescription)
ConfigAddress & setNumeric(bool numeric=true)
ConfigAddress & setPort(uint16_t port)
ConfigAddress & setSocketAddress(const SocketAddress &socketAddress)
SocketAddress * init() final
ConfigAddress & setHost(const std::string &ipOrHostname)
ConfigAddressTypeT< SocketAddress > Super
ConfigAddress & setAiSockType(int aiSocktype)
ConfigAddress & setHostRequired(bool required=true)
ConfigAddress & setAiProtocol(int aiProtocol)
void configurable(bool configurable=true) final
#define STR(a)
Definition clients.h:48