use crate::error::Error;
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct ConnId {
idx: u32,
generation: u32,
}
#[cfg_attr(not(target_os = "linux"), allow(dead_code))]
impl ConnId {
pub(crate) const fn new(idx: u32, generation: u32) -> Self {
Self { idx, generation }
}
pub(crate) const fn generation(self) -> u32 {
self.generation
}
#[must_use]
pub const fn index(self) -> usize {
self.idx as usize
}
#[doc(hidden)]
#[must_use]
pub const fn from_parts(index: u32, generation: u32) -> Self {
Self::new(index, generation)
}
}
pub(crate) mod sealed {
use std::net::SocketAddr;
use std::os::fd::RawFd;
use std::sync::{Arc, OnceLock};
use super::ConnId;
use crate::RxMeta;
use crate::error::Result;
pub trait Io {
const DEADLINES: bool = false;
fn expire(&mut self, now_ns: i64) -> Result<()> {
let _ = now_ns;
Ok(())
}
fn close_reason(&mut self, error: crate::error::Error) -> crate::error::Error {
error
}
#[inline]
fn on_handed(&mut self, n: usize) {
let _ = n;
}
fn fd(&self) -> RawFd;
fn rx_space(&mut self) -> &mut [u8];
fn tx_queue(&mut self) -> &mut Vec<u8>;
fn has_buffered_input(&self) -> bool;
fn set_route(&mut self, route: RouteSlot);
fn route_state(&self) -> &RouteSlot;
}
pub trait Deliver<H: ?Sized>: Io {
fn on_received(
&mut self,
id: ConnId,
n: usize,
meta: &RxMeta,
handler: &mut H,
) -> Result<usize>;
}
#[derive(Debug, Clone)]
#[cfg_attr(not(target_os = "linux"), allow(dead_code))]
pub enum RouteSlot {
Ready(crate::route::RouteCheck),
Pending(Arc<OnceLock<crate::route::RouteCheck>>),
}
impl Default for RouteSlot {
fn default() -> Self {
Self::Ready(crate::route::RouteCheck::NotChecked)
}
}
static PENDING: crate::route::RouteCheck = crate::route::RouteCheck::Pending;
#[cfg_attr(not(target_os = "linux"), allow(dead_code))]
impl RouteSlot {
pub fn get(&self) -> &crate::route::RouteCheck {
match self {
Self::Ready(c) => c,
Self::Pending(cell) => cell.get().unwrap_or(&PENDING),
}
}
pub const fn decided(&self) -> bool {
!matches!(
self,
Self::Ready(crate::route::RouteCheck::NotChecked) | Self::Pending(_)
)
}
}
pub trait DialIo {
type Conn: Io;
fn host(&self) -> &str;
fn port(&self) -> u16;
fn addr(&self) -> Option<SocketAddr>;
fn start(&mut self, addr: SocketAddr) -> Result<()>;
fn step(&mut self) -> Result<Option<Self::Conn>>;
fn gate_route(&mut self);
fn awaiting_route(&self) -> Option<RawFd>;
fn route_checked(&mut self, check: crate::route::RouteCheck);
}
}
#[allow(private_bounds)] pub trait Endpoint: sealed::Io {}
impl<T: sealed::Io> Endpoint for T {}
#[allow(private_bounds)]
pub trait Receive<H: ?Sized>: Endpoint + sealed::Deliver<H> {}
impl<H: ?Sized, T: sealed::Deliver<H>> Receive<H> for T {}
#[allow(private_bounds)]
pub trait Dial: sealed::DialIo {}
impl<T: sealed::DialIo> Dial for T {}
pub struct ConnMut<'a, E>(&'a mut E);
impl<'a, E> ConnMut<'a, E> {
#[cfg_attr(not(target_os = "linux"), allow(dead_code))]
pub(crate) const fn new(conn: &'a mut E) -> Self {
Self(conn)
}
pub(crate) const fn inner(&mut self) -> &mut E {
self.0
}
}
impl<E> std::ops::Deref for ConnMut<'_, E> {
type Target = E;
fn deref(&self) -> &E {
self.0
}
}
pub trait Handler {
fn on_open(&mut self, id: ConnId) {
let _ = id;
}
fn on_closed(&mut self, id: ConnId, error: Error) {
let _ = (id, error);
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct DriverStats {
pub polls: u64,
pub recvmsg_calls: u64,
pub recvmsg_eagain: u64,
pub epoll_wait_calls: u64,
pub send_calls: u64,
pub sends: u64,
pub enter_calls: u64,
pub completions: u64,
pub messages: u64,
pub closed: u64,
pub connects: u64,
pub connect_failures: u64,
pub connect_step_max_ns: u64,
pub route_lookups: u64,
pub route_check_ns: u64,
pub route_check_max_ns: u64,
}
impl DriverStats {
#[must_use]
pub const fn syscalls(&self) -> u64 {
self.recvmsg_calls + self.epoll_wait_calls + self.send_calls + self.enter_calls
}
}