LCOV - code coverage report
Current view: top level - corosio - socket_option.hpp (source / functions) Coverage Total Hit Missed
Test: coverage_remapped.info Lines: 90.0 % 30 27 3
Test Date: 2026-02-25 01:27:20 Functions: 100.0 % 19 19

           TLA  Line data    Source code
       1                 : //
       2                 : // Copyright (c) 2026 Steve Gerbino
       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_SOCKET_OPTION_HPP
      11                 : #define BOOST_COROSIO_SOCKET_OPTION_HPP
      12                 : 
      13                 : #include <boost/corosio/detail/config.hpp>
      14                 : 
      15                 : #include <cstddef>
      16                 : 
      17                 : /** @file socket_option.hpp
      18                 : 
      19                 :     Type-erased socket option types that avoid platform-specific
      20                 :     headers. The protocol level and option name for each type are
      21                 :     resolved at link time via the compiled library.
      22                 : 
      23                 :     For an inline (zero-overhead) alternative that includes platform
      24                 :     headers, use `<boost/corosio/native/native_socket_option.hpp>`
      25                 :     (`boost::corosio::native_socket_option`).
      26                 : 
      27                 :     Both variants satisfy the same option-type interface and work
      28                 :     interchangeably with `tcp_socket::set_option` /
      29                 :     `tcp_socket::get_option` and the corresponding acceptor methods.
      30                 : 
      31                 :     @see native_socket_option
      32                 : */
      33                 : 
      34                 : namespace boost::corosio::socket_option {
      35                 : 
      36                 : /** Base class for concrete boolean socket options.
      37                 : 
      38                 :     Stores a boolean as an `int` suitable for `setsockopt`/`getsockopt`.
      39                 :     Derived types provide `level()` and `name()` for the specific option.
      40                 : */
      41                 : class boolean_option
      42                 : {
      43                 :     int value_ = 0;
      44                 : 
      45                 : public:
      46                 :     /// Construct with default value (disabled).
      47                 :     boolean_option() = default;
      48                 : 
      49                 :     /** Construct with an explicit value.
      50                 : 
      51                 :         @param v `true` to enable the option, `false` to disable.
      52                 :     */
      53 HIT         169 :     explicit boolean_option( bool v ) noexcept : value_( v ? 1 : 0 ) {}
      54                 : 
      55                 :     /// Assign a new value.
      56               4 :     boolean_option& operator=( bool v ) noexcept
      57                 :     {
      58               4 :         value_ = v ? 1 : 0;
      59               4 :         return *this;
      60                 :     }
      61                 : 
      62                 :     /// Return the option value.
      63              34 :     bool value() const noexcept { return value_ != 0; }
      64                 : 
      65                 :     /// Return the option value.
      66               4 :     explicit operator bool() const noexcept { return value_ != 0; }
      67                 : 
      68                 :     /// Return the negated option value.
      69               4 :     bool operator!() const noexcept { return value_ == 0; }
      70                 : 
      71                 :     /// Return a pointer to the underlying storage.
      72              36 :     void* data() noexcept { return &value_; }
      73                 : 
      74                 :     /// Return a pointer to the underlying storage.
      75             171 :     void const* data() const noexcept { return &value_; }
      76                 : 
      77                 :     /// Return the size of the underlying storage.
      78             207 :     std::size_t size() const noexcept { return sizeof( value_ ); }
      79                 : 
      80                 :     /** Normalize after `getsockopt` returns fewer bytes than expected.
      81                 : 
      82                 :         Windows Vista+ may write only 1 byte for boolean options.
      83                 : 
      84                 :         @param s The number of bytes actually written by `getsockopt`.
      85                 :     */
      86              36 :     void resize( std::size_t s ) noexcept
      87                 :     {
      88              36 :         if ( s == sizeof( char ) )
      89 MIS           0 :             value_ = *reinterpret_cast<unsigned char*>( &value_ ) ? 1 : 0;
      90 HIT          36 :     }
      91                 : };
      92                 : 
      93                 : /** Base class for concrete integer socket options.
      94                 : 
      95                 :     Stores an integer suitable for `setsockopt`/`getsockopt`.
      96                 :     Derived types provide `level()` and `name()` for the specific option.
      97                 : */
      98                 : class integer_option
      99                 : {
     100                 :     int value_ = 0;
     101                 : 
     102                 : public:
     103                 :     /// Construct with default value (zero).
     104                 :     integer_option() = default;
     105                 : 
     106                 :     /** Construct with an explicit value.
     107                 : 
     108                 :         @param v The option value.
     109                 :     */
     110               8 :     explicit integer_option( int v ) noexcept : value_( v ) {}
     111                 : 
     112                 :     /// Assign a new value.
     113               2 :     integer_option& operator=( int v ) noexcept
     114                 :     {
     115               2 :         value_ = v;
     116               2 :         return *this;
     117                 :     }
     118                 : 
     119                 :     /// Return the option value.
     120              18 :     int value() const noexcept { return value_; }
     121                 : 
     122                 :     /// Return a pointer to the underlying storage.
     123              16 :     void* data() noexcept { return &value_; }
     124                 : 
     125                 :     /// Return a pointer to the underlying storage.
     126               8 :     void const* data() const noexcept { return &value_; }
     127                 : 
     128                 :     /// Return the size of the underlying storage.
     129              24 :     std::size_t size() const noexcept { return sizeof( value_ ); }
     130                 : 
     131                 :     /** Normalize after `getsockopt` returns fewer bytes than expected.
     132                 : 
     133                 :         @param s The number of bytes actually written by `getsockopt`.
     134                 :     */
     135              16 :     void resize( std::size_t s ) noexcept
     136                 :     {
     137              16 :         if ( s == sizeof( char ) )
     138 MIS           0 :             value_ = static_cast<int>(
     139               0 :                 *reinterpret_cast<unsigned char*>( &value_ ) );
     140 HIT          16 :     }
     141                 : };
     142                 : 
     143                 : /** Disable Nagle's algorithm (TCP_NODELAY).
     144                 : 
     145                 :     @par Example
     146                 :     @code
     147                 :     sock.set_option( socket_option::no_delay( true ) );
     148                 :     auto nd = sock.get_option<socket_option::no_delay>();
     149                 :     if ( nd.value() )
     150                 :         // Nagle's algorithm is disabled
     151                 :     @endcode
     152                 : */
     153                 : class BOOST_COROSIO_DECL no_delay : public boolean_option
     154                 : {
     155                 : public:
     156                 :     using boolean_option::boolean_option;
     157                 :     using boolean_option::operator=;
     158                 : 
     159                 :     /// Return the protocol level.
     160                 :     static int level() noexcept;
     161                 : 
     162                 :     /// Return the option name.
     163                 :     static int name() noexcept;
     164                 : };
     165                 : 
     166                 : /** Enable periodic keepalive probes (SO_KEEPALIVE).
     167                 : 
     168                 :     @par Example
     169                 :     @code
     170                 :     sock.set_option( socket_option::keep_alive( true ) );
     171                 :     @endcode
     172                 : */
     173                 : class BOOST_COROSIO_DECL keep_alive : public boolean_option
     174                 : {
     175                 : public:
     176                 :     using boolean_option::boolean_option;
     177                 :     using boolean_option::operator=;
     178                 : 
     179                 :     /// Return the protocol level.
     180                 :     static int level() noexcept;
     181                 : 
     182                 :     /// Return the option name.
     183                 :     static int name() noexcept;
     184                 : };
     185                 : 
     186                 : /** Restrict an IPv6 socket to IPv6 only (IPV6_V6ONLY).
     187                 : 
     188                 :     When enabled, the socket only accepts IPv6 connections.
     189                 :     When disabled, the socket accepts both IPv4 and IPv6
     190                 :     connections (dual-stack mode).
     191                 : 
     192                 :     @par Example
     193                 :     @code
     194                 :     sock.set_option( socket_option::v6_only( true ) );
     195                 :     @endcode
     196                 : */
     197                 : class BOOST_COROSIO_DECL v6_only : public boolean_option
     198                 : {
     199                 : public:
     200                 :     using boolean_option::boolean_option;
     201                 :     using boolean_option::operator=;
     202                 : 
     203                 :     /// Return the protocol level.
     204                 :     static int level() noexcept;
     205                 : 
     206                 :     /// Return the option name.
     207                 :     static int name() noexcept;
     208                 : };
     209                 : 
     210                 : /** Allow local address reuse (SO_REUSEADDR).
     211                 : 
     212                 :     @par Example
     213                 :     @code
     214                 :     acc.set_option( socket_option::reuse_address( true ) );
     215                 :     @endcode
     216                 : */
     217                 : class BOOST_COROSIO_DECL reuse_address : public boolean_option
     218                 : {
     219                 : public:
     220                 :     using boolean_option::boolean_option;
     221                 :     using boolean_option::operator=;
     222                 : 
     223                 :     /// Return the protocol level.
     224                 :     static int level() noexcept;
     225                 : 
     226                 :     /// Return the option name.
     227                 :     static int name() noexcept;
     228                 : };
     229                 : 
     230                 : /** Allow multiple sockets to bind to the same port (SO_REUSEPORT).
     231                 : 
     232                 :     Not available on all platforms. On unsupported platforms,
     233                 :     `set_option` will return an error.
     234                 : 
     235                 :     @par Example
     236                 :     @code
     237                 :     acc.open( tcp::v6() );
     238                 :     acc.set_option( socket_option::reuse_port( true ) );
     239                 :     acc.bind( endpoint( ipv6_address::any(), 8080 ) );
     240                 :     acc.listen();
     241                 :     @endcode
     242                 : */
     243                 : class BOOST_COROSIO_DECL reuse_port : public boolean_option
     244                 : {
     245                 : public:
     246                 :     using boolean_option::boolean_option;
     247                 :     using boolean_option::operator=;
     248                 : 
     249                 :     /// Return the protocol level.
     250                 :     static int level() noexcept;
     251                 : 
     252                 :     /// Return the option name.
     253                 :     static int name() noexcept;
     254                 : };
     255                 : 
     256                 : /** Set the receive buffer size (SO_RCVBUF).
     257                 : 
     258                 :     @par Example
     259                 :     @code
     260                 :     sock.set_option( socket_option::receive_buffer_size( 65536 ) );
     261                 :     auto opt = sock.get_option<socket_option::receive_buffer_size>();
     262                 :     int sz = opt.value();
     263                 :     @endcode
     264                 : */
     265                 : class BOOST_COROSIO_DECL receive_buffer_size : public integer_option
     266                 : {
     267                 : public:
     268                 :     using integer_option::integer_option;
     269                 :     using integer_option::operator=;
     270                 : 
     271                 :     /// Return the protocol level.
     272                 :     static int level() noexcept;
     273                 : 
     274                 :     /// Return the option name.
     275                 :     static int name() noexcept;
     276                 : };
     277                 : 
     278                 : /** Set the send buffer size (SO_SNDBUF).
     279                 : 
     280                 :     @par Example
     281                 :     @code
     282                 :     sock.set_option( socket_option::send_buffer_size( 65536 ) );
     283                 :     @endcode
     284                 : */
     285                 : class BOOST_COROSIO_DECL send_buffer_size : public integer_option
     286                 : {
     287                 : public:
     288                 :     using integer_option::integer_option;
     289                 :     using integer_option::operator=;
     290                 : 
     291                 :     /// Return the protocol level.
     292                 :     static int level() noexcept;
     293                 : 
     294                 :     /// Return the option name.
     295                 :     static int name() noexcept;
     296                 : };
     297                 : 
     298                 : /** The SO_LINGER socket option.
     299                 : 
     300                 :     Controls behavior when closing a socket with unsent data.
     301                 :     When enabled, `close()` blocks until pending data is sent
     302                 :     or the timeout expires.
     303                 : 
     304                 :     @par Example
     305                 :     @code
     306                 :     sock.set_option( socket_option::linger( true, 5 ) );
     307                 :     auto opt = sock.get_option<socket_option::linger>();
     308                 :     if ( opt.enabled() )
     309                 :         std::cout << "linger timeout: " << opt.timeout() << "s\n";
     310                 :     @endcode
     311                 : */
     312                 : class BOOST_COROSIO_DECL linger
     313                 : {
     314                 :     // Opaque storage for the platform's struct linger.
     315                 :     // POSIX: { int, int } = 8 bytes.
     316                 :     // Windows: { u_short, u_short } = 4 bytes.
     317                 :     static constexpr std::size_t max_storage_ = 8;
     318                 :     alignas( 4 ) unsigned char storage_[max_storage_]{};
     319                 : 
     320                 : public:
     321                 :     /// Construct with default values (disabled, zero timeout).
     322                 :     linger() noexcept = default;
     323                 : 
     324                 :     /** Construct with explicit values.
     325                 : 
     326                 :         @param enabled `true` to enable linger behavior on close.
     327                 :         @param timeout The linger timeout in seconds.
     328                 :     */
     329                 :     linger( bool enabled, int timeout ) noexcept;
     330                 : 
     331                 :     /// Return whether linger is enabled.
     332                 :     bool enabled() const noexcept;
     333                 : 
     334                 :     /// Set whether linger is enabled.
     335                 :     void enabled( bool v ) noexcept;
     336                 : 
     337                 :     /// Return the linger timeout in seconds.
     338                 :     int timeout() const noexcept;
     339                 : 
     340                 :     /// Set the linger timeout in seconds.
     341                 :     void timeout( int v ) noexcept;
     342                 : 
     343                 :     /// Return the protocol level.
     344                 :     static int level() noexcept;
     345                 : 
     346                 :     /// Return the option name.
     347                 :     static int name() noexcept;
     348                 : 
     349                 :     /// Return a pointer to the underlying storage.
     350              10 :     void* data() noexcept { return storage_; }
     351                 : 
     352                 :     /// Return a pointer to the underlying storage.
     353              18 :     void const* data() const noexcept { return storage_; }
     354                 : 
     355                 :     /// Return the size of the underlying storage.
     356                 :     std::size_t size() const noexcept;
     357                 : 
     358                 :     /** Normalize after `getsockopt`.
     359                 : 
     360                 :         No-op — `struct linger` is always returned at full size.
     361                 : 
     362                 :         @param s The number of bytes actually written by `getsockopt`.
     363                 :     */
     364              10 :     void resize( std::size_t ) noexcept {}
     365                 : };
     366                 : 
     367                 : } // namespace boost::corosio::socket_option
     368                 : 
     369                 : #endif // BOOST_COROSIO_SOCKET_OPTION_HPP
        

Generated by: LCOV version 2.3