Skip to content
Open
9 changes: 9 additions & 0 deletions example/server.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
65 changes: 54 additions & 11 deletions rkvm-input/src/monitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand All @@ -16,9 +18,10 @@ pub struct Monitor {
}

impl Monitor {
pub fn new() -> Self {
pub fn new(input_device_paths: &HashSet<String>) -> 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 }
}
Expand All @@ -31,7 +34,7 @@ impl Monitor {
}
}

async fn monitor(sender: Sender<Result<Interceptor, Error>>) {
async fn monitor(sender: Sender<Result<Interceptor, Error>>, input_device_paths: HashSet<String>) {
let run = async {
let registry = Registry::new();

Expand Down Expand Up @@ -70,14 +73,16 @@ async fn monitor(sender: Sender<Result<Interceptor, Error>>) {
continue;
}

let interceptor = match Interceptor::open(&path, &registry).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, &registry).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(());
}
}
}

Expand All @@ -94,3 +99,41 @@ async fn monitor(sender: Sender<Result<Interceptor, Error>>) {
_ = sender.closed() => {}
}
}

fn canonicalize_input_device_paths(input_device_paths: &HashSet<String>) -> HashSet<String> {
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<String>, 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;
}
}
1 change: 1 addition & 0 deletions rkvm-server/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub struct Config {
pub key: PathBuf,
pub password: String,
pub switch_keys: HashSet<SwitchKey>,
pub input_device_paths: HashSet<String>,
}

#[derive(Deserialize, Clone, Copy, PartialEq, Eq, Hash)]
Expand Down
3 changes: 2 additions & 1 deletion rkvm-server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion rkvm-server/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,12 @@ pub async fn run(
acceptor: TlsAcceptor,
password: &str,
switch_keys: &HashSet<Key>,
input_device_paths: &HashSet<String>,
) -> 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::<Device>::new();
let mut clients = Slab::<(Sender<_>, SocketAddr)>::new();
let mut current = 0;
Expand Down