use std::time::Duration;
use crate::DEFAULT_MAX_UDP_PAYLOAD_SIZE;
const DEFAULT_HANDSHAKE_TIMEOUT: Duration = Duration::from_secs(5);
const DEFAULT_IDLE_TIMEOUT: Duration = Duration::from_secs(30);
#[derive(Debug, Clone)]
pub struct QuicConfig {
pub handshake_timeout: Duration,
pub idle_timeout: Duration,
pub max_udp_payload_size: usize,
pub application_protos: Vec<Vec<u8>>,
pub verify_peer: bool,
pub ca_certs_directory: Option<String>,
pub ca_certs_file: Option<String>,
pub verify_algorithm_prefs: Option<Vec<u16>>,
pub initial_max_data: u64,
pub initial_max_stream_data_bidi_local: u64,
pub initial_max_stream_data_bidi_remote: u64,
pub initial_max_stream_data_uni: u64,
pub initial_max_streams_bidi: u64,
pub initial_max_streams_uni: u64,
}
impl Default for QuicConfig {
fn default() -> Self {
Self {
handshake_timeout: DEFAULT_HANDSHAKE_TIMEOUT,
idle_timeout: DEFAULT_IDLE_TIMEOUT,
max_udp_payload_size: DEFAULT_MAX_UDP_PAYLOAD_SIZE,
application_protos: vec![b"h3".to_vec()],
verify_peer: true,
ca_certs_directory: None,
ca_certs_file: None,
verify_algorithm_prefs: None,
initial_max_data: 10_000_000,
initial_max_stream_data_bidi_local: 1_000_000,
initial_max_stream_data_bidi_remote: 1_000_000,
initial_max_stream_data_uni: 1_000_000,
initial_max_streams_bidi: 100,
initial_max_streams_uni: 100,
}
}
}
impl QuicConfig {
pub fn builder() -> QuicConfigBuilder {
QuicConfigBuilder::default()
}
pub fn to_quiche_config(&self) -> Result<squiche::Config, squiche::Error> {
let mut config = squiche::Config::new(squiche::SCION_PROTOCOL_VERSION)?;
config.set_application_protos(
&self
.application_protos
.iter()
.map(|p| p.as_slice())
.collect::<Vec<_>>(),
)?;
if let Some(ca_certs_dir) = &self.ca_certs_directory {
config.load_verify_locations_from_directory(ca_certs_dir)?;
}
if let Some(ca_certs_file) = &self.ca_certs_file {
config.load_verify_locations_from_file(ca_certs_file)?;
}
config.set_max_idle_timeout(self.idle_timeout.as_millis() as u64);
config.set_max_recv_udp_payload_size(self.max_udp_payload_size);
config.set_max_send_udp_payload_size(self.max_udp_payload_size);
config.set_initial_max_data(self.initial_max_data);
config.set_initial_max_stream_data_bidi_local(self.initial_max_stream_data_bidi_local);
config.set_initial_max_stream_data_bidi_remote(self.initial_max_stream_data_bidi_remote);
config.set_initial_max_stream_data_uni(self.initial_max_stream_data_uni);
config.set_initial_max_streams_bidi(self.initial_max_streams_bidi);
config.set_initial_max_streams_uni(self.initial_max_streams_uni);
config.set_disable_active_migration(true);
config.verify_peer(self.verify_peer);
if let Some(prefs) = &self.verify_algorithm_prefs {
config.set_verify_algorithm_prefs(prefs)?;
}
Ok(config)
}
}
#[derive(Debug, Default)]
pub struct QuicConfigBuilder {
config: QuicConfig,
}
impl QuicConfigBuilder {
pub fn handshake_timeout(mut self, timeout: Duration) -> Self {
self.config.handshake_timeout = timeout;
self
}
pub fn idle_timeout(mut self, timeout: Duration) -> Self {
self.config.idle_timeout = timeout;
self
}
pub fn max_udp_payload_size(mut self, size: usize) -> Self {
self.config.max_udp_payload_size = size;
self
}
pub fn application_protos(mut self, protos: Vec<Vec<u8>>) -> Self {
self.config.application_protos = protos;
self
}
pub fn verify_peer(mut self, verify: bool) -> Self {
self.config.verify_peer = verify;
self
}
pub fn ca_certs_dir(mut self, path: impl Into<String>) -> Self {
self.config.ca_certs_directory = Some(path.into());
self
}
pub fn ca_certs_file(mut self, path: impl Into<String>) -> Self {
self.config.ca_certs_file = Some(path.into());
self
}
pub fn verify_algorithm_prefs(mut self, prefs: Vec<u16>) -> Self {
self.config.verify_algorithm_prefs = Some(prefs);
self
}
pub fn build(self) -> QuicConfig {
self.config
}
}