cap_std/net/
udp_socket.rs

1use crate::net::{Ipv4Addr, Ipv6Addr, SocketAddr};
2#[cfg(not(windows))]
3use io_extras::os::rustix::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
4#[cfg(not(windows))]
5use io_lifetimes::{AsFd, BorrowedFd, OwnedFd};
6#[cfg(windows)]
7use io_lifetimes::{AsSocket, BorrowedSocket, OwnedSocket};
8use std::time::Duration;
9use std::{fmt, io, net};
10#[cfg(windows)]
11use {
12    io_extras::os::windows::{
13        AsHandleOrSocket, AsRawHandleOrSocket, BorrowedHandleOrSocket, IntoRawHandleOrSocket,
14        OwnedHandleOrSocket, RawHandleOrSocket,
15    },
16    std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket},
17};
18
19/// A UDP socket.
20///
21/// This corresponds to [`std::net::UdpSocket`].
22///
23/// This `UdpSocket` has no `bind`, `connect`, or `send_to` methods. To create
24/// a `UdpSocket` bound to an address or to send a message to an address, first
25/// obtain a [`Pool`] permitting the address, and then call
26/// [`Pool::bind_udp_socket`], or [`Pool::connect_udp_socket`], or
27/// [`Pool::send_to_udp_socket_addr`].
28///
29/// [`Pool`]: struct.Pool.html
30/// [`Pool::bind_udp_socket`]: struct.Pool.html#method.bind_udp_socket
31/// [`Pool::connect_udp_socket`]: struct.Pool.html#method.connect_udp_socket
32/// [`Pool::send_to_udp_socket_addr`]: struct.Pool.html#method.send_to_udp_socket_addr
33pub struct UdpSocket {
34    pub(crate) std: net::UdpSocket,
35}
36
37impl UdpSocket {
38    /// Constructs a new instance of `Self` from the given
39    /// `std::net::UdpSocket`.
40    ///
41    /// This grants access the resources the `std::net::UdpSocket` instance
42    /// already has access to.
43    #[inline]
44    pub fn from_std(std: net::UdpSocket) -> Self {
45        Self { std }
46    }
47
48    /// Receives a single datagram message on the socket.
49    ///
50    /// This corresponds to [`std::net::UdpSocket::recv_from`].
51    #[inline]
52    pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
53        self.std.recv_from(buf)
54    }
55
56    /// Receives a single datagram message on the socket, without removing it
57    /// from the queue.
58    ///
59    /// This corresponds to [`std::net::UdpSocket::peek_from`].
60    #[inline]
61    pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
62        self.std.peek_from(buf)
63    }
64
65    /// Returns the socket address of the remote peer this socket was connected
66    /// to.
67    ///
68    /// This corresponds to [`std::net::UdpSocket::peer_addr`].
69    #[inline]
70    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
71        self.std.peer_addr()
72    }
73
74    /// Returns the socket address that this socket was created from.
75    ///
76    /// This corresponds to [`std::net::UdpSocket::local_addr`].
77    #[inline]
78    pub fn local_addr(&self) -> io::Result<SocketAddr> {
79        self.std.local_addr()
80    }
81
82    /// Creates a new independently owned handle to the underlying socket.
83    ///
84    /// This corresponds to [`std::net::UdpSocket::try_clone`].
85    #[inline]
86    pub fn try_clone(&self) -> io::Result<Self> {
87        let udp_socket = self.std.try_clone()?;
88        Ok(Self::from_std(udp_socket))
89    }
90
91    /// Sets the read timeout to the timeout specified.
92    ///
93    /// This corresponds to [`std::net::UdpSocket::set_read_timeout`].
94    #[inline]
95    pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
96        self.std.set_read_timeout(dur)
97    }
98
99    /// Sets the write timeout to the timeout specified.
100    ///
101    /// This corresponds to [`std::net::UdpSocket::set_write_timeout`].
102    #[inline]
103    pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
104        self.std.set_write_timeout(dur)
105    }
106
107    /// Returns the read timeout of this socket.
108    ///
109    /// This corresponds to [`std::net::UdpSocket::read_timeout`].
110    #[inline]
111    pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
112        self.std.read_timeout()
113    }
114
115    /// Returns the write timeout of this socket.
116    ///
117    /// This corresponds to [`std::net::UdpSocket::write_timeout`].
118    #[inline]
119    pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
120        self.std.write_timeout()
121    }
122
123    /// Sets the value of the `SO_BROADCAST` option for this socket.
124    ///
125    /// This corresponds to [`std::net::UdpSocket::set_broadcast`].
126    #[inline]
127    pub fn set_broadcast(&self, broadcast: bool) -> io::Result<()> {
128        self.std.set_broadcast(broadcast)
129    }
130
131    /// Gets the value of the `SO_BROADCAST` option for this socket.
132    ///
133    /// This corresponds to [`std::net::UdpSocket::broadcast`].
134    #[inline]
135    pub fn broadcast(&self) -> io::Result<bool> {
136        self.std.broadcast()
137    }
138
139    /// Sets the value of the `IP_MULTICAST_LOOP` option for this socket.
140    ///
141    /// This corresponds to [`std::net::UdpSocket::set_multicast_loop_v4`].
142    #[inline]
143    pub fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()> {
144        self.std.set_multicast_loop_v4(multicast_loop_v4)
145    }
146
147    /// Gets the value of the `IP_MULTICAST_LOOP` option for this socket.
148    ///
149    /// This corresponds to [`std::net::UdpSocket::multicast_loop_v4`].
150    #[inline]
151    pub fn multicast_loop_v4(&self) -> io::Result<bool> {
152        self.std.multicast_loop_v4()
153    }
154
155    /// Sets the value of the `IP_MULTICAST_TTL` option for this socket.
156    ///
157    /// This corresponds to [`std::net::UdpSocket::set_multicast_ttl_v4`].
158    #[inline]
159    pub fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()> {
160        self.std.set_multicast_ttl_v4(multicast_ttl_v4)
161    }
162
163    /// Gets the value of the `IP_MULTICAST_TTL` option for this socket.
164    ///
165    /// This corresponds to [`std::net::UdpSocket::multicast_ttl_v4`].
166    #[inline]
167    pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
168        self.std.multicast_ttl_v4()
169    }
170
171    /// Sets the value of the `IPV6_MULTICAST_LOOP` option for this socket.
172    ///
173    /// This corresponds to [`std::net::UdpSocket::set_multicast_loop_v6`].
174    #[inline]
175    pub fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()> {
176        self.std.set_multicast_loop_v6(multicast_loop_v6)
177    }
178
179    /// Gets the value of the `IPV6_MULTICAST_LOOP` option for this socket.
180    ///
181    /// This corresponds to [`std::net::UdpSocket::multicast_loop_v6`].
182    #[inline]
183    pub fn multicast_loop_v6(&self) -> io::Result<bool> {
184        self.std.multicast_loop_v6()
185    }
186
187    /// Sets the value for the `IP_TTL` option on this socket.
188    ///
189    /// This corresponds to [`std::net::UdpSocket::set_ttl`].
190    #[inline]
191    pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
192        self.std.set_ttl(ttl)
193    }
194
195    /// Gets the value of the `IP_TTL` option for this socket.
196    ///
197    /// This corresponds to [`std::net::UdpSocket::ttl`].
198    #[inline]
199    pub fn ttl(&self) -> io::Result<u32> {
200        self.std.ttl()
201    }
202
203    /// Executes an operation of the `IP_ADD_MEMBERSHIP` type.
204    ///
205    /// This corresponds to [`std::net::UdpSocket::join_multicast_v4`].
206    #[allow(clippy::trivially_copy_pass_by_ref)]
207    #[inline]
208    pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
209        self.std.join_multicast_v4(multiaddr, interface)
210    }
211
212    /// Executes an operation of the `IPV6_ADD_MEMBERSHIP` type.
213    ///
214    /// This corresponds to [`std::net::UdpSocket::join_multicast_v6`].
215    #[allow(clippy::trivially_copy_pass_by_ref)]
216    #[inline]
217    pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
218        self.std.join_multicast_v6(multiaddr, interface)
219    }
220
221    /// Executes an operation of the `IP_DROP_MEMBERSHIP` type.
222    ///
223    /// This corresponds to [`std::net::UdpSocket::leave_multicast_v4`].
224    #[allow(clippy::trivially_copy_pass_by_ref)]
225    #[inline]
226    pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
227        self.std.leave_multicast_v4(multiaddr, interface)
228    }
229
230    /// Executes an operation of the `IPV6_DROP_MEMBERSHIP` type.
231    ///
232    /// This corresponds to [`std::net::UdpSocket::leave_multicast_v6`].
233    #[allow(clippy::trivially_copy_pass_by_ref)]
234    #[inline]
235    pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
236        self.std.leave_multicast_v6(multiaddr, interface)
237    }
238
239    /// Gets the value of the `SO_ERROR` option on this socket.
240    ///
241    /// This corresponds to [`std::net::UdpSocket::take_error`].
242    #[inline]
243    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
244        self.std.take_error()
245    }
246
247    /// Sends data on the socket to the remote address to which it is
248    /// connected.
249    ///
250    /// This corresponds to [`std::net::UdpSocket::send`].
251    #[inline]
252    pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
253        self.std.send(buf)
254    }
255
256    /// Receives a single datagram message on the socket from the remote
257    /// address to which it is connected.
258    ///
259    /// This corresponds to [`std::net::UdpSocket::recv`].
260    #[inline]
261    pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
262        self.std.recv(buf)
263    }
264
265    /// Receives single datagram on the socket from the remote address to which
266    /// it is connected, without removing the message from input queue.
267    ///
268    /// This corresponds to [`std::net::UdpSocket::peek`].
269    #[inline]
270    pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
271        self.std.peek(buf)
272    }
273
274    /// Moves this UDP socket into or out of nonblocking mode.
275    ///
276    /// This corresponds to [`std::net::UdpSocket::set_nonblocking`].
277    #[inline]
278    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
279        self.std.set_nonblocking(nonblocking)
280    }
281}
282
283// Safety: `SocketlikeViewType` is implemented for `std`'s socket types.
284unsafe impl io_lifetimes::views::SocketlikeViewType for UdpSocket {}
285
286#[cfg(not(windows))]
287impl FromRawFd for UdpSocket {
288    #[inline]
289    unsafe fn from_raw_fd(fd: RawFd) -> Self {
290        Self::from_std(net::UdpSocket::from_raw_fd(fd))
291    }
292}
293
294#[cfg(not(windows))]
295impl From<OwnedFd> for UdpSocket {
296    #[inline]
297    fn from(fd: OwnedFd) -> Self {
298        Self::from_std(net::UdpSocket::from(fd))
299    }
300}
301
302#[cfg(windows)]
303impl FromRawSocket for UdpSocket {
304    #[inline]
305    unsafe fn from_raw_socket(socket: RawSocket) -> Self {
306        Self::from_std(net::UdpSocket::from_raw_socket(socket))
307    }
308}
309
310#[cfg(windows)]
311impl From<OwnedSocket> for UdpSocket {
312    #[inline]
313    fn from(socket: OwnedSocket) -> Self {
314        Self::from_std(net::UdpSocket::from(socket))
315    }
316}
317
318#[cfg(not(windows))]
319impl AsRawFd for UdpSocket {
320    #[inline]
321    fn as_raw_fd(&self) -> RawFd {
322        self.std.as_raw_fd()
323    }
324}
325
326#[cfg(not(windows))]
327impl AsFd for UdpSocket {
328    #[inline]
329    fn as_fd(&self) -> BorrowedFd<'_> {
330        self.std.as_fd()
331    }
332}
333
334#[cfg(windows)]
335impl AsRawSocket for UdpSocket {
336    #[inline]
337    fn as_raw_socket(&self) -> RawSocket {
338        self.std.as_raw_socket()
339    }
340}
341
342#[cfg(windows)]
343impl AsSocket for UdpSocket {
344    #[inline]
345    fn as_socket(&self) -> BorrowedSocket<'_> {
346        self.std.as_socket()
347    }
348}
349
350#[cfg(windows)]
351impl AsRawHandleOrSocket for UdpSocket {
352    #[inline]
353    fn as_raw_handle_or_socket(&self) -> RawHandleOrSocket {
354        self.std.as_raw_handle_or_socket()
355    }
356}
357
358#[cfg(windows)]
359impl AsHandleOrSocket for UdpSocket {
360    #[inline]
361    fn as_handle_or_socket(&self) -> BorrowedHandleOrSocket<'_> {
362        self.std.as_handle_or_socket()
363    }
364}
365
366#[cfg(not(windows))]
367impl IntoRawFd for UdpSocket {
368    #[inline]
369    fn into_raw_fd(self) -> RawFd {
370        self.std.into_raw_fd()
371    }
372}
373
374#[cfg(not(windows))]
375impl From<UdpSocket> for OwnedFd {
376    #[inline]
377    fn from(socket: UdpSocket) -> OwnedFd {
378        socket.std.into()
379    }
380}
381
382#[cfg(windows)]
383impl IntoRawSocket for UdpSocket {
384    #[inline]
385    fn into_raw_socket(self) -> RawSocket {
386        self.std.into_raw_socket()
387    }
388}
389
390#[cfg(windows)]
391impl From<UdpSocket> for OwnedSocket {
392    #[inline]
393    fn from(socket: UdpSocket) -> OwnedSocket {
394        socket.std.into()
395    }
396}
397
398#[cfg(windows)]
399impl IntoRawHandleOrSocket for UdpSocket {
400    #[inline]
401    fn into_raw_handle_or_socket(self) -> RawHandleOrSocket {
402        self.std.into_raw_handle_or_socket()
403    }
404}
405
406#[cfg(windows)]
407impl From<UdpSocket> for OwnedHandleOrSocket {
408    #[inline]
409    fn from(socket: UdpSocket) -> Self {
410        socket.std.into()
411    }
412}
413
414impl fmt::Debug for UdpSocket {
415    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
416        self.std.fmt(f)
417    }
418}