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}