mirror of
https://github.com/feschber/lan-mouse.git
synced 2026-03-24 05:30:55 +03:00
simplify cancellation of service
This commit is contained in:
@@ -1,8 +1,13 @@
|
||||
use anyhow::{anyhow, Result};
|
||||
use futures::StreamExt;
|
||||
use std::{collections::HashSet, net::SocketAddr};
|
||||
use tokio_util::sync::CancellationToken;
|
||||
|
||||
use tokio::{process::Command, sync::mpsc::Sender, task::JoinHandle};
|
||||
use tokio::{
|
||||
process::Command,
|
||||
sync::{mpsc::Sender, Notify},
|
||||
task::JoinHandle,
|
||||
};
|
||||
|
||||
use input_capture::{self, error::CaptureCreationError, CaptureHandle, InputCapture, Position};
|
||||
|
||||
@@ -20,8 +25,6 @@ pub enum CaptureEvent {
|
||||
Create(CaptureHandle, Position),
|
||||
/// destory a capture client
|
||||
Destroy(CaptureHandle),
|
||||
/// termination signal
|
||||
Terminate,
|
||||
/// restart input capture
|
||||
Restart,
|
||||
}
|
||||
@@ -30,8 +33,9 @@ pub fn new(
|
||||
backend: Option<CaptureBackend>,
|
||||
server: Server,
|
||||
sender_tx: Sender<(Event, SocketAddr)>,
|
||||
timer_tx: Sender<()>,
|
||||
timer_notify: Notify,
|
||||
release_bind: Vec<scancode::Linux>,
|
||||
cancellation_token: CancellationToken,
|
||||
) -> Result<(JoinHandle<Result<()>>, Sender<CaptureEvent>), CaptureCreationError> {
|
||||
let (tx, mut rx) = tokio::sync::mpsc::channel(32);
|
||||
let backend = backend.map(|b| b.into());
|
||||
@@ -42,7 +46,7 @@ pub fn new(
|
||||
tokio::select! {
|
||||
event = capture.next() => {
|
||||
match event {
|
||||
Some(Ok(event)) => handle_capture_event(&server, &mut capture, &sender_tx, &timer_tx, event, &mut pressed_keys, &release_bind).await?,
|
||||
Some(Ok(event)) => handle_capture_event(&server, &mut capture, &sender_tx, &timer_notify, event, &mut pressed_keys, &release_bind).await?,
|
||||
Some(Err(e)) => return Err(anyhow!("input capture: {e:?}")),
|
||||
None => return Err(anyhow!("input capture terminated")),
|
||||
}
|
||||
@@ -65,11 +69,11 @@ pub fn new(
|
||||
capture.create(handle, pos.into()).await?;
|
||||
}
|
||||
}
|
||||
CaptureEvent::Terminate => break,
|
||||
},
|
||||
None => break,
|
||||
}
|
||||
}
|
||||
_ = cancellation_token.cancelled() => break,
|
||||
}
|
||||
}
|
||||
anyhow::Ok(())
|
||||
@@ -91,7 +95,7 @@ async fn handle_capture_event(
|
||||
server: &Server,
|
||||
capture: &mut Box<dyn InputCapture>,
|
||||
sender_tx: &Sender<(Event, SocketAddr)>,
|
||||
timer_tx: &Sender<()>,
|
||||
timer_notify: &Notify,
|
||||
event: (CaptureHandle, Event),
|
||||
pressed_keys: &mut HashSet<scancode::Linux>,
|
||||
release_bind: &[scancode::Linux],
|
||||
@@ -150,7 +154,7 @@ async fn handle_capture_event(
|
||||
(client_state.active_addr, enter, start_timer)
|
||||
};
|
||||
if start_timer {
|
||||
let _ = timer_tx.try_send(());
|
||||
timer_notify.notify_waiters();
|
||||
}
|
||||
if enter {
|
||||
spawn_hook_command(server, handle);
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
use std::net::SocketAddr;
|
||||
use std::{net::SocketAddr, sync::Arc};
|
||||
|
||||
use thiserror::Error;
|
||||
use tokio::{
|
||||
sync::mpsc::{Receiver, Sender},
|
||||
sync::{
|
||||
mpsc::{Receiver, Sender},
|
||||
Notify,
|
||||
},
|
||||
task::JoinHandle,
|
||||
};
|
||||
use tokio_util::sync::CancellationToken;
|
||||
|
||||
use crate::{
|
||||
client::{ClientHandle, ClientManager},
|
||||
@@ -28,8 +32,6 @@ pub enum EmulationEvent {
|
||||
Destroy(EmulationHandle),
|
||||
/// input emulation must release keys for client
|
||||
ReleaseKeys(ClientHandle),
|
||||
/// termination signal
|
||||
Terminate,
|
||||
/// restart input emulation
|
||||
Restart,
|
||||
}
|
||||
@@ -40,14 +42,23 @@ pub fn new(
|
||||
udp_rx: Receiver<Result<(Event, SocketAddr), NetworkError>>,
|
||||
sender_tx: Sender<(Event, SocketAddr)>,
|
||||
capture_tx: Sender<CaptureEvent>,
|
||||
timer_tx: Sender<()>,
|
||||
timer_notify: Arc<Notify>,
|
||||
cancellation_token: CancellationToken,
|
||||
) -> (
|
||||
JoinHandle<Result<(), LanMouseEmulationError>>,
|
||||
Sender<EmulationEvent>,
|
||||
) {
|
||||
let (tx, rx) = tokio::sync::mpsc::channel(32);
|
||||
let emulation_task =
|
||||
emulation_task(backend, rx, server, udp_rx, sender_tx, capture_tx, timer_tx);
|
||||
let emulation_task = emulation_task(
|
||||
backend,
|
||||
rx,
|
||||
server,
|
||||
udp_rx,
|
||||
sender_tx,
|
||||
capture_tx,
|
||||
timer_notify,
|
||||
cancellation_token,
|
||||
);
|
||||
let emulate_task = tokio::task::spawn_local(emulation_task);
|
||||
(emulate_task, tx)
|
||||
}
|
||||
@@ -67,7 +78,8 @@ async fn emulation_task(
|
||||
mut udp_rx: Receiver<Result<(Event, SocketAddr), NetworkError>>,
|
||||
sender_tx: Sender<(Event, SocketAddr)>,
|
||||
capture_tx: Sender<CaptureEvent>,
|
||||
timer_tx: Sender<()>,
|
||||
timer_notify: Arc<Notify>,
|
||||
cancellation_token: CancellationToken,
|
||||
) -> Result<(), LanMouseEmulationError> {
|
||||
let backend = backend.map(|b| b.into());
|
||||
let mut emulation = input_emulation::create(backend).await?;
|
||||
@@ -84,7 +96,7 @@ async fn emulation_task(
|
||||
}
|
||||
None => break,
|
||||
};
|
||||
handle_udp_rx(&server, &capture_tx, &mut emulation, &sender_tx, &mut last_ignored, udp_event, &timer_tx).await?;
|
||||
handle_udp_rx(&server, &capture_tx, &mut emulation, &sender_tx, &mut last_ignored, udp_event, &timer_notify).await?;
|
||||
}
|
||||
emulate_event = rx.recv() => {
|
||||
match emulate_event {
|
||||
@@ -99,11 +111,11 @@ async fn emulation_task(
|
||||
emulation.create(handle).await;
|
||||
}
|
||||
},
|
||||
EmulationEvent::Terminate => break,
|
||||
},
|
||||
None => break,
|
||||
}
|
||||
}
|
||||
_ = cancellation_token.cancelled() => break,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,7 +132,7 @@ async fn handle_udp_rx(
|
||||
sender_tx: &Sender<(Event, SocketAddr)>,
|
||||
last_ignored: &mut Option<SocketAddr>,
|
||||
event: (Event, SocketAddr),
|
||||
timer_tx: &Sender<()>,
|
||||
timer_notify: &Notify,
|
||||
) -> Result<(), EmulationError> {
|
||||
let (event, addr) = event;
|
||||
|
||||
@@ -170,7 +182,7 @@ async fn handle_udp_rx(
|
||||
);
|
||||
// restart timer if necessary
|
||||
if restart_timer {
|
||||
let _ = timer_tx.try_send(());
|
||||
timer_notify.notify_waiters();
|
||||
}
|
||||
ignore_event
|
||||
} else {
|
||||
|
||||
@@ -15,6 +15,7 @@ use tokio::{
|
||||
sync::mpsc::{Receiver, Sender},
|
||||
task::JoinHandle,
|
||||
};
|
||||
use tokio_util::sync::CancellationToken;
|
||||
|
||||
use crate::{
|
||||
client::{ClientHandle, Position},
|
||||
@@ -33,10 +34,12 @@ pub(crate) fn new(
|
||||
emulate: Sender<EmulationEvent>,
|
||||
resolve_ch: Sender<DnsRequest>,
|
||||
port_tx: Sender<u16>,
|
||||
cancellation_token: CancellationToken,
|
||||
) -> (JoinHandle<Result<()>>, Sender<FrontendRequest>) {
|
||||
let (event_tx, mut event_rx) = tokio::sync::mpsc::channel(32);
|
||||
let event_tx_clone = event_tx.clone();
|
||||
let frontend_task = tokio::task::spawn_local(async move {
|
||||
let mut join_handles = vec![];
|
||||
loop {
|
||||
tokio::select! {
|
||||
stream = frontend.accept() => {
|
||||
@@ -47,7 +50,7 @@ pub(crate) fn new(
|
||||
continue;
|
||||
}
|
||||
};
|
||||
handle_frontend_stream(&event_tx_clone, stream).await;
|
||||
join_handles.push(handle_frontend_stream(&event_tx_clone, stream, cancellation_token.clone()));
|
||||
}
|
||||
event = event_rx.recv() => {
|
||||
let frontend_event = event.ok_or(anyhow!("frontend channel closed"))?;
|
||||
@@ -59,6 +62,10 @@ pub(crate) fn new(
|
||||
let notify = notify.ok_or(anyhow!("frontend notify closed"))?;
|
||||
let _ = frontend.broadcast_event(notify).await;
|
||||
}
|
||||
_ = cancellation_token.cancelled() => {
|
||||
futures::future::join_all(join_handles).await;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
anyhow::Ok(())
|
||||
@@ -66,33 +73,45 @@ pub(crate) fn new(
|
||||
(frontend_task, event_tx)
|
||||
}
|
||||
|
||||
async fn handle_frontend_stream(
|
||||
fn handle_frontend_stream(
|
||||
frontend_tx: &Sender<FrontendRequest>,
|
||||
#[cfg(unix)] stream: ReadHalf<UnixStream>,
|
||||
#[cfg(windows)] stream: ReadHalf<TcpStream>,
|
||||
cancellation_token: CancellationToken,
|
||||
) -> JoinHandle<()> {
|
||||
|
||||
let tx = frontend_tx.clone();
|
||||
tokio::task::spawn_local(async move {
|
||||
tokio::select! {
|
||||
_ = listen_frontend(tx, stream) => return,
|
||||
_ = cancellation_token.cancelled() => return,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async fn listen_frontend(
|
||||
tx: Sender<FrontendRequest>,
|
||||
#[cfg(unix)] mut stream: ReadHalf<UnixStream>,
|
||||
#[cfg(windows)] mut stream: ReadHalf<TcpStream>,
|
||||
) {
|
||||
use std::io;
|
||||
|
||||
let tx = frontend_tx.clone();
|
||||
tokio::task::spawn_local(async move {
|
||||
loop {
|
||||
let request = frontend::wait_for_request(&mut stream).await;
|
||||
match request {
|
||||
Ok(request) => {
|
||||
let _ = tx.send(request).await;
|
||||
}
|
||||
Err(e) => {
|
||||
if let Some(e) = e.downcast_ref::<io::Error>() {
|
||||
if e.kind() == ErrorKind::UnexpectedEof {
|
||||
return;
|
||||
}
|
||||
loop {
|
||||
let request = frontend::wait_for_request(&mut stream).await;
|
||||
match request {
|
||||
Ok(request) => {
|
||||
let _ = tx.send(request).await;
|
||||
}
|
||||
Err(e) => {
|
||||
if let Some(e) = e.downcast_ref::<io::Error>() {
|
||||
if e.kind() == ErrorKind::UnexpectedEof {
|
||||
return;
|
||||
}
|
||||
log::error!("error reading frontend event: {e}");
|
||||
return;
|
||||
}
|
||||
log::error!("error reading frontend event: {e}");
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_frontend_event(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::{net::SocketAddr, time::Duration};
|
||||
use std::{net::SocketAddr, sync::Arc, time::Duration};
|
||||
|
||||
use tokio::{
|
||||
sync::mpsc::{Receiver, Sender},
|
||||
sync::{mpsc::Sender, Notify},
|
||||
task::JoinHandle,
|
||||
};
|
||||
|
||||
@@ -18,15 +18,13 @@ pub fn new(
|
||||
sender_ch: Sender<(Event, SocketAddr)>,
|
||||
emulate_notify: Sender<EmulationEvent>,
|
||||
capture_notify: Sender<CaptureEvent>,
|
||||
mut timer_rx: Receiver<()>,
|
||||
timer_notify: Arc<Notify>,
|
||||
) -> JoinHandle<()> {
|
||||
// timer task
|
||||
let ping_task = tokio::task::spawn_local(async move {
|
||||
loop {
|
||||
// wait for wake up signal
|
||||
let Some(_): Option<()> = timer_rx.recv().await else {
|
||||
break;
|
||||
};
|
||||
timer_notify.notified().await;
|
||||
loop {
|
||||
let receiving = server.state.get() == State::Receiving;
|
||||
let (ping_clients, ping_addrs) = {
|
||||
|
||||
Reference in New Issue
Block a user