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