LCOV - code coverage report
Current view: top level - corosio - endpoint.hpp (source / functions) Coverage Total Hit
Test: coverage_remapped.info Lines: 100.0 % 32 32
Test Date: 2026-09-25 22:49:29 Functions: 100.0 % 12 12

           TLA  Line data    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 HIT      140271 :     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           14848 :     endpoint(ip_address addr, std::uint16_t p) noexcept : addr_(addr), port_(p)
      62                 :     {
      63           14848 :     }
      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              22 :     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               2 :     endpoint(endpoint const& ep, std::uint16_t p) noexcept
      83               2 :         : addr_(ep.addr_)
      84               2 :         , port_(p)
      85                 :     {
      86               2 :     }
      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           10002 :     bool is_v4() const noexcept
     109                 :     {
     110           10002 :         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              61 :     bool is_v6() const noexcept
     118                 :     {
     119              61 :         return addr_.is_v6();
     120                 :     }
     121                 : 
     122                 :     /** Return the IP address.
     123                 : 
     124                 :         @return The endpoint's address.
     125                 :     */
     126            5564 :     ip_address address() const noexcept
     127                 :     {
     128            5564 :         return addr_;
     129                 :     }
     130                 : 
     131                 :     /** Return the port number.
     132                 : 
     133                 :         @return The port number in host byte order.
     134                 :     */
     135            5967 :     std::uint16_t port() const noexcept
     136                 :     {
     137            5967 :         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             102 :     friend bool operator==(endpoint const& a, endpoint const& b) noexcept
     148                 :     {
     149             102 :         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              25 :     operator<=>(endpoint const& a, endpoint const& b) noexcept
     165                 :     {
     166              25 :         if (auto c = a.addr_ <=> b.addr_; c != 0)
     167              12 :             return c;
     168              13 :         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              27 : inline endpoint::endpoint(std::string_view s)
     222                 : {
     223              27 :     auto [ec, ep] = make_endpoint(s);
     224              27 :     if (ec)
     225              16 :         detail::throw_system_error(ec);
     226              11 :     *this = ep;
     227              11 : }
     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              12 :     std::size_t operator()(boost::corosio::endpoint const& ep) const noexcept
     239                 :     {
     240              12 :         std::size_t const h1 = hash<boost::corosio::ip_address>()(ep.address());
     241              12 :         std::size_t const h2 = hash<std::uint16_t>()(ep.port());
     242              12 :         return h1 ^ (h2 + 0x9e3779b9 + (h1 << 6) + (h1 >> 2));
     243                 :     }
     244                 : };
     245                 : 
     246                 : } // namespace std
     247                 : 
     248                 : #endif
        

Generated by: LCOV version 2.3