1use std::net::SocketAddr;
4use std::sync::Arc;
5
6use rustls::pki_types::{CertificateDer, PrivateKeyDer};
7
8use crate::error::ProxyError;
9
10pub struct ListenerConfig {
12 pub bind_addr: SocketAddr,
14 pub cert_chain: Vec<CertificateDer<'static>>,
16 pub key_der: PrivateKeyDer<'static>,
18 pub alpn: Vec<Vec<u8>>,
20}
21
22pub struct Listener {
25 endpoint: quinn::Endpoint,
26}
27
28impl Listener {
29 pub fn bind(config: ListenerConfig) -> Result<Self, ProxyError> {
31 let mut server_tls = rustls::ServerConfig::builder()
32 .with_no_client_auth()
33 .with_single_cert(config.cert_chain, config.key_der)
34 .map_err(|e| ProxyError::TlsConfig(format!("server cert config: {e}")))?;
35
36 server_tls.alpn_protocols = config.alpn;
37 server_tls.max_early_data_size = u32::MAX;
38
39 let quic_server_config: quinn::crypto::rustls::QuicServerConfig =
40 server_tls.try_into().map_err(|e| ProxyError::TlsConfig(format!("{e}")))?;
41
42 let server_config = quinn::ServerConfig::with_crypto(Arc::new(quic_server_config));
43
44 let endpoint = quinn::Endpoint::server(server_config, config.bind_addr)
45 .map_err(|e| ProxyError::Listener(e.to_string()))?;
46
47 Ok(Self { endpoint })
48 }
49
50 pub async fn accept(&self) -> Result<(quinn::Connection, Vec<u8>), ProxyError> {
54 let incoming = self
55 .endpoint
56 .accept()
57 .await
58 .ok_or_else(|| ProxyError::Listener("endpoint closed".to_string()))?;
59
60 let conn = incoming.await.map_err(|e| ProxyError::Listener(e.to_string()))?;
61
62 let alpn = conn
63 .handshake_data()
64 .and_then(|hd| hd.downcast::<quinn::crypto::rustls::HandshakeData>().ok())
65 .and_then(|hd| hd.protocol)
66 .map(|p| p.to_vec())
67 .unwrap_or_default();
68
69 Ok((conn, alpn))
70 }
71
72 pub fn local_addr(&self) -> Result<SocketAddr, ProxyError> {
74 self.endpoint.local_addr().map_err(|e| ProxyError::Listener(e.to_string()))
75 }
76
77 pub fn close(&self) {
79 self.endpoint.close(0u32.into(), b"proxy shutting down");
80 }
81}
82
83#[cfg(feature = "webtransport")]
87pub struct WtListenerConfig {
88 pub bind_addr: SocketAddr,
90 pub cert_chain: Vec<CertificateDer<'static>>,
92 pub key_der: PrivateKeyDer<'static>,
94}
95
96#[cfg(feature = "webtransport")]
98pub struct WtListener {
99 endpoint: wtransport::Endpoint<wtransport::endpoint::endpoint_side::Server>,
100}
101
102#[cfg(feature = "webtransport")]
103impl WtListener {
104 pub fn bind(config: WtListenerConfig) -> Result<Self, ProxyError> {
106 let mut server_tls = rustls::ServerConfig::builder()
107 .with_no_client_auth()
108 .with_single_cert(config.cert_chain, config.key_der)
109 .map_err(|e| ProxyError::TlsConfig(format!("server cert config: {e}")))?;
110
111 server_tls.alpn_protocols = vec![b"h3".to_vec()];
113
114 let wt_config = wtransport::ServerConfig::builder()
115 .with_bind_address(config.bind_addr)
116 .with_custom_tls(server_tls)
117 .build();
118
119 let endpoint = wtransport::Endpoint::server(wt_config)
120 .map_err(|e| ProxyError::Listener(e.to_string()))?;
121
122 Ok(Self { endpoint })
123 }
124
125 pub async fn accept(&self) -> Result<wtransport::Connection, ProxyError> {
127 let incoming = self.endpoint.accept().await;
128 let session_request = incoming.await.map_err(|e| ProxyError::Listener(e.to_string()))?;
129 let conn =
130 session_request.accept().await.map_err(|e| ProxyError::Listener(e.to_string()))?;
131 Ok(conn)
132 }
133
134 pub fn local_addr(&self) -> Result<SocketAddr, ProxyError> {
136 self.endpoint.local_addr().map_err(|e| ProxyError::Listener(e.to_string()))
137 }
138
139 pub fn close(&self) {
141 self.endpoint.close(wtransport::VarInt::from_u32(0), b"proxy shutting down");
142 }
143}