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