//! navka-server – echoes HID reports back to every client #![forbid(unsafe_code)] use anyhow::Result; use tokio::{sync::mpsc, task}; use tokio_stream::wrappers::ReceiverStream; use tonic::{Request, Response, Status, transport::Server}; use tonic::async_trait; use navka_common::navka::{ relay_server::{Relay, RelayServer}, HidReport, }; systemctl list services struct RelaySvc { // shared broadcast channel (unused for now, but kept for future fan-out) _hub_tx: mpsc::Sender, } #[async_trait] impl Relay for RelaySvc { type StreamStream = ReceiverStream>; async fn stream( &self, request: Request>, ) -> Result> + Send>>>, Status> { let mut inbound = request.into_inner(); // each connected client gets its own outbound channel let (tx, rx) = mpsc::channel::>(32); let outbound = ReceiverStream::new(rx); // task: read → echo task::spawn(async move { while let Some(report) = inbound.message().await? { // errors here just mean the client hung up – stop the loop if tx.send(Ok(report)).await.is_err() { break; } } Ok::<(), Status>(()) }); Ok(Response::new(outbound)) } } #[tokio::main] async fn main() -> Result<()> { // placeholder hub – you’ll reuse this when you forward to the OTG gadget let (hub_tx, _hub_rx) = mpsc::channel::(32); println!("🌀 navka-server listening on 0.0.0.0:50051"); Server::builder() .add_service(RelayServer::new(RelaySvc { _hub_tx: hub_tx })) .serve("0.0.0.0:50051".parse().unwrap()) .await?; Ok(()) }