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}