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 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 261 : 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 42 : bool value() const noexcept
66 : {
67 42 : 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 44 : void* data() noexcept
84 : {
85 44 : return &value_;
86 : }
87 :
88 : /// Return a pointer to the underlying storage.
89 261 : void const* data() const noexcept
90 : {
91 261 : return &value_;
92 : }
93 :
94 : /// Return the size of the underlying storage.
95 305 : std::size_t size() const noexcept
96 : {
97 305 : 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 44 : void resize(std::size_t s) noexcept
107 : {
108 44 : if (s == sizeof(char))
109 MIS 0 : value_ = *reinterpret_cast<unsigned char*>(&value_) ? 1 : 0;
110 HIT 44 : }
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 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 24 : 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 30 : int value() const noexcept
141 : {
142 30 : return value_;
143 : }
144 :
145 : /// Return a pointer to the underlying storage.
146 28 : void* data() noexcept
147 : {
148 28 : return &value_;
149 : }
150 :
151 : /// Return a pointer to the underlying storage.
152 24 : void const* data() const noexcept
153 : {
154 24 : return &value_;
155 : }
156 :
157 : /// Return the size of the underlying storage.
158 52 : std::size_t size() const noexcept
159 : {
160 52 : 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 28 : void resize(std::size_t s) noexcept
168 : {
169 28 : if (s == sizeof(char))
170 MIS 0 : value_ =
171 0 : static_cast<int>(*reinterpret_cast<unsigned char*>(&value_));
172 HIT 28 : }
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 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 6 : 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 4 : bool value() const noexcept
205 : {
206 4 : 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 4 : void* data() noexcept
223 : {
224 4 : return &value_;
225 : }
226 :
227 : /// Return a pointer to the underlying storage.
228 6 : void const* data() const noexcept
229 : {
230 6 : return &value_;
231 : }
232 :
233 : /// Return the size of the underlying storage.
234 10 : std::size_t size() const noexcept
235 : {
236 10 : return sizeof(value_);
237 : }
238 :
239 : /// Storage is already one byte; no normalization needed.
240 4 : 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 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 2 : explicit byte_integer_option(int v) noexcept
262 2 : : value_(static_cast<unsigned char>(v))
263 2 : {}
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 2 : int value() const noexcept
274 : {
275 2 : return value_;
276 : }
277 :
278 : /// Return a pointer to the underlying storage.
279 2 : void* data() noexcept
280 : {
281 2 : return &value_;
282 : }
283 :
284 : /// Return a pointer to the underlying storage.
285 2 : void const* data() const noexcept
286 : {
287 2 : return &value_;
288 : }
289 :
290 : /// Return the size of the underlying storage.
291 4 : std::size_t size() const noexcept
292 : {
293 4 : return sizeof(value_);
294 : }
295 :
296 : /// Storage is already one byte; no normalization needed.
297 2 : 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 : if ( nd.value() )
307 : // Nagle's algorithm is disabled
308 : @endcode
309 : */
310 : class BOOST_COROSIO_DECL no_delay : public boolean_option
311 : {
312 : public:
313 : using boolean_option::boolean_option;
314 : using boolean_option::operator=;
315 :
316 : /// Return the protocol level.
317 : static int level() noexcept;
318 :
319 : /// Return the option name.
320 : static int name() noexcept;
321 : };
322 :
323 : /** Enable periodic keepalive probes (SO_KEEPALIVE).
324 :
325 : @par Example
326 : @code
327 : sock.set_option( socket_option::keep_alive( true ) );
328 : @endcode
329 : */
330 : class BOOST_COROSIO_DECL keep_alive : public boolean_option
331 : {
332 : public:
333 : using boolean_option::boolean_option;
334 : using boolean_option::operator=;
335 :
336 : /// Return the protocol level.
337 : static int level() noexcept;
338 :
339 : /// Return the option name.
340 : static int name() noexcept;
341 : };
342 :
343 : /** Restrict an IPv6 socket to IPv6 only (IPV6_V6ONLY).
344 :
345 : When enabled, the socket only accepts IPv6 connections.
346 : When disabled, the socket accepts both IPv4 and IPv6
347 : connections (dual-stack mode).
348 :
349 : @par Example
350 : @code
351 : sock.set_option( socket_option::v6_only( true ) );
352 : @endcode
353 : */
354 : class BOOST_COROSIO_DECL v6_only : public boolean_option
355 : {
356 : public:
357 : using boolean_option::boolean_option;
358 : using boolean_option::operator=;
359 :
360 : /// Return the protocol level.
361 : static int level() noexcept;
362 :
363 : /// Return the option name.
364 : static int name() noexcept;
365 : };
366 :
367 : /** Allow local address reuse (SO_REUSEADDR).
368 :
369 : @par Example
370 : @code
371 : acc.set_option( socket_option::reuse_address( true ) );
372 : @endcode
373 : */
374 : class BOOST_COROSIO_DECL reuse_address : public boolean_option
375 : {
376 : public:
377 : using boolean_option::boolean_option;
378 : using boolean_option::operator=;
379 :
380 : /// Return the protocol level.
381 : static int level() noexcept;
382 :
383 : /// Return the option name.
384 : static int name() noexcept;
385 : };
386 :
387 : /** Allow sending to broadcast addresses (SO_BROADCAST).
388 :
389 : Required for UDP sockets that send to broadcast addresses
390 : such as 255.255.255.255. Without this option, `send_to`
391 : returns an error.
392 :
393 : @par Example
394 : @code
395 : udp_socket sock( ioc );
396 : sock.open();
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` will return an error.
417 :
418 : @par Example
419 : @code
420 : acc.open( tcp::v6() );
421 : acc.set_option( socket_option::reuse_port( true ) );
422 : acc.bind( endpoint( ipv6_address::any(), 8080 ) );
423 : acc.listen();
424 : @endcode
425 : */
426 : class BOOST_COROSIO_DECL reuse_port : public boolean_option
427 : {
428 : public:
429 : using boolean_option::boolean_option;
430 : using boolean_option::operator=;
431 :
432 : /// Return the protocol level.
433 : static int level() noexcept;
434 :
435 : /// Return the option name.
436 : static int name() noexcept;
437 : };
438 :
439 : /** Set the receive buffer size (SO_RCVBUF).
440 :
441 : @par Example
442 : @code
443 : sock.set_option( socket_option::receive_buffer_size( 65536 ) );
444 : auto opt = sock.get_option<socket_option::receive_buffer_size>();
445 : int sz = opt.value();
446 : @endcode
447 : */
448 : class BOOST_COROSIO_DECL receive_buffer_size : public integer_option
449 : {
450 : public:
451 : using integer_option::integer_option;
452 : using integer_option::operator=;
453 :
454 : /// Return the protocol level.
455 : static int level() noexcept;
456 :
457 : /// Return the option name.
458 : static int name() noexcept;
459 : };
460 :
461 : /** Set the send buffer size (SO_SNDBUF).
462 :
463 : @par Example
464 : @code
465 : sock.set_option( socket_option::send_buffer_size( 65536 ) );
466 : @endcode
467 : */
468 : class BOOST_COROSIO_DECL send_buffer_size : public integer_option
469 : {
470 : public:
471 : using integer_option::integer_option;
472 : using integer_option::operator=;
473 :
474 : /// Return the protocol level.
475 : static int level() noexcept;
476 :
477 : /// Return the option name.
478 : static int name() noexcept;
479 : };
480 :
481 : /** The SO_LINGER socket option.
482 :
483 : Controls behavior when closing a socket with unsent data.
484 : When enabled, `close()` blocks until pending data is sent
485 : or the timeout expires.
486 :
487 : @par Example
488 : @code
489 : sock.set_option( socket_option::linger( true, 5 ) );
490 : auto opt = sock.get_option<socket_option::linger>();
491 : if ( opt.enabled() )
492 : std::cout << "linger timeout: " << opt.timeout() << "s\n";
493 : @endcode
494 : */
495 : class BOOST_COROSIO_DECL linger
496 : {
497 : // Opaque storage for the platform's struct linger.
498 : // POSIX: { int, int } = 8 bytes.
499 : // Windows: { u_short, u_short } = 4 bytes.
500 : static constexpr std::size_t max_storage_ = 8;
501 : alignas(4) unsigned char storage_[max_storage_]{};
502 :
503 : public:
504 : /// Construct with default values (disabled, zero timeout).
505 : linger() noexcept = default;
506 :
507 : /** Construct with explicit values.
508 :
509 : @param enabled `true` to enable linger behavior on close.
510 : @param timeout The linger timeout in seconds.
511 : */
512 : linger(bool enabled, int timeout) noexcept;
513 :
514 : /// Return whether linger is enabled.
515 : bool enabled() const noexcept;
516 :
517 : /// Set whether linger is enabled.
518 : void enabled(bool v) noexcept;
519 :
520 : /// Return the linger timeout in seconds.
521 : int timeout() const noexcept;
522 :
523 : /// Set the linger timeout in seconds.
524 : void timeout(int v) noexcept;
525 :
526 : /// Return the protocol level.
527 : static int level() noexcept;
528 :
529 : /// Return the option name.
530 : static int name() noexcept;
531 :
532 : /// Return a pointer to the underlying storage.
533 10 : void* data() noexcept
534 : {
535 10 : return storage_;
536 : }
537 :
538 : /// Return a pointer to the underlying storage.
539 34 : void const* data() const noexcept
540 : {
541 34 : return storage_;
542 : }
543 :
544 : /// Return the size of the underlying storage.
545 : std::size_t size() const noexcept;
546 :
547 : /** Normalize after `getsockopt`.
548 :
549 : No-op — `struct linger` is always returned at full size.
550 :
551 : @param s The number of bytes actually written by `getsockopt`.
552 : */
553 10 : void resize(std::size_t) noexcept {}
554 : };
555 :
556 : /** Enable loopback of outgoing multicast on IPv4 (IP_MULTICAST_LOOP).
557 :
558 : Uses single-byte storage because BSD-derived kernels (macOS, FreeBSD)
559 : reject the four-byte form with `EINVAL`. Linux accepts either size.
560 :
561 : @par Example
562 : @code
563 : sock.set_option( socket_option::multicast_loop_v4( true ) );
564 : @endcode
565 : */
566 : class BOOST_COROSIO_DECL multicast_loop_v4 : public byte_boolean_option
567 : {
568 : public:
569 : using byte_boolean_option::byte_boolean_option;
570 : using byte_boolean_option::operator=;
571 :
572 : /// Return the protocol level.
573 : static int level() noexcept;
574 :
575 : /// Return the option name.
576 : static int name() noexcept;
577 : };
578 :
579 : /** Enable loopback of outgoing multicast on IPv6 (IPV6_MULTICAST_LOOP).
580 :
581 : @par Example
582 : @code
583 : sock.set_option( socket_option::multicast_loop_v6( true ) );
584 : @endcode
585 : */
586 : class BOOST_COROSIO_DECL multicast_loop_v6 : public boolean_option
587 : {
588 : public:
589 : using boolean_option::boolean_option;
590 : using boolean_option::operator=;
591 :
592 : /// Return the protocol level.
593 : static int level() noexcept;
594 :
595 : /// Return the option name.
596 : static int name() noexcept;
597 : };
598 :
599 : /** Set the multicast TTL for IPv4 (IP_MULTICAST_TTL).
600 :
601 : Uses single-byte storage because BSD-derived kernels (macOS, FreeBSD)
602 : reject the four-byte form with `EINVAL`. Linux accepts either size.
603 : Values are truncated to the 0–255 range.
604 :
605 : @par Example
606 : @code
607 : sock.set_option( socket_option::multicast_hops_v4( 4 ) );
608 : @endcode
609 : */
610 : class BOOST_COROSIO_DECL multicast_hops_v4 : public byte_integer_option
611 : {
612 : public:
613 : using byte_integer_option::byte_integer_option;
614 : using byte_integer_option::operator=;
615 :
616 : /// Return the protocol level.
617 : static int level() noexcept;
618 :
619 : /// Return the option name.
620 : static int name() noexcept;
621 : };
622 :
623 : /** Set the multicast hop limit for IPv6 (IPV6_MULTICAST_HOPS).
624 :
625 : @par Example
626 : @code
627 : sock.set_option( socket_option::multicast_hops_v6( 4 ) );
628 : @endcode
629 : */
630 : class BOOST_COROSIO_DECL multicast_hops_v6 : public integer_option
631 : {
632 : public:
633 : using integer_option::integer_option;
634 : using integer_option::operator=;
635 :
636 : /// Return the protocol level.
637 : static int level() noexcept;
638 :
639 : /// Return the option name.
640 : static int name() noexcept;
641 : };
642 :
643 : /** Set the outgoing interface for IPv6 multicast (IPV6_MULTICAST_IF).
644 :
645 : @par Example
646 : @code
647 : sock.set_option( socket_option::multicast_interface_v6( 1 ) );
648 : @endcode
649 : */
650 : class BOOST_COROSIO_DECL multicast_interface_v6 : public integer_option
651 : {
652 : public:
653 : using integer_option::integer_option;
654 : using integer_option::operator=;
655 :
656 : /// Return the protocol level.
657 : static int level() noexcept;
658 :
659 : /// Return the option name.
660 : static int name() noexcept;
661 : };
662 :
663 : /** Join an IPv4 multicast group (IP_ADD_MEMBERSHIP).
664 :
665 : @par Example
666 : @code
667 : sock.set_option( socket_option::join_group_v4(
668 : ipv4_address( "239.255.0.1" ) ) );
669 : @endcode
670 : */
671 : class BOOST_COROSIO_DECL join_group_v4
672 : {
673 : static constexpr std::size_t max_storage_ = 8;
674 : alignas(4) unsigned char storage_[max_storage_]{};
675 :
676 : public:
677 : /// Construct with default values.
678 : join_group_v4() noexcept = default;
679 :
680 : /** Construct with a group and optional interface address.
681 :
682 : @param group The multicast group address to join.
683 : @param iface The local interface to use (default: any).
684 : */
685 : join_group_v4(
686 : ipv4_address group, ipv4_address iface = ipv4_address()) noexcept;
687 :
688 : /// Return the protocol level.
689 : static int level() noexcept;
690 :
691 : /// Return the option name.
692 : static int name() noexcept;
693 :
694 : /// Return a pointer to the underlying storage.
695 : void* data() noexcept
696 : {
697 : return storage_;
698 : }
699 :
700 : /// Return a pointer to the underlying storage.
701 4 : void const* data() const noexcept
702 : {
703 4 : return storage_;
704 : }
705 :
706 : /// Return the size of the underlying storage.
707 : std::size_t size() const noexcept;
708 :
709 : /// No-op resize.
710 : void resize(std::size_t) noexcept {}
711 : };
712 :
713 : /** Leave an IPv4 multicast group (IP_DROP_MEMBERSHIP).
714 :
715 : @par Example
716 : @code
717 : sock.set_option( socket_option::leave_group_v4(
718 : ipv4_address( "239.255.0.1" ) ) );
719 : @endcode
720 : */
721 : class BOOST_COROSIO_DECL leave_group_v4
722 : {
723 : static constexpr std::size_t max_storage_ = 8;
724 : alignas(4) unsigned char storage_[max_storage_]{};
725 :
726 : public:
727 : /// Construct with default values.
728 : leave_group_v4() noexcept = default;
729 :
730 : /** Construct with a group and optional interface address.
731 :
732 : @param group The multicast group address to leave.
733 : @param iface The local interface (default: any).
734 : */
735 : leave_group_v4(
736 : ipv4_address group, ipv4_address iface = ipv4_address()) noexcept;
737 :
738 : /// Return the protocol level.
739 : static int level() noexcept;
740 :
741 : /// Return the option name.
742 : static int name() noexcept;
743 :
744 : /// Return a pointer to the underlying storage.
745 : void* data() noexcept
746 : {
747 : return storage_;
748 : }
749 :
750 : /// Return a pointer to the underlying storage.
751 2 : void const* data() const noexcept
752 : {
753 2 : return storage_;
754 : }
755 :
756 : /// Return the size of the underlying storage.
757 : std::size_t size() const noexcept;
758 :
759 : /// No-op resize.
760 : void resize(std::size_t) noexcept {}
761 : };
762 :
763 : /** Join an IPv6 multicast group (IPV6_JOIN_GROUP).
764 :
765 : @par Example
766 : @code
767 : sock.set_option( socket_option::join_group_v6(
768 : ipv6_address( "ff02::1" ), 0 ) );
769 : @endcode
770 : */
771 : class BOOST_COROSIO_DECL join_group_v6
772 : {
773 : static constexpr std::size_t max_storage_ = 20;
774 : alignas(4) unsigned char storage_[max_storage_]{};
775 :
776 : public:
777 : /// Construct with default values.
778 : join_group_v6() noexcept = default;
779 :
780 : /** Construct with a group and optional interface index.
781 :
782 : @param group The multicast group address to join.
783 : @param if_index The interface index (0 = kernel chooses).
784 : */
785 : join_group_v6(ipv6_address group, unsigned int if_index = 0) noexcept;
786 :
787 : /// Return the protocol level.
788 : static int level() noexcept;
789 :
790 : /// Return the option name.
791 : static int name() noexcept;
792 :
793 : /// Return a pointer to the underlying storage.
794 : void* data() noexcept
795 : {
796 : return storage_;
797 : }
798 :
799 : /// Return a pointer to the underlying storage.
800 2 : void const* data() const noexcept
801 : {
802 2 : return storage_;
803 : }
804 :
805 : /// Return the size of the underlying storage.
806 : std::size_t size() const noexcept;
807 :
808 : /// No-op resize.
809 : void resize(std::size_t) noexcept {}
810 : };
811 :
812 : /** Leave an IPv6 multicast group (IPV6_LEAVE_GROUP).
813 :
814 : @par Example
815 : @code
816 : sock.set_option( socket_option::leave_group_v6(
817 : ipv6_address( "ff02::1" ), 0 ) );
818 : @endcode
819 : */
820 : class BOOST_COROSIO_DECL leave_group_v6
821 : {
822 : static constexpr std::size_t max_storage_ = 20;
823 : alignas(4) unsigned char storage_[max_storage_]{};
824 :
825 : public:
826 : /// Construct with default values.
827 : leave_group_v6() noexcept = default;
828 :
829 : /** Construct with a group and optional interface index.
830 :
831 : @param group The multicast group address to leave.
832 : @param if_index The interface index (0 = kernel chooses).
833 : */
834 : leave_group_v6(ipv6_address group, unsigned int if_index = 0) noexcept;
835 :
836 : /// Return the protocol level.
837 : static int level() noexcept;
838 :
839 : /// Return the option name.
840 : static int name() noexcept;
841 :
842 : /// Return a pointer to the underlying storage.
843 : void* data() noexcept
844 : {
845 : return storage_;
846 : }
847 :
848 : /// Return a pointer to the underlying storage.
849 2 : void const* data() const noexcept
850 : {
851 2 : return storage_;
852 : }
853 :
854 : /// Return the size of the underlying storage.
855 : std::size_t size() const noexcept;
856 :
857 : /// No-op resize.
858 : void resize(std::size_t) noexcept {}
859 : };
860 :
861 : /** Set the outgoing interface for IPv4 multicast (IP_MULTICAST_IF).
862 :
863 : Unlike the integer-based `multicast_interface_v6`, this option
864 : takes an `ipv4_address` identifying the local interface.
865 :
866 : @par Example
867 : @code
868 : sock.set_option( socket_option::multicast_interface_v4(
869 : ipv4_address( "192.168.1.1" ) ) );
870 : @endcode
871 : */
872 : class BOOST_COROSIO_DECL multicast_interface_v4
873 : {
874 : static constexpr std::size_t max_storage_ = 4;
875 : alignas(4) unsigned char storage_[max_storage_]{};
876 :
877 : public:
878 : /// Construct with default values (INADDR_ANY).
879 : multicast_interface_v4() noexcept = default;
880 :
881 : /** Construct with an interface address.
882 :
883 : @param iface The local interface address.
884 : */
885 : explicit multicast_interface_v4(ipv4_address iface) noexcept;
886 :
887 : /// Return the protocol level.
888 : static int level() noexcept;
889 :
890 : /// Return the option name.
891 : static int name() noexcept;
892 :
893 : /// Return a pointer to the underlying storage.
894 : void* data() noexcept
895 : {
896 : return storage_;
897 : }
898 :
899 : /// Return a pointer to the underlying storage.
900 2 : void const* data() const noexcept
901 : {
902 2 : return storage_;
903 : }
904 :
905 : /// Return the size of the underlying storage.
906 : std::size_t size() const noexcept;
907 :
908 : /// No-op resize.
909 : void resize(std::size_t) noexcept {}
910 : };
911 :
912 : } // namespace boost::corosio::socket_option
913 :
914 : #endif // BOOST_COROSIO_SOCKET_OPTION_HPP
|