hickory_proto/h3/
h3_server.rs1use alloc::sync::Arc;
11use std::{io, net::SocketAddr};
12
13use bytes::Bytes;
14use h3::server::{Connection, RequestStream};
15use h3_quinn::{BidiStream, Endpoint};
16use http::Request;
17use quinn::crypto::rustls::QuicServerConfig;
18use quinn::{EndpointConfig, ServerConfig};
19use rustls::server::ResolvesServerCert;
20use rustls::server::ServerConfig as TlsServerConfig;
21use rustls::version::TLS13;
22
23use crate::{error::ProtoError, rustls::default_provider, udp::UdpSocket};
24
25use super::ALPN_H3;
26
27pub struct H3Server {
29 endpoint: Endpoint,
30}
31
32impl H3Server {
33 pub async fn new(
35 name_server: SocketAddr,
36 server_cert_resolver: Arc<dyn ResolvesServerCert>,
37 ) -> Result<Self, ProtoError> {
38 let socket = <tokio::net::UdpSocket as UdpSocket>::bind(name_server).await?;
40 Self::with_socket(socket, server_cert_resolver)
41 }
42
43 pub fn with_socket(
45 socket: tokio::net::UdpSocket,
46 server_cert_resolver: Arc<dyn ResolvesServerCert>,
47 ) -> Result<Self, ProtoError> {
48 let mut config = TlsServerConfig::builder_with_provider(Arc::new(default_provider()))
49 .with_protocol_versions(&[&TLS13])
50 .expect("TLS1.3 not supported")
51 .with_no_client_auth()
52 .with_cert_resolver(server_cert_resolver);
53
54 config.alpn_protocols = vec![ALPN_H3.to_vec()];
55
56 let mut server_config =
57 ServerConfig::with_crypto(Arc::new(QuicServerConfig::try_from(config).unwrap()));
58 server_config.transport = Arc::new(super::transport());
59
60 let socket = socket.into_std()?;
61
62 let endpoint = Endpoint::new(
63 EndpointConfig::default(),
64 Some(server_config),
65 socket,
66 Arc::new(quinn::TokioRuntime),
67 )?;
68
69 Ok(Self { endpoint })
70 }
71
72 pub async fn accept(&mut self) -> Result<Option<(H3Connection, SocketAddr)>, ProtoError> {
78 let connecting = match self.endpoint.accept().await {
79 Some(conn) => conn,
80 None => return Ok(None),
81 };
82
83 let remote_addr = connecting.remote_address();
84 let connection = connecting.await?;
85 Ok(Some((
86 H3Connection {
87 connection: Connection::new(h3_quinn::Connection::new(connection))
88 .await
89 .map_err(|e| ProtoError::from(format!("h3 connection failed: {e}")))?,
90 },
91 remote_addr,
92 )))
93 }
94
95 pub fn local_addr(&self) -> Result<SocketAddr, io::Error> {
100 self.endpoint.local_addr()
101 }
102}
103
104pub struct H3Connection {
106 connection: Connection<h3_quinn::Connection, Bytes>,
107}
108
109impl H3Connection {
110 pub async fn accept(
112 &mut self,
113 ) -> Option<Result<(Request<()>, RequestStream<BidiStream<Bytes>, Bytes>), ProtoError>> {
114 match self.connection.accept().await {
115 Ok(Some((request, stream))) => Some(Ok((request, stream))),
116 Ok(None) => None,
117 Err(e) => Some(Err(ProtoError::from(format!("h3 request failed: {e}")))),
118 }
119 }
120
121 pub async fn shutdown(&mut self) -> Result<(), ProtoError> {
123 self.connection
124 .shutdown(0)
125 .await
126 .map_err(|e| ProtoError::from(format!("h3 connection shutdown failed: {e}")))
127 }
128}