ipv4_address.hpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  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_IPV4_ADDRESS_HPP
  11. #define BOOST_URL_IPV4_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 <string>
  18. #include <array>
  19. #include <cstdint>
  20. #include <iosfwd>
  21. namespace boost {
  22. namespace urls {
  23. /** An IP version 4 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. IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
  29. dec-octet = DIGIT ; 0-9
  30. / %x31-39 DIGIT ; 10-99
  31. / "1" 2DIGIT ; 100-199
  32. / "2" %x30-34 DIGIT ; 200-249
  33. / "25" %x30-35 ; 250-255
  34. @endcode
  35. @par Specification
  36. @li <a href="https://en.wikipedia.org/wiki/IPv4"
  37. >IPv4 (Wikipedia)</a>
  38. @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2"
  39. >3.2.2. Host (rfc3986)</a>
  40. @see
  41. @ref parse_ipv4_address,
  42. @ref ipv6_address.
  43. */
  44. class ipv4_address
  45. {
  46. public:
  47. /** The number of characters in the longest possible IPv4 string.
  48. The longest ipv4 address string is "255.255.255.255".
  49. */
  50. static
  51. constexpr
  52. std::size_t max_str_len = 15;
  53. /** The type used to represent an address as an unsigned integer
  54. */
  55. using uint_type =
  56. std::uint_least32_t;
  57. /** The type used to represent an address as an array of bytes
  58. */
  59. using bytes_type =
  60. std::array<unsigned char, 4>;
  61. /** Constructor.
  62. */
  63. ipv4_address() = default;
  64. /** Constructor.
  65. */
  66. ipv4_address(
  67. ipv4_address const&) = default;
  68. /** Copy Assignment.
  69. */
  70. ipv4_address&
  71. operator=(
  72. ipv4_address const&) = default;
  73. //
  74. //---
  75. //
  76. /** Construct from an unsigned integer.
  77. This function constructs an address from
  78. the unsigned integer `u`, where the most
  79. significant byte forms the first octet
  80. of the resulting address.
  81. @param u The integer to construct from.
  82. */
  83. BOOST_URL_DECL
  84. explicit
  85. ipv4_address(
  86. uint_type u) noexcept;
  87. /** Construct from an array of bytes.
  88. This function constructs an address
  89. from the array in `bytes`, which is
  90. interpreted in big-endian.
  91. @param bytes The value to construct from.
  92. */
  93. BOOST_URL_DECL
  94. explicit
  95. ipv4_address(
  96. bytes_type const& bytes) noexcept;
  97. /** Construct from a string.
  98. This function constructs an address from
  99. the string `s`, which must contain a valid
  100. IPv4 address string or else an exception
  101. is thrown.
  102. @note For a non-throwing parse function,
  103. use @ref parse_ipv4_address.
  104. @par Exception Safety
  105. Exceptions thrown on invalid input.
  106. @throw system_error
  107. The input failed to parse correctly.
  108. @param s The string to parse.
  109. @par Specification
  110. @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2"
  111. >3.2.2. Host (rfc3986)</a>
  112. @see
  113. @ref parse_ipv4_address.
  114. */
  115. BOOST_URL_DECL
  116. explicit
  117. ipv4_address(
  118. core::string_view s);
  119. /** Return the address as bytes, in network byte order.
  120. */
  121. BOOST_URL_DECL
  122. bytes_type
  123. to_bytes() const noexcept;
  124. /** Return the address as an unsigned integer.
  125. */
  126. BOOST_URL_DECL
  127. uint_type
  128. to_uint() const noexcept;
  129. /** Return the address as a string in dotted decimal format
  130. When called with no arguments, the
  131. return type is `std::string`.
  132. Otherwise, the return type and style
  133. of output is determined by which string
  134. token is passed.
  135. @par Example
  136. @code
  137. assert( ipv4_address(0x01020304).to_string() == "1.2.3.4" );
  138. @endcode
  139. @par Complexity
  140. Constant.
  141. @par Exception Safety
  142. Strong guarantee.
  143. Calls to allocate may throw.
  144. String tokens may throw exceptions.
  145. @return The return type of the string token.
  146. If the token parameter is omitted, then
  147. a new `std::string` is returned.
  148. Otherwise, the function return type
  149. is the result type of the token.
  150. @param token An optional string token.
  151. @par Specification
  152. @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.2">
  153. 2.2. Text Representation of Addresses (rfc4291)</a>
  154. */
  155. template<BOOST_URL_STRTOK_TPARAM>
  156. BOOST_URL_STRTOK_RETURN
  157. to_string(
  158. BOOST_URL_STRTOK_ARG(token)) const
  159. {
  160. to_string_impl(token);
  161. return token.result();
  162. }
  163. /** Write a dotted decimal string representing the address to a buffer
  164. The resulting buffer is not null-terminated.
  165. @throw std::length_error `dest_size < ipv4_address::max_str_len`
  166. @return The formatted string
  167. @param dest The buffer in which to write,
  168. which must have at least `dest_size` space.
  169. @param dest_size The size of the output buffer.
  170. */
  171. BOOST_URL_DECL
  172. core::string_view
  173. to_buffer(
  174. char* dest,
  175. std::size_t dest_size) const;
  176. /** Return true if the address is a loopback address
  177. */
  178. BOOST_URL_DECL
  179. bool
  180. is_loopback() const noexcept;
  181. /** Return true if the address is unspecified
  182. */
  183. BOOST_URL_DECL
  184. bool
  185. is_unspecified() const noexcept;
  186. /** Return true if the address is a multicast address
  187. */
  188. BOOST_URL_DECL
  189. bool
  190. is_multicast() const noexcept;
  191. /** Return true if two addresses are equal
  192. */
  193. friend
  194. bool
  195. operator==(
  196. ipv4_address const& a1,
  197. ipv4_address const& a2) noexcept
  198. {
  199. return a1.addr_ == a2.addr_;
  200. }
  201. /** Return true if two addresses are not equal
  202. */
  203. friend
  204. bool
  205. operator!=(
  206. ipv4_address const& a1,
  207. ipv4_address const& a2) noexcept
  208. {
  209. return a1.addr_ != a2.addr_;
  210. }
  211. /** Return an address object that represents any address
  212. */
  213. static
  214. ipv4_address
  215. any() noexcept
  216. {
  217. return ipv4_address();
  218. }
  219. /** Return an address object that represents the loopback address
  220. */
  221. static
  222. ipv4_address
  223. loopback() noexcept
  224. {
  225. return ipv4_address(0x7F000001);
  226. }
  227. /** Return an address object that represents the broadcast address
  228. */
  229. static
  230. ipv4_address
  231. broadcast() noexcept
  232. {
  233. return ipv4_address(0xFFFFFFFF);
  234. }
  235. // hidden friend
  236. friend
  237. std::ostream&
  238. operator<<(
  239. std::ostream& os,
  240. ipv4_address const& addr)
  241. {
  242. char buf[ipv4_address::max_str_len];
  243. os << addr.to_buffer(buf, sizeof(buf));
  244. return os;
  245. }
  246. private:
  247. friend class ipv6_address;
  248. BOOST_URL_DECL
  249. std::size_t
  250. print_impl(
  251. char* dest) const noexcept;
  252. BOOST_URL_DECL
  253. void
  254. to_string_impl(
  255. string_token::arg& t) const;
  256. uint_type addr_ = 0;
  257. };
  258. /** Format the address to an output stream.
  259. IPv4 addresses written to output streams
  260. are written in their dotted decimal format.
  261. @param os The output stream.
  262. @param addr The address to format.
  263. */
  264. std::ostream&
  265. operator<<(
  266. std::ostream& os,
  267. ipv4_address const& addr);
  268. //------------------------------------------------
  269. /** Return an IPv4 address from an IP address string in dotted decimal form
  270. */
  271. BOOST_URL_DECL
  272. system::result<ipv4_address>
  273. parse_ipv4_address(
  274. core::string_view s) noexcept;
  275. } // urls
  276. } // boost
  277. #endif