LCOV - code coverage report
Current view: top level - include/boost/corosio - endpoint.hpp (source / functions) Coverage Total Hit Missed
Test: coverage_remapped.info Lines: 94.3 % 53 50 3
Test Date: 2026-02-16 16:21:08 Functions: 100.0 % 12 12

           TLA  Line data    Source code
       1                 : //
       2                 : // Copyright (c) 2026 Vinnie Falco (vinnie.falco@gmail.com)
       3                 : //
       4                 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
       5                 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
       6                 : //
       7                 : // Official repository: https://github.com/cppalliance/corosio
       8                 : //
       9                 : 
      10                 : #ifndef BOOST_COROSIO_ENDPOINT_HPP
      11                 : #define BOOST_COROSIO_ENDPOINT_HPP
      12                 : 
      13                 : #include <boost/corosio/detail/config.hpp>
      14                 : #include <boost/corosio/detail/except.hpp>
      15                 : #include <boost/corosio/ipv4_address.hpp>
      16                 : #include <boost/corosio/ipv6_address.hpp>
      17                 : 
      18                 : #include <cstdint>
      19                 : #include <string_view>
      20                 : #include <system_error>
      21                 : 
      22                 : namespace boost::corosio {
      23                 : 
      24                 : /** An IP endpoint (address + port) supporting both IPv4 and IPv6.
      25                 : 
      26                 :     This class represents an endpoint for IP communication,
      27                 :     consisting of either an IPv4 or IPv6 address and a port number.
      28                 :     Endpoints are used to specify connection targets and bind addresses.
      29                 : 
      30                 :     The endpoint holds both address types as separate members (not a union),
      31                 :     with a discriminator to track which address type is active.
      32                 : 
      33                 :     @par Thread Safety
      34                 :     Distinct objects: Safe.@n
      35                 :     Shared objects: Safe.
      36                 : 
      37                 :     @par Example
      38                 :     @code
      39                 :     // IPv4 endpoint
      40                 :     endpoint ep4(ipv4_address::loopback(), 8080);
      41                 : 
      42                 :     // IPv6 endpoint
      43                 :     endpoint ep6(ipv6_address::loopback(), 8080);
      44                 : 
      45                 :     // Port only (defaults to IPv4 any address)
      46                 :     endpoint bind_addr(8080);
      47                 : 
      48                 :     // Parse from string
      49                 :     endpoint ep;
      50                 :     if (auto ec = parse_endpoint("192.168.1.1:8080", ep); !ec) {
      51                 :         // use ep
      52                 :     }
      53                 :     @endcode
      54                 : */
      55                 : class endpoint
      56                 : {
      57                 :     ipv4_address v4_address_;
      58                 :     ipv6_address v6_address_;
      59                 :     std::uint16_t port_ = 0;
      60                 :     bool is_v4_ = true;
      61                 : 
      62                 : public:
      63                 :     /** Default constructor.
      64                 : 
      65                 :         Creates an endpoint with the IPv4 any address (0.0.0.0) and port 0.
      66                 :     */
      67 HIT      251289 :     endpoint() noexcept
      68          251289 :         : v4_address_(ipv4_address::any())
      69          251289 :         , v6_address_{}
      70          251289 :         , port_(0)
      71          251289 :         , is_v4_(true)
      72                 :     {
      73          251289 :     }
      74                 : 
      75                 :     /** Construct from IPv4 address and port.
      76                 : 
      77                 :         @param addr The IPv4 address.
      78                 :         @param p The port number in host byte order.
      79                 :     */
      80           28921 :     endpoint(ipv4_address addr, std::uint16_t p) noexcept
      81           28921 :         : v4_address_(addr)
      82           28921 :         , v6_address_{}
      83           28921 :         , port_(p)
      84           28921 :         , is_v4_(true)
      85                 :     {
      86           28921 :     }
      87                 : 
      88                 :     /** Construct from IPv6 address and port.
      89                 : 
      90                 :         @param addr The IPv6 address.
      91                 :         @param p The port number in host byte order.
      92                 :     */
      93              15 :     endpoint(ipv6_address addr, std::uint16_t p) noexcept
      94              15 :         : v4_address_(ipv4_address::any())
      95              15 :         , v6_address_(addr)
      96              15 :         , port_(p)
      97              15 :         , is_v4_(false)
      98                 :     {
      99              15 :     }
     100                 : 
     101                 :     /** Construct from port only.
     102                 : 
     103                 :         Uses the IPv4 any address (0.0.0.0), which binds to all
     104                 :         available network interfaces.
     105                 : 
     106                 :         @param p The port number in host byte order.
     107                 :     */
     108              10 :     explicit endpoint(std::uint16_t p) noexcept
     109              10 :         : v4_address_(ipv4_address::any())
     110              10 :         , v6_address_{}
     111              10 :         , port_(p)
     112              10 :         , is_v4_(true)
     113                 :     {
     114              10 :     }
     115                 : 
     116                 :     /** Construct from an endpoint's address with a different port.
     117                 : 
     118                 :         Creates a new endpoint using the address from an existing
     119                 :         endpoint but with a different port number.
     120                 : 
     121                 :         @param ep The endpoint whose address to use.
     122                 :         @param p The port number in host byte order.
     123                 :     */
     124               2 :     endpoint(endpoint const& ep, std::uint16_t p) noexcept
     125               2 :         : v4_address_(ep.v4_address_)
     126               2 :         , v6_address_(ep.v6_address_)
     127               2 :         , port_(p)
     128               2 :         , is_v4_(ep.is_v4_)
     129                 :     {
     130               2 :     }
     131                 : 
     132                 :     /** Construct from a string.
     133                 : 
     134                 :         Parses an endpoint string in one of the following formats:
     135                 :         @li IPv4 without port: `192.168.1.1`
     136                 :         @li IPv4 with port: `192.168.1.1:8080`
     137                 :         @li IPv6 without port: `::1` or `2001:db8::1`
     138                 :         @li IPv6 with port (bracketed): `[::1]:8080`
     139                 : 
     140                 :         @param s The string to parse.
     141                 : 
     142                 :         @throws std::system_error on parse failure.
     143                 :     */
     144                 :     explicit endpoint(std::string_view s);
     145                 : 
     146                 :     /** Check if this endpoint uses an IPv4 address.
     147                 : 
     148                 :         @return `true` if the endpoint uses IPv4, `false` if IPv6.
     149                 :     */
     150              21 :     bool is_v4() const noexcept
     151                 :     {
     152              21 :         return is_v4_;
     153                 :     }
     154                 : 
     155                 :     /** Check if this endpoint uses an IPv6 address.
     156                 : 
     157                 :         @return `true` if the endpoint uses IPv6, `false` if IPv4.
     158                 :     */
     159              12 :     bool is_v6() const noexcept
     160                 :     {
     161              12 :         return !is_v4_;
     162                 :     }
     163                 : 
     164                 :     /** Get the IPv4 address.
     165                 : 
     166                 :         @return The IPv4 address. The value is valid even if
     167                 :         the endpoint is using IPv6 (it will be the default any address).
     168                 :     */
     169            8499 :     ipv4_address v4_address() const noexcept
     170                 :     {
     171            8499 :         return v4_address_;
     172                 :     }
     173                 : 
     174                 :     /** Get the IPv6 address.
     175                 : 
     176                 :         @return The IPv6 address. The value is valid even if
     177                 :         the endpoint is using IPv4 (it will be the default any address).
     178                 :     */
     179              10 :     ipv6_address v6_address() const noexcept
     180                 :     {
     181              10 :         return v6_address_;
     182                 :     }
     183                 : 
     184                 :     /** Get the port number.
     185                 : 
     186                 :         @return The port number in host byte order.
     187                 :     */
     188            8618 :     std::uint16_t port() const noexcept
     189                 :     {
     190            8618 :         return port_;
     191                 :     }
     192                 : 
     193                 :     /** Compare endpoints for equality.
     194                 : 
     195                 :         Two endpoints are equal if they have the same address type,
     196                 :         the same address value, and the same port.
     197                 : 
     198                 :         @return `true` if both endpoints are equal.
     199                 :     */
     200              54 :     friend bool operator==(endpoint const& a, endpoint const& b) noexcept
     201                 :     {
     202              54 :         if (a.is_v4_ != b.is_v4_)
     203 MIS           0 :             return false;
     204 HIT          54 :         if (a.port_ != b.port_)
     205 MIS           0 :             return false;
     206 HIT          54 :         if (a.is_v4_)
     207              54 :             return a.v4_address_ == b.v4_address_;
     208                 :         else
     209 MIS           0 :             return a.v6_address_ == b.v6_address_;
     210                 :     }
     211                 : 
     212                 :     /** Compare endpoints for inequality.
     213                 : 
     214                 :         @return `true` if endpoints differ.
     215                 :     */
     216                 :     friend bool operator!=(endpoint const& a, endpoint const& b) noexcept
     217                 :     {
     218                 :         return !(a == b);
     219                 :     }
     220                 : };
     221                 : 
     222                 : 
     223                 : /** Endpoint format detection result.
     224                 : 
     225                 :     Used internally by parse_endpoint to determine
     226                 :     the format of an endpoint string.
     227                 : */
     228                 : enum class endpoint_format
     229                 : {
     230                 :     ipv4_no_port,   ///< "192.168.1.1"
     231                 :     ipv4_with_port, ///< "192.168.1.1:8080"
     232                 :     ipv6_no_port,   ///< "::1" or "1:2:3:4:5:6:7:8"
     233                 :     ipv6_bracketed  ///< "[::1]" or "[::1]:8080"
     234                 : };
     235                 : 
     236                 : /** Detect the format of an endpoint string.
     237                 : 
     238                 :     This helper function determines the endpoint format
     239                 :     based on simple rules:
     240                 :     1. Starts with `[` -> `ipv6_bracketed`
     241                 :     2. Else count `:` characters:
     242                 :        - 0 colons -> `ipv4_no_port`
     243                 :        - 1 colon -> `ipv4_with_port`
     244                 :        - 2+ colons -> `ipv6_no_port`
     245                 : 
     246                 :     @param s The string to analyze.
     247                 :     @return The detected endpoint format.
     248                 : */
     249                 : BOOST_COROSIO_DECL
     250                 : endpoint_format detect_endpoint_format(std::string_view s) noexcept;
     251                 : 
     252                 : /** Parse an endpoint from a string.
     253                 : 
     254                 :     This function parses an endpoint string in one of
     255                 :     the following formats:
     256                 : 
     257                 :     @li IPv4 without port: `192.168.1.1`
     258                 :     @li IPv4 with port: `192.168.1.1:8080`
     259                 :     @li IPv6 without port: `::1` or `2001:db8::1`
     260                 :     @li IPv6 with port (bracketed): `[::1]:8080`
     261                 : 
     262                 :     @par Example
     263                 :     @code
     264                 :     endpoint ep;
     265                 :     if (auto ec = parse_endpoint("192.168.1.1:8080", ep); !ec) {
     266                 :         // ep.is_v4() == true
     267                 :         // ep.port() == 8080
     268                 :     }
     269                 : 
     270                 :     if (auto ec = parse_endpoint("[::1]:443", ep); !ec) {
     271                 :         // ep.is_v6() == true
     272                 :         // ep.port() == 443
     273                 :     }
     274                 :     @endcode
     275                 : 
     276                 :     @param s The string to parse.
     277                 :     @param ep The endpoint to store the result.
     278                 :     @return An error code (empty on success).
     279                 : */
     280                 : [[nodiscard]] BOOST_COROSIO_DECL std::error_code
     281                 : parse_endpoint(std::string_view s, endpoint& ep) noexcept;
     282                 : 
     283 HIT          24 : inline endpoint::endpoint(std::string_view s)
     284                 : {
     285              24 :     auto ec = parse_endpoint(s, *this);
     286              24 :     if (ec)
     287              15 :         detail::throw_system_error(ec);
     288               9 : }
     289                 : 
     290                 : } // namespace boost::corosio
     291                 : 
     292                 : #endif
        

Generated by: LCOV version 2.3