Skip to main content

spvirit_server/
beacon.rs

1//! PVA beacon sender.
2
3use std::net::{IpAddr, Ipv4Addr, SocketAddr};
4use std::sync::Arc;
5use std::sync::atomic::{AtomicU16, Ordering};
6use std::time::Duration;
7
8use spvirit_codec::spvirit_encode::{encode_beacon, ip_to_bytes};
9use tokio::net::UdpSocket;
10
11/// Configuration for the beacon sender.
12pub struct BeaconConfig {
13    pub target: SocketAddr,
14    pub guid: [u8; 12],
15    pub tcp_port: u16,
16    pub advertise_ip: Option<IpAddr>,
17    pub listen_ip: IpAddr,
18    pub period_secs: u64,
19}
20
21/// Run the beacon sender loop.  `change_counter` is polled atomically each tick.
22pub async fn run_beacon(
23    config: BeaconConfig,
24    change_counter: Arc<AtomicU16>,
25) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
26    if config.period_secs == 0 {
27        return Ok(());
28    }
29    let bind_addr = if config.target.is_ipv4() {
30        "0.0.0.0:0"
31    } else {
32        "[::]:0"
33    };
34    let socket = UdpSocket::bind(bind_addr).await?;
35    socket.set_broadcast(true)?;
36    let mut interval = tokio::time::interval(Duration::from_secs(config.period_secs));
37    let mut seq: u8 = 0;
38
39    loop {
40        interval.tick().await;
41        let resp_ip = if let Some(ip) = config.advertise_ip {
42            ip
43        } else if !config.listen_ip.is_unspecified() {
44            config.listen_ip
45        } else {
46            IpAddr::V4(Ipv4Addr::UNSPECIFIED)
47        };
48        let addr_bytes = if resp_ip.is_unspecified() {
49            [0u8; 16]
50        } else {
51            ip_to_bytes(resp_ip)
52        };
53        let change_count = change_counter.load(Ordering::SeqCst);
54        let msg = encode_beacon(
55            config.guid,
56            seq,
57            change_count,
58            addr_bytes,
59            config.tcp_port,
60            "tcp",
61            2,
62            false,
63        );
64        let _ = socket.send_to(&msg, config.target).await;
65        seq = seq.wrapping_add(1);
66    }
67}