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