Skip to content

Commit

Permalink
Refactor TCP socket read impl to handle correctly EOF and no data (es…
Browse files Browse the repository at this point in the history
…p-rs#216)

* ref(tcp_read): tcp read now checks for eof and no data

* ref(tcp_read): SocketClosed is returned instead of Ok(0)
  • Loading branch information
Sofiman authored and bjoernQ committed May 23, 2024
1 parent c4d3b90 commit 38f0780
Showing 1 changed file with 14 additions and 46 deletions.
60 changes: 14 additions & 46 deletions esp-wifi/src/wifi_interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,7 @@ impl<'s, 'n: 's> Drop for Socket<'s, 'n> {
pub enum IoError {
SocketClosed,
MultiCastError(smoltcp::iface::MulticastError),
TcpRecvError(smoltcp::socket::tcp::RecvError),
TcpRecvError,
UdpRecvError(smoltcp::socket::udp::RecvError),
TcpSendError(smoltcp::socket::tcp::SendError),
UdpSendError(smoltcp::socket::udp::SendError),
Expand All @@ -623,52 +623,20 @@ impl<'s, 'n: 's> Io for Socket<'s, 'n> {

impl<'s, 'n: 's> Read for Socket<'s, 'n> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
loop {
self.network.with_mut(|interface, device, sockets| {
interface.poll(
Instant::from_millis((self.network.current_millis_fn)() as i64),
device,
sockets,
)
});

let (may_recv, is_open, can_recv) =
self.network.with_mut(|_interface, _device, sockets| {
let socket = sockets.get_mut::<TcpSocket>(self.socket_handle);

(socket.may_recv(), socket.is_open(), socket.can_recv())
});
if may_recv {
break;
}

if !is_open {
return Err(IoError::SocketClosed);
}

if !can_recv {
return Err(IoError::SocketClosed);
}
}

loop {
let res = self.network.with_mut(|interface, device, sockets| {
interface.poll(
Instant::from_millis((self.network.current_millis_fn)() as i64),
device,
sockets,
)
});

if let false = res {
break;
self.network.with_mut(|interface, device, sockets| {
use smoltcp::socket::tcp::RecvError;

loop {
interface.poll(timestamp(), device, sockets);
let socket = sockets.get_mut::<TcpSocket>(self.socket_handle);

match socket.recv_slice(buf) {
Ok(0) => continue, // no data
Ok(n) => return Ok(n),
Err(RecvError::Finished) => return Err(IoError::SocketClosed), // eof
Err(RecvError::InvalidState) => return Err(IoError::TcpRecvError)
}
}
}

self.network.with_mut(|_interface, _device, sockets| {
let socket = sockets.get_mut::<TcpSocket>(self.socket_handle);

socket.recv_slice(buf).map_err(|e| IoError::TcpRecvError(e))
})
}
}
Expand Down

0 comments on commit 38f0780

Please sign in to comment.