include/boost/url/ipv6_address.hpp

100.0% Lines (16/16) 100.0% Functions (7/7) -% Branches (0/0)
include/boost/url/ipv6_address.hpp
Line Hits Source Code
1 //
2 // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3 // Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
4 //
5 // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 //
8 // Official repository: https://github.com/boostorg/url
9 //
10
11 #ifndef BOOST_URL_IPV6_ADDRESS_HPP
12 #define BOOST_URL_IPV6_ADDRESS_HPP
13
14 #include <boost/url/detail/config.hpp>
15 #include <boost/url/error.hpp>
16 #include <boost/url/error_types.hpp>
17 #include <boost/core/detail/string_view.hpp>
18 #include <boost/url/grammar/string_token.hpp>
19 #include <array>
20 #include <cstdint>
21 #include <iosfwd>
22
23 namespace boost {
24 namespace urls {
25
26 class ipv4_address;
27
28 /** An IP version 6 style address.
29
30 Objects of this type are used to construct,
31 parse, and manipulate IP version 6 addresses.
32
33 @par BNF
34 @code
35 IPv6address = 6( h16 ":" ) ls32
36 / "::" 5( h16 ":" ) ls32
37 / [ h16 ] "::" 4( h16 ":" ) ls32
38 / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
39 / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
40 / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
41 / [ *4( h16 ":" ) h16 ] "::" ls32
42 / [ *5( h16 ":" ) h16 ] "::" h16
43 / [ *6( h16 ":" ) h16 ] "::"
44
45 ls32 = ( h16 ":" h16 ) / IPv4address
46 ; least-significant 32 bits of address
47
48 h16 = 1*4HEXDIG
49 ; 16 bits of address represented in hexadecimal
50 @endcode
51
52 @par Specification
53 @li <a href="https://datatracker.ietf.org/doc/html/rfc4291"
54 >IP Version 6 Addressing Architecture (rfc4291)</a>
55 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2"
56 >3.2.2. Host (rfc3986)</a>
57
58 @see
59 @ref ipv4_address,
60 @ref parse_ipv6_address.
61 */
62 class ipv6_address
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
72 @see
73 @ref to_buffer.
74 */
75 // ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
76 // ::ffff:255.255.255.255
77 // 12345678901234567890123456789012345678901234567890
78 // 1 2 3 4
79 static
80 constexpr
81 std::size_t max_str_len = 49;
82
83 /** The type used to represent an address as an array of bytes.
84
85 Octets are stored in network byte order.
86 */
87 using bytes_type = std::array<
88 unsigned char, 16>;
89
90 /** Constructor.
91
92 Default constructed objects represent
93 the unspecified address.
94
95 @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.2"
96 >2.5.2. The Unspecified Address</a>
97
98 @see
99 @ref is_unspecified
100 */
101 98 ipv6_address() = default;
102
103 /** Constructor.
104 */
105 ipv6_address(
106 ipv6_address const&) = default;
107
108 /** Copy Assignment
109
110 @return `*this`
111 */
112 ipv6_address&
113 operator=(
114 ipv6_address const&) = default;
115
116 /** Construct from an array of bytes.
117
118 This function constructs an address
119 from the array in `bytes`, which is
120 interpreted in big-endian.
121
122 @param bytes The value to construct from.
123 */
124 BOOST_URL_CXX20_CONSTEXPR
125 226 ipv6_address(
126 bytes_type const& bytes) noexcept
127 226 : addr_(bytes)
128 {
129 226 }
130
131 /** Construct from an IPv4 address.
132
133 This function constructs an IPv6 address
134 from the IPv4 address `addr`. The resulting
135 address is an IPv4-Mapped IPv6 Address.
136
137 @param addr The address to construct from.
138
139 @par Specification
140 @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.2"
141 >2.5.5.2. IPv4-Mapped IPv6 Address (rfc4291)</a>
142 */
143 BOOST_URL_DECL
144 ipv6_address(
145 ipv4_address const& addr) noexcept;
146
147 /** Construct from a string.
148
149 This function constructs an address from
150 the string `s`, which must contain a valid
151 IPv6 address string or else an exception
152 is thrown.
153
154 @note For a non-throwing parse function,
155 use @ref parse_ipv6_address.
156
157 @par Exception Safety
158 Exceptions thrown on invalid input.
159
160 @throw system_error
161 The input failed to parse correctly.
162
163 @param s The string to parse.
164
165 @par Specification
166 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2"
167 >3.2.2. Host (rfc3986)</a>
168
169 @see
170 @ref parse_ipv6_address.
171 */
172 BOOST_URL_DECL
173 ipv6_address(
174 core::string_view s);
175
176 /** Return the address as bytes, in network byte order
177
178 @return The address as an array of bytes.
179 */
180 bytes_type
181 135 to_bytes() const noexcept
182 {
183 135 return addr_;
184 }
185
186 /** Return the address as a string.
187
188 The returned string does not
189 contain surrounding square brackets.
190
191 When called with no arguments, the
192 return type is `std::string`.
193 Otherwise, the return type and style
194 of output is determined by which string
195 token is passed.
196
197 @par Example
198 @code
199 ipv6_address::bytes_type b = {{
200 0, 1, 0, 2, 0, 3, 0, 4,
201 0, 5, 0, 6, 0, 7, 0, 8 }};
202 ipv6_address a(b);
203 assert(a.to_string() == "1:2:3:4:5:6:7:8");
204 assert( ipv4_address(0x01020304).to_string() == "1.2.3.4" );
205 @endcode
206
207 @par Complexity
208 Constant.
209
210 @par Exception Safety
211 Strong guarantee.
212 Calls to allocate may throw.
213 String tokens may throw exceptions.
214
215 @return The return type of the string token.
216 If the token parameter is omitted, then
217 a new `std::string` is returned.
218 Otherwise, the function return type
219 is the result type of the token.
220
221 @param token An optional string token.
222
223 @par Specification
224 @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.2">
225 2.2. Text Representation of Addresses (rfc4291)</a>
226 */
227 template<BOOST_URL_STRTOK_TPARAM>
228 BOOST_URL_STRTOK_RETURN
229 39 to_string(
230 BOOST_URL_STRTOK_ARG(token)) const
231 {
232 39 to_string_impl(token);
233 39 return token.result();
234 }
235
236 /** Write a dotted decimal string representing the address to a buffer
237
238 The resulting buffer is not null-terminated.
239
240 @throw std::length_error `dest_size < ipv6_address::max_str_len`
241
242 @return The formatted string
243
244 @param dest The buffer in which to write,
245 which must have at least `dest_size` space.
246
247 @param dest_size The size of the output buffer.
248 */
249 BOOST_URL_DECL
250 core::string_view
251 to_buffer(
252 char* dest,
253 std::size_t dest_size) const;
254
255 /** Return true if the address is unspecified
256
257 The address 0:0:0:0:0:0:0:0 is called the
258 unspecified address. It indicates the
259 absence of an address.
260
261 @return `true` if the address is unspecified
262
263 @par Specification
264 @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.2">
265 2.5.2. The Unspecified Address (rfc4291)</a>
266 */
267 BOOST_URL_DECL
268 bool
269 is_unspecified() const noexcept;
270
271 /** Return true if the address is a loopback address
272
273 The unicast address 0:0:0:0:0:0:0:1 is called
274 the loopback address. It may be used by a node
275 to send an IPv6 packet to itself.
276
277 @return `true` if the address is a loopback address
278
279 @par Specification
280 @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.3">
281 2.5.3. The Loopback Address (rfc4291)</a>
282 */
283 BOOST_URL_DECL
284 bool
285 is_loopback() const noexcept;
286
287 /** Return true if the address is a mapped IPv4 address
288
289 This address type is used to represent the
290 addresses of IPv4 nodes as IPv6 addresses.
291
292 @return `true` if the address is a mapped IPv4 address
293
294 @par Specification
295 @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.2">
296 2.5.5.2. IPv4-Mapped IPv6 Address (rfc4291)</a>
297 */
298 BOOST_URL_DECL
299 bool
300 is_v4_mapped() const noexcept;
301
302 /** Return true if two addresses are equal
303
304 @param a1 The first address to compare.
305 @param a2 The second address to compare.
306 @return `true` if the addresses are equal
307 */
308 friend
309 bool
310 81 operator==(
311 ipv6_address const& a1,
312 ipv6_address const& a2) noexcept
313 {
314 81 return a1.addr_ == a2.addr_;
315 }
316
317 /** Return true if two addresses are not equal
318
319 @param a1 The first address to compare.
320 @param a2 The second address to compare.
321 @return `true` if the addresses are not equal
322 */
323 friend
324 bool
325 4 operator!=(
326 ipv6_address const& a1,
327 ipv6_address const& a2) noexcept
328 {
329 4 return !( a1 == a2 );
330 }
331
332 /** Return an address object that represents the loopback address
333
334 The unicast address 0:0:0:0:0:0:0:1 is called
335 the loopback address. It may be used by a node
336 to send an IPv6 packet to itself.
337
338 @par Specification
339 @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.3">
340 2.5.3. The Loopback Address (rfc4291)</a>
341
342 @return The loopback address.
343 */
344 BOOST_URL_DECL
345 static
346 ipv6_address
347 loopback() noexcept;
348
349 /** Format the address to an output stream
350
351 This function writes the address to an
352 output stream using standard notation.
353
354 @return The output stream, for chaining.
355
356 @param os The output stream to write to.
357
358 @param addr The address to write.
359 */
360 friend
361 std::ostream&
362 1 operator<<(
363 std::ostream& os,
364 ipv6_address const& addr)
365 {
366 1 addr.write_ostream(os);
367 1 return os;
368 }
369
370 private:
371 BOOST_URL_DECL void write_ostream(std::ostream&) const;
372
373 BOOST_URL_DECL
374 std::size_t
375 print_impl(
376 char* dest) const noexcept;
377
378 BOOST_URL_DECL
379 void
380 to_string_impl(
381 string_token::arg& t) const;
382
383 bytes_type addr_{{}};
384 };
385
386 //------------------------------------------------
387
388 /** Parse a string containing an IPv6 address.
389
390 This function attempts to parse the string
391 as an IPv6 address and returns a result
392 containing the address upon success, or
393 an error code if the string does not contain
394 a valid IPv6 address.
395
396 @par Exception Safety
397 Throws nothing.
398
399 @return A result containing the address.
400
401 @param s The string to parse.
402 */
403 BOOST_URL_DECL
404 system::result<ipv6_address>
405 parse_ipv6_address(
406 core::string_view s) noexcept;
407
408 } // urls
409 } // boost
410
411 #endif
412