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