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:
Ferdinand Schober
2023-09-19 19:12:47 +02:00
committed by GitHub
parent 22e6c531af
commit 1a4d0e05be
24 changed files with 2453 additions and 965 deletions

View File

@@ -1,19 +1,21 @@
use serde_derive::{Deserialize, Serialize};
use serde::{Deserialize, Serialize};
use core::fmt;
use std::net::IpAddr;
use std::collections::HashSet;
use std::net::{IpAddr, SocketAddr};
use std::{error::Error, fs};
use std::env;
use toml;
use crate::client::Position;
use crate::dns;
pub const DEFAULT_PORT: u16 = 4242;
#[derive(Serialize, Deserialize, Debug)]
pub struct ConfigToml {
pub port: Option<u16>,
pub backend: Option<String>,
pub frontend: Option<String>,
pub left: Option<Client>,
pub right: Option<Client>,
pub top: Option<Client>,
@@ -23,7 +25,7 @@ pub struct ConfigToml {
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
pub struct Client {
pub host_name: Option<String>,
pub ip: Option<IpAddr>,
pub ips: Option<Vec<IpAddr>>,
pub port: Option<u16>,
}
@@ -62,8 +64,13 @@ fn find_arg(key: &'static str) -> Result<Option<String>, MissingParameter> {
Ok(None)
}
pub enum Frontend {
Gtk,
Cli,
}
pub struct Config {
pub backend: Option<String>,
pub frontend: Frontend,
pub port: u16,
pub clients: Vec<(Client, Position)>,
}
@@ -73,19 +80,28 @@ impl Config {
let config_path = "config.toml";
let config_toml = match ConfigToml::new(config_path) {
Err(e) => {
eprintln!("config.toml: {e}");
eprintln!("Continuing without config file ...");
log::error!("config.toml: {e}");
log::warn!("Continuing without config file ...");
None
},
Ok(c) => Some(c),
};
let backend = match find_arg("--backend")? {
let frontend = match find_arg("--frontend")? {
None => match &config_toml {
Some(c) => c.backend.clone(),
Some(c) => c.frontend.clone(),
None => None,
},
backend => backend,
frontend => frontend,
};
let frontend = match frontend {
None => Frontend::Cli,
Some(s) => match s.as_str() {
"cli" => Frontend::Cli,
"gtk" => Frontend::Gtk,
_ => Frontend::Cli,
}
};
let port = match find_arg("--port")? {
@@ -113,6 +129,43 @@ impl Config {
}
}
Ok(Config { backend, clients, port })
Ok(Config { frontend, clients, port })
}
pub fn get_clients(&self) -> Vec<(HashSet<SocketAddr>, Option<String>, Position)> {
self.clients.iter().map(|(c,p)| {
let port = c.port.unwrap_or(DEFAULT_PORT);
// add ips from config
let config_ips: Vec<IpAddr> = if let Some(ips) = c.ips.as_ref() {
ips.iter().cloned().collect()
} else {
vec![]
};
let host_name = c.host_name.clone();
// add ips from dns lookup
let dns_ips = match host_name.as_ref() {
None => vec![],
Some(host_name) => match dns::resolve(host_name) {
Err(e) => {
log::warn!("{host_name}: could not resolve host: {e}");
vec![]
}
Ok(l) if l.is_empty() => {
log::warn!("{host_name}: could not resolve host");
vec![]
}
Ok(l) => l,
}
};
if config_ips.is_empty() && dns_ips.is_empty() {
log::error!("no ips found for client {p:?}, ignoring!");
log::error!("You can manually specify ip addresses via the `ips` config option");
}
let ips = config_ips.into_iter().chain(dns_ips.into_iter());
// map ip addresses to socket addresses
let addrs: HashSet<SocketAddr> = ips.map(|ip| SocketAddr::new(ip, port)).collect();
(addrs, host_name, *p)
}).filter(|(a, _, _)| !a.is_empty()).collect()
}
}