LCOV - code coverage report
Current view: top level - corosio - socket_option.hpp (source / functions) Coverage Total Hit Missed
Test: coverage_remapped.info Lines: 92.9 % 42 39 3
Test Date: 2026-02-27 19:39:18 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
      64                 :     {
      65              34 :         return value_ != 0;
      66                 :     }
      67                 : 
      68                 :     /// Return the option value.
      69               4 :     explicit operator bool() const noexcept
      70                 :     {
      71               4 :         return value_ != 0;
      72                 :     }
      73                 : 
      74                 :     /// Return the negated option value.
      75               4 :     bool operator!() const noexcept
      76                 :     {
      77               4 :         return value_ == 0;
      78                 :     }
      79                 : 
      80                 :     /// Return a pointer to the underlying storage.
      81              36 :     void* data() noexcept
      82                 :     {
      83              36 :         return &value_;
      84                 :     }
      85                 : 
      86                 :     /// Return a pointer to the underlying storage.
      87             171 :     void const* data() const noexcept
      88                 :     {
      89             171 :         return &value_;
      90                 :     }
      91                 : 
      92                 :     /// Return the size of the underlying storage.
      93             207 :     std::size_t size() const noexcept
      94                 :     {
      95             207 :         return sizeof(value_);
      96                 :     }
      97                 : 
      98                 :     /** Normalize after `getsockopt` returns fewer bytes than expected.
      99                 : 
     100                 :         Windows Vista+ may write only 1 byte for boolean options.
     101                 : 
     102                 :         @param s The number of bytes actually written by `getsockopt`.
     103                 :     */
     104              36 :     void resize(std::size_t s) noexcept
     105                 :     {
     106              36 :         if (s == sizeof(char))
     107 MIS           0 :             value_ = *reinterpret_cast<unsigned char*>(&value_) ? 1 : 0;
     108 HIT          36 :     }
     109                 : };
     110                 : 
     111                 : /** Base class for concrete integer socket options.
     112                 : 
     113                 :     Stores an integer suitable for `setsockopt`/`getsockopt`.
     114                 :     Derived types provide `level()` and `name()` for the specific option.
     115                 : */
     116                 : class integer_option
     117                 : {
     118                 :     int value_ = 0;
     119                 : 
     120                 : public:
     121                 :     /// Construct with default value (zero).
     122                 :     integer_option() = default;
     123                 : 
     124                 :     /** Construct with an explicit value.
     125                 : 
     126                 :         @param v The option value.
     127                 :     */
     128               8 :     explicit integer_option(int v) noexcept : value_(v) {}
     129                 : 
     130                 :     /// Assign a new value.
     131               2 :     integer_option& operator=(int v) noexcept
     132                 :     {
     133               2 :         value_ = v;
     134               2 :         return *this;
     135                 :     }
     136                 : 
     137                 :     /// Return the option value.
     138              18 :     int value() const noexcept
     139                 :     {
     140              18 :         return value_;
     141                 :     }
     142                 : 
     143                 :     /// Return a pointer to the underlying storage.
     144              16 :     void* data() noexcept
     145                 :     {
     146              16 :         return &value_;
     147                 :     }
     148                 : 
     149                 :     /// Return a pointer to the underlying storage.
     150               8 :     void const* data() const noexcept
     151                 :     {
     152               8 :         return &value_;
     153                 :     }
     154                 : 
     155                 :     /// Return the size of the underlying storage.
     156              24 :     std::size_t size() const noexcept
     157                 :     {
     158              24 :         return sizeof(value_);
     159                 :     }
     160                 : 
     161                 :     /** Normalize after `getsockopt` returns fewer bytes than expected.
     162                 : 
     163                 :         @param s The number of bytes actually written by `getsockopt`.
     164                 :     */
     165              16 :     void resize(std::size_t s) noexcept
     166                 :     {
     167              16 :         if (s == sizeof(char))
     168 MIS           0 :             value_ =
     169               0 :                 static_cast<int>(*reinterpret_cast<unsigned char*>(&value_));
     170 HIT          16 :     }
     171                 : };
     172                 : 
     173                 : /** Disable Nagle's algorithm (TCP_NODELAY).
     174                 : 
     175                 :     @par Example
     176                 :     @code
     177                 :     sock.set_option( socket_option::no_delay( true ) );
     178                 :     auto nd = sock.get_option<socket_option::no_delay>();
     179                 :     if ( nd.value() )
     180                 :         // Nagle's algorithm is disabled
     181                 :     @endcode
     182                 : */
     183                 : class BOOST_COROSIO_DECL no_delay : public boolean_option
     184                 : {
     185                 : public:
     186                 :     using boolean_option::boolean_option;
     187                 :     using boolean_option::operator=;
     188                 : 
     189                 :     /// Return the protocol level.
     190                 :     static int level() noexcept;
     191                 : 
     192                 :     /// Return the option name.
     193                 :     static int name() noexcept;
     194                 : };
     195                 : 
     196                 : /** Enable periodic keepalive probes (SO_KEEPALIVE).
     197                 : 
     198                 :     @par Example
     199                 :     @code
     200                 :     sock.set_option( socket_option::keep_alive( true ) );
     201                 :     @endcode
     202                 : */
     203                 : class BOOST_COROSIO_DECL keep_alive : public boolean_option
     204                 : {
     205                 : public:
     206                 :     using boolean_option::boolean_option;
     207                 :     using boolean_option::operator=;
     208                 : 
     209                 :     /// Return the protocol level.
     210                 :     static int level() noexcept;
     211                 : 
     212                 :     /// Return the option name.
     213                 :     static int name() noexcept;
     214                 : };
     215                 : 
     216                 : /** Restrict an IPv6 socket to IPv6 only (IPV6_V6ONLY).
     217                 : 
     218                 :     When enabled, the socket only accepts IPv6 connections.
     219                 :     When disabled, the socket accepts both IPv4 and IPv6
     220                 :     connections (dual-stack mode).
     221                 : 
     222                 :     @par Example
     223                 :     @code
     224                 :     sock.set_option( socket_option::v6_only( true ) );
     225                 :     @endcode
     226                 : */
     227                 : class BOOST_COROSIO_DECL v6_only : public boolean_option
     228                 : {
     229                 : public:
     230                 :     using boolean_option::boolean_option;
     231                 :     using boolean_option::operator=;
     232                 : 
     233                 :     /// Return the protocol level.
     234                 :     static int level() noexcept;
     235                 : 
     236                 :     /// Return the option name.
     237                 :     static int name() noexcept;
     238                 : };
     239                 : 
     240                 : /** Allow local address reuse (SO_REUSEADDR).
     241                 : 
     242                 :     @par Example
     243                 :     @code
     244                 :     acc.set_option( socket_option::reuse_address( true ) );
     245                 :     @endcode
     246                 : */
     247                 : class BOOST_COROSIO_DECL reuse_address : public boolean_option
     248                 : {
     249                 : public:
     250                 :     using boolean_option::boolean_option;
     251                 :     using boolean_option::operator=;
     252                 : 
     253                 :     /// Return the protocol level.
     254                 :     static int level() noexcept;
     255                 : 
     256                 :     /// Return the option name.
     257                 :     static int name() noexcept;
     258                 : };
     259                 : 
     260                 : /** Allow multiple sockets to bind to the same port (SO_REUSEPORT).
     261                 : 
     262                 :     Not available on all platforms. On unsupported platforms,
     263                 :     `set_option` will return an error.
     264                 : 
     265                 :     @par Example
     266                 :     @code
     267                 :     acc.open( tcp::v6() );
     268                 :     acc.set_option( socket_option::reuse_port( true ) );
     269                 :     acc.bind( endpoint( ipv6_address::any(), 8080 ) );
     270                 :     acc.listen();
     271                 :     @endcode
     272                 : */
     273                 : class BOOST_COROSIO_DECL reuse_port : public boolean_option
     274                 : {
     275                 : public:
     276                 :     using boolean_option::boolean_option;
     277                 :     using boolean_option::operator=;
     278                 : 
     279                 :     /// Return the protocol level.
     280                 :     static int level() noexcept;
     281                 : 
     282                 :     /// Return the option name.
     283                 :     static int name() noexcept;
     284                 : };
     285                 : 
     286                 : /** Set the receive buffer size (SO_RCVBUF).
     287                 : 
     288                 :     @par Example
     289                 :     @code
     290                 :     sock.set_option( socket_option::receive_buffer_size( 65536 ) );
     291                 :     auto opt = sock.get_option<socket_option::receive_buffer_size>();
     292                 :     int sz = opt.value();
     293                 :     @endcode
     294                 : */
     295                 : class BOOST_COROSIO_DECL receive_buffer_size : public integer_option
     296                 : {
     297                 : public:
     298                 :     using integer_option::integer_option;
     299                 :     using integer_option::operator=;
     300                 : 
     301                 :     /// Return the protocol level.
     302                 :     static int level() noexcept;
     303                 : 
     304                 :     /// Return the option name.
     305                 :     static int name() noexcept;
     306                 : };
     307                 : 
     308                 : /** Set the send buffer size (SO_SNDBUF).
     309                 : 
     310                 :     @par Example
     311                 :     @code
     312                 :     sock.set_option( socket_option::send_buffer_size( 65536 ) );
     313                 :     @endcode
     314                 : */
     315                 : class BOOST_COROSIO_DECL send_buffer_size : public integer_option
     316                 : {
     317                 : public:
     318                 :     using integer_option::integer_option;
     319                 :     using integer_option::operator=;
     320                 : 
     321                 :     /// Return the protocol level.
     322                 :     static int level() noexcept;
     323                 : 
     324                 :     /// Return the option name.
     325                 :     static int name() noexcept;
     326                 : };
     327                 : 
     328                 : /** The SO_LINGER socket option.
     329                 : 
     330                 :     Controls behavior when closing a socket with unsent data.
     331                 :     When enabled, `close()` blocks until pending data is sent
     332                 :     or the timeout expires.
     333                 : 
     334                 :     @par Example
     335                 :     @code
     336                 :     sock.set_option( socket_option::linger( true, 5 ) );
     337                 :     auto opt = sock.get_option<socket_option::linger>();
     338                 :     if ( opt.enabled() )
     339                 :         std::cout << "linger timeout: " << opt.timeout() << "s\n";
     340                 :     @endcode
     341                 : */
     342                 : class BOOST_COROSIO_DECL linger
     343                 : {
     344                 :     // Opaque storage for the platform's struct linger.
     345                 :     // POSIX: { int, int } = 8 bytes.
     346                 :     // Windows: { u_short, u_short } = 4 bytes.
     347                 :     static constexpr std::size_t max_storage_ = 8;
     348                 :     alignas(4) unsigned char storage_[max_storage_]{};
     349                 : 
     350                 : public:
     351                 :     /// Construct with default values (disabled, zero timeout).
     352                 :     linger() noexcept = default;
     353                 : 
     354                 :     /** Construct with explicit values.
     355                 : 
     356                 :         @param enabled `true` to enable linger behavior on close.
     357                 :         @param timeout The linger timeout in seconds.
     358                 :     */
     359                 :     linger(bool enabled, int timeout) noexcept;
     360                 : 
     361                 :     /// Return whether linger is enabled.
     362                 :     bool enabled() const noexcept;
     363                 : 
     364                 :     /// Set whether linger is enabled.
     365                 :     void enabled(bool v) noexcept;
     366                 : 
     367                 :     /// Return the linger timeout in seconds.
     368                 :     int timeout() const noexcept;
     369                 : 
     370                 :     /// Set the linger timeout in seconds.
     371                 :     void timeout(int v) noexcept;
     372                 : 
     373                 :     /// Return the protocol level.
     374                 :     static int level() noexcept;
     375                 : 
     376                 :     /// Return the option name.
     377                 :     static int name() noexcept;
     378                 : 
     379                 :     /// Return a pointer to the underlying storage.
     380              10 :     void* data() noexcept
     381                 :     {
     382              10 :         return storage_;
     383                 :     }
     384                 : 
     385                 :     /// Return a pointer to the underlying storage.
     386              18 :     void const* data() const noexcept
     387                 :     {
     388              18 :         return storage_;
     389                 :     }
     390                 : 
     391                 :     /// Return the size of the underlying storage.
     392                 :     std::size_t size() const noexcept;
     393                 : 
     394                 :     /** Normalize after `getsockopt`.
     395                 : 
     396                 :         No-op — `struct linger` is always returned at full size.
     397                 : 
     398                 :         @param s The number of bytes actually written by `getsockopt`.
     399                 :     */
     400              10 :     void resize(std::size_t) noexcept {}
     401                 : };
     402                 : 
     403                 : } // namespace boost::corosio::socket_option
     404                 : 
     405                 : #endif // BOOST_COROSIO_SOCKET_OPTION_HPP
        

Generated by: LCOV version 2.3