use quinn::{EndpointConfig, MtuDiscoveryConfig, VarInt};
use smol_str::SmolStr;
use std::{sync::Arc, time::Duration};
#[viewit::viewit(setters(prefix = "with"))]
#[derive(Clone)]
pub struct Options {
#[viewit(
getter(
style = "ref",
const,
attrs(doc = "Gets the server name used for TLS.")
),
setter(attrs(doc = "Sets the server name used for TLS."))
)]
server_name: SmolStr,
#[viewit(
getter(const, attrs(doc = "Gets the timeout of the connect phase.")),
setter(attrs(doc = "Sets the timeout for connecting to an address."))
)]
connect_timeout: Duration,
#[viewit(
getter(
const,
attrs(
doc = "Gets the maximum duration of inactivity in ms to accept before timing out the connection."
)
),
setter(attrs(
doc = "Sets the maximum duration of inactivity in ms to accept before timing out the connection."
))
)]
max_idle_timeout: u32,
#[viewit(
getter(
const,
attrs(doc = "Gets the period of inactivity before sending a keep-alive packet.")
),
setter(attrs(doc = "Sets the period of inactivity before sending a keep-alive packet."))
)]
keep_alive_interval: Duration,
#[viewit(
getter(
const,
attrs(
doc = "Gets the maximum number of incoming bidirectional streams that may be open concurrently by the remote peer."
)
),
setter(attrs(
doc = "Sets the maximum number of incoming bidirectional streams that may be open concurrently by the remote peer."
))
)]
max_concurrent_stream_limit: u32,
#[viewit(
getter(
const,
attrs(
doc = "Gets the max unacknowledged data in bytes that may be send on a single stream."
)
),
setter(attrs(
doc = "Sets the max unacknowledged data in bytes that may be send on a single stream."
))
)]
max_stream_data: u32,
#[viewit(
getter(
const,
attrs(
doc = "Gets the max unacknowledged data in bytes that may be send in total on all streams of a connection."
)
),
setter(attrs(
doc = "Sets the max unacknowledged data in bytes that may be send in total on all streams of a connection."
))
)]
max_connection_data: u32,
#[viewit(
getter(
const,
attrs(doc = "Gets the TLS client config for the inner [`quinn::ClientConfig`].")
),
setter(attrs(doc = "Sets the TLS client config for the inner [`quinn::ClientConfig`]."))
)]
client_config: quinn::ClientConfig,
#[viewit(
getter(
const,
attrs(doc = "Gets the TLS server config for the inner [`quinn::ServerConfig`].")
),
setter(attrs(doc = "Sets the TLS server config for the inner [`quinn::ServerConfig`]."))
)]
server_config: quinn::ServerConfig,
#[viewit(
getter(
const,
attrs(doc = "Gets the quinn's [`EndpointConfig`](quinn::EndpointConfig).")
),
setter(attrs(doc = "Sets the quinn's [`EndpointConfig`](quinn::EndpointConfig)."))
)]
endpoint_config: EndpointConfig,
#[viewit(vis = "", getter(skip), setter(skip))]
mtu_discovery_config: Option<MtuDiscoveryConfig>,
}
impl Options {
pub fn new(
server_name: impl Into<SmolStr>,
server_config: quinn::ServerConfig,
client_config: quinn::ClientConfig,
endpoint_config: EndpointConfig,
) -> Self {
Self {
server_name: server_name.into(),
client_config,
server_config,
endpoint_config,
max_idle_timeout: Duration::from_secs(10).as_millis() as u32,
max_concurrent_stream_limit: 256,
keep_alive_interval: Duration::from_secs(8),
max_connection_data: 15_000_000,
connect_timeout: Duration::from_secs(10),
max_stream_data: 10_000_000,
mtu_discovery_config: Some(Default::default()),
}
}
}
#[viewit::viewit]
#[derive(Debug, Clone)]
pub(super) struct QuinnOptions {
server_name: SmolStr,
client_config: quinn::ClientConfig,
server_config: quinn::ServerConfig,
endpoint_config: quinn::EndpointConfig,
connect_timeout: Duration,
max_stream_data: usize,
max_connection_data: usize,
max_open_streams: usize,
}
impl From<Options> for QuinnOptions {
fn from(config: Options) -> QuinnOptions {
let Options {
server_name,
mut client_config,
mut server_config,
max_idle_timeout,
max_concurrent_stream_limit,
keep_alive_interval,
max_connection_data,
max_stream_data,
endpoint_config,
mtu_discovery_config,
connect_timeout,
} = config;
let mut transport = quinn::TransportConfig::default();
transport.max_concurrent_uni_streams(max_concurrent_stream_limit.into());
transport.max_concurrent_bidi_streams(max_concurrent_stream_limit.into());
transport.datagram_receive_buffer_size(None);
transport.keep_alive_interval(Some(keep_alive_interval));
transport.max_idle_timeout(Some(VarInt::from_u32(max_idle_timeout).into()));
transport.allow_spin(false);
transport.stream_receive_window(max_stream_data.into());
transport.receive_window(max_connection_data.into());
transport.mtu_discovery_config(mtu_discovery_config);
let transport = Arc::new(transport);
server_config.transport = Arc::clone(&transport);
server_config.migration(false);
client_config.transport_config(transport);
QuinnOptions {
server_name,
client_config,
server_config,
endpoint_config,
max_stream_data: max_stream_data as usize,
max_connection_data: max_connection_data as usize,
max_open_streams: max_concurrent_stream_limit as usize,
connect_timeout,
}
}
}