ipv6_address.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. //
  2. // Copyright (c) 2019 Vinnie Falco ([email protected])
  3. // Copyright (c) 2022 Alan de Freitas ([email protected])
  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. #ifndef BOOST_URL_DOCS
  23. class ipv4_address;
  24. #endif
  25. /** An IP version 6 style address.
  26. Objects of this type are used to construct,
  27. parse, and manipulate IP version 6 addresses.
  28. @par BNF
  29. @code
  30. IPv6address = 6( h16 ":" ) ls32
  31. / "::" 5( h16 ":" ) ls32
  32. / [ h16 ] "::" 4( h16 ":" ) ls32
  33. / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
  34. / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
  35. / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
  36. / [ *4( h16 ":" ) h16 ] "::" ls32
  37. / [ *5( h16 ":" ) h16 ] "::" h16
  38. / [ *6( h16 ":" ) h16 ] "::"
  39. ls32 = ( h16 ":" h16 ) / IPv4address
  40. ; least-significant 32 bits of address
  41. h16 = 1*4HEXDIG
  42. ; 16 bits of address represented in hexadecimal
  43. @endcode
  44. @par Specification
  45. @li <a href="https://datatracker.ietf.org/doc/html/rfc4291"
  46. >IP Version 6 Addressing Architecture (rfc4291)</a>
  47. @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2"
  48. >3.2.2. Host (rfc3986)</a>
  49. @see
  50. @ref ipv4_address,
  51. @ref parse_ipv6_address.
  52. */
  53. class ipv6_address
  54. {
  55. public:
  56. /** The number of characters in the longest possible IPv6 string.
  57. The longest IPv6 address is:
  58. @code
  59. ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
  60. @endcode
  61. @see
  62. @ref to_buffer.
  63. */
  64. // ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
  65. // ::ffff:255.255.255.255
  66. // 12345678901234567890123456789012345678901234567890
  67. // 1 2 3 4
  68. static
  69. constexpr
  70. std::size_t max_str_len = 49;
  71. /** The type used to represent an address as an array of bytes.
  72. Octets are stored in network byte order.
  73. */
  74. using bytes_type = std::array<
  75. unsigned char, 16>;
  76. /** Constructor.
  77. Default constructed objects represent
  78. the unspecified address.
  79. @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.2"
  80. >2.5.2. The Unspecified Address</a>
  81. @see
  82. @ref is_unspecified
  83. */
  84. ipv6_address() = default;
  85. /** Constructor.
  86. */
  87. ipv6_address(
  88. ipv6_address const&) = default;
  89. /** Copy Assignment
  90. */
  91. ipv6_address&
  92. operator=(
  93. ipv6_address const&) = default;
  94. /** Construct from an array of bytes.
  95. This function constructs an address
  96. from the array in `bytes`, which is
  97. interpreted in big-endian.
  98. @param bytes The value to construct from.
  99. */
  100. BOOST_URL_DECL
  101. ipv6_address(
  102. bytes_type const& bytes) noexcept;
  103. /** Construct from an IPv4 address.
  104. This function constructs an IPv6 address
  105. from the IPv4 address `addr`. The resulting
  106. address is an IPv4-Mapped IPv6 Address.
  107. @param addr The address to construct from.
  108. @par Specification
  109. @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.2"
  110. >2.5.5.2. IPv4-Mapped IPv6 Address (rfc4291)</a>
  111. */
  112. BOOST_URL_DECL
  113. ipv6_address(
  114. ipv4_address const& addr) noexcept;
  115. /** Construct from a string.
  116. This function constructs an address from
  117. the string `s`, which must contain a valid
  118. IPv6 address string or else an exception
  119. is thrown.
  120. @note For a non-throwing parse function,
  121. use @ref parse_ipv6_address.
  122. @par Exception Safety
  123. Exceptions thrown on invalid input.
  124. @throw system_error
  125. The input failed to parse correctly.
  126. @param s The string to parse.
  127. @par Specification
  128. @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2"
  129. >3.2.2. Host (rfc3986)</a>
  130. @see
  131. @ref parse_ipv6_address.
  132. */
  133. BOOST_URL_DECL
  134. ipv6_address(
  135. core::string_view s);
  136. /** Return the address as bytes, in network byte order
  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. @par Specification
  202. @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.2">
  203. 2.5.2. The Unspecified Address (rfc4291)</a>
  204. */
  205. BOOST_URL_DECL
  206. bool
  207. is_unspecified() const noexcept;
  208. /** Return true if the address is a loopback address
  209. The unicast address 0:0:0:0:0:0:0:1 is called
  210. the loopback address. It may be used by a node
  211. to send an IPv6 packet to itself.
  212. @par Specification
  213. @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.3">
  214. 2.5.3. The Loopback Address (rfc4291)</a>
  215. */
  216. BOOST_URL_DECL
  217. bool
  218. is_loopback() const noexcept;
  219. /** Return true if the address is a mapped IPv4 address
  220. This address type is used to represent the
  221. addresses of IPv4 nodes as IPv6 addresses.
  222. @par Specification
  223. @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.2">
  224. 2.5.5.2. IPv4-Mapped IPv6 Address (rfc4291)</a>
  225. */
  226. BOOST_URL_DECL
  227. bool
  228. is_v4_mapped() const noexcept;
  229. /** Return true if two addresses are equal
  230. */
  231. friend
  232. bool
  233. operator==(
  234. ipv6_address const& a1,
  235. ipv6_address const& a2) noexcept
  236. {
  237. return a1.addr_ == a2.addr_;
  238. }
  239. /** Return true if two addresses are not equal
  240. */
  241. friend
  242. bool
  243. operator!=(
  244. ipv6_address const& a1,
  245. ipv6_address const& a2) noexcept
  246. {
  247. return !( a1 == a2 );
  248. }
  249. /** Return an address object that represents the loopback address
  250. The unicast address 0:0:0:0:0:0:0:1 is called
  251. the loopback address. It may be used by a node
  252. to send an IPv6 packet to itself.
  253. @par Specification
  254. @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.3">
  255. 2.5.3. The Loopback Address (rfc4291)</a>
  256. */
  257. BOOST_URL_DECL
  258. static
  259. ipv6_address
  260. loopback() noexcept;
  261. // hidden friend
  262. friend
  263. std::ostream&
  264. operator<<(
  265. std::ostream& os,
  266. ipv6_address const& addr)
  267. {
  268. char buf[ipv6_address::max_str_len];
  269. auto const s = addr.to_buffer(
  270. buf, sizeof(buf));
  271. os << s;
  272. return os;
  273. }
  274. private:
  275. BOOST_URL_DECL
  276. std::size_t
  277. print_impl(
  278. char* dest) const noexcept;
  279. BOOST_URL_DECL
  280. void
  281. to_string_impl(
  282. string_token::arg& t) const;
  283. bytes_type addr_{{}};
  284. };
  285. /** Format the address to an output stream
  286. This function writes the address to an
  287. output stream using standard notation.
  288. @return The output stream, for chaining.
  289. @param os The output stream to write to.
  290. @param addr The address to write.
  291. */
  292. std::ostream&
  293. operator<<(
  294. std::ostream& os,
  295. ipv6_address const& addr);
  296. //------------------------------------------------
  297. /** Parse a string containing an IPv6 address.
  298. This function attempts to parse the string
  299. as an IPv6 address and returns a result
  300. containing the address upon success, or
  301. an error code if the string does not contain
  302. a valid IPv6 address.
  303. @par Exception Safety
  304. Throws nothing.
  305. @return A result containing the address.
  306. @param s The string to parse.
  307. */
  308. BOOST_URL_DECL
  309. system::result<ipv6_address>
  310. parse_ipv6_address(
  311. core::string_view s) noexcept;
  312. } // urls
  313. } // boost
  314. #endif