include/boost/corosio/ipv6_address.hpp

100.0% Lines (9/9) 100.0% Functions (5/5)
include/boost/corosio/ipv6_address.hpp
Line TLA Hits Source Code
1 //
2 // Copyright (c) 2026 Vinnie Falco (vinnie.falco@gmail.com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/cppalliance/corosio
8 //
9
10 #ifndef BOOST_COROSIO_IPV6_ADDRESS_HPP
11 #define BOOST_COROSIO_IPV6_ADDRESS_HPP
12
13 #include <boost/corosio/detail/config.hpp>
14
15 #include <array>
16 #include <cstdint>
17 #include <iosfwd>
18 #include <string>
19 #include <string_view>
20 #include <system_error>
21
22 namespace boost::corosio {
23
24 class ipv4_address;
25
26 /** An IP version 6 style address.
27
28 Objects of this type are used to construct,
29 parse, and manipulate IP version 6 addresses.
30
31 @par BNF
32 @code
33 IPv6address = 6( h16 ":" ) ls32
34 / "::" 5( h16 ":" ) ls32
35 / [ h16 ] "::" 4( h16 ":" ) ls32
36 / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
37 / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
38 / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
39 / [ *4( h16 ":" ) h16 ] "::" ls32
40 / [ *5( h16 ":" ) h16 ] "::" h16
41 / [ *6( h16 ":" ) h16 ] "::"
42
43 ls32 = ( h16 ":" h16 ) / IPv4address
44 ; least-significant 32 bits of address
45
46 h16 = 1*4HEXDIG
47 ; 16 bits of address represented in hexadecimal
48 @endcode
49
50 @par Specification
51 @li <a href="https://datatracker.ietf.org/doc/html/rfc4291"
52 >IP Version 6 Addressing Architecture (rfc4291)</a>
53 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2"
54 >3.2.2. Host (rfc3986)</a>
55
56 @see
57 @ref ipv4_address,
58 @ref parse_ipv6_address.
59 */
60 class BOOST_COROSIO_DECL ipv6_address
61 {
62 std::array<unsigned char, 16> addr_{};
63
64 public:
65 /** The number of characters in the longest possible IPv6 string.
66
67 The longest IPv6 address is:
68 @code
69 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
70 @endcode
71 or with IPv4-mapped:
72 @code
73 ::ffff:255.255.255.255
74 @endcode
75 */
76 static constexpr std::size_t max_str_len = 49;
77
78 /** The type used to represent an address as an array of bytes.
79
80 Octets are stored in network byte order.
81 */
82 using bytes_type = std::array<unsigned char, 16>;
83
84 /** Default constructor.
85
86 Constructs the unspecified address (::).
87
88 @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.2"
89 >2.5.2. The Unspecified Address</a>
90
91 @see
92 @ref is_unspecified
93 */
94 257086 ipv6_address() = default;
95
96 /** Copy constructor.
97 */
98 ipv6_address(ipv6_address const&) = default;
99
100 /** Copy assignment.
101
102 @return A reference to this object.
103 */
104 ipv6_address& operator=(ipv6_address const&) = default;
105
106 /** Construct from an array of bytes.
107
108 This function constructs an address
109 from the array in `bytes`, which is
110 interpreted in big-endian.
111
112 @param bytes The value to construct from.
113 */
114 explicit ipv6_address(bytes_type const& bytes) noexcept;
115
116 /** Construct from an IPv4 address.
117
118 This function constructs an IPv6 address
119 from the IPv4 address `addr`. The resulting
120 address is an IPv4-Mapped IPv6 Address.
121
122 @param addr The address to construct from.
123
124 @par Specification
125 @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.2"
126 >2.5.5.2. IPv4-Mapped IPv6 Address (rfc4291)</a>
127 */
128 explicit ipv6_address(ipv4_address const& addr) noexcept;
129
130 /** Construct from a string.
131
132 This function constructs an address from
133 the string `s`, which must contain a valid
134 IPv6 address string or else an exception
135 is thrown.
136
137 @note For a non-throwing parse function,
138 use @ref parse_ipv6_address.
139
140 @par Exception Safety
141 Exceptions thrown on invalid input.
142
143 @throw std::invalid_argument
144 The input failed to parse correctly.
145
146 @param s The string to parse.
147
148 @par Specification
149 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2"
150 >3.2.2. Host (rfc3986)</a>
151
152 @see
153 @ref parse_ipv6_address.
154 */
155 explicit ipv6_address(std::string_view s);
156
157 /** Return the address as bytes, in network byte order.
158
159 @return The address as an array of bytes.
160 */
161 24 bytes_type to_bytes() const noexcept
162 {
163 24 return addr_;
164 }
165
166 /** Return the address as a string.
167
168 The returned string does not
169 contain surrounding square brackets.
170
171 @par Example
172 @code
173 ipv6_address::bytes_type b = {{
174 0, 1, 0, 2, 0, 3, 0, 4,
175 0, 5, 0, 6, 0, 7, 0, 8 }};
176 ipv6_address a(b);
177 assert(a.to_string() == "1:2:3:4:5:6:7:8");
178 @endcode
179
180 @return The address as a string.
181
182 @par Specification
183 @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.2">
184 2.2. Text Representation of Addresses (rfc4291)</a>
185 */
186 std::string to_string() const;
187
188 /** Write a string representing the address to a buffer.
189
190 The resulting buffer is not null-terminated.
191
192 @throw std::length_error `dest_size < ipv6_address::max_str_len`
193
194 @return The formatted string view.
195
196 @param dest The buffer in which to write,
197 which must have at least `dest_size` space.
198
199 @param dest_size The size of the output buffer.
200 */
201 std::string_view to_buffer(char* dest, std::size_t dest_size) const;
202
203 /** Return true if the address is unspecified.
204
205 The address 0:0:0:0:0:0:0:0 is called the
206 unspecified address. It indicates the
207 absence of an address.
208
209 @return `true` if the address is unspecified.
210
211 @par Specification
212 @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.2">
213 2.5.2. The Unspecified Address (rfc4291)</a>
214 */
215 bool is_unspecified() const noexcept;
216
217 /** Return true if the address is a loopback address.
218
219 The unicast address 0:0:0:0:0:0:0:1 is called
220 the loopback address. It may be used by a node
221 to send an IPv6 packet to itself.
222
223 @return `true` if the address is a loopback address.
224
225 @par Specification
226 @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.3">
227 2.5.3. The Loopback Address (rfc4291)</a>
228 */
229 bool is_loopback() const noexcept;
230
231 /** Return true if the address is a mapped IPv4 address.
232
233 This address type is used to represent the
234 addresses of IPv4 nodes as IPv6 addresses.
235
236 @return `true` if the address is a mapped IPv4 address.
237
238 @par Specification
239 @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.2">
240 2.5.5.2. IPv4-Mapped IPv6 Address (rfc4291)</a>
241 */
242 bool is_v4_mapped() const noexcept;
243
244 /** Return true if two addresses are equal.
245
246 @return `true` if the addresses are equal.
247 */
248 friend bool
249 16 operator==(ipv6_address const& a1, ipv6_address const& a2) noexcept
250 {
251 16 return a1.addr_ == a2.addr_;
252 }
253
254 /** Return true if two addresses are not equal.
255
256 @return `true` if the addresses are not equal.
257 */
258 friend bool
259 2 operator!=(ipv6_address const& a1, ipv6_address const& a2) noexcept
260 {
261 2 return a1.addr_ != a2.addr_;
262 }
263
264 /** Return an address object that represents the unspecified address.
265
266 The address 0:0:0:0:0:0:0:0 (::) may be used to bind a socket
267 to all available interfaces.
268
269 @return The unspecified address (::).
270 */
271 6 static ipv6_address any() noexcept
272 {
273 6 return ipv6_address();
274 }
275
276 /** Return an address object that represents the loopback address.
277
278 The unicast address 0:0:0:0:0:0:0:1 is called
279 the loopback address. It may be used by a node
280 to send an IPv6 packet to itself.
281
282 @par Specification
283 @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.3">
284 2.5.3. The Loopback Address (rfc4291)</a>
285
286 @return The loopback address (::1).
287 */
288 static ipv6_address loopback() noexcept;
289
290 /** Format the address to an output stream.
291
292 This function writes the address to an
293 output stream using standard notation.
294
295 @return The output stream, for chaining.
296
297 @param os The output stream to write to.
298
299 @param addr The address to write.
300 */
301 friend BOOST_COROSIO_DECL std::ostream&
302 operator<<(std::ostream& os, ipv6_address const& addr);
303
304 private:
305 std::size_t print_impl(char* dest) const noexcept;
306 };
307
308 /** Parse a string containing an IPv6 address.
309
310 This function attempts to parse the string
311 as an IPv6 address and returns an error code
312 if the string does not contain a valid IPv6 address.
313
314 @par Exception Safety
315 Throws nothing.
316
317 @return An error code (empty on success).
318
319 @param s The string to parse.
320 @param addr The address to store the result.
321 */
322 [[nodiscard]] BOOST_COROSIO_DECL std::error_code
323 parse_ipv6_address(std::string_view s, ipv6_address& addr) noexcept;
324
325 } // namespace boost::corosio
326
327 #endif
328