use core::fmt::Debug;
use flume::Sender;
use smoltcp::iface::SocketHandle;
mod channel;
mod error;
pub mod raw;
mod request;
pub mod stack_control;
pub mod tcp;
pub mod udp;
pub use channel::{Channel, HasChannel};
pub use error::{Error, InternalErrorKind};
pub use request::{ChannelClosedError, request, request_blocking, request_nonblocking};
pub struct Request {
pub handle: Option<SocketHandle>,
pub command: Command,
pub resp: Sender<Response>,
}
#[derive(Debug)]
pub enum Command {
StackControl(stack_control::Command),
TcpListen(tcp::listen::Command),
TcpStream(tcp::stream::Command),
Udp(udp::Command),
Raw(raw::Command),
}
#[derive(Debug)]
pub enum Response {
Ok,
Error(Error),
WouldBlock {
handle: Option<SocketHandle>,
command: Command,
},
Udp(udp::Response),
TcpListen(tcp::listen::Response),
TcpStream(tcp::stream::Response),
Raw(raw::Response),
}
macro_rules! impl_try_from {
($ty:ty, $variant:ident) => {
impl TryFrom<Response> for $ty {
type Error = Error;
fn try_from(response: Response) -> Result<Self, Self::Error> {
match response {
Response::$variant(resp) => Ok(resp),
Response::Error(e) => Err(e),
_ => Err(Error::wrong_type()),
}
}
}
};
}
impl_try_from!(udp::Response, Udp);
impl_try_from!(raw::Response, Raw);
impl_try_from!(tcp::stream::Response, TcpStream);
impl_try_from!(tcp::listen::Response, TcpListen);
impl Response {
pub fn to_ok(self) -> Result<(), Error> {
match self {
Response::Ok => Ok(()),
Response::Error(e) => Err(e),
_ => Err(Error::wrong_type()),
}
}
}
#[macro_export]
macro_rules! try_response_as {
($resp:expr, $pat:pat) => {
let $pat = $resp.try_into()? else {
::tracing::error!("invalid response type");
return Err($crate::Error::wrong_type().into());
};
};
}