1  
//
1  
//
2  
// Copyright (c) 2026 Steve Gerbino
2  
// Copyright (c) 2026 Steve Gerbino
3  
//
3  
//
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
5  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6  
//
6  
//
7  
// Official repository: https://github.com/cppalliance/corosio
7  
// Official repository: https://github.com/cppalliance/corosio
8  
//
8  
//
9  

9  

10  
#ifndef BOOST_COROSIO_SOCKET_OPTION_HPP
10  
#ifndef BOOST_COROSIO_SOCKET_OPTION_HPP
11  
#define BOOST_COROSIO_SOCKET_OPTION_HPP
11  
#define BOOST_COROSIO_SOCKET_OPTION_HPP
12  

12  

13  
#include <boost/corosio/detail/config.hpp>
13  
#include <boost/corosio/detail/config.hpp>
14  

14  

15  
#include <cstddef>
15  
#include <cstddef>
16  

16  

17  
/** @file socket_option.hpp
17  
/** @file socket_option.hpp
18  

18  

19  
    Type-erased socket option types that avoid platform-specific
19  
    Type-erased socket option types that avoid platform-specific
20  
    headers. The protocol level and option name for each type are
20  
    headers. The protocol level and option name for each type are
21  
    resolved at link time via the compiled library.
21  
    resolved at link time via the compiled library.
22  

22  

23  
    For an inline (zero-overhead) alternative that includes platform
23  
    For an inline (zero-overhead) alternative that includes platform
24  
    headers, use `<boost/corosio/native/native_socket_option.hpp>`
24  
    headers, use `<boost/corosio/native/native_socket_option.hpp>`
25  
    (`boost::corosio::native_socket_option`).
25  
    (`boost::corosio::native_socket_option`).
26  

26  

27  
    Both variants satisfy the same option-type interface and work
27  
    Both variants satisfy the same option-type interface and work
28  
    interchangeably with `tcp_socket::set_option` /
28  
    interchangeably with `tcp_socket::set_option` /
29  
    `tcp_socket::get_option` and the corresponding acceptor methods.
29  
    `tcp_socket::get_option` and the corresponding acceptor methods.
30  

30  

31  
    @see native_socket_option
31  
    @see native_socket_option
32  
*/
32  
*/
33  

33  

34  
namespace boost::corosio::socket_option {
34  
namespace boost::corosio::socket_option {
35  

35  

36  
/** Base class for concrete boolean socket options.
36  
/** Base class for concrete boolean socket options.
37  

37  

38  
    Stores a boolean as an `int` suitable for `setsockopt`/`getsockopt`.
38  
    Stores a boolean as an `int` suitable for `setsockopt`/`getsockopt`.
39  
    Derived types provide `level()` and `name()` for the specific option.
39  
    Derived types provide `level()` and `name()` for the specific option.
40  
*/
40  
*/
41  
class boolean_option
41  
class boolean_option
42  
{
42  
{
43  
    int value_ = 0;
43  
    int value_ = 0;
44  

44  

45  
public:
45  
public:
46  
    /// Construct with default value (disabled).
46  
    /// Construct with default value (disabled).
47  
    boolean_option() = default;
47  
    boolean_option() = default;
48  

48  

49  
    /** Construct with an explicit value.
49  
    /** Construct with an explicit value.
50  

50  

51  
        @param v `true` to enable the option, `false` to disable.
51  
        @param v `true` to enable the option, `false` to disable.
52  
    */
52  
    */
53 -
    explicit boolean_option( bool v ) noexcept : value_( v ? 1 : 0 ) {}
53 +
    explicit boolean_option(bool v) noexcept : value_(v ? 1 : 0) {}
54  

54  

55  
    /// Assign a new value.
55  
    /// Assign a new value.
56 -
    boolean_option& operator=( bool v ) noexcept
56 +
    boolean_option& operator=(bool v) noexcept
57  
    {
57  
    {
58  
        value_ = v ? 1 : 0;
58  
        value_ = v ? 1 : 0;
59  
        return *this;
59  
        return *this;
60  
    }
60  
    }
61  

61  

62  
    /// Return the option value.
62  
    /// Return the option value.
63 -
    bool value() const noexcept { return value_ != 0; }
63 +
    bool value() const noexcept
 
64 +
    {
 
65 +
        return value_ != 0;
 
66 +
    }
64  

67  

65  
    /// Return the option value.
68  
    /// Return the option value.
66 -
    explicit operator bool() const noexcept { return value_ != 0; }
69 +
    explicit operator bool() const noexcept
 
70 +
    {
 
71 +
        return value_ != 0;
 
72 +
    }
67  

73  

68  
    /// Return the negated option value.
74  
    /// Return the negated option value.
69 -
    bool operator!() const noexcept { return value_ == 0; }
75 +
    bool operator!() const noexcept
 
76 +
    {
 
77 +
        return value_ == 0;
 
78 +
    }
70  

79  

71  
    /// Return a pointer to the underlying storage.
80  
    /// Return a pointer to the underlying storage.
72 -
    void* data() noexcept { return &value_; }
81 +
    void* data() noexcept
 
82 +
    {
 
83 +
        return &value_;
 
84 +
    }
73  

85  

74  
    /// Return a pointer to the underlying storage.
86  
    /// Return a pointer to the underlying storage.
75 -
    void const* data() const noexcept { return &value_; }
87 +
    void const* data() const noexcept
 
88 +
    {
 
89 +
        return &value_;
 
90 +
    }
76  

91  

77  
    /// Return the size of the underlying storage.
92  
    /// Return the size of the underlying storage.
78 -
    std::size_t size() const noexcept { return sizeof( value_ ); }
93 +
    std::size_t size() const noexcept
 
94 +
    {
 
95 +
        return sizeof(value_);
 
96 +
    }
79  

97  

80  
    /** Normalize after `getsockopt` returns fewer bytes than expected.
98  
    /** Normalize after `getsockopt` returns fewer bytes than expected.
81  

99  

82  
        Windows Vista+ may write only 1 byte for boolean options.
100  
        Windows Vista+ may write only 1 byte for boolean options.
83  

101  

84  
        @param s The number of bytes actually written by `getsockopt`.
102  
        @param s The number of bytes actually written by `getsockopt`.
85  
    */
103  
    */
86 -
    void resize( std::size_t s ) noexcept
104 +
    void resize(std::size_t s) noexcept
87  
    {
105  
    {
88 -
        if ( s == sizeof( char ) )
106 +
        if (s == sizeof(char))
89 -
            value_ = *reinterpret_cast<unsigned char*>( &value_ ) ? 1 : 0;
107 +
            value_ = *reinterpret_cast<unsigned char*>(&value_) ? 1 : 0;
90  
    }
108  
    }
91  
};
109  
};
92  

110  

93  
/** Base class for concrete integer socket options.
111  
/** Base class for concrete integer socket options.
94  

112  

95  
    Stores an integer suitable for `setsockopt`/`getsockopt`.
113  
    Stores an integer suitable for `setsockopt`/`getsockopt`.
96  
    Derived types provide `level()` and `name()` for the specific option.
114  
    Derived types provide `level()` and `name()` for the specific option.
97  
*/
115  
*/
98  
class integer_option
116  
class integer_option
99  
{
117  
{
100  
    int value_ = 0;
118  
    int value_ = 0;
101  

119  

102  
public:
120  
public:
103  
    /// Construct with default value (zero).
121  
    /// Construct with default value (zero).
104  
    integer_option() = default;
122  
    integer_option() = default;
105  

123  

106  
    /** Construct with an explicit value.
124  
    /** Construct with an explicit value.
107  

125  

108  
        @param v The option value.
126  
        @param v The option value.
109  
    */
127  
    */
110 -
    explicit integer_option( int v ) noexcept : value_( v ) {}
128 +
    explicit integer_option(int v) noexcept : value_(v) {}
111  

129  

112  
    /// Assign a new value.
130  
    /// Assign a new value.
113 -
    integer_option& operator=( int v ) noexcept
131 +
    integer_option& operator=(int v) noexcept
114  
    {
132  
    {
115  
        value_ = v;
133  
        value_ = v;
116  
        return *this;
134  
        return *this;
117  
    }
135  
    }
118  

136  

119  
    /// Return the option value.
137  
    /// Return the option value.
120 -
    int value() const noexcept { return value_; }
138 +
    int value() const noexcept
 
139 +
    {
 
140 +
        return value_;
 
141 +
    }
121  

142  

122  
    /// Return a pointer to the underlying storage.
143  
    /// Return a pointer to the underlying storage.
123 -
    void* data() noexcept { return &value_; }
144 +
    void* data() noexcept
 
145 +
    {
 
146 +
        return &value_;
 
147 +
    }
124  

148  

125  
    /// Return a pointer to the underlying storage.
149  
    /// Return a pointer to the underlying storage.
126 -
    void const* data() const noexcept { return &value_; }
150 +
    void const* data() const noexcept
 
151 +
    {
 
152 +
        return &value_;
 
153 +
    }
127  

154  

128  
    /// Return the size of the underlying storage.
155  
    /// Return the size of the underlying storage.
129 -
    std::size_t size() const noexcept { return sizeof( value_ ); }
156 +
    std::size_t size() const noexcept
 
157 +
    {
 
158 +
        return sizeof(value_);
 
159 +
    }
130  

160  

131  
    /** Normalize after `getsockopt` returns fewer bytes than expected.
161  
    /** Normalize after `getsockopt` returns fewer bytes than expected.
132  

162  

133  
        @param s The number of bytes actually written by `getsockopt`.
163  
        @param s The number of bytes actually written by `getsockopt`.
134  
    */
164  
    */
135 -
    void resize( std::size_t s ) noexcept
165 +
    void resize(std::size_t s) noexcept
136  
    {
166  
    {
137 -
        if ( s == sizeof( char ) )
167 +
        if (s == sizeof(char))
138 -
            value_ = static_cast<int>(
168 +
            value_ =
139 -
                *reinterpret_cast<unsigned char*>( &value_ ) );
169 +
                static_cast<int>(*reinterpret_cast<unsigned char*>(&value_));
140  
    }
170  
    }
141  
};
171  
};
142  

172  

143  
/** Disable Nagle's algorithm (TCP_NODELAY).
173  
/** Disable Nagle's algorithm (TCP_NODELAY).
144  

174  

145  
    @par Example
175  
    @par Example
146  
    @code
176  
    @code
147  
    sock.set_option( socket_option::no_delay( true ) );
177  
    sock.set_option( socket_option::no_delay( true ) );
148  
    auto nd = sock.get_option<socket_option::no_delay>();
178  
    auto nd = sock.get_option<socket_option::no_delay>();
149  
    if ( nd.value() )
179  
    if ( nd.value() )
150  
        // Nagle's algorithm is disabled
180  
        // Nagle's algorithm is disabled
151  
    @endcode
181  
    @endcode
152  
*/
182  
*/
153  
class BOOST_COROSIO_DECL no_delay : public boolean_option
183  
class BOOST_COROSIO_DECL no_delay : public boolean_option
154  
{
184  
{
155  
public:
185  
public:
156  
    using boolean_option::boolean_option;
186  
    using boolean_option::boolean_option;
157  
    using boolean_option::operator=;
187  
    using boolean_option::operator=;
158  

188  

159  
    /// Return the protocol level.
189  
    /// Return the protocol level.
160  
    static int level() noexcept;
190  
    static int level() noexcept;
161  

191  

162  
    /// Return the option name.
192  
    /// Return the option name.
163  
    static int name() noexcept;
193  
    static int name() noexcept;
164  
};
194  
};
165  

195  

166  
/** Enable periodic keepalive probes (SO_KEEPALIVE).
196  
/** Enable periodic keepalive probes (SO_KEEPALIVE).
167  

197  

168  
    @par Example
198  
    @par Example
169  
    @code
199  
    @code
170  
    sock.set_option( socket_option::keep_alive( true ) );
200  
    sock.set_option( socket_option::keep_alive( true ) );
171  
    @endcode
201  
    @endcode
172  
*/
202  
*/
173  
class BOOST_COROSIO_DECL keep_alive : public boolean_option
203  
class BOOST_COROSIO_DECL keep_alive : public boolean_option
174  
{
204  
{
175  
public:
205  
public:
176  
    using boolean_option::boolean_option;
206  
    using boolean_option::boolean_option;
177  
    using boolean_option::operator=;
207  
    using boolean_option::operator=;
178  

208  

179  
    /// Return the protocol level.
209  
    /// Return the protocol level.
180  
    static int level() noexcept;
210  
    static int level() noexcept;
181  

211  

182  
    /// Return the option name.
212  
    /// Return the option name.
183  
    static int name() noexcept;
213  
    static int name() noexcept;
184  
};
214  
};
185  

215  

186  
/** Restrict an IPv6 socket to IPv6 only (IPV6_V6ONLY).
216  
/** Restrict an IPv6 socket to IPv6 only (IPV6_V6ONLY).
187  

217  

188  
    When enabled, the socket only accepts IPv6 connections.
218  
    When enabled, the socket only accepts IPv6 connections.
189  
    When disabled, the socket accepts both IPv4 and IPv6
219  
    When disabled, the socket accepts both IPv4 and IPv6
190  
    connections (dual-stack mode).
220  
    connections (dual-stack mode).
191  

221  

192  
    @par Example
222  
    @par Example
193  
    @code
223  
    @code
194  
    sock.set_option( socket_option::v6_only( true ) );
224  
    sock.set_option( socket_option::v6_only( true ) );
195  
    @endcode
225  
    @endcode
196  
*/
226  
*/
197  
class BOOST_COROSIO_DECL v6_only : public boolean_option
227  
class BOOST_COROSIO_DECL v6_only : public boolean_option
198  
{
228  
{
199  
public:
229  
public:
200  
    using boolean_option::boolean_option;
230  
    using boolean_option::boolean_option;
201  
    using boolean_option::operator=;
231  
    using boolean_option::operator=;
202  

232  

203  
    /// Return the protocol level.
233  
    /// Return the protocol level.
204  
    static int level() noexcept;
234  
    static int level() noexcept;
205  

235  

206  
    /// Return the option name.
236  
    /// Return the option name.
207  
    static int name() noexcept;
237  
    static int name() noexcept;
208  
};
238  
};
209  

239  

210  
/** Allow local address reuse (SO_REUSEADDR).
240  
/** Allow local address reuse (SO_REUSEADDR).
211  

241  

212  
    @par Example
242  
    @par Example
213  
    @code
243  
    @code
214  
    acc.set_option( socket_option::reuse_address( true ) );
244  
    acc.set_option( socket_option::reuse_address( true ) );
215  
    @endcode
245  
    @endcode
216  
*/
246  
*/
217  
class BOOST_COROSIO_DECL reuse_address : public boolean_option
247  
class BOOST_COROSIO_DECL reuse_address : public boolean_option
218  
{
248  
{
219  
public:
249  
public:
220  
    using boolean_option::boolean_option;
250  
    using boolean_option::boolean_option;
221  
    using boolean_option::operator=;
251  
    using boolean_option::operator=;
222  

252  

223  
    /// Return the protocol level.
253  
    /// Return the protocol level.
224  
    static int level() noexcept;
254  
    static int level() noexcept;
225  

255  

226  
    /// Return the option name.
256  
    /// Return the option name.
227  
    static int name() noexcept;
257  
    static int name() noexcept;
228  
};
258  
};
229  

259  

230  
/** Allow multiple sockets to bind to the same port (SO_REUSEPORT).
260  
/** Allow multiple sockets to bind to the same port (SO_REUSEPORT).
231  

261  

232  
    Not available on all platforms. On unsupported platforms,
262  
    Not available on all platforms. On unsupported platforms,
233  
    `set_option` will return an error.
263  
    `set_option` will return an error.
234  

264  

235  
    @par Example
265  
    @par Example
236  
    @code
266  
    @code
237  
    acc.open( tcp::v6() );
267  
    acc.open( tcp::v6() );
238  
    acc.set_option( socket_option::reuse_port( true ) );
268  
    acc.set_option( socket_option::reuse_port( true ) );
239  
    acc.bind( endpoint( ipv6_address::any(), 8080 ) );
269  
    acc.bind( endpoint( ipv6_address::any(), 8080 ) );
240  
    acc.listen();
270  
    acc.listen();
241  
    @endcode
271  
    @endcode
242  
*/
272  
*/
243  
class BOOST_COROSIO_DECL reuse_port : public boolean_option
273  
class BOOST_COROSIO_DECL reuse_port : public boolean_option
244  
{
274  
{
245  
public:
275  
public:
246  
    using boolean_option::boolean_option;
276  
    using boolean_option::boolean_option;
247  
    using boolean_option::operator=;
277  
    using boolean_option::operator=;
248  

278  

249  
    /// Return the protocol level.
279  
    /// Return the protocol level.
250  
    static int level() noexcept;
280  
    static int level() noexcept;
251  

281  

252  
    /// Return the option name.
282  
    /// Return the option name.
253  
    static int name() noexcept;
283  
    static int name() noexcept;
254  
};
284  
};
255  

285  

256  
/** Set the receive buffer size (SO_RCVBUF).
286  
/** Set the receive buffer size (SO_RCVBUF).
257  

287  

258  
    @par Example
288  
    @par Example
259  
    @code
289  
    @code
260  
    sock.set_option( socket_option::receive_buffer_size( 65536 ) );
290  
    sock.set_option( socket_option::receive_buffer_size( 65536 ) );
261  
    auto opt = sock.get_option<socket_option::receive_buffer_size>();
291  
    auto opt = sock.get_option<socket_option::receive_buffer_size>();
262  
    int sz = opt.value();
292  
    int sz = opt.value();
263  
    @endcode
293  
    @endcode
264  
*/
294  
*/
265  
class BOOST_COROSIO_DECL receive_buffer_size : public integer_option
295  
class BOOST_COROSIO_DECL receive_buffer_size : public integer_option
266  
{
296  
{
267  
public:
297  
public:
268  
    using integer_option::integer_option;
298  
    using integer_option::integer_option;
269  
    using integer_option::operator=;
299  
    using integer_option::operator=;
270  

300  

271  
    /// Return the protocol level.
301  
    /// Return the protocol level.
272  
    static int level() noexcept;
302  
    static int level() noexcept;
273  

303  

274  
    /// Return the option name.
304  
    /// Return the option name.
275  
    static int name() noexcept;
305  
    static int name() noexcept;
276  
};
306  
};
277  

307  

278  
/** Set the send buffer size (SO_SNDBUF).
308  
/** Set the send buffer size (SO_SNDBUF).
279  

309  

280  
    @par Example
310  
    @par Example
281  
    @code
311  
    @code
282  
    sock.set_option( socket_option::send_buffer_size( 65536 ) );
312  
    sock.set_option( socket_option::send_buffer_size( 65536 ) );
283  
    @endcode
313  
    @endcode
284  
*/
314  
*/
285  
class BOOST_COROSIO_DECL send_buffer_size : public integer_option
315  
class BOOST_COROSIO_DECL send_buffer_size : public integer_option
286  
{
316  
{
287  
public:
317  
public:
288  
    using integer_option::integer_option;
318  
    using integer_option::integer_option;
289  
    using integer_option::operator=;
319  
    using integer_option::operator=;
290  

320  

291  
    /// Return the protocol level.
321  
    /// Return the protocol level.
292  
    static int level() noexcept;
322  
    static int level() noexcept;
293  

323  

294  
    /// Return the option name.
324  
    /// Return the option name.
295  
    static int name() noexcept;
325  
    static int name() noexcept;
296  
};
326  
};
297  

327  

298  
/** The SO_LINGER socket option.
328  
/** The SO_LINGER socket option.
299  

329  

300  
    Controls behavior when closing a socket with unsent data.
330  
    Controls behavior when closing a socket with unsent data.
301  
    When enabled, `close()` blocks until pending data is sent
331  
    When enabled, `close()` blocks until pending data is sent
302  
    or the timeout expires.
332  
    or the timeout expires.
303  

333  

304  
    @par Example
334  
    @par Example
305  
    @code
335  
    @code
306  
    sock.set_option( socket_option::linger( true, 5 ) );
336  
    sock.set_option( socket_option::linger( true, 5 ) );
307  
    auto opt = sock.get_option<socket_option::linger>();
337  
    auto opt = sock.get_option<socket_option::linger>();
308  
    if ( opt.enabled() )
338  
    if ( opt.enabled() )
309  
        std::cout << "linger timeout: " << opt.timeout() << "s\n";
339  
        std::cout << "linger timeout: " << opt.timeout() << "s\n";
310  
    @endcode
340  
    @endcode
311  
*/
341  
*/
312  
class BOOST_COROSIO_DECL linger
342  
class BOOST_COROSIO_DECL linger
313  
{
343  
{
314  
    // Opaque storage for the platform's struct linger.
344  
    // Opaque storage for the platform's struct linger.
315  
    // POSIX: { int, int } = 8 bytes.
345  
    // POSIX: { int, int } = 8 bytes.
316  
    // Windows: { u_short, u_short } = 4 bytes.
346  
    // Windows: { u_short, u_short } = 4 bytes.
317  
    static constexpr std::size_t max_storage_ = 8;
347  
    static constexpr std::size_t max_storage_ = 8;
318 -
    alignas( 4 ) unsigned char storage_[max_storage_]{};
348 +
    alignas(4) unsigned char storage_[max_storage_]{};
319  

349  

320  
public:
350  
public:
321  
    /// Construct with default values (disabled, zero timeout).
351  
    /// Construct with default values (disabled, zero timeout).
322  
    linger() noexcept = default;
352  
    linger() noexcept = default;
323  

353  

324  
    /** Construct with explicit values.
354  
    /** Construct with explicit values.
325  

355  

326  
        @param enabled `true` to enable linger behavior on close.
356  
        @param enabled `true` to enable linger behavior on close.
327  
        @param timeout The linger timeout in seconds.
357  
        @param timeout The linger timeout in seconds.
328  
    */
358  
    */
329 -
    linger( bool enabled, int timeout ) noexcept;
359 +
    linger(bool enabled, int timeout) noexcept;
330  

360  

331  
    /// Return whether linger is enabled.
361  
    /// Return whether linger is enabled.
332  
    bool enabled() const noexcept;
362  
    bool enabled() const noexcept;
333  

363  

334  
    /// Set whether linger is enabled.
364  
    /// Set whether linger is enabled.
335 -
    void enabled( bool v ) noexcept;
365 +
    void enabled(bool v) noexcept;
336  

366  

337  
    /// Return the linger timeout in seconds.
367  
    /// Return the linger timeout in seconds.
338  
    int timeout() const noexcept;
368  
    int timeout() const noexcept;
339  

369  

340  
    /// Set the linger timeout in seconds.
370  
    /// Set the linger timeout in seconds.
341 -
    void timeout( int v ) noexcept;
371 +
    void timeout(int v) noexcept;
342  

372  

343  
    /// Return the protocol level.
373  
    /// Return the protocol level.
344  
    static int level() noexcept;
374  
    static int level() noexcept;
345  

375  

346  
    /// Return the option name.
376  
    /// Return the option name.
347  
    static int name() noexcept;
377  
    static int name() noexcept;
348  

378  

349  
    /// Return a pointer to the underlying storage.
379  
    /// Return a pointer to the underlying storage.
350 -
    void* data() noexcept { return storage_; }
380 +
    void* data() noexcept
 
381 +
    {
 
382 +
        return storage_;
 
383 +
    }
351  

384  

352  
    /// Return a pointer to the underlying storage.
385  
    /// Return a pointer to the underlying storage.
353 -
    void const* data() const noexcept { return storage_; }
386 +
    void const* data() const noexcept
 
387 +
    {
 
388 +
        return storage_;
 
389 +
    }
354  

390  

355  
    /// Return the size of the underlying storage.
391  
    /// Return the size of the underlying storage.
356  
    std::size_t size() const noexcept;
392  
    std::size_t size() const noexcept;
357  

393  

358  
    /** Normalize after `getsockopt`.
394  
    /** Normalize after `getsockopt`.
359  

395  

360  
        No-op — `struct linger` is always returned at full size.
396  
        No-op — `struct linger` is always returned at full size.
361  

397  

362  
        @param s The number of bytes actually written by `getsockopt`.
398  
        @param s The number of bytes actually written by `getsockopt`.
363  
    */
399  
    */
364 -
    void resize( std::size_t ) noexcept {}
400 +
    void resize(std::size_t) noexcept {}
365  
};
401  
};
366  

402  

367  
} // namespace boost::corosio::socket_option
403  
} // namespace boost::corosio::socket_option
368  

404  

369  
#endif // BOOST_COROSIO_SOCKET_OPTION_HPP
405  
#endif // BOOST_COROSIO_SOCKET_OPTION_HPP