include/boost/corosio/endpoint.hpp

100.0% Lines (32 / 32) 100.0% Functions (12 / 12)
endpoint.hpp
f(x) Functions (12)
Line TLA Hits Source Code
1 //
2 // Copyright (c) 2026 Vinnie Falco (vinnie.falco@gmail.com)
3 // Copyright (c) 2026 Michael Vandeberg
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/cppalliance/corosio
9 //
10
11 #ifndef BOOST_COROSIO_ENDPOINT_HPP
12 #define BOOST_COROSIO_ENDPOINT_HPP
13
14 #include <boost/corosio/detail/config.hpp>
15 #include <boost/corosio/detail/except.hpp>
16 #include <boost/corosio/ip_address.hpp>
17
18 #include <boost/capy/results.hpp>
19
20 #include <compare>
21 #include <cstdint>
22 #include <string_view>
23 #include <system_error>
24
25 namespace boost::corosio {
26
27 /** Pairs an IP address with a port for either IPv4 or IPv6.
28
29 This class represents an endpoint for IP communication,
30 consisting of an IP address of either family and a port number.
31 Use an endpoint to specify a connection target or bind address.
32
33 @par Thread Safety
34 Distinct objects: Safe.@n
35 Shared objects: Safe.
36
37 @par Example
38 @par !example endpoint
39 */
40 class endpoint
41 {
42 ip_address addr_;
43 std::uint16_t port_ = 0;
44
45 public:
46 /** Creates an endpoint with the IPv4 any address (0.0.0.0) and port 0.
47 */
48 258764x endpoint() noexcept = default;
49
50 /** Construct from an IP address and port.
51
52 `ipv4_address` and `ipv6_address` arguments convert
53 implicitly, so both families construct directly:
54 `endpoint(ipv4_address::loopback(), 80)`.
55
56 @param addr The IP address.
57 @param p The port number in host byte order.
58 */
59 34396x endpoint(ip_address addr, std::uint16_t p) noexcept : addr_(addr), port_(p)
60 {
61 34396x }
62
63 /** Construct from port only.
64
65 Uses the IPv4 any address (0.0.0.0), which binds to all
66 available network interfaces.
67
68 @param p The port number in host byte order.
69 */
70 22x explicit endpoint(std::uint16_t p) noexcept : port_(p) {}
71
72 /** Construct from an endpoint's address with a different port.
73
74 Creates a new endpoint using the address from an existing
75 endpoint but with a different port number.
76
77 @param ep The endpoint whose address to use.
78 @param p The port number in host byte order.
79 */
80 2x endpoint(endpoint const& ep, std::uint16_t p) noexcept
81 2x : addr_(ep.addr_)
82 2x , port_(p)
83 {
84 2x }
85
86 /** Construct from a string.
87
88 Parses an endpoint string in one of the following formats:
89 @li IPv4 without port: `192.168.1.1`
90 @li IPv4 with port: `192.168.1.1:8080`
91 @li IPv6 without port: `::1` or `2001:db8::1`
92 @li IPv6 with port (bracketed): `[::1]:8080`
93
94 @ref make_endpoint is the non-throwing form.
95
96 @param s The string to parse.
97
98 @throws std::system_error on parse failure.
99
100 @see @ref make_endpoint
101 */
102 explicit endpoint(std::string_view s);
103
104 /** Check if this endpoint uses an IPv4 address.
105
106 @return `true` if the endpoint uses IPv4, `false` if IPv6.
107 */
108 18324x bool is_v4() const noexcept
109 {
110 18324x return addr_.is_v4();
111 }
112
113 /** Check if this endpoint uses an IPv6 address.
114
115 @return `true` if the endpoint uses IPv6, `false` if IPv4.
116 */
117 61x bool is_v6() const noexcept
118 {
119 61x return addr_.is_v6();
120 }
121
122 /** Return the IP address.
123
124 @return The endpoint's address.
125 */
126 10958x ip_address address() const noexcept
127 {
128 10958x return addr_;
129 }
130
131 /** Return the port number.
132
133 @return The port number in host byte order.
134 */
135 11628x std::uint16_t port() const noexcept
136 {
137 11628x return port_;
138 }
139
140 /** Compare endpoints for equality.
141
142 Two endpoints are equal if they have the same address type,
143 the same address value, and the same port.
144
145 @return `true` if both endpoints are equal.
146 */
147 118x friend bool operator==(endpoint const& a, endpoint const& b) noexcept
148 {
149 118x return a.port_ == b.port_ && a.addr_ == b.addr_;
150 }
151
152 /** Order two endpoints.
153
154 Establishes a strict total ordering consistent with
155 @ref operator==: equal endpoints compare equivalent.
156 `operator<=>` orders endpoints first by address family
157 (IPv4 before IPv6), then by address value, then by port. This
158 makes `endpoint` usable as a key in ordered containers
159 such as `std::map` and `std::set`.
160
161 @return The relative order of @p a and @p b.
162 */
163 friend std::strong_ordering
164 25x operator<=>(endpoint const& a, endpoint const& b) noexcept
165 {
166 25x if (auto c = a.addr_ <=> b.addr_; c != 0)
167 12x return c;
168 13x return a.port_ <=> b.port_;
169 }
170 };
171
172 /** Identifies which of the four supported endpoint string formats a string is in.
173
174 Used internally by `make_endpoint` to determine
175 the format of an endpoint string.
176 */
177 enum class endpoint_format
178 {
179 ipv4_no_port, ///< "192.168.1.1"
180 ipv4_with_port, ///< "192.168.1.1:8080"
181 ipv6_no_port, ///< "::1" or "1:2:3:4:5:6:7:8"
182 ipv6_bracketed ///< "[::1]" or "[::1]:8080"
183 };
184
185 /** Detect the format of an endpoint string.
186
187 This helper function determines the endpoint format
188 based on simple rules:
189 1. Starts with `[` -> `ipv6_bracketed`
190 2. Else count `:` characters:
191 - 0 colons -> `ipv4_no_port`
192 - 1 colon -> `ipv4_with_port`
193 - 2+ colons -> `ipv6_no_port`
194
195 @param s The string to analyze.
196 @return The detected endpoint format.
197 */
198 BOOST_COROSIO_DECL
199 endpoint_format detect_endpoint_format(std::string_view s) noexcept;
200
201 /** Create an endpoint from a string.
202
203 This function parses an endpoint string in one of
204 the following formats:
205
206 @li IPv4 without port: `192.168.1.1`
207 @li IPv4 with port: `192.168.1.1:8080`
208 @li IPv6 without port: `::1` or `2001:db8::1`
209 @li IPv6 with port (bracketed): `[::1]:8080`
210
211 @par Example
212 @par !example make_endpoint
213
214 @param s The string to parse.
215 @return The error code, empty on success, and the parsed
216 endpoint — default-constructed on failure.
217 */
218 [[nodiscard]] BOOST_COROSIO_DECL capy::results<endpoint>
219 make_endpoint(std::string_view s) noexcept;
220
221 27x inline endpoint::endpoint(std::string_view s)
222 {
223 27x auto [ec, ep] = make_endpoint(s);
224 27x if (ec)
225 16x detail::throw_system_error(ec);
226 11x *this = ep;
227 11x }
228
229 } // namespace boost::corosio
230
231 namespace std {
232
233 /// Hash support for `boost::corosio::endpoint`.
234 template<>
235 struct hash<boost::corosio::endpoint>
236 {
237 /// Return the hash of `ep`.
238 12x std::size_t operator()(boost::corosio::endpoint const& ep) const noexcept
239 {
240 12x std::size_t const h1 = hash<boost::corosio::ip_address>()(ep.address());
241 12x std::size_t const h2 = hash<std::uint16_t>()(ep.port());
242 12x return h1 ^ (h2 + 0x9e3779b9 + (h1 << 6) + (h1 >> 2));
243 }
244 };
245
246 } // namespace std
247
248 #endif
249