agnostic_net/udp.rs
1use std::{
2 future::Future,
3 io,
4 net::{Ipv4Addr, Ipv6Addr, SocketAddr},
5 task::{Context, Poll},
6};
7
8use agnostic_lite::RuntimeLite;
9
10use super::{Fd, ToSocketAddrs};
11
12#[cfg(any(feature = "smol", feature = "tokio"))]
13macro_rules! udp_common_methods_impl {
14 ($ty:ident.$field:ident) => {
15 async fn bind<A: $crate::ToSocketAddrs<Self::Runtime>>(addr: A) -> io::Result<Self>
16 where
17 Self: Sized,
18 {
19 let addrs = addr.to_socket_addrs().await?;
20
21 let mut last_err = None;
22 for addr in addrs {
23 match $ty::bind(addr).await {
24 Ok(socket) => return Ok(Self::from(socket)),
25 Err(e) => {
26 last_err = Some(e);
27 }
28 }
29 }
30
31 Err(last_err.unwrap_or_else(|| {
32 io::Error::new(
33 io::ErrorKind::InvalidInput,
34 "could not resolve to any address",
35 )
36 }))
37 }
38
39 async fn connect<A: $crate::ToSocketAddrs<Self::Runtime>>(&self, addr: A) -> io::Result<()> {
40 let addrs = addr.to_socket_addrs().await?;
41
42 let mut last_err = None;
43
44 for addr in addrs {
45 match self.$field.connect(addr).await {
46 Ok(()) => return Ok(()),
47 Err(e) => last_err = Some(e),
48 }
49 }
50
51 Err(last_err.unwrap_or_else(|| {
52 io::Error::new(
53 io::ErrorKind::InvalidInput,
54 "could not resolve to any address",
55 )
56 }))
57 }
58
59 fn local_addr(&self) -> io::Result<SocketAddr> {
60 self.$field.local_addr()
61 }
62
63 fn peer_addr(&self) -> io::Result<SocketAddr> {
64 self.$field.peer_addr()
65 }
66
67 async fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
68 call!(self.$field.recv(buf))
69 }
70
71 async fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
72 call!(self.$field.recv_from(buf))
73 }
74
75 async fn send(&self, buf: &[u8]) -> io::Result<usize> {
76 call!(self.$field.send(buf))
77 }
78
79 async fn send_to<A: $crate::ToSocketAddrs<Self::Runtime>>(
80 &self,
81 buf: &[u8],
82 target: A,
83 ) -> io::Result<usize> {
84 call!(@send_to self.$field(buf, target))
85 }
86
87 async fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
88 call!(self.$field.peek(buf))
89 }
90
91 async fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
92 call!(self.$field.peek_from(buf))
93 }
94
95 fn join_multicast_v4(&self, multiaddr: ::std::net::Ipv4Addr, interface: ::std::net::Ipv4Addr) -> io::Result<()> {
96 self.$field.join_multicast_v4(multiaddr, interface)
97 }
98
99 fn join_multicast_v6(&self, multiaddr: &::std::net::Ipv6Addr, interface: u32) -> io::Result<()> {
100 self.$field.join_multicast_v6(multiaddr, interface)
101 }
102
103 fn leave_multicast_v4(&self, multiaddr: ::std::net::Ipv4Addr, interface: ::std::net::Ipv4Addr) -> io::Result<()> {
104 self.$field.leave_multicast_v4(multiaddr, interface)
105 }
106
107 fn leave_multicast_v6(&self, multiaddr: &::std::net::Ipv6Addr, interface: u32) -> io::Result<()> {
108 self.$field.leave_multicast_v6(multiaddr, interface)
109 }
110
111 fn multicast_loop_v4(&self) -> io::Result<bool> {
112 self.$field.multicast_loop_v4()
113 }
114
115 fn set_multicast_loop_v4(&self, on: bool) -> io::Result<()> {
116 self.$field.set_multicast_loop_v4(on)
117 }
118
119 fn multicast_ttl_v4(&self) -> io::Result<u32> {
120 self.$field.multicast_ttl_v4()
121 }
122
123 fn set_multicast_ttl_v4(&self, ttl: u32) -> io::Result<()> {
124 self.$field.set_multicast_ttl_v4(ttl)
125 }
126
127 fn multicast_loop_v6(&self) -> io::Result<bool> {
128 self.$field.multicast_loop_v6()
129 }
130
131 fn set_multicast_loop_v6(&self, on: bool) -> io::Result<()> {
132 self.$field.set_multicast_loop_v6(on)
133 }
134
135 fn set_ttl(&self, ttl: u32) -> io::Result<()> {
136 self.$field.set_ttl(ttl)
137 }
138
139 fn ttl(&self) -> io::Result<u32> {
140 self.$field.ttl()
141 }
142
143 fn set_broadcast(&self, broadcast: bool) -> io::Result<()> {
144 self.$field.set_broadcast(broadcast)
145 }
146
147 fn broadcast(&self) -> io::Result<bool> {
148 self.$field.broadcast()
149 }
150 };
151}
152
153/// The abstraction of a UDP socket.
154pub trait UdpSocket:
155 TryFrom<std::net::UdpSocket, Error = io::Error> + Fd + Unpin + Send + Sync + 'static
156{
157 /// The async runtime.
158 type Runtime: RuntimeLite;
159
160 /// Binds this socket to the specified address.
161 fn bind<A: ToSocketAddrs<Self::Runtime>>(
162 addr: A,
163 ) -> impl Future<Output = io::Result<Self>> + Send
164 where
165 Self: Sized;
166
167 /// Connects this socket to the specified address.
168 fn connect<A: ToSocketAddrs<Self::Runtime>>(
169 &self,
170 addr: A,
171 ) -> impl Future<Output = io::Result<()>> + Send;
172
173 /// Returns the local address that this listener is bound to.
174 ///
175 /// This can be useful, for example, when binding to port `0` to figure out which port was actually bound.
176 fn local_addr(&self) -> io::Result<SocketAddr>;
177
178 /// Returns the peer address that this listener is connected to.
179 ///
180 /// This can be useful, for example, when connect to port `0` to figure out which port was actually connected.
181 fn peer_addr(&self) -> io::Result<SocketAddr>;
182
183 /// Receives data from the socket. Returns the number of bytes read and the source address.
184 fn recv(&self, buf: &mut [u8]) -> impl Future<Output = io::Result<usize>> + Send;
185
186 /// Receives data from the socket, returning the number of bytes read and the source address.
187 fn recv_from(
188 &self,
189 buf: &mut [u8],
190 ) -> impl Future<Output = io::Result<(usize, SocketAddr)>> + Send;
191
192 /// Sends data by the socket.
193 fn send(&self, buf: &[u8]) -> impl Future<Output = io::Result<usize>> + Send;
194
195 /// Sends data by the socket to the given address.
196 fn send_to<A: ToSocketAddrs<Self::Runtime>>(
197 &self,
198 buf: &[u8],
199 target: A,
200 ) -> impl Future<Output = io::Result<usize>> + Send;
201
202 /// Receives data from the socket without removing it from the queue.
203 ///
204 /// On success, returns the number of bytes peeked.
205 fn peek(&self, buf: &mut [u8]) -> impl Future<Output = io::Result<usize>> + Send;
206
207 /// Receives data from socket without removing it from the queue.
208 ///
209 /// On success, returns the number of bytes peeked and the origin.
210 fn peek_from(
211 &self,
212 buf: &mut [u8],
213 ) -> impl Future<Output = io::Result<(usize, SocketAddr)>> + Send;
214
215 /// Executes an operation of the `IP_ADD_MEMBERSHIP` type.
216 ///
217 /// This function specifies a new multicast group for this socket to join.
218 /// The address must be a valid multicast address, and `interface` is the
219 /// address of the local interface with which the system should join the
220 /// multicast group. If it's equal to `INADDR_ANY` then an appropriate
221 /// interface is chosen by the system.
222 fn join_multicast_v4(&self, multiaddr: Ipv4Addr, interface: Ipv4Addr) -> io::Result<()>;
223
224 /// Executes an operation of the `IPV6_ADD_MEMBERSHIP` type.
225 ///
226 /// This function specifies a new multicast group for this socket to join.
227 /// The address must be a valid multicast address, and `interface` is the
228 /// index of the interface to join/leave (or 0 to indicate any interface).
229 fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()>;
230
231 /// Executes an operation of the `IP_DROP_MEMBERSHIP` type.
232 ///
233 /// For more information about this option, see [`join_multicast_v4`].
234 ///
235 /// [`join_multicast_v4`]: method@UdpSocket::join_multicast_v4
236 fn leave_multicast_v4(&self, multiaddr: Ipv4Addr, interface: Ipv4Addr) -> io::Result<()>;
237
238 /// Executes an operation of the `IPV6_DROP_MEMBERSHIP` type.
239 ///
240 /// For more information about this option, see [`join_multicast_v6`].
241 ///
242 /// [`join_multicast_v6`]: method@UdpSocket::join_multicast_v6
243 fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()>;
244
245 /// Gets the value of the `IP_MULTICAST_LOOP` option for this socket.
246 ///
247 /// For more information about this option, see [`set_multicast_loop_v4`].
248 ///
249 /// [`set_multicast_loop_v4`]: #method.set_multicast_loop_v4
250 fn multicast_loop_v4(&self) -> io::Result<bool>;
251
252 /// Sets the value of the `IP_MULTICAST_LOOP` option for this socket.
253 ///
254 /// If enabled, multicast packets will be looped back to the local socket.
255 ///
256 /// # Note
257 ///
258 /// This may not have any affect on IPv6 sockets.
259 fn set_multicast_loop_v4(&self, on: bool) -> io::Result<()>;
260
261 /// Gets the value of the `IP_MULTICAST_TTL` option for this socket.
262 ///
263 /// For more information about this option, see [`set_multicast_ttl_v4`].
264 ///
265 /// [`set_multicast_ttl_v4`]: #method.set_multicast_ttl_v4
266 fn multicast_ttl_v4(&self) -> io::Result<u32>;
267
268 /// Sets the value of the `IP_MULTICAST_TTL` option for this socket.
269 ///
270 /// Indicates the time-to-live value of outgoing multicast packets for this socket. The default
271 /// value is 1 which means that multicast packets don't leave the local network unless
272 /// explicitly requested.
273 ///
274 /// # Note
275 ///
276 /// This may not have any affect on IPv6 sockets.
277 fn set_multicast_ttl_v4(&self, ttl: u32) -> io::Result<()>;
278
279 /// Gets the value of the `IPV6_MULTICAST_LOOP` option for this socket.
280 ///
281 /// For more information about this option, see [`set_multicast_loop_v6`].
282 ///
283 /// [`set_multicast_loop_v6`]: #method.set_multicast_loop_v6
284 fn multicast_loop_v6(&self) -> io::Result<bool>;
285
286 /// Sets the value of the `IPV6_MULTICAST_LOOP` option for this socket.
287 ///
288 /// Controls whether this socket sees the multicast packets it sends itself.
289 ///
290 /// # Note
291 ///
292 /// This may not have any affect on IPv4 sockets.
293 fn set_multicast_loop_v6(&self, on: bool) -> io::Result<()>;
294
295 /// Sets the ttl of this UDP socket.
296 fn set_ttl(&self, ttl: u32) -> io::Result<()>;
297
298 /// Gets the ttl of this UDP socket.
299 fn ttl(&self) -> io::Result<u32>;
300
301 /// Sets the broadcast flag for this UDP socket.
302 fn set_broadcast(&self, broadcast: bool) -> io::Result<()>;
303
304 /// Gets the broadcast flag of this UDP socket.
305 fn broadcast(&self) -> io::Result<bool>;
306
307 /// Creates a new independently owned handle to the underlying socket.
308 ///
309 /// The returned `UdpSocket` is a reference to the same socket that this
310 /// object references. Both handles will read and write the same port, and
311 /// options set on one socket will be propagated to the other.
312 fn try_clone(&self) -> ::std::io::Result<Self> {
313 super::os::duplicate::<_, std::net::UdpSocket>(self).and_then(Self::try_from)
314 }
315
316 /// Get the value of the `IPV6_V6ONLY` option for this socket.
317 fn only_v6(&self) -> io::Result<bool> {
318 super::os::only_v6(self)
319 }
320
321 /// Set value for the `SO_RCVBUF` option on this socket.
322 ///
323 /// Changes the size of the operating system’s receive buffer associated with the socket.
324 fn set_recv_buffer_size(&self, size: usize) -> io::Result<()> {
325 super::os::set_recv_buffer_size(self, size)
326 }
327
328 /// Get value for the `SO_RCVBUF` option on this socket.
329 ///
330 /// For more information about this option, see [`set_recv_buffer_size`](UdpSocket::set_recv_buffer_size).
331 fn recv_buffer_size(&self) -> io::Result<usize> {
332 super::os::recv_buffer_size(self)
333 }
334
335 /// Set value for the `SO_SNDBUF` option on this socket.
336 ///
337 /// Changes the size of the operating system’s send buffer associated with the socket.
338 fn set_send_buffer_size(&self, size: usize) -> io::Result<()> {
339 super::os::set_send_buffer_size(self, size)
340 }
341
342 /// Get the value of the `SO_SNDBUF` option on this socket.
343 ///
344 /// For more information about this option, see [`set_send_buffer_size`](UdpSocket::set_send_buffer_size).
345 fn send_buffer_size(&self) -> io::Result<usize> {
346 super::os::send_buffer_size(self)
347 }
348
349 /// Attempts to receive a single datagram on the socket.
350 ///
351 /// Note that on multiple calls to a `poll_*` method in the recv direction, only the
352 /// `Waker` from the `Context` passed to the most recent call will be scheduled to
353 /// receive a wakeup.
354 ///
355 /// # Return value
356 ///
357 /// The function returns:
358 ///
359 /// * `Poll::Pending` if the socket is not ready to read
360 /// * `Poll::Ready(Ok(addr))` reads data from `addr` into `ReadBuf` if the socket is ready
361 /// * `Poll::Ready(Err(e))` if an error is encountered.
362 ///
363 /// # Errors
364 ///
365 /// This function may encounter any standard I/O error except `WouldBlock`.
366 ///
367 /// # Notes
368 /// Note that the socket address **cannot** be implicitly trusted, because it is relatively
369 /// trivial to send a UDP datagram with a spoofed origin in a [packet injection attack].
370 /// Because UDP is stateless and does not validate the origin of a packet,
371 /// the attacker does not need to be able to intercept traffic in order to interfere.
372 /// It is important to be aware of this when designing your application-level protocol.
373 ///
374 /// [packet injection attack]: https://en.wikipedia.org/wiki/Packet_injection
375 fn poll_recv_from(
376 &self,
377 cx: &mut Context<'_>,
378 buf: &mut [u8],
379 ) -> Poll<io::Result<(usize, SocketAddr)>>;
380
381 /// Attempts to send data on the socket to a given address.
382 ///
383 /// Note that on multiple calls to a `poll_*` method in the send direction, only the
384 /// `Waker` from the `Context` passed to the most recent call will be scheduled to
385 /// receive a wakeup.
386 ///
387 /// # Return value
388 ///
389 /// The function returns:
390 ///
391 /// * `Poll::Pending` if the socket is not ready to write
392 /// * `Poll::Ready(Ok(n))` `n` is the number of bytes sent.
393 /// * `Poll::Ready(Err(e))` if an error is encountered.
394 ///
395 /// # Errors
396 ///
397 /// This function may encounter any standard I/O error except `WouldBlock`.
398 fn poll_send_to(
399 &self,
400 cx: &mut Context<'_>,
401 buf: &[u8],
402 target: SocketAddr,
403 ) -> Poll<io::Result<usize>>;
404}