Hi, I've been looking at this repo and I was wondering if you thought of my question about the way you poll each socket. I'd love to use this instead of mine because it does not do a second copy of the rx buffer. But it looks to me that this copy is needed. Look:
impl AsyncRead for TcpSocket {
fn poll_read(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut ReadBuf<'_>,
) -> Poll<io::Result<()>> {
let mut set = self.reactor.socket_alloctor().lock();
let mut socket = set.get::<socket::TcpSocket>(*self.handle);
if !socket.may_recv() {
return Poll::Ready(Ok(()));
}
if socket.can_recv() {
let read = socket
.recv_slice(buf.initialize_unfilled())
.map_err(map_err)?;
buf.advance(read);
return Poll::Ready(Ok(()));
}
socket.register_recv_waker(cx.waker());
Poll::Pending
}
}
you are saying that there's no chance the socket will be overwritten before a new poll is made. It looks like smoltcp uses arbitrary socket sizes, so if the socket size is of half a TCP packet size, then I thought it could be that half a packet must be taken out of the socket before a new part emerges and then the ACK is sent. However, I think there's no sense in what I said because smoltcp will always analyze the entire packet before delivering to me. So a ACK will only be sent after the entire packet is received.
But is the ACK sent when socket.recv_slice
is called? I researched a bit and it looks like not. I think the ACK is sent right after the packet is received in smoltcp and put available to socket.recv_slice
. So if I don't call recv_slice
fast enough it would be overwritten by the next packet, because ACK is already sent before I call socket.rect_slice
. The socket.recv_slice
end up calling this:
pub fn dequeue_many_with<'b, R, F>(&'b mut self, f: F) -> (usize, R)
where F: FnOnce(&'b mut [T]) -> (usize, R) {
let capacity = self.capacity();
let max_size = cmp::min(self.len(), capacity - self.read_at);
let (size, result) = f(&mut self.storage[self.read_at..self.read_at + max_size]);
assert!(size <= max_size);
self.read_at = if capacity > 0 {
(self.read_at + size) % capacity
} else {
0
};
self.length -= size;
(size, result)
}
which does not look like it triggers an ACK response. So it looks like ACK is sent before this.
I'm still not convinced for the TCP case, but what about UDP?
pub fn poll_recv_from(
&self,
cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<io::Result<(usize, SocketAddr)>> {
let mut set = self.reactor.socket_alloctor().lock();
let mut socket = set.get::<socket::UdpSocket>(*self.handle);
match socket.recv_slice(buf) {
// the buffer is empty
Err(smoltcp::Error::Exhausted) => {}
r => {
let (size, endpoint) = r.map_err(map_err)?;
return Poll::Ready(Ok((size, ep2sa(&endpoint))));
}
}
socket.register_recv_waker(cx.waker());
Poll::Pending
}
UDP has no ACK, so there's no way that the server would know that I already received a packet, so there's the chance that poll does not occur fast enough to grab a packet before it's overwritten. Same for RawSocket.
By the way, will you support the most recent version of smoltcp? I needed it because of some things from there, mostly to do a virtual interface.
Thanks