mirror of
https://github.com/feschber/lan-mouse.git
synced 2026-03-31 09:00:54 +03:00
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:
committed by
Ferdinand Schober
parent
6a6d9a9fa9
commit
64e3bf3ff4
@@ -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();
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
71
src/event.rs
71
src/event.rs
@@ -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(),
|
||||||
})),
|
})),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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(())
|
||||||
|
|||||||
611
src/server.rs
611
src/server.rs
@@ -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> {
|
||||||
|
|||||||
Reference in New Issue
Block a user