mirror of
https://github.com/feschber/lan-mouse.git
synced 2026-04-05 15:41:29 +03:00
Epoll (#20)
major update: - remove threading overhead by resorting to an event driven design with mio as a backend for epoll - Clients can now have an arbitrary amount of ip adresses and lan-mouse will automatically choose the correct one - -> seemless switching between ethernet and wifi - cli frontend + frontend adapter for future frontends
This commit is contained in:
committed by
GitHub
parent
22e6c531af
commit
1a4d0e05be
140
src/main.rs
140
src/main.rs
@@ -1,111 +1,65 @@
|
||||
use std::{sync::{mpsc, Arc}, process, env};
|
||||
use std::{process, error::Error};
|
||||
|
||||
use env_logger::Env;
|
||||
use lan_mouse::{
|
||||
client::ClientManager,
|
||||
consumer, producer,
|
||||
config, event, request,
|
||||
config::{Config, Frontend::{Gtk, Cli}}, event::server::Server,
|
||||
frontend::{FrontendAdapter, cli::CliFrontend},
|
||||
};
|
||||
|
||||
fn usage() {
|
||||
eprintln!("usage: {} [--backend <backend>] [--port <port>]",
|
||||
env::args().next().unwrap_or("lan-mouse".into()));
|
||||
pub fn main() {
|
||||
|
||||
// init logging
|
||||
let env = Env::default().filter_or("LAN_MOUSE_LOG_LEVEL", "info");
|
||||
env_logger::init_from_env(env);
|
||||
|
||||
if let Err(e) = run() {
|
||||
log::error!("{e}");
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
pub fn run() -> Result<(), Box<dyn Error>> {
|
||||
// parse config file
|
||||
let config = match config::Config::new() {
|
||||
Err(e) => {
|
||||
eprintln!("{e}");
|
||||
usage();
|
||||
process::exit(1);
|
||||
}
|
||||
Ok(config) => config,
|
||||
};
|
||||
|
||||
// port or default
|
||||
let port = config.port;
|
||||
|
||||
// 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);
|
||||
|
||||
// create client manager
|
||||
let client_manager = match ClientManager::new(&config) {
|
||||
Err(e) => {
|
||||
eprintln!("{e}");
|
||||
process::exit(1);
|
||||
}
|
||||
Ok(m) => m,
|
||||
};
|
||||
|
||||
// start receiving client connection requests
|
||||
let (request_server, request_thread) = match request::Server::listen(port) {
|
||||
Err(e) => {
|
||||
eprintln!("Could not bind to port {port}: {e}");
|
||||
process::exit(1);
|
||||
}
|
||||
Ok(r) => r,
|
||||
};
|
||||
|
||||
println!("Press Ctrl+Alt+Shift+Super to release the mouse");
|
||||
let config = Config::new()?;
|
||||
|
||||
// start producing and consuming events
|
||||
let event_producer = match producer::start(produce_tx, client_manager.get_clients(), request_server) {
|
||||
Err(e) => {
|
||||
eprintln!("Could not start event producer: {e}");
|
||||
None
|
||||
},
|
||||
Ok(p) => Some(p),
|
||||
};
|
||||
let event_consumer = match consumer::start(consume_rx, client_manager.get_clients(), config.backend) {
|
||||
Err(e) => {
|
||||
eprintln!("Could not start event consumer: {e}");
|
||||
None
|
||||
},
|
||||
Ok(p) => Some(p),
|
||||
};
|
||||
let producer = producer::create()?;
|
||||
let consumer = consumer::create()?;
|
||||
|
||||
if event_consumer.is_none() && event_producer.is_none() {
|
||||
process::exit(1);
|
||||
}
|
||||
// create frontend communication adapter
|
||||
let frontend_adapter = FrontendAdapter::new()?;
|
||||
|
||||
// start sending and receiving events
|
||||
let event_server = match event::server::Server::new(port) {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
eprintln!("{e}");
|
||||
process::exit(1);
|
||||
}
|
||||
};
|
||||
let (receiver, sender) = match event_server.run(Arc::new(client_manager), produce_rx, consume_tx) {
|
||||
Ok((r,s)) => (r,s),
|
||||
Err(e) => {
|
||||
eprintln!("{e}");
|
||||
process::exit(1);
|
||||
let mut event_server = Server::new(config.port, producer, consumer, frontend_adapter)?;
|
||||
|
||||
// add clients form config
|
||||
config.get_clients().into_iter().for_each(|(c, h, p)| {
|
||||
let host_name = match h {
|
||||
Some(h) => format!(" '{}'", h),
|
||||
None => "".to_owned(),
|
||||
};
|
||||
if c.len() == 0 {
|
||||
log::warn!("ignoring client{} with 0 assigned ips!", host_name);
|
||||
}
|
||||
log::info!("adding client [{}]{} @ {:?}", p, host_name, c);
|
||||
event_server.add_client(c, p);
|
||||
});
|
||||
|
||||
// any threads need to be started after event_server sets up signal handling
|
||||
match config.frontend {
|
||||
Gtk => {
|
||||
#[cfg(all(unix, feature = "gtk"))]
|
||||
frontend::gtk::create();
|
||||
#[cfg(not(feature = "gtk"))]
|
||||
panic!("gtk frontend requested but feature not enabled!");
|
||||
},
|
||||
Cli => Box::new(CliFrontend::new()?),
|
||||
};
|
||||
|
||||
request_thread.join().unwrap();
|
||||
log::info!("Press Ctrl+Alt+Shift+Super to release the mouse");
|
||||
// run event loop
|
||||
event_server.run()?;
|
||||
|
||||
// stop receiving events and terminate event-consumer
|
||||
if let Err(e) = receiver.join().unwrap() {
|
||||
eprint!("{e}");
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
if let Some(thread) = event_consumer {
|
||||
thread.join().unwrap();
|
||||
}
|
||||
|
||||
// stop producing events and terminate event-sender
|
||||
if let Some(thread) = event_producer {
|
||||
thread.join().unwrap();
|
||||
}
|
||||
|
||||
if let Err(e) = sender.join().unwrap() {
|
||||
eprint!("{e}");
|
||||
process::exit(1);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user