100.00% Lines (76/76) 100.00% Functions (37/37)
TLA Baseline Branch
Line Hits Code Line Hits Code
1   // 1   //
2   // Copyright (c) 2026 Steve Gerbino 2   // Copyright (c) 2026 Steve Gerbino
3   // Copyright (c) 2026 Michael Vandeberg 3   // Copyright (c) 2026 Michael Vandeberg
4   // 4   //
5   // Distributed under the Boost Software License, Version 1.0. (See accompanying 5   // Distributed under the Boost Software License, Version 1.0. (See accompanying
6   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7   // 7   //
8   // Official repository: https://github.com/cppalliance/corosio 8   // Official repository: https://github.com/cppalliance/corosio
9   // 9   //
10   10  
11   #ifndef BOOST_COROSIO_SOCKET_OPTION_HPP 11   #ifndef BOOST_COROSIO_SOCKET_OPTION_HPP
12   #define BOOST_COROSIO_SOCKET_OPTION_HPP 12   #define BOOST_COROSIO_SOCKET_OPTION_HPP
13   13  
14   #include <boost/corosio/detail/config.hpp> 14   #include <boost/corosio/detail/config.hpp>
15   #include <boost/corosio/ipv4_address.hpp> 15   #include <boost/corosio/ipv4_address.hpp>
16   #include <boost/corosio/ipv6_address.hpp> 16   #include <boost/corosio/ipv6_address.hpp>
17   17  
18   #include <cstddef> 18   #include <cstddef>
19   19  
20   /** @file socket_option.hpp 20   /** @file socket_option.hpp
21   21  
22   Type-erased socket option types that avoid platform-specific 22   Type-erased socket option types that avoid platform-specific
23   headers. The protocol level and option name for each type are 23   headers. The protocol level and option name for each type are
24   resolved at link time via the compiled library. 24   resolved at link time via the compiled library.
25   25  
26   For an inline (zero-overhead) alternative that includes platform 26   For an inline (zero-overhead) alternative that includes platform
27   headers, use `<boost/corosio/native/native_socket_option.hpp>` 27   headers, use `<boost/corosio/native/native_socket_option.hpp>`
28   (`boost::corosio::native_socket_option`). 28   (`boost::corosio::native_socket_option`).
29   29  
30   Both variants satisfy the same option-type interface and work 30   Both variants satisfy the same option-type interface and work
31   interchangeably with `tcp_socket::set_option` / 31   interchangeably with `tcp_socket::set_option` /
32   `tcp_socket::get_option` and the corresponding acceptor methods. 32   `tcp_socket::get_option` and the corresponding acceptor methods.
33   33  
34   @see native_socket_option 34   @see native_socket_option
35   */ 35   */
36   36  
37   namespace boost::corosio::socket_option { 37   namespace boost::corosio::socket_option {
38   38  
39   /** Base class for concrete boolean socket options. 39   /** Base class for concrete boolean socket options.
40   40  
41   Stores a boolean as an `int` suitable for `setsockopt`/`getsockopt`. 41   Stores a boolean as an `int` suitable for `setsockopt`/`getsockopt`.
42   Derived types provide `level()` and `name()` for the specific option. 42   Derived types provide `level()` and `name()` for the specific option.
43   */ 43   */
44   class BOOST_COROSIO_DECL boolean_option 44   class BOOST_COROSIO_DECL boolean_option
45   { 45   {
46   int value_ = 0; 46   int value_ = 0;
47   47  
48   public: 48   public:
49   /// Construct with default value (disabled). 49   /// Construct with default value (disabled).
50   boolean_option() = default; 50   boolean_option() = default;
51   51  
52   /** Construct with an explicit value. 52   /** Construct with an explicit value.
53   53  
54   @param v `true` to enable the option, `false` to disable. 54   @param v `true` to enable the option, `false` to disable.
55   */ 55   */
HITCBC 56   662 explicit boolean_option(bool v) noexcept : value_(v ? 1 : 0) {} 56   662 explicit boolean_option(bool v) noexcept : value_(v ? 1 : 0) {}
57   57  
58   /// Assign a new value. 58   /// Assign a new value.
HITCBC 59   4 boolean_option& operator=(bool v) noexcept 59   4 boolean_option& operator=(bool v) noexcept
60   { 60   {
HITCBC 61   4 value_ = v ? 1 : 0; 61   4 value_ = v ? 1 : 0;
HITCBC 62   4 return *this; 62   4 return *this;
63   } 63   }
64   64  
65   /// Return the option value. 65   /// Return the option value.
HITCBC 66   64 bool value() const noexcept 66   64 bool value() const noexcept
67   { 67   {
HITCBC 68   64 return value_ != 0; 68   64 return value_ != 0;
69   } 69   }
70   70  
71   /// Return the option value. 71   /// Return the option value.
HITCBC 72   4 explicit operator bool() const noexcept 72   4 explicit operator bool() const noexcept
73   { 73   {
HITCBC 74   4 return value_ != 0; 74   4 return value_ != 0;
75   } 75   }
76   76  
77   /// Return the negated option value. 77   /// Return the negated option value.
HITCBC 78   4 bool operator!() const noexcept 78   4 bool operator!() const noexcept
79   { 79   {
HITCBC 80   4 return value_ == 0; 80   4 return value_ == 0;
81   } 81   }
82   82  
83   /// Return a pointer to the underlying storage. 83   /// Return a pointer to the underlying storage.
HITCBC 84   89 void* data() noexcept 84   89 void* data() noexcept
85   { 85   {
HITCBC 86   89 return &value_; 86   89 return &value_;
87   } 87   }
88   88  
89   /// Return a pointer to the underlying storage. 89   /// Return a pointer to the underlying storage.
HITCBC 90   654 void const* data() const noexcept 90   654 void const* data() const noexcept
91   { 91   {
HITCBC 92   654 return &value_; 92   654 return &value_;
93   } 93   }
94   94  
95   /// Return the size of the underlying storage. 95   /// Return the size of the underlying storage.
HITCBC 96   743 std::size_t size() const noexcept 96   743 std::size_t size() const noexcept
97   { 97   {
HITCBC 98   743 return sizeof(value_); 98   743 return sizeof(value_);
99   } 99   }
100   100  
101   /** Normalize after `getsockopt` returns fewer bytes than expected. 101   /** Normalize after `getsockopt` returns fewer bytes than expected.
102   102  
103   Windows Vista+ may write only 1 byte for boolean options. 103   Windows Vista+ may write only 1 byte for boolean options.
104   104  
105   @param s The number of bytes actually written by `getsockopt`. 105   @param s The number of bytes actually written by `getsockopt`.
106   */ 106   */
HITCBC 107   68 void resize(std::size_t s) noexcept 107   68 void resize(std::size_t s) noexcept
108   { 108   {
HITCBC 109   68 if (s == sizeof(char)) 109   68 if (s == sizeof(char))
HITCBC 110   2 value_ = *reinterpret_cast<unsigned char*>(&value_) ? 1 : 0; 110   2 value_ = *reinterpret_cast<unsigned char*>(&value_) ? 1 : 0;
HITCBC 111   68 } 111   68 }
112   }; 112   };
113   113  
114   /** Base class for concrete integer socket options. 114   /** Base class for concrete integer socket options.
115   115  
116   Stores an integer suitable for `setsockopt`/`getsockopt`. 116   Stores an integer suitable for `setsockopt`/`getsockopt`.
117   Derived types provide `level()` and `name()` for the specific option. 117   Derived types provide `level()` and `name()` for the specific option.
118   */ 118   */
119   class BOOST_COROSIO_DECL integer_option 119   class BOOST_COROSIO_DECL integer_option
120   { 120   {
121   int value_ = 0; 121   int value_ = 0;
122   122  
123   public: 123   public:
124   /// Construct with default value (zero). 124   /// Construct with default value (zero).
125   integer_option() = default; 125   integer_option() = default;
126   126  
127   /** Construct with an explicit value. 127   /** Construct with an explicit value.
128   128  
129   @param v The option value. 129   @param v The option value.
130   */ 130   */
HITCBC 131   87 explicit integer_option(int v) noexcept : value_(v) {} 131   87 explicit integer_option(int v) noexcept : value_(v) {}
132   132  
133   /// Assign a new value. 133   /// Assign a new value.
HITCBC 134   2 integer_option& operator=(int v) noexcept 134   2 integer_option& operator=(int v) noexcept
135   { 135   {
HITCBC 136   2 value_ = v; 136   2 value_ = v;
HITCBC 137   2 return *this; 137   2 return *this;
138   } 138   }
139   139  
140   /// Return the option value. 140   /// Return the option value.
HITCBC 141   62 int value() const noexcept 141   62 int value() const noexcept
142   { 142   {
HITCBC 143   62 return value_; 143   62 return value_;
144   } 144   }
145   145  
146   /// Return a pointer to the underlying storage. 146   /// Return a pointer to the underlying storage.
HITCBC 147   58 void* data() noexcept 147   58 void* data() noexcept
148   { 148   {
HITCBC 149   58 return &value_; 149   58 return &value_;
150   } 150   }
151   151  
152   /// Return a pointer to the underlying storage. 152   /// Return a pointer to the underlying storage.
HITCBC 153   81 void const* data() const noexcept 153   81 void const* data() const noexcept
154   { 154   {
HITCBC 155   81 return &value_; 155   81 return &value_;
156   } 156   }
157   157  
158   /// Return the size of the underlying storage. 158   /// Return the size of the underlying storage.
HITCBC 159   139 std::size_t size() const noexcept 159   139 std::size_t size() const noexcept
160   { 160   {
HITCBC 161   139 return sizeof(value_); 161   139 return sizeof(value_);
162   } 162   }
163   163  
164   /** Normalize after `getsockopt` returns fewer bytes than expected. 164   /** Normalize after `getsockopt` returns fewer bytes than expected.
165   165  
166   @param s The number of bytes actually written by `getsockopt`. 166   @param s The number of bytes actually written by `getsockopt`.
167   */ 167   */
HITCBC 168   60 void resize(std::size_t s) noexcept 168   60 void resize(std::size_t s) noexcept
169   { 169   {
HITCBC 170   60 if (s == sizeof(char)) 170   60 if (s == sizeof(char))
HITCBC 171   2 value_ = 171   2 value_ =
HITCBC 172   2 static_cast<int>(*reinterpret_cast<unsigned char*>(&value_)); 172   2 static_cast<int>(*reinterpret_cast<unsigned char*>(&value_));
HITCBC 173   60 } 173   60 }
174   }; 174   };
175   175  
176   /** Base class for concrete boolean socket options with single-byte storage. 176   /** Base class for concrete boolean socket options with single-byte storage.
177   177  
178   Some BSD-derived kernels (macOS, FreeBSD) require certain IPv4 multicast 178   Some BSD-derived kernels (macOS, FreeBSD) require certain IPv4 multicast
179   options (`IP_MULTICAST_LOOP`) to be set with a one-byte value and return 179   options (`IP_MULTICAST_LOOP`) to be set with a one-byte value and return
180   `EINVAL` for the four-byte form that Linux accepts. This base provides 180   `EINVAL` for the four-byte form that Linux accepts. This base provides
181   `unsigned char` storage so the same options work on every platform. 181   `unsigned char` storage so the same options work on every platform.
182   */ 182   */
183   class BOOST_COROSIO_DECL byte_boolean_option 183   class BOOST_COROSIO_DECL byte_boolean_option
184   { 184   {
185   unsigned char value_ = 0; 185   unsigned char value_ = 0;
186   186  
187   public: 187   public:
188   /// Construct with default value (disabled). 188   /// Construct with default value (disabled).
189   byte_boolean_option() = default; 189   byte_boolean_option() = default;
190   190  
191   /** Construct with an explicit value. 191   /** Construct with an explicit value.
192   192  
193   @param v `true` to enable the option, `false` to disable. 193   @param v `true` to enable the option, `false` to disable.
194   */ 194   */
HITCBC 195   10 explicit byte_boolean_option(bool v) noexcept : value_(v ? 1 : 0) {} 195   10 explicit byte_boolean_option(bool v) noexcept : value_(v ? 1 : 0) {}
196   196  
197   /// Assign a new value. 197   /// Assign a new value.
198   byte_boolean_option& operator=(bool v) noexcept 198   byte_boolean_option& operator=(bool v) noexcept
199   { 199   {
200   value_ = v ? 1 : 0; 200   value_ = v ? 1 : 0;
201   return *this; 201   return *this;
202   } 202   }
203   203  
204   /// Return the option value. 204   /// Return the option value.
HITCBC 205   8 bool value() const noexcept 205   8 bool value() const noexcept
206   { 206   {
HITCBC 207   8 return value_ != 0; 207   8 return value_ != 0;
208   } 208   }
209   209  
210   /// Return the option value. 210   /// Return the option value.
211   explicit operator bool() const noexcept 211   explicit operator bool() const noexcept
212   { 212   {
213   return value_ != 0; 213   return value_ != 0;
214   } 214   }
215   215  
216   /// Return the negated option value. 216   /// Return the negated option value.
217   bool operator!() const noexcept 217   bool operator!() const noexcept
218   { 218   {
219   return value_ == 0; 219   return value_ == 0;
220   } 220   }
221   221  
222   /// Return a pointer to the underlying storage. 222   /// Return a pointer to the underlying storage.
HITCBC 223   8 void* data() noexcept 223   8 void* data() noexcept
224   { 224   {
HITCBC 225   8 return &value_; 225   8 return &value_;
226   } 226   }
227   227  
228   /// Return a pointer to the underlying storage. 228   /// Return a pointer to the underlying storage.
HITCBC 229   10 void const* data() const noexcept 229   10 void const* data() const noexcept
230   { 230   {
HITCBC 231   10 return &value_; 231   10 return &value_;
232   } 232   }
233   233  
234   /// Return the size of the underlying storage. 234   /// Return the size of the underlying storage.
HITCBC 235   18 std::size_t size() const noexcept 235   18 std::size_t size() const noexcept
236   { 236   {
HITCBC 237   18 return sizeof(value_); 237   18 return sizeof(value_);
238   } 238   }
239   239  
240   /// Storage is already one byte; no normalization needed. 240   /// Storage is already one byte; no normalization needed.
HITCBC 241   8 void resize(std::size_t) noexcept {} 241   8 void resize(std::size_t) noexcept {}
242   }; 242   };
243   243  
244   /** Base class for concrete integer socket options with single-byte storage. 244   /** Base class for concrete integer socket options with single-byte storage.
245   245  
246   Same rationale as `byte_boolean_option`: BSD-derived kernels require 246   Same rationale as `byte_boolean_option`: BSD-derived kernels require
247   `IP_MULTICAST_TTL` to be set with a one-byte value. Linux accepts 247   `IP_MULTICAST_TTL` to be set with a one-byte value. Linux accepts
248   one-byte too, so single-byte storage is portable. 248   one-byte too, so single-byte storage is portable.
249   */ 249   */
250   class BOOST_COROSIO_DECL byte_integer_option 250   class BOOST_COROSIO_DECL byte_integer_option
251   { 251   {
252   unsigned char value_ = 0; 252   unsigned char value_ = 0;
253   253  
254   public: 254   public:
255   /// Construct with default value (zero). 255   /// Construct with default value (zero).
256   byte_integer_option() = default; 256   byte_integer_option() = default;
257   257  
258   /** Construct with an explicit value. 258   /** Construct with an explicit value.
259   259  
260   @param v The option value; truncated to one byte. 260   @param v The option value; truncated to one byte.
261   */ 261   */
HITCBC 262   4 explicit byte_integer_option(int v) noexcept 262   4 explicit byte_integer_option(int v) noexcept
HITCBC 263   4 : value_(static_cast<unsigned char>(v)) 263   4 : value_(static_cast<unsigned char>(v))
HITGIC 264 - { 264 + 4 {}
DCB 265 - 4 }  
266   265  
267   /// Assign a new value; truncated to one byte. 266   /// Assign a new value; truncated to one byte.
268   byte_integer_option& operator=(int v) noexcept 267   byte_integer_option& operator=(int v) noexcept
269   { 268   {
270   value_ = static_cast<unsigned char>(v); 269   value_ = static_cast<unsigned char>(v);
271   return *this; 270   return *this;
272   } 271   }
273   272  
274   /// Return the option value. 273   /// Return the option value.
HITCBC 275   4 int value() const noexcept 274   4 int value() const noexcept
276   { 275   {
HITCBC 277   4 return value_; 276   4 return value_;
278   } 277   }
279   278  
280   /// Return a pointer to the underlying storage. 279   /// Return a pointer to the underlying storage.
HITCBC 281   4 void* data() noexcept 280   4 void* data() noexcept
282   { 281   {
HITCBC 283   4 return &value_; 282   4 return &value_;
284   } 283   }
285   284  
286   /// Return a pointer to the underlying storage. 285   /// Return a pointer to the underlying storage.
HITCBC 287   4 void const* data() const noexcept 286   4 void const* data() const noexcept
288   { 287   {
HITCBC 289   4 return &value_; 288   4 return &value_;
290   } 289   }
291   290  
292   /// Return the size of the underlying storage. 291   /// Return the size of the underlying storage.
HITCBC 293   8 std::size_t size() const noexcept 292   8 std::size_t size() const noexcept
294   { 293   {
HITCBC 295   8 return sizeof(value_); 294   8 return sizeof(value_);
296   } 295   }
297   296  
298   /// Storage is already one byte; no normalization needed. 297   /// Storage is already one byte; no normalization needed.
HITCBC 299   4 void resize(std::size_t) noexcept {} 298   4 void resize(std::size_t) noexcept {}
300   }; 299   };
301   300  
302   /** Disable Nagle's algorithm (TCP_NODELAY). 301   /** Disable Nagle's algorithm (TCP_NODELAY).
303   302  
304   @par Example 303   @par Example
305   @par !example no_delay 304   @par !example no_delay
306   */ 305   */
307   class BOOST_COROSIO_DECL no_delay : public boolean_option 306   class BOOST_COROSIO_DECL no_delay : public boolean_option
308   { 307   {
309   public: 308   public:
310   using boolean_option::boolean_option; 309   using boolean_option::boolean_option;
311   using boolean_option::operator=; 310   using boolean_option::operator=;
312   311  
313   /// Return the protocol level. 312   /// Return the protocol level.
314   static int level() noexcept; 313   static int level() noexcept;
315   314  
316   /// Return the option name. 315   /// Return the option name.
317   static int name() noexcept; 316   static int name() noexcept;
318   }; 317   };
319   318  
320   /** Enable periodic keepalive probes (SO_KEEPALIVE). 319   /** Enable periodic keepalive probes (SO_KEEPALIVE).
321   320  
322   @par Example 321   @par Example
323   @par !example keep_alive 322   @par !example keep_alive
324   */ 323   */
325   class BOOST_COROSIO_DECL keep_alive : public boolean_option 324   class BOOST_COROSIO_DECL keep_alive : public boolean_option
326   { 325   {
327   public: 326   public:
328   using boolean_option::boolean_option; 327   using boolean_option::boolean_option;
329   using boolean_option::operator=; 328   using boolean_option::operator=;
330   329  
331   /// Return the protocol level. 330   /// Return the protocol level.
332   static int level() noexcept; 331   static int level() noexcept;
333   332  
334   /// Return the option name. 333   /// Return the option name.
335   static int name() noexcept; 334   static int name() noexcept;
336   }; 335   };
337   336  
338   /** Restrict an IPv6 socket to IPv6 only (IPV6_V6ONLY). 337   /** Restrict an IPv6 socket to IPv6 only (IPV6_V6ONLY).
339   338  
340   When enabled, the socket only accepts IPv6 connections. 339   When enabled, the socket only accepts IPv6 connections.
341   When disabled, the socket accepts both IPv4 and IPv6 340   When disabled, the socket accepts both IPv4 and IPv6
342   connections (dual-stack mode). 341   connections (dual-stack mode).
343   342  
344   @par Example 343   @par Example
345   @par !example v6_only 344   @par !example v6_only
346   */ 345   */
347   class BOOST_COROSIO_DECL v6_only : public boolean_option 346   class BOOST_COROSIO_DECL v6_only : public boolean_option
348   { 347   {
349   public: 348   public:
350   using boolean_option::boolean_option; 349   using boolean_option::boolean_option;
351   using boolean_option::operator=; 350   using boolean_option::operator=;
352   351  
353   /// Return the protocol level. 352   /// Return the protocol level.
354   static int level() noexcept; 353   static int level() noexcept;
355   354  
356   /// Return the option name. 355   /// Return the option name.
357   static int name() noexcept; 356   static int name() noexcept;
358   }; 357   };
359   358  
360   /** Allow local address reuse (SO_REUSEADDR). 359   /** Allow local address reuse (SO_REUSEADDR).
361   360  
362   @par Example 361   @par Example
363   @par !example reuse_address 362   @par !example reuse_address
364   */ 363   */
365   class BOOST_COROSIO_DECL reuse_address : public boolean_option 364   class BOOST_COROSIO_DECL reuse_address : public boolean_option
366   { 365   {
367   public: 366   public:
368   using boolean_option::boolean_option; 367   using boolean_option::boolean_option;
369   using boolean_option::operator=; 368   using boolean_option::operator=;
370   369  
371   /// Return the protocol level. 370   /// Return the protocol level.
372   static int level() noexcept; 371   static int level() noexcept;
373   372  
374   /// Return the option name. 373   /// Return the option name.
375   static int name() noexcept; 374   static int name() noexcept;
376   }; 375   };
377   376  
378   /** Allow sending to broadcast addresses (SO_BROADCAST). 377   /** Allow sending to broadcast addresses (SO_BROADCAST).
379   378  
380   Required for UDP sockets that send to broadcast addresses 379   Required for UDP sockets that send to broadcast addresses
381   such as 255.255.255.255. Without this option, `send_to` 380   such as 255.255.255.255. Without this option, `send_to`
382   returns an error. 381   returns an error.
383   382  
384   @par Example 383   @par Example
385   @par !example broadcast 384   @par !example broadcast
386   */ 385   */
387   class BOOST_COROSIO_DECL broadcast : public boolean_option 386   class BOOST_COROSIO_DECL broadcast : public boolean_option
388   { 387   {
389   public: 388   public:
390   using boolean_option::boolean_option; 389   using boolean_option::boolean_option;
391   using boolean_option::operator=; 390   using boolean_option::operator=;
392   391  
393   /// Return the protocol level. 392   /// Return the protocol level.
394   static int level() noexcept; 393   static int level() noexcept;
395   394  
396   /// Return the option name. 395   /// Return the option name.
397   static int name() noexcept; 396   static int name() noexcept;
398   }; 397   };
399   398  
400   /** Allow multiple sockets to bind to the same port (SO_REUSEPORT). 399   /** Allow multiple sockets to bind to the same port (SO_REUSEPORT).
401   400  
402   Not available on all platforms. On unsupported platforms, 401   Not available on all platforms. On unsupported platforms,
403   `set_option` throws `std::system_error`. 402   `set_option` throws `std::system_error`.
404   403  
405   @par Example 404   @par Example
406   @par !example reuse_port 405   @par !example reuse_port
407   */ 406   */
408   class BOOST_COROSIO_DECL reuse_port : public boolean_option 407   class BOOST_COROSIO_DECL reuse_port : public boolean_option
409   { 408   {
410   public: 409   public:
411   using boolean_option::boolean_option; 410   using boolean_option::boolean_option;
412   using boolean_option::operator=; 411   using boolean_option::operator=;
413   412  
414   /// Return the protocol level. 413   /// Return the protocol level.
415   static int level() noexcept; 414   static int level() noexcept;
416   415  
417   /// Return the option name. 416   /// Return the option name.
418   static int name() noexcept; 417   static int name() noexcept;
419   }; 418   };
420   419  
421   /** Set the receive buffer size (SO_RCVBUF). 420   /** Set the receive buffer size (SO_RCVBUF).
422   421  
423   @par Example 422   @par Example
424   @par !example receive_buffer_size 423   @par !example receive_buffer_size
425   */ 424   */
426   class BOOST_COROSIO_DECL receive_buffer_size : public integer_option 425   class BOOST_COROSIO_DECL receive_buffer_size : public integer_option
427   { 426   {
428   public: 427   public:
429   using integer_option::integer_option; 428   using integer_option::integer_option;
430   using integer_option::operator=; 429   using integer_option::operator=;
431   430  
432   /// Return the protocol level. 431   /// Return the protocol level.
433   static int level() noexcept; 432   static int level() noexcept;
434   433  
435   /// Return the option name. 434   /// Return the option name.
436   static int name() noexcept; 435   static int name() noexcept;
437   }; 436   };
438   437  
439   /** Set the send buffer size (SO_SNDBUF). 438   /** Set the send buffer size (SO_SNDBUF).
440   439  
441   @par Example 440   @par Example
442   @par !example send_buffer_size 441   @par !example send_buffer_size
443   */ 442   */
444   class BOOST_COROSIO_DECL send_buffer_size : public integer_option 443   class BOOST_COROSIO_DECL send_buffer_size : public integer_option
445   { 444   {
446   public: 445   public:
447   using integer_option::integer_option; 446   using integer_option::integer_option;
448   using integer_option::operator=; 447   using integer_option::operator=;
449   448  
450   /// Return the protocol level. 449   /// Return the protocol level.
451   static int level() noexcept; 450   static int level() noexcept;
452   451  
453   /// Return the option name. 452   /// Return the option name.
454   static int name() noexcept; 453   static int name() noexcept;
455   }; 454   };
456   455  
457   /** The SO_LINGER socket option. 456   /** The SO_LINGER socket option.
458   457  
459   Controls behavior when closing a socket with unsent data. 458   Controls behavior when closing a socket with unsent data.
460   When enabled, `close()` blocks until pending data is sent 459   When enabled, `close()` blocks until pending data is sent
461   or the timeout expires. 460   or the timeout expires.
462   461  
463   @par Example 462   @par Example
464   @par !example linger 463   @par !example linger
465   */ 464   */
466   class BOOST_COROSIO_DECL linger 465   class BOOST_COROSIO_DECL linger
467   { 466   {
468   // Opaque storage for the platform's struct linger. 467   // Opaque storage for the platform's struct linger.
469   // POSIX: { int, int } = 8 bytes. 468   // POSIX: { int, int } = 8 bytes.
470   // Windows: { u_short, u_short } = 4 bytes. 469   // Windows: { u_short, u_short } = 4 bytes.
471   static constexpr std::size_t max_storage_ = 8; 470   static constexpr std::size_t max_storage_ = 8;
472   alignas(4) unsigned char storage_[max_storage_]{}; 471   alignas(4) unsigned char storage_[max_storage_]{};
473   472  
474   public: 473   public:
475   /// Construct with default values (disabled, zero timeout). 474   /// Construct with default values (disabled, zero timeout).
476   linger() noexcept = default; 475   linger() noexcept = default;
477   476  
478   /** Construct with explicit values. 477   /** Construct with explicit values.
479   478  
480   @param enabled `true` to enable linger behavior on close. 479   @param enabled `true` to enable linger behavior on close.
481   @param timeout The linger timeout in seconds. 480   @param timeout The linger timeout in seconds.
482   */ 481   */
483   linger(bool enabled, int timeout) noexcept; 482   linger(bool enabled, int timeout) noexcept;
484   483  
485   /// Return whether linger is enabled. 484   /// Return whether linger is enabled.
486   bool enabled() const noexcept; 485   bool enabled() const noexcept;
487   486  
488   /// Set whether linger is enabled. 487   /// Set whether linger is enabled.
489   void enabled(bool v) noexcept; 488   void enabled(bool v) noexcept;
490   489  
491   /// Return the linger timeout in seconds. 490   /// Return the linger timeout in seconds.
492   int timeout() const noexcept; 491   int timeout() const noexcept;
493   492  
494   /// Set the linger timeout in seconds. 493   /// Set the linger timeout in seconds.
495   void timeout(int v) noexcept; 494   void timeout(int v) noexcept;
496   495  
497   /// Return the protocol level. 496   /// Return the protocol level.
498   static int level() noexcept; 497   static int level() noexcept;
499   498  
500   /// Return the option name. 499   /// Return the option name.
501   static int name() noexcept; 500   static int name() noexcept;
502   501  
503   /// Return a pointer to the underlying storage. 502   /// Return a pointer to the underlying storage.
HITCBC 504   12 void* data() noexcept 503   12 void* data() noexcept
505   { 504   {
HITCBC 506   12 return storage_; 505   12 return storage_;
507   } 506   }
508   507  
509   /// Return a pointer to the underlying storage. 508   /// Return a pointer to the underlying storage.
HITCBC 510   203 void const* data() const noexcept 509   203 void const* data() const noexcept
511   { 510   {
HITCBC 512   203 return storage_; 511   203 return storage_;
513   } 512   }
514   513  
515   /// Return the size of the underlying storage. 514   /// Return the size of the underlying storage.
516   std::size_t size() const noexcept; 515   std::size_t size() const noexcept;
517   516  
518   /** Normalize after `getsockopt`. 517   /** Normalize after `getsockopt`.
519   518  
520   No-op — `struct linger` is always returned at full size. 519   No-op — `struct linger` is always returned at full size.
521   520  
522   @param s The number of bytes actually written by `getsockopt`. 521   @param s The number of bytes actually written by `getsockopt`.
523   */ 522   */
HITCBC 524   12 void resize(std::size_t) noexcept {} 523   12 void resize(std::size_t) noexcept {}
525   }; 524   };
526   525  
527   /** Enable loopback of outgoing multicast on IPv4 (IP_MULTICAST_LOOP). 526   /** Enable loopback of outgoing multicast on IPv4 (IP_MULTICAST_LOOP).
528   527  
529   Uses single-byte storage because BSD-derived kernels (macOS, FreeBSD) 528   Uses single-byte storage because BSD-derived kernels (macOS, FreeBSD)
530   reject the four-byte form with `EINVAL`. Linux accepts either size. 529   reject the four-byte form with `EINVAL`. Linux accepts either size.
531   530  
532   @par Example 531   @par Example
533   @par !example multicast_loop_v4 532   @par !example multicast_loop_v4
534   */ 533   */
535   class BOOST_COROSIO_DECL multicast_loop_v4 : public byte_boolean_option 534   class BOOST_COROSIO_DECL multicast_loop_v4 : public byte_boolean_option
536   { 535   {
537   public: 536   public:
538   using byte_boolean_option::byte_boolean_option; 537   using byte_boolean_option::byte_boolean_option;
539   using byte_boolean_option::operator=; 538   using byte_boolean_option::operator=;
540   539  
541   /// Return the protocol level. 540   /// Return the protocol level.
542   static int level() noexcept; 541   static int level() noexcept;
543   542  
544   /// Return the option name. 543   /// Return the option name.
545   static int name() noexcept; 544   static int name() noexcept;
546   }; 545   };
547   546  
548   /** Enable loopback of outgoing multicast on IPv6 (IPV6_MULTICAST_LOOP). 547   /** Enable loopback of outgoing multicast on IPv6 (IPV6_MULTICAST_LOOP).
549   548  
550   @par Example 549   @par Example
551   @par !example multicast_loop_v6 550   @par !example multicast_loop_v6
552   */ 551   */
553   class BOOST_COROSIO_DECL multicast_loop_v6 : public boolean_option 552   class BOOST_COROSIO_DECL multicast_loop_v6 : public boolean_option
554   { 553   {
555   public: 554   public:
556   using boolean_option::boolean_option; 555   using boolean_option::boolean_option;
557   using boolean_option::operator=; 556   using boolean_option::operator=;
558   557  
559   /// Return the protocol level. 558   /// Return the protocol level.
560   static int level() noexcept; 559   static int level() noexcept;
561   560  
562   /// Return the option name. 561   /// Return the option name.
563   static int name() noexcept; 562   static int name() noexcept;
564   }; 563   };
565   564  
566   /** Set the multicast TTL for IPv4 (IP_MULTICAST_TTL). 565   /** Set the multicast TTL for IPv4 (IP_MULTICAST_TTL).
567   566  
568   Uses single-byte storage because BSD-derived kernels (macOS, FreeBSD) 567   Uses single-byte storage because BSD-derived kernels (macOS, FreeBSD)
569   reject the four-byte form with `EINVAL`. Linux accepts either size. 568   reject the four-byte form with `EINVAL`. Linux accepts either size.
570   Values are truncated to the 0–255 range. 569   Values are truncated to the 0–255 range.
571   570  
572   @par Example 571   @par Example
573   @par !example multicast_hops_v4 572   @par !example multicast_hops_v4
574   */ 573   */
575   class BOOST_COROSIO_DECL multicast_hops_v4 : public byte_integer_option 574   class BOOST_COROSIO_DECL multicast_hops_v4 : public byte_integer_option
576   { 575   {
577   public: 576   public:
578   using byte_integer_option::byte_integer_option; 577   using byte_integer_option::byte_integer_option;
579   using byte_integer_option::operator=; 578   using byte_integer_option::operator=;
580   579  
581   /// Return the protocol level. 580   /// Return the protocol level.
582   static int level() noexcept; 581   static int level() noexcept;
583   582  
584   /// Return the option name. 583   /// Return the option name.
585   static int name() noexcept; 584   static int name() noexcept;
586   }; 585   };
587   586  
588   /** Set the multicast hop limit for IPv6 (IPV6_MULTICAST_HOPS). 587   /** Set the multicast hop limit for IPv6 (IPV6_MULTICAST_HOPS).
589   588  
590   @par Example 589   @par Example
591   @par !example multicast_hops_v6 590   @par !example multicast_hops_v6
592   */ 591   */
593   class BOOST_COROSIO_DECL multicast_hops_v6 : public integer_option 592   class BOOST_COROSIO_DECL multicast_hops_v6 : public integer_option
594   { 593   {
595   public: 594   public:
596   using integer_option::integer_option; 595   using integer_option::integer_option;
597   using integer_option::operator=; 596   using integer_option::operator=;
598   597  
599   /// Return the protocol level. 598   /// Return the protocol level.
600   static int level() noexcept; 599   static int level() noexcept;
601   600  
602   /// Return the option name. 601   /// Return the option name.
603   static int name() noexcept; 602   static int name() noexcept;
604   }; 603   };
605   604  
606   /** Set the outgoing interface for IPv6 multicast (IPV6_MULTICAST_IF). 605   /** Set the outgoing interface for IPv6 multicast (IPV6_MULTICAST_IF).
607   606  
608   @par Example 607   @par Example
609   @par !example multicast_interface_v6 608   @par !example multicast_interface_v6
610   */ 609   */
611   class BOOST_COROSIO_DECL multicast_interface_v6 : public integer_option 610   class BOOST_COROSIO_DECL multicast_interface_v6 : public integer_option
612   { 611   {
613   public: 612   public:
614   using integer_option::integer_option; 613   using integer_option::integer_option;
615   using integer_option::operator=; 614   using integer_option::operator=;
616   615  
617   /// Return the protocol level. 616   /// Return the protocol level.
618   static int level() noexcept; 617   static int level() noexcept;
619   618  
620   /// Return the option name. 619   /// Return the option name.
621   static int name() noexcept; 620   static int name() noexcept;
622   }; 621   };
623   622  
624   /** Join an IPv4 multicast group (IP_ADD_MEMBERSHIP). 623   /** Join an IPv4 multicast group (IP_ADD_MEMBERSHIP).
625   624  
626   @par Example 625   @par Example
627   @par !example join_group_v4 626   @par !example join_group_v4
628   */ 627   */
629   class BOOST_COROSIO_DECL join_group_v4 628   class BOOST_COROSIO_DECL join_group_v4
630   { 629   {
631   static constexpr std::size_t max_storage_ = 8; 630   static constexpr std::size_t max_storage_ = 8;
632   alignas(4) unsigned char storage_[max_storage_]{}; 631   alignas(4) unsigned char storage_[max_storage_]{};
633   632  
634   public: 633   public:
635   /// Construct with default values. 634   /// Construct with default values.
636   join_group_v4() noexcept = default; 635   join_group_v4() noexcept = default;
637   636  
638   /** Construct with a group and optional interface address. 637   /** Construct with a group and optional interface address.
639   638  
640   @param group The multicast group address to join. 639   @param group The multicast group address to join.
641   @param iface The local interface to use (default: any). 640   @param iface The local interface to use (default: any).
642   */ 641   */
643   join_group_v4( 642   join_group_v4(
644   ipv4_address group, ipv4_address iface = ipv4_address()) noexcept; 643   ipv4_address group, ipv4_address iface = ipv4_address()) noexcept;
645   644  
646   /// Return the protocol level. 645   /// Return the protocol level.
647   static int level() noexcept; 646   static int level() noexcept;
648   647  
649   /// Return the option name. 648   /// Return the option name.
650   static int name() noexcept; 649   static int name() noexcept;
651   650  
652   /// Return a pointer to the underlying storage. 651   /// Return a pointer to the underlying storage.
653   void* data() noexcept 652   void* data() noexcept
654   { 653   {
655   return storage_; 654   return storage_;
656   } 655   }
657   656  
658   /// Return a pointer to the underlying storage. 657   /// Return a pointer to the underlying storage.
HITCBC 659   4 void const* data() const noexcept 658   4 void const* data() const noexcept
660   { 659   {
HITCBC 661   4 return storage_; 660   4 return storage_;
662   } 661   }
663   662  
664   /// Return the size of the underlying storage. 663   /// Return the size of the underlying storage.
665   std::size_t size() const noexcept; 664   std::size_t size() const noexcept;
666   665  
667   /// No-op resize. 666   /// No-op resize.
668   void resize(std::size_t) noexcept {} 667   void resize(std::size_t) noexcept {}
669   }; 668   };
670   669  
671   /** Leave an IPv4 multicast group (IP_DROP_MEMBERSHIP). 670   /** Leave an IPv4 multicast group (IP_DROP_MEMBERSHIP).
672   671  
673   @par Example 672   @par Example
674   @par !example leave_group_v4 673   @par !example leave_group_v4
675   */ 674   */
676   class BOOST_COROSIO_DECL leave_group_v4 675   class BOOST_COROSIO_DECL leave_group_v4
677   { 676   {
678   static constexpr std::size_t max_storage_ = 8; 677   static constexpr std::size_t max_storage_ = 8;
679   alignas(4) unsigned char storage_[max_storage_]{}; 678   alignas(4) unsigned char storage_[max_storage_]{};
680   679  
681   public: 680   public:
682   /// Construct with default values. 681   /// Construct with default values.
683   leave_group_v4() noexcept = default; 682   leave_group_v4() noexcept = default;
684   683  
685   /** Construct with a group and optional interface address. 684   /** Construct with a group and optional interface address.
686   685  
687   @param group The multicast group address to leave. 686   @param group The multicast group address to leave.
688   @param iface The local interface (default: any). 687   @param iface The local interface (default: any).
689   */ 688   */
690   leave_group_v4( 689   leave_group_v4(
691   ipv4_address group, ipv4_address iface = ipv4_address()) noexcept; 690   ipv4_address group, ipv4_address iface = ipv4_address()) noexcept;
692   691  
693   /// Return the protocol level. 692   /// Return the protocol level.
694   static int level() noexcept; 693   static int level() noexcept;
695   694  
696   /// Return the option name. 695   /// Return the option name.
697   static int name() noexcept; 696   static int name() noexcept;
698   697  
699   /// Return a pointer to the underlying storage. 698   /// Return a pointer to the underlying storage.
700   void* data() noexcept 699   void* data() noexcept
701   { 700   {
702   return storage_; 701   return storage_;
703   } 702   }
704   703  
705   /// Return a pointer to the underlying storage. 704   /// Return a pointer to the underlying storage.
HITCBC 706   2 void const* data() const noexcept 705   2 void const* data() const noexcept
707   { 706   {
HITCBC 708   2 return storage_; 707   2 return storage_;
709   } 708   }
710   709  
711   /// Return the size of the underlying storage. 710   /// Return the size of the underlying storage.
712   std::size_t size() const noexcept; 711   std::size_t size() const noexcept;
713   712  
714   /// No-op resize. 713   /// No-op resize.
715   void resize(std::size_t) noexcept {} 714   void resize(std::size_t) noexcept {}
716   }; 715   };
717   716  
718   /** Join an IPv6 multicast group (IPV6_JOIN_GROUP). 717   /** Join an IPv6 multicast group (IPV6_JOIN_GROUP).
719   718  
720   @par Example 719   @par Example
721   @par !example join_group_v6 720   @par !example join_group_v6
722   */ 721   */
723   class BOOST_COROSIO_DECL join_group_v6 722   class BOOST_COROSIO_DECL join_group_v6
724   { 723   {
725   static constexpr std::size_t max_storage_ = 20; 724   static constexpr std::size_t max_storage_ = 20;
726   alignas(4) unsigned char storage_[max_storage_]{}; 725   alignas(4) unsigned char storage_[max_storage_]{};
727   726  
728   public: 727   public:
729   /// Construct with default values. 728   /// Construct with default values.
730   join_group_v6() noexcept = default; 729   join_group_v6() noexcept = default;
731   730  
732   /** Construct with a group and optional interface index. 731   /** Construct with a group and optional interface index.
733   732  
734   @param group The multicast group address to join. 733   @param group The multicast group address to join.
735   @param if_index The interface index (0 = kernel chooses). 734   @param if_index The interface index (0 = kernel chooses).
736   */ 735   */
737   join_group_v6(ipv6_address group, unsigned int if_index = 0) noexcept; 736   join_group_v6(ipv6_address group, unsigned int if_index = 0) noexcept;
738   737  
739   /// Return the protocol level. 738   /// Return the protocol level.
740   static int level() noexcept; 739   static int level() noexcept;
741   740  
742   /// Return the option name. 741   /// Return the option name.
743   static int name() noexcept; 742   static int name() noexcept;
744   743  
745   /// Return a pointer to the underlying storage. 744   /// Return a pointer to the underlying storage.
746   void* data() noexcept 745   void* data() noexcept
747   { 746   {
748   return storage_; 747   return storage_;
749   } 748   }
750   749  
751   /// Return a pointer to the underlying storage. 750   /// Return a pointer to the underlying storage.
HITCBC 752   2 void const* data() const noexcept 751   2 void const* data() const noexcept
753   { 752   {
HITCBC 754   2 return storage_; 753   2 return storage_;
755   } 754   }
756   755  
757   /// Return the size of the underlying storage. 756   /// Return the size of the underlying storage.
758   std::size_t size() const noexcept; 757   std::size_t size() const noexcept;
759   758  
760   /// No-op resize. 759   /// No-op resize.
761   void resize(std::size_t) noexcept {} 760   void resize(std::size_t) noexcept {}
762   }; 761   };
763   762  
764   /** Leave an IPv6 multicast group (IPV6_LEAVE_GROUP). 763   /** Leave an IPv6 multicast group (IPV6_LEAVE_GROUP).
765   764  
766   @par Example 765   @par Example
767   @par !example leave_group_v6 766   @par !example leave_group_v6
768   */ 767   */
769   class BOOST_COROSIO_DECL leave_group_v6 768   class BOOST_COROSIO_DECL leave_group_v6
770   { 769   {
771   static constexpr std::size_t max_storage_ = 20; 770   static constexpr std::size_t max_storage_ = 20;
772   alignas(4) unsigned char storage_[max_storage_]{}; 771   alignas(4) unsigned char storage_[max_storage_]{};
773   772  
774   public: 773   public:
775   /// Construct with default values. 774   /// Construct with default values.
776   leave_group_v6() noexcept = default; 775   leave_group_v6() noexcept = default;
777   776  
778   /** Construct with a group and optional interface index. 777   /** Construct with a group and optional interface index.
779   778  
780   @param group The multicast group address to leave. 779   @param group The multicast group address to leave.
781   @param if_index The interface index (0 = kernel chooses). 780   @param if_index The interface index (0 = kernel chooses).
782   */ 781   */
783   leave_group_v6(ipv6_address group, unsigned int if_index = 0) noexcept; 782   leave_group_v6(ipv6_address group, unsigned int if_index = 0) noexcept;
784   783  
785   /// Return the protocol level. 784   /// Return the protocol level.
786   static int level() noexcept; 785   static int level() noexcept;
787   786  
788   /// Return the option name. 787   /// Return the option name.
789   static int name() noexcept; 788   static int name() noexcept;
790   789  
791   /// Return a pointer to the underlying storage. 790   /// Return a pointer to the underlying storage.
HITCBC 792   2 void* data() noexcept 791   2 void* data() noexcept
793   { 792   {
HITCBC 794   2 return storage_; 793   2 return storage_;
795   } 794   }
796   795  
797   /// Return a pointer to the underlying storage. 796   /// Return a pointer to the underlying storage.
HITCBC 798   2 void const* data() const noexcept 797   2 void const* data() const noexcept
799   { 798   {
HITCBC 800   2 return storage_; 799   2 return storage_;
801   } 800   }
802   801  
803   /// Return the size of the underlying storage. 802   /// Return the size of the underlying storage.
804   std::size_t size() const noexcept; 803   std::size_t size() const noexcept;
805   804  
806   /// No-op resize. 805   /// No-op resize.
807   void resize(std::size_t) noexcept {} 806   void resize(std::size_t) noexcept {}
808   }; 807   };
809   808  
810   /** Set the outgoing interface for IPv4 multicast (IP_MULTICAST_IF). 809   /** Set the outgoing interface for IPv4 multicast (IP_MULTICAST_IF).
811   810  
812   Unlike the integer-based `multicast_interface_v6`, this option 811   Unlike the integer-based `multicast_interface_v6`, this option
813   takes an `ipv4_address` identifying the local interface. 812   takes an `ipv4_address` identifying the local interface.
814   813  
815   @par Example 814   @par Example
816   @par !example multicast_interface_v4 815   @par !example multicast_interface_v4
817   */ 816   */
818   class BOOST_COROSIO_DECL multicast_interface_v4 817   class BOOST_COROSIO_DECL multicast_interface_v4
819   { 818   {
820   static constexpr std::size_t max_storage_ = 4; 819   static constexpr std::size_t max_storage_ = 4;
821   alignas(4) unsigned char storage_[max_storage_]{}; 820   alignas(4) unsigned char storage_[max_storage_]{};
822   821  
823   public: 822   public:
824   /// Construct with default values (INADDR_ANY). 823   /// Construct with default values (INADDR_ANY).
825   multicast_interface_v4() noexcept = default; 824   multicast_interface_v4() noexcept = default;
826   825  
827   /** Construct with an interface address. 826   /** Construct with an interface address.
828   827  
829   @param iface The local interface address. 828   @param iface The local interface address.
830   */ 829   */
831   explicit multicast_interface_v4(ipv4_address iface) noexcept; 830   explicit multicast_interface_v4(ipv4_address iface) noexcept;
832   831  
833   /// Return the protocol level. 832   /// Return the protocol level.
834   static int level() noexcept; 833   static int level() noexcept;
835   834  
836   /// Return the option name. 835   /// Return the option name.
837   static int name() noexcept; 836   static int name() noexcept;
838   837  
839   /// Return a pointer to the underlying storage. 838   /// Return a pointer to the underlying storage.
840   void* data() noexcept 839   void* data() noexcept
841   { 840   {
842   return storage_; 841   return storage_;
843   } 842   }
844   843  
845   /// Return a pointer to the underlying storage. 844   /// Return a pointer to the underlying storage.
HITCBC 846   2 void const* data() const noexcept 845   2 void const* data() const noexcept
847   { 846   {
HITCBC 848   2 return storage_; 847   2 return storage_;
849   } 848   }
850   849  
851   /// Return the size of the underlying storage. 850   /// Return the size of the underlying storage.
852   std::size_t size() const noexcept; 851   std::size_t size() const noexcept;
853   852  
854   /// No-op resize. 853   /// No-op resize.
855   void resize(std::size_t) noexcept {} 854   void resize(std::size_t) noexcept {}
856   }; 855   };
857   856  
858   } // namespace boost::corosio::socket_option 857   } // namespace boost::corosio::socket_option
859   858  
860   #endif // BOOST_COROSIO_SOCKET_OPTION_HPP 859   #endif // BOOST_COROSIO_SOCKET_OPTION_HPP