Skip to main content

seydd/input/
udp.rs

1// Copyright 2026 Anton Gravestam
2// SPDX-License-Identifier: Apache-2.0
3//! UDP datagram source for sensor channels: one datagram = one message.
4
5use bytes::Bytes;
6use tokio::net::UdpSocket;
7use tokio::sync::mpsc;
8
9pub async fn run(addr: String, tx: mpsc::Sender<Bytes>) {
10    let sock = match UdpSocket::bind(&addr).await {
11        Ok(s) => s,
12        Err(e) => {
13            tracing::error!(%addr, error = %e, "sensor input: bind failed");
14            return;
15        }
16    };
17    tracing::info!(%addr, "sensor input listening");
18    let mut buf = vec![0u8; 65536];
19    while let Ok(n) = sock.recv(&mut buf).await {
20        if tx.send(Bytes::copy_from_slice(&buf[..n])).await.is_err() {
21            return;
22        }
23    }
24}
25
26/// Parse `udp://host:port` into a bindable/sendable address string.
27pub fn addr_from_url(url: &str) -> anyhow::Result<String> {
28    let u = url::Url::parse(url)?;
29    if u.scheme() != "udp" {
30        anyhow::bail!("expected udp:// url, got {url:?}");
31    }
32    Ok(format!(
33        "{}:{}",
34        u.host_str().unwrap_or("127.0.0.1"),
35        u.port()
36            .ok_or_else(|| anyhow::anyhow!("{url:?}: port required"))?
37    ))
38}