From f4d3d921460b606a9ff6686c9bb9a79bf546f264 Mon Sep 17 00:00:00 2001 From: FxQnLr Date: Thu, 2 Nov 2023 21:01:16 +0100 Subject: baseline ping --- src/main.rs | 48 ++++++++++++++++++++++++--------- src/requests/device.rs | 42 +++++++++++++++++------------ src/requests/start.rs | 73 +++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 120 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/main.rs b/src/main.rs index ab7e476..3e1388b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,5 @@ +use std::fmt::Display; + use clap::{Parser, Subcommand}; use config::SETTINGS; use error::CliError; @@ -21,7 +23,9 @@ struct Args { enum Commands { Start { /// id of the device - id: String + id: String, + #[arg(short, long)] + ping: Option }, Device { #[command(subcommand)] @@ -34,7 +38,8 @@ enum DeviceCmd { Add { id: String, mac: String, - broadcast_addr: String + broadcast_addr: String, + ip: String }, Get { id: String, @@ -42,27 +47,29 @@ enum DeviceCmd { Edit { id: String, mac: String, - broadcast_addr: String + broadcast_addr: String, + ip: String }, } -fn main() -> Result<(), CliError> { +#[tokio::main] +async fn main() -> Result<(), CliError> { let cli = Args::parse(); match cli.commands { - Commands::Start { id } => { - start(id)?; + Commands::Start { id, ping } => { + start(id, ping.unwrap_or(true)).await?; }, Commands::Device { devicecmd } => { match devicecmd { - DeviceCmd::Add { id, mac, broadcast_addr } => { - device::put(id, mac, broadcast_addr)?; + DeviceCmd::Add { id, mac, broadcast_addr, ip } => { + device::put(id, mac, broadcast_addr, ip).await?; }, DeviceCmd::Get { id } => { - device::get(id)?; + device::get(id).await?; }, - DeviceCmd::Edit { id, mac, broadcast_addr } => { - device::post(id, mac, broadcast_addr)?; + DeviceCmd::Edit { id, mac, broadcast_addr, ip } => { + device::post(id, mac, broadcast_addr, ip).await?; }, } } @@ -87,14 +94,29 @@ fn default_headers() -> Result { Ok(map) } -fn format_url(path: &str) -> Result { +fn format_url(path: &str, protocol: Protocols) -> Result { Ok(format!( - "{}/{}", + "{}://{}/{}", + protocol, SETTINGS.get_string("server").map_err(CliError::Config)?, path )) } +enum Protocols { + Http, + Websocket, +} + +impl Display for Protocols { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Http => f.write_str("http"), + Self::Websocket => f.write_str("ws") + } + } +} + #[derive(Debug, Deserialize)] struct ErrorResponse { error: String diff --git a/src/requests/device.rs b/src/requests/device.rs index 525745a..f7754a4 100644 --- a/src/requests/device.rs +++ b/src/requests/device.rs @@ -1,55 +1,63 @@ -use crate::{error::CliError, default_headers, format_url}; +use crate::{error::CliError, default_headers, format_url, Protocols}; -pub fn put(id: String, mac: String, broadcast_addr: String) -> Result<(), CliError> { - let res = reqwest::blocking::Client::new() - .put(format_url("device")?) +pub async fn put(id: String, mac: String, broadcast_addr: String, ip: String) -> Result<(), CliError> { + let res = reqwest::Client::new() + .put(format_url("device", Protocols::Http)?) .headers(default_headers()?) .body( format!( - r#"{{"id": "{}", "mac": "{}", "broadcast_addr": "{}"}}"#, + r#"{{"id": "{}", "mac": "{}", "broadcast_addr": "{}", "ip": "{}"}}"#, id, mac, - broadcast_addr + broadcast_addr, + ip ) ) .send() + .await .map_err(CliError::Reqwest)? - .text(); + .text() + .await; println!("{:?}", res); Ok(()) } -pub fn get(id: String) -> Result<(), CliError> { - let res = reqwest::blocking::Client::new() - .get(format_url("device")?) +pub async fn get(id: String) -> Result<(), CliError> { + let res = reqwest::Client::new() + .get(format_url("device", Protocols::Http)?) .headers(default_headers()?) .body( format!(r#"{{"id": "{}"}}"#, id) ) .send() + .await .map_err(CliError::Reqwest)? - .text(); + .text() + .await; println!("{:?}", res); Ok(()) } -pub fn post(id: String, mac: String, broadcast_addr: String) -> Result<(), CliError> { - let res = reqwest::blocking::Client::new() - .post(format_url("device")?) +pub async fn post(id: String, mac: String, broadcast_addr: String, ip: String) -> Result<(), CliError> { + let res = reqwest::Client::new() + .post(format_url("device", Protocols::Http)?) .headers(default_headers()?) .body( format!( - r#"{{"id": "{}", "mac": "{}", "broadcast_addr": "{}"}}"#, + r#"{{"id": "{}", "mac": "{}", "broadcast_addr": "{}", "ip": "{}"}}"#, id, mac, - broadcast_addr + broadcast_addr, + ip ) ) .send() + .await .map_err(CliError::Reqwest)? - .text(); + .text() + .await; println!("{:?}", res); Ok(()) diff --git a/src/requests/start.rs b/src/requests/start.rs index 30f65b9..d0c4411 100644 --- a/src/requests/start.rs +++ b/src/requests/start.rs @@ -1,37 +1,57 @@ +use std::time::Duration; + +use futures_util::{StreamExt, SinkExt}; +use indicatif::{ProgressBar, ProgressStyle}; use reqwest::StatusCode; use serde::Deserialize; +use tokio_tungstenite::{connect_async, tungstenite::Message}; -use crate::{config::SETTINGS, error::CliError, default_headers, ErrorResponse}; +use crate::{error::CliError, default_headers, ErrorResponse, format_url, Protocols}; -pub fn start(id: String) -> Result<(), CliError> { - let res = reqwest::blocking::Client::new() - .post( - format!( - "{}/start", - SETTINGS.get_string("server").map_err(CliError::Config)? - ) - ) +pub async fn start(id: String, ping: bool) -> Result<(), CliError> { + + let send_start = ProgressBar::new(1); + + // TODO: calculate average start-time on server + send_start.set_style( + ProgressStyle::with_template("{spinner:.green} ({elapsed}) {wide_msg}") + .unwrap() + .tick_chars("|/-\\\\") + ); + + let url = format_url("start", Protocols::Http)?; + + send_start.set_message(format!("connect to {}", url)); + send_start.enable_steady_tick(Duration::from_millis(125)); + + let res = reqwest::Client::new() + .post(url) .headers(default_headers()?) .body( - format!(r#"{{"id": "{}"}}"#, id) + format!(r#"{{"id": "{}", "ping": {}}}"#, id, ping) ) .send() + .await .map_err(CliError::Reqwest)?; match res.status() { StatusCode::OK => { let body = serde_json::from_str::( - &res.text().map_err(CliError::Reqwest)? + &res.text().await.map_err(CliError::Reqwest)? ) .map_err(CliError::Serde)?; if body.boot { - println!("successfully started {}", body.id); + send_start.println("connected, sent start packet"); + } + + if ping { + send_start.println(status_socket(body.uuid, &send_start).await?.to_string()); } }, _ => { let body = serde_json::from_str::( - &res.text().map_err(CliError::Reqwest)? + &res.text().await.map_err(CliError::Reqwest)? ) .map_err(CliError::Serde)?; @@ -42,8 +62,35 @@ pub fn start(id: String) -> Result<(), CliError> { Ok(()) } +async fn status_socket(uuid: String, pb: &ProgressBar) -> Result { + pb.set_message("setup websocket"); + + let (mut ws_stream, _response) = connect_async(format_url("status", Protocols::Websocket)?) + .await + .expect("Failed to connect"); + pb.println("connected to websocket"); + + pb.set_message("send uuid message"); + ws_stream.send(Message::Text(uuid)).await.unwrap(); + pb.println("sent uuid message"); + + pb.set_message("wait for message"); + let msg = ws_stream.next().await.unwrap(); + + pb.println(format!("msg: {:?}", msg)); + + ws_stream.close(None).await.unwrap(); + pb.println("connection closed"); + // TODO: Check for correct UUID and timeout + pb.set_message("verifying message"); + if msg.is_ok() { return Ok(true) } + + Ok(false) +} + #[derive(Debug, Deserialize)] struct StartResponse { boot: bool, id: String, + uuid: String, } -- cgit v1.2.3