use crate::socket::stats;
use core::mem::size_of;
use s2n_quic_core::{
inet::{ethernet, ipv4, udp},
path::{mtu, MtuError},
};
use s2n_quic_xdp::umem::DEFAULT_FRAME_SIZE;
use tokio::runtime::Handle;
const MIN_FRAME_OVERHEAD: u16 =
(size_of::<ethernet::Header>() + size_of::<ipv4::Header>() + size_of::<udp::Header>()) as _;
#[derive(Debug)]
#[must_use = "Builders do nothing without calling `build`"]
pub struct Builder<Rx = (), Tx = ()> {
rx: Rx,
tx: Tx,
stats: Option<stats::Receiver>,
mtu_config_builder: mtu::Builder,
handle: Option<Handle>,
}
impl Default for Builder<(), ()> {
fn default() -> Self {
Self {
rx: (),
tx: (),
stats: None,
mtu_config_builder: mtu::Config::builder()
.with_max_mtu(DEFAULT_FRAME_SIZE as u16 - MIN_FRAME_OVERHEAD)
.unwrap(),
handle: None,
}
}
}
impl<Rx, Tx> Builder<Rx, Tx> {
pub fn with_handle(mut self, handle: Handle) -> Self {
self.handle = Some(handle);
self
}
pub fn with_stats(mut self, stats: stats::Receiver) -> Self {
self.stats = Some(stats);
self
}
pub fn with_frame_size(mut self, frame_size: u16) -> Result<Self, MtuError> {
self.mtu_config_builder = self
.mtu_config_builder
.with_max_mtu(frame_size.saturating_sub(MIN_FRAME_OVERHEAD))?;
Ok(self)
}
pub fn with_rx<NewRx>(self, rx: NewRx) -> Builder<NewRx, Tx>
where
NewRx: super::rx::Rx,
{
let Self {
tx,
handle,
stats,
mtu_config_builder,
..
} = self;
Builder {
rx,
tx,
handle,
stats,
mtu_config_builder,
}
}
pub fn with_tx<NewTx>(self, tx: NewTx) -> Builder<Rx, NewTx>
where
NewTx: super::tx::Tx,
{
let Self {
rx,
handle,
stats,
mtu_config_builder,
..
} = self;
Builder {
rx,
tx,
handle,
stats,
mtu_config_builder,
}
}
}
impl<Rx, Tx> Builder<Rx, Tx>
where
Rx: 'static + super::rx::Rx + Send,
Tx: 'static + super::tx::Tx<PathHandle = Rx::PathHandle> + Send,
{
pub fn build(self) -> super::Provider<Rx, Tx> {
let Self {
rx,
tx,
stats,
handle,
mtu_config_builder,
} = self;
let stats = stats.unwrap_or_else(|| {
let (_sender, receiver) = stats::channel();
receiver
});
super::Provider {
rx,
tx,
handle,
stats,
mtu_config_builder,
}
}
}