add default duration
This commit is contained in:
parent
471fc5d73c
commit
8791468c17
5 changed files with 66 additions and 46 deletions
|
@ -7,7 +7,7 @@ use std::{
|
||||||
|
|
||||||
use crossterm::event::{Event, EventStream, KeyCode, KeyEvent, KeyEventKind};
|
use crossterm::event::{Event, EventStream, KeyCode, KeyEvent, KeyEventKind};
|
||||||
use futures::{FutureExt, StreamExt};
|
use futures::{FutureExt, StreamExt};
|
||||||
use jocalsend::{JocalService, ReceiveDialog, ReceiveRequest, TransferEvent, error::Result};
|
use jocalsend::{JocalEvent, JocalService, ReceiveDialog, ReceiveRequest, error::Result};
|
||||||
use julid::Julid;
|
use julid::Julid;
|
||||||
use log::{LevelFilter, debug, error, warn};
|
use log::{LevelFilter, debug, error, warn};
|
||||||
use ratatui::{
|
use ratatui::{
|
||||||
|
@ -54,7 +54,7 @@ pub struct App {
|
||||||
receiving_state: TableState,
|
receiving_state: TableState,
|
||||||
// for getting messages back from the web server or web client about things we've done; the
|
// for getting messages back from the web server or web client about things we've done; the
|
||||||
// other end is held by the service
|
// other end is held by the service
|
||||||
event_listener: UnboundedReceiver<TransferEvent>,
|
event_listener: UnboundedReceiver<JocalEvent>,
|
||||||
file_finder: FileFinder,
|
file_finder: FileFinder,
|
||||||
text: Option<String>,
|
text: Option<String>,
|
||||||
input: Input,
|
input: Input,
|
||||||
|
@ -83,7 +83,7 @@ pub enum FileMode {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
pub fn new(service: JocalService, event_listener: UnboundedReceiver<TransferEvent>) -> Self {
|
pub fn new(service: JocalService, event_listener: UnboundedReceiver<JocalEvent>) -> Self {
|
||||||
App {
|
App {
|
||||||
service,
|
service,
|
||||||
event_listener,
|
event_listener,
|
||||||
|
@ -117,12 +117,15 @@ impl App {
|
||||||
if let Some(event) = transfer_event {
|
if let Some(event) = transfer_event {
|
||||||
debug!("got transferr event {event:?}");
|
debug!("got transferr event {event:?}");
|
||||||
match event {
|
match event {
|
||||||
TransferEvent::ReceiveRequest { id, request } => {
|
JocalEvent::ReceiveRequest { id, request } => {
|
||||||
self.receive_requests.insert(id, request);
|
self.receive_requests.insert(id, request);
|
||||||
}
|
}
|
||||||
TransferEvent::Cancelled(id) | TransferEvent::Received(id) => {
|
JocalEvent::Cancelled(id) | JocalEvent::ReceivedInbound(id) => {
|
||||||
self.receive_requests.remove(&id);
|
self.receive_requests.remove(&id);
|
||||||
}
|
}
|
||||||
|
JocalEvent::SendApproved(_id) => todo!(),
|
||||||
|
JocalEvent::SendDenied(_id) => todo!(),
|
||||||
|
JocalEvent::Tick => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use std::{
|
use std::{
|
||||||
net::{SocketAddr, SocketAddrV4},
|
net::{SocketAddr, SocketAddrV4},
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
time::Duration,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use axum::{
|
use axum::{
|
||||||
|
@ -11,7 +10,7 @@ use axum::{
|
||||||
use log::{debug, error, trace, warn};
|
use log::{debug, error, trace, warn};
|
||||||
use tokio::net::UdpSocket;
|
use tokio::net::UdpSocket;
|
||||||
|
|
||||||
use crate::{Config, JocalService, RunningState, models::Device};
|
use crate::{Config, DEFAULT_INTERVAL, JocalService, RunningState, models::Device};
|
||||||
|
|
||||||
impl JocalService {
|
impl JocalService {
|
||||||
pub async fn announce(&self, socket: Option<SocketAddr>) -> crate::error::Result<()> {
|
pub async fn announce(&self, socket: Option<SocketAddr>) -> crate::error::Result<()> {
|
||||||
|
@ -29,7 +28,7 @@ impl JocalService {
|
||||||
pub async fn listen_multicast(&self) -> crate::error::Result<()> {
|
pub async fn listen_multicast(&self) -> crate::error::Result<()> {
|
||||||
let mut buf = [0; 65536];
|
let mut buf = [0; 65536];
|
||||||
|
|
||||||
let mut timeout = tokio::time::interval(Duration::from_secs(5));
|
let mut timeout = tokio::time::interval(DEFAULT_INTERVAL);
|
||||||
timeout.tick().await;
|
timeout.tick().await;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
@ -45,7 +44,6 @@ impl JocalService {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
r = self.socket.recv_from(&mut buf) => {
|
r = self.socket.recv_from(&mut buf) => {
|
||||||
trace!("received multicast datagram");
|
|
||||||
match r {
|
match r {
|
||||||
Ok((size, src)) => {
|
Ok((size, src)) => {
|
||||||
let received_msg = String::from_utf8_lossy(&buf[..size]);
|
let received_msg = String::from_utf8_lossy(&buf[..size]);
|
||||||
|
|
81
src/lib.rs
81
src/lib.rs
|
@ -32,11 +32,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);
|
||||||
|
|
||||||
|
pub const DEFAULT_INTERVAL: Duration = Duration::from_millis(200);
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum Listeners {
|
pub enum JocalTasks {
|
||||||
Udp,
|
Udp,
|
||||||
Http,
|
Http,
|
||||||
Multicast,
|
Multicast,
|
||||||
|
Tick,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
@ -46,10 +49,13 @@ pub enum ReceiveDialog {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum TransferEvent {
|
pub enum JocalEvent {
|
||||||
Received(Julid),
|
ReceivedInbound(Julid),
|
||||||
|
SendApproved(Julid),
|
||||||
|
SendDenied(Julid),
|
||||||
Cancelled(Julid),
|
Cancelled(Julid),
|
||||||
ReceiveRequest { id: Julid, request: ReceiveRequest },
|
ReceiveRequest { id: Julid, request: ReceiveRequest },
|
||||||
|
Tick,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -80,13 +86,13 @@ pub struct JocalService {
|
||||||
http_handle: OnceLock<axum_server::Handle>,
|
http_handle: OnceLock<axum_server::Handle>,
|
||||||
// the receiving end will be held by the application so it can update the UI based on backend
|
// the receiving end will be held by the application so it can update the UI based on backend
|
||||||
// events
|
// events
|
||||||
transfer_event_tx: UnboundedSender<TransferEvent>,
|
transfer_event_tx: UnboundedSender<JocalEvent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl JocalService {
|
impl JocalService {
|
||||||
pub async fn new(
|
pub async fn new(
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> crate::error::Result<(Self, UnboundedReceiver<TransferEvent>)> {
|
) -> crate::error::Result<(Self, UnboundedReceiver<JocalEvent>)> {
|
||||||
let (tx, rx) = mpsc::unbounded_channel();
|
let (tx, rx) = mpsc::unbounded_channel();
|
||||||
let socket = UdpSocket::bind(LISTENING_SOCKET_ADDR).await?;
|
let socket = UdpSocket::bind(LISTENING_SOCKET_ADDR).await?;
|
||||||
socket.set_multicast_loop_v4(true)?;
|
socket.set_multicast_loop_v4(true)?;
|
||||||
|
@ -113,43 +119,56 @@ impl JocalService {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn start(&self, handles: &mut JoinSet<Listeners>) {
|
pub async fn start(&self, handles: &mut JoinSet<JocalTasks>) {
|
||||||
let service = self.clone();
|
let service = self.clone();
|
||||||
|
|
||||||
handles.spawn({
|
handles.spawn(async move {
|
||||||
async move {
|
if let Err(e) = service.start_http_server().await {
|
||||||
if let Err(e) = service.start_http_server().await {
|
error!("HTTP server error: {e}");
|
||||||
error!("HTTP server error: {e}");
|
|
||||||
}
|
|
||||||
Listeners::Http
|
|
||||||
}
|
}
|
||||||
|
JocalTasks::Http
|
||||||
});
|
});
|
||||||
let service = self.clone();
|
let service = self.clone();
|
||||||
|
|
||||||
handles.spawn({
|
handles.spawn(async move {
|
||||||
async move {
|
if let Err(e) = service.listen_multicast().await {
|
||||||
if let Err(e) = service.listen_multicast().await {
|
error!("UDP listener error: {e}");
|
||||||
error!("UDP listener error: {e}");
|
|
||||||
}
|
|
||||||
Listeners::Multicast
|
|
||||||
}
|
}
|
||||||
|
JocalTasks::Multicast
|
||||||
});
|
});
|
||||||
|
|
||||||
let service = self.clone();
|
let service = self.clone();
|
||||||
handles.spawn({
|
handles.spawn(async move {
|
||||||
async move {
|
let service = &service;
|
||||||
loop {
|
let mut tick = tokio::time::interval(DEFAULT_INTERVAL);
|
||||||
let rstate = service.running_state.lock().await;
|
|
||||||
if *rstate == RunningState::Stopping {
|
loop {
|
||||||
break;
|
let rstate = service.running_state.lock().await;
|
||||||
}
|
if *rstate == RunningState::Stopping {
|
||||||
if let Err(e) = service.announce(None).await {
|
break;
|
||||||
error!("Announcement error: {e}");
|
|
||||||
}
|
|
||||||
tokio::time::sleep(Duration::from_secs(5)).await;
|
|
||||||
}
|
}
|
||||||
Listeners::Udp
|
tick.tick().await;
|
||||||
|
service
|
||||||
|
.transfer_event_tx
|
||||||
|
.send(JocalEvent::Tick)
|
||||||
|
.unwrap_or_else(|e| log::warn!("could not send tick event: {e:?}"));
|
||||||
}
|
}
|
||||||
|
JocalTasks::Tick
|
||||||
|
});
|
||||||
|
|
||||||
|
let service = self.clone();
|
||||||
|
handles.spawn(async move {
|
||||||
|
loop {
|
||||||
|
let rstate = service.running_state.lock().await;
|
||||||
|
if *rstate == RunningState::Stopping {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if let Err(e) = service.announce(None).await {
|
||||||
|
error!("Announcement error: {e}");
|
||||||
|
}
|
||||||
|
tokio::time::sleep(Duration::from_secs(2)).await;
|
||||||
|
}
|
||||||
|
JocalTasks::Udp
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,7 +187,7 @@ impl JocalService {
|
||||||
peers.clear();
|
peers.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_event(&self, event: TransferEvent) {
|
pub fn send_event(&self, event: JocalEvent) {
|
||||||
if let Err(e) = self.transfer_event_tx.send(event.clone()) {
|
if let Err(e) = self.transfer_event_tx.send(event.clone()) {
|
||||||
error!("got error sending transfer event '{event:?}': {e:?}");
|
error!("got error sending transfer event '{event:?}': {e:?}");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::{path::Path, str::FromStr, time::Duration};
|
use std::{path::Path, str::FromStr, time::Duration};
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use jocalsend::{Config, JocalService, Listeners, error::Result};
|
use jocalsend::{Config, JocalService, JocalTasks, error::Result};
|
||||||
use log::{error, info};
|
use log::{error, info};
|
||||||
use ratatui::DefaultTerminal;
|
use ratatui::DefaultTerminal;
|
||||||
use ratatui_explorer::FileExplorer;
|
use ratatui_explorer::FileExplorer;
|
||||||
|
@ -105,7 +105,7 @@ async fn start_and_run(terminal: &mut DefaultTerminal, config: Config) -> Result
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn shutdown(handles: &mut JoinSet<Listeners>) {
|
async fn shutdown(handles: &mut JoinSet<JocalTasks>) {
|
||||||
let mut timeout = tokio::time::interval(Duration::from_secs(5));
|
let mut timeout = tokio::time::interval(Duration::from_secs(5));
|
||||||
timeout.tick().await;
|
timeout.tick().await;
|
||||||
loop {
|
loop {
|
||||||
|
|
|
@ -13,7 +13,7 @@ use serde::{Deserialize, Serialize};
|
||||||
use tokio::sync::mpsc::unbounded_channel;
|
use tokio::sync::mpsc::unbounded_channel;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
JocalService, ReceiveDialog, ReceiveRequest, TransferEvent,
|
JocalEvent, JocalService, ReceiveDialog, ReceiveRequest,
|
||||||
error::{LocalSendError, Result},
|
error::{LocalSendError, Result},
|
||||||
models::{Device, FileMetadata},
|
models::{Device, FileMetadata},
|
||||||
};
|
};
|
||||||
|
@ -239,7 +239,7 @@ pub async fn handle_prepare_upload(
|
||||||
|
|
||||||
match service
|
match service
|
||||||
.transfer_event_tx
|
.transfer_event_tx
|
||||||
.send(TransferEvent::ReceiveRequest { id, request })
|
.send(JocalEvent::ReceiveRequest { id, request })
|
||||||
{
|
{
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -354,7 +354,7 @@ pub async fn handle_receive_upload(
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(id) = Julid::from_str(session_id) {
|
if let Ok(id) = Julid::from_str(session_id) {
|
||||||
service.send_event(TransferEvent::Received(id));
|
service.send_event(JocalEvent::ReceivedInbound(id));
|
||||||
};
|
};
|
||||||
|
|
||||||
StatusCode::OK.into_response()
|
StatusCode::OK.into_response()
|
||||||
|
@ -384,7 +384,7 @@ pub async fn handle_cancel(
|
||||||
session.status = SessionStatus::Cancelled;
|
session.status = SessionStatus::Cancelled;
|
||||||
|
|
||||||
if let Ok(id) = Julid::from_str(¶ms.session_id) {
|
if let Ok(id) = Julid::from_str(¶ms.session_id) {
|
||||||
service.send_event(TransferEvent::Cancelled(id));
|
service.send_event(JocalEvent::Cancelled(id));
|
||||||
};
|
};
|
||||||
|
|
||||||
StatusCode::OK.into_response()
|
StatusCode::OK.into_response()
|
||||||
|
|
Loading…
Reference in a new issue