diff --git a/example/server.toml b/example/server.toml index c7f7ba8..5ada42a 100644 --- a/example/server.toml +++ b/example/server.toml @@ -3,6 +3,15 @@ listen = "0.0.0.0:5258" switch-keys = ["left-alt", "left-ctrl"] certificate = "/etc/rkvm/certificate.pem" key = "/etc/rkvm/key.pem" +# Specify a list of absolute paths to input device event file that are +# to be registered by the server in the following array, or leave the +# array emtpy to register all detected input devices. +# +# You can find symlinks that point to event file of each input device +# in the `/dev/input/by-id/` folder. These can also be used in the +# following array (make sure to input the absolute path of the +# symlinks). +input-device-paths = [] # This is to prevent malicious clients from connecting to the server. # Make sure this matches your client's config. diff --git a/rkvm-input/src/monitor.rs b/rkvm-input/src/monitor.rs index 1346d28..1400365 100644 --- a/rkvm-input/src/monitor.rs +++ b/rkvm-input/src/monitor.rs @@ -5,7 +5,9 @@ use futures::StreamExt; use inotify::{Inotify, WatchMask}; use std::ffi::OsStr; use std::io::{Error, ErrorKind}; -use std::path::Path; +use std::path::{Path, PathBuf}; +use std::collections::HashSet; +use std::fs::canonicalize; use tokio::fs; use tokio::sync::mpsc::{self, Receiver, Sender}; @@ -16,9 +18,10 @@ pub struct Monitor { } impl Monitor { - pub fn new() -> Self { + pub fn new(input_device_paths: &HashSet) -> Self { let (sender, receiver) = mpsc::channel(1); - tokio::spawn(monitor(sender)); + let absolute_input_device_paths = canonicalize_input_device_paths(input_device_paths); + tokio::spawn(monitor(sender, absolute_input_device_paths)); Self { receiver } } @@ -31,7 +34,7 @@ impl Monitor { } } -async fn monitor(sender: Sender>) { +async fn monitor(sender: Sender>, input_device_paths: HashSet) { let run = async { let registry = Registry::new(); @@ -70,14 +73,16 @@ async fn monitor(sender: Sender>) { continue; } - let interceptor = match Interceptor::open(&path, ®istry).await { - Ok(interceptor) => interceptor, - Err(OpenError::Io(err)) => return Err(err), - Err(OpenError::NotAppliable) => continue, - }; + if register_input_device(&input_device_paths, path.clone()) { + let interceptor = match Interceptor::open(&path, ®istry).await { + Ok(interceptor) => interceptor, + Err(OpenError::Io(err)) => return Err(err), + Err(OpenError::NotAppliable) => continue, + }; - if sender.send(Ok(interceptor)).await.is_err() { - return Ok(()); + if sender.send(Ok(interceptor)).await.is_err() { + return Ok(()); + } } } @@ -94,3 +99,41 @@ async fn monitor(sender: Sender>) { _ = sender.closed() => {} } } + +fn canonicalize_input_device_paths(input_device_paths: &HashSet) -> HashSet { + let mut absolute_paths = HashSet::new(); + for path in input_device_paths { + match canonicalize(path) { + Ok(abs_path) => { + match abs_path.into_os_string().into_string() { + Ok(ap) => { + absolute_paths.insert(ap); + }, + Err(err) => { + tracing::error!("Failed to convert absolute path into string {:?}", err); + continue; + }, + } + }, + Err(err) => { + tracing::error!("Failed to canonicalize a path: {}", err); + continue; + }, + } + } + return absolute_paths; +} + +fn register_input_device(input_device_paths: &HashSet, input_device_path: PathBuf) -> bool { + if input_device_paths.len() > 0 { + match input_device_path.into_os_string().into_string() { + Ok(path) => return input_device_paths.contains(&path), + Err(err) => { + tracing::error!("Can't convert a path into string! {:?}", err); + return false; + }, + } + } else { + return true; + } +} diff --git a/rkvm-server/src/config.rs b/rkvm-server/src/config.rs index ffc19cd..eeeeed6 100644 --- a/rkvm-server/src/config.rs +++ b/rkvm-server/src/config.rs @@ -12,6 +12,7 @@ pub struct Config { pub key: PathBuf, pub password: String, pub switch_keys: HashSet, + pub input_device_paths: HashSet, } #[derive(Deserialize, Clone, Copy, PartialEq, Eq, Hash)] diff --git a/rkvm-server/src/main.rs b/rkvm-server/src/main.rs index 4d3e4fd..190a932 100644 --- a/rkvm-server/src/main.rs +++ b/rkvm-server/src/main.rs @@ -68,9 +68,10 @@ async fn main() -> ExitCode { }; let switch_keys = config.switch_keys.into_iter().map(Into::into).collect(); + let input_device_paths = config.input_device_paths; tokio::select! { - result = server::run(config.listen, acceptor, &config.password, &switch_keys) => { + result = server::run(config.listen, acceptor, &config.password, &switch_keys, &input_device_paths) => { if let Err(err) = result { tracing::error!("Error: {}", err); return ExitCode::FAILURE; diff --git a/rkvm-server/src/server.rs b/rkvm-server/src/server.rs index e7cae21..8f4ba59 100644 --- a/rkvm-server/src/server.rs +++ b/rkvm-server/src/server.rs @@ -38,11 +38,12 @@ pub async fn run( acceptor: TlsAcceptor, password: &str, switch_keys: &HashSet, + input_device_paths: &HashSet, ) -> Result<(), Error> { let listener = TcpListener::bind(&listen).await.map_err(Error::Network)?; tracing::info!("Listening on {}", listen); - let mut monitor = Monitor::new(); + let mut monitor = Monitor::new(input_device_paths); let mut devices = Slab::::new(); let mut clients = Slab::<(Sender<_>, SocketAddr)>::new(); let mut current = 0;