1use std::{fs::File, io::BufReader, sync::Arc};
6use tokio_rustls::{
7 TlsAcceptor,
8 rustls::{
9 RootCertStore, ServerConfig,
10 pki_types::{CertificateDer, PrivateKeyDer},
11 server::WebPkiClientVerifier,
12 },
13};
14
15use crate::{WaeError, WaeResult};
16
17pub mod alpn {
19 pub const HTTP_1_1: &[u8] = b"http/1.1";
21 pub const HTTP_2: &[u8] = b"h2";
23}
24
25pub fn create_tls_acceptor(cert_path: &str, key_path: &str) -> WaeResult<TlsAcceptor> {
30 create_tls_acceptor_with_http2(cert_path, key_path, false)
31}
32
33pub fn create_tls_acceptor_with_http2(cert_path: &str, key_path: &str, enable_http2: bool) -> WaeResult<TlsAcceptor> {
43 let certs = load_certs(cert_path)?;
44 let key = load_private_key(key_path)?;
45
46 let alpn_protocols =
47 if enable_http2 { vec![alpn::HTTP_2.to_vec(), alpn::HTTP_1_1.to_vec()] } else { vec![alpn::HTTP_1_1.to_vec()] };
48
49 let config = ServerConfig::builder()
50 .with_no_client_auth()
51 .with_single_cert(certs, key)
52 .map_err(|e| WaeError::internal(format!("Failed to create TLS config: {}", e)))?;
53
54 let mut config = Arc::new(config);
55 Arc::get_mut(&mut config).expect("Config should be unique").alpn_protocols = alpn_protocols;
56
57 Ok(TlsAcceptor::from(config))
58}
59
60pub fn create_tls_acceptor_with_client_auth(
71 cert_path: &str,
72 key_path: &str,
73 ca_path: &str,
74 enable_http2: bool,
75) -> WaeResult<TlsAcceptor> {
76 let certs = load_certs(cert_path)?;
77 let key = load_private_key(key_path)?;
78 let ca_certs = load_certs(ca_path)?;
79
80 let mut root_cert_store = RootCertStore::empty();
81 for cert in ca_certs {
82 root_cert_store.add(cert).map_err(|e| WaeError::internal(format!("Failed to add CA cert: {}", e)))?;
83 }
84
85 let client_verifier = WebPkiClientVerifier::builder(Arc::new(root_cert_store))
86 .build()
87 .map_err(|e| WaeError::internal(format!("Failed to create client verifier: {}", e)))?;
88
89 let alpn_protocols =
90 if enable_http2 { vec![alpn::HTTP_2.to_vec(), alpn::HTTP_1_1.to_vec()] } else { vec![alpn::HTTP_1_1.to_vec()] };
91
92 let config = ServerConfig::builder()
93 .with_client_cert_verifier(client_verifier)
94 .with_single_cert(certs, key)
95 .map_err(|e| WaeError::internal(format!("Failed to create TLS config: {}", e)))?;
96
97 let mut config = Arc::new(config);
98 Arc::get_mut(&mut config).expect("Config should be unique").alpn_protocols = alpn_protocols;
99
100 Ok(TlsAcceptor::from(config))
101}
102
103fn load_certs(path: &str) -> WaeResult<Vec<CertificateDer<'static>>> {
105 let file = File::open(path).map_err(|e| WaeError::internal(format!("Failed to open cert file {}: {}", path, e)))?;
106 let mut reader = BufReader::new(file);
107
108 rustls_pemfile::certs(&mut reader)
109 .collect::<Result<Vec<_>, _>>()
110 .map_err(|e| WaeError::internal(format!("Failed to parse cert file {}: {}", path, e)))
111}
112
113fn load_private_key(path: &str) -> WaeResult<PrivateKeyDer<'static>> {
115 let file = File::open(path).map_err(|e| WaeError::internal(format!("Failed to open key file {}: {}", path, e)))?;
116 let mut reader = BufReader::new(file);
117
118 let keys: Vec<PrivateKeyDer<'static>> = rustls_pemfile::private_key(&mut reader)
119 .map_err(|e| WaeError::internal(format!("Failed to parse key file {}: {}", path, e)))?
120 .into_iter()
121 .collect();
122
123 keys.into_iter().next().ok_or_else(|| WaeError::internal(format!("No private key found in {}", path)))
124}
125
126pub struct TlsConfigBuilder {
128 cert_path: Option<String>,
129 key_path: Option<String>,
130 ca_path: Option<String>,
131 enable_http2: bool,
132}
133
134impl TlsConfigBuilder {
135 pub fn new() -> Self {
137 Self { cert_path: None, key_path: None, ca_path: None, enable_http2: true }
138 }
139
140 pub fn cert_path(mut self, path: impl Into<String>) -> Self {
142 self.cert_path = Some(path.into());
143 self
144 }
145
146 pub fn key_path(mut self, path: impl Into<String>) -> Self {
148 self.key_path = Some(path.into());
149 self
150 }
151
152 pub fn ca_path(mut self, path: impl Into<String>) -> Self {
154 self.ca_path = Some(path.into());
155 self
156 }
157
158 pub fn enable_http2(mut self, enable: bool) -> Self {
160 self.enable_http2 = enable;
161 self
162 }
163
164 pub fn build(self) -> WaeResult<TlsAcceptor> {
166 let cert_path = self.cert_path.ok_or_else(|| WaeError::internal("Certificate path is required"))?;
167 let key_path = self.key_path.ok_or_else(|| WaeError::internal("Key path is required"))?;
168
169 match self.ca_path {
170 Some(ca_path) => create_tls_acceptor_with_client_auth(&cert_path, &key_path, &ca_path, self.enable_http2),
171 None => create_tls_acceptor_with_http2(&cert_path, &key_path, self.enable_http2),
172 }
173 }
174}
175
176impl Default for TlsConfigBuilder {
177 fn default() -> Self {
178 Self::new()
179 }
180}