// I'm not sure where I got this module from, but it's probably from the // quinn examples, so the license should be okay. use std::{ net::SocketAddr, sync::Arc, time::Duration, }; use quinn::{ Certificate, CertificateChain, ClientConfig, ClientConfigBuilder, Endpoint, Incoming, PrivateKey, ServerConfig, ServerConfigBuilder, TransportConfig, }; /// Constructs a QUIC endpoint configured for use a client only. /// /// ## Args /// /// - server_certs: list of trusted certificates. #[allow(unused)] pub fn make_client_endpoint( bind_addr: SocketAddr, server_certs: &[&[u8]], ) -> anyhow::Result { let mut client_cfg = configure_client (server_certs)?; let mut transport = quinn::TransportConfig::default (); transport.keep_alive_interval (Some (Duration::from_millis (5_000))); client_cfg.transport = Arc::new (transport); let mut endpoint_builder = Endpoint::builder (); endpoint_builder.default_client_config (client_cfg); let (endpoint, _incoming) = endpoint_builder.bind(&bind_addr)?; Ok(endpoint) } /// Constructs a QUIC endpoint configured to listen for incoming connections /// on a certain address and port. /// /// ## Returns /// /// - a stream of incoming QUIC connections /// - server certificate serialized into DER format #[allow(unused)] pub fn make_server_endpoint(bind_addr: SocketAddr) -> anyhow::Result<(Incoming, Vec)> { let (server_config, server_cert) = configure_server()?; let mut endpoint_builder = Endpoint::builder(); endpoint_builder.listen(server_config); let (_endpoint, incoming) = endpoint_builder.bind(&bind_addr)?; Ok((incoming, server_cert)) } /// Builds default quinn client config and trusts given certificates. /// /// ## Args /// /// - server_certs: a list of trusted certificates in DER format. fn configure_client(server_certs: &[&[u8]]) -> anyhow::Result { let mut cfg_builder = ClientConfigBuilder::default(); for cert in server_certs { cfg_builder.add_certificate_authority(Certificate::from_der(cert)?)?; } Ok(cfg_builder.build()) } /// Returns default server configuration along with its certificate. #[allow(clippy::field_reassign_with_default)] // https://github.com/rust-lang/rust-clippy/issues/6527 fn configure_server() -> anyhow::Result<(ServerConfig, Vec)> { let cert = rcgen::generate_simple_self_signed(vec!["localhost".into()]).unwrap(); let cert_der = cert.serialize_der().unwrap(); let priv_key = cert.serialize_private_key_der(); let priv_key = PrivateKey::from_der(&priv_key)?; let mut transport_config = TransportConfig::default(); transport_config.max_concurrent_uni_streams(0).unwrap(); let mut server_config = ServerConfig::default(); server_config.transport = Arc::new(transport_config); let mut cfg_builder = ServerConfigBuilder::new(server_config); let cert = Certificate::from_der(&cert_der)?; cfg_builder.certificate(CertificateChain::from_certs(vec![cert]), priv_key)?; Ok((cfg_builder.build(), cert_der)) }