include/boost/corosio/endpoint.hpp

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