Skip to content

Commit 4046fdd

Browse files
committed
Migrate to tokio
1 parent 6adf0ce commit 4046fdd

29 files changed

+859
-763
lines changed

antares/Cargo.lock

Lines changed: 596 additions & 33 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

antares/Cargo.toml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
[package]
2-
name = "naval-radar-simulator"
3-
version = "0.1.0"
2+
name = "antares"
3+
version = "1.0.0"
44
edition = "2021"
55

66
[dependencies]
77
chrono = "0.4.38"
88
rand = "0.8.5"
9-
serde = { version = "1.0.214", features = ["derive"] }
9+
tokio = { version = "1", features = ["full"] }
10+
serde = { version = "1", features = ["derive"] }
1011
toml = "0.8.19"
12+
async-trait = "0.1.88"
13+
tokio-tungstenite = "0.26.2"
14+
futures-util = "0.3.31"
15+
futures = "0.3.31"

antares/src/controller.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//!
55
66
use super::{Config, Radar, Simulation};
7-
use std::sync::mpsc::channel;
7+
use tokio::sync::mpsc;
88

99
pub struct Controller {
1010
radar: Radar,
@@ -19,10 +19,15 @@ impl Controller {
1919
}
2020
}
2121

22-
pub fn run(self) {
23-
let (wave_sender, wave_receiver) = channel();
24-
self.simulation.start(wave_sender);
25-
self.radar.start(wave_receiver);
26-
loop {}
22+
pub async fn run(self) {
23+
let (wave_sender, wave_receiver) = mpsc::channel(100);
24+
let Controller { radar, simulation } = self;
25+
26+
tokio::spawn(simulation.start(wave_sender));
27+
tokio::spawn(radar.start(wave_receiver));
28+
29+
tokio::signal::ctrl_c()
30+
.await
31+
.expect("failed to listen for Ctrl+C");
2732
}
2833
}

antares/src/lib.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
1-
//! # Radar Simulation Library
1+
//! # ANTARES Radar Simulation Library
22
//!
3-
//! `radar-simulation` is a library for simulating radar data.
3+
//! `antares` is a library for simulating radar data.
44
//!
55
66
mod config;
77
mod controller;
88
mod radar;
99
mod simulation;
10-
mod utils;
1110

1211
use radar::{Radar, RadarConfig};
1312
use simulation::{Simulation, SimulationConfig, Wave};

antares/src/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
use naval_radar_simulator::{Config, Controller};
1+
use antares::{Config, Controller};
22
use std::{env, fs, process};
33

44
fn main() {
55
let args: Vec<String> = env::args().collect();
66

77
if args.len() != 2 {
8-
eprintln!("Usage: naval_radar <config-file>");
8+
eprintln!("Usage: antares <config-file>");
99
process::exit(1);
1010
}
1111

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
use super::super::Track;
2+
use async_trait::async_trait;
3+
use tokio::sync::broadcast::Sender;
4+
5+
/// A trait representing a broadcast interface that sends track data to clients.
6+
#[async_trait]
7+
pub trait Broadcaster: Send + Sync {
8+
async fn start(&self);
9+
fn sender(&self) -> Sender<Track>;
10+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
mod broadcaster;
2+
mod tcp;
3+
mod websocket;
4+
5+
pub use broadcaster::Broadcaster;
6+
pub use tcp::TcpBroadcaster;
7+
pub use websocket::WebSocketBroadcaster;
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
use super::super::Track;
2+
use super::Broadcaster;
3+
use async_trait::async_trait;
4+
use tokio::io::AsyncWriteExt;
5+
use tokio::net::{TcpListener, TcpStream};
6+
use tokio::sync::broadcast::{self, Sender};
7+
8+
pub struct TcpBroadcaster {
9+
bind_addr: String,
10+
sender: Sender<Track>,
11+
}
12+
13+
impl TcpBroadcaster {
14+
pub fn new(bind_addr: String) -> Self {
15+
let (sender, _) = broadcast::channel(100);
16+
Self { bind_addr, sender }
17+
}
18+
19+
async fn handle_client(
20+
mut stream: TcpStream,
21+
mut receiver: tokio::sync::broadcast::Receiver<Track>,
22+
) {
23+
while let Ok(track) = receiver.recv().await {
24+
let csv_line = format!("{}\n", track.serialize());
25+
if let Err(e) = stream.write_all(csv_line.as_bytes()).await {
26+
eprintln!("Failed to send data to TCP client: {}", e);
27+
break;
28+
}
29+
}
30+
}
31+
}
32+
33+
#[async_trait]
34+
impl Broadcaster for TcpBroadcaster {
35+
async fn start(&self) {
36+
let listener = TcpListener::bind(&self.bind_addr).await.unwrap();
37+
let sender = self.sender.clone();
38+
39+
println!("📡 TCP broadcaster listening on {}", self.bind_addr);
40+
41+
loop {
42+
let (stream, _) = listener.accept().await.unwrap();
43+
let receiver = sender.subscribe();
44+
tokio::spawn(Self::handle_client(stream, receiver));
45+
}
46+
}
47+
48+
fn sender(&self) -> Sender<Track> {
49+
self.sender.clone()
50+
}
51+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
use super::super::Track;
2+
use super::Broadcaster;
3+
use async_trait::async_trait;
4+
use futures_util::{SinkExt, StreamExt};
5+
use tokio::net::TcpListener;
6+
use tokio::sync::broadcast::{self, Sender};
7+
use tokio_tungstenite::accept_async;
8+
use tokio_tungstenite::tungstenite::Message;
9+
10+
pub struct WebSocketBroadcaster {
11+
bind_addr: String,
12+
sender: Sender<Track>,
13+
}
14+
15+
impl WebSocketBroadcaster {
16+
pub fn new(bind_addr: String) -> Self {
17+
let (sender, _) = broadcast::channel(100);
18+
Self { bind_addr, sender }
19+
}
20+
21+
async fn handle_client(
22+
stream: tokio::net::TcpStream,
23+
mut receiver: tokio::sync::broadcast::Receiver<Track>,
24+
) {
25+
if let Ok(ws_stream) = accept_async(stream).await {
26+
let (mut sink, _) = ws_stream.split();
27+
while let Ok(track) = receiver.recv().await {
28+
let csv = format!("{}\n", track.serialize());
29+
let _ = sink.send(Message::Text(csv.into())).await;
30+
}
31+
}
32+
}
33+
}
34+
35+
#[async_trait]
36+
impl Broadcaster for WebSocketBroadcaster {
37+
async fn start(&self) {
38+
let listener = TcpListener::bind(&self.bind_addr).await.unwrap();
39+
let sender = self.sender.clone();
40+
41+
println!("📡 WebSocket broadcaster listening on {}", self.bind_addr);
42+
43+
loop {
44+
let (stream, _) = listener.accept().await.unwrap();
45+
let receiver = sender.subscribe();
46+
tokio::spawn(Self::handle_client(stream, receiver));
47+
}
48+
}
49+
50+
fn sender(&self) -> Sender<Track> {
51+
self.sender.clone()
52+
}
53+
}

antares/src/radar/config.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,7 @@ use serde::Deserialize;
33
#[derive(Debug, Deserialize)]
44
pub struct RadarConfig {
55
pub detector: DetectorConfig,
6-
pub protocol: ProtocolConfig,
7-
}
8-
9-
#[derive(Debug, Deserialize)]
10-
pub struct ProtocolConfig {
11-
pub host: String,
12-
pub num_workers_tci: usize,
13-
pub num_workers_tdi: usize,
6+
pub broadcast: BroadcastConfig,
147
}
158

169
#[derive(Debug, Deserialize, Clone)]
@@ -20,3 +13,10 @@ pub struct DetectorConfig {
2013
pub angle: f64,
2114
pub start_coordinates: (f64, f64),
2215
}
16+
17+
#[derive(Debug, Deserialize)]
18+
#[serde(tag = "type", rename_all = "lowercase")]
19+
pub enum BroadcastConfig {
20+
Tcp { bind_addr: String },
21+
WebSocket { bind_addr: String },
22+
}

0 commit comments

Comments
 (0)