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