From 70214fc2c23aded1f5a1b8a62425ac3aa581102f Mon Sep 17 00:00:00 2001 From: Anthony Grondin <104731965+AnthonyGrondin@users.noreply.github.com> Date: Thu, 31 Oct 2024 16:20:01 -0400 Subject: [PATCH 1/2] feat(embassy-net): Implement `TcpReader::wait_read_ready()` + `TcpWriter::wait_send_ready()` --- embassy-net/src/tcp.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/embassy-net/src/tcp.rs b/embassy-net/src/tcp.rs index a00ced8f4..150b4b36b 100644 --- a/embassy-net/src/tcp.rs +++ b/embassy-net/src/tcp.rs @@ -73,6 +73,16 @@ pub struct TcpWriter<'a> { } impl<'a> TcpReader<'a> { + /// Wait until the socket becomes readable. + /// + /// A socket becomes readable when the receive half of the full-duplex connection is open + /// (see [`may_recv()`](TcpSocket::may_recv)), and there is some pending data in the receive buffer. + /// + /// This is the equivalent of [read](#method.read), without buffering any data. + pub async fn wait_read_ready(&self) { + poll_fn(move |cx| self.io.poll_read_ready(cx)).await + } + /// Read data from the socket. /// /// Returns how many bytes were read, or an error. If no data is available, it waits @@ -115,6 +125,16 @@ impl<'a> TcpReader<'a> { } impl<'a> TcpWriter<'a> { + /// Wait until the socket becomes writable. + /// + /// A socket becomes writable when the transmit half of the full-duplex connection is open + /// (see [`may_send()`](TcpSocket::may_send)), and the transmit buffer is not full. + /// + /// This is the equivalent of [write](#method.write), without sending any data. + pub async fn wait_write_ready(&self) { + poll_fn(move |cx| self.io.poll_write_ready(cx)).await + } + /// Write data to the socket. /// /// Returns how many bytes were written, or an error. If the socket is not ready to From acaba50704b27abe6160539e6e764f5df0d58120 Mon Sep 17 00:00:00 2001 From: Anthony Grondin <104731965+AnthonyGrondin@users.noreply.github.com> Date: Thu, 31 Oct 2024 22:19:49 -0400 Subject: [PATCH 2/2] feat(embassy-net): Implement `wait_send_ready()` + `wait_recv_ready()` for Raw sockets. --- embassy-net/src/raw.rs | 53 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/embassy-net/src/raw.rs b/embassy-net/src/raw.rs index 1f725d00b..a88bcc458 100644 --- a/embassy-net/src/raw.rs +++ b/embassy-net/src/raw.rs @@ -62,6 +62,14 @@ impl<'a> RawSocket<'a> { }) } + /// Wait until the socket becomes readable. + /// + /// A socket is readable when a packet has been received, or when there are queued packets in + /// the buffer. + pub async fn wait_recv_ready(&self) { + poll_fn(move |cx| self.poll_recv_ready(cx)).await + } + /// Receive a datagram. /// /// This method will wait until a datagram is received. @@ -69,6 +77,24 @@ impl<'a> RawSocket<'a> { poll_fn(move |cx| self.poll_recv(buf, cx)).await } + /// Wait until a datagram can be read. + /// + /// When no datagram is readable, this method will return `Poll::Pending` and + /// register the current task to be notified when a datagram is received. + /// + /// When a datagram is received, this method will return `Poll::Ready`. + pub fn poll_recv_ready(&self, cx: &mut Context<'_>) -> Poll<()> { + self.with_mut(|s, _| { + if s.can_recv() { + Poll::Ready(()) + } else { + // socket buffer is empty wait until at least one byte has arrived + s.register_recv_waker(cx.waker()); + Poll::Pending + } + }) + } + /// Receive a datagram. /// /// When no datagram is available, this method will return `Poll::Pending` and @@ -85,6 +111,33 @@ impl<'a> RawSocket<'a> { }) } + /// Wait until the socket becomes writable. + /// + /// A socket becomes writable when there is space in the buffer, from initial memory or after + /// dispatching datagrams on a full buffer. + pub async fn wait_send_ready(&self) { + poll_fn(move |cx| self.poll_send_ready(cx)).await + } + + /// Wait until a datagram can be sent. + /// + /// When no datagram can be sent (i.e. the buffer is full), this method will return + /// `Poll::Pending` and register the current task to be notified when + /// space is freed in the buffer after a datagram has been dispatched. + /// + /// When a datagram can be sent, this method will return `Poll::Ready`. + pub fn poll_send_ready(&self, cx: &mut Context<'_>) -> Poll<()> { + self.with_mut(|s, _| { + if s.can_send() { + Poll::Ready(()) + } else { + // socket buffer is full wait until a datagram has been dispatched + s.register_send_waker(cx.waker()); + Poll::Pending + } + }) + } + /// Send a datagram. /// /// This method will wait until the datagram has been sent.`