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