diff options
Diffstat (limited to 'embassy-net/src/tcp.rs')
| -rw-r--r-- | embassy-net/src/tcp.rs | 62 |
1 files changed, 59 insertions, 3 deletions
diff --git a/embassy-net/src/tcp.rs b/embassy-net/src/tcp.rs index 043062e06..a00ced8f4 100644 --- a/embassy-net/src/tcp.rs +++ b/embassy-net/src/tcp.rs | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | 10 | ||
| 11 | use core::future::poll_fn; | 11 | use core::future::poll_fn; |
| 12 | use core::mem; | 12 | use core::mem; |
| 13 | use core::task::Poll; | 13 | use core::task::{Context, Poll}; |
| 14 | 14 | ||
| 15 | use embassy_time::Duration; | 15 | use embassy_time::Duration; |
| 16 | use smoltcp::iface::{Interface, SocketHandle}; | 16 | use smoltcp::iface::{Interface, SocketHandle}; |
| @@ -274,6 +274,16 @@ impl<'a> TcpSocket<'a> { | |||
| 274 | .await | 274 | .await |
| 275 | } | 275 | } |
| 276 | 276 | ||
| 277 | /// Wait until the socket becomes readable. | ||
| 278 | /// | ||
| 279 | /// A socket becomes readable when the receive half of the full-duplex connection is open | ||
| 280 | /// (see [may_recv](#method.may_recv)), and there is some pending data in the receive buffer. | ||
| 281 | /// | ||
| 282 | /// This is the equivalent of [read](#method.read), without buffering any data. | ||
| 283 | pub async fn wait_read_ready(&self) { | ||
| 284 | poll_fn(move |cx| self.io.poll_read_ready(cx)).await | ||
| 285 | } | ||
| 286 | |||
| 277 | /// Read data from the socket. | 287 | /// Read data from the socket. |
| 278 | /// | 288 | /// |
| 279 | /// Returns how many bytes were read, or an error. If no data is available, it waits | 289 | /// Returns how many bytes were read, or an error. If no data is available, it waits |
| @@ -285,6 +295,16 @@ impl<'a> TcpSocket<'a> { | |||
| 285 | self.io.read(buf).await | 295 | self.io.read(buf).await |
| 286 | } | 296 | } |
| 287 | 297 | ||
| 298 | /// Wait until the socket becomes writable. | ||
| 299 | /// | ||
| 300 | /// A socket becomes writable when the transmit half of the full-duplex connection is open | ||
| 301 | /// (see [may_send](#method.may_send)), and the transmit buffer is not full. | ||
| 302 | /// | ||
| 303 | /// This is the equivalent of [write](#method.write), without sending any data. | ||
| 304 | pub async fn wait_write_ready(&self) { | ||
| 305 | poll_fn(move |cx| self.io.poll_write_ready(cx)).await | ||
| 306 | } | ||
| 307 | |||
| 288 | /// Write data to the socket. | 308 | /// Write data to the socket. |
| 289 | /// | 309 | /// |
| 290 | /// Returns how many bytes were written, or an error. If the socket is not ready to | 310 | /// Returns how many bytes were written, or an error. If the socket is not ready to |
| @@ -376,11 +396,25 @@ impl<'a> TcpSocket<'a> { | |||
| 376 | self.io.with_mut(|s, _| s.abort()) | 396 | self.io.with_mut(|s, _| s.abort()) |
| 377 | } | 397 | } |
| 378 | 398 | ||
| 379 | /// Get whether the socket is ready to send data, i.e. whether there is space in the send buffer. | 399 | /// Return whether the transmit half of the full-duplex connection is open. |
| 400 | /// | ||
| 401 | /// This function returns true if it's possible to send data and have it arrive | ||
| 402 | /// to the remote endpoint. However, it does not make any guarantees about the state | ||
| 403 | /// of the transmit buffer, and even if it returns true, [write](#method.write) may | ||
| 404 | /// not be able to enqueue any octets. | ||
| 405 | /// | ||
| 406 | /// In terms of the TCP state machine, the socket must be in the `ESTABLISHED` or | ||
| 407 | /// `CLOSE-WAIT` state. | ||
| 380 | pub fn may_send(&self) -> bool { | 408 | pub fn may_send(&self) -> bool { |
| 381 | self.io.with(|s, _| s.may_send()) | 409 | self.io.with(|s, _| s.may_send()) |
| 382 | } | 410 | } |
| 383 | 411 | ||
| 412 | /// Check whether the transmit half of the full-duplex connection is open | ||
| 413 | /// (see [may_send](#method.may_send)), and the transmit buffer is not full. | ||
| 414 | pub fn can_send(&self) -> bool { | ||
| 415 | self.io.with(|s, _| s.can_send()) | ||
| 416 | } | ||
| 417 | |||
| 384 | /// return whether the receive half of the full-duplex connection is open. | 418 | /// return whether the receive half of the full-duplex connection is open. |
| 385 | /// This function returns true if it’s possible to receive data from the remote endpoint. | 419 | /// This function returns true if it’s possible to receive data from the remote endpoint. |
| 386 | /// It will return true while there is data in the receive buffer, and if there isn’t, | 420 | /// It will return true while there is data in the receive buffer, and if there isn’t, |
| @@ -427,7 +461,7 @@ impl<'d> TcpIo<'d> { | |||
| 427 | }) | 461 | }) |
| 428 | } | 462 | } |
| 429 | 463 | ||
| 430 | fn with_mut<R>(&mut self, f: impl FnOnce(&mut tcp::Socket, &mut Interface) -> R) -> R { | 464 | fn with_mut<R>(&self, f: impl FnOnce(&mut tcp::Socket, &mut Interface) -> R) -> R { |
| 431 | self.stack.with_mut(|i| { | 465 | self.stack.with_mut(|i| { |
| 432 | let socket = i.sockets.get_mut::<tcp::Socket>(self.handle); | 466 | let socket = i.sockets.get_mut::<tcp::Socket>(self.handle); |
| 433 | let res = f(socket, &mut i.iface); | 467 | let res = f(socket, &mut i.iface); |
| @@ -436,6 +470,17 @@ impl<'d> TcpIo<'d> { | |||
| 436 | }) | 470 | }) |
| 437 | } | 471 | } |
| 438 | 472 | ||
| 473 | fn poll_read_ready(&self, cx: &mut Context<'_>) -> Poll<()> { | ||
| 474 | self.with_mut(|s, _| { | ||
| 475 | if s.can_recv() { | ||
| 476 | Poll::Ready(()) | ||
| 477 | } else { | ||
| 478 | s.register_recv_waker(cx.waker()); | ||
| 479 | Poll::Pending | ||
| 480 | } | ||
| 481 | }) | ||
| 482 | } | ||
| 483 | |||
| 439 | async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> { | 484 | async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> { |
| 440 | poll_fn(move |cx| { | 485 | poll_fn(move |cx| { |
| 441 | // CAUTION: smoltcp semantics around EOF are different to what you'd expect | 486 | // CAUTION: smoltcp semantics around EOF are different to what you'd expect |
| @@ -464,6 +509,17 @@ impl<'d> TcpIo<'d> { | |||
| 464 | .await | 509 | .await |
| 465 | } | 510 | } |
| 466 | 511 | ||
| 512 | fn poll_write_ready(&self, cx: &mut Context<'_>) -> Poll<()> { | ||
| 513 | self.with_mut(|s, _| { | ||
| 514 | if s.can_send() { | ||
| 515 | Poll::Ready(()) | ||
| 516 | } else { | ||
| 517 | s.register_send_waker(cx.waker()); | ||
| 518 | Poll::Pending | ||
| 519 | } | ||
| 520 | }) | ||
| 521 | } | ||
| 522 | |||
| 467 | async fn write(&mut self, buf: &[u8]) -> Result<usize, Error> { | 523 | async fn write(&mut self, buf: &[u8]) -> Result<usize, Error> { |
| 468 | poll_fn(move |cx| { | 524 | poll_fn(move |cx| { |
| 469 | self.with_mut(|s, _| match s.send_slice(buf) { | 525 | self.with_mut(|s, _| match s.send_slice(buf) { |
