LCOV - code coverage report
Current view: top level - /jenkins/workspace/boost-root/boost/corosio - endpoint.hpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 94.3 % 53 50
Test Date: 2026-02-04 16:37:34 Functions: 100.0 % 12 12

            Line data    Source code
       1              : //
       2              : // Copyright (c) 2026 Vinnie Falco (vinnie dot falco at gmail dot 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        78907 :     endpoint() noexcept
      68        78907 :         : v4_address_(ipv4_address::any())
      69        78907 :         , v6_address_{}
      70        78907 :         , port_(0)
      71        78907 :         , is_v4_(true)
      72              :     {
      73        78907 :     }
      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        19804 :     endpoint(ipv4_address addr, std::uint16_t p) noexcept
      81        19804 :         : v4_address_(addr)
      82        19804 :         , v6_address_{}
      83        19804 :         , port_(p)
      84        19804 :         , is_v4_(true)
      85              :     {
      86        19804 :     }
      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         5025 :     ipv4_address v4_address() const noexcept
     170              :     {
     171         5025 :         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         5072 :     std::uint16_t port() const noexcept
     189              :     {
     190         5072 :         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            0 :             return false;
     204           54 :         if (a.port_ != b.port_)
     205            0 :             return false;
     206           54 :         if (a.is_v4_)
     207           54 :             return a.v4_address_ == b.v4_address_;
     208              :         else
     209            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              : 
     224              : /** Endpoint format detection result.
     225              : 
     226              :     Used internally by parse_endpoint to determine
     227              :     the format of an endpoint string.
     228              : */
     229              : enum class endpoint_format
     230              : {
     231              :     ipv4_no_port,      ///< "192.168.1.1"
     232              :     ipv4_with_port,    ///< "192.168.1.1:8080"
     233              :     ipv6_no_port,      ///< "::1" or "1:2:3:4:5:6:7:8"
     234              :     ipv6_bracketed     ///< "[::1]" or "[::1]:8080"
     235              : };
     236              : 
     237              : /** Detect the format of an endpoint string.
     238              : 
     239              :     This helper function determines the endpoint format
     240              :     based on simple rules:
     241              :     1. Starts with `[` -> `ipv6_bracketed`
     242              :     2. Else count `:` characters:
     243              :        - 0 colons -> `ipv4_no_port`
     244              :        - 1 colon -> `ipv4_with_port`
     245              :        - 2+ colons -> `ipv6_no_port`
     246              : 
     247              :     @param s The string to analyze.
     248              :     @return The detected endpoint format.
     249              : */
     250              : BOOST_COROSIO_DECL
     251              : endpoint_format
     252              : detect_endpoint_format(std::string_view s) noexcept;
     253              : 
     254              : /** Parse an endpoint from a string.
     255              : 
     256              :     This function parses an endpoint string in one of
     257              :     the following formats:
     258              : 
     259              :     @li IPv4 without port: `192.168.1.1`
     260              :     @li IPv4 with port: `192.168.1.1:8080`
     261              :     @li IPv6 without port: `::1` or `2001:db8::1`
     262              :     @li IPv6 with port (bracketed): `[::1]:8080`
     263              : 
     264              :     @par Example
     265              :     @code
     266              :     endpoint ep;
     267              :     if (auto ec = parse_endpoint("192.168.1.1:8080", ep); !ec) {
     268              :         // ep.is_v4() == true
     269              :         // ep.port() == 8080
     270              :     }
     271              : 
     272              :     if (auto ec = parse_endpoint("[::1]:443", ep); !ec) {
     273              :         // ep.is_v6() == true
     274              :         // ep.port() == 443
     275              :     }
     276              :     @endcode
     277              : 
     278              :     @param s The string to parse.
     279              :     @param ep The endpoint to store the result.
     280              :     @return An error code (empty on success).
     281              : */
     282              : [[nodiscard]] BOOST_COROSIO_DECL
     283              : std::error_code
     284              : parse_endpoint(
     285              :     std::string_view s,
     286              :     endpoint& ep) noexcept;
     287              : 
     288              : inline
     289           24 : endpoint::endpoint(std::string_view s)
     290              : {
     291           24 :     auto ec = parse_endpoint(s, *this);
     292           24 :     if (ec)
     293           15 :         detail::throw_system_error(ec);
     294            9 : }
     295              : 
     296              : } // namespace boost::corosio
     297              : 
     298              : #endif
        

Generated by: LCOV version 2.3