use crate::{
socket::recv::{pool, router::Router},
stream::socket::{fd::udp, Socket},
};
use std::{io, os::fd::AsRawFd, task::Poll};
pub fn blocking<S: AsRawFd, R: Router>(socket: S, mut alloc: pool::Pool, mut router: R) {
while router.is_open() {
let mut unfilled = alloc.alloc_or_grow();
while router.is_open() {
let res = unfilled.recv_with(|addr, cmsg, buffer| {
udp::recv(&socket, addr, cmsg, &mut [buffer], Default::default())
});
match res {
Ok(segments) => {
for segment in segments {
router.on_segment(segment);
}
break;
}
Err((desc, err)) => {
tracing::error!("socket recv error: {err}");
unfilled = desc;
continue;
}
}
}
}
}
pub async fn non_blocking<S: Socket, R: Router>(socket: S, mut alloc: pool::Pool, mut router: R) {
let mut pending = None;
core::future::poll_fn(move |cx| {
while router.is_open() {
let unfilled = pending.take().unwrap_or_else(|| alloc.alloc_or_grow());
let res = unfilled.recv_with(|addr, cmsg, buffer| {
match socket.poll_recv(cx, addr, cmsg, &mut [buffer]) {
Poll::Pending => Err(io::ErrorKind::WouldBlock.into()),
Poll::Ready(Ok(len)) => Ok(len),
Poll::Ready(Err(err)) => Err(err),
}
});
match res {
Ok(segments) => {
for segment in segments {
router.on_segment(segment);
}
continue;
}
Err((desc, err)) => {
pending = Some(desc);
let kind = err.kind();
if kind == io::ErrorKind::WouldBlock {
return Poll::Pending;
}
if kind == io::ErrorKind::Other {
tracing::info!("worker shutting down due to: {err}");
break;
}
tracing::error!("socket recv error (kind={:?}): {err}", err.kind());
}
}
}
Poll::Ready(())
})
.await;
}