nvpn 4.0.96

CLI and daemon for Nostr VPN private mesh networks
Documentation
use super::*;

pub(crate) fn args_from_daemon(args: &DaemonArgs) -> Result<Option<WebvmGuestArgs>> {
    let Some(ethernet_interface) = args.webvm_ethernet_interface.as_ref() else {
        if args.webvm_discovery_scope.is_some() {
            return Err(anyhow!(
                "--webvm-discovery-scope requires --webvm-ethernet-interface"
            ));
        }
        return Ok(None);
    };
    let discovery_scope = args
        .webvm_discovery_scope
        .as_ref()
        .ok_or_else(|| anyhow!("--webvm-ethernet-interface requires --webvm-discovery-scope"))?;
    Ok(Some(WebvmGuestArgs {
        config: args.config.clone().unwrap_or_else(default_config_path),
        ethernet_interface: ethernet_interface.clone(),
        discovery_scope: discovery_scope.clone(),
        host_hint_port: FIPS_NOSTR_PUBSUB_SERVICE_PORT,
        pairing_uri_file: PathBuf::from(DEFAULT_WEBVM_PAIRING_URI_PATH),
        tun_interface: args.iface.clone(),
    }))
}

pub(crate) async fn run_daemon(args: WebvmGuestArgs, service: bool) -> Result<()> {
    validate_args(&args)?;

    #[cfg(not(target_os = "linux"))]
    {
        let _ = (args, service);
        Err(anyhow!("webvm-guest is supported only on Linux"))
    }

    #[cfg(target_os = "linux")]
    run_daemon_linux(args, service).await
}

#[cfg(target_os = "linux")]
async fn run_daemon_linux(args: WebvmGuestArgs, service: bool) -> Result<()> {
    if service && let Err(error) = redirect_stdio_to_daemon_log(&args.config) {
        eprintln!("daemon: failed to redirect WebVM service log: {error}");
    }
    if let Err(error) = compact_daemon_log_if_needed(&args.config) {
        eprintln!("daemon: failed to compact WebVM service log: {error}");
    }
    ensure_no_other_daemon_processes_for_config(&args.config, std::process::id())?;
    let pid_file = daemon_pid_file_path(&args.config);
    write_daemon_pid_record(
        &pid_file,
        &DaemonPidRecord {
            pid: std::process::id(),
            config_path: args.config.display().to_string(),
            started_at: unix_timestamp(),
        },
    )?;
    let _ = fs::remove_file(daemon_control_file_path(&args.config));
    clear_daemon_control_result(&args.config);

    let result = run_linux(args).await;
    if read_daemon_pid_record(&pid_file)
        .ok()
        .flatten()
        .is_some_and(|record| record.pid == std::process::id())
    {
        let _ = fs::remove_file(&pid_file);
    }
    match result {
        Err(error) if error.downcast_ref::<WebvmStop>().is_some() => Ok(()),
        other => other,
    }
}