diff options
| author | Easyoakland <[email protected]> | 2025-01-24 18:45:43 -0700 |
|---|---|---|
| committer | Easyoakland <[email protected]> | 2025-01-24 18:45:43 -0700 |
| commit | 2fe299cc538c28711fd838b5f2c3da6143a7335e (patch) | |
| tree | bba0017b2442bad552e9430fc2cb6d307acb3935 /embassy-net/src | |
| parent | 51d87c6603631fda6fb59ca1a65a99c08138b081 (diff) | |
don't infinite loop if udp::send methods receive a buffer too large to ever be sent
Diffstat (limited to 'embassy-net/src')
| -rw-r--r-- | embassy-net/src/udp.rs | 28 |
1 files changed, 26 insertions, 2 deletions
diff --git a/embassy-net/src/udp.rs b/embassy-net/src/udp.rs index 64a22d45b..7baa89ea0 100644 --- a/embassy-net/src/udp.rs +++ b/embassy-net/src/udp.rs | |||
| @@ -21,7 +21,7 @@ pub enum BindError { | |||
| 21 | NoRoute, | 21 | NoRoute, |
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | /// Error returned by [`UdpSocket::recv_from`] and [`UdpSocket::send_to`]. | 24 | /// Error returned by [`UdpSocket::send_to`]. |
| 25 | #[derive(PartialEq, Eq, Clone, Copy, Debug)] | 25 | #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
| 26 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 26 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 27 | pub enum SendError { | 27 | pub enum SendError { |
| @@ -29,9 +29,11 @@ pub enum SendError { | |||
| 29 | NoRoute, | 29 | NoRoute, |
| 30 | /// Socket not bound to an outgoing port. | 30 | /// Socket not bound to an outgoing port. |
| 31 | SocketNotBound, | 31 | SocketNotBound, |
| 32 | /// There is not enough transmit buffer capacity to ever send this packet. | ||
| 33 | Truncated, | ||
| 32 | } | 34 | } |
| 33 | 35 | ||
| 34 | /// Error returned by [`UdpSocket::recv_from`] and [`UdpSocket::send_to`]. | 36 | /// Error returned by [`UdpSocket::recv_from`]. |
| 35 | #[derive(PartialEq, Eq, Clone, Copy, Debug)] | 37 | #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
| 36 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 38 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 37 | pub enum RecvError { | 39 | pub enum RecvError { |
| @@ -224,6 +226,8 @@ impl<'a> UdpSocket<'a> { | |||
| 224 | /// | 226 | /// |
| 225 | /// This method will wait until the datagram has been sent. | 227 | /// This method will wait until the datagram has been sent. |
| 226 | /// | 228 | /// |
| 229 | /// If the socket's send buffer is too small to fit `buf`, this method will return `Poll::Ready(Err(SendError::Truncated))` | ||
| 230 | /// | ||
| 227 | /// When the remote endpoint is not reachable, this method will return `Err(SendError::NoRoute)` | 231 | /// When the remote endpoint is not reachable, this method will return `Err(SendError::NoRoute)` |
| 228 | pub async fn send_to<T>(&self, buf: &[u8], remote_endpoint: T) -> Result<(), SendError> | 232 | pub async fn send_to<T>(&self, buf: &[u8], remote_endpoint: T) -> Result<(), SendError> |
| 229 | where | 233 | where |
| @@ -240,11 +244,21 @@ impl<'a> UdpSocket<'a> { | |||
| 240 | /// When the socket's send buffer is full, this method will return `Poll::Pending` | 244 | /// When the socket's send buffer is full, this method will return `Poll::Pending` |
| 241 | /// and register the current task to be notified when the buffer has space available. | 245 | /// and register the current task to be notified when the buffer has space available. |
| 242 | /// | 246 | /// |
| 247 | /// If the socket's send buffer is too small to fit `buf`, this method will return `Poll::Ready(Err(SendError::Truncated))` | ||
| 248 | /// | ||
| 243 | /// When the remote endpoint is not reachable, this method will return `Poll::Ready(Err(Error::NoRoute))`. | 249 | /// When the remote endpoint is not reachable, this method will return `Poll::Ready(Err(Error::NoRoute))`. |
| 244 | pub fn poll_send_to<T>(&self, buf: &[u8], remote_endpoint: T, cx: &mut Context<'_>) -> Poll<Result<(), SendError>> | 250 | pub fn poll_send_to<T>(&self, buf: &[u8], remote_endpoint: T, cx: &mut Context<'_>) -> Poll<Result<(), SendError>> |
| 245 | where | 251 | where |
| 246 | T: Into<UdpMetadata>, | 252 | T: Into<UdpMetadata>, |
| 247 | { | 253 | { |
| 254 | // Don't need to wake waker in `with_mut` if the buffer will never fit the udp tx_buffer. | ||
| 255 | let send_capacity_too_small = self | ||
| 256 | .stack | ||
| 257 | .with(|i| i.sockets.get::<udp::Socket>(self.handle).payload_send_capacity() < buf.len()); | ||
| 258 | if send_capacity_too_small { | ||
| 259 | return Poll::Ready(Err(SendError::Truncated)); | ||
| 260 | } | ||
| 261 | |||
| 248 | self.with_mut(|s, _| match s.send_slice(buf, remote_endpoint) { | 262 | self.with_mut(|s, _| match s.send_slice(buf, remote_endpoint) { |
| 249 | // Entire datagram has been sent | 263 | // Entire datagram has been sent |
| 250 | Ok(()) => Poll::Ready(Ok(())), | 264 | Ok(()) => Poll::Ready(Ok(())), |
| @@ -268,12 +282,22 @@ impl<'a> UdpSocket<'a> { | |||
| 268 | /// This method will wait until the buffer can fit the requested size before | 282 | /// This method will wait until the buffer can fit the requested size before |
| 269 | /// calling the function to fill its contents. | 283 | /// calling the function to fill its contents. |
| 270 | /// | 284 | /// |
| 285 | /// If the socket's send buffer is too small to fit `size`, this method will return `Poll::Ready(Err(SendError::Truncated))` | ||
| 286 | /// | ||
| 271 | /// When the remote endpoint is not reachable, this method will return `Err(SendError::NoRoute)` | 287 | /// When the remote endpoint is not reachable, this method will return `Err(SendError::NoRoute)` |
| 272 | pub async fn send_to_with<T, F, R>(&mut self, size: usize, remote_endpoint: T, f: F) -> Result<R, SendError> | 288 | pub async fn send_to_with<T, F, R>(&mut self, size: usize, remote_endpoint: T, f: F) -> Result<R, SendError> |
| 273 | where | 289 | where |
| 274 | T: Into<UdpMetadata> + Copy, | 290 | T: Into<UdpMetadata> + Copy, |
| 275 | F: FnOnce(&mut [u8]) -> R, | 291 | F: FnOnce(&mut [u8]) -> R, |
| 276 | { | 292 | { |
| 293 | // Don't need to wake waker in `with_mut` if the buffer will never fit the udp tx_buffer. | ||
| 294 | let send_capacity_too_small = self | ||
| 295 | .stack | ||
| 296 | .with(|i| i.sockets.get::<udp::Socket>(self.handle).payload_send_capacity() < size); | ||
| 297 | if send_capacity_too_small { | ||
| 298 | return Err(SendError::Truncated); | ||
| 299 | } | ||
| 300 | |||
| 277 | let mut f = Some(f); | 301 | let mut f = Some(f); |
| 278 | poll_fn(move |cx| { | 302 | poll_fn(move |cx| { |
| 279 | self.with_mut(|s, _| { | 303 | self.with_mut(|s, _| { |
