Compare commits

..

No commits in common. "5e4e31d64fa8e9a69f39b30b699f3ef158e77d41" and "c02e4bc879539475c8b2378691d7b9628fe34900" have entirely different histories.

4 changed files with 39 additions and 36 deletions

View file

@ -29,12 +29,13 @@ impl JoecalState {
println!("Listening on multicast addr: {}", config.multicast_addr); println!("Listening on multicast addr: {}", config.multicast_addr);
let mut timeout = tokio::time::interval(Duration::from_secs(5)); let mut timeout = tokio::time::interval(Duration::from_secs(5));
timeout.tick().await;
loop { loop {
tokio::select! { tokio::select! {
_ = timeout.tick() => { _ = timeout.tick() => {
let rstate = self.running_state.lock().await; if let Ok(state) = self.running_state.try_lock()
if *rstate == RunningState::Stopping && *state == RunningState::Stopping
{ {
break; break;
} }

View file

@ -59,5 +59,6 @@ impl JoecalState {
} }
async fn shutdown(mut rx: mpsc::Receiver<()>) { async fn shutdown(mut rx: mpsc::Receiver<()>) {
println!("shutting down");
rx.recv().await.unwrap_or_default() rx.recv().await.unwrap_or_default()
} }

View file

@ -7,8 +7,7 @@ pub mod transfer;
use std::{ use std::{
collections::HashMap, collections::HashMap,
net::{Ipv4Addr, SocketAddr, SocketAddrV4}, net::{Ipv4Addr, SocketAddr, SocketAddrV4},
sync::{Arc, OnceLock}, sync::Arc,
time::Duration,
}; };
use models::Device; use models::Device;
@ -25,8 +24,6 @@ pub const MULTICAST_IP: Ipv4Addr = Ipv4Addr::new(224, 0, 0, 167);
pub const LISTENING_SOCKET_ADDR: SocketAddrV4 = pub const LISTENING_SOCKET_ADDR: SocketAddrV4 =
SocketAddrV4::new(Ipv4Addr::from_bits(0), DEFAULT_PORT); SocketAddrV4::new(Ipv4Addr::from_bits(0), DEFAULT_PORT);
type ShutdownSender = mpsc::Sender<()>;
/// Contains the main network and application state for an application session. /// Contains the main network and application state for an application session.
#[derive(Clone)] #[derive(Clone)]
pub struct JoecalState { pub struct JoecalState {
@ -36,7 +33,7 @@ pub struct JoecalState {
pub running_state: Arc<Mutex<RunningState>>, pub running_state: Arc<Mutex<RunningState>>,
pub socket: Arc<UdpSocket>, pub socket: Arc<UdpSocket>,
pub client: reqwest::Client, pub client: reqwest::Client,
stop_tx: OnceLock<ShutdownSender>, stop_tx: std::sync::OnceLock<mpsc::Sender<()>>,
} }
impl JoecalState { impl JoecalState {
@ -64,10 +61,10 @@ impl JoecalState {
let state = self.clone(); let state = self.clone();
let konfig = config.clone(); let konfig = config.clone();
let server_handle = { let server_handle = {
let (tx, shutdown_rx) = mpsc::channel(1); let (tx, rx) = mpsc::channel(1);
self.stop_tx.get_or_init(|| tx); self.stop_tx.get_or_init(|| tx);
tokio::spawn(async move { tokio::spawn(async move {
if let Err(e) = state.start_http_server(shutdown_rx, &konfig).await { if let Err(e) = state.start_http_server(rx, &konfig).await {
eprintln!("HTTP server error: {e}"); eprintln!("HTTP server error: {e}");
} }
}) })
@ -87,10 +84,12 @@ impl JoecalState {
let announcement_handle = { let announcement_handle = {
tokio::spawn(async move { tokio::spawn(async move {
loop { loop {
let rstate = state.running_state.lock().await; if let Ok(lock) = state.running_state.try_lock()
if *rstate == RunningState::Stopping { && *lock == RunningState::Stopping
{
break; break;
} }
if let Err(e) = state.announce(None, &config).await { if let Err(e) = state.announce(None, &config).await {
eprintln!("Announcement error: {e}"); eprintln!("Announcement error: {e}");
} }
@ -104,8 +103,8 @@ impl JoecalState {
pub async fn stop(&self) { pub async fn stop(&self) {
loop { loop {
let mut rstate = self.running_state.lock().await; if let Ok(mut lock) = self.running_state.try_lock() {
*rstate = RunningState::Stopping; *lock = RunningState::Stopping;
if self if self
.stop_tx .stop_tx
.get() .get()
@ -115,8 +114,7 @@ impl JoecalState {
.is_ok() .is_ok()
{ {
break; break;
} else { }
tokio::time::sleep(Duration::from_millis(777)).await;
} }
} }
} }
@ -130,6 +128,8 @@ impl JoecalState {
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RunningState { pub enum RunningState {
Running, Running,
Sending,
Receiving,
Stopping, Stopping,
} }

View file

@ -46,7 +46,7 @@ async fn main() -> error::Result<()> {
let config = Config::default(); let config = Config::default();
let (h1, h2, h3) = state.start(&config).await.unwrap(); let (h1, h2, h3) = state.start(&config).await.unwrap();
let mut app = App::new(state.clone()).await; let mut app = App::new(state.clone());
let mut terminal = ratatui::init(); let mut terminal = ratatui::init();
let result = app.run(&mut terminal).await; let result = app.run(&mut terminal).await;
ratatui::restore(); ratatui::restore();
@ -58,24 +58,20 @@ async fn main() -> error::Result<()> {
struct App { struct App {
state: JoecalState, state: JoecalState,
rstate: RunningState,
} }
impl App { impl App {
pub async fn new(state: JoecalState) -> Self { pub fn new(state: JoecalState) -> Self {
App { App { state }
state: state.clone(),
rstate: *state.running_state.lock().await,
}
} }
pub async fn run(&mut self, terminal: &mut DefaultTerminal) -> io::Result<()> { pub async fn run(&mut self, terminal: &mut DefaultTerminal) -> io::Result<()> {
loop { loop {
terminal.draw(|frame| self.draw(frame))?; terminal.draw(|frame| self.draw(frame))?;
self.handle_events().await?; self.handle_events().await?;
let rstate = self.state.running_state.lock().await; if let Ok(lock) = self.state.running_state.try_lock()
self.rstate = *rstate; && *lock == RunningState::Stopping
if *rstate == RunningState::Stopping { {
break; break;
} }
} }
@ -115,7 +111,7 @@ impl App {
impl Widget for &App { impl Widget for &App {
fn render(self, area: Rect, buf: &mut Buffer) { fn render(self, area: Rect, buf: &mut Buffer) {
let title = Line::from(" Joecalsend ".bold()); let title = Line::from(" Counter App Tutorial ".bold());
let instructions = Line::from(vec![ let instructions = Line::from(vec![
" Send ".into(), " Send ".into(),
"<S>".blue().bold(), "<S>".blue().bold(),
@ -131,7 +127,12 @@ impl Widget for &App {
.title_bottom(instructions.centered()) .title_bottom(instructions.centered())
.border_set(border::THICK); .border_set(border::THICK);
let rs = format!("{:?}", self.rstate); let rs = self
.state
.running_state
.try_lock()
.map(|s| format!("{s:?}"))
.unwrap_or("Just a moment...".into());
let state_text = Text::from(vec![Line::from(vec!["runstate: ".into(), rs.yellow()])]); let state_text = Text::from(vec![Line::from(vec!["runstate: ".into(), rs.yellow()])]);
Paragraph::new(state_text) Paragraph::new(state_text)