added cli options

This commit is contained in:
Parker TenBroeck 2026-03-11 13:23:28 -04:00
parent defbd88adf
commit 00dcf6d3f8
4 changed files with 119 additions and 11 deletions

21
relay.nix Normal file
View file

@ -0,0 +1,21 @@
{ pkgs ? import <nixpkgs> {} }:
pkgs.rustPlatform.buildRustPackage {
pname = "relay";
version = "0.1.0";
src = ./.;
cargoLock = {
lockFile = ./Cargo.lock;
};
cargoBuildFlags = [ "-p" "relay" ];
nativeBuildInputs = [ pkgs.makeWrapper ];
buildInputs = [ pkgs.ghdl-llvm ];
postFixup = ''
wrapProgram $out/bin/relay \
--prefix PATH : ${pkgs.lib.makeBinPath [ pkgs.ghdl-llvm ]}
'';
}

View file

@ -37,7 +37,7 @@ struct Handler {
impl Handler { impl Handler {
fn local(socket: WebSocket, build: PathBuf, src: PathBuf) -> Self { fn local(socket: WebSocket, build: PathBuf, src: PathBuf, refresh_time: Duration) -> Self {
let (sender, receiver) = socket.split(); let (sender, receiver) = socket.split();
Self { Self {
sender, sender,
@ -45,7 +45,7 @@ impl Handler {
build_dir: build, build_dir: build,
src_dir: src, src_dir: src,
process: None, process: None,
refresh_time: Duration::from_millis(30), refresh_time,
} }
} }
@ -207,6 +207,6 @@ impl Handler {
} }
} }
pub async fn ws_handler(socket: WebSocket) { pub async fn ws_handler(socket: WebSocket, refresh_time: Duration) {
Handler::local(socket, "../target".into(), "../src".into()).run().await; Handler::local(socket, "../target".into(), "../src".into(), refresh_time).run().await;
} }

View file

@ -6,7 +6,10 @@ use axum::{
routing::get, routing::get,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::net::SocketAddr; use std::{
net::{IpAddr, SocketAddr},
time::Duration,
};
pub mod build; pub mod build;
pub mod run; pub mod run;
@ -39,8 +42,73 @@ async fn not_found() -> impl IntoResponse {
(StatusCode::NOT_FOUND, "not found") (StatusCode::NOT_FOUND, "not found")
} }
#[derive(Clone, Copy, Debug)]
struct Config {
ip: IpAddr,
port: u16,
update_ms: u64,
}
impl Default for Config {
fn default() -> Self {
Self {
ip: IpAddr::from([127, 0, 0, 1]),
port: 8080,
update_ms: 30,
}
}
}
fn parse_config_from_args() -> Result<Config, String> {
let mut cfg = Config::default();
let mut args = std::env::args().skip(1);
while let Some(arg) = args.next() {
match arg.as_str() {
"--" => break,
"--ip" => {
let value = args.next().ok_or("missing value for --ip")?;
cfg.ip = value
.parse::<IpAddr>()
.map_err(|err| format!("invalid --ip `{value}`: {err}"))?;
}
"--port" => {
let value = args.next().ok_or("missing value for --port")?;
cfg.port = value
.parse::<u16>()
.map_err(|err| format!("invalid --port `{value}`: {err}"))?;
}
"--update-ms" => {
let value = args.next().ok_or("missing value for --update-ms")?;
cfg.update_ms = value
.parse::<u64>()
.map_err(|err| format!("invalid --update-ms `{value}`: {err}"))?;
}
"--help" | "-h" => {
return Err("usage: relay [--ip <ip>] [--port <port>] [--update-ms <ms>]".into());
}
_ => {
return Err(format!(
"unknown argument `{arg}`\nusage: relay [--ip <ip>] [--port <port>] [--update-ms <ms>]"
));
}
}
}
Ok(cfg)
}
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
let cfg = match parse_config_from_args() {
Ok(cfg) => cfg,
Err(msg) => {
eprintln!("{msg}");
std::process::exit(2);
}
};
let update_interval = Duration::from_millis(cfg.update_ms);
let app = Router::new() let app = Router::new()
.route("/", get(serve_index)) .route("/", get(serve_index))
.route("/index.html", get(serve_index)) .route("/index.html", get(serve_index))
@ -48,15 +116,34 @@ async fn main() {
.route("/app.js", get(serve_app_js)) .route("/app.js", get(serve_app_js))
.route( .route(
"/ws/remote", "/ws/remote",
get(|ws: WebSocketUpgrade| async move { ws.on_upgrade(local::ws_handler) }), get(move |ws: WebSocketUpgrade| {
let update_interval = update_interval;
async move {
ws.on_upgrade(move |socket| remote::ws_handler(socket, update_interval))
}
}),
) )
.route( .route(
"/ws/local", "/ws/local",
get(|ws: WebSocketUpgrade| async move { ws.on_upgrade(remote::ws_handler) }), get(move |ws: WebSocketUpgrade| {
let update_interval = update_interval;
async move {
ws.on_upgrade(move |socket| local::ws_handler(socket, update_interval))
}
}),
)
.route(
"/ws",
get(move |ws: WebSocketUpgrade| {
let update_interval = update_interval;
async move {
ws.on_upgrade(move |socket| remote::ws_handler(socket, update_interval))
}
}),
) )
.fallback(get(not_found)); .fallback(get(not_found));
let addr = SocketAddr::from(([127, 0, 0, 1], 8080)); let addr = SocketAddr::new(cfg.ip, cfg.port);
println!("Open UI: http://{}/", addr); println!("Open UI: http://{}/", addr);
axum::serve(tokio::net::TcpListener::bind(addr).await.unwrap(), app) axum::serve(tokio::net::TcpListener::bind(addr).await.unwrap(), app)

View file

@ -11,7 +11,7 @@ use tokio::{
use crate::{ClientMsg, HResult, ServerMsg, build, run}; use crate::{ClientMsg, HResult, ServerMsg, build, run};
pub async fn ws_handler(socket: WebSocket) { pub async fn ws_handler(socket: WebSocket, refresh_time: Duration) {
let (mut sender, mut receiver) = socket.split(); let (mut sender, mut receiver) = socket.split();
let files = if let Some(Ok(Message::Text(msg))) = receiver.next().await let files = if let Some(Ok(Message::Text(msg))) = receiver.next().await
@ -113,7 +113,7 @@ pub async fn ws_handler(socket: WebSocket) {
} }
_ = tokio::time::sleep_until(print_deadline) => { _ = tokio::time::sleep_until(print_deadline) => {
use tokio::io::AsyncWriteExt; use tokio::io::AsyncWriteExt;
print_deadline += Duration::from_millis(30); print_deadline += refresh_time;
process.stdin.write_all("\n".as_bytes()).await?; process.stdin.write_all("\n".as_bytes()).await?;
} }
} }