#[cfg(feature = "lazycert")]
pub mod client;
#[cfg(feature = "lazycert")]
pub mod config;
#[cfg(feature = "lazycert")]
pub mod registry;
#[cfg(feature = "lazycert")]
pub mod sync;
#[cfg(feature = "lazycert")]
use client::LazyCertClient;
#[cfg(feature = "lazycert")]
use config::LazyCertConfig;
#[cfg(feature = "lazycert")]
use fancy_log::{LogLevel, log};
#[cfg(feature = "lazycert")]
use once_cell::sync::OnceCell;
#[cfg(feature = "lazycert")]
use std::sync::Arc;
#[cfg(feature = "lazycert")]
use tokio::sync::RwLock;
#[cfg(feature = "lazycert")]
pub static LAZYCERT_CONFIG: OnceCell<Arc<RwLock<Option<LazyCertConfig>>>> = OnceCell::new();
#[cfg(feature = "lazycert")]
pub static LAZYCERT_CLIENT: OnceCell<Arc<RwLock<Option<Arc<LazyCertClient>>>>> = OnceCell::new();
pub async fn initialize() {
#[cfg(feature = "lazycert")]
{
let _ = LAZYCERT_CONFIG.set(Arc::new(RwLock::new(None)));
let _ = LAZYCERT_CLIENT.set(Arc::new(RwLock::new(None)));
update_from_config().await;
tokio::spawn(async {
let config_manager = crate::config::get();
if let Some(lc) = &config_manager.lazycert {
let mut rx = lc.subscribe();
while let Ok(_event) = rx.recv().await {
update_from_config().await;
}
}
});
}
}
pub async fn update_from_config() {
#[cfg(feature = "lazycert")]
{
let config_manager = crate::config::get();
let new_config = config_manager
.lazycert
.as_ref()
.and_then(|lc| lc.get())
.map(|arc| (*arc).clone());
if let Some(config_lock) = LAZYCERT_CONFIG.get() {
let mut config = config_lock.write().await;
*config = new_config.clone();
}
if let Some(cfg) = new_config {
if !cfg.enabled {
log(LogLevel::Info, "LazyCert integration disabled in config");
stop_sync().await;
return;
}
let client = Arc::new(LazyCertClient::new(&cfg.url, cfg.token.clone()));
match client.health().await {
Ok(true) => {
log(
LogLevel::Info,
&format!("Connected to LazyCert at {}", cfg.url),
);
}
_ => {
log(
LogLevel::Warn,
&format!("Cannot reach LazyCert at {}, will retry", cfg.url),
);
}
}
if let Some(client_lock) = LAZYCERT_CLIENT.get() {
let mut c = client_lock.write().await;
*c = Some(client.clone());
}
sync::spawn_sync_task(client, std::time::Duration::from_secs(cfg.poll_interval));
log(
LogLevel::Info,
&format!(
"LazyCert sync started (poll interval: {}s)",
cfg.poll_interval
),
);
} else {
stop_sync().await;
}
}
}
#[cfg(feature = "lazycert")]
async fn stop_sync() {
if let Some(client_lock) = LAZYCERT_CLIENT.get() {
let mut c = client_lock.write().await;
*c = None;
}
}
#[cfg(feature = "lazycert")]
pub async fn get_public_ip() -> Option<String> {
if let Some(config_lock) = LAZYCERT_CONFIG.get() {
let config = config_lock.read().await;
if let Some(cfg) = config.as_ref() {
if cfg.public_ip == "auto" {
return detect_public_ip().await;
}
return Some(cfg.public_ip.clone());
}
}
None
}
#[cfg(feature = "lazycert")]
async fn detect_public_ip() -> Option<String> {
let client = reqwest::Client::new();
if let Ok(resp) = client.get("https://api.ipify.org").send().await
&& let Ok(ip) = resp.text().await
{
return Some(ip.trim().to_owned());
}
None
}