release stuck keys (#53)

Keys are now released when
- A client disconnects and still has pressed keys
- A client disconnects through CTLR+ALT+SHIFT+WIN
- Lan Mouse terminates with keys still being pressed through a remote client

This is also fixes an issue caused by KDE's implementation of the remote desktop portal backend:
Keys are not correctly released when a remote desktop session is closed while keys are still pressed,
causing them to be permanently stuck until kwin is restarted.

This workaround remembers all pressed keys and releases them when lan-mouse exits or a device disconnects.

closes #15
This commit is contained in:
Ferdinand Schober
2023-12-31 15:41:06 +01:00
committed by Ferdinand Schober
parent 6a6d9a9fa9
commit 64e3bf3ff4
6 changed files with 421 additions and 297 deletions

View File

@@ -568,6 +568,7 @@ impl EventProducer for WaylandEventProducer {
} }
fn release(&mut self) { fn release(&mut self) {
log::debug!("releasing pointer");
let inner = self.0.get_mut(); let inner = self.0.get_mut();
inner.state.ungrab(); inner.state.ungrab();
inner.flush_events(); inner.flush_events();

View File

@@ -2,7 +2,6 @@ use std::{
collections::HashSet, collections::HashSet,
fmt::Display, fmt::Display,
net::{IpAddr, SocketAddr}, net::{IpAddr, SocketAddr},
time::Instant,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -57,10 +56,6 @@ pub struct Client {
/// This way any event consumer / producer backend does not /// This way any event consumer / producer backend does not
/// need to know anything about a client other than its handle. /// need to know anything about a client other than its handle.
pub handle: ClientHandle, pub handle: ClientHandle,
/// `active` address of the client, used to send data to.
/// This should generally be the socket address where data
/// was last received from.
pub active_addr: Option<SocketAddr>,
/// all socket addresses associated with a particular client /// all socket addresses associated with a particular client
/// e.g. Laptops usually have at least an ethernet and a wifi port /// e.g. Laptops usually have at least an ethernet and a wifi port
/// which have different ip addresses /// which have different ip addresses
@@ -71,7 +66,7 @@ pub struct Client {
pub pos: Position, pub pos: Position,
} }
#[derive(Debug)] #[derive(Clone, Copy, Debug)]
pub enum ClientEvent { pub enum ClientEvent {
Create(ClientHandle, Position), Create(ClientHandle, Position),
Destroy(ClientHandle), Destroy(ClientHandle),
@@ -81,11 +76,18 @@ pub type ClientHandle = u32;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct ClientState { pub struct ClientState {
/// information about the client
pub client: Client, pub client: Client,
/// events should be sent to and received from the client
pub active: bool, pub active: bool,
pub last_ping: Option<Instant>, /// `active` address of the client, used to send data to.
pub last_seen: Option<Instant>, /// This should generally be the socket address where data
pub last_replied: Option<Instant>, /// was last received from.
pub active_addr: Option<SocketAddr>,
/// tracks whether or not the client is responding to pings
pub alive: bool,
/// keys currently pressed by this client
pub pressed_keys: HashSet<u32>,
} }
pub struct ClientManager { pub struct ClientManager {
@@ -114,9 +116,6 @@ impl ClientManager {
// get a new client_handle // get a new client_handle
let handle = self.free_id(); let handle = self.free_id();
// we dont know, which IP is initially active
let active_addr = None;
// store fix ip addresses // store fix ip addresses
let fix_ips = ips.iter().cloned().collect(); let fix_ips = ips.iter().cloned().collect();
@@ -128,7 +127,6 @@ impl ClientManager {
hostname, hostname,
fix_ips, fix_ips,
handle, handle,
active_addr,
addrs, addrs,
port, port,
pos, pos,
@@ -137,10 +135,10 @@ impl ClientManager {
// client was never seen, nor pinged // client was never seen, nor pinged
let client_state = ClientState { let client_state = ClientState {
client, client,
last_ping: None,
last_seen: None,
last_replied: None,
active: false, active: false,
active_addr: None,
alive: false,
pressed_keys: HashSet::new(),
}; };
if handle as usize >= self.clients.len() { if handle as usize >= self.clients.len() {

View File

@@ -1,3 +1,4 @@
use anyhow::{anyhow, Result};
use std::{ use std::{
error::Error, error::Error,
fmt::{self, Display}, fmt::{self, Display},
@@ -65,6 +66,9 @@ pub enum Event {
/// response to a ping event: this event signals that a client /// response to a ping event: this event signals that a client
/// is still alive but must otherwise be ignored /// is still alive but must otherwise be ignored
Pong(), Pong(),
/// explicit disconnect request. The client will no longer
/// send events until the next Enter event. All of its keys should be released.
Disconnect(),
} }
impl Display for PointerEvent { impl Display for PointerEvent {
@@ -120,6 +124,7 @@ impl Display for Event {
Event::Leave() => write!(f, "leave"), Event::Leave() => write!(f, "leave"),
Event::Ping() => write!(f, "ping"), Event::Ping() => write!(f, "ping"),
Event::Pong() => write!(f, "pong"), Event::Pong() => write!(f, "pong"),
Event::Disconnect() => write!(f, "disconnect"),
} }
} }
} }
@@ -133,6 +138,7 @@ impl Event {
Self::Leave() => EventType::Leave, Self::Leave() => EventType::Leave,
Self::Ping() => EventType::Ping, Self::Ping() => EventType::Ping,
Self::Pong() => EventType::Pong, Self::Pong() => EventType::Pong,
Self::Disconnect() => EventType::Disconnect,
} }
} }
} }
@@ -174,18 +180,19 @@ enum EventType {
Leave, Leave,
Ping, Ping,
Pong, Pong,
Disconnect,
} }
impl TryFrom<u8> for PointerEventType { impl TryFrom<u8> for PointerEventType {
type Error = Box<dyn Error>; type Error = anyhow::Error;
fn try_from(value: u8) -> Result<Self, Self::Error> { fn try_from(value: u8) -> Result<Self> {
match value { match value {
x if x == Self::Motion as u8 => Ok(Self::Motion), x if x == Self::Motion as u8 => Ok(Self::Motion),
x if x == Self::Button as u8 => Ok(Self::Button), x if x == Self::Button as u8 => Ok(Self::Button),
x if x == Self::Axis as u8 => Ok(Self::Axis), x if x == Self::Axis as u8 => Ok(Self::Axis),
x if x == Self::Frame as u8 => Ok(Self::Frame), x if x == Self::Frame as u8 => Ok(Self::Frame),
_ => Err(Box::new(ProtocolError { _ => Err(anyhow!(ProtocolError {
msg: format!("invalid pointer event type {}", value), msg: format!("invalid pointer event type {}", value),
})), })),
} }
@@ -193,13 +200,13 @@ impl TryFrom<u8> for PointerEventType {
} }
impl TryFrom<u8> for KeyboardEventType { impl TryFrom<u8> for KeyboardEventType {
type Error = Box<dyn Error>; type Error = anyhow::Error;
fn try_from(value: u8) -> Result<Self, Self::Error> { fn try_from(value: u8) -> Result<Self> {
match value { match value {
x if x == Self::Key as u8 => Ok(Self::Key), x if x == Self::Key as u8 => Ok(Self::Key),
x if x == Self::Modifiers as u8 => Ok(Self::Modifiers), x if x == Self::Modifiers as u8 => Ok(Self::Modifiers),
_ => Err(Box::new(ProtocolError { _ => Err(anyhow!(ProtocolError {
msg: format!("invalid keyboard event type {}", value), msg: format!("invalid keyboard event type {}", value),
})), })),
} }
@@ -216,6 +223,7 @@ impl From<&Event> for Vec<u8> {
Event::Leave() => vec![], Event::Leave() => vec![],
Event::Ping() => vec![], Event::Ping() => vec![],
Event::Pong() => vec![], Event::Pong() => vec![],
Event::Disconnect() => vec![],
}; };
[event_id, event_data].concat() [event_id, event_data].concat()
} }
@@ -234,9 +242,9 @@ impl fmt::Display for ProtocolError {
impl Error for ProtocolError {} impl Error for ProtocolError {}
impl TryFrom<Vec<u8>> for Event { impl TryFrom<Vec<u8>> for Event {
type Error = Box<dyn Error>; type Error = anyhow::Error;
fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> { fn try_from(value: Vec<u8>) -> Result<Self> {
let event_id = u8::from_be_bytes(value[..1].try_into()?); let event_id = u8::from_be_bytes(value[..1].try_into()?);
match event_id { match event_id {
i if i == (EventType::Pointer as u8) => Ok(Event::Pointer(value.try_into()?)), i if i == (EventType::Pointer as u8) => Ok(Event::Pointer(value.try_into()?)),
@@ -245,7 +253,8 @@ impl TryFrom<Vec<u8>> for Event {
i if i == (EventType::Leave as u8) => Ok(Event::Leave()), i if i == (EventType::Leave as u8) => Ok(Event::Leave()),
i if i == (EventType::Ping as u8) => Ok(Event::Ping()), i if i == (EventType::Ping as u8) => Ok(Event::Ping()),
i if i == (EventType::Pong as u8) => Ok(Event::Pong()), i if i == (EventType::Pong as u8) => Ok(Event::Pong()),
_ => Err(Box::new(ProtocolError { i if i == (EventType::Disconnect as u8) => Ok(Event::Disconnect()),
_ => Err(anyhow!(ProtocolError {
msg: format!("invalid event_id {}", event_id), msg: format!("invalid event_id {}", event_id),
})), })),
} }
@@ -291,9 +300,9 @@ impl From<&PointerEvent> for Vec<u8> {
} }
impl TryFrom<Vec<u8>> for PointerEvent { impl TryFrom<Vec<u8>> for PointerEvent {
type Error = Box<dyn Error>; type Error = anyhow::Error;
fn try_from(data: Vec<u8>) -> Result<Self, Self::Error> { fn try_from(data: Vec<u8>) -> Result<Self> {
match data.get(1) { match data.get(1) {
Some(id) => { Some(id) => {
let event_type = match id.to_owned().try_into() { let event_type = match id.to_owned().try_into() {
@@ -305,7 +314,7 @@ impl TryFrom<Vec<u8>> for PointerEvent {
let time = match data.get(2..6) { let time = match data.get(2..6) {
Some(d) => u32::from_be_bytes(d.try_into()?), Some(d) => u32::from_be_bytes(d.try_into()?),
None => { None => {
return Err(Box::new(ProtocolError { return Err(anyhow!(ProtocolError {
msg: "Expected 4 Bytes at index 2".into(), msg: "Expected 4 Bytes at index 2".into(),
})) }))
} }
@@ -313,7 +322,7 @@ impl TryFrom<Vec<u8>> for PointerEvent {
let relative_x = match data.get(6..14) { let relative_x = match data.get(6..14) {
Some(d) => f64::from_be_bytes(d.try_into()?), Some(d) => f64::from_be_bytes(d.try_into()?),
None => { None => {
return Err(Box::new(ProtocolError { return Err(anyhow!(ProtocolError {
msg: "Expected 8 Bytes at index 6".into(), msg: "Expected 8 Bytes at index 6".into(),
})) }))
} }
@@ -321,7 +330,7 @@ impl TryFrom<Vec<u8>> for PointerEvent {
let relative_y = match data.get(14..22) { let relative_y = match data.get(14..22) {
Some(d) => f64::from_be_bytes(d.try_into()?), Some(d) => f64::from_be_bytes(d.try_into()?),
None => { None => {
return Err(Box::new(ProtocolError { return Err(anyhow!(ProtocolError {
msg: "Expected 8 Bytes at index 14".into(), msg: "Expected 8 Bytes at index 14".into(),
})) }))
} }
@@ -336,7 +345,7 @@ impl TryFrom<Vec<u8>> for PointerEvent {
let time = match data.get(2..6) { let time = match data.get(2..6) {
Some(d) => u32::from_be_bytes(d.try_into()?), Some(d) => u32::from_be_bytes(d.try_into()?),
None => { None => {
return Err(Box::new(ProtocolError { return Err(anyhow!(ProtocolError {
msg: "Expected 4 Bytes at index 2".into(), msg: "Expected 4 Bytes at index 2".into(),
})) }))
} }
@@ -344,7 +353,7 @@ impl TryFrom<Vec<u8>> for PointerEvent {
let button = match data.get(6..10) { let button = match data.get(6..10) {
Some(d) => u32::from_be_bytes(d.try_into()?), Some(d) => u32::from_be_bytes(d.try_into()?),
None => { None => {
return Err(Box::new(ProtocolError { return Err(anyhow!(ProtocolError {
msg: "Expected 4 Bytes at index 10".into(), msg: "Expected 4 Bytes at index 10".into(),
})) }))
} }
@@ -352,7 +361,7 @@ impl TryFrom<Vec<u8>> for PointerEvent {
let state = match data.get(10..14) { let state = match data.get(10..14) {
Some(d) => u32::from_be_bytes(d.try_into()?), Some(d) => u32::from_be_bytes(d.try_into()?),
None => { None => {
return Err(Box::new(ProtocolError { return Err(anyhow!(ProtocolError {
msg: "Expected 4 Bytes at index 14".into(), msg: "Expected 4 Bytes at index 14".into(),
})) }))
} }
@@ -367,7 +376,7 @@ impl TryFrom<Vec<u8>> for PointerEvent {
let time = match data.get(2..6) { let time = match data.get(2..6) {
Some(d) => u32::from_be_bytes(d.try_into()?), Some(d) => u32::from_be_bytes(d.try_into()?),
None => { None => {
return Err(Box::new(ProtocolError { return Err(anyhow!(ProtocolError {
msg: "Expected 4 Bytes at index 2".into(), msg: "Expected 4 Bytes at index 2".into(),
})) }))
} }
@@ -375,7 +384,7 @@ impl TryFrom<Vec<u8>> for PointerEvent {
let axis = match data.get(6) { let axis = match data.get(6) {
Some(d) => *d, Some(d) => *d,
None => { None => {
return Err(Box::new(ProtocolError { return Err(anyhow!(ProtocolError {
msg: "Expected 1 Byte at index 6".into(), msg: "Expected 1 Byte at index 6".into(),
})); }));
} }
@@ -383,7 +392,7 @@ impl TryFrom<Vec<u8>> for PointerEvent {
let value = match data.get(7..15) { let value = match data.get(7..15) {
Some(d) => f64::from_be_bytes(d.try_into()?), Some(d) => f64::from_be_bytes(d.try_into()?),
None => { None => {
return Err(Box::new(ProtocolError { return Err(anyhow!(ProtocolError {
msg: "Expected 8 Bytes at index 7".into(), msg: "Expected 8 Bytes at index 7".into(),
})); }));
} }
@@ -393,7 +402,7 @@ impl TryFrom<Vec<u8>> for PointerEvent {
PointerEventType::Frame => Ok(Self::Frame {}), PointerEventType::Frame => Ok(Self::Frame {}),
} }
} }
None => Err(Box::new(ProtocolError { None => Err(anyhow!(ProtocolError {
msg: "Expected an element at index 0".into(), msg: "Expected an element at index 0".into(),
})), })),
} }
@@ -434,9 +443,9 @@ impl From<&KeyboardEvent> for Vec<u8> {
} }
impl TryFrom<Vec<u8>> for KeyboardEvent { impl TryFrom<Vec<u8>> for KeyboardEvent {
type Error = Box<dyn Error>; type Error = anyhow::Error;
fn try_from(data: Vec<u8>) -> Result<Self, Self::Error> { fn try_from(data: Vec<u8>) -> Result<Self> {
match data.get(1) { match data.get(1) {
Some(id) => { Some(id) => {
let event_type = match id.to_owned().try_into() { let event_type = match id.to_owned().try_into() {
@@ -448,7 +457,7 @@ impl TryFrom<Vec<u8>> for KeyboardEvent {
let time = match data.get(2..6) { let time = match data.get(2..6) {
Some(d) => u32::from_be_bytes(d.try_into()?), Some(d) => u32::from_be_bytes(d.try_into()?),
None => { None => {
return Err(Box::new(ProtocolError { return Err(anyhow!(ProtocolError {
msg: "Expected 4 Bytes at index 6".into(), msg: "Expected 4 Bytes at index 6".into(),
})) }))
} }
@@ -456,7 +465,7 @@ impl TryFrom<Vec<u8>> for KeyboardEvent {
let key = match data.get(6..10) { let key = match data.get(6..10) {
Some(d) => u32::from_be_bytes(d.try_into()?), Some(d) => u32::from_be_bytes(d.try_into()?),
None => { None => {
return Err(Box::new(ProtocolError { return Err(anyhow!(ProtocolError {
msg: "Expected 4 Bytes at index 10".into(), msg: "Expected 4 Bytes at index 10".into(),
})) }))
} }
@@ -464,7 +473,7 @@ impl TryFrom<Vec<u8>> for KeyboardEvent {
let state = match data.get(10) { let state = match data.get(10) {
Some(d) => *d, Some(d) => *d,
None => { None => {
return Err(Box::new(ProtocolError { return Err(anyhow!(ProtocolError {
msg: "Expected 1 Bytes at index 14".into(), msg: "Expected 1 Bytes at index 14".into(),
})) }))
} }
@@ -475,7 +484,7 @@ impl TryFrom<Vec<u8>> for KeyboardEvent {
let mods_depressed = match data.get(2..6) { let mods_depressed = match data.get(2..6) {
Some(d) => u32::from_be_bytes(d.try_into()?), Some(d) => u32::from_be_bytes(d.try_into()?),
None => { None => {
return Err(Box::new(ProtocolError { return Err(anyhow!(ProtocolError {
msg: "Expected 4 Bytes at index 6".into(), msg: "Expected 4 Bytes at index 6".into(),
})) }))
} }
@@ -483,7 +492,7 @@ impl TryFrom<Vec<u8>> for KeyboardEvent {
let mods_latched = match data.get(6..10) { let mods_latched = match data.get(6..10) {
Some(d) => u32::from_be_bytes(d.try_into()?), Some(d) => u32::from_be_bytes(d.try_into()?),
None => { None => {
return Err(Box::new(ProtocolError { return Err(anyhow!(ProtocolError {
msg: "Expected 4 Bytes at index 10".into(), msg: "Expected 4 Bytes at index 10".into(),
})) }))
} }
@@ -491,7 +500,7 @@ impl TryFrom<Vec<u8>> for KeyboardEvent {
let mods_locked = match data.get(10..14) { let mods_locked = match data.get(10..14) {
Some(d) => u32::from_be_bytes(d.try_into()?), Some(d) => u32::from_be_bytes(d.try_into()?),
None => { None => {
return Err(Box::new(ProtocolError { return Err(anyhow!(ProtocolError {
msg: "Expected 4 Bytes at index 14".into(), msg: "Expected 4 Bytes at index 14".into(),
})) }))
} }
@@ -499,7 +508,7 @@ impl TryFrom<Vec<u8>> for KeyboardEvent {
let group = match data.get(14..18) { let group = match data.get(14..18) {
Some(d) => u32::from_be_bytes(d.try_into()?), Some(d) => u32::from_be_bytes(d.try_into()?),
None => { None => {
return Err(Box::new(ProtocolError { return Err(anyhow!(ProtocolError {
msg: "Expected 4 Bytes at index 18".into(), msg: "Expected 4 Bytes at index 18".into(),
})) }))
} }
@@ -513,7 +522,7 @@ impl TryFrom<Vec<u8>> for KeyboardEvent {
} }
} }
} }
None => Err(Box::new(ProtocolError { None => Err(anyhow!(ProtocolError {
msg: "Expected an element at index 0".into(), msg: "Expected an element at index 0".into(),
})), })),
} }

View File

@@ -108,6 +108,7 @@ pub enum FrontendNotify {
NotifyClientDelete(ClientHandle), NotifyClientDelete(ClientHandle),
/// new port, reason of failure (if failed) /// new port, reason of failure (if failed)
NotifyPortChange(u16, Option<String>), NotifyPortChange(u16, Option<String>),
/// Client State, active
Enumerate(Vec<(Client, bool)>), Enumerate(Vec<(Client, bool)>),
NotifyError(String), NotifyError(String),
} }

View File

@@ -65,7 +65,9 @@ fn run_service(config: &Config) -> Result<()> {
runtime.block_on(LocalSet::new().run_until(async { runtime.block_on(LocalSet::new().run_until(async {
// run main loop // run main loop
log::info!("Press Ctrl+Alt+Shift+Super to release the mouse"); log::info!("Press Ctrl+Alt+Shift+Super to release the mouse");
Server::run(config).await?;
let server = Server::new(config);
server.run().await?;
log::debug!("service exiting"); log::debug!("service exiting");
anyhow::Ok(()) anyhow::Ok(())

View File

@@ -4,13 +4,12 @@ use log;
use std::{ use std::{
cell::{Cell, RefCell}, cell::{Cell, RefCell},
collections::HashSet, collections::HashSet,
error::Error,
io::Result, io::Result,
net::IpAddr, net::IpAddr,
rc::Rc, rc::Rc,
time::{Duration, Instant}, time::Duration,
}; };
use tokio::{io::ReadHalf, net::UdpSocket, signal, sync::mpsc::Sender, task}; use tokio::{io::ReadHalf, net::UdpSocket, signal, sync::mpsc::Sender};
#[cfg(unix)] #[cfg(unix)]
use tokio::net::UnixStream; use tokio::net::UnixStream;
@@ -27,6 +26,7 @@ use crate::{
dns, dns,
frontend::{self, FrontendEvent, FrontendListener, FrontendNotify}, frontend::{self, FrontendEvent, FrontendListener, FrontendNotify},
producer::EventProducer, producer::EventProducer,
scancode,
}; };
use crate::{ use crate::{
consumer, consumer,
@@ -34,20 +34,37 @@ use crate::{
producer, producer,
}; };
const MAX_RESPONSE_TIME: Duration = Duration::from_millis(500);
#[derive(Clone, Copy, Debug, Eq, PartialEq)] #[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum State { enum State {
/// Currently sending events to another device
Sending, Sending,
/// Currently receiving events from other devices
Receiving, Receiving,
/// Entered the deadzone of another device but waiting
/// for acknowledgement (Leave event) from the device
AwaitingLeave, AwaitingLeave,
} }
#[derive(Clone, Copy, Debug)]
pub enum ProducerEvent { pub enum ProducerEvent {
/// producer must release the mouse
Release, Release,
/// producer is notified of a change in client states
ClientEvent(ClientEvent), ClientEvent(ClientEvent),
/// termination signal
Terminate,
} }
#[derive(Clone, Debug)]
pub enum ConsumerEvent { pub enum ConsumerEvent {
/// consumer is notified of a change in client states
ClientEvent(ClientEvent), ClientEvent(ClientEvent),
/// consumer must release keys for client
ReleaseKeys(ClientHandle),
/// termination signal
Terminate,
} }
#[derive(Clone)] #[derive(Clone)]
@@ -58,14 +75,35 @@ struct ClientUpdate {
pos: Position, pos: Position,
} }
pub struct Server {} #[derive(Clone)]
pub struct Server {
active_client: Rc<Cell<Option<ClientHandle>>>,
client_manager: Rc<RefCell<ClientManager>>,
port: Rc<Cell<u16>>,
state: Rc<Cell<State>>,
}
impl Server { impl Server {
pub async fn run(config: &Config) -> anyhow::Result<()> { pub fn new(config: &Config) -> Self {
let active_client = Rc::new(Cell::new(None));
let client_manager = Rc::new(RefCell::new(ClientManager::new()));
let state = Rc::new(Cell::new(State::Receiving));
let port = Rc::new(Cell::new(config.port));
for (ips, host, port, pos) in config.get_clients() {
client_manager.borrow_mut().add_client(host, ips, port, pos);
}
Self {
active_client,
client_manager,
port,
state,
}
}
pub async fn run(&self) -> anyhow::Result<()> {
// create frontend communication adapter // create frontend communication adapter
let mut frontend = match FrontendListener::new().await { let mut frontend = match FrontendListener::new().await {
Some(Err(e)) => return Err(e), Some(f) => f?,
Some(Ok(f)) => f,
None => { None => {
// none means some other instance is already running // none means some other instance is already running
log::info!("service already running, exiting"); log::info!("service already running, exiting");
@@ -74,98 +112,67 @@ impl Server {
}; };
let (mut consumer, mut producer) = tokio::join!(consumer::create(), producer::create()); let (mut consumer, mut producer) = tokio::join!(consumer::create(), producer::create());
// create dns resolver
let resolver = dns::DnsResolver::new().await?;
// bind the udp socket
let listen_addr = SocketAddr::new("0.0.0.0".parse().unwrap(), config.port);
let mut socket = UdpSocket::bind(listen_addr).await?;
let (frontend_tx, mut frontend_rx) = tokio::sync::mpsc::channel(1); let (frontend_tx, mut frontend_rx) = tokio::sync::mpsc::channel(1);
// create client manager
let client_manager_rc = Rc::new(RefCell::new(ClientManager::new()));
let state_rc = Rc::new(Cell::new(State::Receiving));
// channel to notify producer
let (producer_notify_tx, mut producer_notify_rx) = tokio::sync::mpsc::channel(32); let (producer_notify_tx, mut producer_notify_rx) = tokio::sync::mpsc::channel(32);
// channel to notify consumer
let (consumer_notify_tx, mut consumer_notify_rx) = tokio::sync::mpsc::channel(32); let (consumer_notify_tx, mut consumer_notify_rx) = tokio::sync::mpsc::channel(32);
// channel to request dns resolver
let (resolve_tx, mut resolve_rx) = tokio::sync::mpsc::channel(32); let (resolve_tx, mut resolve_rx) = tokio::sync::mpsc::channel(32);
// channel to send events to frontends
let (frontend_notify_tx, mut frontend_notify_rx) = tokio::sync::mpsc::channel(32); let (frontend_notify_tx, mut frontend_notify_rx) = tokio::sync::mpsc::channel(32);
// channels for udp send / receive
let (receiver_tx, mut receiver_rx) = tokio::sync::mpsc::channel(32); let (receiver_tx, mut receiver_rx) = tokio::sync::mpsc::channel(32);
let (sender_tx, mut sender_rx) = tokio::sync::mpsc::channel(32); let (sender_tx, mut sender_rx) = tokio::sync::mpsc::channel(32);
let (port_tx, mut port_rx) = tokio::sync::mpsc::channel(32); let (port_tx, mut port_rx) = tokio::sync::mpsc::channel(32);
let (timer_tx, mut timer_rx) = tokio::sync::mpsc::channel(1);
// add clients from config
for (c, h, port, p) in config.get_clients().into_iter() {
Self::add_client(
&resolve_tx,
&client_manager_rc,
&mut frontend,
h,
c,
port,
p,
)
.await;
}
// event producer // event producer
let client_manager = client_manager_rc.clone();
let state = state_rc.clone();
let sender_ch = sender_tx.clone(); let sender_ch = sender_tx.clone();
let producer_task = tokio::task::spawn_local(async move { let timer_ch = timer_tx.clone();
let server = self.clone();
let mut producer_task = tokio::task::spawn_local(async move {
loop { loop {
tokio::select! { tokio::select! {
e = producer.next() => { event = producer.next() => {
let (client, event) = match e { let event = event.ok_or(anyhow!("event producer closed"))??;
Some(e) => e?, log::debug!("producer event: {event:?}");
None => return Err::<(), anyhow::Error>(anyhow!("event producer closed")), server.handle_producer_event(&mut producer, &sender_ch, &timer_ch, event).await;
};
Self::handle_producer_event(&mut producer, &client_manager, &state, &sender_ch, client, event).await;
} }
e = producer_notify_rx.recv() => { e = producer_notify_rx.recv() => {
log::debug!("producer notify rx: {e:?}");
match e { match e {
Some(e) => match e { Some(e) => match e {
ProducerEvent::Release => producer.release(), ProducerEvent::Release => {
producer.release();
server.state.replace(State::Receiving);
}
ProducerEvent::ClientEvent(e) => producer.notify(e), ProducerEvent::ClientEvent(e) => producer.notify(e),
ProducerEvent::Terminate => break,
}, },
None => break Ok(()), None => break,
} }
} }
} }
} }
anyhow::Ok(())
}); });
// event consumer // event consumer
let client_manager = client_manager_rc.clone();
let state = state_rc.clone();
let producer_notify = producer_notify_tx.clone(); let producer_notify = producer_notify_tx.clone();
let receiver_task = tokio::task::spawn_local(async move { let sender_ch = sender_tx.clone();
let server = self.clone();
let mut consumer_task = tokio::task::spawn_local(async move {
let mut last_ignored = None; let mut last_ignored = None;
loop { loop {
tokio::select! { tokio::select! {
udp_event = receiver_rx.recv() => { udp_event = receiver_rx.recv() => {
let udp_event = match udp_event { let udp_event = udp_event.ok_or(anyhow!("receiver closed"))??;
Some(Ok(e)) => e, server.handle_udp_rx(&producer_notify, &mut consumer, &sender_ch, &mut last_ignored, udp_event, &timer_tx).await;
Some(Err(e)) => return Err::<(), anyhow::Error>(anyhow!("{}", e)),
None => return Err::<(), anyhow::Error>(anyhow!("receiver closed")),
};
Self::handle_udp_rx(&client_manager, &producer_notify, &mut consumer, &sender_tx, &state, &mut last_ignored, udp_event).await;
} }
consumer_event = consumer_notify_rx.recv() => { consumer_event = consumer_notify_rx.recv() => {
match consumer_event { match consumer_event {
Some(e) => match e { Some(e) => match e {
ConsumerEvent::ClientEvent(e) => consumer.notify(e).await, ConsumerEvent::ClientEvent(e) => consumer.notify(e).await,
ConsumerEvent::ReleaseKeys(c) => server.release_keys(&mut consumer, c).await,
ConsumerEvent::Terminate => break,
}, },
None => break, None => break,
} }
@@ -173,14 +180,29 @@ impl Server {
_ = consumer.dispatch() => { } _ = consumer.dispatch() => { }
} }
} }
// release potentially still pressed keys
let clients = server
.client_manager
.borrow()
.get_client_states()
.map(|s| s.client.handle)
.collect::<Vec<_>>();
for client in clients {
server.release_keys(&mut consumer, client).await;
}
// destroy consumer // destroy consumer
consumer.destroy().await; consumer.destroy().await;
Ok(()) anyhow::Ok(())
}); });
// frontend listener // frontend listener
let client_manager = client_manager_rc.clone(); let server = self.clone();
let frontend_task = tokio::task::spawn_local(async move { let producer_notify = producer_notify_tx.clone();
let consumer_notify = consumer_notify_tx.clone();
let frontend_ch = frontend_tx.clone();
let mut frontend_task = tokio::task::spawn_local(async move {
loop { loop {
tokio::select! { tokio::select! {
stream = frontend.accept() => { stream = frontend.accept() => {
@@ -191,32 +213,29 @@ impl Server {
continue; continue;
} }
}; };
Self::handle_frontend_stream(&client_manager, &mut frontend, &frontend_tx, stream).await; server.handle_frontend_stream(&mut frontend, &frontend_ch, stream).await;
} }
event = frontend_rx.recv() => { event = frontend_rx.recv() => {
let frontend_event = match event { let frontend_event = event.ok_or(anyhow!("frontend channel closed"))?;
Some(e) => e, if server.handle_frontend_event(&producer_notify, &consumer_notify, &resolve_tx, &mut frontend, &port_tx, frontend_event).await {
None => return Err::<(), anyhow::Error>(anyhow!("frontend channel closed")), break;
};
let exit = Self::handle_frontend_event(&producer_notify_tx, &consumer_notify_tx, &client_manager, &resolve_tx, &mut frontend, &port_tx, frontend_event).await;
if exit {
return Ok(());
} }
} }
notify = frontend_notify_rx.recv() => { notify = frontend_notify_rx.recv() => {
let notify = match notify { let notify = notify.ok_or(anyhow!("frontend notify closed"))?;
Some(n) => n,
None => return Err::<(), anyhow::Error>(anyhow!("frontend notify closed")),
};
let _ = frontend.notify_all(notify).await; let _ = frontend.notify_all(notify).await;
} }
} }
} }
anyhow::Ok(())
}); });
// dns resolver // dns resolver
let client_manager = client_manager_rc.clone();
let resolver_task = tokio::task::spawn_local(async move { // create dns resolver
let resolver = dns::DnsResolver::new().await?;
let server = self.clone();
let mut resolver_task = tokio::task::spawn_local(async move {
loop { loop {
let (host, client): (String, ClientHandle) = match resolve_rx.recv().await { let (host, client): (String, ClientHandle) = match resolve_rx.recv().await {
Some(r) => r, Some(r) => r,
@@ -229,7 +248,7 @@ impl Server {
continue; continue;
} }
}; };
if let Some(state) = client_manager.borrow_mut().get_mut(client) { if let Some(state) = server.client_manager.borrow_mut().get_mut(client) {
let port = state.client.port; let port = state.client.port;
let mut addrs = HashSet::from_iter( let mut addrs = HashSet::from_iter(
state state
@@ -247,8 +266,11 @@ impl Server {
} }
}); });
// bind the udp socket
let listen_addr = SocketAddr::new("0.0.0.0".parse().unwrap(), self.port.get());
let mut socket = UdpSocket::bind(listen_addr).await?;
// udp task // udp task
let udp_task = tokio::task::spawn_local(async move { let mut udp_task = tokio::task::spawn_local(async move {
loop { loop {
tokio::select! { tokio::select! {
event = receive_event(&socket) => { event = receive_event(&socket) => {
@@ -266,16 +288,16 @@ impl Server {
let Some(port) = port else { let Some(port) = port else {
break; break;
}; };
let current_port = socket.local_addr().unwrap().port();
if current_port == port { if socket.local_addr().unwrap().port() == port {
let _ = frontend_notify_tx.send(FrontendNotify::NotifyPortChange(port, None)).await;
continue; continue;
}; }
let listen_addr = SocketAddr::new("0.0.0.0".parse().unwrap(), port); let listen_addr = SocketAddr::new("0.0.0.0".parse().unwrap(), port);
match UdpSocket::bind(listen_addr).await { match UdpSocket::bind(listen_addr).await {
Ok(new_socket) => { Ok(new_socket) => {
socket = new_socket; socket = new_socket;
server.port.replace(port);
let _ = frontend_notify_tx.send(FrontendNotify::NotifyPortChange(port, None)).await; let _ = frontend_notify_tx.send(FrontendNotify::NotifyPortChange(port, None)).await;
} }
Err(e) => { Err(e) => {
@@ -293,37 +315,157 @@ impl Server {
} }
}); });
let reaper = task::spawn_local(async move { // timer task
tokio::select! { let server = self.clone();
_ = signal::ctrl_c() => { let sender_ch = sender_tx.clone();
log::info!("terminating service"); let consumer_notify = consumer_notify_tx.clone();
}, let producer_notify = producer_notify_tx.clone();
_ = producer_task => { let mut live_tracker = tokio::task::spawn_local(async move {
// TODO restart producer? loop {
} // wait for wake up signal
_ = receiver_task => { let Some(_): Option<()> = timer_rx.recv().await else {
// TODO restart producer? break;
} };
_ = frontend_task => { loop {
// frontend exited => exit requested let receiving = server.state.get() == State::Receiving;
} let (ping_clients, ping_addrs) = {
_ = resolver_task => { let mut client_manager = server.client_manager.borrow_mut();
// resolver exited
} let ping_clients: Vec<ClientHandle> = if receiving {
_ = udp_task => { // if receiving we care about clients with pressed keys
// udp exited client_manager
.get_client_states_mut()
.filter(|s| !s.pressed_keys.is_empty())
.map(|s| s.client.handle)
.collect()
} else {
// if sending we care about the active client
server.active_client.get().iter().cloned().collect()
};
// get relevant socket addrs for clients
let ping_addrs: Vec<SocketAddr> = {
ping_clients
.iter()
.flat_map(|&c| client_manager.get(c))
.flat_map(|state| {
if let Some(a) = state.active_addr {
vec![a]
} else {
state.client.addrs.iter().cloned().collect()
}
})
.collect()
};
// reset alive
for state in client_manager.get_client_states_mut() {
state.alive = false;
}
(ping_clients, ping_addrs)
};
if receiving && ping_clients.is_empty() {
// receiving and no client has pressed keys
// -> no need to keep pinging
break;
}
// ping clients
for addr in ping_addrs {
if sender_ch.send((Event::Ping(), addr)).await.is_err() {
break;
}
}
// give clients time to resond
if receiving {
log::debug!("waiting {MAX_RESPONSE_TIME:?} for response from client with pressed keys ...");
} else {
log::debug!("state: {:?} => waiting {MAX_RESPONSE_TIME:?} for client to respond ...", server.state.get());
}
tokio::time::sleep(MAX_RESPONSE_TIME).await;
// when anything is received from a client,
// the alive flag gets set
let unresponsive_clients: Vec<_> = {
let client_manager = server.client_manager.borrow();
ping_clients
.iter()
.filter_map(|&c| match client_manager.get(c) {
Some(state) if !state.alive => Some(c),
_ => None,
})
.collect()
};
// we may not be receiving anymore but we should respond
// to the original state and not the "new" one
if receiving {
for c in unresponsive_clients {
log::warn!("device not responding, releasing keys!");
let _ = consumer_notify.send(ConsumerEvent::ReleaseKeys(c)).await;
}
} else {
// release pointer if the active client has not responded
if !unresponsive_clients.is_empty() {
log::warn!("client not responding, releasing pointer!");
server.state.replace(State::Receiving);
let _ = producer_notify.send(ProducerEvent::Release).await;
}
}
} }
} }
}); });
reaper.await?; // initial sync of clients
frontend_tx.send(FrontendEvent::Enumerate()).await?;
tokio::select! {
_ = signal::ctrl_c() => {
log::info!("terminating service");
},
_ = &mut producer_task => {
// TODO restart producer?
}
_ = &mut consumer_task => {
// TODO restart producer?
}
_ = &mut frontend_task => {
// frontend exited => exit requested
}
_ = &mut resolver_task => {
// resolver exited
}
_ = &mut udp_task => {
// udp exited
}
_ = &mut live_tracker => {
// live tracker exited
}
}
let _ = consumer_notify_tx.send(ConsumerEvent::Terminate).await;
let _ = producer_notify_tx.send(ProducerEvent::Terminate).await;
let _ = frontend_tx.send(FrontendEvent::Shutdown()).await;
let (a, b, c) = tokio::join!(producer_task, consumer_task, frontend_task);
a??;
b??;
c??;
resolver_task.abort();
udp_task.abort();
live_tracker.abort();
Ok(()) Ok(())
} }
pub async fn add_client( pub async fn add_client(
&self,
resolver_tx: &Sender<(String, ClientHandle)>, resolver_tx: &Sender<(String, ClientHandle)>,
client_manager: &Rc<RefCell<ClientManager>>,
frontend: &mut FrontendListener, frontend: &mut FrontendListener,
hostname: Option<String>, hostname: Option<String>,
addr: HashSet<IpAddr>, addr: HashSet<IpAddr>,
@@ -336,7 +478,8 @@ impl Server {
hostname.as_deref().unwrap_or(""), hostname.as_deref().unwrap_or(""),
&addr &addr
); );
let client = client_manager let client = self
.client_manager
.borrow_mut() .borrow_mut()
.add_client(hostname.clone(), addr, port, pos); .add_client(hostname.clone(), addr, port, pos);
@@ -352,13 +495,13 @@ impl Server {
} }
pub async fn activate_client( pub async fn activate_client(
&self,
producer_notify_tx: &Sender<ProducerEvent>, producer_notify_tx: &Sender<ProducerEvent>,
consumer_notify_tx: &Sender<ConsumerEvent>, consumer_notify_tx: &Sender<ConsumerEvent>,
client_manager: &Rc<RefCell<ClientManager>>,
client: ClientHandle, client: ClientHandle,
active: bool, active: bool,
) { ) {
let (client, pos) = match client_manager.borrow_mut().get_mut(client) { let (client, pos) = match self.client_manager.borrow_mut().get_mut(client) {
Some(state) => { Some(state) => {
state.active = active; state.active = active;
(state.client.handle, state.client.pos) (state.client.handle, state.client.pos)
@@ -383,7 +526,7 @@ impl Server {
} }
pub async fn remove_client( pub async fn remove_client(
client_manager: &Rc<RefCell<ClientManager>>, &self,
producer_notify_tx: &Sender<ProducerEvent>, producer_notify_tx: &Sender<ProducerEvent>,
consumer_notify_tx: &Sender<ConsumerEvent>, consumer_notify_tx: &Sender<ConsumerEvent>,
frontend: &mut FrontendListener, frontend: &mut FrontendListener,
@@ -396,7 +539,8 @@ impl Server {
.send(ConsumerEvent::ClientEvent(ClientEvent::Destroy(client))) .send(ConsumerEvent::ClientEvent(ClientEvent::Destroy(client)))
.await; .await;
let Some(client) = client_manager let Some(client) = self
.client_manager
.borrow_mut() .borrow_mut()
.remove_client(client) .remove_client(client)
.map(|s| s.client.handle) .map(|s| s.client.handle)
@@ -413,15 +557,15 @@ impl Server {
} }
async fn update_client( async fn update_client(
&self,
producer_notify_tx: &Sender<ProducerEvent>, producer_notify_tx: &Sender<ProducerEvent>,
consumer_notify_tx: &Sender<ConsumerEvent>, consumer_notify_tx: &Sender<ConsumerEvent>,
resolve_tx: &Sender<(String, ClientHandle)>, resolve_tx: &Sender<(String, ClientHandle)>,
client_manager: &Rc<RefCell<ClientManager>>,
client_update: ClientUpdate, client_update: ClientUpdate,
) { ) {
let (hostname, handle, active) = { let (hostname, handle, active) = {
// retrieve state // retrieve state
let mut client_manager = client_manager.borrow_mut(); let mut client_manager = self.client_manager.borrow_mut();
let Some(state) = client_manager.get_mut(client_update.client) else { let Some(state) = client_manager.get_mut(client_update.client) else {
return; return;
}; };
@@ -443,7 +587,6 @@ impl Server {
}) })
.collect(); .collect();
state state
.client
.active_addr .active_addr
.map(|a| SocketAddr::new(a.ip(), client_update.port)); .map(|a| SocketAddr::new(a.ip(), client_update.port));
} }
@@ -451,7 +594,7 @@ impl Server {
// update hostname // update hostname
if state.client.hostname != client_update.hostname { if state.client.hostname != client_update.hostname {
state.client.addrs = HashSet::new(); state.client.addrs = HashSet::new();
state.client.active_addr = None; state.active_addr = None;
state.client.hostname = client_update.hostname; state.client.hostname = client_update.hostname;
} }
@@ -496,18 +639,18 @@ impl Server {
} }
async fn handle_udp_rx( async fn handle_udp_rx(
client_manager: &Rc<RefCell<ClientManager>>, &self,
producer_notify_tx: &Sender<ProducerEvent>, producer_notify_tx: &Sender<ProducerEvent>,
consumer: &mut Box<dyn EventConsumer>, consumer: &mut Box<dyn EventConsumer>,
sender_tx: &Sender<(Event, SocketAddr)>, sender_tx: &Sender<(Event, SocketAddr)>,
state: &Rc<Cell<State>>,
last_ignored: &mut Option<SocketAddr>, last_ignored: &mut Option<SocketAddr>,
event: (Event, SocketAddr), event: (Event, SocketAddr),
timer_tx: &Sender<()>,
) { ) {
let (event, addr) = event; let (event, addr) = event;
// get handle for addr // get handle for addr
let handle = match client_manager.borrow().get_client(addr) { let handle = match self.client_manager.borrow().get_client(addr) {
Some(a) => a, Some(a) => a,
None => { None => {
if last_ignored.is_none() || last_ignored.is_some() && last_ignored.unwrap() != addr if last_ignored.is_none() || last_ignored.is_some() && last_ignored.unwrap() != addr
@@ -524,7 +667,7 @@ impl Server {
log::trace!("{:20} <-<-<-<------ {addr} ({handle})", event.to_string()); log::trace!("{:20} <-<-<-<------ {addr} ({handle})", event.to_string());
{ {
let mut client_manager = client_manager.borrow_mut(); let mut client_manager = self.client_manager.borrow_mut();
let client_state = match client_manager.get_mut(handle) { let client_state = match client_manager.get_mut(handle) {
Some(s) => s, Some(s) => s,
None => { None => {
@@ -534,9 +677,9 @@ impl Server {
}; };
// reset ttl for client and // reset ttl for client and
client_state.last_seen = Some(Instant::now()); client_state.alive = true;
// set addr as new default for this client // set addr as new default for this client
client_state.client.active_addr = Some(addr); client_state.active_addr = Some(addr);
} }
match (event, addr) { match (event, addr) {
@@ -544,24 +687,49 @@ impl Server {
(Event::Ping(), addr) => { (Event::Ping(), addr) => {
let _ = sender_tx.send((Event::Pong(), addr)).await; let _ = sender_tx.send((Event::Pong(), addr)).await;
} }
(Event::Disconnect(), _) => {
self.release_keys(consumer, handle).await;
}
(event, addr) => { (event, addr) => {
// tell clients that we are ready to receive events // tell clients that we are ready to receive events
if let Event::Enter() = event { if let Event::Enter() = event {
let _ = sender_tx.send((Event::Leave(), addr)).await; let _ = sender_tx.send((Event::Leave(), addr)).await;
} }
match state.get() {
match self.state.get() {
State::Sending => { State::Sending => {
if let Event::Leave() = event { if let Event::Leave() = event {
// ignore additional leave events that may // ignore additional leave events that may
// have been sent for redundancy // have been sent for redundancy
} else { } else {
// upon receiving any event, we go back to receiving mode // upon receiving any event, we go back to receiving mode
self.state.replace(State::Receiving);
let _ = producer_notify_tx.send(ProducerEvent::Release).await; let _ = producer_notify_tx.send(ProducerEvent::Release).await;
state.replace(State::Receiving);
log::trace!("STATE ===> Receiving"); log::trace!("STATE ===> Receiving");
} }
} }
State::Receiving => { State::Receiving => {
if let Event::Keyboard(KeyboardEvent::Key {
time: _,
key,
state,
}) = event
{
let mut client_manager = self.client_manager.borrow_mut();
let client_state =
if let Some(client_state) = client_manager.get_mut(handle) {
client_state
} else {
log::error!("unknown handle");
return;
};
if state == 0 {
client_state.pressed_keys.remove(&key);
} else {
client_state.pressed_keys.insert(key);
let _ = timer_tx.try_send(());
}
}
// consume event // consume event
consumer.consume(event, handle).await; consumer.consume(event, handle).await;
log::trace!("{event:?} => consumer"); log::trace!("{event:?} => consumer");
@@ -572,59 +740,33 @@ impl Server {
// be on the way until a leave event occurs // be on the way until a leave event occurs
// telling us the client registered the enter // telling us the client registered the enter
if let Event::Leave() = event { if let Event::Leave() = event {
state.replace(State::Sending); self.state.replace(State::Sending);
log::trace!("STATE ===> Sending"); log::trace!("STATE ===> Sending");
} }
// entering a client that is waiting for a leave // entering a client that is waiting for a leave
// event should still be possible // event should still be possible
if let Event::Enter() = event { if let Event::Enter() = event {
state.replace(State::Receiving); self.state.replace(State::Receiving);
log::trace!("STATE ===> Receiving");
let _ = producer_notify_tx.send(ProducerEvent::Release).await; let _ = producer_notify_tx.send(ProducerEvent::Release).await;
log::trace!("STATE ===> Receiving");
} }
} }
} }
} }
} }
let pong = {
let mut client_manager = client_manager.borrow_mut();
let client_state = match client_manager.get_mut(handle) {
Some(s) => s,
None => {
log::error!("unknown handle");
return;
}
};
// let the server know we are still alive once every second
if client_state.last_replied.is_none()
|| client_state.last_replied.is_some()
&& client_state.last_replied.unwrap().elapsed() > Duration::from_secs(1)
{
client_state.last_replied = Some(Instant::now());
true
} else {
false
}
};
if pong {
let _ = sender_tx.send((Event::Pong(), addr)).await;
}
} }
const RELEASE_MODIFIERDS: u32 = 77; // ctrl+shift+super+alt const RELEASE_MODIFIERDS: u32 = 77; // ctrl+shift+super+alt
async fn handle_producer_event( async fn handle_producer_event(
&self,
producer: &mut Box<dyn EventProducer>, producer: &mut Box<dyn EventProducer>,
client_manager: &Rc<RefCell<ClientManager>>,
state: &Rc<Cell<State>>,
sender_tx: &Sender<(Event, SocketAddr)>, sender_tx: &Sender<(Event, SocketAddr)>,
c: ClientHandle, timer_tx: &Sender<()>,
mut e: Event, event: (ClientHandle, Event),
) { ) {
let (c, mut e) = event;
log::trace!("producer: ({c}) {e:?}"); log::trace!("producer: ({c}) {e:?}");
if let Event::Keyboard(crate::event::KeyboardEvent::Modifiers { if let Event::Keyboard(crate::event::KeyboardEvent::Modifiers {
@@ -636,31 +778,26 @@ impl Server {
{ {
if mods_depressed == Self::RELEASE_MODIFIERDS { if mods_depressed == Self::RELEASE_MODIFIERDS {
producer.release(); producer.release();
state.replace(State::Receiving); self.state.replace(State::Receiving);
log::trace!("STATE ===> Receiving"); log::trace!("STATE ===> Receiving");
// send an event to release all the modifiers // send an event to release all the modifiers
e = Event::Keyboard(KeyboardEvent::Modifiers { e = Event::Disconnect();
mods_depressed: 0,
mods_latched: 0,
mods_locked: 0,
group: 0,
});
} }
} }
let (addr, enter, ping_addrs) = { let (addr, enter, start_timer) = {
let mut enter = false; let mut enter = false;
let mut ping_addrs: Option<Vec<SocketAddr>> = None; let mut start_timer = false;
// get client state for handle // get client state for handle
let mut client_manager = client_manager.borrow_mut(); let mut client_manager = self.client_manager.borrow_mut();
let client_state = match client_manager.get_mut(c) { let client_state = match client_manager.get_mut(c) {
Some(state) => state, Some(state) => state,
None => { None => {
// should not happen // should not happen
log::warn!("unknown client!"); log::warn!("unknown client!");
producer.release(); producer.release();
state.replace(State::Receiving); self.state.replace(State::Receiving);
log::trace!("STATE ===> Receiving"); log::trace!("STATE ===> Receiving");
return; return;
} }
@@ -668,59 +805,30 @@ impl Server {
// if we just entered the client we want to send additional enter events until // if we just entered the client we want to send additional enter events until
// we get a leave event // we get a leave event
if let State::Receiving | State::AwaitingLeave = state.get() { if let Event::Enter() = e {
state.replace(State::AwaitingLeave); self.state.replace(State::AwaitingLeave);
self.active_client.replace(Some(client_state.client.handle));
log::trace!("Active client => {}", client_state.client.handle);
start_timer = true;
log::trace!("STATE ===> AwaitingLeave"); log::trace!("STATE ===> AwaitingLeave");
enter = true; enter = true;
} }
let last_seen = match client_state.last_seen { (client_state.active_addr, enter, start_timer)
None => Duration::MAX,
Some(i) => i.elapsed(),
};
let last_pinged = match client_state.last_ping {
None => Duration::MAX,
Some(i) => i.elapsed(),
};
// not seen for one second but pinged at least 500ms ago
if last_seen > Duration::from_secs(1)
&& last_pinged > Duration::from_millis(500)
&& last_pinged < Duration::from_secs(1)
{
// client unresponsive -> set state to receiving
if state.get() != State::Receiving {
log::info!("client not responding - releasing pointer");
producer.release();
state.replace(State::Receiving);
log::trace!("STATE ===> Receiving");
}
}
// last ping > 500ms ago -> ping all interfaces
if last_pinged > Duration::from_millis(500) {
ping_addrs = Some(client_state.client.addrs.iter().cloned().collect());
client_state.last_ping = Some(Instant::now());
}
(client_state.client.active_addr, enter, ping_addrs)
}; };
if start_timer {
let _ = timer_tx.try_send(());
}
if let Some(addr) = addr { if let Some(addr) = addr {
if enter { if enter {
let _ = sender_tx.send((Event::Enter(), addr)).await; let _ = sender_tx.send((Event::Enter(), addr)).await;
} }
let _ = sender_tx.send((e, addr)).await; let _ = sender_tx.send((e, addr)).await;
} }
if let Some(addrs) = ping_addrs {
for addr in addrs {
let _ = sender_tx.send((Event::Ping(), addr)).await;
}
}
} }
async fn handle_frontend_stream( async fn handle_frontend_stream(
client_manager: &Rc<RefCell<ClientManager>>, &self,
frontend: &mut FrontendListener, frontend: &mut FrontendListener,
frontend_tx: &Sender<FrontendEvent>, frontend_tx: &Sender<FrontendEvent>,
#[cfg(unix)] mut stream: ReadHalf<UnixStream>, #[cfg(unix)] mut stream: ReadHalf<UnixStream>,
@@ -748,13 +856,13 @@ impl Server {
} }
} }
}); });
Self::enumerate(client_manager, frontend).await; self.enumerate(frontend).await;
} }
async fn handle_frontend_event( async fn handle_frontend_event(
&self,
producer_notify_tx: &Sender<ProducerEvent>, producer_notify_tx: &Sender<ProducerEvent>,
consumer_notify_tx: &Sender<ConsumerEvent>, consumer_notify_tx: &Sender<ConsumerEvent>,
client_manager: &Rc<RefCell<ClientManager>>,
resolve_tx: &Sender<(String, ClientHandle)>, resolve_tx: &Sender<(String, ClientHandle)>,
frontend: &mut FrontendListener, frontend: &mut FrontendListener,
port_tx: &Sender<u16>, port_tx: &Sender<u16>,
@@ -763,41 +871,21 @@ impl Server {
log::debug!("frontend: {event:?}"); log::debug!("frontend: {event:?}");
match event { match event {
FrontendEvent::AddClient(hostname, port, pos) => { FrontendEvent::AddClient(hostname, port, pos) => {
Self::add_client( self.add_client(resolve_tx, frontend, hostname, HashSet::new(), port, pos)
resolve_tx, .await;
client_manager,
frontend,
hostname,
HashSet::new(),
port,
pos,
)
.await;
} }
FrontendEvent::ActivateClient(client, active) => { FrontendEvent::ActivateClient(client, active) => {
Self::activate_client( self.activate_client(producer_notify_tx, consumer_notify_tx, client, active)
producer_notify_tx, .await
consumer_notify_tx,
client_manager,
client,
active,
)
.await
} }
FrontendEvent::ChangePort(port) => { FrontendEvent::ChangePort(port) => {
let _ = port_tx.send(port).await; let _ = port_tx.send(port).await;
} }
FrontendEvent::DelClient(client) => { FrontendEvent::DelClient(client) => {
Self::remove_client( self.remove_client(producer_notify_tx, consumer_notify_tx, frontend, client)
client_manager, .await;
producer_notify_tx,
consumer_notify_tx,
frontend,
client,
)
.await;
} }
FrontendEvent::Enumerate() => Self::enumerate(client_manager, frontend).await, FrontendEvent::Enumerate() => self.enumerate(frontend).await,
FrontendEvent::Shutdown() => { FrontendEvent::Shutdown() => {
log::info!("terminating gracefully..."); log::info!("terminating gracefully...");
return true; return true;
@@ -809,11 +897,10 @@ impl Server {
port, port,
pos, pos,
}; };
Self::update_client( self.update_client(
producer_notify_tx, producer_notify_tx,
consumer_notify_tx, consumer_notify_tx,
resolve_tx, resolve_tx,
client_manager,
client_update, client_update,
) )
.await .await
@@ -822,11 +909,41 @@ impl Server {
false false
} }
async fn enumerate( async fn release_keys(&self, consumer: &mut Box<dyn EventConsumer>, client: ClientHandle) {
client_manager: &Rc<RefCell<ClientManager>>, let keys = self
frontend: &mut FrontendListener, .client_manager
) { .borrow_mut()
let clients = client_manager .get_mut(client)
.iter_mut()
.flat_map(|s| s.pressed_keys.drain())
.collect::<Vec<_>>();
for key in keys {
let event = Event::Keyboard(KeyboardEvent::Key {
time: 0,
key,
state: 0,
});
consumer.consume(event, client).await;
if let Ok(key) = scancode::Linux::try_from(key) {
log::warn!("releasing stuck key: {key:?}");
}
}
let modifiers_event = KeyboardEvent::Modifiers {
mods_depressed: 0,
mods_latched: 0,
mods_locked: 0,
group: 0,
};
consumer
.consume(Event::Keyboard(modifiers_event), client)
.await;
}
async fn enumerate(&self, frontend: &mut FrontendListener) {
let clients = self
.client_manager
.borrow() .borrow()
.get_client_states() .get_client_states()
.map(|s| (s.client.clone(), s.active)) .map(|s| (s.client.clone(), s.active))
@@ -840,14 +957,10 @@ impl Server {
} }
} }
async fn receive_event( async fn receive_event(socket: &UdpSocket) -> anyhow::Result<(Event, SocketAddr)> {
socket: &UdpSocket,
) -> std::result::Result<(Event, SocketAddr), Box<dyn Error>> {
let mut buf = vec![0u8; 22]; let mut buf = vec![0u8; 22];
match socket.recv_from(&mut buf).await { let (_amt, src) = socket.recv_from(&mut buf).await?;
Ok((_amt, src)) => Ok((Event::try_from(buf)?, src)), Ok((Event::try_from(buf)?, src))
Err(e) => Err(Box::new(e)),
}
} }
fn send_event(sock: &UdpSocket, e: Event, addr: SocketAddr) -> Result<usize> { fn send_event(sock: &UdpSocket, e: Event, addr: SocketAddr) -> Result<usize> {