include/boost/corosio/native/native_socket_option.hpp

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