LCOV - code coverage report
Current view: top level - corosio/native - native_socket_option.hpp (source / functions) Coverage Total Hit Missed
Test: coverage_remapped.info Lines: 100.0 % 32 32
Test Date: 2026-02-27 19:39:18 Functions: 91.7 % 24 22 2

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

Generated by: LCOV version 2.3