ipv6_address.hpp 11 KB

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