more informative shutdown
This commit is contained in:
parent
9e1e08851e
commit
a543c177b2
3 changed files with 38 additions and 29 deletions
45
src/lib.rs
45
src/lib.rs
|
@ -16,7 +16,7 @@ use serde::{Deserialize, Serialize};
|
||||||
use tokio::{
|
use tokio::{
|
||||||
net::UdpSocket,
|
net::UdpSocket,
|
||||||
sync::{Mutex, mpsc},
|
sync::{Mutex, mpsc},
|
||||||
task::JoinHandle,
|
task::JoinSet,
|
||||||
};
|
};
|
||||||
use transfer::Session;
|
use transfer::Session;
|
||||||
|
|
||||||
|
@ -25,7 +25,14 @@ 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<()>;
|
pub type ShutdownSender = mpsc::Sender<()>;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum Listeners {
|
||||||
|
Udp,
|
||||||
|
Http,
|
||||||
|
Multicast,
|
||||||
|
}
|
||||||
|
|
||||||
/// Contains the main network and backend state for an application session.
|
/// Contains the main network and backend state for an application session.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -57,35 +64,34 @@ impl JoecalState {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn start(
|
pub async fn start(&self, config: &Config, handles: &mut JoinSet<Listeners>) {
|
||||||
&self,
|
|
||||||
config: &Config,
|
|
||||||
) -> crate::error::Result<(JoinHandle<()>, JoinHandle<()>, JoinHandle<()>)> {
|
|
||||||
let state = self.clone();
|
let state = self.clone();
|
||||||
let konfig = config.clone();
|
let konfig = config.clone();
|
||||||
let server_handle = {
|
handles.spawn({
|
||||||
let (tx, shutdown_rx) = mpsc::channel(1);
|
let (tx, shutdown_rx) = mpsc::channel(1);
|
||||||
self.stop_tx.get_or_init(|| tx);
|
self.stop_tx.get_or_init(|| tx);
|
||||||
tokio::spawn(async move {
|
async move {
|
||||||
if let Err(e) = state.start_http_server(shutdown_rx, &konfig).await {
|
if let Err(e) = state.start_http_server(shutdown_rx, &konfig).await {
|
||||||
eprintln!("HTTP server error: {e}");
|
eprintln!("HTTP server error: {e}");
|
||||||
}
|
}
|
||||||
})
|
Listeners::Http
|
||||||
};
|
}
|
||||||
|
});
|
||||||
let state = self.clone();
|
let state = self.clone();
|
||||||
let konfig = config.clone();
|
let konfig = config.clone();
|
||||||
let udp_handle = {
|
handles.spawn({
|
||||||
tokio::spawn(async move {
|
async move {
|
||||||
if let Err(e) = state.listen_multicast(&konfig).await {
|
if let Err(e) = state.listen_multicast(&konfig).await {
|
||||||
eprintln!("UDP listener error: {e}");
|
eprintln!("UDP listener error: {e}");
|
||||||
}
|
}
|
||||||
})
|
Listeners::Multicast
|
||||||
};
|
}
|
||||||
|
});
|
||||||
|
|
||||||
let state = self.clone();
|
let state = self.clone();
|
||||||
let config = config.clone();
|
let config = config.clone();
|
||||||
let announcement_handle = {
|
handles.spawn({
|
||||||
tokio::spawn(async move {
|
async move {
|
||||||
loop {
|
loop {
|
||||||
let rstate = state.running_state.lock().await;
|
let rstate = state.running_state.lock().await;
|
||||||
if *rstate == RunningState::Stopping {
|
if *rstate == RunningState::Stopping {
|
||||||
|
@ -96,10 +102,9 @@ impl JoecalState {
|
||||||
}
|
}
|
||||||
tokio::time::sleep(std::time::Duration::from_secs(5)).await;
|
tokio::time::sleep(std::time::Duration::from_secs(5)).await;
|
||||||
}
|
}
|
||||||
})
|
Listeners::Udp
|
||||||
};
|
}
|
||||||
|
});
|
||||||
Ok((server_handle, udp_handle, announcement_handle))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn stop(&self) {
|
pub async fn stop(&self) {
|
||||||
|
|
18
src/main.rs
18
src/main.rs
|
@ -1,11 +1,11 @@
|
||||||
#![feature(slice_as_array)]
|
#![feature(slice_as_array)]
|
||||||
use std::{collections::BTreeMap, io, net::SocketAddr};
|
use std::{collections::BTreeMap, io, net::SocketAddr};
|
||||||
|
|
||||||
use joecalsend::{Config, JoecalState, RunningState, error, models::Device};
|
use joecalsend::{Config, JoecalState, error, models::Device};
|
||||||
use local_ip_address::local_ip;
|
use local_ip_address::local_ip;
|
||||||
use network_interface::{Addr, NetworkInterface, NetworkInterfaceConfig, V4IfAddr};
|
use network_interface::{Addr, NetworkInterface, NetworkInterfaceConfig, V4IfAddr};
|
||||||
use ratatui::{
|
use ratatui::{
|
||||||
DefaultTerminal, Frame,
|
DefaultTerminal,
|
||||||
buffer::Buffer,
|
buffer::Buffer,
|
||||||
crossterm::event::{self, Event, KeyCode, KeyEvent, KeyEventKind},
|
crossterm::event::{self, Event, KeyCode, KeyEvent, KeyEventKind},
|
||||||
layout::Rect,
|
layout::Rect,
|
||||||
|
@ -14,6 +14,7 @@ use ratatui::{
|
||||||
text::{Line, Text},
|
text::{Line, Text},
|
||||||
widgets::{Block, Paragraph, Widget},
|
widgets::{Block, Paragraph, Widget},
|
||||||
};
|
};
|
||||||
|
use tokio::task::JoinSet;
|
||||||
|
|
||||||
mod ui;
|
mod ui;
|
||||||
|
|
||||||
|
@ -46,14 +47,19 @@ async fn main() -> error::Result<()> {
|
||||||
.await
|
.await
|
||||||
.expect("Could not create application session");
|
.expect("Could not create application session");
|
||||||
let config = Config::default();
|
let config = Config::default();
|
||||||
let (h1, h2, h3) = state.start(&config).await.unwrap();
|
let mut handles = JoinSet::new();
|
||||||
|
state.start(&config, &mut handles).await;
|
||||||
let mut app = App::new(state.clone()).await;
|
let mut app = App::new(state.clone()).await;
|
||||||
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();
|
||||||
|
|
||||||
let _ = tokio::join!(h1, h2, h3);
|
while let Some(handle) = handles.join_next().await {
|
||||||
|
match handle {
|
||||||
|
Ok(h) => println!("Stopped {h:?}"),
|
||||||
|
Err(e) => println!("Got error {e:?}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(result?)
|
Ok(result?)
|
||||||
}
|
}
|
||||||
|
@ -78,7 +84,7 @@ enum CurrentScreen {
|
||||||
impl App {
|
impl App {
|
||||||
pub async fn new(state: JoecalState) -> Self {
|
pub async fn new(state: JoecalState) -> Self {
|
||||||
App {
|
App {
|
||||||
state: state.clone(),
|
state,
|
||||||
screen: CurrentScreen::Main,
|
screen: CurrentScreen::Main,
|
||||||
peers: Default::default(),
|
peers: Default::default(),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
use std::{collections::BTreeMap, net::SocketAddr};
|
|
||||||
|
|
||||||
use ratatui::{
|
use ratatui::{
|
||||||
Frame,
|
Frame,
|
||||||
layout::{Constraint, Direction, Layout, Rect},
|
layout::{Constraint, Direction, Layout, Rect},
|
||||||
style::Stylize,
|
style::Stylize,
|
||||||
text::{Line, Span},
|
text::Line,
|
||||||
widgets::{Block, Borders, List, ListItem},
|
widgets::{Block, Borders, List, ListItem},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue