Skip to main content

nuclei/net/
udp.rs

1//! UDP sockets.
2
3use core::future::poll_fn;
4use core::task::{Context, Poll};
5use std::io;
6use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, UdpSocket};
7
8use super::addr::{ToSocketAddrs, first, resolve};
9use super::none_worked;
10use crate::buf::owned::{IoBuf, IoBufMut};
11use crate::io::source::write::Dest;
12use crate::io::source::{Kind, Sender};
13use crate::io::{Handle, Interest, ReadBuf, Ready};
14
15impl Handle<UdpSocket> {
16    /// A socket bound to the first of the addresses `addr` names that it
17    /// can bind.
18    ///
19    /// # Errors
20    ///
21    /// The last address's error when none could be bound, or the lookup's.
22    pub async fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<Handle<UdpSocket>> {
23        let mut last = None;
24        for addr in resolve(&addr).await? {
25            match UdpSocket::bind(addr) {
26                Ok(socket) => return Handle::adopt(socket, Kind::Udp),
27                Err(err) => last = Some(err),
28            }
29        }
30        Err(none_worked(last))
31    }
32
33    /// A socket on an ephemeral local port, connected to the first of
34    /// `sock_addrs` it can connect to: `send` and `recv` then talk to that
35    /// peer only.
36    ///
37    /// This makes a socket: it is called as `UdpSocket::connect(addr)`.
38    /// Called on a socket, `socket.connect(addr)` is std's own
39    /// `UdpSocket::connect`, reached through `Deref`, which connects that
40    /// socket in place and looks a name up with a blocking call, on the
41    /// calling thread (a shard's, with every task of it). Connect a socket
42    /// in place with a numeric address, or look the name up first with
43    /// [`lookup_host`](super::lookup_host).
44    ///
45    /// # Errors
46    ///
47    /// The last address's error when none worked, or the lookup's.
48    pub async fn connect<A: ToSocketAddrs>(sock_addrs: A) -> io::Result<Handle<UdpSocket>> {
49        let mut last = None;
50        for addr in resolve(&sock_addrs).await? {
51            let local: IpAddr = if addr.is_ipv4() {
52                Ipv4Addr::UNSPECIFIED.into()
53            } else {
54                Ipv6Addr::UNSPECIFIED.into()
55            };
56            let attempt = UdpSocket::bind((local, 0)).and_then(|socket| {
57                socket.connect(addr)?;
58                Handle::adopt(socket, Kind::Udp)
59            });
60            match attempt {
61                Ok(socket) => return Ok(socket),
62                Err(err) => last = Some(err),
63            }
64        }
65        Err(none_worked(last))
66    }
67
68    /// Sends a datagram to the connected peer.
69    ///
70    /// # Errors
71    ///
72    /// As `send(2)` of this datagram. On Windows the completion port sends it
73    /// after the call returns, so a failure the stack finds only then (its
74    /// size is checked first) is the next send's error.
75    pub async fn send(&self, buf: &[u8]) -> io::Result<usize> {
76        poll_fn(|cx| self.source().poll_send(cx, buf, Dest::Connected)).await
77    }
78
79    /// Receives a datagram from the connected peer; what does not fit `buf`
80    /// is cut.
81    ///
82    /// # Errors
83    ///
84    /// As `recv(2)`.
85    pub async fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
86        self.receive(buf, false).await.map(|(n, _)| n)
87    }
88
89    /// Sends all of `buf` as one datagram to the connected peer and gives
90    /// it back with its length. The driver sends from `buf` itself, so the
91    /// bytes are never copied.
92    ///
93    /// If the future is dropped before it completes, the datagram is sent
94    /// whole or not at all: one the driver has not handed to the kernel is
95    /// withdrawn, and one already handed over goes out. `buf` is any
96    /// [`IoBuf`](crate::io::IoBuf).
97    pub async fn send_owned<B>(&self, buf: B) -> (io::Result<usize>, B)
98    where
99        B: IoBuf,
100    {
101        self.source().send_owned(buf, Dest::Connected).await
102    }
103
104    /// Sends all of `buf` as one datagram to the first address `addr` names
105    /// and gives it back with its length, as [`send_owned`](Self::send_owned)
106    /// sends to the connected peer.
107    pub async fn send_to_owned<A, B>(&self, buf: B, addr: A) -> (io::Result<usize>, B)
108    where
109        A: ToSocketAddrs,
110        B: IoBuf,
111    {
112        let target = match first(&addr).await {
113            Ok(target) => target.ok_or_else(|| none_worked(None)),
114            Err(err) => Err(err),
115        };
116        match target {
117            Ok(target) => self.source().send_owned(buf, Dest::Inet(target)).await,
118            Err(err) => (Err(err), buf),
119        }
120    }
121
122    /// Receives a datagram from the connected peer into the spare capacity
123    /// of `buf`, after the bytes it holds, and gives `buf` back with the
124    /// datagram's length. The driver receives into `buf` itself, so the bytes
125    /// are never copied; what does not fit is cut.
126    ///
127    /// If the future is dropped before it completes, a datagram the driver
128    /// received into `buf` stays with the socket for its next receive, so
129    /// none is lost. `buf` is any [`IoBufMut`](crate::io::IoBufMut).
130    pub async fn recv_owned<B>(&self, buf: B) -> (io::Result<usize>, B)
131    where
132        B: IoBufMut,
133    {
134        let (result, buf) = self.recv_from_owned(buf).await;
135        (result.map(|(n, _)| n), buf)
136    }
137
138    /// Receives a datagram with its sender's address into the spare capacity
139    /// of `buf`, as [`recv_owned`](Self::recv_owned).
140    pub async fn recv_from_owned<B>(&self, buf: B) -> (io::Result<(usize, SocketAddr)>, B)
141    where
142        B: IoBufMut,
143    {
144        let (result, buf) = self.source().recv_from_owned(buf).await;
145        let result = result.and_then(|(n, addr)| SocketAddr::from_addr(addr).map(|addr| (n, addr)));
146        (result, buf)
147    }
148
149    /// Looks at the next datagram without taking it.
150    ///
151    /// # Errors
152    ///
153    /// As `recv(2)` with `MSG_PEEK`.
154    pub async fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
155        self.receive(buf, true).await.map(|(n, _)| n)
156    }
157
158    /// Sends a datagram to the first address `addr` names.
159    ///
160    /// # Errors
161    ///
162    /// As `sendto(2)` of this datagram (on Windows, as for
163    /// [`send`](Self::send)), or the lookup's.
164    pub async fn send_to<A: ToSocketAddrs>(&self, buf: &[u8], addr: A) -> io::Result<usize> {
165        let addr = first(&addr).await?.ok_or_else(|| none_worked(None))?;
166        poll_fn(|cx| self.source().poll_send(cx, buf, Dest::Inet(addr))).await
167    }
168
169    /// Receives a datagram with its sender's address.
170    ///
171    /// # Errors
172    ///
173    /// As `recvfrom(2)`.
174    pub async fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
175        self.receive(buf, false).await
176    }
177
178    /// Looks at the next datagram and its sender without taking it.
179    ///
180    /// # Errors
181    ///
182    /// As `recvfrom(2)` with `MSG_PEEK`.
183    pub async fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
184        self.receive(buf, true).await
185    }
186
187    /// Polls for a datagram and its sender, received into the unfilled part
188    /// of `buf`, which advances by its length; what does not fit is cut.
189    /// `Pending` with `cx`'s waker kept until one comes.
190    ///
191    /// # Errors
192    ///
193    /// As `recvfrom(2)`.
194    pub fn poll_recv_from(
195        &self,
196        cx: &mut Context<'_>,
197        buf: &mut ReadBuf<'_>,
198    ) -> Poll<io::Result<SocketAddr>> {
199        let (n, addr) =
200            core::task::ready!(self.poll_receive(cx, buf.initialize_unfilled(), false))?;
201        buf.advance(n);
202        Poll::Ready(Ok(addr))
203    }
204
205    /// Polls to send a datagram to `target`, `Pending` with `cx`'s waker kept
206    /// while one is still queued.
207    ///
208    /// # Errors
209    ///
210    /// As `sendto(2)` of this datagram (on Windows, as for
211    /// [`send`](Self::send)).
212    pub fn poll_send_to(
213        &self,
214        cx: &mut Context<'_>,
215        buf: &[u8],
216        target: SocketAddr,
217    ) -> Poll<io::Result<usize>> {
218        self.source().poll_send(cx, buf, Dest::Inet(target))
219    }
220
221    /// Waits until a receive would end at once: a datagram came, or an
222    /// error (which the receive reports).
223    ///
224    /// # Errors
225    ///
226    /// When the socket cannot be watched.
227    pub async fn readable(&self) -> io::Result<()> {
228        self.ready(Interest::READABLE).await.map(drop)
229    }
230
231    /// Waits until a send would be taken at once.
232    ///
233    /// # Errors
234    ///
235    /// When the socket cannot be watched.
236    pub async fn writable(&self) -> io::Result<()> {
237        self.ready(Interest::WRITABLE).await.map(drop)
238    }
239
240    /// Waits until some of `interest` is ready, and says what is.
241    ///
242    /// # Errors
243    ///
244    /// When the socket cannot be watched.
245    pub async fn ready(&self, interest: Interest) -> io::Result<Ready> {
246        poll_fn(|cx| super::poll_ready(self.source(), cx, interest)).await
247    }
248
249    /// Polls until a receive would end at once.
250    ///
251    /// # Errors
252    ///
253    /// When the socket cannot be watched.
254    pub fn poll_recv_ready(
255        &self,
256        cx: &mut core::task::Context<'_>,
257    ) -> core::task::Poll<io::Result<()>> {
258        self.source().poll_read_ready(cx).map(|r| r.map(drop))
259    }
260
261    /// Polls until a send would be taken at once.
262    ///
263    /// # Errors
264    ///
265    /// When the socket cannot be watched.
266    pub fn poll_send_ready(
267        &self,
268        cx: &mut core::task::Context<'_>,
269    ) -> core::task::Poll<io::Result<()>> {
270        self.source().poll_write_ready(cx).map(|r| r.map(drop))
271    }
272
273    /// Sends a datagram to the connected peer without waiting.
274    ///
275    /// # Errors
276    ///
277    /// `WouldBlock` when a datagram is still queued, and as `send(2)`.
278    pub fn try_send(&self, buf: &[u8]) -> io::Result<usize> {
279        super::at_once(|cx| self.source().poll_send(cx, buf, Dest::Connected))
280    }
281
282    /// Receives a datagram from the connected peer without waiting; what
283    /// does not fit `buf` is cut.
284    ///
285    /// # Errors
286    ///
287    /// `WouldBlock` when none came yet, and as `recv(2)`.
288    pub fn try_recv(&self, buf: &mut [u8]) -> io::Result<usize> {
289        super::at_once(|cx| self.poll_receive(cx, buf, false)).map(|(n, _)| n)
290    }
291
292    /// Looks at the next datagram without taking it or waiting.
293    ///
294    /// # Errors
295    ///
296    /// `WouldBlock` when none came yet, and as `recv(2)` with `MSG_PEEK`.
297    pub fn try_peek(&self, buf: &mut [u8]) -> io::Result<usize> {
298        super::at_once(|cx| self.poll_receive(cx, buf, true)).map(|(n, _)| n)
299    }
300
301    /// Sends a datagram to `target` without waiting.
302    ///
303    /// # Errors
304    ///
305    /// `WouldBlock` when a datagram is still queued, and as `sendto(2)`.
306    pub fn try_send_to(&self, buf: &[u8], target: SocketAddr) -> io::Result<usize> {
307        super::at_once(|cx| self.source().poll_send(cx, buf, Dest::Inet(target)))
308    }
309
310    /// Receives a datagram and its sender's address without waiting.
311    ///
312    /// # Errors
313    ///
314    /// `WouldBlock` when none came yet, and as `recvfrom(2)`.
315    pub fn try_recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
316        super::at_once(|cx| self.poll_receive(cx, buf, false))
317    }
318
319    /// Looks at the next datagram and its sender without taking it or
320    /// waiting.
321    ///
322    /// # Errors
323    ///
324    /// `WouldBlock` when none came yet, and as `recvfrom(2)` with `MSG_PEEK`.
325    pub fn try_peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
326        super::at_once(|cx| self.poll_receive(cx, buf, true))
327    }
328
329    /// The sender of the next datagram, which stays to be received.
330    ///
331    /// # Errors
332    ///
333    /// As `recvfrom(2)` with `MSG_PEEK`.
334    pub async fn peek_sender(&self) -> io::Result<SocketAddr> {
335        poll_fn(|cx| self.poll_peek_sender(cx)).await
336    }
337
338    /// Polls for the sender of the next datagram, which stays to be
339    /// received. At most one byte of it is copied, and dropped.
340    ///
341    /// # Errors
342    ///
343    /// As `recvfrom(2)` with `MSG_PEEK`.
344    pub fn poll_peek_sender(&self, cx: &mut Context<'_>) -> Poll<io::Result<SocketAddr>> {
345        // macOS names no sender for a receive into an empty buffer: a peek of one byte gets
346        // it named, and leaves the datagram whole on the socket. Windows names it for an
347        // empty one, and answers a peek cut short with an error.
348        #[cfg(unix)]
349        let mut room = [0u8; 1];
350        #[cfg(windows)]
351        let mut room = [0u8; 0];
352        self.poll_receive(cx, &mut room, true)
353            .map(|r| r.map(|(_, addr)| addr))
354    }
355
356    /// Receives a datagram from the connected peer into the unfilled part of
357    /// `buf`, which advances by its length; what does not fit is cut.
358    ///
359    /// # Errors
360    ///
361    /// As `recv(2)`.
362    pub async fn recv_buf(&self, buf: &mut ReadBuf<'_>) -> io::Result<usize> {
363        self.recv_buf_from(buf).await.map(|(n, _)| n)
364    }
365
366    /// Receives a datagram and its sender's address into the unfilled part
367    /// of `buf`, which advances by its length; what does not fit is cut.
368    ///
369    /// # Errors
370    ///
371    /// As `recvfrom(2)`.
372    pub async fn recv_buf_from(&self, buf: &mut ReadBuf<'_>) -> io::Result<(usize, SocketAddr)> {
373        // vertexia: the unfilled part is zeroed the first time a buffer offers
374        // it (a `ReadBuf` remembers what it initialized); the receive path
375        // takes initialized bytes. Uninitialized memory through the receive
376        // paths if a profile shows the zeroing.
377        let (n, addr) = self.receive(buf.initialize_unfilled(), false).await?;
378        buf.advance(n);
379        Ok((n, addr))
380    }
381
382    async fn receive(&self, buf: &mut [u8], peek: bool) -> io::Result<(usize, SocketAddr)> {
383        poll_fn(|cx| self.poll_receive(cx, buf, peek)).await
384    }
385
386    #[inline(always)]
387    fn poll_receive(
388        &self,
389        cx: &mut Context<'_>,
390        buf: &mut [u8],
391        peek: bool,
392    ) -> Poll<io::Result<(usize, SocketAddr)>> {
393        self.source().poll_receive_as(cx, buf, peek)
394    }
395}