mirror of
https://github.com/feschber/lan-mouse.git
synced 2026-04-15 01:01:27 +03:00
fingerprint add ui mockup
This commit is contained in:
68
lan-mouse-gtk/resources/fingerprint_window.ui
Normal file
68
lan-mouse-gtk/resources/fingerprint_window.ui
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<interface>
|
||||||
|
<requires lib="gtk" version="4.0"/>
|
||||||
|
<requires lib="libadwaita" version="1.0"/>
|
||||||
|
<template class="FingerprintWindow" parent="AdwWindow">
|
||||||
|
<property name="modal">True</property>
|
||||||
|
<property name="width-request">880</property>
|
||||||
|
<property name="default-width">880</property>
|
||||||
|
<property name="default-height">240</property>
|
||||||
|
<property name="title" translatable="yes">Add Public Key Fingerprint</property>
|
||||||
|
<property name="content">
|
||||||
|
<object class="AdwToolbarView">
|
||||||
|
<child type="top">
|
||||||
|
<object class="AdwHeaderBar"/>
|
||||||
|
</child>
|
||||||
|
<property name="content">
|
||||||
|
<object class="AdwClamp">
|
||||||
|
<property name="maximum-size">770</property>
|
||||||
|
<property name="tightening-threshold">0</property>
|
||||||
|
<property name="child">
|
||||||
|
<object class="GtkBox">
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<property name="spacing">18</property>
|
||||||
|
<child>
|
||||||
|
<object class="AdwPreferencesGroup">
|
||||||
|
<child>
|
||||||
|
<object class="AdwActionRow">
|
||||||
|
<property name="title" translatable="yes">fingerprint</property>
|
||||||
|
<property name="child">
|
||||||
|
<object class="GtkText" id="text">
|
||||||
|
<property name="margin-top">10</property>
|
||||||
|
<property name="margin-bottom">10</property>
|
||||||
|
<property name="margin-start">10</property>
|
||||||
|
<property name="margin-end">10</property>
|
||||||
|
<property name="enable-undo">True</property>
|
||||||
|
<property name="hexpand">True</property>
|
||||||
|
<property name="vexpand">True</property>
|
||||||
|
<property name="max-length">0</property>
|
||||||
|
</object>
|
||||||
|
</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox">
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<property name="halign">center</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton">
|
||||||
|
<property name="label" translatable="yes">Confirm</property>
|
||||||
|
<property name="can-shrink">True</property>
|
||||||
|
<style>
|
||||||
|
<class name="pill"/>
|
||||||
|
<class name="suggested-action"/>
|
||||||
|
</style>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</property>
|
||||||
|
</object>
|
||||||
|
</property>
|
||||||
|
</object>
|
||||||
|
</property>
|
||||||
|
</template>
|
||||||
|
</interface>
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
<gresources>
|
<gresources>
|
||||||
<gresource prefix="/de/feschber/LanMouse">
|
<gresource prefix="/de/feschber/LanMouse">
|
||||||
<file compressed="true" preprocess="xml-stripblanks">window.ui</file>
|
<file compressed="true" preprocess="xml-stripblanks">window.ui</file>
|
||||||
|
<file compressed="true" preprocess="xml-stripblanks">fingerprint_window.ui</file>
|
||||||
<file compressed="true" preprocess="xml-stripblanks">client_row.ui</file>
|
<file compressed="true" preprocess="xml-stripblanks">client_row.ui</file>
|
||||||
</gresource>
|
</gresource>
|
||||||
<gresource prefix="/de/feschber/LanMouse/icons">
|
<gresource prefix="/de/feschber/LanMouse/icons">
|
||||||
|
|||||||
24
lan-mouse-gtk/src/fingerprint_window.rs
Normal file
24
lan-mouse-gtk/src/fingerprint_window.rs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
mod imp;
|
||||||
|
|
||||||
|
use adw::prelude::*;
|
||||||
|
use adw::subclass::prelude::*;
|
||||||
|
use glib::{clone, Object};
|
||||||
|
use gtk::{
|
||||||
|
gio,
|
||||||
|
glib::{self, closure_local},
|
||||||
|
ListBox, NoSelection,
|
||||||
|
};
|
||||||
|
|
||||||
|
glib::wrapper! {
|
||||||
|
pub struct FingerprintWindow(ObjectSubclass<imp::FingerprintWindow>)
|
||||||
|
@extends adw::Window, gtk::Window, gtk::Widget,
|
||||||
|
@implements gio::ActionGroup, gio::ActionMap, gtk::Accessible, gtk::Buildable,
|
||||||
|
gtk::ConstraintTarget, gtk::Native, gtk::Root, gtk::ShortcutManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FingerprintWindow {
|
||||||
|
pub(crate) fn new() -> Self {
|
||||||
|
let window: Self = Object::builder().build();
|
||||||
|
window
|
||||||
|
}
|
||||||
|
}
|
||||||
45
lan-mouse-gtk/src/fingerprint_window/imp.rs
Normal file
45
lan-mouse-gtk/src/fingerprint_window/imp.rs
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
use adw::subclass::prelude::*;
|
||||||
|
use glib::subclass::InitializingObject;
|
||||||
|
use gtk::{glib, template_callbacks, CompositeTemplate, Entry};
|
||||||
|
|
||||||
|
#[derive(CompositeTemplate, Default)]
|
||||||
|
#[template(resource = "/de/feschber/LanMouse/fingerprint_window.ui")]
|
||||||
|
pub struct FingerprintWindow {
|
||||||
|
// #[template_child]
|
||||||
|
// pub fingerprint_entry: TemplateChild<Entry>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[glib::object_subclass]
|
||||||
|
impl ObjectSubclass for FingerprintWindow {
|
||||||
|
const NAME: &'static str = "FingerprintWindow";
|
||||||
|
const ABSTRACT: bool = false;
|
||||||
|
|
||||||
|
type Type = super::FingerprintWindow;
|
||||||
|
type ParentType = adw::Window;
|
||||||
|
|
||||||
|
fn class_init(klass: &mut Self::Class) {
|
||||||
|
klass.bind_template();
|
||||||
|
klass.bind_template_callbacks();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn instance_init(obj: &InitializingObject<Self>) {
|
||||||
|
obj.init_template();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[template_callbacks]
|
||||||
|
impl FingerprintWindow {
|
||||||
|
// #[template_callback]
|
||||||
|
// fn handle_confirm() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ObjectImpl for FingerprintWindow {
|
||||||
|
fn constructed(&self) {
|
||||||
|
self.parent_constructed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WidgetImpl for FingerprintWindow {}
|
||||||
|
impl WindowImpl for FingerprintWindow {}
|
||||||
|
impl ApplicationWindowImpl for FingerprintWindow {}
|
||||||
|
impl AdwWindowImpl for FingerprintWindow {}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
mod client_object;
|
mod client_object;
|
||||||
mod client_row;
|
mod client_row;
|
||||||
|
mod fingerprint_window;
|
||||||
mod window;
|
mod window;
|
||||||
|
|
||||||
use std::{env, process, str};
|
use std::{env, process, str};
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use glib::{clone, Object};
|
|||||||
use gtk::{
|
use gtk::{
|
||||||
gio,
|
gio,
|
||||||
glib::{self, closure_local},
|
glib::{self, closure_local},
|
||||||
ListBox, NoSelection,
|
ListBox, NoSelection, Widget,
|
||||||
};
|
};
|
||||||
|
|
||||||
use lan_mouse_ipc::{
|
use lan_mouse_ipc::{
|
||||||
@@ -14,6 +14,8 @@ use lan_mouse_ipc::{
|
|||||||
DEFAULT_PORT,
|
DEFAULT_PORT,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::fingerprint_window::FingerprintWindow;
|
||||||
|
|
||||||
use super::{client_object::ClientObject, client_row::ClientRow};
|
use super::{client_object::ClientObject, client_row::ClientRow};
|
||||||
|
|
||||||
glib::wrapper! {
|
glib::wrapper! {
|
||||||
@@ -286,6 +288,16 @@ impl Window {
|
|||||||
self.request(FrontendRequest::Delete(client.handle()));
|
self.request(FrontendRequest::Delete(client.handle()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn open_fingerprint_dialog(&self) {
|
||||||
|
let window = FingerprintWindow::new();
|
||||||
|
window.set_transient_for(Some(self));
|
||||||
|
window.present();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn request_fingerprint_add(&self, fp: String) {
|
||||||
|
self.request(FrontendRequest::FingerprintAdd(fp));
|
||||||
|
}
|
||||||
|
|
||||||
pub fn request(&self, request: FrontendRequest) {
|
pub fn request(&self, request: FrontendRequest) {
|
||||||
let mut requester = self.imp().frontend_request_writer.borrow_mut();
|
let mut requester = self.imp().frontend_request_writer.borrow_mut();
|
||||||
let requester = requester.as_mut().unwrap();
|
let requester = requester.as_mut().unwrap();
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ impl Window {
|
|||||||
|
|
||||||
#[template_callback]
|
#[template_callback]
|
||||||
fn handle_add_cert_fingerprint(&self, _button: &Button) {
|
fn handle_add_cert_fingerprint(&self, _button: &Button) {
|
||||||
log::info!("TODO: impl add certificate fingerprint");
|
self.obj().open_fingerprint_dialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_port(&self, port: u16) {
|
pub fn set_port(&self, port: u16) {
|
||||||
|
|||||||
@@ -65,6 +65,17 @@ pub enum Position {
|
|||||||
Bottom,
|
Bottom,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Position {
|
||||||
|
pub fn opposite(&self) -> Self {
|
||||||
|
match self {
|
||||||
|
Position::Left => Position::Right,
|
||||||
|
Position::Right => Position::Left,
|
||||||
|
Position::Top => Position::Bottom,
|
||||||
|
Position::Bottom => Position::Top,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
#[error("not a valid position: {pos}")]
|
#[error("not a valid position: {pos}")]
|
||||||
pub struct PositionParseError {
|
pub struct PositionParseError {
|
||||||
@@ -218,6 +229,10 @@ pub enum FrontendRequest {
|
|||||||
EnableEmulation,
|
EnableEmulation,
|
||||||
/// synchronize all state
|
/// synchronize all state
|
||||||
Sync,
|
Sync,
|
||||||
|
/// authorize fingerprint
|
||||||
|
FingerprintAdd(String),
|
||||||
|
/// remove fingerprint
|
||||||
|
FingerprintRemove(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize)]
|
#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize)]
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ impl Display for Position {
|
|||||||
/// main lan-mouse protocol event type
|
/// main lan-mouse protocol event type
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub enum ProtoEvent {
|
pub enum ProtoEvent {
|
||||||
/// notify a client that the cursor entered its region
|
/// notify a client that the cursor entered its region at the given position
|
||||||
/// [`ProtoEvent::Ack`] with the same serial is used for synchronization between devices
|
/// [`ProtoEvent::Ack`] with the same serial is used for synchronization between devices
|
||||||
Enter(Position),
|
Enter(Position),
|
||||||
/// notify a client that the cursor left its region
|
/// notify a client that the cursor left its region
|
||||||
|
|||||||
@@ -47,9 +47,9 @@ impl Capture {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn create(&self, handle: CaptureHandle, pos: Position) {
|
pub(crate) fn create(&self, handle: CaptureHandle, pos: lan_mouse_ipc::Position) {
|
||||||
self.tx
|
self.tx
|
||||||
.send(CaptureRequest::Create(handle, pos))
|
.send(CaptureRequest::Create(handle, to_capture_pos(pos)))
|
||||||
.expect("channel closed");
|
.expect("channel closed");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,11 +100,16 @@ async fn do_capture(
|
|||||||
};
|
};
|
||||||
server.set_capture_status(Status::Enabled);
|
server.set_capture_status(Status::Enabled);
|
||||||
|
|
||||||
let clients = server.active_clients();
|
let clients = server.client_manager.active_clients();
|
||||||
let clients = clients
|
let clients = clients.iter().copied().map(|handle| {
|
||||||
.iter()
|
(
|
||||||
.copied()
|
handle,
|
||||||
.map(|handle| (handle, server.get_pos(handle).expect("no such client")));
|
server
|
||||||
|
.client_manager
|
||||||
|
.get_pos(handle)
|
||||||
|
.expect("no such client"),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
/* create barriers for active clients */
|
/* create barriers for active clients */
|
||||||
for (handle, pos) in clients {
|
for (handle, pos) in clients {
|
||||||
@@ -201,7 +206,7 @@ async fn handle_capture_event(
|
|||||||
return release_capture(capture, server).await;
|
return release_capture(capture, server).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
if capture.keys_pressed(&server.release_bind) {
|
if capture.keys_pressed(&server.config.release_bind) {
|
||||||
log::info!("releasing capture: release-bind pressed");
|
log::info!("releasing capture: release-bind pressed");
|
||||||
return release_capture(capture, server).await;
|
return release_capture(capture, server).await;
|
||||||
}
|
}
|
||||||
@@ -214,11 +219,16 @@ async fn handle_capture_event(
|
|||||||
spawn_hook_command(server, handle);
|
spawn_hook_command(server, handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let pos = match server.client_manager.get_pos(handle) {
|
||||||
|
Some(pos) => to_proto_pos(pos.opposite()),
|
||||||
|
None => return release_capture(capture, server).await,
|
||||||
|
};
|
||||||
|
|
||||||
let event = match event {
|
let event = match event {
|
||||||
CaptureEvent::Begin => ProtoEvent::Enter(lan_mouse_proto::Position::Left),
|
CaptureEvent::Begin => ProtoEvent::Enter(pos),
|
||||||
CaptureEvent::Input(e) => match state {
|
CaptureEvent::Input(e) => match state {
|
||||||
// connection not acknowledged, repeat `Enter` event
|
// connection not acknowledged, repeat `Enter` event
|
||||||
State::WaitingForAck => ProtoEvent::Enter(lan_mouse_proto::Position::Left),
|
State::WaitingForAck => ProtoEvent::Enter(pos),
|
||||||
_ => ProtoEvent::Input(e),
|
_ => ProtoEvent::Input(e),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -245,13 +255,17 @@ fn to_capture_pos(pos: lan_mouse_ipc::Position) -> input_capture::Position {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn to_proto_pos(pos: lan_mouse_ipc::Position) -> lan_mouse_proto::Position {
|
||||||
|
match pos {
|
||||||
|
lan_mouse_ipc::Position::Left => lan_mouse_proto::Position::Left,
|
||||||
|
lan_mouse_ipc::Position::Right => lan_mouse_proto::Position::Right,
|
||||||
|
lan_mouse_ipc::Position::Top => lan_mouse_proto::Position::Top,
|
||||||
|
lan_mouse_ipc::Position::Bottom => lan_mouse_proto::Position::Bottom,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn spawn_hook_command(server: &Server, handle: ClientHandle) {
|
fn spawn_hook_command(server: &Server, handle: ClientHandle) {
|
||||||
let Some(cmd) = server
|
let Some(cmd) = server.client_manager.get_enter_cmd(handle) else {
|
||||||
.client_manager
|
|
||||||
.borrow()
|
|
||||||
.get(handle)
|
|
||||||
.and_then(|(c, _)| c.cmd.clone())
|
|
||||||
else {
|
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
tokio::task::spawn_local(async move {
|
tokio::task::spawn_local(async move {
|
||||||
|
|||||||
223
src/client.rs
223
src/client.rs
@@ -1,18 +1,63 @@
|
|||||||
use std::net::SocketAddr;
|
use std::{
|
||||||
|
cell::RefCell,
|
||||||
|
collections::HashSet,
|
||||||
|
net::{IpAddr, SocketAddr},
|
||||||
|
rc::Rc,
|
||||||
|
};
|
||||||
|
|
||||||
use slab::Slab;
|
use slab::Slab;
|
||||||
|
|
||||||
use lan_mouse_ipc::{ClientConfig, ClientHandle, ClientState, Position};
|
use lan_mouse_ipc::{ClientConfig, ClientHandle, ClientState, Position};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Clone, Default)]
|
||||||
pub struct ClientManager {
|
pub struct ClientManager {
|
||||||
clients: Slab<(ClientConfig, ClientState)>,
|
clients: Rc<RefCell<Slab<(ClientConfig, ClientState)>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClientManager {
|
impl ClientManager {
|
||||||
/// add a new client to this manager
|
/// add a new client to this manager
|
||||||
pub fn add_client(&mut self) -> ClientHandle {
|
pub fn add_client(&self) -> ClientHandle {
|
||||||
self.clients.insert(Default::default()) as ClientHandle
|
self.clients.borrow_mut().insert(Default::default()) as ClientHandle
|
||||||
|
}
|
||||||
|
|
||||||
|
/// set the config of the given client
|
||||||
|
pub fn set_config(&self, handle: ClientHandle, config: ClientConfig) {
|
||||||
|
if let Some((c, _)) = self.clients.borrow_mut().get_mut(handle as usize) {
|
||||||
|
*c = config;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// set the state of the given client
|
||||||
|
pub fn set_state(&self, handle: ClientHandle, state: ClientState) {
|
||||||
|
if let Some((_, s)) = self.clients.borrow_mut().get_mut(handle as usize) {
|
||||||
|
*s = state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// activate the given client
|
||||||
|
/// returns, whether the client was activated
|
||||||
|
pub fn activate_client(&self, handle: ClientHandle) -> bool {
|
||||||
|
let mut clients = self.clients.borrow_mut();
|
||||||
|
match clients.get_mut(handle as usize) {
|
||||||
|
Some((_, s)) if s.active == false => {
|
||||||
|
s.active = true;
|
||||||
|
true
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// deactivate the given client
|
||||||
|
/// returns, whether the client was deactivated
|
||||||
|
pub fn deactivate_client(&self, handle: ClientHandle) -> bool {
|
||||||
|
let mut clients = self.clients.borrow_mut();
|
||||||
|
match clients.get_mut(handle as usize) {
|
||||||
|
Some((_, s)) if s.active => {
|
||||||
|
s.active = false;
|
||||||
|
true
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// find a client by its address
|
/// find a client by its address
|
||||||
@@ -20,6 +65,7 @@ impl ClientManager {
|
|||||||
// since there shouldn't be more than a handful of clients at any given
|
// since there shouldn't be more than a handful of clients at any given
|
||||||
// time this is likely faster than using a HashMap
|
// time this is likely faster than using a HashMap
|
||||||
self.clients
|
self.clients
|
||||||
|
.borrow()
|
||||||
.iter()
|
.iter()
|
||||||
.find_map(|(k, (_, s))| {
|
.find_map(|(k, (_, s))| {
|
||||||
if s.active && s.ips.contains(&addr.ip()) {
|
if s.active && s.ips.contains(&addr.ip()) {
|
||||||
@@ -31,8 +77,10 @@ impl ClientManager {
|
|||||||
.map(|p| p as ClientHandle)
|
.map(|p| p as ClientHandle)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_client(&self, pos: Position) -> Option<ClientHandle> {
|
/// get the client at the given position
|
||||||
|
pub fn client_at(&self, pos: Position) -> Option<ClientHandle> {
|
||||||
self.clients
|
self.clients
|
||||||
|
.borrow()
|
||||||
.iter()
|
.iter()
|
||||||
.find_map(|(k, (c, s))| {
|
.find_map(|(k, (c, s))| {
|
||||||
if s.active && c.pos == pos {
|
if s.active && c.pos == pos {
|
||||||
@@ -44,31 +92,162 @@ impl ClientManager {
|
|||||||
.map(|p| p as ClientHandle)
|
.map(|p| p as ClientHandle)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn get_hostname(&self, handle: ClientHandle) -> Option<String> {
|
||||||
|
self.clients
|
||||||
|
.borrow_mut()
|
||||||
|
.get_mut(handle as usize)
|
||||||
|
.and_then(|(c, _)| c.hostname.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// get the position of the corresponding client
|
||||||
|
pub(crate) fn get_pos(&self, handle: ClientHandle) -> Option<Position> {
|
||||||
|
self.clients
|
||||||
|
.borrow()
|
||||||
|
.get(handle as usize)
|
||||||
|
.map(|(c, _)| c.pos)
|
||||||
|
}
|
||||||
|
|
||||||
/// remove a client from the list
|
/// remove a client from the list
|
||||||
pub fn remove_client(&mut self, client: ClientHandle) -> Option<(ClientConfig, ClientState)> {
|
pub fn remove_client(&self, client: ClientHandle) -> Option<(ClientConfig, ClientState)> {
|
||||||
// remove id from occupied ids
|
// remove id from occupied ids
|
||||||
self.clients.try_remove(client as usize)
|
self.clients.borrow_mut().try_remove(client as usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns an immutable reference to the client state corresponding to `client`
|
/// get the config & state of the given client
|
||||||
pub fn get(&self, handle: ClientHandle) -> Option<&(ClientConfig, ClientState)> {
|
pub fn get_state(&self, handle: ClientHandle) -> Option<(ClientConfig, ClientState)> {
|
||||||
self.clients.get(handle as usize)
|
self.clients.borrow().get(handle as usize).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// returns a mutable reference to the client state corresponding to `client`
|
/// get the current config & state of all clients
|
||||||
pub fn get_mut(&mut self, handle: ClientHandle) -> Option<&mut (ClientConfig, ClientState)> {
|
pub fn get_client_states(&self) -> Vec<(ClientHandle, ClientConfig, ClientState)> {
|
||||||
self.clients.get_mut(handle as usize)
|
self.clients
|
||||||
|
.borrow()
|
||||||
|
.iter()
|
||||||
|
.map(|(k, v)| (k as ClientHandle, v.0.clone(), v.1.clone()))
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_client_states(
|
/// update the fix ips of the client
|
||||||
&self,
|
pub fn set_fix_ips(&self, handle: ClientHandle, fix_ips: Vec<IpAddr>) {
|
||||||
) -> impl Iterator<Item = (ClientHandle, &(ClientConfig, ClientState))> {
|
if let Some((c, _)) = self.clients.borrow_mut().get_mut(handle as usize) {
|
||||||
self.clients.iter().map(|(k, v)| (k as ClientHandle, v))
|
c.fix_ips = fix_ips
|
||||||
|
}
|
||||||
|
self.update_ips(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_client_states_mut(
|
/// update the dns-ips of the client
|
||||||
&mut self,
|
pub fn set_dns_ips(&self, handle: ClientHandle, dns_ips: Vec<IpAddr>) {
|
||||||
) -> impl Iterator<Item = (ClientHandle, &mut (ClientConfig, ClientState))> {
|
if let Some((_, s)) = self.clients.borrow_mut().get_mut(handle as usize) {
|
||||||
self.clients.iter_mut().map(|(k, v)| (k as ClientHandle, v))
|
s.dns_ips = dns_ips
|
||||||
|
}
|
||||||
|
self.update_ips(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_ips(&self, handle: ClientHandle) {
|
||||||
|
if let Some((c, s)) = self.clients.borrow_mut().get_mut(handle as usize) {
|
||||||
|
s.ips = c
|
||||||
|
.fix_ips
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.chain(s.dns_ips.iter().cloned())
|
||||||
|
.collect::<HashSet<_>>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// update the hostname of the given client
|
||||||
|
/// this automatically clears the active ip address and ips from dns
|
||||||
|
pub fn set_hostname(&self, handle: ClientHandle, hostname: Option<String>) -> bool {
|
||||||
|
let mut clients = self.clients.borrow_mut();
|
||||||
|
let Some((c, s)) = clients.get_mut(handle as usize) else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// hostname changed
|
||||||
|
if c.hostname != hostname {
|
||||||
|
c.hostname = hostname;
|
||||||
|
s.active_addr = None;
|
||||||
|
s.dns_ips.clear();
|
||||||
|
drop(clients);
|
||||||
|
self.update_ips(handle);
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// update the port of the client
|
||||||
|
pub(crate) fn set_port(&self, handle: ClientHandle, port: u16) {
|
||||||
|
match self.clients.borrow_mut().get_mut(handle as usize) {
|
||||||
|
Some((c, s)) if c.port != port => {
|
||||||
|
c.port = port;
|
||||||
|
s.active_addr = s.active_addr.map(|a| SocketAddr::new(a.ip(), port));
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// update the position of the client
|
||||||
|
/// returns true, if a change in capture position is required (pos changed & client is active)
|
||||||
|
pub(crate) fn set_pos(&self, handle: ClientHandle, pos: Position) -> bool {
|
||||||
|
match self.clients.borrow_mut().get_mut(handle as usize) {
|
||||||
|
Some((c, s)) if c.pos != pos => {
|
||||||
|
log::info!("update pos {handle} {} -> {}", c.pos, pos);
|
||||||
|
c.pos = pos;
|
||||||
|
s.active
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// set resolving status of the client
|
||||||
|
pub(crate) fn set_resolving(&self, handle: ClientHandle, status: bool) {
|
||||||
|
if let Some((_, s)) = self.clients.borrow_mut().get_mut(handle as usize) {
|
||||||
|
s.resolving = status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// get the enter hook command
|
||||||
|
pub(crate) fn get_enter_cmd(&self, handle: ClientHandle) -> Option<String> {
|
||||||
|
self.clients
|
||||||
|
.borrow()
|
||||||
|
.get(handle as usize)
|
||||||
|
.and_then(|(c, _)| c.cmd.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// returns all clients that are currently active
|
||||||
|
pub(crate) fn active_clients(&self) -> Vec<ClientHandle> {
|
||||||
|
self.clients
|
||||||
|
.borrow()
|
||||||
|
.iter()
|
||||||
|
.filter(|(_, (_, s))| s.active)
|
||||||
|
.map(|(h, _)| h as ClientHandle)
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn set_active_addr(&self, handle: u64, addr: Option<SocketAddr>) {
|
||||||
|
if let Some((_, s)) = self.clients.borrow_mut().get_mut(handle as usize) {
|
||||||
|
s.active_addr = addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn active_addr(&self, handle: u64) -> Option<SocketAddr> {
|
||||||
|
self.clients
|
||||||
|
.borrow()
|
||||||
|
.get(handle as usize)
|
||||||
|
.and_then(|(_, s)| s.active_addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn get_port(&self, handle: u64) -> Option<u16> {
|
||||||
|
self.clients
|
||||||
|
.borrow()
|
||||||
|
.get(handle as usize)
|
||||||
|
.map(|(c, _)| c.port)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn get_ips(&self, handle: u64) -> Option<HashSet<IpAddr>> {
|
||||||
|
self.clients
|
||||||
|
.borrow()
|
||||||
|
.get(handle as usize)
|
||||||
|
.map(|(_, s)| s.ips.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ impl LanMouseConnection {
|
|||||||
) -> Result<(), LanMouseConnectionError> {
|
) -> Result<(), LanMouseConnectionError> {
|
||||||
let (buf, len): ([u8; MAX_EVENT_SIZE], usize) = event.into();
|
let (buf, len): ([u8; MAX_EVENT_SIZE], usize) = event.into();
|
||||||
let buf = &buf[..len];
|
let buf = &buf[..len];
|
||||||
if let Some(addr) = self.server.active_addr(handle) {
|
if let Some(addr) = self.server.client_manager.active_addr(handle) {
|
||||||
let conn = {
|
let conn = {
|
||||||
let conns = self.conns.lock().await;
|
let conns = self.conns.lock().await;
|
||||||
conns.get(&addr).cloned()
|
conns.get(&addr).cloned()
|
||||||
@@ -138,8 +138,11 @@ async fn connect_to_handle(
|
|||||||
) -> Result<(), LanMouseConnectionError> {
|
) -> Result<(), LanMouseConnectionError> {
|
||||||
log::info!("client {handle} connecting ...");
|
log::info!("client {handle} connecting ...");
|
||||||
// sending did not work, figure out active conn.
|
// sending did not work, figure out active conn.
|
||||||
if let Some(addrs) = server.get_ips(handle) {
|
if let Some(addrs) = server.client_manager.get_ips(handle) {
|
||||||
let port = server.get_port(handle).unwrap_or(DEFAULT_PORT);
|
let port = server
|
||||||
|
.client_manager
|
||||||
|
.get_port(handle)
|
||||||
|
.unwrap_or(DEFAULT_PORT);
|
||||||
let addrs = addrs
|
let addrs = addrs
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|a| SocketAddr::new(a, port))
|
.map(|a| SocketAddr::new(a, port))
|
||||||
@@ -154,7 +157,7 @@ async fn connect_to_handle(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
log::info!("client ({handle}) connected @ {addr}");
|
log::info!("client ({handle}) connected @ {addr}");
|
||||||
server.set_active_addr(handle, Some(addr));
|
server.client_manager.set_active_addr(handle, Some(addr));
|
||||||
conns.lock().await.insert(addr, conn.clone());
|
conns.lock().await.insert(addr, conn.clone());
|
||||||
connecting.lock().await.remove(&handle);
|
connecting.lock().await.remove(&handle);
|
||||||
|
|
||||||
@@ -193,7 +196,7 @@ async fn ping_pong(
|
|||||||
|
|
||||||
tokio::time::sleep(Duration::from_millis(500)).await;
|
tokio::time::sleep(Duration::from_millis(500)).await;
|
||||||
|
|
||||||
if server.active_addr(handle).is_none() {
|
if server.client_manager.active_addr(handle).is_none() {
|
||||||
log::warn!("no active addr");
|
log::warn!("no active addr");
|
||||||
disconnect(&server, handle, addr, &conns).await;
|
disconnect(&server, handle, addr, &conns).await;
|
||||||
}
|
}
|
||||||
@@ -212,7 +215,7 @@ async fn receive_loop(
|
|||||||
while let Ok(_) = conn.recv(&mut buf).await {
|
while let Ok(_) = conn.recv(&mut buf).await {
|
||||||
if let Ok(event) = buf.try_into() {
|
if let Ok(event) = buf.try_into() {
|
||||||
match event {
|
match event {
|
||||||
ProtoEvent::Pong => server.set_active_addr(handle, Some(addr)),
|
ProtoEvent::Pong => server.client_manager.set_active_addr(handle, Some(addr)),
|
||||||
event => tx.send((handle, event)).expect("channel closed"),
|
event => tx.send((handle, event)).expect("channel closed"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -229,7 +232,7 @@ async fn disconnect(
|
|||||||
) {
|
) {
|
||||||
log::warn!("client ({handle}) @ {addr} connection closed");
|
log::warn!("client ({handle}) @ {addr} connection closed");
|
||||||
conns.lock().await.remove(&addr);
|
conns.lock().await.remove(&addr);
|
||||||
server.set_active_addr(handle, None);
|
server.client_manager.set_active_addr(handle, None);
|
||||||
let active: Vec<SocketAddr> = conns.lock().await.keys().copied().collect();
|
let active: Vec<SocketAddr> = conns.lock().await.keys().copied().collect();
|
||||||
log::info!("active connections: {active:?}");
|
log::info!("active connections: {active:?}");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ impl DnsResolver {
|
|||||||
let handle = rx.recv().await.expect("channel closed");
|
let handle = rx.recv().await.expect("channel closed");
|
||||||
|
|
||||||
/* update resolving status */
|
/* update resolving status */
|
||||||
let hostname = match server.get_hostname(handle) {
|
let hostname = match server.client_manager.get_hostname(handle) {
|
||||||
Some(hostname) => hostname,
|
Some(hostname) => hostname,
|
||||||
None => continue,
|
None => continue,
|
||||||
};
|
};
|
||||||
|
|||||||
252
src/server.rs
252
src/server.rs
@@ -16,7 +16,7 @@ use lan_mouse_ipc::{
|
|||||||
use log;
|
use log;
|
||||||
use std::{
|
use std::{
|
||||||
cell::{Cell, RefCell},
|
cell::{Cell, RefCell},
|
||||||
collections::{HashSet, VecDeque},
|
collections::{HashMap, HashSet, VecDeque},
|
||||||
io,
|
io,
|
||||||
net::{IpAddr, SocketAddr},
|
net::{IpAddr, SocketAddr},
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
@@ -42,16 +42,17 @@ pub struct ReleaseToken;
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Server {
|
pub struct Server {
|
||||||
active: Rc<Cell<Option<ClientHandle>>>,
|
active: Rc<Cell<Option<ClientHandle>>>,
|
||||||
pub(crate) client_manager: Rc<RefCell<ClientManager>>,
|
authorized_keys: Rc<RefCell<HashSet<String>>>,
|
||||||
|
known_hosts: Rc<RefCell<HashSet<String>>>,
|
||||||
|
pub(crate) client_manager: ClientManager,
|
||||||
port: Rc<Cell<u16>>,
|
port: Rc<Cell<u16>>,
|
||||||
pub(crate) release_bind: Vec<input_event::scancode::Linux>,
|
|
||||||
notifies: Rc<Notifies>,
|
notifies: Rc<Notifies>,
|
||||||
pub(crate) config: Rc<Config>,
|
pub(crate) config: Rc<Config>,
|
||||||
pending_frontend_events: Rc<RefCell<VecDeque<FrontendEvent>>>,
|
pending_frontend_events: Rc<RefCell<VecDeque<FrontendEvent>>>,
|
||||||
capture_status: Rc<Cell<Status>>,
|
capture_status: Rc<Cell<Status>>,
|
||||||
pub(crate) emulation_status: Rc<Cell<Status>>,
|
pub(crate) emulation_status: Rc<Cell<Status>>,
|
||||||
pub(crate) should_release: Rc<RefCell<Option<ReleaseToken>>>,
|
pub(crate) should_release: Rc<RefCell<Option<ReleaseToken>>>,
|
||||||
incoming_conns: Rc<RefCell<Vec<(SocketAddr, Position)>>>,
|
incoming_conns: Rc<RefCell<HashMap<SocketAddr, Position>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
@@ -65,44 +66,43 @@ struct Notifies {
|
|||||||
|
|
||||||
impl Server {
|
impl Server {
|
||||||
pub fn new(config: Config) -> Self {
|
pub fn new(config: Config) -> Self {
|
||||||
let client_manager = Rc::new(RefCell::new(ClientManager::default()));
|
let client_manager = ClientManager::default();
|
||||||
let port = Rc::new(Cell::new(config.port));
|
let port = Rc::new(Cell::new(config.port));
|
||||||
for config_client in config.get_clients() {
|
for client in config.get_clients() {
|
||||||
let client = ClientConfig {
|
let config = ClientConfig {
|
||||||
hostname: config_client.hostname,
|
hostname: client.hostname,
|
||||||
fix_ips: config_client.ips.into_iter().collect(),
|
fix_ips: client.ips.into_iter().collect(),
|
||||||
port: config_client.port,
|
port: client.port,
|
||||||
pos: config_client.pos,
|
pos: client.pos,
|
||||||
cmd: config_client.enter_hook,
|
cmd: client.enter_hook,
|
||||||
};
|
};
|
||||||
let state = ClientState {
|
let state = ClientState {
|
||||||
active: config_client.active,
|
active: client.active,
|
||||||
ips: HashSet::from_iter(client.fix_ips.iter().cloned()),
|
ips: HashSet::from_iter(config.fix_ips.iter().cloned()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let mut client_manager = client_manager.borrow_mut();
|
|
||||||
let handle = client_manager.add_client();
|
let handle = client_manager.add_client();
|
||||||
let c = client_manager.get_mut(handle).expect("invalid handle");
|
client_manager.set_config(handle, config);
|
||||||
*c = (client, state);
|
client_manager.set_state(handle, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
// task notification tokens
|
// task notification tokens
|
||||||
let notifies = Rc::new(Notifies::default());
|
let notifies = Rc::new(Notifies::default());
|
||||||
let release_bind = config.release_bind.clone();
|
|
||||||
|
|
||||||
let config = Rc::new(config);
|
let config = Rc::new(config);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
active: Rc::new(Cell::new(None)),
|
active: Rc::new(Cell::new(None)),
|
||||||
|
authorized_keys: Default::default(),
|
||||||
|
known_hosts: Default::default(),
|
||||||
config,
|
config,
|
||||||
client_manager,
|
client_manager,
|
||||||
port,
|
port,
|
||||||
release_bind,
|
|
||||||
notifies,
|
notifies,
|
||||||
pending_frontend_events: Rc::new(RefCell::new(VecDeque::new())),
|
pending_frontend_events: Rc::new(RefCell::new(VecDeque::new())),
|
||||||
capture_status: Default::default(),
|
capture_status: Default::default(),
|
||||||
emulation_status: Default::default(),
|
emulation_status: Default::default(),
|
||||||
incoming_conns: Rc::new(RefCell::new(Vec::new())),
|
incoming_conns: Rc::new(RefCell::new(HashMap::new())),
|
||||||
should_release: Default::default(),
|
should_release: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -129,7 +129,7 @@ impl Server {
|
|||||||
// create dns resolver
|
// create dns resolver
|
||||||
let resolver = DnsResolver::new(self.clone())?;
|
let resolver = DnsResolver::new(self.clone())?;
|
||||||
|
|
||||||
for handle in self.active_clients() {
|
for handle in self.client_manager.active_clients() {
|
||||||
resolver.resolve(handle);
|
resolver.resolve(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,15 +221,6 @@ impl Server {
|
|||||||
self.notify_frontend(FrontendEvent::Changed(handle));
|
self.notify_frontend(FrontendEvent::Changed(handle));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn active_clients(&self) -> Vec<ClientHandle> {
|
|
||||||
self.client_manager
|
|
||||||
.borrow()
|
|
||||||
.get_client_states()
|
|
||||||
.filter(|(_, (_, s))| s.active)
|
|
||||||
.map(|(h, _)| h)
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_request(&self, capture: &Capture, event: FrontendRequest, dns: &DnsResolver) -> bool {
|
fn handle_request(&self, capture: &Capture, event: FrontendRequest, dns: &DnsResolver) -> bool {
|
||||||
log::debug!("frontend: {event:?}");
|
log::debug!("frontend: {event:?}");
|
||||||
match event {
|
match event {
|
||||||
@@ -267,183 +258,109 @@ impl Server {
|
|||||||
self.notify_frontend(FrontendEvent::CaptureStatus(self.capture_status.get()));
|
self.notify_frontend(FrontendEvent::CaptureStatus(self.capture_status.get()));
|
||||||
self.notify_frontend(FrontendEvent::PortChanged(self.port.get(), None));
|
self.notify_frontend(FrontendEvent::PortChanged(self.port.get(), None));
|
||||||
}
|
}
|
||||||
|
FrontendRequest::FingerprintAdd(key) => {
|
||||||
|
self.add_authorized_key(key);
|
||||||
|
}
|
||||||
|
FrontendRequest::FingerprintRemove(key) => {
|
||||||
|
self.remove_authorized_key(key);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn add_authorized_key(&self, key: String) {
|
||||||
|
self.authorized_keys.borrow_mut().insert(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remove_authorized_key(&self, key: String) {
|
||||||
|
self.authorized_keys.borrow_mut().remove(&key);
|
||||||
|
}
|
||||||
|
|
||||||
fn enumerate(&self) {
|
fn enumerate(&self) {
|
||||||
let clients = self
|
let clients = self.client_manager.get_client_states();
|
||||||
.client_manager
|
|
||||||
.borrow()
|
|
||||||
.get_client_states()
|
|
||||||
.map(|(h, (c, s))| (h, c.clone(), s.clone()))
|
|
||||||
.collect();
|
|
||||||
self.notify_frontend(FrontendEvent::Enumerate(clients));
|
self.notify_frontend(FrontendEvent::Enumerate(clients));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_client(&self) -> ClientHandle {
|
fn add_client(&self) -> ClientHandle {
|
||||||
let handle = self.client_manager.borrow_mut().add_client();
|
let handle = self.client_manager.add_client();
|
||||||
log::info!("added client {handle}");
|
log::info!("added client {handle}");
|
||||||
let (c, s) = self.client_manager.borrow().get(handle).unwrap().clone();
|
let (c, s) = self.client_manager.get_state(handle).unwrap();
|
||||||
self.notify_frontend(FrontendEvent::Created(handle, c, s));
|
self.notify_frontend(FrontendEvent::Created(handle, c, s));
|
||||||
handle
|
handle
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deactivate_client(&self, capture: &Capture, handle: ClientHandle) {
|
fn deactivate_client(&self, capture: &Capture, handle: ClientHandle) {
|
||||||
log::debug!("deactivating client {handle}");
|
log::debug!("deactivating client {handle}");
|
||||||
match self.client_manager.borrow_mut().get_mut(handle) {
|
if self.client_manager.deactivate_client(handle) {
|
||||||
None => return,
|
capture.destroy(handle);
|
||||||
Some((_, s)) if !s.active => return,
|
self.client_updated(handle);
|
||||||
Some((_, s)) => s.active = false,
|
log::info!("deactivated client {handle}");
|
||||||
};
|
}
|
||||||
|
|
||||||
capture.destroy(handle);
|
|
||||||
self.client_updated(handle);
|
|
||||||
log::info!("deactivated client {handle}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn activate_client(&self, capture: &Capture, handle: ClientHandle) {
|
fn activate_client(&self, capture: &Capture, 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 pos = match self.client_manager.borrow().get(handle) {
|
let Some(pos) = self.client_manager.get_pos(handle) else {
|
||||||
None => return,
|
return;
|
||||||
Some((_, s)) if s.active => return,
|
|
||||||
Some((client, _)) => client.pos,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let other = self.client_manager.borrow_mut().find_client(pos);
|
if let Some(other) = self.client_manager.client_at(pos) {
|
||||||
if let Some(other) = other {
|
if other != handle {
|
||||||
self.deactivate_client(capture, other);
|
self.deactivate_client(capture, other);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* activate the client */
|
/* activate the client */
|
||||||
if let Some((_, s)) = self.client_manager.borrow_mut().get_mut(handle) {
|
if self.client_manager.activate_client(handle) {
|
||||||
s.active = true;
|
/* notify capture and frontends */
|
||||||
} else {
|
capture.create(handle, pos);
|
||||||
return;
|
self.client_updated(handle);
|
||||||
};
|
log::info!("activated client {handle} ({pos})");
|
||||||
|
}
|
||||||
/* notify capture and frontends */
|
|
||||||
capture.create(handle, to_capture_pos(pos));
|
|
||||||
self.client_updated(handle);
|
|
||||||
log::info!("activated client {handle} ({pos})");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_client(&self, capture: &Capture, handle: ClientHandle) {
|
fn remove_client(&self, capture: &Capture, handle: ClientHandle) {
|
||||||
let Some(active) = self
|
if let Some(true) = self
|
||||||
.client_manager
|
.client_manager
|
||||||
.borrow_mut()
|
|
||||||
.remove_client(handle)
|
.remove_client(handle)
|
||||||
.map(|(_, s)| s.active)
|
.map(|(_, s)| s.active)
|
||||||
else {
|
{
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
if active {
|
|
||||||
capture.destroy(handle);
|
capture.destroy(handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_fix_ips(&self, handle: ClientHandle, fix_ips: Vec<IpAddr>) {
|
fn update_fix_ips(&self, handle: ClientHandle, fix_ips: Vec<IpAddr>) {
|
||||||
if let Some((c, _)) = self.client_manager.borrow_mut().get_mut(handle) {
|
self.client_manager.set_fix_ips(handle, fix_ips);
|
||||||
c.fix_ips = fix_ips;
|
|
||||||
};
|
|
||||||
self.update_ips(handle);
|
|
||||||
self.client_updated(handle);
|
self.client_updated(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn update_dns_ips(&self, handle: ClientHandle, dns_ips: Vec<IpAddr>) {
|
pub(crate) fn update_dns_ips(&self, handle: ClientHandle, dns_ips: Vec<IpAddr>) {
|
||||||
if let Some((_, s)) = self.client_manager.borrow_mut().get_mut(handle) {
|
self.client_manager.set_dns_ips(handle, dns_ips);
|
||||||
s.dns_ips = dns_ips;
|
|
||||||
};
|
|
||||||
self.update_ips(handle);
|
|
||||||
self.client_updated(handle);
|
self.client_updated(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_ips(&self, handle: ClientHandle) {
|
|
||||||
if let Some((c, s)) = self.client_manager.borrow_mut().get_mut(handle) {
|
|
||||||
s.ips = c
|
|
||||||
.fix_ips
|
|
||||||
.iter()
|
|
||||||
.cloned()
|
|
||||||
.chain(s.dns_ips.iter().cloned())
|
|
||||||
.collect::<HashSet<_>>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn get_ips(&self, handle: ClientHandle) -> Option<Vec<IpAddr>> {
|
|
||||||
if let Some((_, s)) = self.client_manager.borrow().get(handle) {
|
|
||||||
Some(s.ips.iter().copied().collect())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn get_port(&self, handle: ClientHandle) -> Option<u16> {
|
|
||||||
if let Some((c, _)) = self.client_manager.borrow().get(handle) {
|
|
||||||
Some(c.port)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update_hostname(&self, handle: ClientHandle, hostname: Option<String>, dns: &DnsResolver) {
|
fn update_hostname(&self, handle: ClientHandle, hostname: Option<String>, dns: &DnsResolver) {
|
||||||
let mut client_manager = self.client_manager.borrow_mut();
|
if self.client_manager.set_hostname(handle, hostname) {
|
||||||
let Some((c, s)) = client_manager.get_mut(handle) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
// hostname changed
|
|
||||||
if c.hostname != hostname {
|
|
||||||
c.hostname = hostname;
|
|
||||||
s.active_addr = None;
|
|
||||||
s.dns_ips.clear();
|
|
||||||
drop(client_manager);
|
|
||||||
self.update_ips(handle);
|
|
||||||
dns.resolve(handle);
|
dns.resolve(handle);
|
||||||
|
self.client_updated(handle);
|
||||||
}
|
}
|
||||||
self.client_updated(handle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_port(&self, handle: ClientHandle, port: u16) {
|
fn update_port(&self, handle: ClientHandle, port: u16) {
|
||||||
let mut client_manager = self.client_manager.borrow_mut();
|
self.client_manager.set_port(handle, port);
|
||||||
let Some((c, s)) = client_manager.get_mut(handle) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
if c.port != port {
|
|
||||||
c.port = port;
|
|
||||||
s.active_addr = s.active_addr.map(|a| SocketAddr::new(a.ip(), port));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_pos(&self, handle: ClientHandle, capture: &Capture, pos: Position) {
|
fn update_pos(&self, handle: ClientHandle, capture: &Capture, pos: Position) {
|
||||||
let (changed, active) = {
|
|
||||||
let mut client_manager = self.client_manager.borrow_mut();
|
|
||||||
let Some((c, s)) = client_manager.get_mut(handle) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
let changed = c.pos != pos;
|
|
||||||
if changed {
|
|
||||||
log::info!("update pos {handle} {} -> {}", c.pos, pos);
|
|
||||||
}
|
|
||||||
c.pos = pos;
|
|
||||||
(changed, s.active)
|
|
||||||
};
|
|
||||||
|
|
||||||
// update state in event input emulator & input capture
|
// update state in event input emulator & input capture
|
||||||
if changed {
|
if self.client_manager.set_pos(handle, pos) {
|
||||||
self.deactivate_client(capture, handle);
|
self.deactivate_client(capture, handle);
|
||||||
if active {
|
self.activate_client(capture, handle);
|
||||||
self.activate_client(capture, handle);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn broadcast_client(&self, handle: ClientHandle) {
|
fn broadcast_client(&self, handle: ClientHandle) {
|
||||||
let client = self.client_manager.borrow().get(handle).cloned();
|
let event = if let Some((config, state)) = self.client_manager.get_state(handle) {
|
||||||
let event = if let Some((config, state)) = client {
|
|
||||||
FrontendEvent::State(handle, config, state)
|
FrontendEvent::State(handle, config, state)
|
||||||
} else {
|
} else {
|
||||||
FrontendEvent::NoSuchClient(handle)
|
FrontendEvent::NoSuchClient(handle)
|
||||||
@@ -464,36 +381,10 @@ impl Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn set_resolving(&self, handle: ClientHandle, status: bool) {
|
pub(crate) fn set_resolving(&self, handle: ClientHandle, status: bool) {
|
||||||
if let Some((_, s)) = self.client_manager.borrow_mut().get_mut(handle) {
|
self.client_manager.set_resolving(handle, status);
|
||||||
s.resolving = status;
|
|
||||||
}
|
|
||||||
self.client_updated(handle);
|
self.client_updated(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_hostname(&self, handle: ClientHandle) -> Option<String> {
|
|
||||||
self.client_manager
|
|
||||||
.borrow_mut()
|
|
||||||
.get_mut(handle)
|
|
||||||
.and_then(|(c, _)| c.hostname.clone())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn get_pos(&self, handle: ClientHandle) -> Option<Position> {
|
|
||||||
self.client_manager.borrow().get(handle).map(|(c, _)| c.pos)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn set_active_addr(&self, handle: ClientHandle, addr: Option<SocketAddr>) {
|
|
||||||
if let Some((_, s)) = self.client_manager.borrow_mut().get_mut(handle) {
|
|
||||||
s.active_addr = addr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn active_addr(&self, handle: ClientHandle) -> Option<SocketAddr> {
|
|
||||||
self.client_manager
|
|
||||||
.borrow()
|
|
||||||
.get(handle)
|
|
||||||
.and_then(|(_, s)| s.active_addr)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn release_capture(&self) {
|
pub(crate) fn release_capture(&self) {
|
||||||
self.should_release.replace(Some(ReleaseToken));
|
self.should_release.replace(Some(ReleaseToken));
|
||||||
}
|
}
|
||||||
@@ -507,15 +398,6 @@ impl Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn register_incoming(&self, addr: SocketAddr, pos: Position) {
|
pub(crate) fn register_incoming(&self, addr: SocketAddr, pos: Position) {
|
||||||
self.incoming_conns.borrow_mut().push((addr, pos));
|
self.incoming_conns.borrow_mut().insert(addr, pos);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_capture_pos(pos: Position) -> input_capture::Position {
|
|
||||||
match pos {
|
|
||||||
Position::Left => input_capture::Position::Left,
|
|
||||||
Position::Right => input_capture::Position::Right,
|
|
||||||
Position::Top => input_capture::Position::Top,
|
|
||||||
Position::Bottom => input_capture::Position::Bottom,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user