include/boost/corosio/native/native_socket_option.hpp

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