Skip to main content

compio_net/
udp.rs

1use std::{
2    future::Future,
3    io,
4    net::{Ipv4Addr, Ipv6Addr, SocketAddr},
5};
6
7use compio_buf::{BufResult, IoBuf, IoBufMut, IoVectoredBuf, IoVectoredBufMut};
8use compio_driver::{
9    BufferRef, impl_raw_fd,
10    op::{RecvFlags, RecvFromMultiResult, RecvMsgMultiResult},
11};
12use futures_util::Stream;
13use socket2::{Protocol, SockAddr, Socket as Socket2, Type};
14
15use crate::{MSG_NOSIGNAL, Socket, ToSocketAddrsAsync};
16
17/// A UDP socket.
18///
19/// UDP is "connectionless", unlike TCP. Meaning, regardless of what address
20/// you've bound to, a `UdpSocket` is free to communicate with many different
21/// remotes. There are basically two main ways to use `UdpSocket`:
22///
23/// * one to many: [`bind`](`UdpSocket::bind`) and use
24///   [`send_to`](`UdpSocket::send_to`) and
25///   [`recv_from`](`UdpSocket::recv_from`) to communicate with many different
26///   addresses
27/// * one to one: [`connect`](`UdpSocket::connect`) and associate with a single
28///   address, using [`send`](`UdpSocket::send`) and [`recv`](`UdpSocket::recv`)
29///   to communicate only with that remote address
30///
31/// # Examples
32/// Bind and connect a pair of sockets and send a packet:
33///
34/// ```
35/// use std::net::SocketAddr;
36///
37/// use compio_net::UdpSocket;
38///
39/// # compio_runtime::Runtime::new().unwrap().block_on(async {
40/// let first_addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
41/// let second_addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
42///
43/// // bind sockets
44/// let mut socket = UdpSocket::bind(first_addr).await.unwrap();
45/// let first_addr = socket.local_addr().unwrap();
46/// let mut other_socket = UdpSocket::bind(second_addr).await.unwrap();
47/// let second_addr = other_socket.local_addr().unwrap();
48///
49/// // connect sockets
50/// socket.connect(second_addr).await.unwrap();
51/// other_socket.connect(first_addr).await.unwrap();
52///
53/// let buf = Vec::with_capacity(12);
54///
55/// // write data
56/// socket.send("Hello world!").await.unwrap();
57///
58/// // read data
59/// let (n_bytes, buf) = other_socket.recv(buf).await.unwrap();
60///
61/// assert_eq!(n_bytes, buf.len());
62/// assert_eq!(buf, b"Hello world!");
63/// # });
64/// ```
65/// Send and receive packets without connecting:
66///
67/// ```
68/// use std::net::SocketAddr;
69///
70/// use compio_net::UdpSocket;
71/// use socket2::SockAddr;
72///
73/// # compio_runtime::Runtime::new().unwrap().block_on(async {
74/// let first_addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
75/// let second_addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
76///
77/// // bind sockets
78/// let mut socket = UdpSocket::bind(first_addr).await.unwrap();
79/// let first_addr = socket.local_addr().unwrap();
80/// let mut other_socket = UdpSocket::bind(second_addr).await.unwrap();
81/// let second_addr = other_socket.local_addr().unwrap();
82///
83/// let buf = Vec::with_capacity(32);
84///
85/// // write data
86/// socket.send_to("hello world", second_addr).await.unwrap();
87///
88/// // read data
89/// let ((n_bytes, addr), buf) = other_socket.recv_from(buf).await.unwrap();
90///
91/// assert_eq!(addr, first_addr);
92/// assert_eq!(n_bytes, buf.len());
93/// assert_eq!(buf, b"hello world");
94/// # });
95/// ```
96#[derive(Debug, Clone)]
97pub struct UdpSocket {
98    inner: Socket,
99}
100
101impl UdpSocket {
102    /// Creates a new UDP socket and attempt to bind it to the addr provided.
103    pub async fn bind(addr: impl ToSocketAddrsAsync) -> io::Result<Self> {
104        super::each_addr(addr, |addr| async move {
105            let addr = SockAddr::from(addr);
106            let socket = Socket::new(addr.domain(), Type::DGRAM, Some(Protocol::UDP)).await?;
107            socket.bind(&addr).await?;
108            Ok(Self { inner: socket })
109        })
110        .await
111    }
112
113    /// Connects this UDP socket to a remote address, allowing the `send` and
114    /// `recv` to be used to send data and also applies filters to only
115    /// receive data from the specified address.
116    ///
117    /// Note that usually, a successful `connect` call does not specify
118    /// that there is a remote server listening on the port, rather, such an
119    /// error would only be detected after the first send.
120    pub async fn connect(&self, addr: impl ToSocketAddrsAsync) -> io::Result<()> {
121        super::each_addr(addr, |addr| async move {
122            self.inner.connect(&SockAddr::from(addr))
123        })
124        .await
125    }
126
127    /// Creates new UdpSocket from a std::net::UdpSocket.
128    pub fn from_std(socket: std::net::UdpSocket) -> io::Result<Self> {
129        Ok(Self {
130            inner: Socket::from_socket2(Socket2::from(socket))?,
131        })
132    }
133
134    /// Close the socket. If the returned future is dropped before polling, the
135    /// socket won't be closed.
136    ///
137    /// See [`TcpStream::close`] for more details.
138    ///
139    /// [`TcpStream::close`]: crate::tcp::TcpStream::close
140    pub fn close(self) -> impl Future<Output = io::Result<()>> {
141        self.inner.close()
142    }
143
144    /// Returns the socket address of the remote peer this socket was connected
145    /// to.
146    ///
147    /// # Examples
148    ///
149    /// ```no_run
150    /// use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
151    ///
152    /// use compio_net::UdpSocket;
153    /// use socket2::SockAddr;
154    ///
155    /// # compio_runtime::Runtime::new().unwrap().block_on(async {
156    /// let socket = UdpSocket::bind("127.0.0.1:34254")
157    ///     .await
158    ///     .expect("couldn't bind to address");
159    /// socket
160    ///     .connect("192.168.0.1:41203")
161    ///     .await
162    ///     .expect("couldn't connect to address");
163    /// assert_eq!(
164    ///     socket.peer_addr().unwrap(),
165    ///     SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(192, 168, 0, 1), 41203))
166    /// );
167    /// # });
168    /// ```
169    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
170        self.inner
171            .peer_addr()
172            .map(|addr| addr.as_socket().expect("should be SocketAddr"))
173    }
174
175    /// Returns the local address that this socket is bound to.
176    ///
177    /// # Example
178    ///
179    /// ```
180    /// use std::net::SocketAddr;
181    ///
182    /// use compio_net::UdpSocket;
183    /// use socket2::SockAddr;
184    ///
185    /// # compio_runtime::Runtime::new().unwrap().block_on(async {
186    /// let addr: SocketAddr = "127.0.0.1:8080".parse().unwrap();
187    /// let sock = UdpSocket::bind(&addr).await.unwrap();
188    /// // the address the socket is bound to
189    /// let local_addr = sock.local_addr().unwrap();
190    /// assert_eq!(local_addr, addr);
191    /// # });
192    /// ```
193    pub fn local_addr(&self) -> io::Result<SocketAddr> {
194        self.inner
195            .local_addr()
196            .map(|addr| addr.as_socket().expect("should be SocketAddr"))
197    }
198
199    /// Receives a packet of data from the socket into the buffer, returning the
200    /// original buffer and quantity of data received.
201    pub async fn recv<T: IoBufMut>(&self, buffer: T) -> BufResult<usize, T> {
202        self.inner.recv(buffer, RecvFlags::empty()).await
203    }
204
205    /// Receives a packet of data from the socket into the buffer, returning the
206    /// original buffer and quantity of data received.
207    pub async fn recv_vectored<T: IoVectoredBufMut>(&self, buffer: T) -> BufResult<usize, T> {
208        self.inner.recv_vectored(buffer, RecvFlags::empty()).await
209    }
210
211    /// Read some bytes from this source and return a [`BufferRef`].
212    ///
213    /// If `len` == 0, will use buffer pool's inner buffer size as the max len;
214    /// if `len` > 0, `min(len, inner buffer size)` will be the read max len.
215    pub async fn recv_managed(&self, len: usize) -> io::Result<Option<BufferRef>> {
216        self.inner.recv_managed(len, RecvFlags::empty()).await
217    }
218
219    /// Read some bytes from this source and return a stream of [`BufferRef`]s.
220    ///
221    /// If `len` == 0, will use buffer pool's inner buffer size as the max len
222    /// of each buffer; if `len` > 0, `min(len, inner buffer size)` will be
223    /// the read max len of each buffer.
224    pub fn recv_multi(&self, len: usize) -> impl Stream<Item = io::Result<BufferRef>> {
225        self.inner.recv_multi(len, RecvFlags::empty())
226    }
227
228    /// Sends some data to the socket from the buffer, returning the original
229    /// buffer and quantity of data sent.
230    pub async fn send<T: IoBuf>(&self, buffer: T) -> BufResult<usize, T> {
231        self.inner.send(buffer, MSG_NOSIGNAL).await
232    }
233
234    /// Sends some data to the socket from the buffer, returning the original
235    /// buffer and quantity of data sent.
236    pub async fn send_vectored<T: IoVectoredBuf>(&self, buffer: T) -> BufResult<usize, T> {
237        self.inner.send_vectored(buffer, MSG_NOSIGNAL).await
238    }
239
240    /// Receives a single datagram message on the socket. On success, returns
241    /// the number of bytes received and the origin.
242    pub async fn recv_from<T: IoBufMut>(&self, buffer: T) -> BufResult<(usize, SocketAddr), T> {
243        self.inner
244            .recv_from(buffer, RecvFlags::empty())
245            .await
246            .map_res(|(n, addr)| {
247                let addr = addr
248                    .expect("should have addr")
249                    .as_socket()
250                    .expect("should be SocketAddr");
251                (n, addr)
252            })
253    }
254
255    /// Receives a single datagram message on the socket. On success, returns
256    /// the number of bytes received and the origin.
257    pub async fn recv_from_vectored<T: IoVectoredBufMut>(
258        &self,
259        buffer: T,
260    ) -> BufResult<(usize, SocketAddr), T> {
261        self.inner
262            .recv_from_vectored(buffer, RecvFlags::empty())
263            .await
264            .map_res(|(n, addr)| {
265                let addr = addr
266                    .expect("should have addr")
267                    .as_socket()
268                    .expect("should be SocketAddr");
269                (n, addr)
270            })
271    }
272
273    /// Read some bytes from this source and the runtime's buffer pool and
274    /// return a [`BufferRef`] with the sender address.
275    ///
276    /// If `len` == 0, will use buffer pool's inner buffer size as the max len;
277    /// if `len` > 0, `min(len, inner buffer size)` will be the read max len
278    pub async fn recv_from_managed(
279        &self,
280        len: usize,
281    ) -> io::Result<Option<(BufferRef, SocketAddr)>> {
282        let res = self
283            .inner
284            .recv_from_managed(len, RecvFlags::empty())
285            .await?;
286        let ret = match res {
287            Some((buffer, addr)) => {
288                let addr = addr
289                    .expect("should have addr")
290                    .as_socket()
291                    .expect("should be SocketAddr");
292                Some((buffer, addr))
293            }
294            None => None,
295        };
296        Ok(ret)
297    }
298
299    /// Read some bytes from this source and the runtime's buffer pool and
300    /// return a stream of [`RecvFromMultiResult`].
301    pub fn recv_from_multi(&self) -> impl Stream<Item = io::Result<RecvFromMultiResult>> {
302        self.inner.recv_from_multi(RecvFlags::empty())
303    }
304
305    /// Receives a single datagram message and ancillary data on the socket. On
306    /// success, returns the number of bytes received and the origin.
307    pub async fn recv_msg<T: IoBufMut, C: IoBufMut>(
308        &self,
309        buffer: T,
310        control: C,
311    ) -> BufResult<(usize, usize, SocketAddr), (T, C)> {
312        self.inner
313            .recv_msg(buffer, control, RecvFlags::empty())
314            .await
315            .map_res(|(n, m, addr)| {
316                let addr = addr
317                    .expect("should have addr")
318                    .as_socket()
319                    .expect("should be SocketAddr");
320                (n, m, addr)
321            })
322    }
323
324    /// Receives a single datagram message and ancillary data on the socket. On
325    /// success, returns the number of bytes received and the origin.
326    pub async fn recv_msg_vectored<T: IoVectoredBufMut, C: IoBufMut>(
327        &self,
328        buffer: T,
329        control: C,
330    ) -> BufResult<(usize, usize, SocketAddr), (T, C)> {
331        self.inner
332            .recv_msg_vectored(buffer, control, RecvFlags::empty())
333            .await
334            .map_res(|(n, m, addr)| {
335                let addr = addr
336                    .expect("should have addr")
337                    .as_socket()
338                    .expect("should be SocketAddr");
339                (n, m, addr)
340            })
341    }
342
343    /// Receives a single datagram message on the socket from the runtime's
344    /// buffer pool, together with ancillary data. The ancillary data buffer is
345    /// provided by the caller.
346    ///
347    /// If `len` == 0, will use buffer pool's inner buffer size as the max len;
348    /// if `len` > 0, `min(len, inner buffer size)` will be the read max len
349    pub async fn recv_msg_managed<C: IoBufMut>(
350        &self,
351        len: usize,
352        control: C,
353    ) -> io::Result<Option<(BufferRef, C, SocketAddr)>> {
354        let res = self
355            .inner
356            .recv_msg_managed(len, control, RecvFlags::empty())
357            .await?;
358        let ret = match res {
359            Some((buffer, control, addr)) => {
360                let addr = addr
361                    .expect("should have addr")
362                    .as_socket()
363                    .expect("should be SocketAddr");
364                Some((buffer, control, addr))
365            }
366            None => None,
367        };
368        Ok(ret)
369    }
370
371    /// Receives multiple single datagram messages and ancillary data on the
372    /// socket from the runtime's buffer pool.
373    pub fn recv_msg_multi(
374        &self,
375        control_len: usize,
376    ) -> impl Stream<Item = io::Result<RecvMsgMultiResult>> {
377        self.inner.recv_msg_multi(control_len, RecvFlags::empty())
378    }
379
380    /// Sends data on the socket to the given address. On success, returns the
381    /// number of bytes sent.
382    pub async fn send_to<T: IoBuf>(
383        &self,
384        buffer: T,
385        addr: impl ToSocketAddrsAsync,
386    ) -> BufResult<usize, T> {
387        super::first_addr_buf(addr, buffer, |addr, buffer| async move {
388            self.inner
389                .send_to(buffer, &SockAddr::from(addr), MSG_NOSIGNAL)
390                .await
391        })
392        .await
393    }
394
395    /// Sends data on the socket to the given address. On success, returns the
396    /// number of bytes sent.
397    pub async fn send_to_vectored<T: IoVectoredBuf>(
398        &self,
399        buffer: T,
400        addr: impl ToSocketAddrsAsync,
401    ) -> BufResult<usize, T> {
402        super::first_addr_buf(addr, buffer, |addr, buffer| async move {
403            self.inner
404                .send_to_vectored(buffer, &SockAddr::from(addr), MSG_NOSIGNAL)
405                .await
406        })
407        .await
408    }
409
410    /// Sends data on the socket to the given address accompanied by ancillary
411    /// data. On success, returns the number of bytes sent.
412    pub async fn send_msg<T: IoBuf, C: IoBuf>(
413        &self,
414        buffer: T,
415        control: C,
416        addr: impl ToSocketAddrsAsync,
417    ) -> BufResult<usize, (T, C)> {
418        super::first_addr_buf(
419            addr,
420            (buffer, control),
421            |addr, (buffer, control)| async move {
422                self.inner
423                    .send_msg(buffer, control, Some(&SockAddr::from(addr)), MSG_NOSIGNAL)
424                    .await
425            },
426        )
427        .await
428    }
429
430    /// Sends data on the socket to the given address accompanied by ancillary
431    /// data. On success, returns the number of bytes sent.
432    pub async fn send_msg_vectored<T: IoVectoredBuf, C: IoBuf>(
433        &self,
434        buffer: T,
435        control: C,
436        addr: impl ToSocketAddrsAsync,
437    ) -> BufResult<usize, (T, C)> {
438        super::first_addr_buf(
439            addr,
440            (buffer, control),
441            |addr, (buffer, control)| async move {
442                self.inner
443                    .send_msg_vectored(buffer, control, Some(&SockAddr::from(addr)), MSG_NOSIGNAL)
444                    .await
445            },
446        )
447        .await
448    }
449
450    /// Sends data on the socket with zero copy.
451    ///
452    /// Returns the result of send and a future that resolves to the
453    /// original buffer when the send is complete.
454    pub async fn send_zerocopy<T: IoBuf>(
455        &self,
456        buf: T,
457    ) -> BufResult<usize, impl Future<Output = T> + use<T>> {
458        self.inner.send_zerocopy(buf, MSG_NOSIGNAL).await
459    }
460
461    /// Sends vectored data on the socket with zero copy.
462    ///
463    /// Returns the result of send and a future that resolves to the
464    /// original buffer when the send is complete.
465    pub async fn send_zerocopy_vectored<T: IoVectoredBuf>(
466        &self,
467        buf: T,
468    ) -> BufResult<usize, impl Future<Output = T> + use<T>> {
469        self.inner.send_zerocopy_vectored(buf, MSG_NOSIGNAL).await
470    }
471
472    /// Sends data on the socket to the given address with zero copy.
473    ///
474    /// Returns the result of send and a future that resolves to the
475    /// original buffer when the send is complete.
476    pub async fn send_to_zerocopy<A: ToSocketAddrsAsync, T: IoBuf>(
477        &self,
478        buffer: T,
479        addr: A,
480    ) -> BufResult<usize, impl Future<Output = T> + use<A, T>> {
481        super::first_addr_buf_zerocopy(addr, buffer, |addr, buffer| async move {
482            self.inner
483                .send_to_zerocopy(buffer, &addr.into(), MSG_NOSIGNAL)
484                .await
485        })
486        .await
487    }
488
489    /// Sends vectored data on the socket to the given address with zero copy.
490    ///
491    /// Returns the result of send and a future that resolves to the
492    /// original buffer when the send is complete.
493    pub async fn send_to_zerocopy_vectored<A: ToSocketAddrsAsync, T: IoVectoredBuf>(
494        &self,
495        buffer: T,
496        addr: A,
497    ) -> BufResult<usize, impl Future<Output = T> + use<A, T>> {
498        super::first_addr_buf_zerocopy(addr, buffer, |addr, buffer| async move {
499            self.inner
500                .send_to_zerocopy_vectored(buffer, &addr.into(), MSG_NOSIGNAL)
501                .await
502        })
503        .await
504    }
505
506    /// Sends data with control message on the socket to the given address with
507    /// zero copy.
508    ///
509    /// Returns the result of send and a future that resolves to the
510    /// original buffer when the send is complete.
511    pub async fn send_msg_zerocopy<A: ToSocketAddrsAsync, T: IoBuf, C: IoBuf>(
512        &self,
513        buffer: T,
514        control: C,
515        addr: A,
516    ) -> BufResult<usize, impl Future<Output = (T, C)> + use<A, T, C>> {
517        super::first_addr_buf_zerocopy(addr, (buffer, control), |addr, (b, c)| async move {
518            self.inner
519                .send_msg_zerocopy(b, c, Some(&addr.into()), MSG_NOSIGNAL)
520                .await
521        })
522        .await
523    }
524
525    /// Sends vectored data with control message on the socket to the given
526    /// address with zero copy.
527    ///
528    /// Returns the result of send and a future that resolves to the
529    /// original buffer when the send is complete.
530    pub async fn send_msg_zerocopy_vectored<A: ToSocketAddrsAsync, T: IoVectoredBuf, C: IoBuf>(
531        &self,
532        buffer: T,
533        control: C,
534        addr: A,
535    ) -> BufResult<usize, impl Future<Output = (T, C)> + use<A, T, C>> {
536        super::first_addr_buf_zerocopy(addr, (buffer, control), |addr, (b, c)| async move {
537            self.inner
538                .send_msg_zerocopy_vectored(b, c, Some(&addr.into()), MSG_NOSIGNAL)
539                .await
540        })
541        .await
542    }
543
544    /// Gets the value of the `SO_BROADCAST` option for this socket.
545    ///
546    /// For more information about this option, see [`set_broadcast`].
547    ///
548    /// [`set_broadcast`]: method@Self::set_broadcast
549    pub fn broadcast(&self) -> io::Result<bool> {
550        self.inner.socket.broadcast()
551    }
552
553    /// Sets the value of the `SO_BROADCAST` option for this socket.
554    ///
555    /// When enabled, this socket is allowed to send packets to a broadcast
556    /// address.
557    pub fn set_broadcast(&self, on: bool) -> io::Result<()> {
558        self.inner.socket.set_broadcast(on)
559    }
560
561    /// Gets the value of the `IP_MULTICAST_LOOP` option for this socket.
562    ///
563    /// For more information about this option, see [`set_multicast_loop_v4`].
564    ///
565    /// [`set_multicast_loop_v4`]: method@Self::set_multicast_loop_v4
566    pub fn multicast_loop_v4(&self) -> io::Result<bool> {
567        self.inner.socket.multicast_loop_v4()
568    }
569
570    /// Sets the value of the `IP_MULTICAST_LOOP` option for this socket.
571    ///
572    /// If enabled, multicast packets will be looped back to the local socket.
573    ///
574    /// # Note
575    ///
576    /// This may not have any effect on IPv6 sockets.
577    pub fn set_multicast_loop_v4(&self, on: bool) -> io::Result<()> {
578        self.inner.socket.set_multicast_loop_v4(on)
579    }
580
581    /// Gets the value of the `IP_MULTICAST_TTL` option for this socket.
582    ///
583    /// For more information about this option, see [`set_multicast_ttl_v4`].
584    ///
585    /// [`set_multicast_ttl_v4`]: method@Self::set_multicast_ttl_v4
586    pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
587        self.inner.socket.multicast_ttl_v4()
588    }
589
590    /// Sets the value of the `IP_MULTICAST_TTL` option for this socket.
591    ///
592    /// Indicates the time-to-live value of outgoing multicast packets for
593    /// this socket. The default value is 1 which means that multicast packets
594    /// don't leave the local network unless explicitly requested.
595    ///
596    /// # Note
597    ///
598    /// This may not have any effect on IPv6 sockets.
599    pub fn set_multicast_ttl_v4(&self, ttl: u32) -> io::Result<()> {
600        self.inner.socket.set_multicast_ttl_v4(ttl)
601    }
602
603    /// Gets the value of the `IPV6_MULTICAST_LOOP` option for this socket.
604    ///
605    /// For more information about this option, see [`set_multicast_loop_v6`].
606    ///
607    /// [`set_multicast_loop_v6`]: method@Self::set_multicast_loop_v6
608    pub fn multicast_loop_v6(&self) -> io::Result<bool> {
609        self.inner.socket.multicast_loop_v6()
610    }
611
612    /// Sets the value of the `IPV6_MULTICAST_LOOP` option for this socket.
613    ///
614    /// Controls whether this socket sees the multicast packets it sends itself.
615    ///
616    /// # Note
617    ///
618    /// This may not have any effect on IPv4 sockets.
619    pub fn set_multicast_loop_v6(&self, on: bool) -> io::Result<()> {
620        self.inner.socket.set_multicast_loop_v6(on)
621    }
622
623    /// Gets the value of the `IPV6_TCLASS` option for this socket.
624    ///
625    /// For more information about this option, see [`set_tclass_v6`].
626    ///
627    /// [`set_tclass_v6`]: Self::set_tclass_v6
628    #[cfg(any(
629        target_os = "android",
630        target_os = "dragonfly",
631        target_os = "freebsd",
632        target_os = "fuchsia",
633        target_os = "linux",
634        target_os = "macos",
635        target_os = "netbsd",
636        target_os = "openbsd",
637        target_os = "cygwin",
638    ))]
639    pub fn tclass_v6(&self) -> io::Result<u32> {
640        self.inner.socket.tclass_v6()
641    }
642
643    /// Sets the value for the `IPV6_TCLASS` option on this socket.
644    ///
645    /// Specifies the traffic class field that is used in every packet
646    /// sent from this socket.
647    ///
648    /// # Note
649    ///
650    /// This may not have any effect on IPv4 sockets.
651    #[cfg(any(
652        target_os = "android",
653        target_os = "dragonfly",
654        target_os = "freebsd",
655        target_os = "fuchsia",
656        target_os = "linux",
657        target_os = "macos",
658        target_os = "netbsd",
659        target_os = "openbsd",
660        target_os = "cygwin",
661    ))]
662    pub fn set_tclass_v6(&self, tclass: u32) -> io::Result<()> {
663        self.inner.socket.set_tclass_v6(tclass)
664    }
665
666    /// Gets the value of the `IP_TTL` option for this socket.
667    ///
668    /// For more information about this option, see [`set_ttl_v4`].
669    ///
670    /// [`set_ttl_v4`]: method@Self::set_ttl_v4
671    pub fn ttl_v4(&self) -> io::Result<u32> {
672        self.inner.socket.ttl_v4()
673    }
674
675    /// Sets the value for the `IP_TTL` option on this socket.
676    ///
677    /// This value sets the time-to-live field that is used in every packet sent
678    /// from this socket.
679    pub fn set_ttl_v4(&self, ttl: u32) -> io::Result<()> {
680        self.inner.socket.set_ttl_v4(ttl)
681    }
682
683    /// Gets the value of the `IP_TOS` option for this socket.
684    ///
685    /// For more information about this option, see [`set_tos_v4`].
686    ///
687    /// [`set_tos_v4`]: Self::set_tos_v4
688    // https://docs.rs/socket2/0.6.1/src/socket2/socket.rs.html#1585
689    #[cfg(not(any(
690        target_os = "fuchsia",
691        target_os = "redox",
692        target_os = "solaris",
693        target_os = "illumos",
694        target_os = "haiku"
695    )))]
696    pub fn tos_v4(&self) -> io::Result<u32> {
697        self.inner.socket.tos_v4()
698    }
699
700    /// Sets the value for the `IP_TOS` option on this socket.
701    ///
702    /// This value sets the type-of-service field that is used in every packet
703    /// sent from this socket.
704    ///
705    /// # Note
706    ///
707    /// - This may not have any effect on IPv6 sockets.
708    #[cfg(not(any(
709        target_os = "fuchsia",
710        target_os = "redox",
711        target_os = "solaris",
712        target_os = "illumos",
713        target_os = "haiku"
714    )))]
715    pub fn set_tos_v4(&self, tos: u32) -> io::Result<()> {
716        self.inner.socket.set_tos_v4(tos)
717    }
718
719    /// Gets the value for the `SO_BINDTODEVICE` option on this socket
720    ///
721    /// This value gets the socket-bound device's interface name.
722    #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux",))]
723    pub fn device(&self) -> io::Result<Option<Vec<u8>>> {
724        self.inner.socket.device()
725    }
726
727    /// Sets the value for the `SO_BINDTODEVICE` option on this socket
728    ///
729    /// If a socket is bound to an interface, only packets received from that
730    /// particular interface are processed by the socket. Note that this only
731    /// works for some socket types, particularly `AF_INET` sockets.
732    ///
733    /// If `interface` is `None` or an empty string it removes the binding.
734    #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
735    pub fn bind_device(&self, interface: Option<&[u8]>) -> io::Result<()> {
736        self.inner.socket.bind_device(interface)
737    }
738
739    /// Executes an operation of the `IP_ADD_MEMBERSHIP` type.
740    ///
741    /// This function specifies a new multicast group for this socket to join.
742    /// The address must be a valid multicast address, and `interface` is the
743    /// address of the local interface with which the system should join the
744    /// multicast group. If it's equal to `INADDR_ANY` then an appropriate
745    /// interface is chosen by the system.
746    pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
747        self.inner.socket.join_multicast_v4(multiaddr, interface)
748    }
749
750    /// Executes an operation of the `IPV6_ADD_MEMBERSHIP` type.
751    ///
752    /// This function specifies a new multicast group for this socket to join.
753    /// The address must be a valid multicast address, and `interface` is the
754    /// index of the interface to join/leave (or 0 to indicate any interface).
755    pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
756        self.inner.socket.join_multicast_v6(multiaddr, interface)
757    }
758
759    /// Executes an operation of the `IP_DROP_MEMBERSHIP` type.
760    ///
761    /// For more information about this option, see [`join_multicast_v4`].
762    ///
763    /// [`join_multicast_v4`]: method@Self::join_multicast_v4
764    pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
765        self.inner.socket.leave_multicast_v4(multiaddr, interface)
766    }
767
768    /// Executes an operation of the `IPV6_DROP_MEMBERSHIP` type.
769    ///
770    /// For more information about this option, see [`join_multicast_v6`].
771    ///
772    /// [`join_multicast_v6`]: method@Self::join_multicast_v6
773    pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
774        self.inner.socket.leave_multicast_v6(multiaddr, interface)
775    }
776
777    /// Returns the value of the `SO_ERROR` option.
778    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
779        self.inner.socket.take_error()
780    }
781
782    /// Gets a socket option.
783    ///
784    /// # Safety
785    ///
786    /// The caller must ensure `T` is the correct type for `level` and `name`.
787    pub unsafe fn get_socket_option<T: Copy>(&self, level: i32, name: i32) -> io::Result<T> {
788        unsafe { self.inner.get_socket_option(level, name) }
789    }
790
791    /// Sets a socket option.
792    ///
793    /// # Safety
794    ///
795    /// The caller must ensure `T` is the correct type for `level` and `name`.
796    pub unsafe fn set_socket_option<T: Copy>(
797        &self,
798        level: i32,
799        name: i32,
800        value: &T,
801    ) -> io::Result<()> {
802        unsafe { self.inner.set_socket_option(level, name, value) }
803    }
804}
805
806impl_raw_fd!(UdpSocket, socket2::Socket, inner, socket);