use std::net::IpAddr;
use std::process::ExitCode;
use std::time::Duration;
use clap::Parser;
use epics_bridge_rs::pva_gateway::{PvaGateway, PvaGatewayConfig};
use epics_pva_rs::server_native::PvaServerConfig;
#[derive(Parser, Debug)]
#[command(
name = "pva-gateway-rs",
about = "Pure Rust PVA-to-PVA gateway (mirrors pva2pva)",
version
)]
struct Args {
#[arg(long, default_value = "0.0.0.0")]
bind: IpAddr,
#[arg(long, default_value_t = 5075)]
tcp_port: u16,
#[arg(long, default_value_t = 5076)]
udp_port: u16,
#[arg(long, default_value_t = 5)]
connect_timeout_secs: u64,
#[arg(long, default_value_t = 30)]
cleanup_interval_secs: u64,
#[arg(long = "prefetch", num_args = 1.., value_delimiter = ',')]
prefetch: Vec<String>,
#[arg(short, long, action = clap::ArgAction::Count)]
verbose: u8,
}
fn init_tracing(verbose: u8) {
let level = match verbose {
0 => "warn",
1 => "info",
2 => "debug",
_ => "trace",
};
let filter = std::env::var("RUST_LOG").unwrap_or_else(|_| level.to_string());
let _ = tracing_subscriber::fmt()
.with_env_filter(tracing_subscriber::EnvFilter::new(filter))
.try_init();
}
#[tokio::main]
async fn main() -> ExitCode {
let args = Args::parse();
init_tracing(args.verbose);
let server_config = PvaServerConfig {
tcp_port: args.tcp_port,
udp_port: args.udp_port,
bind_ip: args.bind,
..PvaServerConfig::default()
};
let cfg = PvaGatewayConfig {
upstream_client: None,
server_config,
cleanup_interval: Duration::from_secs(args.cleanup_interval_secs),
connect_timeout: Duration::from_secs(args.connect_timeout_secs),
..PvaGatewayConfig::default()
};
let gateway = match PvaGateway::start(cfg) {
Ok(g) => g,
Err(e) => {
eprintln!("pva-gateway-rs: failed to start: {e}");
return ExitCode::FAILURE;
}
};
if !args.prefetch.is_empty() {
let names: Vec<&str> = args.prefetch.iter().map(String::as_str).collect();
tracing::info!(count = names.len(), "pre-warming gateway cache");
gateway.prefetch(&names).await;
}
let report = gateway.report();
eprintln!(
"pva-gateway-rs listening tcp/{} udp/{} (Ctrl-C to stop)",
report.tcp_port, report.udp_port
);
match gateway.run().await {
Ok(()) => ExitCode::SUCCESS,
Err(e) => {
eprintln!("pva-gateway-rs: stopped with error: {e}");
ExitCode::FAILURE
}
}
}