diff options
| author | Dario Nieuwenhuis <[email protected]> | 2025-01-26 23:02:05 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-01-26 23:02:05 +0000 |
| commit | 7ec0b30484a6d975a17f14117c4323d372b400d3 (patch) | |
| tree | 361098872c4dc812acbb1471e2e5fa63352fb120 | |
| parent | ecc1aab867ede9f0b5146b758a5797dbc595d486 (diff) | |
| parent | c0d14a145c901126a548a77026ef2ef0d6e79738 (diff) | |
Merge pull request #3804 from Easyoakland/fix-udp-send
Return Truncate error instead of looping forever on udp send.
| -rw-r--r-- | embassy-net/src/udp.rs | 24 |
1 files changed, 22 insertions, 2 deletions
diff --git a/embassy-net/src/udp.rs b/embassy-net/src/udp.rs index 64a22d45b..eca3980b9 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 | PacketTooLarge, | ||
| 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,19 @@ 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.with(|s, _| s.payload_send_capacity() < buf.len()); | ||
| 256 | if send_capacity_too_small { | ||
| 257 | return Poll::Ready(Err(SendError::PacketTooLarge)); | ||
| 258 | } | ||
| 259 | |||
| 248 | self.with_mut(|s, _| match s.send_slice(buf, remote_endpoint) { | 260 | self.with_mut(|s, _| match s.send_slice(buf, remote_endpoint) { |
| 249 | // Entire datagram has been sent | 261 | // Entire datagram has been sent |
| 250 | Ok(()) => Poll::Ready(Ok(())), | 262 | Ok(()) => Poll::Ready(Ok(())), |
| @@ -268,12 +280,20 @@ impl<'a> UdpSocket<'a> { | |||
| 268 | /// This method will wait until the buffer can fit the requested size before | 280 | /// This method will wait until the buffer can fit the requested size before |
| 269 | /// calling the function to fill its contents. | 281 | /// calling the function to fill its contents. |
| 270 | /// | 282 | /// |
| 283 | /// If the socket's send buffer is too small to fit `size`, this method will return `Poll::Ready(Err(SendError::Truncated))` | ||
| 284 | /// | ||
| 271 | /// When the remote endpoint is not reachable, this method will return `Err(SendError::NoRoute)` | 285 | /// 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> | 286 | pub async fn send_to_with<T, F, R>(&mut self, size: usize, remote_endpoint: T, f: F) -> Result<R, SendError> |
| 273 | where | 287 | where |
| 274 | T: Into<UdpMetadata> + Copy, | 288 | T: Into<UdpMetadata> + Copy, |
| 275 | F: FnOnce(&mut [u8]) -> R, | 289 | F: FnOnce(&mut [u8]) -> R, |
| 276 | { | 290 | { |
| 291 | // Don't need to wake waker in `with_mut` if the buffer will never fit the udp tx_buffer. | ||
| 292 | let send_capacity_too_small = self.with(|s, _| s.payload_send_capacity() < size); | ||
| 293 | if send_capacity_too_small { | ||
| 294 | return Err(SendError::PacketTooLarge); | ||
| 295 | } | ||
| 296 | |||
| 277 | let mut f = Some(f); | 297 | let mut f = Some(f); |
| 278 | poll_fn(move |cx| { | 298 | poll_fn(move |cx| { |
| 279 | self.with_mut(|s, _| { | 299 | self.with_mut(|s, _| { |
