- let config = match ServerConfig::builder()
- .with_client_cert_verifier(Arc::new(GeminiClientVerifier))
- .with_single_cert(cert_chain, private_key)
- {
- Ok(config) => config,
- Err(_) => {
- return Err(self.machine_st.open_permission_error(
- self.machine_st.registers[1],
- atom!("tls_server_negotiate"),
- 3,
- ));
+ let cached_config = CONFIG_CACHE.with(|cache| {
+ cache.borrow().as_ref().and_then(|(cert, key, config)| {
+ (cert == &cert_pem && key == &key_pem).then(|| config.clone())
+ })
+ });
+
+ let config = match cached_config {
+ Some(config) => config,
+ None => {
+ let cert_chain: Vec<CertificateDer<'static>> =
+ match rustls_pemfile::certs(&mut &cert_pem[..]).collect::<Result<Vec<_>, _>>() {
+ Ok(certs) if !certs.is_empty() => certs,
+ _ => {
+ return Err(self.machine_st.open_permission_error(
+ self.machine_st.registers[1],
+ atom!("tls_server_negotiate"),
+ 3,
+ ));
+ }
+ };
+
+ let private_key: PrivateKeyDer<'static> =
+ match rustls_pemfile::private_key(&mut &key_pem[..]) {
+ Ok(Some(key)) => key,
+ _ => {
+ return Err(self.machine_st.open_permission_error(
+ self.machine_st.registers[2],
+ atom!("tls_server_negotiate"),
+ 3,
+ ));
+ }
+ };
+
+ let config = match ServerConfig::builder()
+ .with_client_cert_verifier(Arc::new(GeminiClientVerifier))
+ .with_single_cert(cert_chain, private_key)
+ {
+ Ok(config) => Arc::new(config),
+ Err(_) => {
+ return Err(self.machine_st.open_permission_error(
+ self.machine_st.registers[1],
+ atom!("tls_server_negotiate"),
+ 3,
+ ));
+ }
+ };
+
+ CONFIG_CACHE.with(|cache| {
+ *cache.borrow_mut() =
+ Some((cert_pem.clone(), key_pem.clone(), config.clone()));
+ });
+
+ config