include/boost/corosio/native/native_socket_option.hpp

100.0% Lines (165/0/165) 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() :273 22x 100.0% 100.0% boost::corosio::native_socket_option::byte_boolean<0, 34>::name() :274 22x 100.0% 100.0% boost::corosio::native_socket_option::byte_boolean<0, 34>::data() :276 2x 100.0% 100.0% boost::corosio::native_socket_option::byte_boolean<0, 34>::data() const :277 2x 100.0% 100.0% boost::corosio::native_socket_option::byte_boolean<0, 34>::size() const :278 4x 100.0% 100.0% boost::corosio::native_socket_option::byte_boolean<0, 34>::resize(unsigned long) :280 2x 100.0% 100.0% boost::corosio::native_socket_option::byte_integer<0, 33>::byte_integer(int) :301 2x 100.0% 100.0% boost::corosio::native_socket_option::byte_integer<0, 33>::value() const :311 2x 100.0% 100.0% boost::corosio::native_socket_option::byte_integer<0, 33>::level() :313 12x 100.0% 100.0% boost::corosio::native_socket_option::byte_integer<0, 33>::name() :314 12x 100.0% 100.0% boost::corosio::native_socket_option::byte_integer<0, 33>::data() :316 2x 100.0% 100.0% boost::corosio::native_socket_option::byte_integer<0, 33>::data() const :317 2x 100.0% 100.0% boost::corosio::native_socket_option::byte_integer<0, 33>::size() const :318 4x 100.0% 100.0% boost::corosio::native_socket_option::byte_integer<0, 33>::resize(unsigned long) :320 2x 100.0% 100.0% boost::corosio::native_socket_option::linger::linger() :342 215x 100.0% 100.0% boost::corosio::native_socket_option::linger::linger(bool, int) :349 203x 100.0% 100.0% boost::corosio::native_socket_option::linger::enabled() const :356 22x 100.0% 100.0% boost::corosio::native_socket_option::linger::enabled(bool) :362 4x 100.0% 75.0% boost::corosio::native_socket_option::linger::timeout() const :368 20x 100.0% 100.0% boost::corosio::native_socket_option::linger::timeout(int) :374 4x 100.0% 100.0% boost::corosio::native_socket_option::linger::level() :380 217x 100.0% 100.0% boost::corosio::native_socket_option::linger::name() :386 217x 100.0% 100.0% boost::corosio::native_socket_option::linger::data() :392 241x 100.0% 100.0% boost::corosio::native_socket_option::linger::data() const :398 2x 100.0% 100.0% boost::corosio::native_socket_option::linger::size() const :404 456x 100.0% 100.0% boost::corosio::native_socket_option::join_group_v4::join_group_v4() :470 4x 100.0% 100.0% boost::corosio::native_socket_option::join_group_v4::join_group_v4(boost::corosio::ipv4_address, boost::corosio::ipv4_address) :477 6x 100.0% 100.0% boost::corosio::native_socket_option::join_group_v4::level() :487 8x 100.0% 100.0% boost::corosio::native_socket_option::join_group_v4::name() :493 8x 100.0% 100.0% boost::corosio::native_socket_option::join_group_v4::data() :499 6x 100.0% 100.0% boost::corosio::native_socket_option::join_group_v4::data() const :505 2x 100.0% 100.0% boost::corosio::native_socket_option::join_group_v4::size() const :511 12x 100.0% 100.0% boost::corosio::native_socket_option::leave_group_v4::leave_group_v4() :531 2x 100.0% 100.0% boost::corosio::native_socket_option::leave_group_v4::leave_group_v4(boost::corosio::ipv4_address, boost::corosio::ipv4_address) :538 4x 100.0% 100.0% boost::corosio::native_socket_option::leave_group_v4::level() :548 6x 100.0% 100.0% boost::corosio::native_socket_option::leave_group_v4::name() :554 6x 100.0% 100.0% boost::corosio::native_socket_option::leave_group_v4::data() :560 4x 100.0% 100.0% boost::corosio::native_socket_option::leave_group_v4::data() const :566 2x 100.0% 100.0% boost::corosio::native_socket_option::leave_group_v4::size() const :572 8x 100.0% 100.0% boost::corosio::native_socket_option::join_group_v6::join_group_v6() :592 4x 100.0% 100.0% boost::corosio::native_socket_option::join_group_v6::join_group_v6(boost::corosio::ipv6_address, unsigned int) :599 6x 100.0% 100.0% boost::corosio::native_socket_option::join_group_v6::level() :607 8x 100.0% 100.0% boost::corosio::native_socket_option::join_group_v6::name() :613 8x 100.0% 100.0% boost::corosio::native_socket_option::join_group_v6::data() :619 6x 100.0% 100.0% boost::corosio::native_socket_option::join_group_v6::data() const :625 2x 100.0% 100.0% boost::corosio::native_socket_option::join_group_v6::size() const :631 12x 100.0% 100.0% boost::corosio::native_socket_option::leave_group_v6::leave_group_v6() :651 4x 100.0% 100.0% boost::corosio::native_socket_option::leave_group_v6::leave_group_v6(boost::corosio::ipv6_address, unsigned int) :658 6x 100.0% 100.0% boost::corosio::native_socket_option::leave_group_v6::level() :666 8x 100.0% 100.0% boost::corosio::native_socket_option::leave_group_v6::name() :672 8x 100.0% 100.0% boost::corosio::native_socket_option::leave_group_v6::data() :678 6x 100.0% 100.0% boost::corosio::native_socket_option::leave_group_v6::data() const :684 2x 100.0% 100.0% boost::corosio::native_socket_option::leave_group_v6::size() const :690 12x 100.0% 100.0% boost::corosio::native_socket_option::multicast_interface_v4::multicast_interface_v4() :713 2x 100.0% 100.0% boost::corosio::native_socket_option::multicast_interface_v4::multicast_interface_v4(boost::corosio::ipv4_address) :719 4x 100.0% 100.0% boost::corosio::native_socket_option::multicast_interface_v4::level() :726 6x 100.0% 100.0% boost::corosio::native_socket_option::multicast_interface_v4::name() :732 6x 100.0% 100.0% boost::corosio::native_socket_option::multicast_interface_v4::data() :738 4x 100.0% 100.0% boost::corosio::native_socket_option::multicast_interface_v4::data() const :744 2x 100.0% 100.0% boost::corosio::native_socket_option::multicast_interface_v4::size() const :750 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 { return value_ != 0; }
270 explicit operator bool() const noexcept { return value_ != 0; }
271 bool operator!() const noexcept { return value_ == 0; }
272
273 22x static constexpr int level() noexcept { return Level; }
274 22x static constexpr int name() noexcept { return Name; }
275
276 2x void* data() noexcept { return &value_; }
277 2x void const* data() const noexcept { return &value_; }
278 4x std::size_t size() const noexcept { return sizeof(value_); }
279
280 2x void resize(std::size_t) noexcept {}
281 };
282
283 /** An integer socket option with single-byte storage.
284
285 Same rationale as `byte_boolean`: BSD-derived kernels require
286 `IP_MULTICAST_TTL` to be set with a one-byte value. Linux accepts
287 one byte too, so single-byte storage is portable. Values are
288 truncated to the 0–255 range.
289
290 @tparam Level The protocol level.
291 @tparam Name The option name.
292 */
293 template<int Level, int Name>
294 class byte_integer
295 {
296 unsigned char value_ = 0;
297
298 public:
299 byte_integer() = default;
300
301 2x explicit byte_integer(int v) noexcept
302 2x : value_(static_cast<unsigned char>(v))
303 2x {}
304
305 byte_integer& operator=(int v) noexcept
306 {
307 value_ = static_cast<unsigned char>(v);
308 return *this;
309 }
310
311 2x int value() const noexcept { return value_; }
312
313 12x static constexpr int level() noexcept { return Level; }
314 12x static constexpr int name() noexcept { return Name; }
315
316 2x void* data() noexcept { return &value_; }
317 2x void const* data() const noexcept { return &value_; }
318 4x std::size_t size() const noexcept { return sizeof(value_); }
319
320 2x void resize(std::size_t) noexcept {}
321 };
322
323 /** The SO_LINGER socket option (native variant).
324
325 Controls behavior when closing a socket with unsent data.
326 When enabled, `close()` blocks until pending data is sent
327 or the timeout expires.
328
329 This variant stores the platform's `struct linger` directly,
330 avoiding the opaque-storage indirection of the type-erased
331 version.
332
333 @par Example
334 @par !example linger
335 */
336 class linger
337 {
338 struct ::linger value_{};
339
340 public:
341 /// Construct with default values (disabled, zero timeout).
342 215x linger() = default;
343
344 /** Construct with explicit values.
345
346 @param enabled `true` to enable linger behavior on close.
347 @param timeout The linger timeout in seconds.
348 */
349 203x linger(bool enabled, int timeout) noexcept
350 203x {
351 203x value_.l_onoff = enabled ? 1 : 0;
352 203x value_.l_linger = static_cast<decltype(value_.l_linger)>(timeout);
353 203x }
354
355 /// Return whether linger is enabled.
356 22x bool enabled() const noexcept
357 {
358 22x return value_.l_onoff != 0;
359 }
360
361 /// Set whether linger is enabled.
362 4x void enabled(bool v) noexcept
363 {
364 4x value_.l_onoff = v ? 1 : 0;
365 4x }
366
367 /// Return the linger timeout in seconds.
368 20x int timeout() const noexcept
369 {
370 20x return static_cast<int>(value_.l_linger);
371 }
372
373 /// Set the linger timeout in seconds.
374 4x void timeout(int v) noexcept
375 {
376 4x value_.l_linger = static_cast<decltype(value_.l_linger)>(v);
377 4x }
378
379 /// Return the protocol level for `setsockopt`/`getsockopt`.
380 217x static constexpr int level() noexcept
381 {
382 217x return SOL_SOCKET;
383 }
384
385 /// Return the option name for `setsockopt`/`getsockopt`.
386 217x static constexpr int name() noexcept
387 {
388 217x return SO_LINGER;
389 }
390
391 /// Return a pointer to the underlying storage.
392 241x void* data() noexcept
393 {
394 241x return &value_;
395 }
396
397 /// Return a pointer to the underlying storage.
398 2x void const* data() const noexcept
399 {
400 2x return &value_;
401 }
402
403 /// Return the size of the underlying storage.
404 456x std::size_t size() const noexcept
405 {
406 456x return sizeof(value_);
407 }
408
409 /** Normalize after `getsockopt`.
410
411 No-op — `struct linger` is always returned at full size.
412
413 @param s The number of bytes actually written by `getsockopt`.
414 */
415 void resize(std::size_t) noexcept {}
416 };
417
418 /// Disable Nagle's algorithm (TCP_NODELAY).
419 using no_delay = boolean<IPPROTO_TCP, TCP_NODELAY>;
420
421 /// Enable periodic keepalive probes (SO_KEEPALIVE).
422 using keep_alive = boolean<SOL_SOCKET, SO_KEEPALIVE>;
423
424 /// Restrict an IPv6 socket to IPv6 only (IPV6_V6ONLY).
425 using v6_only = boolean<IPPROTO_IPV6, IPV6_V6ONLY>;
426
427 /// Allow local address reuse (SO_REUSEADDR).
428 using reuse_address = boolean<SOL_SOCKET, SO_REUSEADDR>;
429
430 /// Allow sending to broadcast addresses (SO_BROADCAST).
431 using broadcast = boolean<SOL_SOCKET, SO_BROADCAST>;
432
433 /// Set the receive buffer size (SO_RCVBUF).
434 using receive_buffer_size = integer<SOL_SOCKET, SO_RCVBUF>;
435
436 /// Set the send buffer size (SO_SNDBUF).
437 using send_buffer_size = integer<SOL_SOCKET, SO_SNDBUF>;
438
439 #ifdef SO_REUSEPORT
440 /// Allow multiple sockets to bind to the same port (SO_REUSEPORT).
441 using reuse_port = boolean<SOL_SOCKET, SO_REUSEPORT>;
442 #endif
443
444 /// Enable loopback of outgoing multicast on IPv4 (IP_MULTICAST_LOOP).
445 using multicast_loop_v4 = byte_boolean<IPPROTO_IP, IP_MULTICAST_LOOP>;
446
447 /// Enable loopback of outgoing multicast on IPv6 (IPV6_MULTICAST_LOOP).
448 using multicast_loop_v6 = boolean<IPPROTO_IPV6, IPV6_MULTICAST_LOOP>;
449
450 /// Set the multicast TTL for IPv4 (IP_MULTICAST_TTL).
451 using multicast_hops_v4 = byte_integer<IPPROTO_IP, IP_MULTICAST_TTL>;
452
453 /// Set the multicast hop limit for IPv6 (IPV6_MULTICAST_HOPS).
454 using multicast_hops_v6 = integer<IPPROTO_IPV6, IPV6_MULTICAST_HOPS>;
455
456 /// Set the outgoing interface for IPv6 multicast (IPV6_MULTICAST_IF).
457 using multicast_interface_v6 = integer<IPPROTO_IPV6, IPV6_MULTICAST_IF>;
458
459 /** Join an IPv4 multicast group (IP_ADD_MEMBERSHIP).
460
461 @par Example
462 @par !example join_group_v4
463 */
464 class join_group_v4
465 {
466 struct ip_mreq value_{};
467
468 public:
469 /// Construct with default values.
470 4x join_group_v4() = default;
471
472 /** Construct with a group and optional interface address.
473
474 @param group The multicast group address to join.
475 @param iface The local interface to use (default: any).
476 */
477 6x join_group_v4(
478 ipv4_address group, ipv4_address iface = ipv4_address()) noexcept
479 6x {
480 6x auto gb = group.to_bytes();
481 6x auto ib = iface.to_bytes();
482 6x std::memcpy(&value_.imr_multiaddr, gb.data(), 4);
483 6x std::memcpy(&value_.imr_interface, ib.data(), 4);
484 6x }
485
486 /// Return the protocol level for `setsockopt`/`getsockopt`.
487 8x static constexpr int level() noexcept
488 {
489 8x return IPPROTO_IP;
490 }
491
492 /// Return the option name for `setsockopt`/`getsockopt`.
493 8x static constexpr int name() noexcept
494 {
495 8x return IP_ADD_MEMBERSHIP;
496 }
497
498 /// Return a pointer to the underlying storage.
499 6x void* data() noexcept
500 {
501 6x return &value_;
502 }
503
504 /// Return a pointer to the underlying storage.
505 2x void const* data() const noexcept
506 {
507 2x return &value_;
508 }
509
510 /// Return the size of the underlying storage.
511 12x std::size_t size() const noexcept
512 {
513 12x return sizeof(value_);
514 }
515
516 /// No-op resize.
517 void resize(std::size_t) noexcept {}
518 };
519
520 /** Leave an IPv4 multicast group (IP_DROP_MEMBERSHIP).
521
522 @par Example
523 @par !example leave_group_v4
524 */
525 class leave_group_v4
526 {
527 struct ip_mreq value_{};
528
529 public:
530 /// Construct with default values.
531 2x leave_group_v4() = default;
532
533 /** Construct with a group and optional interface address.
534
535 @param group The multicast group address to leave.
536 @param iface The local interface (default: any).
537 */
538 4x leave_group_v4(
539 ipv4_address group, ipv4_address iface = ipv4_address()) noexcept
540 4x {
541 4x auto gb = group.to_bytes();
542 4x auto ib = iface.to_bytes();
543 4x std::memcpy(&value_.imr_multiaddr, gb.data(), 4);
544 4x std::memcpy(&value_.imr_interface, ib.data(), 4);
545 4x }
546
547 /// Return the protocol level for `setsockopt`/`getsockopt`.
548 6x static constexpr int level() noexcept
549 {
550 6x return IPPROTO_IP;
551 }
552
553 /// Return the option name for `setsockopt`/`getsockopt`.
554 6x static constexpr int name() noexcept
555 {
556 6x return IP_DROP_MEMBERSHIP;
557 }
558
559 /// Return a pointer to the underlying storage.
560 4x void* data() noexcept
561 {
562 4x return &value_;
563 }
564
565 /// Return a pointer to the underlying storage.
566 2x void const* data() const noexcept
567 {
568 2x return &value_;
569 }
570
571 /// Return the size of the underlying storage.
572 8x std::size_t size() const noexcept
573 {
574 8x return sizeof(value_);
575 }
576
577 /// No-op resize.
578 void resize(std::size_t) noexcept {}
579 };
580
581 /** Join an IPv6 multicast group (IPV6_JOIN_GROUP).
582
583 @par Example
584 @par !example join_group_v6
585 */
586 class join_group_v6
587 {
588 struct ipv6_mreq value_{};
589
590 public:
591 /// Construct with default values.
592 4x join_group_v6() = default;
593
594 /** Construct with a group and optional interface index.
595
596 @param group The multicast group address to join.
597 @param if_index The interface index (0 = kernel chooses).
598 */
599 6x join_group_v6(ipv6_address group, unsigned int if_index = 0) noexcept
600 6x {
601 6x auto gb = group.to_bytes();
602 6x std::memcpy(&value_.ipv6mr_multiaddr, gb.data(), 16);
603 6x value_.ipv6mr_interface = if_index;
604 6x }
605
606 /// Return the protocol level for `setsockopt`/`getsockopt`.
607 8x static constexpr int level() noexcept
608 {
609 8x return IPPROTO_IPV6;
610 }
611
612 /// Return the option name for `setsockopt`/`getsockopt`.
613 8x static constexpr int name() noexcept
614 {
615 8x return IPV6_JOIN_GROUP;
616 }
617
618 /// Return a pointer to the underlying storage.
619 6x void* data() noexcept
620 {
621 6x return &value_;
622 }
623
624 /// Return a pointer to the underlying storage.
625 2x void const* data() const noexcept
626 {
627 2x return &value_;
628 }
629
630 /// Return the size of the underlying storage.
631 12x std::size_t size() const noexcept
632 {
633 12x return sizeof(value_);
634 }
635
636 /// No-op resize.
637 void resize(std::size_t) noexcept {}
638 };
639
640 /** Leave an IPv6 multicast group (IPV6_LEAVE_GROUP).
641
642 @par Example
643 @par !example leave_group_v6
644 */
645 class leave_group_v6
646 {
647 struct ipv6_mreq value_{};
648
649 public:
650 /// Construct with default values.
651 4x leave_group_v6() = default;
652
653 /** Construct with a group and optional interface index.
654
655 @param group The multicast group address to leave.
656 @param if_index The interface index (0 = kernel chooses).
657 */
658 6x leave_group_v6(ipv6_address group, unsigned int if_index = 0) noexcept
659 6x {
660 6x auto gb = group.to_bytes();
661 6x std::memcpy(&value_.ipv6mr_multiaddr, gb.data(), 16);
662 6x value_.ipv6mr_interface = if_index;
663 6x }
664
665 /// Return the protocol level for `setsockopt`/`getsockopt`.
666 8x static constexpr int level() noexcept
667 {
668 8x return IPPROTO_IPV6;
669 }
670
671 /// Return the option name for `setsockopt`/`getsockopt`.
672 8x static constexpr int name() noexcept
673 {
674 8x return IPV6_LEAVE_GROUP;
675 }
676
677 /// Return a pointer to the underlying storage.
678 6x void* data() noexcept
679 {
680 6x return &value_;
681 }
682
683 /// Return a pointer to the underlying storage.
684 2x void const* data() const noexcept
685 {
686 2x return &value_;
687 }
688
689 /// Return the size of the underlying storage.
690 12x std::size_t size() const noexcept
691 {
692 12x return sizeof(value_);
693 }
694
695 /// No-op resize.
696 void resize(std::size_t) noexcept {}
697 };
698
699 /** Set the outgoing interface for IPv4 multicast (IP_MULTICAST_IF).
700
701 Unlike the integer-based `multicast_interface_v6`, this option
702 takes an `ipv4_address` identifying the local interface.
703
704 @par Example
705 @par !example multicast_interface_v4
706 */
707 class multicast_interface_v4
708 {
709 struct in_addr value_{};
710
711 public:
712 /// Construct with default values (INADDR_ANY).
713 2x multicast_interface_v4() = default;
714
715 /** Construct with an interface address.
716
717 @param iface The local interface address.
718 */
719 4x explicit multicast_interface_v4(ipv4_address iface) noexcept
720 4x {
721 4x auto b = iface.to_bytes();
722 4x std::memcpy(&value_, b.data(), 4);
723 4x }
724
725 /// Return the protocol level for `setsockopt`/`getsockopt`.
726 6x static constexpr int level() noexcept
727 {
728 6x return IPPROTO_IP;
729 }
730
731 /// Return the option name for `setsockopt`/`getsockopt`.
732 6x static constexpr int name() noexcept
733 {
734 6x return IP_MULTICAST_IF;
735 }
736
737 /// Return a pointer to the underlying storage.
738 4x void* data() noexcept
739 {
740 4x return &value_;
741 }
742
743 /// Return a pointer to the underlying storage.
744 2x void const* data() const noexcept
745 {
746 2x return &value_;
747 }
748
749 /// Return the size of the underlying storage.
750 8x std::size_t size() const noexcept
751 {
752 8x return sizeof(value_);
753 }
754
755 /// No-op resize.
756 void resize(std::size_t) noexcept {}
757 };
758
759 } // namespace boost::corosio::native_socket_option
760
761 #endif // BOOST_COROSIO_NATIVE_NATIVE_SOCKET_OPTION_HPP
762