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

Generated by: LCOV version 2.3