include/boost/corosio/socket_option.hpp

95.9% Lines (71/0/74) 100.0% List of functions (36/0/36)
socket_option.hpp
f(x) Functions (36)
Function Calls Lines Blocks
boost::corosio::socket_option::boolean_option::boolean_option(bool) :55 469x 100.0% 100.0% boost::corosio::socket_option::boolean_option::operator=(bool) :58 4x 100.0% 100.0% boost::corosio::socket_option::boolean_option::value() const :65 62x 100.0% 100.0% boost::corosio::socket_option::boolean_option::operator bool() const :71 4x 100.0% 100.0% boost::corosio::socket_option::boolean_option::operator!() const :77 4x 100.0% 100.0% boost::corosio::socket_option::boolean_option::data() :83 78x 100.0% 100.0% boost::corosio::socket_option::boolean_option::data() const :89 463x 100.0% 100.0% boost::corosio::socket_option::boolean_option::size() const :95 541x 100.0% 100.0% boost::corosio::socket_option::boolean_option::resize(unsigned long) :106 66x 75.0% 33.0% boost::corosio::socket_option::integer_option::integer_option(int) :130 65x 100.0% 100.0% boost::corosio::socket_option::integer_option::operator=(int) :133 2x 100.0% 100.0% boost::corosio::socket_option::integer_option::value() const :140 46x 100.0% 100.0% boost::corosio::socket_option::integer_option::data() :146 44x 100.0% 100.0% boost::corosio::socket_option::integer_option::data() const :152 61x 100.0% 100.0% boost::corosio::socket_option::integer_option::size() const :158 105x 100.0% 100.0% boost::corosio::socket_option::integer_option::resize(unsigned long) :167 44x 60.0% 67.0% boost::corosio::socket_option::byte_boolean_option::byte_boolean_option(bool) :194 10x 100.0% 100.0% boost::corosio::socket_option::byte_boolean_option::value() const :204 8x 100.0% 100.0% boost::corosio::socket_option::byte_boolean_option::data() :222 8x 100.0% 100.0% boost::corosio::socket_option::byte_boolean_option::data() const :228 10x 100.0% 100.0% boost::corosio::socket_option::byte_boolean_option::size() const :234 18x 100.0% 100.0% boost::corosio::socket_option::byte_boolean_option::resize(unsigned long) :240 8x 100.0% 100.0% boost::corosio::socket_option::byte_integer_option::byte_integer_option(int) :261 4x 100.0% 100.0% boost::corosio::socket_option::byte_integer_option::value() const :273 4x 100.0% 100.0% boost::corosio::socket_option::byte_integer_option::data() :279 4x 100.0% 100.0% boost::corosio::socket_option::byte_integer_option::data() const :285 4x 100.0% 100.0% boost::corosio::socket_option::byte_integer_option::size() const :291 8x 100.0% 100.0% boost::corosio::socket_option::byte_integer_option::resize(unsigned long) :297 4x 100.0% 100.0% boost::corosio::socket_option::linger::data() :536 12x 100.0% 100.0% boost::corosio::socket_option::linger::data() const :542 152x 100.0% 100.0% boost::corosio::socket_option::linger::resize(unsigned long) :556 12x 100.0% 100.0% boost::corosio::socket_option::join_group_v4::data() const :704 4x 100.0% 100.0% boost::corosio::socket_option::leave_group_v4::data() const :754 2x 100.0% 100.0% boost::corosio::socket_option::join_group_v6::data() const :803 2x 100.0% 100.0% boost::corosio::socket_option::leave_group_v6::data() const :852 2x 100.0% 100.0% boost::corosio::socket_option::multicast_interface_v4::data() const :903 2x 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 #ifndef BOOST_COROSIO_SOCKET_OPTION_HPP
11 #define BOOST_COROSIO_SOCKET_OPTION_HPP
12
13 #include <boost/corosio/detail/config.hpp>
14 #include <boost/corosio/ipv4_address.hpp>
15 #include <boost/corosio/ipv6_address.hpp>
16
17 #include <cstddef>
18
19 /** @file socket_option.hpp
20
21 Type-erased socket option types that avoid platform-specific
22 headers. The protocol level and option name for each type are
23 resolved at link time via the compiled library.
24
25 For an inline (zero-overhead) alternative that includes platform
26 headers, use `<boost/corosio/native/native_socket_option.hpp>`
27 (`boost::corosio::native_socket_option`).
28
29 Both variants satisfy the same option-type interface and work
30 interchangeably with `tcp_socket::set_option` /
31 `tcp_socket::get_option` and the corresponding acceptor methods.
32
33 @see native_socket_option
34 */
35
36 namespace boost::corosio::socket_option {
37
38 /** Base class for concrete boolean socket options.
39
40 Stores a boolean as an `int` suitable for `setsockopt`/`getsockopt`.
41 Derived types provide `level()` and `name()` for the specific option.
42 */
43 class BOOST_COROSIO_DECL boolean_option
44 {
45 int value_ = 0;
46
47 public:
48 /// Construct with default value (disabled).
49 boolean_option() = default;
50
51 /** Construct with an explicit value.
52
53 @param v `true` to enable the option, `false` to disable.
54 */
55 469x explicit boolean_option(bool v) noexcept : value_(v ? 1 : 0) {}
56
57 /// Assign a new value.
58 4x boolean_option& operator=(bool v) noexcept
59 {
60 4x value_ = v ? 1 : 0;
61 4x return *this;
62 }
63
64 /// Return the option value.
65 62x bool value() const noexcept
66 {
67 62x return value_ != 0;
68 }
69
70 /// Return the option value.
71 4x explicit operator bool() const noexcept
72 {
73 4x return value_ != 0;
74 }
75
76 /// Return the negated option value.
77 4x bool operator!() const noexcept
78 {
79 4x return value_ == 0;
80 }
81
82 /// Return a pointer to the underlying storage.
83 78x void* data() noexcept
84 {
85 78x return &value_;
86 }
87
88 /// Return a pointer to the underlying storage.
89 463x void const* data() const noexcept
90 {
91 463x return &value_;
92 }
93
94 /// Return the size of the underlying storage.
95 541x std::size_t size() const noexcept
96 {
97 541x return sizeof(value_);
98 }
99
100 /** Normalize after `getsockopt` returns fewer bytes than expected.
101
102 Windows Vista+ may write only 1 byte for boolean options.
103
104 @param s The number of bytes actually written by `getsockopt`.
105 */
106 66x void resize(std::size_t s) noexcept
107 {
108 66x if (s == sizeof(char))
109 value_ = *reinterpret_cast<unsigned char*>(&value_) ? 1 : 0;
110 66x }
111 };
112
113 /** Base class for concrete integer socket options.
114
115 Stores an integer suitable for `setsockopt`/`getsockopt`.
116 Derived types provide `level()` and `name()` for the specific option.
117 */
118 class BOOST_COROSIO_DECL integer_option
119 {
120 int value_ = 0;
121
122 public:
123 /// Construct with default value (zero).
124 integer_option() = default;
125
126 /** Construct with an explicit value.
127
128 @param v The option value.
129 */
130 65x explicit integer_option(int v) noexcept : value_(v) {}
131
132 /// Assign a new value.
133 2x integer_option& operator=(int v) noexcept
134 {
135 2x value_ = v;
136 2x return *this;
137 }
138
139 /// Return the option value.
140 46x int value() const noexcept
141 {
142 46x return value_;
143 }
144
145 /// Return a pointer to the underlying storage.
146 44x void* data() noexcept
147 {
148 44x return &value_;
149 }
150
151 /// Return a pointer to the underlying storage.
152 61x void const* data() const noexcept
153 {
154 61x return &value_;
155 }
156
157 /// Return the size of the underlying storage.
158 105x std::size_t size() const noexcept
159 {
160 105x return sizeof(value_);
161 }
162
163 /** Normalize after `getsockopt` returns fewer bytes than expected.
164
165 @param s The number of bytes actually written by `getsockopt`.
166 */
167 44x void resize(std::size_t s) noexcept
168 {
169 44x if (s == sizeof(char))
170 value_ =
171 static_cast<int>(*reinterpret_cast<unsigned char*>(&value_));
172 44x }
173 };
174
175 /** Base class for concrete boolean socket options with single-byte storage.
176
177 Some BSD-derived kernels (macOS, FreeBSD) require certain IPv4 multicast
178 options (`IP_MULTICAST_LOOP`) to be set with a one-byte value and return
179 `EINVAL` for the four-byte form that Linux accepts. This base provides
180 `unsigned char` storage so the same options work on every platform.
181 */
182 class BOOST_COROSIO_DECL byte_boolean_option
183 {
184 unsigned char value_ = 0;
185
186 public:
187 /// Construct with default value (disabled).
188 byte_boolean_option() = default;
189
190 /** Construct with an explicit value.
191
192 @param v `true` to enable the option, `false` to disable.
193 */
194 10x explicit byte_boolean_option(bool v) noexcept : value_(v ? 1 : 0) {}
195
196 /// Assign a new value.
197 byte_boolean_option& operator=(bool v) noexcept
198 {
199 value_ = v ? 1 : 0;
200 return *this;
201 }
202
203 /// Return the option value.
204 8x bool value() const noexcept
205 {
206 8x return value_ != 0;
207 }
208
209 /// Return the option value.
210 explicit operator bool() const noexcept
211 {
212 return value_ != 0;
213 }
214
215 /// Return the negated option value.
216 bool operator!() const noexcept
217 {
218 return value_ == 0;
219 }
220
221 /// Return a pointer to the underlying storage.
222 8x void* data() noexcept
223 {
224 8x return &value_;
225 }
226
227 /// Return a pointer to the underlying storage.
228 10x void const* data() const noexcept
229 {
230 10x return &value_;
231 }
232
233 /// Return the size of the underlying storage.
234 18x std::size_t size() const noexcept
235 {
236 18x return sizeof(value_);
237 }
238
239 /// Storage is already one byte; no normalization needed.
240 8x void resize(std::size_t) noexcept {}
241 };
242
243 /** Base class for concrete integer socket options with single-byte storage.
244
245 Same rationale as `byte_boolean_option`: BSD-derived kernels require
246 `IP_MULTICAST_TTL` to be set with a one-byte value. Linux accepts
247 one-byte too, so single-byte storage is portable.
248 */
249 class BOOST_COROSIO_DECL byte_integer_option
250 {
251 unsigned char value_ = 0;
252
253 public:
254 /// Construct with default value (zero).
255 byte_integer_option() = default;
256
257 /** Construct with an explicit value.
258
259 @param v The option value; truncated to one byte.
260 */
261 4x explicit byte_integer_option(int v) noexcept
262 4x : value_(static_cast<unsigned char>(v))
263 4x {}
264
265 /// Assign a new value; truncated to one byte.
266 byte_integer_option& operator=(int v) noexcept
267 {
268 value_ = static_cast<unsigned char>(v);
269 return *this;
270 }
271
272 /// Return the option value.
273 4x int value() const noexcept
274 {
275 4x return value_;
276 }
277
278 /// Return a pointer to the underlying storage.
279 4x void* data() noexcept
280 {
281 4x return &value_;
282 }
283
284 /// Return a pointer to the underlying storage.
285 4x void const* data() const noexcept
286 {
287 4x return &value_;
288 }
289
290 /// Return the size of the underlying storage.
291 8x std::size_t size() const noexcept
292 {
293 8x return sizeof(value_);
294 }
295
296 /// Storage is already one byte; no normalization needed.
297 4x void resize(std::size_t) noexcept {}
298 };
299
300 /** Disable Nagle's algorithm (TCP_NODELAY).
301
302 @par Example
303 @code
304 sock.set_option( socket_option::no_delay( true ) );
305 auto nd = sock.get_option<socket_option::no_delay>();
306 bool disabled = nd.value(); // true: Nagle's algorithm is off
307 @endcode
308 */
309 class BOOST_COROSIO_DECL no_delay : public boolean_option
310 {
311 public:
312 using boolean_option::boolean_option;
313 using boolean_option::operator=;
314
315 /// Return the protocol level.
316 static int level() noexcept;
317
318 /// Return the option name.
319 static int name() noexcept;
320 };
321
322 /** Enable periodic keepalive probes (SO_KEEPALIVE).
323
324 @par Example
325 @code
326 sock.set_option( socket_option::keep_alive( true ) );
327 @endcode
328 */
329 class BOOST_COROSIO_DECL keep_alive : public boolean_option
330 {
331 public:
332 using boolean_option::boolean_option;
333 using boolean_option::operator=;
334
335 /// Return the protocol level.
336 static int level() noexcept;
337
338 /// Return the option name.
339 static int name() noexcept;
340 };
341
342 /** Restrict an IPv6 socket to IPv6 only (IPV6_V6ONLY).
343
344 When enabled, the socket only accepts IPv6 connections.
345 When disabled, the socket accepts both IPv4 and IPv6
346 connections (dual-stack mode).
347
348 @par Example
349 @code
350 sock.set_option( socket_option::v6_only( true ) );
351 @endcode
352 */
353 class BOOST_COROSIO_DECL v6_only : public boolean_option
354 {
355 public:
356 using boolean_option::boolean_option;
357 using boolean_option::operator=;
358
359 /// Return the protocol level.
360 static int level() noexcept;
361
362 /// Return the option name.
363 static int name() noexcept;
364 };
365
366 /** Allow local address reuse (SO_REUSEADDR).
367
368 @par Example
369 @code
370 acc.set_option( socket_option::reuse_address( true ) );
371 @endcode
372 */
373 class BOOST_COROSIO_DECL reuse_address : public boolean_option
374 {
375 public:
376 using boolean_option::boolean_option;
377 using boolean_option::operator=;
378
379 /// Return the protocol level.
380 static int level() noexcept;
381
382 /// Return the option name.
383 static int name() noexcept;
384 };
385
386 /** Allow sending to broadcast addresses (SO_BROADCAST).
387
388 Required for UDP sockets that send to broadcast addresses
389 such as 255.255.255.255. Without this option, `send_to`
390 returns an error.
391
392 @par Example
393 @code
394 udp_socket sock( ioc );
395 if ( auto ec = sock.open() )
396 return;
397 sock.set_option( socket_option::broadcast( true ) );
398 @endcode
399 */
400 class BOOST_COROSIO_DECL broadcast : public boolean_option
401 {
402 public:
403 using boolean_option::boolean_option;
404 using boolean_option::operator=;
405
406 /// Return the protocol level.
407 static int level() noexcept;
408
409 /// Return the option name.
410 static int name() noexcept;
411 };
412
413 /** Allow multiple sockets to bind to the same port (SO_REUSEPORT).
414
415 Not available on all platforms. On unsupported platforms,
416 `set_option` throws `std::system_error`.
417
418 @par Example
419 @code
420 if ( auto ec = acc.open( tcp::v6() ) )
421 return;
422 acc.set_option( socket_option::reuse_port( true ) );
423 if ( auto ec = acc.bind( endpoint( ipv6_address::any(), 8080 ) ) )
424 return;
425 if ( auto ec = acc.listen() )
426 return;
427 @endcode
428 */
429 class BOOST_COROSIO_DECL reuse_port : public boolean_option
430 {
431 public:
432 using boolean_option::boolean_option;
433 using boolean_option::operator=;
434
435 /// Return the protocol level.
436 static int level() noexcept;
437
438 /// Return the option name.
439 static int name() noexcept;
440 };
441
442 /** Set the receive buffer size (SO_RCVBUF).
443
444 @par Example
445 @code
446 sock.set_option( socket_option::receive_buffer_size( 65536 ) );
447 auto opt = sock.get_option<socket_option::receive_buffer_size>();
448 int sz = opt.value();
449 @endcode
450 */
451 class BOOST_COROSIO_DECL receive_buffer_size : public integer_option
452 {
453 public:
454 using integer_option::integer_option;
455 using integer_option::operator=;
456
457 /// Return the protocol level.
458 static int level() noexcept;
459
460 /// Return the option name.
461 static int name() noexcept;
462 };
463
464 /** Set the send buffer size (SO_SNDBUF).
465
466 @par Example
467 @code
468 sock.set_option( socket_option::send_buffer_size( 65536 ) );
469 @endcode
470 */
471 class BOOST_COROSIO_DECL send_buffer_size : public integer_option
472 {
473 public:
474 using integer_option::integer_option;
475 using integer_option::operator=;
476
477 /// Return the protocol level.
478 static int level() noexcept;
479
480 /// Return the option name.
481 static int name() noexcept;
482 };
483
484 /** The SO_LINGER socket option.
485
486 Controls behavior when closing a socket with unsent data.
487 When enabled, `close()` blocks until pending data is sent
488 or the timeout expires.
489
490 @par Example
491 @code
492 sock.set_option( socket_option::linger( true, 5 ) );
493 auto opt = sock.get_option<socket_option::linger>();
494 if ( opt.enabled() )
495 std::cout << "linger timeout: " << opt.timeout() << "s\n";
496 @endcode
497 */
498 class BOOST_COROSIO_DECL linger
499 {
500 // Opaque storage for the platform's struct linger.
501 // POSIX: { int, int } = 8 bytes.
502 // Windows: { u_short, u_short } = 4 bytes.
503 static constexpr std::size_t max_storage_ = 8;
504 alignas(4) unsigned char storage_[max_storage_]{};
505
506 public:
507 /// Construct with default values (disabled, zero timeout).
508 linger() noexcept = default;
509
510 /** Construct with explicit values.
511
512 @param enabled `true` to enable linger behavior on close.
513 @param timeout The linger timeout in seconds.
514 */
515 linger(bool enabled, int timeout) noexcept;
516
517 /// Return whether linger is enabled.
518 bool enabled() const noexcept;
519
520 /// Set whether linger is enabled.
521 void enabled(bool v) noexcept;
522
523 /// Return the linger timeout in seconds.
524 int timeout() const noexcept;
525
526 /// Set the linger timeout in seconds.
527 void timeout(int v) noexcept;
528
529 /// Return the protocol level.
530 static int level() noexcept;
531
532 /// Return the option name.
533 static int name() noexcept;
534
535 /// Return a pointer to the underlying storage.
536 12x void* data() noexcept
537 {
538 12x return storage_;
539 }
540
541 /// Return a pointer to the underlying storage.
542 152x void const* data() const noexcept
543 {
544 152x return storage_;
545 }
546
547 /// Return the size of the underlying storage.
548 std::size_t size() const noexcept;
549
550 /** Normalize after `getsockopt`.
551
552 No-op — `struct linger` is always returned at full size.
553
554 @param s The number of bytes actually written by `getsockopt`.
555 */
556 12x void resize(std::size_t) noexcept {}
557 };
558
559 /** Enable loopback of outgoing multicast on IPv4 (IP_MULTICAST_LOOP).
560
561 Uses single-byte storage because BSD-derived kernels (macOS, FreeBSD)
562 reject the four-byte form with `EINVAL`. Linux accepts either size.
563
564 @par Example
565 @code
566 sock.set_option( socket_option::multicast_loop_v4( true ) );
567 @endcode
568 */
569 class BOOST_COROSIO_DECL multicast_loop_v4 : public byte_boolean_option
570 {
571 public:
572 using byte_boolean_option::byte_boolean_option;
573 using byte_boolean_option::operator=;
574
575 /// Return the protocol level.
576 static int level() noexcept;
577
578 /// Return the option name.
579 static int name() noexcept;
580 };
581
582 /** Enable loopback of outgoing multicast on IPv6 (IPV6_MULTICAST_LOOP).
583
584 @par Example
585 @code
586 sock.set_option( socket_option::multicast_loop_v6( true ) );
587 @endcode
588 */
589 class BOOST_COROSIO_DECL multicast_loop_v6 : public boolean_option
590 {
591 public:
592 using boolean_option::boolean_option;
593 using boolean_option::operator=;
594
595 /// Return the protocol level.
596 static int level() noexcept;
597
598 /// Return the option name.
599 static int name() noexcept;
600 };
601
602 /** Set the multicast TTL for IPv4 (IP_MULTICAST_TTL).
603
604 Uses single-byte storage because BSD-derived kernels (macOS, FreeBSD)
605 reject the four-byte form with `EINVAL`. Linux accepts either size.
606 Values are truncated to the 0–255 range.
607
608 @par Example
609 @code
610 sock.set_option( socket_option::multicast_hops_v4( 4 ) );
611 @endcode
612 */
613 class BOOST_COROSIO_DECL multicast_hops_v4 : public byte_integer_option
614 {
615 public:
616 using byte_integer_option::byte_integer_option;
617 using byte_integer_option::operator=;
618
619 /// Return the protocol level.
620 static int level() noexcept;
621
622 /// Return the option name.
623 static int name() noexcept;
624 };
625
626 /** Set the multicast hop limit for IPv6 (IPV6_MULTICAST_HOPS).
627
628 @par Example
629 @code
630 sock.set_option( socket_option::multicast_hops_v6( 4 ) );
631 @endcode
632 */
633 class BOOST_COROSIO_DECL multicast_hops_v6 : public integer_option
634 {
635 public:
636 using integer_option::integer_option;
637 using integer_option::operator=;
638
639 /// Return the protocol level.
640 static int level() noexcept;
641
642 /// Return the option name.
643 static int name() noexcept;
644 };
645
646 /** Set the outgoing interface for IPv6 multicast (IPV6_MULTICAST_IF).
647
648 @par Example
649 @code
650 sock.set_option( socket_option::multicast_interface_v6( 1 ) );
651 @endcode
652 */
653 class BOOST_COROSIO_DECL multicast_interface_v6 : public integer_option
654 {
655 public:
656 using integer_option::integer_option;
657 using integer_option::operator=;
658
659 /// Return the protocol level.
660 static int level() noexcept;
661
662 /// Return the option name.
663 static int name() noexcept;
664 };
665
666 /** Join an IPv4 multicast group (IP_ADD_MEMBERSHIP).
667
668 @par Example
669 @code
670 sock.set_option( socket_option::join_group_v4(
671 ipv4_address( "239.255.0.1" ) ) );
672 @endcode
673 */
674 class BOOST_COROSIO_DECL join_group_v4
675 {
676 static constexpr std::size_t max_storage_ = 8;
677 alignas(4) unsigned char storage_[max_storage_]{};
678
679 public:
680 /// Construct with default values.
681 join_group_v4() noexcept = default;
682
683 /** Construct with a group and optional interface address.
684
685 @param group The multicast group address to join.
686 @param iface The local interface to use (default: any).
687 */
688 join_group_v4(
689 ipv4_address group, ipv4_address iface = ipv4_address()) noexcept;
690
691 /// Return the protocol level.
692 static int level() noexcept;
693
694 /// Return the option name.
695 static int name() noexcept;
696
697 /// Return a pointer to the underlying storage.
698 void* data() noexcept
699 {
700 return storage_;
701 }
702
703 /// Return a pointer to the underlying storage.
704 4x void const* data() const noexcept
705 {
706 4x return storage_;
707 }
708
709 /// Return the size of the underlying storage.
710 std::size_t size() const noexcept;
711
712 /// No-op resize.
713 void resize(std::size_t) noexcept {}
714 };
715
716 /** Leave an IPv4 multicast group (IP_DROP_MEMBERSHIP).
717
718 @par Example
719 @code
720 sock.set_option( socket_option::leave_group_v4(
721 ipv4_address( "239.255.0.1" ) ) );
722 @endcode
723 */
724 class BOOST_COROSIO_DECL leave_group_v4
725 {
726 static constexpr std::size_t max_storage_ = 8;
727 alignas(4) unsigned char storage_[max_storage_]{};
728
729 public:
730 /// Construct with default values.
731 leave_group_v4() noexcept = default;
732
733 /** Construct with a group and optional interface address.
734
735 @param group The multicast group address to leave.
736 @param iface The local interface (default: any).
737 */
738 leave_group_v4(
739 ipv4_address group, ipv4_address iface = ipv4_address()) noexcept;
740
741 /// Return the protocol level.
742 static int level() noexcept;
743
744 /// Return the option name.
745 static int name() noexcept;
746
747 /// Return a pointer to the underlying storage.
748 void* data() noexcept
749 {
750 return storage_;
751 }
752
753 /// Return a pointer to the underlying storage.
754 2x void const* data() const noexcept
755 {
756 2x return storage_;
757 }
758
759 /// Return the size of the underlying storage.
760 std::size_t size() const noexcept;
761
762 /// No-op resize.
763 void resize(std::size_t) noexcept {}
764 };
765
766 /** Join an IPv6 multicast group (IPV6_JOIN_GROUP).
767
768 @par Example
769 @code
770 sock.set_option( socket_option::join_group_v6(
771 ipv6_address( "ff02::1" ), 0 ) );
772 @endcode
773 */
774 class BOOST_COROSIO_DECL join_group_v6
775 {
776 static constexpr std::size_t max_storage_ = 20;
777 alignas(4) unsigned char storage_[max_storage_]{};
778
779 public:
780 /// Construct with default values.
781 join_group_v6() noexcept = default;
782
783 /** Construct with a group and optional interface index.
784
785 @param group The multicast group address to join.
786 @param if_index The interface index (0 = kernel chooses).
787 */
788 join_group_v6(ipv6_address group, unsigned int if_index = 0) noexcept;
789
790 /// Return the protocol level.
791 static int level() noexcept;
792
793 /// Return the option name.
794 static int name() noexcept;
795
796 /// Return a pointer to the underlying storage.
797 void* data() noexcept
798 {
799 return storage_;
800 }
801
802 /// Return a pointer to the underlying storage.
803 2x void const* data() const noexcept
804 {
805 2x return storage_;
806 }
807
808 /// Return the size of the underlying storage.
809 std::size_t size() const noexcept;
810
811 /// No-op resize.
812 void resize(std::size_t) noexcept {}
813 };
814
815 /** Leave an IPv6 multicast group (IPV6_LEAVE_GROUP).
816
817 @par Example
818 @code
819 sock.set_option( socket_option::leave_group_v6(
820 ipv6_address( "ff02::1" ), 0 ) );
821 @endcode
822 */
823 class BOOST_COROSIO_DECL leave_group_v6
824 {
825 static constexpr std::size_t max_storage_ = 20;
826 alignas(4) unsigned char storage_[max_storage_]{};
827
828 public:
829 /// Construct with default values.
830 leave_group_v6() noexcept = default;
831
832 /** Construct with a group and optional interface index.
833
834 @param group The multicast group address to leave.
835 @param if_index The interface index (0 = kernel chooses).
836 */
837 leave_group_v6(ipv6_address group, unsigned int if_index = 0) noexcept;
838
839 /// Return the protocol level.
840 static int level() noexcept;
841
842 /// Return the option name.
843 static int name() noexcept;
844
845 /// Return a pointer to the underlying storage.
846 void* data() noexcept
847 {
848 return storage_;
849 }
850
851 /// Return a pointer to the underlying storage.
852 2x void const* data() const noexcept
853 {
854 2x return storage_;
855 }
856
857 /// Return the size of the underlying storage.
858 std::size_t size() const noexcept;
859
860 /// No-op resize.
861 void resize(std::size_t) noexcept {}
862 };
863
864 /** Set the outgoing interface for IPv4 multicast (IP_MULTICAST_IF).
865
866 Unlike the integer-based `multicast_interface_v6`, this option
867 takes an `ipv4_address` identifying the local interface.
868
869 @par Example
870 @code
871 sock.set_option( socket_option::multicast_interface_v4(
872 ipv4_address( "192.168.1.1" ) ) );
873 @endcode
874 */
875 class BOOST_COROSIO_DECL multicast_interface_v4
876 {
877 static constexpr std::size_t max_storage_ = 4;
878 alignas(4) unsigned char storage_[max_storage_]{};
879
880 public:
881 /// Construct with default values (INADDR_ANY).
882 multicast_interface_v4() noexcept = default;
883
884 /** Construct with an interface address.
885
886 @param iface The local interface address.
887 */
888 explicit multicast_interface_v4(ipv4_address iface) noexcept;
889
890 /// Return the protocol level.
891 static int level() noexcept;
892
893 /// Return the option name.
894 static int name() noexcept;
895
896 /// Return a pointer to the underlying storage.
897 void* data() noexcept
898 {
899 return storage_;
900 }
901
902 /// Return a pointer to the underlying storage.
903 2x void const* data() const noexcept
904 {
905 2x return storage_;
906 }
907
908 /// Return the size of the underlying storage.
909 std::size_t size() const noexcept;
910
911 /// No-op resize.
912 void resize(std::size_t) noexcept {}
913 };
914
915 } // namespace boost::corosio::socket_option
916
917 #endif // BOOST_COROSIO_SOCKET_OPTION_HPP
918