TLA Line data 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 HIT 469 : explicit boolean_option(bool v) noexcept : value_(v ? 1 : 0) {}
56 :
57 : /// Assign a new value.
58 4 : boolean_option& operator=(bool v) noexcept
59 : {
60 4 : value_ = v ? 1 : 0;
61 4 : return *this;
62 : }
63 :
64 : /// Return the option value.
65 62 : bool value() const noexcept
66 : {
67 62 : return value_ != 0;
68 : }
69 :
70 : /// Return the option value.
71 4 : explicit operator bool() const noexcept
72 : {
73 4 : return value_ != 0;
74 : }
75 :
76 : /// Return the negated option value.
77 4 : bool operator!() const noexcept
78 : {
79 4 : return value_ == 0;
80 : }
81 :
82 : /// Return a pointer to the underlying storage.
83 78 : void* data() noexcept
84 : {
85 78 : return &value_;
86 : }
87 :
88 : /// Return a pointer to the underlying storage.
89 463 : void const* data() const noexcept
90 : {
91 463 : return &value_;
92 : }
93 :
94 : /// Return the size of the underlying storage.
95 541 : std::size_t size() const noexcept
96 : {
97 541 : 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 66 : void resize(std::size_t s) noexcept
107 : {
108 66 : if (s == sizeof(char))
109 MIS 0 : value_ = *reinterpret_cast<unsigned char*>(&value_) ? 1 : 0;
110 HIT 66 : }
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 65 : explicit integer_option(int v) noexcept : value_(v) {}
131 :
132 : /// Assign a new value.
133 2 : integer_option& operator=(int v) noexcept
134 : {
135 2 : value_ = v;
136 2 : return *this;
137 : }
138 :
139 : /// Return the option value.
140 46 : int value() const noexcept
141 : {
142 46 : return value_;
143 : }
144 :
145 : /// Return a pointer to the underlying storage.
146 44 : void* data() noexcept
147 : {
148 44 : return &value_;
149 : }
150 :
151 : /// Return a pointer to the underlying storage.
152 61 : void const* data() const noexcept
153 : {
154 61 : return &value_;
155 : }
156 :
157 : /// Return the size of the underlying storage.
158 105 : std::size_t size() const noexcept
159 : {
160 105 : 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 44 : void resize(std::size_t s) noexcept
168 : {
169 44 : if (s == sizeof(char))
170 MIS 0 : value_ =
171 0 : static_cast<int>(*reinterpret_cast<unsigned char*>(&value_));
172 HIT 44 : }
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 10 : 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 8 : bool value() const noexcept
205 : {
206 8 : 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 8 : void* data() noexcept
223 : {
224 8 : return &value_;
225 : }
226 :
227 : /// Return a pointer to the underlying storage.
228 10 : void const* data() const noexcept
229 : {
230 10 : return &value_;
231 : }
232 :
233 : /// Return the size of the underlying storage.
234 18 : std::size_t size() const noexcept
235 : {
236 18 : return sizeof(value_);
237 : }
238 :
239 : /// Storage is already one byte; no normalization needed.
240 8 : 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 4 : explicit byte_integer_option(int v) noexcept
262 4 : : value_(static_cast<unsigned char>(v))
263 4 : {}
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 4 : int value() const noexcept
274 : {
275 4 : return value_;
276 : }
277 :
278 : /// Return a pointer to the underlying storage.
279 4 : void* data() noexcept
280 : {
281 4 : return &value_;
282 : }
283 :
284 : /// Return a pointer to the underlying storage.
285 4 : void const* data() const noexcept
286 : {
287 4 : return &value_;
288 : }
289 :
290 : /// Return the size of the underlying storage.
291 8 : std::size_t size() const noexcept
292 : {
293 8 : return sizeof(value_);
294 : }
295 :
296 : /// Storage is already one byte; no normalization needed.
297 4 : 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 12 : void* data() noexcept
537 : {
538 12 : return storage_;
539 : }
540 :
541 : /// Return a pointer to the underlying storage.
542 152 : void const* data() const noexcept
543 : {
544 152 : 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 12 : 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 4 : void const* data() const noexcept
705 : {
706 4 : 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 2 : void const* data() const noexcept
755 : {
756 2 : 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 2 : void const* data() const noexcept
804 : {
805 2 : 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 2 : void const* data() const noexcept
853 : {
854 2 : 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 2 : void const* data() const noexcept
904 : {
905 2 : 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
|