#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(default, deny_unknown_fields)] pub struct Settings { pub alt_svc_max_age: u64, pub max_concurrent_connections: u32, pub max_concurrent_bidistream: u32, pub max_concurrent_unistream: u32, /// QUIC idle timeout in seconds; zero disables the transport idle timeout. pub max_idle_timeout: u64, } impl Default for Settings { fn default() -> Self { Self { alt_svc_max_age: 3600, max_concurrent_connections: 512, max_concurrent_bidistream: 100, max_concurrent_unistream: 100, max_idle_timeout: 10, } } } impl Settings { pub fn validate(&self) -> Result<()> { ensure!( self.alt_svc_max_age <= 604800, "HTTP/3 Alt-Svc lifetime must be at most seven days" ); ensure!( (1..=4096).contains(&self.max_concurrent_connections), "HTTP/3 connections per listener must be 1..4096" ); ensure!( (1..=1024).contains(&self.max_concurrent_bidistream), "HTTP/3 bidirectional streams must be 1..1024" ); ensure!((3..=1024).contains(&self.max_concurrent_unistream),"HTTP/3 requires at least three peer unidirectional streams (control and QPACK), maximum 1024"); ensure!( self.max_idle_timeout <= 86400, "HTTP/3 idle timeout must be 0..86400 seconds" ); Ok(()) } pub fn transport(&self) -> Result { self.validate()?; let mut transport = quinn::TransportConfig::default(); transport .max_concurrent_bidi_streams(self.max_concurrent_bidistream.into()) .max_concurrent_uni_streams(self.max_concurrent_unistream.into()) .max_idle_timeout(if self.max_idle_timeout == 0 { None } else { Some(Duration::from_secs(self.max_idle_timeout).try_into()?) }) .stream_receive_window((256 * 1024u32).into()) .receive_window((8 * 1024 * 1024u32).into()) .send_window(8 * 1024 * 1024) .datagram_receive_buffer_size(None); Ok(transport) } }