include/boost/corosio/socket_option.hpp

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