aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2025-01-26 23:02:05 +0000
committerGitHub <[email protected]>2025-01-26 23:02:05 +0000
commit7ec0b30484a6d975a17f14117c4323d372b400d3 (patch)
tree361098872c4dc812acbb1471e2e5fa63352fb120
parentecc1aab867ede9f0b5146b758a5797dbc595d486 (diff)
parentc0d14a145c901126a548a77026ef2ef0d6e79738 (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.rs24
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))]
27pub enum SendError { 27pub 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))]
37pub enum RecvError { 39pub 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, _| {