use std::{error::Error, sync::Arc, time::Duration};
use ::dquic::{
builder::QuicListenersBuilder,
prelude::{
AuthClient, BindUri, Connection, ListenError, ProductStreamsConcurrencyController,
QuicListeners, Resolve, ServerError, handy,
},
qbase::{param::ServerParameters, token::TokenProvider},
qevent::telemetry::QLog,
qinterface::{
component::route::QuicRouter, device::Devices, io::ProductIO, manager::InterfaceManager,
},
};
use rustls::{crypto::CryptoProvider, server::danger::ClientCertVerifier};
use crate::{
connection::ConnectionBuilder,
pool::Pool,
server::{Servers, ServersRouter, UnresolvedRequest},
};
pub struct H3ServersTlsBuilder {
crypto_provider: Option<Arc<CryptoProvider>>,
client_cert_verifier: Option<Arc<dyn ClientCertVerifier>>,
}
pub type H3Servers<S> = Servers<Arc<QuicListeners>, ServersRouter<S>>;
impl H3Servers<()> {
pub fn builder() -> H3ServersTlsBuilder {
H3ServersTlsBuilder {
crypto_provider: None,
client_cert_verifier: None,
}
}
}
impl H3ServersTlsBuilder {
pub fn with_crypto_provider(mut self, crypto_provider: impl Into<Arc<CryptoProvider>>) -> Self {
self.crypto_provider = Some(crypto_provider.into());
self
}
pub fn with_client_cert_verifier(
mut self,
client_cert_verifier: Arc<dyn ClientCertVerifier>,
) -> Result<H3ServersBuilder, rustls::Error> {
self.client_cert_verifier = Some(client_cert_verifier);
self.try_into()
}
pub fn without_client_cert_verifier(mut self) -> Result<H3ServersBuilder, rustls::Error> {
self.client_cert_verifier = None;
self.try_into()
}
}
impl TryFrom<H3ServersTlsBuilder> for H3ServersBuilder {
type Error = rustls::Error;
fn try_from(builder: H3ServersTlsBuilder) -> Result<Self, Self::Error> {
let listeners_builder = match builder.crypto_provider {
Some(crypto_provider) => QuicListeners::builder_with_crypto_provider(crypto_provider),
None => Ok(QuicListeners::builder()),
}?;
let listeners_builder = match builder.client_cert_verifier {
Some(client_cert_verifier) => {
listeners_builder.with_client_cert_verifier(client_cert_verifier)
}
None => listeners_builder.without_client_cert_verifier(),
}
.with_alpns(vec!["h3"]);
Ok(H3ServersBuilder {
listeners_builder,
backlog: 1024,
pool: Pool::empty(),
builder: Arc::new(ConnectionBuilder::new(Arc::default())),
})
}
}
pub struct H3ServersBuilder {
listeners_builder: QuicListenersBuilder<rustls::ServerConfig>,
backlog: usize,
pool: Pool<Connection>,
builder: Arc<ConnectionBuilder<Connection>>,
}
impl H3ServersBuilder {
pub fn with_resolver(mut self, resolver: Arc<dyn Resolve + Send + Sync>) -> Self {
self.listeners_builder = self.listeners_builder.with_resolver(resolver);
self
}
pub fn with_iface_factory(mut self, factory: Arc<dyn ProductIO + 'static>) -> Self {
self.listeners_builder = self.listeners_builder.with_iface_factory(factory);
self
}
pub fn with_iface_manager(mut self, iface_manager: Arc<InterfaceManager>) -> Self {
self.listeners_builder = self.listeners_builder.with_iface_manager(iface_manager);
self
}
pub fn with_router(mut self, router: Arc<QuicRouter>) -> Self {
self.listeners_builder = self.listeners_builder.with_router(router);
self
}
pub fn with_token_provider(mut self, token_provider: Arc<dyn TokenProvider>) -> Self {
self.listeners_builder = self.listeners_builder.with_token_provider(token_provider);
self
}
pub fn with_streams_concurrency_strategy(
mut self,
strategy_factory: Arc<dyn ProductStreamsConcurrencyController>,
) -> Self {
self.listeners_builder = self
.listeners_builder
.with_streams_concurrency_strategy(strategy_factory);
self
}
pub fn defer_idle_timeout(mut self, duration: Duration) -> Self {
self.listeners_builder = self.listeners_builder.defer_idle_timeout(duration);
self
}
pub fn with_quic_parameters(mut self, parameters: ServerParameters) -> Self {
self.listeners_builder = self.listeners_builder.with_parameters(parameters);
self
}
pub fn physical_ifaces(mut self, physical_ifaces: &'static Devices) -> Self {
self.listeners_builder = self.listeners_builder.with_physical_ifaces(physical_ifaces);
self
}
pub fn with_qlog(mut self, logger: Arc<dyn QLog + Send + Sync>) -> Self {
self.listeners_builder = self.listeners_builder.with_qlog(logger);
self
}
pub fn enable_anti_port_scan(mut self) -> Self {
self.listeners_builder = self.listeners_builder.enable_anti_port_scan();
self
}
pub fn with_client_auther(mut self, client_auther: impl AuthClient + 'static) -> Self {
self.listeners_builder = self.listeners_builder.with_client_auther(client_auther);
self
}
pub fn enable_0rtt(mut self) -> Self {
self.listeners_builder = self.listeners_builder.enable_0rtt();
self
}
pub fn with_backlog(mut self, backlog: usize) -> Self {
self.backlog = backlog;
self
}
pub fn with_builder(mut self, builder: Arc<ConnectionBuilder<Connection>>) -> Self {
self.builder = builder;
self
}
pub fn listen<S>(self) -> Result<H3Servers<S>, ListenError> {
let listener = self.listeners_builder.listen(self.backlog)?;
Ok(Servers::from_quic_listener()
.listener(listener)
.pool(self.pool)
.service(ServersRouter::new())
.builder(self.builder)
.build())
}
}
impl<S> Servers<Arc<QuicListeners>, ServersRouter<S>>
where
S: tower_service::Service<UnresolvedRequest, Response = ()> + Clone + Send + Sync + 'static,
S::Future: Send,
S::Error: Into<Box<dyn Error + Send + Sync>>,
{
pub async fn add_server(
&mut self,
server_name: impl Into<String>,
cert_chain: impl handy::ToCertificate,
private_key: impl handy::ToPrivateKey,
ocsp: impl Into<Option<Vec<u8>>>,
bind_uris: impl IntoIterator<Item = impl Into<BindUri>>,
router: S,
) -> Result<&mut Self, ServerError> {
let server_name = server_name.into();
self.quic_listener()
.add_server(&server_name, cert_chain, private_key, bind_uris, ocsp)
.await?;
self.service_mut().serve(server_name, router);
Ok(self)
}
}