mirror of
https://github.com/feschber/lan-mouse.git
synced 2026-04-05 19:31:28 +03:00
fix service exit
This commit is contained in:
@@ -19,8 +19,9 @@ use tokio::{
|
|||||||
use crate::{connect::LanMouseConnection, service::Service};
|
use crate::{connect::LanMouseConnection, service::Service};
|
||||||
|
|
||||||
pub(crate) struct Capture {
|
pub(crate) struct Capture {
|
||||||
|
exit_requested: Rc<Cell<bool>>,
|
||||||
_active: Rc<Cell<Option<CaptureHandle>>>,
|
_active: Rc<Cell<Option<CaptureHandle>>>,
|
||||||
tx: Sender<CaptureRequest>,
|
request_tx: Sender<CaptureRequest>,
|
||||||
task: JoinHandle<()>,
|
task: JoinHandle<()>,
|
||||||
event_rx: Receiver<ICaptureEvent>,
|
event_rx: Receiver<ICaptureEvent>,
|
||||||
}
|
}
|
||||||
@@ -54,33 +55,37 @@ impl Capture {
|
|||||||
conn: LanMouseConnection,
|
conn: LanMouseConnection,
|
||||||
service: Service,
|
service: Service,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let (tx, rx) = channel();
|
let (request_tx, request_rx) = channel();
|
||||||
let (event_tx, event_rx) = channel();
|
let (event_tx, event_rx) = channel();
|
||||||
let active = Rc::new(Cell::new(None));
|
let active = Rc::new(Cell::new(None));
|
||||||
|
let exit_requested = Rc::new(Cell::new(false));
|
||||||
let task = spawn_local(Self::run(
|
let task = spawn_local(Self::run(
|
||||||
active.clone(),
|
active.clone(),
|
||||||
|
exit_requested.clone(),
|
||||||
service,
|
service,
|
||||||
backend,
|
backend,
|
||||||
rx,
|
request_rx,
|
||||||
conn,
|
conn,
|
||||||
event_tx,
|
event_tx,
|
||||||
));
|
));
|
||||||
Self {
|
Self {
|
||||||
_active: active,
|
_active: active,
|
||||||
tx,
|
exit_requested,
|
||||||
|
request_tx,
|
||||||
task,
|
task,
|
||||||
event_rx,
|
event_rx,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn reenable(&self) {
|
pub(crate) fn reenable(&self) {
|
||||||
self.tx
|
self.request_tx
|
||||||
.send(CaptureRequest::Reenable)
|
.send(CaptureRequest::Reenable)
|
||||||
.expect("channel closed");
|
.expect("channel closed");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn terminate(&mut self) {
|
pub(crate) async fn terminate(&mut self) {
|
||||||
self.tx
|
self.exit_requested.replace(true);
|
||||||
|
self.request_tx
|
||||||
.send(CaptureRequest::Terminate)
|
.send(CaptureRequest::Terminate)
|
||||||
.expect("channel closed");
|
.expect("channel closed");
|
||||||
log::debug!("terminating capture");
|
log::debug!("terminating capture");
|
||||||
@@ -90,19 +95,19 @@ impl Capture {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn create(&self, handle: CaptureHandle, pos: lan_mouse_ipc::Position) {
|
pub(crate) fn create(&self, handle: CaptureHandle, pos: lan_mouse_ipc::Position) {
|
||||||
self.tx
|
self.request_tx
|
||||||
.send(CaptureRequest::Create(handle, to_capture_pos(pos)))
|
.send(CaptureRequest::Create(handle, to_capture_pos(pos)))
|
||||||
.expect("channel closed");
|
.expect("channel closed");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn destroy(&self, handle: CaptureHandle) {
|
pub(crate) fn destroy(&self, handle: CaptureHandle) {
|
||||||
self.tx
|
self.request_tx
|
||||||
.send(CaptureRequest::Destroy(handle))
|
.send(CaptureRequest::Destroy(handle))
|
||||||
.expect("channel closed");
|
.expect("channel closed");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn release(&self) {
|
pub(crate) fn release(&self) {
|
||||||
self.tx
|
self.request_tx
|
||||||
.send(CaptureRequest::Release)
|
.send(CaptureRequest::Release)
|
||||||
.expect("channel closed");
|
.expect("channel closed");
|
||||||
}
|
}
|
||||||
@@ -113,9 +118,10 @@ impl Capture {
|
|||||||
|
|
||||||
async fn run(
|
async fn run(
|
||||||
active: Rc<Cell<Option<CaptureHandle>>>,
|
active: Rc<Cell<Option<CaptureHandle>>>,
|
||||||
|
exit_requested: Rc<Cell<bool>>,
|
||||||
service: Service,
|
service: Service,
|
||||||
backend: Option<input_capture::Backend>,
|
backend: Option<input_capture::Backend>,
|
||||||
mut rx: Receiver<CaptureRequest>,
|
mut request_rx: Receiver<CaptureRequest>,
|
||||||
mut conn: LanMouseConnection,
|
mut conn: LanMouseConnection,
|
||||||
mut event_tx: Sender<ICaptureEvent>,
|
mut event_tx: Sender<ICaptureEvent>,
|
||||||
) {
|
) {
|
||||||
@@ -125,18 +131,18 @@ impl Capture {
|
|||||||
&service,
|
&service,
|
||||||
backend,
|
backend,
|
||||||
&mut conn,
|
&mut conn,
|
||||||
&mut rx,
|
&mut request_rx,
|
||||||
&mut event_tx,
|
&mut event_tx,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
log::warn!("input capture exited: {e}");
|
log::warn!("input capture exited: {e}");
|
||||||
}
|
}
|
||||||
event_tx
|
if exit_requested.get() {
|
||||||
.send(ICaptureEvent::CaptureDisabled)
|
break;
|
||||||
.expect("channel closed");
|
}
|
||||||
loop {
|
loop {
|
||||||
match rx.recv().await.expect("channel closed") {
|
match request_rx.recv().await.expect("channel closed") {
|
||||||
CaptureRequest::Reenable => break,
|
CaptureRequest::Reenable => break,
|
||||||
CaptureRequest::Terminate => return,
|
CaptureRequest::Terminate => return,
|
||||||
_ => {}
|
_ => {}
|
||||||
@@ -151,13 +157,13 @@ async fn do_capture(
|
|||||||
service: &Service,
|
service: &Service,
|
||||||
backend: Option<input_capture::Backend>,
|
backend: Option<input_capture::Backend>,
|
||||||
conn: &mut LanMouseConnection,
|
conn: &mut LanMouseConnection,
|
||||||
rx: &mut Receiver<CaptureRequest>,
|
request_rx: &mut Receiver<CaptureRequest>,
|
||||||
event_tx: &mut Sender<ICaptureEvent>,
|
event_tx: &mut Sender<ICaptureEvent>,
|
||||||
) -> Result<(), InputCaptureError> {
|
) -> Result<(), InputCaptureError> {
|
||||||
/* allow cancelling capture request */
|
/* allow cancelling capture request */
|
||||||
let mut capture = tokio::select! {
|
let mut capture = tokio::select! {
|
||||||
r = InputCapture::new(backend) => r?,
|
r = InputCapture::new(backend) => r?,
|
||||||
_ = wait_for_termination(rx) => return Ok(()),
|
_ = wait_for_termination(request_rx) => return Ok(()),
|
||||||
};
|
};
|
||||||
event_tx
|
event_tx
|
||||||
.send(ICaptureEvent::CaptureEnabled)
|
.send(ICaptureEvent::CaptureEnabled)
|
||||||
@@ -179,12 +185,35 @@ async fn do_capture(
|
|||||||
capture.create(handle, to_capture_pos(pos)).await?;
|
capture.create(handle, to_capture_pos(pos)).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let res = do_capture_session(active, &mut capture, conn, event_tx, request_rx, service).await;
|
||||||
|
// FIXME replace with async drop when stabilized
|
||||||
|
let res1 = capture.terminate().await;
|
||||||
|
|
||||||
|
// handle errors
|
||||||
|
res?;
|
||||||
|
res1?;
|
||||||
|
|
||||||
|
event_tx
|
||||||
|
.send(ICaptureEvent::CaptureDisabled)
|
||||||
|
.expect("channel closed");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn do_capture_session(
|
||||||
|
active: &Cell<Option<CaptureHandle>>,
|
||||||
|
capture: &mut InputCapture,
|
||||||
|
conn: &mut LanMouseConnection,
|
||||||
|
event_tx: &Sender<ICaptureEvent>,
|
||||||
|
request_rx: &mut Receiver<CaptureRequest>,
|
||||||
|
service: &Service,
|
||||||
|
) -> Result<(), InputCaptureError> {
|
||||||
let mut state = State::WaitingForAck;
|
let mut state = State::WaitingForAck;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
event = capture.next() => match event {
|
event = capture.next() => match event {
|
||||||
Some(event) => handle_capture_event(active, &service, &mut capture, conn, event?, &mut state, event_tx).await?,
|
Some(event) => handle_capture_event(active, service, capture, conn, event?, &mut state, event_tx).await?,
|
||||||
None => return Ok(()),
|
None => return Ok(()),
|
||||||
},
|
},
|
||||||
(handle, event) = conn.recv() => {
|
(handle, event) = conn.recv() => {
|
||||||
@@ -205,22 +234,20 @@ async fn do_capture(
|
|||||||
// client disconnected
|
// client disconnected
|
||||||
ProtoEvent::Leave(_) => {
|
ProtoEvent::Leave(_) => {
|
||||||
log::info!("releasing capture: left remote client device region");
|
log::info!("releasing capture: left remote client device region");
|
||||||
release_capture(&mut capture, &active).await?;
|
release_capture(capture, active).await?;
|
||||||
},
|
},
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
e = rx.recv() => match e.expect("channel closed") {
|
e = request_rx.recv() => match e.expect("channel closed") {
|
||||||
CaptureRequest::Reenable => { /* already active */ },
|
CaptureRequest::Reenable => { /* already active */ },
|
||||||
CaptureRequest::Release => release_capture(&mut capture, &active).await?,
|
CaptureRequest::Release => release_capture(capture, active).await?,
|
||||||
CaptureRequest::Create(h, p) => capture.create(h, p).await?,
|
CaptureRequest::Create(h, p) => capture.create(h, p).await?,
|
||||||
CaptureRequest::Destroy(h) => capture.destroy(h).await?,
|
CaptureRequest::Destroy(h) => capture.destroy(h).await?,
|
||||||
CaptureRequest::Terminate => break,
|
CaptureRequest::Terminate => break,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
capture.terminate().await?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -258,7 +285,7 @@ async fn handle_capture_event(
|
|||||||
conn: &LanMouseConnection,
|
conn: &LanMouseConnection,
|
||||||
event: (CaptureHandle, CaptureEvent),
|
event: (CaptureHandle, CaptureEvent),
|
||||||
state: &mut State,
|
state: &mut State,
|
||||||
event_tx: &mut Sender<ICaptureEvent>,
|
event_tx: &Sender<ICaptureEvent>,
|
||||||
) -> Result<(), CaptureError> {
|
) -> Result<(), CaptureError> {
|
||||||
let (handle, event) = event;
|
let (handle, event) = event;
|
||||||
log::trace!("({handle}): {event:?}");
|
log::trace!("({handle}): {event:?}");
|
||||||
|
|||||||
@@ -174,6 +174,7 @@ impl Emulation {
|
|||||||
/// discarding events when it is disabled
|
/// discarding events when it is disabled
|
||||||
pub(crate) struct EmulationProxy {
|
pub(crate) struct EmulationProxy {
|
||||||
emulation_active: Rc<Cell<bool>>,
|
emulation_active: Rc<Cell<bool>>,
|
||||||
|
exit_requested: Rc<Cell<bool>>,
|
||||||
request_tx: Sender<ProxyRequest>,
|
request_tx: Sender<ProxyRequest>,
|
||||||
event_rx: Receiver<EmulationEvent>,
|
event_rx: Receiver<EmulationEvent>,
|
||||||
task: JoinHandle<()>,
|
task: JoinHandle<()>,
|
||||||
@@ -191,9 +192,16 @@ impl EmulationProxy {
|
|||||||
let (request_tx, request_rx) = channel();
|
let (request_tx, request_rx) = channel();
|
||||||
let (event_tx, event_rx) = channel();
|
let (event_tx, event_rx) = channel();
|
||||||
let emulation_active = Rc::new(Cell::new(false));
|
let emulation_active = Rc::new(Cell::new(false));
|
||||||
let task = spawn_local(Self::emulation_task(backend, request_rx, event_tx));
|
let exit_requested = Rc::new(Cell::new(false));
|
||||||
|
let task = spawn_local(Self::emulation_task(
|
||||||
|
backend,
|
||||||
|
exit_requested.clone(),
|
||||||
|
request_rx,
|
||||||
|
event_tx,
|
||||||
|
));
|
||||||
Self {
|
Self {
|
||||||
emulation_active,
|
emulation_active,
|
||||||
|
exit_requested,
|
||||||
request_tx,
|
request_tx,
|
||||||
task,
|
task,
|
||||||
event_rx,
|
event_rx,
|
||||||
@@ -228,6 +236,7 @@ impl EmulationProxy {
|
|||||||
|
|
||||||
async fn emulation_task(
|
async fn emulation_task(
|
||||||
backend: Option<input_emulation::Backend>,
|
backend: Option<input_emulation::Backend>,
|
||||||
|
exit_requested: Rc<Cell<bool>>,
|
||||||
mut request_rx: Receiver<ProxyRequest>,
|
mut request_rx: Receiver<ProxyRequest>,
|
||||||
event_tx: Sender<EmulationEvent>,
|
event_tx: Sender<EmulationEvent>,
|
||||||
) {
|
) {
|
||||||
@@ -245,6 +254,9 @@ impl EmulationProxy {
|
|||||||
{
|
{
|
||||||
log::warn!("input emulation exited: {e}");
|
log::warn!("input emulation exited: {e}");
|
||||||
}
|
}
|
||||||
|
if exit_requested.get() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
// wait for reenable request
|
// wait for reenable request
|
||||||
loop {
|
loop {
|
||||||
match request_rx.recv().await.expect("channel closed") {
|
match request_rx.recv().await.expect("channel closed") {
|
||||||
@@ -330,6 +342,7 @@ impl EmulationProxy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn terminate(&mut self) {
|
async fn terminate(&mut self) {
|
||||||
|
self.exit_requested.replace(true);
|
||||||
self.request_tx
|
self.request_tx
|
||||||
.send(ProxyRequest::Terminate)
|
.send(ProxyRequest::Terminate)
|
||||||
.expect("channel closed");
|
.expect("channel closed");
|
||||||
|
|||||||
130
src/service.rs
130
src/service.rs
@@ -171,9 +171,61 @@ impl Service {
|
|||||||
}
|
}
|
||||||
None => break,
|
None => break,
|
||||||
};
|
};
|
||||||
log::debug!("received frontend request: {request:?}");
|
match request {
|
||||||
self.handle_request(&capture, &emulation, request, &resolver);
|
FrontendRequest::EnableCapture => capture.reenable(),
|
||||||
log::debug!("handled frontend request");
|
FrontendRequest::EnableEmulation => emulation.reenable(),
|
||||||
|
FrontendRequest::Create => {
|
||||||
|
self.add_client();
|
||||||
|
}
|
||||||
|
FrontendRequest::Activate(handle, active) => {
|
||||||
|
if active {
|
||||||
|
if let Some(hostname) = self.client_manager.get_hostname(handle) {
|
||||||
|
resolver.resolve(handle, hostname);
|
||||||
|
}
|
||||||
|
self.activate_client(&capture, handle);
|
||||||
|
} else {
|
||||||
|
self.deactivate_client(&capture, handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FrontendRequest::ChangePort(port) => emulation.request_port_change(port),
|
||||||
|
FrontendRequest::Delete(handle) => {
|
||||||
|
self.remove_client(&capture, handle);
|
||||||
|
self.notify_frontend(FrontendEvent::Deleted(handle));
|
||||||
|
}
|
||||||
|
FrontendRequest::Enumerate() => self.enumerate(),
|
||||||
|
FrontendRequest::GetState(handle) => self.broadcast_client(handle),
|
||||||
|
FrontendRequest::UpdateFixIps(handle, fix_ips) => self.update_fix_ips(handle, fix_ips),
|
||||||
|
FrontendRequest::UpdateHostname(handle, host) => {
|
||||||
|
self.update_hostname(handle, host, &resolver)
|
||||||
|
}
|
||||||
|
FrontendRequest::UpdatePort(handle, port) => self.update_port(handle, port),
|
||||||
|
FrontendRequest::UpdatePosition(handle, pos) => {
|
||||||
|
self.update_pos(handle, &capture, pos);
|
||||||
|
}
|
||||||
|
FrontendRequest::ResolveDns(handle) => {
|
||||||
|
if let Some(hostname) = self.client_manager.get_hostname(handle) {
|
||||||
|
resolver.resolve(handle, hostname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FrontendRequest::Sync => {
|
||||||
|
self.enumerate();
|
||||||
|
self.notify_frontend(FrontendEvent::EmulationStatus(self.emulation_status.get()));
|
||||||
|
self.notify_frontend(FrontendEvent::CaptureStatus(self.capture_status.get()));
|
||||||
|
self.notify_frontend(FrontendEvent::PortChanged(self.port.get(), None));
|
||||||
|
self.notify_frontend(FrontendEvent::PublicKeyFingerprint(
|
||||||
|
self.public_key_fingerprint.clone(),
|
||||||
|
));
|
||||||
|
self.notify_frontend(FrontendEvent::AuthorizedUpdated(
|
||||||
|
self.authorized_keys.read().expect("lock").clone(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
FrontendRequest::AuthorizeKey(desc, fp) => {
|
||||||
|
self.add_authorized_key(desc, fp);
|
||||||
|
}
|
||||||
|
FrontendRequest::RemoveAuthorizedKey(key) => {
|
||||||
|
self.remove_authorized_key(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ = self.notifies.frontend_event_pending.notified() => {
|
_ = self.notifies.frontend_event_pending.notified() => {
|
||||||
while let Some(event) = {
|
while let Some(event) = {
|
||||||
@@ -262,10 +314,12 @@ impl Service {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log::info!("terminating service");
|
log::info!("terminating service ...");
|
||||||
|
log::info!("terminating capture ...");
|
||||||
capture.terminate().await;
|
capture.terminate().await;
|
||||||
|
log::info!("terminating emulation ...");
|
||||||
emulation.terminate().await;
|
emulation.terminate().await;
|
||||||
|
log::info!("terminating dns resolver ...");
|
||||||
resolver.terminate().await;
|
resolver.terminate().await;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -324,72 +378,6 @@ impl Service {
|
|||||||
self.notify_frontend(FrontendEvent::Changed(handle));
|
self.notify_frontend(FrontendEvent::Changed(handle));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_request(
|
|
||||||
&self,
|
|
||||||
capture: &Capture,
|
|
||||||
emulation: &Emulation,
|
|
||||||
event: FrontendRequest,
|
|
||||||
dns: &DnsResolver,
|
|
||||||
) -> bool {
|
|
||||||
log::debug!("frontend: {event:?}");
|
|
||||||
match event {
|
|
||||||
FrontendRequest::EnableCapture => capture.reenable(),
|
|
||||||
FrontendRequest::EnableEmulation => emulation.reenable(),
|
|
||||||
FrontendRequest::Create => {
|
|
||||||
self.add_client();
|
|
||||||
}
|
|
||||||
FrontendRequest::Activate(handle, active) => {
|
|
||||||
if active {
|
|
||||||
if let Some(hostname) = self.client_manager.get_hostname(handle) {
|
|
||||||
dns.resolve(handle, hostname);
|
|
||||||
}
|
|
||||||
self.activate_client(capture, handle);
|
|
||||||
} else {
|
|
||||||
self.deactivate_client(capture, handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FrontendRequest::ChangePort(port) => emulation.request_port_change(port),
|
|
||||||
FrontendRequest::Delete(handle) => {
|
|
||||||
self.remove_client(capture, handle);
|
|
||||||
self.notify_frontend(FrontendEvent::Deleted(handle));
|
|
||||||
}
|
|
||||||
FrontendRequest::Enumerate() => self.enumerate(),
|
|
||||||
FrontendRequest::GetState(handle) => self.broadcast_client(handle),
|
|
||||||
FrontendRequest::UpdateFixIps(handle, fix_ips) => self.update_fix_ips(handle, fix_ips),
|
|
||||||
FrontendRequest::UpdateHostname(handle, host) => {
|
|
||||||
self.update_hostname(handle, host, dns)
|
|
||||||
}
|
|
||||||
FrontendRequest::UpdatePort(handle, port) => self.update_port(handle, port),
|
|
||||||
FrontendRequest::UpdatePosition(handle, pos) => {
|
|
||||||
self.update_pos(handle, capture, pos);
|
|
||||||
}
|
|
||||||
FrontendRequest::ResolveDns(handle) => {
|
|
||||||
if let Some(hostname) = self.client_manager.get_hostname(handle) {
|
|
||||||
dns.resolve(handle, hostname);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FrontendRequest::Sync => {
|
|
||||||
self.enumerate();
|
|
||||||
self.notify_frontend(FrontendEvent::EmulationStatus(self.emulation_status.get()));
|
|
||||||
self.notify_frontend(FrontendEvent::CaptureStatus(self.capture_status.get()));
|
|
||||||
self.notify_frontend(FrontendEvent::PortChanged(self.port.get(), None));
|
|
||||||
self.notify_frontend(FrontendEvent::PublicKeyFingerprint(
|
|
||||||
self.public_key_fingerprint.clone(),
|
|
||||||
));
|
|
||||||
self.notify_frontend(FrontendEvent::AuthorizedUpdated(
|
|
||||||
self.authorized_keys.read().expect("lock").clone(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
FrontendRequest::AuthorizeKey(desc, fp) => {
|
|
||||||
self.add_authorized_key(desc, fp);
|
|
||||||
}
|
|
||||||
FrontendRequest::RemoveAuthorizedKey(key) => {
|
|
||||||
self.remove_authorized_key(key);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add_authorized_key(&self, desc: String, fp: String) {
|
fn add_authorized_key(&self, desc: String, fp: String) {
|
||||||
self.authorized_keys.write().expect("lock").insert(fp, desc);
|
self.authorized_keys.write().expect("lock").insert(fp, desc);
|
||||||
self.notify_frontend(FrontendEvent::AuthorizedUpdated(
|
self.notify_frontend(FrontendEvent::AuthorizedUpdated(
|
||||||
|
|||||||
Reference in New Issue
Block a user