moq_uring/quic/server.rs
1//! Accepting: everything one incoming connection needs.
2
3use super::{Connection, Error, Identity};
4use crate::udp;
5
6/// Whether connecting clients are asked for a certificate, and against what.
7///
8/// Asking for a certificate and validating one that arrives still admits a
9/// client that presents none; only [`Required`](Self::Required) turns a
10/// missing certificate into a failed handshake.
11#[derive(Clone, Debug, Default)]
12#[non_exhaustive]
13pub enum ClientAuth {
14 /// Don't ask for a client certificate.
15 #[default]
16 None,
17 /// Ask, and verify against these roots if one is presented. A client that
18 /// presents none is still accepted.
19 Optional(Vec<std::path::PathBuf>),
20 /// Require every client to present a certificate chaining to these roots.
21 Required(Vec<std::path::PathBuf>),
22}
23
24impl ClientAuth {
25 /// The roots a presented certificate is checked against, and whether one
26 /// is mandatory.
27 pub(crate) fn roots(&self) -> Option<(&[std::path::PathBuf], bool)> {
28 match self {
29 Self::None => None,
30 Self::Optional(roots) => Some((roots, false)),
31 Self::Required(roots) => Some((roots, true)),
32 }
33 }
34}
35
36/// What to present, what to speak, and who may connect.
37#[derive(Clone, Debug)]
38#[non_exhaustive]
39pub struct Config {
40 /// The certificate chain and key this server presents. Not optional: a
41 /// QUIC server without an identity cannot complete a handshake.
42 pub identity: Identity,
43 /// ALPN protocols to accept, in preference order. Required: QUIC without
44 /// an application protocol is refused.
45 pub alpn: Vec<String>,
46 /// Whether to ask connecting clients for a certificate.
47 pub client_auth: ClientAuth,
48 /// The per-connection transport settings (timeouts, stream limits,
49 /// congestion control).
50 pub transport: super::Transport,
51}
52
53impl Config {
54 /// Serve `identity`, speaking no ALPN and asking no client for a
55 /// certificate until told otherwise.
56 pub fn new(identity: Identity) -> Self {
57 Self {
58 identity,
59 alpn: Vec::new(),
60 client_auth: ClientAuth::default(),
61 transport: super::Transport::default(),
62 }
63 }
64
65 /// Refuse a configuration no client could satisfy.
66 ///
67 /// An empty store rejects every chain, so asking for a certificate with
68 /// nothing to check it against refuses exactly the clients that obey.
69 pub(crate) fn check(&self) -> Result<(), Error> {
70 if self.client_auth.roots().is_some_and(|(roots, _)| roots.is_empty()) {
71 return Err(Error::Tls(
72 "client authentication needs at least one root certificate".to_string(),
73 ));
74 }
75 Ok(())
76 }
77}
78
79/// Accept the next connection arriving on `socket`, driving the handshake to
80/// completion.
81///
82/// Shorthand for an [`Endpoint`](super::Endpoint) serving this configuration
83/// and one [`accept`](super::Endpoint::accept) from it: later arrivals on the
84/// socket keep reaching the accepted connection, but nothing else is ever
85/// accepted. Keep the endpoint itself for a listener.
86pub async fn accept(socket: udp::Socket, config: &Config) -> Result<Connection, Error> {
87 let endpoint = super::Endpoint::new(socket, super::endpoint::Config::default().with_server(config.clone()))?;
88 endpoint.accept().await
89}