refactor: split network config into game_host and listen_addr

Replace RUSTY_TELEMETRY_BIND with two env vars:
- RUSTY_TELEMETRY_GAME_HOST: IP of the machine running the sim (for
  KSUDP handshake target). Default: 127.0.0.1
- RUSTY_TELEMETRY_LISTEN: local address to bind for incoming feeds
  (Telemetry Tool, PCARS). Default: 0.0.0.0 (accept from any interface)

Both fall back to RUSTY_TELEMETRY_BIND for backward compatibility.
This enables running rusty-telemetry on a separate machine from the game.
This commit is contained in:
Jan-Peter von Hunnius 2026-06-04 10:28:52 +02:00
parent a50d3af290
commit 6732ff0199

View file

@ -45,8 +45,23 @@ fn decode_utf16le(bytes: &[u8]) -> String {
String::from_utf16_lossy(&chars)
}
fn bind_addr() -> String {
std::env::var("RUSTY_TELEMETRY_BIND").unwrap_or_else(|_| "127.0.0.1".to_string())
/// IP address of the machine running the sim game.
/// Used as the KSUDP handshake target (AC binds :9996 on this host).
/// Default: 127.0.0.1 (local — game and listener on same machine).
/// Set to e.g. 192.168.1.2 when the game runs on a different machine.
fn game_host() -> String {
std::env::var("RUSTY_TELEMETRY_GAME_HOST")
.or_else(|_| std::env::var("RUSTY_TELEMETRY_BIND"))
.unwrap_or_else(|_| "127.0.0.1".to_string())
}
/// Local address to bind for incoming UDP feeds (Telemetry Tool, PCARS).
/// Default: 0.0.0.0 (accept from any interface — works for both local and remote).
/// Set to 127.0.0.1 to only accept local packets.
fn listen_addr() -> String {
std::env::var("RUSTY_TELEMETRY_LISTEN")
.or_else(|_| std::env::var("RUSTY_TELEMETRY_BIND"))
.unwrap_or_else(|_| "0.0.0.0".to_string())
}
#[derive(Clone)]
@ -113,15 +128,15 @@ async fn run_feed(
shutdown: Arc<tokio::sync::Notify>,
) {
let handshake_target: Option<std::net::SocketAddr> = if feed.needs_handshake {
let target: std::net::SocketAddr = match format!("{}:{}", bind_addr(), feed.port).parse() {
let target: std::net::SocketAddr = match format!("{}:{}", game_host(), feed.port).parse() {
Ok(addr) => addr,
Err(e) => {
eprintln!(
"[ERROR] {} :{} Invalid target address '{}': {}",
feed.label, feed.port, bind_addr(), e
"[ERROR] {} :{} Invalid game host address '{}': {}",
feed.label, feed.port, game_host(), e
);
if let Ok(mut s) = state.lock() {
s.set_error(&format!("Invalid target address: {}", e));
s.set_error(&format!("Invalid game host address: {}", e));
}
return;
}
@ -357,7 +372,7 @@ async fn run_feed(
async fn main() {
install_panic_hook();
let bind = bind_addr();
let listen = listen_addr();
let session_id = chrono::Local::now().format("%Y%m%d_%H%M%S").to_string();
let session_dir = format!("./data/{}", session_id);
@ -382,7 +397,7 @@ async fn main() {
let state = Arc::new(std::sync::Mutex::new(FeedState::new()));
let (socket_opt, mode) = if feed.needs_handshake {
let recv_addr = format!("{}:0", bind);
let recv_addr = format!("{}:0", listen);
match tokio::net::UdpSocket::bind(&recv_addr).await {
Ok(s) => {
let local_port = s.local_addr().map(|a| a.port()).unwrap_or(0);
@ -406,7 +421,7 @@ async fn main() {
}
}
} else {
let addr = format!("{}:{}", bind, feed.port);
let addr = format!("{}:{}", listen, feed.port);
match tokio::net::UdpSocket::bind(&addr).await {
Ok(s) => (Some(s), FeedMode::BindListen),
Err(e) => {