aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-07-12 10:46:08 +0000
committerGitHub <[email protected]>2023-07-12 10:46:08 +0000
commitd8c7c3fc4be377491f5073dff3f884d7af106c57 (patch)
treea2db15460c077cd32187d6b84d2df64b9f584c1f
parentc6e2f4a90b8bc1caf2b62e355af6285347e99c21 (diff)
parentf192f440187c705ce2674731c4d595dc327f08a3 (diff)
Merge pull request #1641 from royb3/poll_udp_socket
Adding polling functions for udp send_to and recv_from.
-rw-r--r--embassy-net/src/udp.rs70
1 files changed, 47 insertions, 23 deletions
diff --git a/embassy-net/src/udp.rs b/embassy-net/src/udp.rs
index 36f8d06f2..0d97b6db1 100644
--- a/embassy-net/src/udp.rs
+++ b/embassy-net/src/udp.rs
@@ -3,7 +3,7 @@
3use core::cell::RefCell; 3use core::cell::RefCell;
4use core::future::poll_fn; 4use core::future::poll_fn;
5use core::mem; 5use core::mem;
6use core::task::Poll; 6use core::task::{Context, Poll};
7 7
8use embassy_net_driver::Driver; 8use embassy_net_driver::Driver;
9use smoltcp::iface::{Interface, SocketHandle}; 9use smoltcp::iface::{Interface, SocketHandle};
@@ -102,37 +102,61 @@ impl<'a> UdpSocket<'a> {
102 /// 102 ///
103 /// Returns the number of bytes received and the remote endpoint. 103 /// Returns the number of bytes received and the remote endpoint.
104 pub async fn recv_from(&self, buf: &mut [u8]) -> Result<(usize, IpEndpoint), Error> { 104 pub async fn recv_from(&self, buf: &mut [u8]) -> Result<(usize, IpEndpoint), Error> {
105 poll_fn(move |cx| { 105 poll_fn(move |cx| self.poll_recv_from(buf, cx)).await
106 self.with_mut(|s, _| match s.recv_slice(buf) { 106 }
107 Ok((n, meta)) => Poll::Ready(Ok((n, meta.endpoint))), 107
108 // No data ready 108 /// Receive a datagram.
109 Err(udp::RecvError::Exhausted) => { 109 ///
110 s.register_recv_waker(cx.waker()); 110 /// When no datagram is available, this method will return `Poll::Pending` and
111 Poll::Pending 111 /// register the current task to be notified when a datagram is received.
112 } 112 ///
113 }) 113 /// When a datagram is received, this method will return `Poll::Ready` with the
114 /// number of bytes received and the remote endpoint.
115 pub fn poll_recv_from(&self, buf: &mut [u8], cx: &mut Context<'_>) -> Poll<Result<(usize, IpEndpoint), Error>> {
116 self.with_mut(|s, _| match s.recv_slice(buf) {
117 Ok((n, meta)) => Poll::Ready(Ok((n, meta.endpoint))),
118 // No data ready
119 Err(udp::RecvError::Exhausted) => {
120 s.register_recv_waker(cx.waker());
121 Poll::Pending
122 }
114 }) 123 })
115 .await
116 } 124 }
117 125
118 /// Send a datagram to the specified remote endpoint. 126 /// Send a datagram to the specified remote endpoint.
127 ///
128 /// This method will wait until the datagram has been sent.
129 ///
130 /// When the remote endpoint is not reachable, this method will return `Err(Error::NoRoute)`
119 pub async fn send_to<T>(&self, buf: &[u8], remote_endpoint: T) -> Result<(), Error> 131 pub async fn send_to<T>(&self, buf: &[u8], remote_endpoint: T) -> Result<(), Error>
120 where 132 where
121 T: Into<IpEndpoint>, 133 T: Into<IpEndpoint>,
122 { 134 {
123 let remote_endpoint = remote_endpoint.into(); 135 let remote_endpoint: IpEndpoint = remote_endpoint.into();
124 poll_fn(move |cx| { 136 poll_fn(move |cx| self.poll_send_to(buf, remote_endpoint, cx)).await
125 self.with_mut(|s, _| match s.send_slice(buf, remote_endpoint) { 137 }
126 // Entire datagram has been sent 138
127 Ok(()) => Poll::Ready(Ok(())), 139 /// Send a datagram to the specified remote endpoint.
128 Err(udp::SendError::BufferFull) => { 140 ///
129 s.register_send_waker(cx.waker()); 141 /// When the datagram has been sent, this method will return `Poll::Ready(Ok())`.
130 Poll::Pending 142 ///
131 } 143 /// When the socket's send buffer is full, this method will return `Poll::Pending`
132 Err(udp::SendError::Unaddressable) => Poll::Ready(Err(Error::NoRoute)), 144 /// and register the current task to be notified when the buffer has space available.
133 }) 145 ///
146 /// When the remote endpoint is not reachable, this method will return `Poll::Ready(Err(Error::NoRoute))`.
147 pub fn poll_send_to<T>(&self, buf: &[u8], remote_endpoint: T, cx: &mut Context<'_>) -> Poll<Result<(), Error>>
148 where
149 T: Into<IpEndpoint>,
150 {
151 self.with_mut(|s, _| match s.send_slice(buf, remote_endpoint) {
152 // Entire datagram has been sent
153 Ok(()) => Poll::Ready(Ok(())),
154 Err(udp::SendError::BufferFull) => {
155 s.register_send_waker(cx.waker());
156 Poll::Pending
157 }
158 Err(udp::SendError::Unaddressable) => Poll::Ready(Err(Error::NoRoute)),
134 }) 159 })
135 .await
136 } 160 }
137 161
138 /// Returns the local endpoint of the socket. 162 /// Returns the local endpoint of the socket.