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