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