mirror of
https://github.com/feschber/lan-mouse.git
synced 2026-04-13 06:51:30 +03:00
simplify service
This commit is contained in:
149
src/service.rs
149
src/service.rs
@@ -23,7 +23,6 @@ use std::{
|
|||||||
};
|
};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use tokio::{process::Command, signal, sync::Notify};
|
use tokio::{process::Command, signal, sync::Notify};
|
||||||
use webrtc_dtls::crypto::Certificate;
|
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum ServiceError {
|
pub enum ServiceError {
|
||||||
@@ -49,12 +48,15 @@ pub struct Incoming {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Service {
|
pub struct Service {
|
||||||
|
capture: Capture,
|
||||||
|
emulation: Emulation,
|
||||||
|
resolver: DnsResolver,
|
||||||
|
frontend_listener: AsyncFrontendListener,
|
||||||
authorized_keys: Arc<RwLock<HashMap<String, String>>>,
|
authorized_keys: Arc<RwLock<HashMap<String, String>>>,
|
||||||
pub(crate) client_manager: ClientManager,
|
pub(crate) client_manager: ClientManager,
|
||||||
port: u16,
|
port: u16,
|
||||||
public_key_fingerprint: String,
|
public_key_fingerprint: String,
|
||||||
frontend_event_pending: Notify,
|
frontend_event_pending: Notify,
|
||||||
pub(crate) config: Config,
|
|
||||||
pending_frontend_events: VecDeque<FrontendEvent>,
|
pending_frontend_events: VecDeque<FrontendEvent>,
|
||||||
capture_status: Status,
|
capture_status: Status,
|
||||||
pub(crate) emulation_status: Status,
|
pub(crate) emulation_status: Status,
|
||||||
@@ -62,7 +64,6 @@ pub struct Service {
|
|||||||
incoming_conns: HashSet<SocketAddr>,
|
incoming_conns: HashSet<SocketAddr>,
|
||||||
/// map from capture handle to connection info
|
/// map from capture handle to connection info
|
||||||
incoming_conn_info: HashMap<ClientHandle, Incoming>,
|
incoming_conn_info: HashMap<ClientHandle, Incoming>,
|
||||||
cert: Certificate,
|
|
||||||
next_trigger_handle: u64,
|
next_trigger_handle: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,12 +92,32 @@ impl Service {
|
|||||||
let cert = crypto::load_or_generate_key_and_cert(&config.cert_path)?;
|
let cert = crypto::load_or_generate_key_and_cert(&config.cert_path)?;
|
||||||
let public_key_fingerprint = crypto::certificate_fingerprint(&cert);
|
let public_key_fingerprint = crypto::certificate_fingerprint(&cert);
|
||||||
|
|
||||||
|
// create frontend communication adapter, exit if already running
|
||||||
|
let frontend_listener = AsyncFrontendListener::new().await?;
|
||||||
|
|
||||||
|
let authorized_keys = Arc::new(RwLock::new(config.authorized_fingerprints.clone()));
|
||||||
|
// listener + connection
|
||||||
|
let listener =
|
||||||
|
LanMouseListener::new(config.port, cert.clone(), authorized_keys.clone()).await?;
|
||||||
|
let conn = LanMouseConnection::new(cert.clone(), client_manager.clone());
|
||||||
|
|
||||||
|
// input capture + emulation
|
||||||
|
let capture_backend = config.capture_backend.map(|b| b.into());
|
||||||
|
let capture = Capture::new(capture_backend, conn, config.release_bind.clone());
|
||||||
|
let emulation_backend = config.emulation_backend.map(|b| b.into());
|
||||||
|
let emulation = Emulation::new(emulation_backend, listener);
|
||||||
|
|
||||||
|
// create dns resolver
|
||||||
|
let resolver = DnsResolver::new()?;
|
||||||
|
|
||||||
let port = config.port;
|
let port = config.port;
|
||||||
let service = Self {
|
let service = Self {
|
||||||
authorized_keys: Arc::new(RwLock::new(config.authorized_fingerprints.clone())),
|
capture,
|
||||||
cert,
|
emulation,
|
||||||
|
frontend_listener,
|
||||||
|
resolver,
|
||||||
|
authorized_keys,
|
||||||
public_key_fingerprint,
|
public_key_fingerprint,
|
||||||
config,
|
|
||||||
client_manager,
|
client_manager,
|
||||||
frontend_event_pending: Default::default(),
|
frontend_event_pending: Default::default(),
|
||||||
port,
|
port,
|
||||||
@@ -111,39 +132,18 @@ impl Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn run(&mut self) -> Result<(), ServiceError> {
|
pub async fn run(&mut self) -> Result<(), ServiceError> {
|
||||||
// create frontend communication adapter, exit if already running
|
|
||||||
let mut frontend_listener = AsyncFrontendListener::new().await?;
|
|
||||||
|
|
||||||
// listener + connection
|
|
||||||
let listener = LanMouseListener::new(
|
|
||||||
self.config.port,
|
|
||||||
self.cert.clone(),
|
|
||||||
self.authorized_keys.clone(),
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
let conn = LanMouseConnection::new(self.cert.clone(), self.client_manager.clone());
|
|
||||||
|
|
||||||
// input capture + emulation
|
|
||||||
let capture_backend = self.config.capture_backend.map(|b| b.into());
|
|
||||||
let mut capture = Capture::new(capture_backend, conn, self.config.release_bind.clone());
|
|
||||||
let emulation_backend = self.config.emulation_backend.map(|b| b.into());
|
|
||||||
let mut emulation = Emulation::new(emulation_backend, listener);
|
|
||||||
|
|
||||||
// create dns resolver
|
|
||||||
let mut resolver = DnsResolver::new()?;
|
|
||||||
|
|
||||||
for handle in self.client_manager.active_clients() {
|
for handle in self.client_manager.active_clients() {
|
||||||
if let Some(hostname) = self.client_manager.get_hostname(handle) {
|
if let Some(hostname) = self.client_manager.get_hostname(handle) {
|
||||||
resolver.resolve(handle, hostname);
|
self.resolver.resolve(handle, hostname);
|
||||||
}
|
}
|
||||||
if let Some(pos) = self.client_manager.get_pos(handle) {
|
if let Some(pos) = self.client_manager.get_pos(handle) {
|
||||||
capture.create(handle, pos, CaptureType::Default);
|
self.capture.create(handle, pos, CaptureType::Default);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
request = frontend_listener.next() => {
|
request = self.frontend_listener.next() => {
|
||||||
let request = match request {
|
let request = match request {
|
||||||
Some(Ok(r)) => r,
|
Some(Ok(r)) => r,
|
||||||
Some(Err(e)) => {
|
Some(Err(e)) => {
|
||||||
@@ -153,45 +153,45 @@ impl Service {
|
|||||||
None => break,
|
None => break,
|
||||||
};
|
};
|
||||||
match request {
|
match request {
|
||||||
FrontendRequest::EnableCapture => capture.reenable(),
|
FrontendRequest::EnableCapture => self.capture.reenable(),
|
||||||
FrontendRequest::EnableEmulation => emulation.reenable(),
|
FrontendRequest::EnableEmulation => self.emulation.reenable(),
|
||||||
FrontendRequest::Create => {
|
FrontendRequest::Create => {
|
||||||
self.add_client();
|
self.add_client();
|
||||||
}
|
}
|
||||||
FrontendRequest::Activate(handle, active) => {
|
FrontendRequest::Activate(handle, active) => {
|
||||||
if active {
|
if active {
|
||||||
if let Some(hostname) = self.client_manager.get_hostname(handle) {
|
if let Some(hostname) = self.client_manager.get_hostname(handle) {
|
||||||
resolver.resolve(handle, hostname);
|
self.resolver.resolve(handle, hostname);
|
||||||
}
|
}
|
||||||
self.activate_client(&capture, handle);
|
self.activate_client(handle);
|
||||||
} else {
|
} else {
|
||||||
self.deactivate_client(&capture, handle);
|
self.deactivate_client(handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FrontendRequest::ChangePort(port) => {
|
FrontendRequest::ChangePort(port) => {
|
||||||
if self.port != port {
|
if self.port != port {
|
||||||
emulation.request_port_change(port);
|
self.emulation.request_port_change(port);
|
||||||
} else {
|
} else {
|
||||||
self.notify_frontend(FrontendEvent::PortChanged(self.port, None));
|
self.notify_frontend(FrontendEvent::PortChanged(self.port, None));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FrontendRequest::Delete(handle) => {
|
FrontendRequest::Delete(handle) => {
|
||||||
self.remove_client(&capture, handle);
|
self.remove_client(handle);
|
||||||
self.notify_frontend(FrontendEvent::Deleted(handle));
|
self.notify_frontend(FrontendEvent::Deleted(handle));
|
||||||
}
|
}
|
||||||
FrontendRequest::Enumerate() => self.enumerate(),
|
FrontendRequest::Enumerate() => self.enumerate(),
|
||||||
FrontendRequest::GetState(handle) => self.broadcast_client(handle),
|
FrontendRequest::GetState(handle) => self.broadcast_client(handle),
|
||||||
FrontendRequest::UpdateFixIps(handle, fix_ips) => self.update_fix_ips(handle, fix_ips),
|
FrontendRequest::UpdateFixIps(handle, fix_ips) => self.update_fix_ips(handle, fix_ips),
|
||||||
FrontendRequest::UpdateHostname(handle, host) => {
|
FrontendRequest::UpdateHostname(handle, host) => {
|
||||||
self.update_hostname(handle, host, &resolver)
|
self.update_hostname(handle, host)
|
||||||
}
|
}
|
||||||
FrontendRequest::UpdatePort(handle, port) => self.update_port(handle, port),
|
FrontendRequest::UpdatePort(handle, port) => self.update_port(handle, port),
|
||||||
FrontendRequest::UpdatePosition(handle, pos) => {
|
FrontendRequest::UpdatePosition(handle, pos) => {
|
||||||
self.update_pos(handle, &capture, pos);
|
self.update_pos(handle, pos);
|
||||||
}
|
}
|
||||||
FrontendRequest::ResolveDns(handle) => {
|
FrontendRequest::ResolveDns(handle) => {
|
||||||
if let Some(hostname) = self.client_manager.get_hostname(handle) {
|
if let Some(hostname) = self.client_manager.get_hostname(handle) {
|
||||||
resolver.resolve(handle, hostname);
|
self.resolver.resolve(handle, hostname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FrontendRequest::Sync => {
|
FrontendRequest::Sync => {
|
||||||
@@ -215,14 +215,14 @@ impl Service {
|
|||||||
}
|
}
|
||||||
_ = self.frontend_event_pending.notified() => {
|
_ = self.frontend_event_pending.notified() => {
|
||||||
while let Some(event) = self.pending_frontend_events.pop_front() {
|
while let Some(event) = self.pending_frontend_events.pop_front() {
|
||||||
frontend_listener.broadcast(event).await;
|
self.frontend_listener.broadcast(event).await;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
event = emulation.event() => match event {
|
event = self.emulation.event() => match event {
|
||||||
EmulationEvent::Connected { addr, pos, fingerprint } => {
|
EmulationEvent::Connected { addr, pos, fingerprint } => {
|
||||||
// check if already registered
|
// check if already registered
|
||||||
if !self.incoming_conns.contains(&addr) {
|
if !self.incoming_conns.contains(&addr) {
|
||||||
self.add_incoming(addr, pos, fingerprint.clone(), &capture);
|
self.add_incoming(addr, pos, fingerprint.clone());
|
||||||
self.notify_frontend(FrontendEvent::IncomingConnected(fingerprint, addr, pos));
|
self.notify_frontend(FrontendEvent::IncomingConnected(fingerprint, addr, pos));
|
||||||
} else {
|
} else {
|
||||||
let handle = self
|
let handle = self
|
||||||
@@ -243,15 +243,15 @@ impl Service {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if changed {
|
if changed {
|
||||||
self.remove_incoming(addr, &capture);
|
self.remove_incoming(addr);
|
||||||
self.add_incoming(addr, pos, fingerprint.clone(), &capture);
|
self.add_incoming(addr, pos, fingerprint.clone());
|
||||||
self.notify_frontend(FrontendEvent::IncomingDisconnected(addr));
|
self.notify_frontend(FrontendEvent::IncomingDisconnected(addr));
|
||||||
self.notify_frontend(FrontendEvent::IncomingConnected(fingerprint, addr, pos));
|
self.notify_frontend(FrontendEvent::IncomingConnected(fingerprint, addr, pos));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EmulationEvent::Disconnected { addr } => {
|
EmulationEvent::Disconnected { addr } => {
|
||||||
if let Some(addr) = self.remove_incoming(addr, &capture) {
|
if let Some(addr) = self.remove_incoming(addr) {
|
||||||
self.notify_frontend(FrontendEvent::IncomingDisconnected(addr));
|
self.notify_frontend(FrontendEvent::IncomingDisconnected(addr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -270,14 +270,14 @@ impl Service {
|
|||||||
self.emulation_status = Status::Enabled;
|
self.emulation_status = Status::Enabled;
|
||||||
self.notify_frontend(FrontendEvent::EmulationStatus(Status::Enabled));
|
self.notify_frontend(FrontendEvent::EmulationStatus(Status::Enabled));
|
||||||
},
|
},
|
||||||
EmulationEvent::ReleaseNotify => capture.release(),
|
EmulationEvent::ReleaseNotify => self.capture.release(),
|
||||||
},
|
},
|
||||||
event = capture.event() => match event {
|
event = self.capture.event() => match event {
|
||||||
ICaptureEvent::CaptureBegin(handle) => {
|
ICaptureEvent::CaptureBegin(handle) => {
|
||||||
// we entered the capture zone for an incoming connection
|
// we entered the capture zone for an incoming connection
|
||||||
// => notify it that its capture should be released
|
// => notify it that its capture should be released
|
||||||
if let Some(incoming) = self.incoming_conn_info.get(&handle) {
|
if let Some(incoming) = self.incoming_conn_info.get(&handle) {
|
||||||
emulation.send_leave_event(incoming.addr);
|
self.emulation.send_leave_event(incoming.addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ICaptureEvent::CaptureDisabled => {
|
ICaptureEvent::CaptureDisabled => {
|
||||||
@@ -293,7 +293,7 @@ impl Service {
|
|||||||
self.spawn_hook_command(handle)
|
self.spawn_hook_command(handle)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
event = resolver.event() => match event {
|
event = self.resolver.event() => match event {
|
||||||
DnsEvent::Resolving(handle) => self.set_resolving(handle, true),
|
DnsEvent::Resolving(handle) => self.set_resolving(handle, true),
|
||||||
DnsEvent::Resolved(handle, hostname, ips) => {
|
DnsEvent::Resolved(handle, hostname, ips) => {
|
||||||
self.set_resolving(handle, false);
|
self.set_resolving(handle, false);
|
||||||
@@ -315,27 +315,21 @@ impl Service {
|
|||||||
|
|
||||||
log::info!("terminating service ...");
|
log::info!("terminating service ...");
|
||||||
log::info!("terminating capture ...");
|
log::info!("terminating capture ...");
|
||||||
capture.terminate().await;
|
self.capture.terminate().await;
|
||||||
log::info!("terminating emulation ...");
|
log::info!("terminating emulation ...");
|
||||||
emulation.terminate().await;
|
self.emulation.terminate().await;
|
||||||
log::info!("terminating dns resolver ...");
|
log::info!("terminating dns resolver ...");
|
||||||
resolver.terminate().await;
|
self.resolver.terminate().await;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) const ENTER_HANDLE_BEGIN: u64 = u64::MAX / 2 + 1;
|
pub(crate) const ENTER_HANDLE_BEGIN: u64 = u64::MAX / 2 + 1;
|
||||||
|
|
||||||
fn add_incoming(
|
fn add_incoming(&mut self, addr: SocketAddr, pos: Position, fingerprint: String) {
|
||||||
&mut self,
|
|
||||||
addr: SocketAddr,
|
|
||||||
pos: Position,
|
|
||||||
fingerprint: String,
|
|
||||||
capture: &Capture,
|
|
||||||
) {
|
|
||||||
let handle = Self::ENTER_HANDLE_BEGIN + self.next_trigger_handle;
|
let handle = Self::ENTER_HANDLE_BEGIN + self.next_trigger_handle;
|
||||||
self.next_trigger_handle += 1;
|
self.next_trigger_handle += 1;
|
||||||
capture.create(handle, pos, CaptureType::EnterOnly);
|
self.capture.create(handle, pos, CaptureType::EnterOnly);
|
||||||
self.incoming_conns.insert(addr);
|
self.incoming_conns.insert(addr);
|
||||||
self.incoming_conn_info.insert(
|
self.incoming_conn_info.insert(
|
||||||
handle,
|
handle,
|
||||||
@@ -347,13 +341,13 @@ impl Service {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_incoming(&mut self, addr: SocketAddr, capture: &Capture) -> Option<SocketAddr> {
|
fn remove_incoming(&mut self, addr: SocketAddr) -> Option<SocketAddr> {
|
||||||
let handle = self
|
let handle = self
|
||||||
.incoming_conn_info
|
.incoming_conn_info
|
||||||
.iter()
|
.iter()
|
||||||
.find(|(_, incoming)| incoming.addr == addr)
|
.find(|(_, incoming)| incoming.addr == addr)
|
||||||
.map(|(k, _)| *k)?;
|
.map(|(k, _)| *k)?;
|
||||||
capture.destroy(handle);
|
self.capture.destroy(handle);
|
||||||
self.incoming_conns.remove(&addr);
|
self.incoming_conns.remove(&addr);
|
||||||
self.incoming_conn_info
|
self.incoming_conn_info
|
||||||
.remove(&handle)
|
.remove(&handle)
|
||||||
@@ -394,16 +388,16 @@ impl Service {
|
|||||||
handle
|
handle
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deactivate_client(&mut self, capture: &Capture, handle: ClientHandle) {
|
fn deactivate_client(&mut self, handle: ClientHandle) {
|
||||||
log::debug!("deactivating client {handle}");
|
log::debug!("deactivating client {handle}");
|
||||||
if self.client_manager.deactivate_client(handle) {
|
if self.client_manager.deactivate_client(handle) {
|
||||||
capture.destroy(handle);
|
self.capture.destroy(handle);
|
||||||
self.client_updated(handle);
|
self.client_updated(handle);
|
||||||
log::info!("deactivated client {handle}");
|
log::info!("deactivated client {handle}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn activate_client(&mut self, capture: &Capture, handle: ClientHandle) {
|
fn activate_client(&mut self, handle: ClientHandle) {
|
||||||
log::debug!("activating client");
|
log::debug!("activating client");
|
||||||
/* deactivate potential other client at this position */
|
/* deactivate potential other client at this position */
|
||||||
let Some(pos) = self.client_manager.get_pos(handle) else {
|
let Some(pos) = self.client_manager.get_pos(handle) else {
|
||||||
@@ -412,26 +406,26 @@ impl Service {
|
|||||||
|
|
||||||
if let Some(other) = self.client_manager.client_at(pos) {
|
if let Some(other) = self.client_manager.client_at(pos) {
|
||||||
if other != handle {
|
if other != handle {
|
||||||
self.deactivate_client(capture, other);
|
self.deactivate_client(other);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* activate the client */
|
/* activate the client */
|
||||||
if self.client_manager.activate_client(handle) {
|
if self.client_manager.activate_client(handle) {
|
||||||
/* notify capture and frontends */
|
/* notify capture and frontends */
|
||||||
capture.create(handle, pos, CaptureType::Default);
|
self.capture.create(handle, pos, CaptureType::Default);
|
||||||
self.client_updated(handle);
|
self.client_updated(handle);
|
||||||
log::info!("activated client {handle} ({pos})");
|
log::info!("activated client {handle} ({pos})");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_client(&self, capture: &Capture, handle: ClientHandle) {
|
fn remove_client(&self, handle: ClientHandle) {
|
||||||
if let Some(true) = self
|
if let Some(true) = self
|
||||||
.client_manager
|
.client_manager
|
||||||
.remove_client(handle)
|
.remove_client(handle)
|
||||||
.map(|(_, s)| s.active)
|
.map(|(_, s)| s.active)
|
||||||
{
|
{
|
||||||
capture.destroy(handle);
|
self.capture.destroy(handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -445,15 +439,10 @@ impl Service {
|
|||||||
self.client_updated(handle);
|
self.client_updated(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_hostname(
|
fn update_hostname(&mut self, handle: ClientHandle, hostname: Option<String>) {
|
||||||
&mut self,
|
|
||||||
handle: ClientHandle,
|
|
||||||
hostname: Option<String>,
|
|
||||||
dns: &DnsResolver,
|
|
||||||
) {
|
|
||||||
if self.client_manager.set_hostname(handle, hostname.clone()) {
|
if self.client_manager.set_hostname(handle, hostname.clone()) {
|
||||||
if let Some(hostname) = hostname {
|
if let Some(hostname) = hostname {
|
||||||
dns.resolve(handle, hostname);
|
self.resolver.resolve(handle, hostname);
|
||||||
}
|
}
|
||||||
self.client_updated(handle);
|
self.client_updated(handle);
|
||||||
}
|
}
|
||||||
@@ -463,11 +452,11 @@ impl Service {
|
|||||||
self.client_manager.set_port(handle, port);
|
self.client_manager.set_port(handle, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_pos(&mut self, handle: ClientHandle, capture: &Capture, pos: Position) {
|
fn update_pos(&mut self, handle: ClientHandle, pos: Position) {
|
||||||
// update state in event input emulator & input capture
|
// update state in event input emulator & input capture
|
||||||
if self.client_manager.set_pos(handle, pos) {
|
if self.client_manager.set_pos(handle, pos) {
|
||||||
self.deactivate_client(capture, handle);
|
self.deactivate_client(handle);
|
||||||
self.activate_client(capture, handle);
|
self.activate_client(handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user