mirror of
https://github.com/feschber/lan-mouse.git
synced 2026-04-03 23:51:28 +03:00
enforce only one client at a position (#102)
This commit is contained in:
committed by
GitHub
parent
cc7984c066
commit
9ca7e2378c
@@ -178,6 +178,19 @@ impl ClientManager {
|
|||||||
.map(|p| p as ClientHandle)
|
.map(|p| p as ClientHandle)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn find_client(&self, pos: Position) -> Option<ClientHandle> {
|
||||||
|
self.clients
|
||||||
|
.iter()
|
||||||
|
.position(|c| {
|
||||||
|
if let Some(c) = c {
|
||||||
|
c.active && c.client.pos == pos
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.map(|p| p as ClientHandle)
|
||||||
|
}
|
||||||
|
|
||||||
/// remove a client from the list
|
/// remove a client from the list
|
||||||
pub fn remove_client(&mut self, client: ClientHandle) -> Option<ClientState> {
|
pub fn remove_client(&mut self, client: ClientHandle) -> Option<ClientState> {
|
||||||
// remove id from occupied ids
|
// remove id from occupied ids
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ pub(crate) fn new(
|
|||||||
mut frontend: FrontendListener,
|
mut frontend: FrontendListener,
|
||||||
mut notify_rx: Receiver<FrontendNotify>,
|
mut notify_rx: Receiver<FrontendNotify>,
|
||||||
server: Server,
|
server: Server,
|
||||||
capture_notify: Sender<CaptureEvent>,
|
capture: Sender<CaptureEvent>,
|
||||||
emulate_notify: Sender<EmulationEvent>,
|
emulate: Sender<EmulationEvent>,
|
||||||
resolve_ch: Sender<DnsRequest>,
|
resolve_ch: Sender<DnsRequest>,
|
||||||
port_tx: Sender<u16>,
|
port_tx: Sender<u16>,
|
||||||
) -> (JoinHandle<Result<()>>, Sender<FrontendEvent>) {
|
) -> (JoinHandle<Result<()>>, Sender<FrontendEvent>) {
|
||||||
@@ -51,7 +51,7 @@ pub(crate) fn new(
|
|||||||
}
|
}
|
||||||
event = event_rx.recv() => {
|
event = event_rx.recv() => {
|
||||||
let frontend_event = event.ok_or(anyhow!("frontend channel closed"))?;
|
let frontend_event = event.ok_or(anyhow!("frontend channel closed"))?;
|
||||||
if handle_frontend_event(&server, &capture_notify, &emulate_notify, &resolve_ch, &mut frontend, &port_tx, frontend_event).await {
|
if handle_frontend_event(&server, &capture, &emulate, &resolve_ch, &mut frontend, &port_tx, frontend_event).await {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -106,30 +106,31 @@ async fn handle_frontend_event(
|
|||||||
event: FrontendEvent,
|
event: FrontendEvent,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
log::debug!("frontend: {event:?}");
|
log::debug!("frontend: {event:?}");
|
||||||
let response = match event {
|
match event {
|
||||||
FrontendEvent::AddClient(hostname, port, pos) => {
|
FrontendEvent::AddClient(hostname, port, pos) => {
|
||||||
let handle = add_client(server, resolve_tx, hostname, HashSet::new(), port, pos).await;
|
add_client(
|
||||||
|
server,
|
||||||
let client = server
|
frontend,
|
||||||
.client_manager
|
resolve_tx,
|
||||||
.borrow()
|
hostname,
|
||||||
.get(handle)
|
HashSet::new(),
|
||||||
.unwrap()
|
port,
|
||||||
.client
|
pos,
|
||||||
.clone();
|
)
|
||||||
Some(FrontendNotify::NotifyClientCreate(client))
|
.await;
|
||||||
}
|
}
|
||||||
FrontendEvent::ActivateClient(handle, active) => {
|
FrontendEvent::ActivateClient(handle, active) => {
|
||||||
activate_client(server, capture_tx, emulate_tx, handle, active).await;
|
if active {
|
||||||
Some(FrontendNotify::NotifyClientActivate(handle, active))
|
activate_client(server, frontend, capture_tx, emulate_tx, handle).await;
|
||||||
|
} else {
|
||||||
|
deactivate_client(server, frontend, capture_tx, emulate_tx, handle).await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
FrontendEvent::ChangePort(port) => {
|
FrontendEvent::ChangePort(port) => {
|
||||||
let _ = port_tx.send(port).await;
|
let _ = port_tx.send(port).await;
|
||||||
None
|
|
||||||
}
|
}
|
||||||
FrontendEvent::DelClient(handle) => {
|
FrontendEvent::DelClient(handle) => {
|
||||||
remove_client(server, capture_tx, emulate_tx, frontend, handle).await;
|
remove_client(server, frontend, capture_tx, emulate_tx, handle).await;
|
||||||
Some(FrontendNotify::NotifyClientDelete(handle))
|
|
||||||
}
|
}
|
||||||
FrontendEvent::Enumerate() => {
|
FrontendEvent::Enumerate() => {
|
||||||
let clients = server
|
let clients = server
|
||||||
@@ -138,7 +139,7 @@ async fn handle_frontend_event(
|
|||||||
.get_client_states()
|
.get_client_states()
|
||||||
.map(|s| (s.client.clone(), s.active))
|
.map(|s| (s.client.clone(), s.active))
|
||||||
.collect();
|
.collect();
|
||||||
Some(FrontendNotify::Enumerate(clients))
|
notify_all(frontend, FrontendNotify::Enumerate(clients)).await;
|
||||||
}
|
}
|
||||||
FrontendEvent::Shutdown() => {
|
FrontendEvent::Shutdown() => {
|
||||||
log::info!("terminating gracefully...");
|
log::info!("terminating gracefully...");
|
||||||
@@ -147,40 +148,33 @@ async fn handle_frontend_event(
|
|||||||
FrontendEvent::UpdateClient(handle, hostname, port, pos) => {
|
FrontendEvent::UpdateClient(handle, hostname, port, pos) => {
|
||||||
update_client(
|
update_client(
|
||||||
server,
|
server,
|
||||||
|
frontend,
|
||||||
capture_tx,
|
capture_tx,
|
||||||
emulate_tx,
|
emulate_tx,
|
||||||
resolve_tx,
|
resolve_tx,
|
||||||
(handle, hostname, port, pos),
|
(handle, hostname, port, pos),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let client = server
|
|
||||||
.client_manager
|
|
||||||
.borrow()
|
|
||||||
.get(handle)
|
|
||||||
.unwrap()
|
|
||||||
.client
|
|
||||||
.clone();
|
|
||||||
Some(FrontendNotify::NotifyClientUpdate(client))
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let Some(response) = response else {
|
false
|
||||||
return false;
|
}
|
||||||
};
|
|
||||||
if let Err(e) = frontend.notify_all(response).await {
|
async fn notify_all(frontend: &mut FrontendListener, event: FrontendNotify) {
|
||||||
|
if let Err(e) = frontend.notify_all(event).await {
|
||||||
log::error!("error notifying frontend: {e}");
|
log::error!("error notifying frontend: {e}");
|
||||||
}
|
}
|
||||||
false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn add_client(
|
pub async fn add_client(
|
||||||
server: &Server,
|
server: &Server,
|
||||||
|
frontend: &mut FrontendListener,
|
||||||
resolver_tx: &Sender<DnsRequest>,
|
resolver_tx: &Sender<DnsRequest>,
|
||||||
hostname: Option<String>,
|
hostname: Option<String>,
|
||||||
addr: HashSet<IpAddr>,
|
addr: HashSet<IpAddr>,
|
||||||
port: u16,
|
port: u16,
|
||||||
pos: Position,
|
pos: Position,
|
||||||
) -> ClientHandle {
|
) {
|
||||||
log::info!(
|
log::info!(
|
||||||
"adding client [{}]{} @ {:?}",
|
"adding client [{}]{} @ {:?}",
|
||||||
pos,
|
pos,
|
||||||
@@ -198,77 +192,105 @@ pub async fn add_client(
|
|||||||
if let Some(hostname) = hostname {
|
if let Some(hostname) = hostname {
|
||||||
let _ = resolver_tx.send(DnsRequest { hostname, handle }).await;
|
let _ = resolver_tx.send(DnsRequest { hostname, handle }).await;
|
||||||
}
|
}
|
||||||
|
let client = server
|
||||||
handle
|
.client_manager
|
||||||
|
.borrow()
|
||||||
|
.get(handle)
|
||||||
|
.unwrap()
|
||||||
|
.client
|
||||||
|
.clone();
|
||||||
|
notify_all(frontend, FrontendNotify::NotifyClientCreate(client)).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn activate_client(
|
pub async fn deactivate_client(
|
||||||
server: &Server,
|
server: &Server,
|
||||||
capture_notify_tx: &Sender<CaptureEvent>,
|
frontend: &mut FrontendListener,
|
||||||
emulate_notify_tx: &Sender<EmulationEvent>,
|
capture: &Sender<CaptureEvent>,
|
||||||
|
emulate: &Sender<EmulationEvent>,
|
||||||
client: ClientHandle,
|
client: ClientHandle,
|
||||||
active: bool,
|
|
||||||
) {
|
) {
|
||||||
let (client, pos) = match server.client_manager.borrow_mut().get_mut(client) {
|
let (client, _) = match server.client_manager.borrow_mut().get_mut(client) {
|
||||||
Some(state) => {
|
Some(state) => {
|
||||||
state.active = active;
|
state.active = false;
|
||||||
(state.client.handle, state.client.pos)
|
(state.client.handle, state.client.pos)
|
||||||
}
|
}
|
||||||
None => return,
|
None => return,
|
||||||
};
|
};
|
||||||
if active {
|
|
||||||
let _ = capture_notify_tx
|
let event = ClientEvent::Destroy(client);
|
||||||
.send(CaptureEvent::ClientEvent(ClientEvent::Create(client, pos)))
|
let _ = capture.send(CaptureEvent::ClientEvent(event)).await;
|
||||||
.await;
|
let _ = emulate.send(EmulationEvent::ClientEvent(event)).await;
|
||||||
let _ = emulate_notify_tx
|
let event = FrontendNotify::NotifyClientActivate(client, false);
|
||||||
.send(EmulationEvent::ClientEvent(ClientEvent::Create(
|
notify_all(frontend, event).await;
|
||||||
client, pos,
|
}
|
||||||
)))
|
|
||||||
.await;
|
pub async fn activate_client(
|
||||||
} else {
|
server: &Server,
|
||||||
let _ = capture_notify_tx
|
frontend: &mut FrontendListener,
|
||||||
.send(CaptureEvent::ClientEvent(ClientEvent::Destroy(client)))
|
capture: &Sender<CaptureEvent>,
|
||||||
.await;
|
emulate: &Sender<EmulationEvent>,
|
||||||
let _ = emulate_notify_tx
|
handle: ClientHandle,
|
||||||
.send(EmulationEvent::ClientEvent(ClientEvent::Destroy(client)))
|
) {
|
||||||
.await;
|
/* deactivate potential other client at this position */
|
||||||
|
let pos = match server.client_manager.borrow().get(handle) {
|
||||||
|
Some(state) => state.client.pos,
|
||||||
|
None => return,
|
||||||
|
};
|
||||||
|
|
||||||
|
let other = server.client_manager.borrow_mut().find_client(pos);
|
||||||
|
if let Some(other) = other {
|
||||||
|
if other != handle {
|
||||||
|
deactivate_client(server, frontend, capture, emulate, other).await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* activate the client */
|
||||||
|
server
|
||||||
|
.client_manager
|
||||||
|
.borrow_mut()
|
||||||
|
.get_mut(handle)
|
||||||
|
.unwrap()
|
||||||
|
.active = true;
|
||||||
|
|
||||||
|
/* notify emulation, capture and frontends */
|
||||||
|
let event = ClientEvent::Create(handle, pos);
|
||||||
|
let _ = capture.send(CaptureEvent::ClientEvent(event)).await;
|
||||||
|
let _ = emulate.send(EmulationEvent::ClientEvent(event)).await;
|
||||||
|
let event = FrontendNotify::NotifyClientActivate(handle, true);
|
||||||
|
notify_all(frontend, event).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn remove_client(
|
pub async fn remove_client(
|
||||||
server: &Server,
|
server: &Server,
|
||||||
capture_notify_tx: &Sender<CaptureEvent>,
|
|
||||||
emulate_notify_tx: &Sender<EmulationEvent>,
|
|
||||||
frontend: &mut FrontendListener,
|
frontend: &mut FrontendListener,
|
||||||
|
capture: &Sender<CaptureEvent>,
|
||||||
|
emulate: &Sender<EmulationEvent>,
|
||||||
client: ClientHandle,
|
client: ClientHandle,
|
||||||
) -> Option<ClientHandle> {
|
) {
|
||||||
let (client, active) = server
|
let Some((client, active)) = server
|
||||||
.client_manager
|
.client_manager
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.remove_client(client)
|
.remove_client(client)
|
||||||
.map(|s| (s.client.handle, s.active))?;
|
.map(|s| (s.client.handle, s.active))
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
if active {
|
if active {
|
||||||
let _ = capture_notify_tx
|
let destroy = ClientEvent::Destroy(client);
|
||||||
.send(CaptureEvent::ClientEvent(ClientEvent::Destroy(client)))
|
let _ = capture.send(CaptureEvent::ClientEvent(destroy)).await;
|
||||||
.await;
|
let _ = emulate.send(EmulationEvent::ClientEvent(destroy)).await;
|
||||||
let _ = emulate_notify_tx
|
|
||||||
.send(EmulationEvent::ClientEvent(ClientEvent::Destroy(client)))
|
|
||||||
.await;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let notify = FrontendNotify::NotifyClientDelete(client);
|
let event = FrontendNotify::NotifyClientDelete(client);
|
||||||
log::debug!("{notify:?}");
|
notify_all(frontend, event).await;
|
||||||
if let Err(e) = frontend.notify_all(notify).await {
|
|
||||||
log::error!("error notifying frontend: {e}");
|
|
||||||
}
|
|
||||||
Some(client)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn update_client(
|
async fn update_client(
|
||||||
server: &Server,
|
server: &Server,
|
||||||
capture_notify_tx: &Sender<CaptureEvent>,
|
frontend: &mut FrontendListener,
|
||||||
emulate_notify_tx: &Sender<EmulationEvent>,
|
capture: &Sender<CaptureEvent>,
|
||||||
|
emulate: &Sender<EmulationEvent>,
|
||||||
resolve_tx: &Sender<DnsRequest>,
|
resolve_tx: &Sender<DnsRequest>,
|
||||||
client_update: (ClientHandle, Option<String>, u16, Position),
|
client_update: (ClientHandle, Option<String>, u16, Position),
|
||||||
) {
|
) {
|
||||||
@@ -321,19 +343,20 @@ async fn update_client(
|
|||||||
// update state in event input emulator & input capture
|
// update state in event input emulator & input capture
|
||||||
if changed && active {
|
if changed && active {
|
||||||
// update state
|
// update state
|
||||||
let _ = capture_notify_tx
|
let destroy = ClientEvent::Destroy(handle);
|
||||||
.send(CaptureEvent::ClientEvent(ClientEvent::Destroy(handle)))
|
let create = ClientEvent::Create(handle, pos);
|
||||||
.await;
|
let _ = capture.send(CaptureEvent::ClientEvent(destroy)).await;
|
||||||
let _ = emulate_notify_tx
|
let _ = emulate.send(EmulationEvent::ClientEvent(destroy)).await;
|
||||||
.send(EmulationEvent::ClientEvent(ClientEvent::Destroy(handle)))
|
let _ = capture.send(CaptureEvent::ClientEvent(create)).await;
|
||||||
.await;
|
let _ = emulate.send(EmulationEvent::ClientEvent(create)).await;
|
||||||
let _ = capture_notify_tx
|
|
||||||
.send(CaptureEvent::ClientEvent(ClientEvent::Create(handle, pos)))
|
|
||||||
.await;
|
|
||||||
let _ = emulate_notify_tx
|
|
||||||
.send(EmulationEvent::ClientEvent(ClientEvent::Create(
|
|
||||||
handle, pos,
|
|
||||||
)))
|
|
||||||
.await;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let client = server
|
||||||
|
.client_manager
|
||||||
|
.borrow()
|
||||||
|
.get(handle)
|
||||||
|
.unwrap()
|
||||||
|
.client
|
||||||
|
.clone();
|
||||||
|
notify_all(frontend, FrontendNotify::NotifyClientUpdate(client)).await;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user