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