use pingora_core::listeners::tls::TlsSettings;
use praxis_core::ProxyError;
use praxis_tls::ListenerTls;
use tokio::sync::watch;
#[expect(clippy::too_many_lines, reason = "hot-reload vs static TLS branching")]
pub(crate) fn build_tls_settings(
tls: &ListenerTls,
address: &str,
context_label: &str,
) -> Result<(TlsSettings, Option<watch::Sender<bool>>), ProxyError> {
macro_rules! tls_err {
($e:expr) => {{
let err = $e;
ProxyError::Config(format!("TLS for {address}: {err}"))
}};
}
if tls.is_hot_reload() {
tracing::debug!(address, context_label, "building TLS ServerConfig with hot-reload");
let result = praxis_tls::setup::build_reloadable_server_config(tls)
.map_err(|e| ProxyError::Config(format!("TLS hot-reload for {address}: {e}")))?;
let pair =
tls.certificates.first().cloned().ok_or_else(|| {
ProxyError::Config(format!("TLS hot-reload for {address}: no certificate configured"))
})?;
let verifier_reload = result.verifier_handle.and_then(|handle| {
tls.client_ca
.as_ref()
.map(|ca_cfg| praxis_tls::watcher::ClientVerifierReload {
ca_path: ca_cfg.ca_path.clone(),
crl_paths: ca_cfg.crl_paths.clone(),
mode: tls.client_cert_mode,
swap_handle: handle,
})
});
let (shutdown_tx, shutdown_rx) = watch::channel(false);
praxis_tls::watcher::CertWatcher::spawn(result.cert_handle, pair, verifier_reload, shutdown_rx);
let settings = TlsSettings::with_server_config(result.config).map_err(|e| tls_err!(e))?;
return Ok((settings, Some(shutdown_tx)));
}
tracing::debug!(address, context_label, "building TLS ServerConfig");
let server_config = praxis_tls::setup::build_server_config(tls).map_err(|e| tls_err!(e))?;
let settings = TlsSettings::with_server_config(server_config).map_err(|e| tls_err!(e))?;
Ok((settings, None))
}