use byteorder::{ReadBytesExt, WriteBytesExt, LE};
use std::{
io,
num::{NonZeroU32, NonZeroUsize},
time::Duration,
};
use crate::protocol_err;
#[cfg_attr(feature = "dump", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[non_exhaustive]
pub enum LinkPing {
Periodic(Duration),
WhenIdle(Duration),
WhenTimedOut,
}
#[cfg_attr(feature = "dump", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "dump", serde(default))]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[allow(clippy::manual_non_exhaustive)]
pub struct Cfg {
pub io_write_size: NonZeroUsize,
pub send_buffer: NonZeroU32,
pub send_queue: NonZeroUsize,
pub recv_buffer: NonZeroU32,
pub recv_queue: NonZeroUsize,
pub link_ack_timeout_min: Duration,
pub link_ack_timeout_roundtrip_factor: NonZeroU32,
pub link_ack_timeout_max: Duration,
pub link_unacked_init: NonZeroUsize,
pub link_unacked_limit: NonZeroUsize,
pub link_ping: LinkPing,
pub link_ping_timeout: Duration,
pub link_retest_interval: Duration,
pub link_non_working_timeout: Duration,
pub link_flush_delay: Duration,
pub no_link_timeout: Duration,
pub termination_timeout: Duration,
pub connect_queue: NonZeroUsize,
pub stats_intervals: Vec<Duration>,
#[doc(hidden)]
pub _non_exhaustive: (),
}
impl Default for Cfg {
fn default() -> Self {
Self {
io_write_size: NonZeroUsize::new(8_192).unwrap(),
send_buffer: NonZeroU32::new(67_108_864).unwrap(),
send_queue: NonZeroUsize::new(1024).unwrap(),
recv_buffer: NonZeroU32::new(67_108_864).unwrap(),
recv_queue: NonZeroUsize::new(1024).unwrap(),
link_ack_timeout_min: Duration::from_secs(1),
link_ack_timeout_roundtrip_factor: NonZeroU32::new(5).unwrap(),
link_ack_timeout_max: Duration::from_secs(30),
link_unacked_init: NonZeroUsize::new(8192).unwrap(),
link_unacked_limit: NonZeroUsize::new(33_554_432).unwrap(),
link_ping: LinkPing::WhenIdle(Duration::from_secs(15)),
link_ping_timeout: Duration::from_secs(40),
link_retest_interval: Duration::from_secs(15),
link_non_working_timeout: Duration::from_secs(60),
link_flush_delay: Duration::from_millis(500),
no_link_timeout: Duration::from_secs(90),
termination_timeout: Duration::from_secs(300),
connect_queue: NonZeroUsize::new(32).unwrap(),
stats_intervals: vec![Duration::from_secs(1), Duration::from_secs(5), Duration::from_secs(10)],
_non_exhaustive: (),
}
}
}
#[derive(Clone, Debug)]
pub(crate) struct ExchangedCfg {
pub recv_buffer: NonZeroU32,
}
impl ExchangedCfg {
pub fn write(&self, mut writer: impl io::Write) -> Result<(), io::Error> {
writer.write_u32::<LE>(self.recv_buffer.get())?;
Ok(())
}
pub fn read(mut reader: impl io::Read) -> Result<Self, io::Error> {
let this = Self {
recv_buffer: NonZeroU32::new(reader.read_u32::<LE>()?)
.ok_or_else(|| protocol_err!("recv_buffer must not be zero"))?,
};
Ok(this)
}
}
impl From<&Cfg> for ExchangedCfg {
fn from(cfg: &Cfg) -> Self {
Self { recv_buffer: cfg.recv_buffer }
}
}