include/boost/corosio/socket_option.hpp

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