major refactor

every instance of lan-mouse can now simultaneously send and receive
events
This commit is contained in:
Ferdinand Schober
2023-01-30 19:15:58 +01:00
parent 5c60e2eb58
commit 5222f54eee
15 changed files with 923 additions and 528 deletions

View File

@@ -1,147 +0,0 @@
use lan_mouse::{
config::Config,
protocol::{self, DataRequest},
};
use std::{
io::{BufWriter, Write},
os::unix::prelude::AsRawFd,
};
use wayland_protocols_wlr::virtual_pointer::v1::client::{
zwlr_virtual_pointer_manager_v1::ZwlrVirtualPointerManagerV1 as VpManager,
zwlr_virtual_pointer_v1::ZwlrVirtualPointerV1 as Vp,
};
use wayland_protocols_misc::zwp_virtual_keyboard_v1::client::{
zwp_virtual_keyboard_manager_v1::ZwpVirtualKeyboardManagerV1 as VkManager,
zwp_virtual_keyboard_v1::ZwpVirtualKeyboardV1 as Vk,
};
use wayland_client::{
delegate_noop,
globals::{registry_queue_init, GlobalListContents},
protocol::{wl_keyboard, wl_pointer, wl_registry, wl_seat},
Connection, Dispatch, EventQueue, QueueHandle,
};
use tempfile;
// App State, implements Dispatch event handlers
struct App;
fn main() {
let config = Config::new("config.toml").unwrap();
let conn = Connection::connect_to_env().unwrap();
let (globals, queue) = registry_queue_init::<App>(&conn).unwrap();
let qh = queue.handle();
let vpm: VpManager = globals.bind(&qh, 1..=1, ()).unwrap();
let vkm: VkManager = globals.bind(&qh, 1..=1, ()).unwrap();
let seat: wl_seat::WlSeat = globals.bind(&qh, 7..=8, ()).unwrap();
let pointer: Vp = vpm.create_virtual_pointer(None, &qh, ());
let keyboard: Vk = vkm.create_virtual_keyboard(&seat, &qh, ());
let connection = protocol::Connection::new(config);
let data = loop {
match connection.receive_data(DataRequest::KeyMap) {
Some(data) => break data,
None => {}
}
};
// TODO use shm_open
let f = tempfile::tempfile().unwrap();
let mut buf = BufWriter::new(&f);
buf.write_all(&data[..]).unwrap();
buf.flush().unwrap();
keyboard.keymap(1, f.as_raw_fd(), data.len() as u32);
loop {
receive_event(&connection, &pointer, &keyboard, &queue).unwrap();
}
}
/// main loop handling udp packets
fn receive_event(
connection: &protocol::Connection,
pointer: &Vp,
keyboard: &Vk,
q: &EventQueue<App>,
) -> std::io::Result<()> {
let event = if let Some(event) = connection.receive_event() {
event
} else {
return Ok(());
};
match event {
protocol::Event::Pointer(e) => match e {
wl_pointer::Event::Motion {
time,
surface_x,
surface_y,
} => {
pointer.motion(time, surface_x, surface_y);
pointer.frame();
}
wl_pointer::Event::Button {
serial: _,
time: t,
button: b,
state: s,
} => {
pointer.button(t, b, s.into_result().unwrap());
pointer.frame();
}
wl_pointer::Event::Axis {
time: t,
axis: a,
value: v,
} => {
pointer.axis(t, a.into_result().unwrap(), v);
pointer.frame();
}
wl_pointer::Event::Frame => {
pointer.frame();
}
_ => todo!(),
},
protocol::Event::Keyboard(e) => match e {
wl_keyboard::Event::Key {
serial: _,
time: t,
key: k,
state: s,
} => {
keyboard.key(t, k, u32::from(s));
}
wl_keyboard::Event::Modifiers {
serial: _,
mods_depressed,
mods_latched,
mods_locked,
group,
} => {
keyboard.modifiers(mods_depressed, mods_latched, mods_locked, group);
}
_ => todo!(),
},
}
q.flush().unwrap();
Ok(())
}
delegate_noop!(App: Vp);
delegate_noop!(App: Vk);
delegate_noop!(App: VpManager);
delegate_noop!(App: VkManager);
delegate_noop!(App: wl_seat::WlSeat);
impl Dispatch<wl_registry::WlRegistry, GlobalListContents> for App {
fn event(
_: &mut App,
_: &wl_registry::WlRegistry,
_: wl_registry::Event,
_: &GlobalListContents,
_: &Connection,
_: &QueueHandle<App>,
) {
}
}

57
src/client.rs Normal file
View File

@@ -0,0 +1,57 @@
use std::net::SocketAddr;
#[derive(Eq, Hash, PartialEq, Clone, Copy)]
pub enum Position {
Left, Right, Top, Bottom,
}
#[derive(Clone, Copy)]
pub struct Client {
pub addr: SocketAddr,
pub pos: Position,
pub handle: ClientHandle,
}
impl Client {
pub fn handle(&self) -> ClientHandle {
return self.handle;
}
}
pub enum ClientEvent {
Create(Client),
Destroy(Client),
}
pub struct ClientManager {
next_id: u32,
clients: Vec<Client>,
}
pub type ClientHandle = u32;
impl ClientManager {
fn new_id(&mut self) -> ClientHandle {
self.next_id += 1;
self.next_id
}
pub fn new() -> Self {
ClientManager {
next_id: 0,
clients: Vec::new(),
}
}
pub fn add_client(&mut self, addr: SocketAddr, pos: Position) {
let handle = self.new_id();
let client = Client { addr, pos, handle };
self.clients.push(client);
}
pub fn get_clients(&self) -> Vec<Client> {
self.clients.clone()
}
}

View File

@@ -17,7 +17,7 @@ pub struct Clients {
pub bottom: Option<Client>,
}
#[derive(Serialize, Deserialize, Debug)]
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
pub struct Client {
pub host_name: Option<String>,
pub ip: Option<IpAddr>,

View File

@@ -10,14 +10,6 @@ struct DnsError {
host: String,
}
impl Error for InvalidConfigError {}
impl Display for InvalidConfigError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "No hostname specified!")
}
}
impl Error for DnsError {}
impl Display for DnsError {
@@ -26,11 +18,7 @@ impl Display for DnsError {
}
}
pub fn resolve(host: &Option<String>) -> Result<IpAddr, Box<dyn Error>> {
let host = match host {
Some(host) => host,
None => return Err(InvalidConfigError.into()),
};
pub fn resolve(host: &String) -> Result<IpAddr, Box<dyn Error>> {
let response = Resolver::from_system_conf()?.lookup_ip(host)?;
match response.iter().next() {
Some(ip) => Ok(ip),

154
src/event.rs Normal file
View File

@@ -0,0 +1,154 @@
pub mod producer;
pub mod consumer;
pub mod server;
/*
* TODO: currently the wayland events are encoded
* directly with no generalized event format
*/
use wayland_client::{protocol::{wl_pointer, wl_keyboard}, WEnum};
pub trait Encode {
fn encode(&self) -> Vec<u8>;
}
pub trait Decode {
fn decode(buf: Vec<u8>) -> Self;
}
impl Encode for wl_pointer::Event {
fn encode(&self) -> Vec<u8> {
let mut buf = Vec::new();
match *self {
Self::Motion {
time: t,
surface_x: x,
surface_y: y,
} => {
buf.push(0u8);
buf.extend_from_slice(t.to_ne_bytes().as_ref());
buf.extend_from_slice(x.to_ne_bytes().as_ref());
buf.extend_from_slice(y.to_ne_bytes().as_ref());
}
Self::Button {
serial: _,
time: t,
button: b,
state: s,
} => {
buf.push(1u8);
buf.extend_from_slice(t.to_ne_bytes().as_ref());
buf.extend_from_slice(b.to_ne_bytes().as_ref());
buf.push(u32::from(s) as u8);
}
Self::Axis {
time: t,
axis: a,
value: v,
} => {
buf.push(2u8);
buf.extend_from_slice(t.to_ne_bytes().as_ref());
buf.push(u32::from(a) as u8);
buf.extend_from_slice(v.to_ne_bytes().as_ref());
}
Self::Frame {} => {
buf.push(3u8);
}
_ => todo!(),
}
buf
}
}
impl Encode for wl_keyboard::Event {
fn encode(&self) -> Vec<u8> {
let mut buf = Vec::new();
match self {
Self::Key {
serial: _,
time: t,
key: k,
state: s,
} => {
buf.push(4u8);
buf.extend_from_slice(t.to_ne_bytes().as_ref());
buf.extend_from_slice(k.to_ne_bytes().as_ref());
buf.push(u32::from(*s) as u8);
}
Self::Modifiers {
serial: _,
mods_depressed,
mods_latched,
mods_locked,
group,
} => {
buf.push(5u8);
buf.extend_from_slice(mods_depressed.to_ne_bytes().as_ref());
buf.extend_from_slice(mods_latched.to_ne_bytes().as_ref());
buf.extend_from_slice(mods_locked.to_ne_bytes().as_ref());
buf.extend_from_slice(group.to_ne_bytes().as_ref());
}
_ => todo!(),
}
buf
}
}
pub enum Event {
Pointer(wl_pointer::Event),
Keyboard(wl_keyboard::Event),
Release(),
}
impl Encode for Event {
fn encode(&self) -> Vec<u8> {
match self {
Event::Pointer(p) => p.encode(),
Event::Keyboard(k) => k.encode(),
Event::Release() => vec![6u8],
}
}
}
unsafe impl Send for Event {}
unsafe impl Sync for Event {}
impl Decode for Event {
fn decode(buf: Vec<u8>) -> Self {
match buf[0] {
0 => Self::Pointer(wl_pointer::Event::Motion {
time: u32::from_ne_bytes(buf[1..5].try_into().unwrap()),
surface_x: f64::from_ne_bytes(buf[5..13].try_into().unwrap()),
surface_y: f64::from_ne_bytes(buf[13..21].try_into().unwrap()),
}),
1 => Self::Pointer(wl_pointer::Event::Button {
serial: 0,
time: (u32::from_ne_bytes(buf[1..5].try_into().unwrap())),
button: (u32::from_ne_bytes(buf[5..9].try_into().unwrap())),
state: (WEnum::Value(wl_pointer::ButtonState::try_from(buf[9] as u32).unwrap())),
}),
2 => Self::Pointer(wl_pointer::Event::Axis {
time: (u32::from_ne_bytes(buf[1..5].try_into().unwrap())),
axis: (WEnum::Value(wl_pointer::Axis::try_from(buf[5] as u32).unwrap())),
value: (f64::from_ne_bytes(buf[6..14].try_into().unwrap())),
}),
3 => Self::Pointer(wl_pointer::Event::Frame {}),
4 => Self::Keyboard(wl_keyboard::Event::Key {
serial: 0,
time: u32::from_ne_bytes(buf[1..5].try_into().unwrap()),
key: u32::from_ne_bytes(buf[5..9].try_into().unwrap()),
state: WEnum::Value(wl_keyboard::KeyState::try_from(buf[9] as u32).unwrap()),
}),
5 => Self::Keyboard(wl_keyboard::Event::Modifiers {
serial: 0,
mods_depressed: u32::from_ne_bytes(buf[1..5].try_into().unwrap()),
mods_latched: u32::from_ne_bytes(buf[5..9].try_into().unwrap()),
mods_locked: u32::from_ne_bytes(buf[9..13].try_into().unwrap()),
group: u32::from_ne_bytes(buf[13..17].try_into().unwrap()),
}),
6 => Self::Release(),
_ => panic!("protocol violation"),
}
}
}

197
src/event/consumer.rs Normal file
View File

@@ -0,0 +1,197 @@
use crate::client::{Client, ClientHandle};
use crate::request::{self, Request};
use std::collections::HashMap;
use std::time::Duration;
use std::{io, thread};
use std::sync::mpsc::Receiver;
use std::{
io::{BufWriter, Write},
os::unix::prelude::AsRawFd,
};
use wayland_protocols_wlr::virtual_pointer::v1::client::{
zwlr_virtual_pointer_manager_v1::ZwlrVirtualPointerManagerV1 as VpManager,
zwlr_virtual_pointer_v1::ZwlrVirtualPointerV1 as Vp,
};
use wayland_protocols_misc::zwp_virtual_keyboard_v1::client::{
zwp_virtual_keyboard_manager_v1::ZwpVirtualKeyboardManagerV1 as VkManager,
zwp_virtual_keyboard_v1::ZwpVirtualKeyboardV1 as Vk,
};
use wayland_client::{
delegate_noop,
globals::{registry_queue_init, GlobalListContents},
protocol::{wl_keyboard, wl_pointer, wl_registry, wl_seat},
Connection, Dispatch, EventQueue, QueueHandle,
};
use tempfile;
use super::Event;
// App State, implements Dispatch event handlers
struct App {
input_for_client: HashMap<ClientHandle, VirtualInput>,
seat: wl_seat::WlSeat,
event_rx: Receiver<(Event, ClientHandle)>,
vpm: VpManager,
vkm: VkManager,
queue: EventQueue<Self>,
qh: QueueHandle<Self>,
}
pub fn run(event_rx: Receiver<(Event, ClientHandle)>, clients: Vec<Client>) {
let mut app = App::new(event_rx, clients);
app.run();
}
impl App {
pub fn new(event_rx: Receiver<(Event, ClientHandle)>, clients: Vec<Client>) -> Self {
let conn = Connection::connect_to_env().unwrap();
let (globals, queue) = registry_queue_init::<App>(&conn).unwrap();
let qh = queue.handle();
let vpm: VpManager = globals.bind(&qh, 1..=1, ()).expect("zwlr_virtual_pointer_manager_v1 protocol is required to emulate mouse input");
let vkm: VkManager = globals.bind(&qh, 1..=1, ()).expect("zwp_virtual_keyboard_manager_v1 protocol is required to emulate keyboard input");
let input_for_client: HashMap<ClientHandle, VirtualInput> = HashMap::new();
let seat: wl_seat::WlSeat = globals.bind(&qh, 7..=8, ()).unwrap();
let mut app = App { input_for_client, seat, event_rx, vpm, vkm, queue, qh };
for client in clients {
app.add_client(client);
}
app
}
pub fn run(&mut self) {
loop {
let (event, client) = self.event_rx.recv().unwrap();
if let Some(virtual_input) = self.input_for_client.get(&client) {
virtual_input.consume_event(event).unwrap();
if let Err(e) = self.queue.flush() {
eprintln!("{}", e);
}
}
}
}
fn add_client(&mut self, client: Client) {
// create virtual input devices
let pointer: Vp = self.vpm.create_virtual_pointer(None, &self.qh, ());
let keyboard: Vk = self.vkm.create_virtual_keyboard(&self.seat, &self.qh, ());
// receive keymap from device
eprintln!("connecting to {}", client.addr);
let data = loop {
match request::request_data(client.addr, Request::KeyMap) {
Some(data) => break data,
None => {
eprint!(".");
io::stderr().flush().unwrap();
thread::sleep(Duration::from_millis(500));
}
}
};
// TODO use shm_open
let f = tempfile::tempfile().unwrap();
let mut buf = BufWriter::new(&f);
buf.write_all(&data[..]).unwrap();
buf.flush().unwrap();
keyboard.keymap(1, f.as_raw_fd(), data.len() as u32);
let vinput = VirtualInput { pointer, keyboard };
self.input_for_client.insert(client.handle, vinput);
}
}
struct VirtualInput {
pointer: Vp,
keyboard: Vk,
}
impl VirtualInput {
/// main loop handling udp packets
fn consume_event(&self, event: Event) -> std::io::Result<()> {
match event {
Event::Pointer(e) => match e {
wl_pointer::Event::Motion {
time,
surface_x,
surface_y,
} => {
self.pointer.motion(time, surface_x, surface_y);
self.pointer.frame();
}
wl_pointer::Event::Button {
serial: _,
time: t,
button: b,
state: s,
} => {
self.pointer.button(t, b, s.into_result().unwrap());
self.pointer.frame();
}
wl_pointer::Event::Axis {
time: t,
axis: a,
value: v,
} => {
self.pointer.axis(t, a.into_result().unwrap(), v);
self.pointer.frame();
}
wl_pointer::Event::Frame => {
self.pointer.frame();
}
_ => todo!(),
},
Event::Keyboard(e) => match e {
wl_keyboard::Event::Key {
serial: _,
time: t,
key: k,
state: s,
} => {
self.keyboard.key(t, k, u32::from(s));
}
wl_keyboard::Event::Modifiers {
serial: _,
mods_depressed,
mods_latched,
mods_locked,
group,
} => {
self.keyboard.modifiers(mods_depressed, mods_latched, mods_locked, group);
}
_ => todo!(),
},
Event::Release() => {
self.keyboard.modifiers(77, 0, 0, 0);
self.keyboard.modifiers(0, 0, 0, 0);
}
}
Ok(())
}
}
delegate_noop!(App: Vp);
delegate_noop!(App: Vk);
delegate_noop!(App: VpManager);
delegate_noop!(App: VkManager);
delegate_noop!(App: wl_seat::WlSeat);
impl Dispatch<wl_registry::WlRegistry, GlobalListContents> for App {
fn event(
_: &mut App,
_: &wl_registry::WlRegistry,
_: wl_registry::Event,
_: &GlobalListContents,
_: &Connection,
_: &QueueHandle<App>,
) {
}
}

View File

@@ -1,10 +1,11 @@
use lan_mouse::protocol;
use crate::{request, client::{ClientHandle, Position, Client}};
use memmap::Mmap;
use std::{
fs::File,
io::{BufWriter, Write},
os::unix::prelude::{AsRawFd, FromRawFd},
os::unix::prelude::{AsRawFd, FromRawFd}, sync::mpsc::SyncSender, rc::Rc,
};
use wayland_protocols::wp::{
@@ -39,6 +40,8 @@ use wayland_client::{
use tempfile;
use super::Event;
struct Globals {
compositor: wl_compositor::WlCompositor,
pointer_constraints: ZwpPointerConstraintsV1,
@@ -51,19 +54,15 @@ struct Globals {
struct App {
running: bool,
windows: Windows,
pointer_lock: Option<ZwpLockedPointerV1>,
rel_pointer: Option<ZwpRelativePointerV1>,
shortcut_inhibitor: Option<ZwpKeyboardShortcutsInhibitorV1>,
connection: protocol::Connection,
client_for_window: Vec<(Rc<Window>, ClientHandle)>,
focused: Option<(Rc<Window>, ClientHandle)>,
g: Globals,
}
struct Windows {
_left: Option<Window>,
right: Option<Window>,
_top: Option<Window>,
_bottom: Option<Window>,
tx: SyncSender<(Event, ClientHandle)>,
server: request::Server,
qh: QueueHandle<Self>,
}
struct Window {
@@ -73,34 +72,40 @@ struct Window {
}
impl Window {
fn new(g: &Globals, qh: QueueHandle<App>) -> Window {
fn new(g: &Globals, qh: &QueueHandle<App>, pos: Position) -> Window {
let (width, height) = (1, 1440);
let mut file = tempfile::tempfile().unwrap();
draw(&mut file, (width, height));
let pool = g
.shm
.create_pool(file.as_raw_fd(), (width * height * 4) as i32, &qh, ());
.create_pool(file.as_raw_fd(), (width * height * 4) as i32, qh, ());
let buffer = pool.create_buffer(
0,
width as i32,
height as i32,
(width * 4) as i32,
wl_shm::Format::Argb8888,
&qh,
qh,
(),
);
let surface = g.compositor.create_surface(&qh, ());
let surface = g.compositor.create_surface(qh, ());
let layer_surface = g.layer_shell.get_layer_surface(
&surface,
None,
Layer::Top,
"LAN Mouse Sharing".into(),
&qh,
qh,
(),
);
let anchor = match pos {
Position::Left => Anchor::Left,
Position::Right => Anchor::Right,
Position::Top => Anchor::Top,
Position::Bottom => Anchor::Bottom,
};
layer_surface.set_anchor(Anchor::Right);
layer_surface.set_anchor(anchor);
layer_surface.set_size(1, 1440);
layer_surface.set_exclusive_zone(0);
layer_surface.set_margin(0, 0, 0, 0);
@@ -114,9 +119,11 @@ impl Window {
}
}
fn main() {
let config = lan_mouse::config::Config::new("config.toml").unwrap();
let connection = protocol::Connection::new(config);
pub fn run(
tx: SyncSender<(Event, ClientHandle)>,
server: request::Server,
clients: Vec<Client>,
) {
let conn = Connection::connect_to_env().expect("could not connect to wayland compositor");
let (g, mut queue) = registry_queue_init::<App>(&conn).expect("failed to initialize wl_registry");
let qh = queue.handle();
@@ -129,7 +136,7 @@ fn main() {
.expect("wl_shm v1 not supported");
let layer_shell: ZwlrLayerShellV1 = g
.bind(&qh, 3..=4, ())
.expect("zwlr_layer_shell_v1 >= v3 not supported");
.expect("zwlr_layer_shell_v1 >= v3 not supported - required to display a surface at the edge of the screen");
let seat: wl_seat::WlSeat = g
.bind(&qh, 7..=8, ())
.expect("wl_seat >= v7 not supported");
@@ -153,23 +160,25 @@ fn main() {
shortcut_inhibit_manager,
};
let windows: Windows = Windows {
_left: None,
right: Some(Window::new(&g, qh)),
_top: None,
_bottom: None,
};
let client_for_window = Vec::new();
let mut app = App {
running: true,
g,
windows,
pointer_lock: None,
rel_pointer: None,
shortcut_inhibitor: None,
connection,
client_for_window,
focused: None,
tx,
server,
qh,
};
for client in clients {
app.add_client(client.handle, client.pos);
}
while app.running {
queue.blocking_dispatch(&mut app).unwrap();
}
@@ -185,15 +194,27 @@ fn draw(f: &mut File, (width, height): (u32, u32)) {
}
impl App {
fn grab(&mut self, pointer: &wl_pointer::WlPointer, serial: u32, qh: &QueueHandle<App>) {
fn grab(
&mut self,
surface: &wl_surface::WlSurface,
pointer: &wl_pointer::WlPointer,
serial: u32,
qh: &QueueHandle<App>
) {
let (window, _) = self.focused.as_ref().unwrap();
// hide the cursor
pointer.set_cursor(serial, None, 0, 0);
let layer_surface = &self.windows.right.as_ref().unwrap().layer_surface;
layer_surface.set_keyboard_interactivity(KeyboardInteractivity::Exclusive);
let surface = &self.windows.right.as_ref().unwrap().surface;
surface.commit();
// capture input
window.layer_surface.set_keyboard_interactivity(KeyboardInteractivity::Exclusive);
window.surface.commit();
// lock pointer
if self.pointer_lock.is_none() {
self.pointer_lock = Some(self.g.pointer_constraints.lock_pointer(
&surface,
surface,
pointer,
None,
Lifetime::Oneshot,
@@ -201,6 +222,8 @@ impl App {
(),
));
}
// request relative input
if self.rel_pointer.is_none() {
self.rel_pointer = Some(self.g.relative_pointer_manager.get_relative_pointer(
pointer,
@@ -208,9 +231,11 @@ impl App {
(),
));
}
// capture modifier keys
if self.shortcut_inhibitor.is_none() {
self.shortcut_inhibitor = Some(self.g.shortcut_inhibit_manager.inhibit_shortcuts(
&surface,
surface,
&self.g.seat,
qh,
(),
@@ -219,23 +244,36 @@ impl App {
}
fn ungrab(&mut self) {
let layer_surface = &self.windows.right.as_ref().unwrap().layer_surface;
layer_surface.set_keyboard_interactivity(KeyboardInteractivity::None);
let surface = &self.windows.right.as_ref().unwrap().surface;
surface.commit();
// get focused client
let (window, _client) = self.focused.as_ref().unwrap();
// ungrab surface
window.layer_surface.set_keyboard_interactivity(KeyboardInteractivity::None);
window.surface.commit();
// release pointer
if let Some(pointer_lock) = &self.pointer_lock {
pointer_lock.destroy();
self.pointer_lock = None;
}
// destroy relative input
if let Some(rel_pointer) = &self.rel_pointer {
rel_pointer.destroy();
self.rel_pointer = None;
}
// release shortcut inhibitor
if let Some(shortcut_inhibitor) = &self.shortcut_inhibitor {
shortcut_inhibitor.destroy();
self.shortcut_inhibitor = None;
}
}
fn add_client(&mut self, client: ClientHandle, pos: Position) {
let window = Rc::new(Window::new(&self.g, &self.qh, pos));
self.client_for_window.push((window, client));
}
}
impl Dispatch<wl_seat::WlSeat, ()> for App {
@@ -273,23 +311,40 @@ impl Dispatch<wl_pointer::WlPointer, ()> for App {
match event {
wl_pointer::Event::Enter {
serial,
surface: _,
surface,
surface_x: _,
surface_y: _,
} => {
app.grab(pointer, serial, qh);
// get client corresponding to the focused surface
{
let (window, client) = app.client_for_window
.iter()
.find(|(w,_c)| w.surface == surface)
.unwrap();
app.focused = Some((window.clone(), *client));
app.grab(&surface, pointer, serial.clone(), qh);
}
let (_, client) = app.client_for_window
.iter()
.find(|(w,_c)| w.surface == surface)
.unwrap();
app.tx.send((Event::Release(), *client)).unwrap();
}
wl_pointer::Event::Leave { .. } => {
app.ungrab();
}
wl_pointer::Event::Button { .. } => {
app.connection.send_event(event);
let (_, client) = app.focused.as_ref().unwrap();
app.tx.send((Event::Pointer(event), *client)).unwrap();
}
wl_pointer::Event::Axis { .. } => {
app.connection.send_event(event);
let (_, client) = app.focused.as_ref().unwrap();
app.tx.send((Event::Pointer(event), *client)).unwrap();
}
wl_pointer::Event::Frame { .. } => {
app.connection.send_event(event);
let (_, client) = app.focused.as_ref().unwrap();
app.tx.send((Event::Pointer(event), *client)).unwrap();
}
_ => {}
}
@@ -305,12 +360,20 @@ impl Dispatch<wl_keyboard::WlKeyboard, ()> for App {
_: &Connection,
_: &QueueHandle<Self>,
) {
let (_window, client) = match &app.focused {
Some(focused) => (Some(&focused.0), Some(&focused.1)),
None => (None, None),
};
match event {
wl_keyboard::Event::Key { .. } => {
app.connection.send_event(event);
if let Some(client) = client {
app.tx.send((Event::Keyboard(event), *client)).unwrap();
}
}
wl_keyboard::Event::Modifiers { mods_depressed, .. } => {
app.connection.send_event(event);
if let Some(client) = client {
app.tx.send((Event::Keyboard(event), *client)).unwrap();
}
if mods_depressed == 77 {
// ctrl shift super alt
app.ungrab();
@@ -322,8 +385,7 @@ impl Dispatch<wl_keyboard::WlKeyboard, ()> for App {
size: _,
} => {
let mmap = unsafe { Mmap::map(&File::from_raw_fd(fd.as_raw_fd())).unwrap() };
app.connection
.offer_data(protocol::DataRequest::KeyMap, mmap);
app.server.offer_data(request::Request::KeyMap, mmap);
}
_ => (),
}
@@ -348,12 +410,18 @@ impl Dispatch<ZwpRelativePointerV1, ()> for App {
dy_unaccel: surface_y,
} = event
{
let time = (((utime_hi as u64) << 32 | utime_lo as u64) / 1000) as u32;
app.connection.send_event(wl_pointer::Event::Motion {
time,
surface_x,
surface_y,
});
if let Some((_window, client)) = &app.focused {
let time = (((utime_hi as u64) << 32 | utime_lo as u64) / 1000) as u32;
app.tx.send((
Event::Pointer(wl_pointer::Event::Motion {
time,
surface_x,
surface_y,
}),
*client,
)).unwrap();
}
}
}
}
@@ -368,10 +436,16 @@ impl Dispatch<ZwlrLayerSurfaceV1, ()> for App {
_: &QueueHandle<Self>,
) {
if let zwlr_layer_surface_v1::Event::Configure { serial, .. } = event {
let surface = &app.windows.right.as_ref().unwrap().surface;
let (window, _client) = app.client_for_window
.iter()
.find(|(w,_c)| &w.layer_surface == layer_surface)
.unwrap();
// client corresponding to the layer_surface
let surface = &window.surface;
let buffer = &window.buffer;
surface.commit();
layer_surface.ack_configure(serial);
surface.attach(Some(&app.windows.right.as_ref().unwrap().buffer), 0, 0);
surface.attach(Some(&buffer), 0, 0);
surface.commit();
}
}

119
src/event/server.rs Normal file
View File

@@ -0,0 +1,119 @@
use std::{
net::{UdpSocket, SocketAddr},
error::Error,
sync::{mpsc::{SyncSender, Receiver}, atomic::{AtomicBool, Ordering}, Arc},
thread::{self, JoinHandle}, collections::HashMap,
};
use crate::client::{ClientHandle, ClientManager};
use super::{Event, Encode, Decode};
pub struct Server {
listen_addr: SocketAddr,
sending: Arc<AtomicBool>,
}
impl Server {
pub fn new(port: u16) -> Self {
let listen_addr = SocketAddr::new("0.0.0.0".parse().unwrap(), port);
let sending = Arc::new(AtomicBool::new(false));
Server { listen_addr, sending }
}
pub fn run(self, client_manager: &mut ClientManager, produce_rx: Receiver<(Event, ClientHandle)>, consume_tx: SyncSender<(Event, ClientHandle)>) -> Result<(JoinHandle<()>, JoinHandle<()>), Box<dyn Error>> {
let udp_socket = UdpSocket::bind(self.listen_addr)?;
let rx = udp_socket.try_clone().unwrap();
let tx = udp_socket;
let sending = self.sending.clone();
let mut client_for_socket = HashMap::new();
for client in client_manager.get_clients() {
println!("{}: {}", client.handle, client.addr);
client_for_socket.insert(client.addr, client.handle);
}
let receiver = thread::Builder::new().name("event receiver".into()).spawn(move || {
loop {
let (event, addr) = match Server::receive_event(&rx) {
Some(e) => e,
None => { continue },
};
let client_handle = match client_for_socket.get(&addr) {
Some(c) => *c,
None => {
println!("Allow connection from {:?}? [Y/n]", addr);
continue
},
};
// There is a race condition between loading this
// value and handling the event:
// In the meantime a event could be produced, which
// should theoretically disable receiving of events.
//
// This is however not a huge problem, as some
// events that make it through are not a large problem
if sending.load(Ordering::Acquire) {
// ignore received events when in sending state
// if release event is received, switch state to receiving
if let Event::Release() = event {
sending.store(false, Ordering::Release);
consume_tx.send((event, client_handle)).expect("event consumer unavailable");
}
} else {
if let Event::Release() = event {
sending.store(false, Ordering::Release);
}
// we retrieve all events
consume_tx.send((event, client_handle)).expect("event consumer unavailable");
}
}
}).unwrap();
let sending = self.sending.clone();
let mut socket_for_client = HashMap::new();
for client in client_manager.get_clients() {
socket_for_client.insert(client.handle, client.addr);
}
let sender = thread::Builder::new().name("event sender".into()).spawn(move || {
loop {
let (event, client_handle) = produce_rx.recv().expect("event producer unavailable");
let addr = match socket_for_client.get(&client_handle) {
Some(addr) => addr,
None => continue,
};
if sending.load(Ordering::Acquire) {
Server::send_event(&tx, event, *addr);
} else {
// only accept enter event
if let Event::Release() = event {
// set state to sending, to ignore incoming events
// and enable sending of events
sending.store(true, Ordering::Release);
Server::send_event(&tx, event, *addr);
}
}
}
}).unwrap();
Ok((receiver, sender))
}
fn send_event<E: Encode>(tx: &UdpSocket, e: E, addr: SocketAddr) {
if let Err(e) = tx.send_to(&e.encode(), addr) {
eprintln!("{}", e);
}
}
fn receive_event(rx: &UdpSocket) -> Option<(Event, SocketAddr)> {
let mut buf = vec![0u8; 21];
if let Ok((_amt, src)) = rx.recv_from(&mut buf) {
Some((Event::decode(buf), src))
} else {
None
}
}
}

View File

@@ -1,3 +1,5 @@
pub mod config;
pub mod dns;
pub mod protocol;
pub mod event;
pub mod request;
pub mod client;

88
src/main.rs Normal file
View File

@@ -0,0 +1,88 @@
use std::{sync::mpsc, thread, net::SocketAddr};
use lan_mouse::{
event::{self, producer, consumer},
config,
request,
client::{ClientManager, Position}, dns,
};
fn add_client(client_manager: &mut ClientManager, client: &config::Client, pos: Position) {
let ip = match client.ip {
Some(ip) => ip,
None => match &client.host_name {
Some(host_name) => match dns::resolve(host_name) {
Ok(ip) => ip,
Err(e) => panic!("{}", e),
},
None => panic!("neither ip nor hostname specified"),
}
};
let addr = SocketAddr::new(ip, client.port.unwrap_or(42069));
client_manager.add_client(addr, pos);
}
pub fn main() {
// parse config file
let config = config::Config::new("config.toml").unwrap();
// port or default
let port = config.port.unwrap_or(42069);
// event channel for producing events
let (produce_tx, produce_rx) = mpsc::sync_channel(128);
// event channel for consuming events
let (consume_tx, consume_rx) = mpsc::sync_channel(128);
let mut client_manager = ClientManager::new();
// add clients from config
for client in vec![
&config.client.left,
&config.client.right,
&config.client.top,
&config.client.bottom,
] {
if let Some(client) = client {
let pos = match client {
client if Some(client) == config.client.left.as_ref() => Position::Left,
client if Some(client) == config.client.right.as_ref() => Position::Right,
client if Some(client) == config.client.top.as_ref() => Position::Top,
client if Some(client) == config.client.bottom.as_ref() => Position::Bottom,
_ => panic!(),
};
add_client(&mut client_manager, client, pos);
}
}
// start receiving client connection requests
let (request_server, request_thread) = request::Server::listen(port).unwrap();
let clients = client_manager.get_clients();
// start producing and consuming events
let event_producer = thread::Builder::new()
.name("event producer".into())
.spawn(|| {
producer::run(produce_tx, request_server, clients);
}).unwrap();
let clients = client_manager.get_clients();
let event_consumer = thread::Builder::new()
.name("event consumer".into())
.spawn(|| {
consumer::run(consume_rx, clients);
}).unwrap();
// start sending and receiving events
let event_server = event::server::Server::new(port);
let (receiver, sender) = event_server.run(&mut client_manager, produce_rx, consume_tx).unwrap();
request_thread.join().unwrap();
receiver.join().unwrap();
sender.join().unwrap();
event_producer.join().unwrap();
event_consumer.join().unwrap();
}

View File

@@ -1,302 +0,0 @@
use crate::config::{self, Config};
use crate::dns;
use memmap::Mmap;
use std::{
collections::HashMap,
io::prelude::*,
net::TcpListener,
process::exit,
sync::{Arc, RwLock},
thread,
};
use wayland_client::{
protocol::{wl_keyboard, wl_pointer},
WEnum,
};
use std::net::{SocketAddr, TcpStream, UdpSocket};
trait Resolve {
fn resolve(&self) -> Option<SocketAddr>;
}
impl Resolve for Option<config::Client> {
fn resolve(&self) -> Option<SocketAddr> {
let client = match self {
Some(client) => client,
None => return None,
};
let ip = match client.ip {
Some(ip) => ip,
None => dns::resolve(&client.host_name).unwrap(),
};
Some(SocketAddr::new(ip, client.port.unwrap_or(42069)))
}
}
struct ClientAddrs {
left: Option<SocketAddr>,
right: Option<SocketAddr>,
_top: Option<SocketAddr>,
_bottom: Option<SocketAddr>,
}
pub struct Connection {
udp_socket: UdpSocket,
client: ClientAddrs,
offer_data: Arc<RwLock<HashMap<DataRequest, Mmap>>>,
}
pub trait Encode {
fn encode(&self) -> Vec<u8>;
}
pub trait Decode {
fn decode(buf: Vec<u8>) -> Self;
}
impl Encode for wl_pointer::Event {
fn encode(&self) -> Vec<u8> {
let mut buf = Vec::new();
match *self {
Self::Motion {
time: t,
surface_x: x,
surface_y: y,
} => {
buf.push(0u8);
buf.extend_from_slice(t.to_ne_bytes().as_ref());
buf.extend_from_slice(x.to_ne_bytes().as_ref());
buf.extend_from_slice(y.to_ne_bytes().as_ref());
}
Self::Button {
serial: _,
time: t,
button: b,
state: s,
} => {
buf.push(1u8);
buf.extend_from_slice(t.to_ne_bytes().as_ref());
buf.extend_from_slice(b.to_ne_bytes().as_ref());
buf.push(u32::from(s) as u8);
}
Self::Axis {
time: t,
axis: a,
value: v,
} => {
buf.push(2u8);
buf.extend_from_slice(t.to_ne_bytes().as_ref());
buf.push(u32::from(a) as u8);
buf.extend_from_slice(v.to_ne_bytes().as_ref());
}
Self::Frame {} => {
buf.push(3u8);
}
_ => todo!(),
}
buf
}
}
impl Encode for wl_keyboard::Event {
fn encode(&self) -> Vec<u8> {
let mut buf = Vec::new();
match self {
Self::Key {
serial: _,
time: t,
key: k,
state: s,
} => {
buf.push(4u8);
buf.extend_from_slice(t.to_ne_bytes().as_ref());
buf.extend_from_slice(k.to_ne_bytes().as_ref());
buf.push(u32::from(*s) as u8);
}
Self::Modifiers {
serial: _,
mods_depressed,
mods_latched,
mods_locked,
group,
} => {
buf.push(5u8);
buf.extend_from_slice(mods_depressed.to_ne_bytes().as_ref());
buf.extend_from_slice(mods_latched.to_ne_bytes().as_ref());
buf.extend_from_slice(mods_locked.to_ne_bytes().as_ref());
buf.extend_from_slice(group.to_ne_bytes().as_ref());
}
_ => todo!(),
}
buf
}
}
pub enum Event {
Pointer(wl_pointer::Event),
Keyboard(wl_keyboard::Event),
}
impl Decode for Event {
fn decode(buf: Vec<u8>) -> Self {
match buf[0] {
0 => Self::Pointer(wl_pointer::Event::Motion {
time: u32::from_ne_bytes(buf[1..5].try_into().unwrap()),
surface_x: f64::from_ne_bytes(buf[5..13].try_into().unwrap()),
surface_y: f64::from_ne_bytes(buf[13..21].try_into().unwrap()),
}),
1 => Self::Pointer(wl_pointer::Event::Button {
serial: 0,
time: (u32::from_ne_bytes(buf[1..5].try_into().unwrap())),
button: (u32::from_ne_bytes(buf[5..9].try_into().unwrap())),
state: (WEnum::Value(wl_pointer::ButtonState::try_from(buf[9] as u32).unwrap())),
}),
2 => Self::Pointer(wl_pointer::Event::Axis {
time: (u32::from_ne_bytes(buf[1..5].try_into().unwrap())),
axis: (WEnum::Value(wl_pointer::Axis::try_from(buf[5] as u32).unwrap())),
value: (f64::from_ne_bytes(buf[6..14].try_into().unwrap())),
}),
3 => Self::Pointer(wl_pointer::Event::Frame {}),
4 => Self::Keyboard(wl_keyboard::Event::Key {
serial: 0,
time: u32::from_ne_bytes(buf[1..5].try_into().unwrap()),
key: u32::from_ne_bytes(buf[5..9].try_into().unwrap()),
state: WEnum::Value(wl_keyboard::KeyState::try_from(buf[9] as u32).unwrap()),
}),
5 => Self::Keyboard(wl_keyboard::Event::Modifiers {
serial: 0,
mods_depressed: u32::from_ne_bytes(buf[1..5].try_into().unwrap()),
mods_latched: u32::from_ne_bytes(buf[5..9].try_into().unwrap()),
mods_locked: u32::from_ne_bytes(buf[9..13].try_into().unwrap()),
group: u32::from_ne_bytes(buf[13..17].try_into().unwrap()),
}),
_ => panic!("protocol violation"),
}
}
}
#[derive(PartialEq, Eq, Hash)]
pub enum DataRequest {
KeyMap,
}
impl From<u32> for DataRequest {
fn from(idx: u32) -> Self {
match idx {
0 => Self::KeyMap,
_ => panic!("invalid enum value"),
}
}
}
impl From<[u8; 4]> for DataRequest {
fn from(buf: [u8; 4]) -> Self {
DataRequest::from(u32::from_ne_bytes(buf))
}
}
impl From<DataRequest> for u32 {
fn from(d: DataRequest) -> Self {
match d {
DataRequest::KeyMap => 0,
}
}
}
fn handle_request(data: &Arc<RwLock<HashMap<DataRequest, Mmap>>>, mut stream: TcpStream) {
let mut buf = [0u8; 4];
stream.read_exact(&mut buf).unwrap();
match DataRequest::from(buf) {
DataRequest::KeyMap => {
let data = data.read().unwrap();
let buf = data.get(&DataRequest::KeyMap);
match buf {
None => {
stream.write(&0u32.to_ne_bytes()).unwrap();
}
Some(buf) => {
stream.write(&buf[..].len().to_ne_bytes()).unwrap();
stream.write(&buf[..]).unwrap();
}
}
stream.flush().unwrap();
}
}
}
impl Connection {
pub fn new(config: Config) -> Connection {
let clients = ClientAddrs {
left: config.client.left.resolve(),
right: config.client.right.resolve(),
_top: config.client.top.resolve(),
_bottom: config.client.bottom.resolve(),
};
let data: Arc<RwLock<HashMap<DataRequest, Mmap>>> = Arc::new(RwLock::new(HashMap::new()));
let thread_data = data.clone();
let port = config.port.unwrap_or(42069);
let listen_addr = SocketAddr::new("0.0.0.0".parse().unwrap(), port);
thread::spawn(move || {
let sock = TcpListener::bind(listen_addr).unwrap();
for stream in sock.incoming() {
if let Ok(stream) = stream {
handle_request(&thread_data, stream);
}
}
});
let sock = UdpSocket::bind(listen_addr);
let sock = match sock {
Ok(sock) => sock,
Err(e) => match e.kind() {
std::io::ErrorKind::AddrInUse => {
eprintln!("Server already running on port {}", port);
exit(1);
}
_ => panic!("{}", e),
},
};
let c = Connection {
udp_socket: sock,
client: clients,
offer_data: data,
};
c
}
pub fn offer_data(&self, req: DataRequest, d: Mmap) {
self.offer_data.write().unwrap().insert(req, d);
}
pub fn receive_data(&self, req: DataRequest) -> Option<Vec<u8>> {
let mut sock = TcpStream::connect(self.client.left.unwrap()).unwrap();
sock.write(&u32::from(req).to_ne_bytes()).unwrap();
sock.flush().unwrap();
let mut buf = [0u8; 8];
sock.read_exact(&mut buf[..]).unwrap();
let len = usize::from_ne_bytes(buf);
if len == 0 {
return None;
}
let mut data: Vec<u8> = vec![0u8; len];
sock.read_exact(&mut data[..]).unwrap();
Some(data)
}
pub fn send_event<E: Encode>(&self, e: E) {
// TODO check which client
if let Some(addr) = self.client.right {
self.udp_socket.send_to(&e.encode(), addr).unwrap();
}
}
pub fn receive_event(&self) -> Option<Event> {
let mut buf = vec![0u8; 21];
if let Ok((_amt, _src)) = self.udp_socket.recv_from(&mut buf) {
Some(Event::decode(buf))
} else {
None
}
}
}

130
src/request.rs Normal file
View File

@@ -0,0 +1,130 @@
use std::{
net::{TcpListener, SocketAddr, TcpStream},
io::prelude::*,
collections::HashMap, sync::{RwLock, Arc},
error::Error,
thread::{self, JoinHandle},
};
use memmap::Mmap;
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub enum Request {
KeyMap,
Connect,
}
impl TryFrom<[u8; 4]> for Request {
fn try_from(buf: [u8; 4]) -> Result<Self, Self::Error> {
let val = u32::from_ne_bytes(buf);
match val {
x if x == Request::KeyMap as u32 => Ok(Self::KeyMap),
x if x == Request::Connect as u32 => Ok(Self::Connect),
_ => Err("Bad Request"),
}
}
type Error = &'static str;
}
#[derive(Clone)]
pub struct Server {
data: Arc<RwLock<HashMap<Request, Mmap>>>,
}
impl Server {
fn handle_request(&self, mut stream: TcpStream) {
let mut buf = [0u8; 4];
stream.read_exact(&mut buf).unwrap();
match Request::try_from(buf) {
Ok(Request::KeyMap) => {
let data = self.data.read().unwrap();
let buf = data.get(&Request::KeyMap);
match buf {
None => {
stream.write(&0u32.to_ne_bytes()).unwrap();
}
Some(buf) => {
stream.write(&buf[..].len().to_ne_bytes()).unwrap();
stream.write(&buf[..]).unwrap();
}
}
stream.flush().unwrap();
}
Ok(Request::Connect) => todo!(),
Err(msg) => eprintln!("{}", msg),
}
}
pub fn listen(port: u16) -> Result<(Server, JoinHandle<()>), Box<dyn Error>> {
let data: Arc<RwLock<HashMap<Request, Mmap>>> = Arc::new(RwLock::new(HashMap::new()));
let listen_addr = SocketAddr::new("0.0.0.0".parse().unwrap(), port);
let server = Server { data };
let server_copy = server.clone();
let thread = thread::spawn(move || {
let listen_socket = TcpListener::bind(listen_addr).unwrap();
for stream in listen_socket.incoming() {
match stream {
Ok(stream) => {
server.handle_request(stream);
}
Err(e) => {
eprintln!("{}", e);
}
}
}
});
Ok((server_copy, thread))
}
pub fn offer_data(&self, req: Request, d: Mmap) {
self.data.write().unwrap().insert(req, d);
}
}
pub fn request_data(addr: SocketAddr, req: Request) -> Option<Vec<u8>> {
// connect to server
let mut sock = match TcpStream::connect(addr) {
Ok(sock) => sock,
Err(e) => {
eprintln!("{}", e);
return None;
}
};
// write the request to the socket
// convert to u32
let req: u32 = req as u32;
if let Err(e) = sock.write(&req.to_ne_bytes()) {
eprintln!("{}", e);
return None;
}
if let Err(e) = sock.flush() {
eprintln!("{}", e);
return None;
}
// read the response = (len, data) - len 0 means no data / bad request
// read len
let mut buf = [0u8; 8];
if let Err(e) = sock.read_exact(&mut buf[..]) {
eprintln!("{}", e);
return None;
}
let len = usize::from_ne_bytes(buf);
// check for bad request
if len == 0 {
return None;
}
// read the data
let mut data: Vec<u8> = vec![0u8; len];
if let Err(e) = sock.read_exact(&mut data[..]) {
eprintln!("{}", e);
return None;
}
Some(data)
}