Skip to main content

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}