Line data 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
|