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/io_result.hpp>
19
20 #include <compare>
21 #include <cstdint>
22 #include <string_view>
23 #include <system_error>
24
25 namespace boost::corosio {
26
27 /** An IP endpoint (address + port) supporting both IPv4 and 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 Endpoints are used to specify connection targets and bind addresses.
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 /** Default constructor.
47
48 Creates an endpoint with the IPv4 any address (0.0.0.0) and port 0.
49 */
50 140271x endpoint() noexcept = default;
51
52 /** Construct from an IP address and port.
53
54 `ipv4_address` and `ipv6_address` arguments convert
55 implicitly, so both families construct directly:
56 `endpoint(ipv4_address::loopback(), 80)`.
57
58 @param addr The IP address.
59 @param p The port number in host byte order.
60 */
61 14848x endpoint(ip_address addr, std::uint16_t p) noexcept : addr_(addr), port_(p)
62 {
63 14848x }
64
65 /** Construct from port only.
66
67 Uses the IPv4 any address (0.0.0.0), which binds to all
68 available network interfaces.
69
70 @param p The port number in host byte order.
71 */
72 22x explicit endpoint(std::uint16_t p) noexcept : port_(p) {}
73
74 /** Construct from an endpoint's address with a different port.
75
76 Creates a new endpoint using the address from an existing
77 endpoint but with a different port number.
78
79 @param ep The endpoint whose address to use.
80 @param p The port number in host byte order.
81 */
82 2x endpoint(endpoint const& ep, std::uint16_t p) noexcept
83 2x : addr_(ep.addr_)
84 2x , port_(p)
85 {
86 2x }
87
88 /** Construct from a string.
89
90 Parses an endpoint string in one of the following formats:
91 @li IPv4 without port: `192.168.1.1`
92 @li IPv4 with port: `192.168.1.1:8080`
93 @li IPv6 without port: `::1` or `2001:db8::1`
94 @li IPv6 with port (bracketed): `[::1]:8080`
95
96 @param s The string to parse.
97
98 @throws std::system_error on parse failure.
99
100 @see make_endpoint for the non-throwing form.
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 10002x bool is_v4() const noexcept
109 {
110 10002x 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 5564x ip_address address() const noexcept
127 {
128 5564x return addr_;
129 }
130
131 /** Return the port number.
132
133 @return The port number in host byte order.
134 */
135 5967x std::uint16_t port() const noexcept
136 {
137 5967x 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 102x friend bool operator==(endpoint const& a, endpoint const& b) noexcept
148 {
149 102x 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 Endpoints are ordered first by address family (IPv4
157 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 /** Endpoint format detection result.
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::io_result<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