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))
264   { 264   {
HITCBC 265   4 } 265   4 }
266   266  
267   /// Assign a new value; truncated to one byte. 267   /// Assign a new value; truncated to one byte.
268   byte_integer_option& operator=(int v) noexcept 268   byte_integer_option& operator=(int v) noexcept
269   { 269   {
270   value_ = static_cast<unsigned char>(v); 270   value_ = static_cast<unsigned char>(v);
271   return *this; 271   return *this;
272   } 272   }
273   273  
274   /// Return the option value. 274   /// Return the option value.
HITCBC 275   4 int value() const noexcept 275   4 int value() const noexcept
276   { 276   {
HITCBC 277   4 return value_; 277   4 return value_;
278   } 278   }
279   279  
280   /// Return a pointer to the underlying storage. 280   /// Return a pointer to the underlying storage.
HITCBC 281   4 void* data() noexcept 281   4 void* data() noexcept
282   { 282   {
HITCBC 283   4 return &value_; 283   4 return &value_;
284   } 284   }
285   285  
286   /// Return a pointer to the underlying storage. 286   /// Return a pointer to the underlying storage.
HITCBC 287   4 void const* data() const noexcept 287   4 void const* data() const noexcept
288   { 288   {
HITCBC 289   4 return &value_; 289   4 return &value_;
290   } 290   }
291   291  
292   /// Return the size of the underlying storage. 292   /// Return the size of the underlying storage.
HITCBC 293   8 std::size_t size() const noexcept 293   8 std::size_t size() const noexcept
294   { 294   {
HITCBC 295   8 return sizeof(value_); 295   8 return sizeof(value_);
296   } 296   }
297   297  
298   /// Storage is already one byte; no normalization needed. 298   /// Storage is already one byte; no normalization needed.
HITCBC 299   4 void resize(std::size_t) noexcept {} 299   4 void resize(std::size_t) noexcept {}
300   }; 300   };
301   301  
302   /** Disable Nagle's algorithm (TCP_NODELAY). 302   /** Disable Nagle's algorithm (TCP_NODELAY).
303   303  
304   @par Example 304   @par Example
305   @par !example no_delay 305   @par !example no_delay
306   */ 306   */
307   class BOOST_COROSIO_DECL no_delay : public boolean_option 307   class BOOST_COROSIO_DECL no_delay : public boolean_option
308   { 308   {
309   public: 309   public:
310   using boolean_option::boolean_option; 310   using boolean_option::boolean_option;
311   using boolean_option::operator=; 311   using boolean_option::operator=;
312   312  
313   /// Return the protocol level. 313   /// Return the protocol level.
314   static int level() noexcept; 314   static int level() noexcept;
315   315  
316   /// Return the option name. 316   /// Return the option name.
317   static int name() noexcept; 317   static int name() noexcept;
318   }; 318   };
319   319  
320   /** Enable periodic keepalive probes (SO_KEEPALIVE). 320   /** Enable periodic keepalive probes (SO_KEEPALIVE).
321   321  
322   @par Example 322   @par Example
323   @par !example keep_alive 323   @par !example keep_alive
324   */ 324   */
325   class BOOST_COROSIO_DECL keep_alive : public boolean_option 325   class BOOST_COROSIO_DECL keep_alive : public boolean_option
326   { 326   {
327   public: 327   public:
328   using boolean_option::boolean_option; 328   using boolean_option::boolean_option;
329   using boolean_option::operator=; 329   using boolean_option::operator=;
330   330  
331   /// Return the protocol level. 331   /// Return the protocol level.
332   static int level() noexcept; 332   static int level() noexcept;
333   333  
334   /// Return the option name. 334   /// Return the option name.
335   static int name() noexcept; 335   static int name() noexcept;
336   }; 336   };
337   337  
338   /** Restrict an IPv6 socket to IPv6 only (IPV6_V6ONLY). 338   /** Restrict an IPv6 socket to IPv6 only (IPV6_V6ONLY).
339   339  
340   When enabled, the socket only accepts IPv6 connections. 340   When enabled, the socket only accepts IPv6 connections.
341   When disabled, the socket accepts both IPv4 and IPv6 341   When disabled, the socket accepts both IPv4 and IPv6
342   connections (dual-stack mode). 342   connections (dual-stack mode).
343   343  
344   @par Example 344   @par Example
345   @par !example v6_only 345   @par !example v6_only
346   */ 346   */
347   class BOOST_COROSIO_DECL v6_only : public boolean_option 347   class BOOST_COROSIO_DECL v6_only : public boolean_option
348   { 348   {
349   public: 349   public:
350   using boolean_option::boolean_option; 350   using boolean_option::boolean_option;
351   using boolean_option::operator=; 351   using boolean_option::operator=;
352   352  
353   /// Return the protocol level. 353   /// Return the protocol level.
354   static int level() noexcept; 354   static int level() noexcept;
355   355  
356   /// Return the option name. 356   /// Return the option name.
357   static int name() noexcept; 357   static int name() noexcept;
358   }; 358   };
359   359  
360   /** Allow local address reuse (SO_REUSEADDR). 360   /** Allow local address reuse (SO_REUSEADDR).
361   361  
362   @par Example 362   @par Example
363   @par !example reuse_address 363   @par !example reuse_address
364   */ 364   */
365   class BOOST_COROSIO_DECL reuse_address : public boolean_option 365   class BOOST_COROSIO_DECL reuse_address : public boolean_option
366   { 366   {
367   public: 367   public:
368   using boolean_option::boolean_option; 368   using boolean_option::boolean_option;
369   using boolean_option::operator=; 369   using boolean_option::operator=;
370   370  
371   /// Return the protocol level. 371   /// Return the protocol level.
372   static int level() noexcept; 372   static int level() noexcept;
373   373  
374   /// Return the option name. 374   /// Return the option name.
375   static int name() noexcept; 375   static int name() noexcept;
376   }; 376   };
377   377  
378   /** Allow sending to broadcast addresses (SO_BROADCAST). 378   /** Allow sending to broadcast addresses (SO_BROADCAST).
379   379  
380   Required for UDP sockets that send to broadcast addresses 380   Required for UDP sockets that send to broadcast addresses
381   such as 255.255.255.255. Without this option, `send_to` 381   such as 255.255.255.255. Without this option, `send_to`
382   returns an error. 382   returns an error.
383   383  
384   @par Example 384   @par Example
385   @par !example broadcast 385   @par !example broadcast
386   */ 386   */
387   class BOOST_COROSIO_DECL broadcast : public boolean_option 387   class BOOST_COROSIO_DECL broadcast : public boolean_option
388   { 388   {
389   public: 389   public:
390   using boolean_option::boolean_option; 390   using boolean_option::boolean_option;
391   using boolean_option::operator=; 391   using boolean_option::operator=;
392   392  
393   /// Return the protocol level. 393   /// Return the protocol level.
394   static int level() noexcept; 394   static int level() noexcept;
395   395  
396   /// Return the option name. 396   /// Return the option name.
397   static int name() noexcept; 397   static int name() noexcept;
398   }; 398   };
399   399  
400   /** Allow multiple sockets to bind to the same port (SO_REUSEPORT). 400   /** Allow multiple sockets to bind to the same port (SO_REUSEPORT).
401   401  
402   Not available on all platforms. On unsupported platforms, 402   Not available on all platforms. On unsupported platforms,
403   `set_option` throws `std::system_error`. 403   `set_option` throws `std::system_error`.
404   404  
405   @par Example 405   @par Example
406   @par !example reuse_port 406   @par !example reuse_port
407   */ 407   */
408   class BOOST_COROSIO_DECL reuse_port : public boolean_option 408   class BOOST_COROSIO_DECL reuse_port : public boolean_option
409   { 409   {
410   public: 410   public:
411   using boolean_option::boolean_option; 411   using boolean_option::boolean_option;
412   using boolean_option::operator=; 412   using boolean_option::operator=;
413   413  
414   /// Return the protocol level. 414   /// Return the protocol level.
415   static int level() noexcept; 415   static int level() noexcept;
416   416  
417   /// Return the option name. 417   /// Return the option name.
418   static int name() noexcept; 418   static int name() noexcept;
419   }; 419   };
420   420  
421   /** Set the receive buffer size (SO_RCVBUF). 421   /** Set the receive buffer size (SO_RCVBUF).
422   422  
423   @par Example 423   @par Example
424   @par !example receive_buffer_size 424   @par !example receive_buffer_size
425   */ 425   */
426   class BOOST_COROSIO_DECL receive_buffer_size : public integer_option 426   class BOOST_COROSIO_DECL receive_buffer_size : public integer_option
427   { 427   {
428   public: 428   public:
429   using integer_option::integer_option; 429   using integer_option::integer_option;
430   using integer_option::operator=; 430   using integer_option::operator=;
431   431  
432   /// Return the protocol level. 432   /// Return the protocol level.
433   static int level() noexcept; 433   static int level() noexcept;
434   434  
435   /// Return the option name. 435   /// Return the option name.
436   static int name() noexcept; 436   static int name() noexcept;
437   }; 437   };
438   438  
439   /** Set the send buffer size (SO_SNDBUF). 439   /** Set the send buffer size (SO_SNDBUF).
440   440  
441   @par Example 441   @par Example
442   @par !example send_buffer_size 442   @par !example send_buffer_size
443   */ 443   */
444   class BOOST_COROSIO_DECL send_buffer_size : public integer_option 444   class BOOST_COROSIO_DECL send_buffer_size : public integer_option
445   { 445   {
446   public: 446   public:
447   using integer_option::integer_option; 447   using integer_option::integer_option;
448   using integer_option::operator=; 448   using integer_option::operator=;
449   449  
450   /// Return the protocol level. 450   /// Return the protocol level.
451   static int level() noexcept; 451   static int level() noexcept;
452   452  
453   /// Return the option name. 453   /// Return the option name.
454   static int name() noexcept; 454   static int name() noexcept;
455   }; 455   };
456   456  
457   /** The SO_LINGER socket option. 457   /** The SO_LINGER socket option.
458   458  
459   Controls behavior when closing a socket with unsent data. 459   Controls behavior when closing a socket with unsent data.
460   When enabled, `close()` blocks until pending data is sent 460   When enabled, `close()` blocks until pending data is sent
461   or the timeout expires. 461   or the timeout expires.
462   462  
463   @par Example 463   @par Example
464   @par !example linger 464   @par !example linger
465   */ 465   */
466   class BOOST_COROSIO_DECL linger 466   class BOOST_COROSIO_DECL linger
467   { 467   {
468   // Opaque storage for the platform's struct linger. 468   // Opaque storage for the platform's struct linger.
469   // POSIX: { int, int } = 8 bytes. 469   // POSIX: { int, int } = 8 bytes.
470   // Windows: { u_short, u_short } = 4 bytes. 470   // Windows: { u_short, u_short } = 4 bytes.
471   static constexpr std::size_t max_storage_ = 8; 471   static constexpr std::size_t max_storage_ = 8;
472   alignas(4) unsigned char storage_[max_storage_]{}; 472   alignas(4) unsigned char storage_[max_storage_]{};
473   473  
474   public: 474   public:
475   /// Construct with default values (disabled, zero timeout). 475   /// Construct with default values (disabled, zero timeout).
476   linger() noexcept = default; 476   linger() noexcept = default;
477   477  
478   /** Construct with explicit values. 478   /** Construct with explicit values.
479   479  
480   @param enabled `true` to enable linger behavior on close. 480   @param enabled `true` to enable linger behavior on close.
481   @param timeout The linger timeout in seconds. 481   @param timeout The linger timeout in seconds.
482   */ 482   */
483   linger(bool enabled, int timeout) noexcept; 483   linger(bool enabled, int timeout) noexcept;
484   484  
485   /// Return whether linger is enabled. 485   /// Return whether linger is enabled.
486   bool enabled() const noexcept; 486   bool enabled() const noexcept;
487   487  
488   /// Set whether linger is enabled. 488   /// Set whether linger is enabled.
489   void enabled(bool v) noexcept; 489   void enabled(bool v) noexcept;
490   490  
491   /// Return the linger timeout in seconds. 491   /// Return the linger timeout in seconds.
492   int timeout() const noexcept; 492   int timeout() const noexcept;
493   493  
494   /// Set the linger timeout in seconds. 494   /// Set the linger timeout in seconds.
495   void timeout(int v) noexcept; 495   void timeout(int v) noexcept;
496   496  
497   /// Return the protocol level. 497   /// Return the protocol level.
498   static int level() noexcept; 498   static int level() noexcept;
499   499  
500   /// Return the option name. 500   /// Return the option name.
501   static int name() noexcept; 501   static int name() noexcept;
502   502  
503   /// Return a pointer to the underlying storage. 503   /// Return a pointer to the underlying storage.
HITCBC 504   12 void* data() noexcept 504   12 void* data() noexcept
505   { 505   {
HITCBC 506   12 return storage_; 506   12 return storage_;
507   } 507   }
508   508  
509   /// Return a pointer to the underlying storage. 509   /// Return a pointer to the underlying storage.
HITCBC 510   203 void const* data() const noexcept 510   203 void const* data() const noexcept
511   { 511   {
HITCBC 512   203 return storage_; 512   203 return storage_;
513   } 513   }
514   514  
515   /// Return the size of the underlying storage. 515   /// Return the size of the underlying storage.
516   std::size_t size() const noexcept; 516   std::size_t size() const noexcept;
517   517  
518   /** Normalize after `getsockopt`. 518   /** Normalize after `getsockopt`.
519   519  
520   No-op — `struct linger` is always returned at full size. 520   No-op — `struct linger` is always returned at full size.
521   521  
522   @param s The number of bytes actually written by `getsockopt`. 522   @param s The number of bytes actually written by `getsockopt`.
523   */ 523   */
HITCBC 524   12 void resize(std::size_t) noexcept {} 524   12 void resize(std::size_t) noexcept {}
525   }; 525   };
526   526  
527   /** Enable loopback of outgoing multicast on IPv4 (IP_MULTICAST_LOOP). 527   /** Enable loopback of outgoing multicast on IPv4 (IP_MULTICAST_LOOP).
528   528  
529   Uses single-byte storage because BSD-derived kernels (macOS, FreeBSD) 529   Uses single-byte storage because BSD-derived kernels (macOS, FreeBSD)
530   reject the four-byte form with `EINVAL`. Linux accepts either size. 530   reject the four-byte form with `EINVAL`. Linux accepts either size.
531   531  
532   @par Example 532   @par Example
533   @par !example multicast_loop_v4 533   @par !example multicast_loop_v4
534   */ 534   */
535   class BOOST_COROSIO_DECL multicast_loop_v4 : public byte_boolean_option 535   class BOOST_COROSIO_DECL multicast_loop_v4 : public byte_boolean_option
536   { 536   {
537   public: 537   public:
538   using byte_boolean_option::byte_boolean_option; 538   using byte_boolean_option::byte_boolean_option;
539   using byte_boolean_option::operator=; 539   using byte_boolean_option::operator=;
540   540  
541   /// Return the protocol level. 541   /// Return the protocol level.
542   static int level() noexcept; 542   static int level() noexcept;
543   543  
544   /// Return the option name. 544   /// Return the option name.
545   static int name() noexcept; 545   static int name() noexcept;
546   }; 546   };
547   547  
548   /** Enable loopback of outgoing multicast on IPv6 (IPV6_MULTICAST_LOOP). 548   /** Enable loopback of outgoing multicast on IPv6 (IPV6_MULTICAST_LOOP).
549   549  
550   @par Example 550   @par Example
551   @par !example multicast_loop_v6 551   @par !example multicast_loop_v6
552   */ 552   */
553   class BOOST_COROSIO_DECL multicast_loop_v6 : public boolean_option 553   class BOOST_COROSIO_DECL multicast_loop_v6 : public boolean_option
554   { 554   {
555   public: 555   public:
556   using boolean_option::boolean_option; 556   using boolean_option::boolean_option;
557   using boolean_option::operator=; 557   using boolean_option::operator=;
558   558  
559   /// Return the protocol level. 559   /// Return the protocol level.
560   static int level() noexcept; 560   static int level() noexcept;
561   561  
562   /// Return the option name. 562   /// Return the option name.
563   static int name() noexcept; 563   static int name() noexcept;
564   }; 564   };
565   565  
566   /** Set the multicast TTL for IPv4 (IP_MULTICAST_TTL). 566   /** Set the multicast TTL for IPv4 (IP_MULTICAST_TTL).
567   567  
568   Uses single-byte storage because BSD-derived kernels (macOS, FreeBSD) 568   Uses single-byte storage because BSD-derived kernels (macOS, FreeBSD)
569   reject the four-byte form with `EINVAL`. Linux accepts either size. 569   reject the four-byte form with `EINVAL`. Linux accepts either size.
570   Values are truncated to the 0–255 range. 570   Values are truncated to the 0–255 range.
571   571  
572   @par Example 572   @par Example
573   @par !example multicast_hops_v4 573   @par !example multicast_hops_v4
574   */ 574   */
575   class BOOST_COROSIO_DECL multicast_hops_v4 : public byte_integer_option 575   class BOOST_COROSIO_DECL multicast_hops_v4 : public byte_integer_option
576   { 576   {
577   public: 577   public:
578   using byte_integer_option::byte_integer_option; 578   using byte_integer_option::byte_integer_option;
579   using byte_integer_option::operator=; 579   using byte_integer_option::operator=;
580   580  
581   /// Return the protocol level. 581   /// Return the protocol level.
582   static int level() noexcept; 582   static int level() noexcept;
583   583  
584   /// Return the option name. 584   /// Return the option name.
585   static int name() noexcept; 585   static int name() noexcept;
586   }; 586   };
587   587  
588   /** Set the multicast hop limit for IPv6 (IPV6_MULTICAST_HOPS). 588   /** Set the multicast hop limit for IPv6 (IPV6_MULTICAST_HOPS).
589   589  
590   @par Example 590   @par Example
591   @par !example multicast_hops_v6 591   @par !example multicast_hops_v6
592   */ 592   */
593   class BOOST_COROSIO_DECL multicast_hops_v6 : public integer_option 593   class BOOST_COROSIO_DECL multicast_hops_v6 : public integer_option
594   { 594   {
595   public: 595   public:
596   using integer_option::integer_option; 596   using integer_option::integer_option;
597   using integer_option::operator=; 597   using integer_option::operator=;
598   598  
599   /// Return the protocol level. 599   /// Return the protocol level.
600   static int level() noexcept; 600   static int level() noexcept;
601   601  
602   /// Return the option name. 602   /// Return the option name.
603   static int name() noexcept; 603   static int name() noexcept;
604   }; 604   };
605   605  
606   /** Set the outgoing interface for IPv6 multicast (IPV6_MULTICAST_IF). 606   /** Set the outgoing interface for IPv6 multicast (IPV6_MULTICAST_IF).
607   607  
608   @par Example 608   @par Example
609   @par !example multicast_interface_v6 609   @par !example multicast_interface_v6
610   */ 610   */
611   class BOOST_COROSIO_DECL multicast_interface_v6 : public integer_option 611   class BOOST_COROSIO_DECL multicast_interface_v6 : public integer_option
612   { 612   {
613   public: 613   public:
614   using integer_option::integer_option; 614   using integer_option::integer_option;
615   using integer_option::operator=; 615   using integer_option::operator=;
616   616  
617   /// Return the protocol level. 617   /// Return the protocol level.
618   static int level() noexcept; 618   static int level() noexcept;
619   619  
620   /// Return the option name. 620   /// Return the option name.
621   static int name() noexcept; 621   static int name() noexcept;
622   }; 622   };
623   623  
624   /** Join an IPv4 multicast group (IP_ADD_MEMBERSHIP). 624   /** Join an IPv4 multicast group (IP_ADD_MEMBERSHIP).
625   625  
626   @par Example 626   @par Example
627   @par !example join_group_v4 627   @par !example join_group_v4
628   */ 628   */
629   class BOOST_COROSIO_DECL join_group_v4 629   class BOOST_COROSIO_DECL join_group_v4
630   { 630   {
631   static constexpr std::size_t max_storage_ = 8; 631   static constexpr std::size_t max_storage_ = 8;
632   alignas(4) unsigned char storage_[max_storage_]{}; 632   alignas(4) unsigned char storage_[max_storage_]{};
633   633  
634   public: 634   public:
635   /// Construct with default values. 635   /// Construct with default values.
636   join_group_v4() noexcept = default; 636   join_group_v4() noexcept = default;
637   637  
638   /** Construct with a group and optional interface address. 638   /** Construct with a group and optional interface address.
639   639  
640   @param group The multicast group address to join. 640   @param group The multicast group address to join.
641   @param iface The local interface to use (default: any). 641   @param iface The local interface to use (default: any).
642   */ 642   */
643   join_group_v4( 643   join_group_v4(
644   ipv4_address group, ipv4_address iface = ipv4_address()) noexcept; 644   ipv4_address group, ipv4_address iface = ipv4_address()) noexcept;
645   645  
646   /// Return the protocol level. 646   /// Return the protocol level.
647   static int level() noexcept; 647   static int level() noexcept;
648   648  
649   /// Return the option name. 649   /// Return the option name.
650   static int name() noexcept; 650   static int name() noexcept;
651   651  
652   /// Return a pointer to the underlying storage. 652   /// Return a pointer to the underlying storage.
653   void* data() noexcept 653   void* data() noexcept
654   { 654   {
655   return storage_; 655   return storage_;
656   } 656   }
657   657  
658   /// Return a pointer to the underlying storage. 658   /// Return a pointer to the underlying storage.
HITCBC 659   4 void const* data() const noexcept 659   4 void const* data() const noexcept
660   { 660   {
HITCBC 661   4 return storage_; 661   4 return storage_;
662   } 662   }
663   663  
664   /// Return the size of the underlying storage. 664   /// Return the size of the underlying storage.
665   std::size_t size() const noexcept; 665   std::size_t size() const noexcept;
666   666  
667   /// No-op resize. 667   /// No-op resize.
668   void resize(std::size_t) noexcept {} 668   void resize(std::size_t) noexcept {}
669   }; 669   };
670   670  
671   /** Leave an IPv4 multicast group (IP_DROP_MEMBERSHIP). 671   /** Leave an IPv4 multicast group (IP_DROP_MEMBERSHIP).
672   672  
673   @par Example 673   @par Example
674   @par !example leave_group_v4 674   @par !example leave_group_v4
675   */ 675   */
676   class BOOST_COROSIO_DECL leave_group_v4 676   class BOOST_COROSIO_DECL leave_group_v4
677   { 677   {
678   static constexpr std::size_t max_storage_ = 8; 678   static constexpr std::size_t max_storage_ = 8;
679   alignas(4) unsigned char storage_[max_storage_]{}; 679   alignas(4) unsigned char storage_[max_storage_]{};
680   680  
681   public: 681   public:
682   /// Construct with default values. 682   /// Construct with default values.
683   leave_group_v4() noexcept = default; 683   leave_group_v4() noexcept = default;
684   684  
685   /** Construct with a group and optional interface address. 685   /** Construct with a group and optional interface address.
686   686  
687   @param group The multicast group address to leave. 687   @param group The multicast group address to leave.
688   @param iface The local interface (default: any). 688   @param iface The local interface (default: any).
689   */ 689   */
690   leave_group_v4( 690   leave_group_v4(
691   ipv4_address group, ipv4_address iface = ipv4_address()) noexcept; 691   ipv4_address group, ipv4_address iface = ipv4_address()) noexcept;
692   692  
693   /// Return the protocol level. 693   /// Return the protocol level.
694   static int level() noexcept; 694   static int level() noexcept;
695   695  
696   /// Return the option name. 696   /// Return the option name.
697   static int name() noexcept; 697   static int name() noexcept;
698   698  
699   /// Return a pointer to the underlying storage. 699   /// Return a pointer to the underlying storage.
700   void* data() noexcept 700   void* data() noexcept
701   { 701   {
702   return storage_; 702   return storage_;
703   } 703   }
704   704  
705   /// Return a pointer to the underlying storage. 705   /// Return a pointer to the underlying storage.
HITCBC 706   2 void const* data() const noexcept 706   2 void const* data() const noexcept
707   { 707   {
HITCBC 708   2 return storage_; 708   2 return storage_;
709   } 709   }
710   710  
711   /// Return the size of the underlying storage. 711   /// Return the size of the underlying storage.
712   std::size_t size() const noexcept; 712   std::size_t size() const noexcept;
713   713  
714   /// No-op resize. 714   /// No-op resize.
715   void resize(std::size_t) noexcept {} 715   void resize(std::size_t) noexcept {}
716   }; 716   };
717   717  
718   /** Join an IPv6 multicast group (IPV6_JOIN_GROUP). 718   /** Join an IPv6 multicast group (IPV6_JOIN_GROUP).
719   719  
720   @par Example 720   @par Example
721   @par !example join_group_v6 721   @par !example join_group_v6
722   */ 722   */
723   class BOOST_COROSIO_DECL join_group_v6 723   class BOOST_COROSIO_DECL join_group_v6
724   { 724   {
725   static constexpr std::size_t max_storage_ = 20; 725   static constexpr std::size_t max_storage_ = 20;
726   alignas(4) unsigned char storage_[max_storage_]{}; 726   alignas(4) unsigned char storage_[max_storage_]{};
727   727  
728   public: 728   public:
729   /// Construct with default values. 729   /// Construct with default values.
730   join_group_v6() noexcept = default; 730   join_group_v6() noexcept = default;
731   731  
732   /** Construct with a group and optional interface index. 732   /** Construct with a group and optional interface index.
733   733  
734   @param group The multicast group address to join. 734   @param group The multicast group address to join.
735   @param if_index The interface index (0 = kernel chooses). 735   @param if_index The interface index (0 = kernel chooses).
736   */ 736   */
737   join_group_v6(ipv6_address group, unsigned int if_index = 0) noexcept; 737   join_group_v6(ipv6_address group, unsigned int if_index = 0) noexcept;
738   738  
739   /// Return the protocol level. 739   /// Return the protocol level.
740   static int level() noexcept; 740   static int level() noexcept;
741   741  
742   /// Return the option name. 742   /// Return the option name.
743   static int name() noexcept; 743   static int name() noexcept;
744   744  
745   /// Return a pointer to the underlying storage. 745   /// Return a pointer to the underlying storage.
746   void* data() noexcept 746   void* data() noexcept
747   { 747   {
748   return storage_; 748   return storage_;
749   } 749   }
750   750  
751   /// Return a pointer to the underlying storage. 751   /// Return a pointer to the underlying storage.
HITCBC 752   2 void const* data() const noexcept 752   2 void const* data() const noexcept
753   { 753   {
HITCBC 754   2 return storage_; 754   2 return storage_;
755   } 755   }
756   756  
757   /// Return the size of the underlying storage. 757   /// Return the size of the underlying storage.
758   std::size_t size() const noexcept; 758   std::size_t size() const noexcept;
759   759  
760   /// No-op resize. 760   /// No-op resize.
761   void resize(std::size_t) noexcept {} 761   void resize(std::size_t) noexcept {}
762   }; 762   };
763   763  
764   /** Leave an IPv6 multicast group (IPV6_LEAVE_GROUP). 764   /** Leave an IPv6 multicast group (IPV6_LEAVE_GROUP).
765   765  
766   @par Example 766   @par Example
767   @par !example leave_group_v6 767   @par !example leave_group_v6
768   */ 768   */
769   class BOOST_COROSIO_DECL leave_group_v6 769   class BOOST_COROSIO_DECL leave_group_v6
770   { 770   {
771   static constexpr std::size_t max_storage_ = 20; 771   static constexpr std::size_t max_storage_ = 20;
772   alignas(4) unsigned char storage_[max_storage_]{}; 772   alignas(4) unsigned char storage_[max_storage_]{};
773   773  
774   public: 774   public:
775   /// Construct with default values. 775   /// Construct with default values.
776   leave_group_v6() noexcept = default; 776   leave_group_v6() noexcept = default;
777   777  
778   /** Construct with a group and optional interface index. 778   /** Construct with a group and optional interface index.
779   779  
780   @param group The multicast group address to leave. 780   @param group The multicast group address to leave.
781   @param if_index The interface index (0 = kernel chooses). 781   @param if_index The interface index (0 = kernel chooses).
782   */ 782   */
783   leave_group_v6(ipv6_address group, unsigned int if_index = 0) noexcept; 783   leave_group_v6(ipv6_address group, unsigned int if_index = 0) noexcept;
784   784  
785   /// Return the protocol level. 785   /// Return the protocol level.
786   static int level() noexcept; 786   static int level() noexcept;
787   787  
788   /// Return the option name. 788   /// Return the option name.
789   static int name() noexcept; 789   static int name() noexcept;
790   790  
791   /// Return a pointer to the underlying storage. 791   /// Return a pointer to the underlying storage.
HITCBC 792   2 void* data() noexcept 792   2 void* data() noexcept
793   { 793   {
HITCBC 794   2 return storage_; 794   2 return storage_;
795   } 795   }
796   796  
797   /// Return a pointer to the underlying storage. 797   /// Return a pointer to the underlying storage.
HITCBC 798   2 void const* data() const noexcept 798   2 void const* data() const noexcept
799   { 799   {
HITCBC 800   2 return storage_; 800   2 return storage_;
801   } 801   }
802   802  
803   /// Return the size of the underlying storage. 803   /// Return the size of the underlying storage.
804   std::size_t size() const noexcept; 804   std::size_t size() const noexcept;
805   805  
806   /// No-op resize. 806   /// No-op resize.
807   void resize(std::size_t) noexcept {} 807   void resize(std::size_t) noexcept {}
808   }; 808   };
809   809  
810   /** Set the outgoing interface for IPv4 multicast (IP_MULTICAST_IF). 810   /** Set the outgoing interface for IPv4 multicast (IP_MULTICAST_IF).
811   811  
812   Unlike the integer-based `multicast_interface_v6`, this option 812   Unlike the integer-based `multicast_interface_v6`, this option
813   takes an `ipv4_address` identifying the local interface. 813   takes an `ipv4_address` identifying the local interface.
814   814  
815   @par Example 815   @par Example
816   @par !example multicast_interface_v4 816   @par !example multicast_interface_v4
817   */ 817   */
818   class BOOST_COROSIO_DECL multicast_interface_v4 818   class BOOST_COROSIO_DECL multicast_interface_v4
819   { 819   {
820   static constexpr std::size_t max_storage_ = 4; 820   static constexpr std::size_t max_storage_ = 4;
821   alignas(4) unsigned char storage_[max_storage_]{}; 821   alignas(4) unsigned char storage_[max_storage_]{};
822   822  
823   public: 823   public:
824   /// Construct with default values (INADDR_ANY). 824   /// Construct with default values (INADDR_ANY).
825   multicast_interface_v4() noexcept = default; 825   multicast_interface_v4() noexcept = default;
826   826  
827   /** Construct with an interface address. 827   /** Construct with an interface address.
828   828  
829   @param iface The local interface address. 829   @param iface The local interface address.
830   */ 830   */
831   explicit multicast_interface_v4(ipv4_address iface) noexcept; 831   explicit multicast_interface_v4(ipv4_address iface) noexcept;
832   832  
833   /// Return the protocol level. 833   /// Return the protocol level.
834   static int level() noexcept; 834   static int level() noexcept;
835   835  
836   /// Return the option name. 836   /// Return the option name.
837   static int name() noexcept; 837   static int name() noexcept;
838   838  
839   /// Return a pointer to the underlying storage. 839   /// Return a pointer to the underlying storage.
840   void* data() noexcept 840   void* data() noexcept
841   { 841   {
842   return storage_; 842   return storage_;
843   } 843   }
844   844  
845   /// Return a pointer to the underlying storage. 845   /// Return a pointer to the underlying storage.
HITCBC 846   2 void const* data() const noexcept 846   2 void const* data() const noexcept
847   { 847   {
HITCBC 848   2 return storage_; 848   2 return storage_;
849   } 849   }
850   850  
851   /// Return the size of the underlying storage. 851   /// Return the size of the underlying storage.
852   std::size_t size() const noexcept; 852   std::size_t size() const noexcept;
853   853  
854   /// No-op resize. 854   /// No-op resize.
855   void resize(std::size_t) noexcept {} 855   void resize(std::size_t) noexcept {}
856   }; 856   };
857   857  
858   } // namespace boost::corosio::socket_option 858   } // namespace boost::corosio::socket_option
859   859  
860   #endif // BOOST_COROSIO_SOCKET_OPTION_HPP 860   #endif // BOOST_COROSIO_SOCKET_OPTION_HPP