Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ shadow-rs = { version = "1.2.0", features = ["metadata"] }

hickory-resolver = "0.25.2"
toml = "0.8"
toml_edit = { version = "0.22", features = ["serde"] }
serde = { version = "1.0", features = ["derive"] }
log = "0.4.20"
env_logger = "0.11.3"
Expand Down
3 changes: 3 additions & 0 deletions lan-mouse-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ enum CliSubcommand {
},
/// deauthorize a public key
RemoveAuthorizedKey { sha256_fingerprint: String },
/// save configuration to file
SaveConfig,
}

pub async fn run(args: CliArgs) -> Result<(), CliError> {
Expand Down Expand Up @@ -162,6 +164,7 @@ async fn execute(cmd: CliSubcommand) -> Result<(), CliError> {
tx.request(FrontendRequest::RemoveAuthorizedKey(sha256_fingerprint))
.await?
}
CliSubcommand::SaveConfig => tx.request(FrontendRequest::SaveConfiguration).await?,
}
Ok(())
}
2 changes: 2 additions & 0 deletions lan-mouse-ipc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,8 @@ pub enum FrontendRequest {
RemoveAuthorizedKey(String),
/// change the hook command
UpdateEnterHook(u64, Option<String>),
/// save config file
SaveConfiguration,
}

#[derive(Clone, Copy, PartialEq, Eq, Debug, Default, Serialize, Deserialize)]
Expand Down
9 changes: 9 additions & 0 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@ pub struct ClientManager {
}

impl ClientManager {
/// get all clients
pub fn clients(&self) -> Vec<(ClientConfig, ClientState)> {
self.clients
.borrow()
.iter()
.map(|(_, c)| c.clone())
.collect::<Vec<_>>()
}

/// add a new client to this manager
pub fn add_client(&self) -> ClientHandle {
self.clients.borrow_mut().insert(Default::default()) as ClientHandle
Expand Down
77 changes: 76 additions & 1 deletion src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use std::path::{Path, PathBuf};
use std::{collections::HashSet, io};
use thiserror::Error;
use toml;
use toml_edit::{self, DocumentMut};

use lan_mouse_cli::CliArgs;
use lan_mouse_ipc::{Position, DEFAULT_PORT};
Expand Down Expand Up @@ -44,7 +45,7 @@ fn default_path() -> Result<PathBuf, VarError> {
Ok(PathBuf::from(default_path))
}

#[derive(Serialize, Deserialize, Debug)]
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
struct ConfigToml {
capture_backend: Option<CaptureBackend>,
emulation_backend: Option<EmulationBackend>,
Expand Down Expand Up @@ -274,6 +275,33 @@ impl From<TomlClient> for ConfigClient {
}
}

impl From<ConfigClient> for TomlClient {
fn from(client: ConfigClient) -> Self {
let hostname = client.hostname;
let host_name = None;
let mut ips = client.ips.into_iter().collect::<Vec<_>>();
ips.sort();
let ips = Some(ips);
let port = if client.port == DEFAULT_PORT {
None
} else {
Some(client.port)
};
let position = Some(client.pos);
let activate_on_startup = if client.active { Some(true) } else { None };
let enter_hook = client.enter_hook;
Self {
hostname,
host_name,
ips,
port,
position,
activate_on_startup,
enter_hook,
}
}
}

#[derive(Debug, Error)]
pub enum ConfigError {
#[error(transparent)]
Expand Down Expand Up @@ -384,4 +412,51 @@ impl Config {
.and_then(|c| c.release_bind.clone())
.unwrap_or(Vec::from_iter(DEFAULT_RELEASE_KEYS.iter().cloned()))
}

/// set configured clients
pub fn set_clients(&mut self, clients: Vec<ConfigClient>) {
if clients.is_empty() {
return;
}
if self.config_toml.is_none() {
self.config_toml = Default::default();
}
self.config_toml.as_mut().expect("config").clients =
Some(clients.into_iter().map(|c| c.into()).collect::<Vec<_>>());
}

/// set authorized keys
pub fn set_authorized_keys(&mut self, fingerprints: HashMap<String, String>) {
if fingerprints.is_empty() {
return;
}
if self.config_toml.is_none() {
self.config_toml = Default::default();
}
self.config_toml
.as_mut()
.expect("config")
.authorized_fingerprints = Some(fingerprints);
}

pub fn write_back(&self) -> Result<(), io::Error> {
log::info!("writing config to {:?}", &self.config_path);
/* load the current configuration file */
let current_config = fs::read_to_string(&self.config_path)?;
let current_config = current_config.parse::<DocumentMut>().expect("fix me");
let _current_config =
toml_edit::de::from_document::<ConfigToml>(current_config).expect("fixme");

/* the new config */
let new_config = self.config_toml.clone().unwrap_or_default();
// let new_config = toml_edit::ser::to_document::<ConfigToml>(&new_config).expect("fixme");
let new_config = toml_edit::ser::to_string_pretty(&new_config).expect("todo");

/* TODO merge documents */

/* write new config to file */
fs::write(&self.config_path, new_config)?;

Ok(())
}
}
27 changes: 26 additions & 1 deletion src/service.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
capture::{Capture, CaptureType, ICaptureEvent},
client::ClientManager,
config::Config,
config::{Config, ConfigClient},
connect::LanMouseConnection,
crypto,
dns::{DnsEvent, DnsResolver},
Expand Down Expand Up @@ -39,6 +39,8 @@ pub enum ServiceError {
}

pub struct Service {
/// configuration
config: Config,
/// input capture
capture: Capture,
/// input emulation
Expand Down Expand Up @@ -122,6 +124,7 @@ impl Service {

let port = config.port();
let service = Self {
config,
capture,
emulation,
frontend_listener,
Expand Down Expand Up @@ -200,6 +203,28 @@ impl Service {
FrontendRequest::UpdateEnterHook(handle, enter_hook) => {
self.update_enter_hook(handle, enter_hook)
}
FrontendRequest::SaveConfiguration => self.save_config(),
}
}

fn save_config(&mut self) {
let clients = self.client_manager.clients();
let clients = clients
.into_iter()
.map(|(c, s)| ConfigClient {
ips: HashSet::from_iter(c.fix_ips),
hostname: c.hostname,
port: c.port,
pos: c.pos,
active: s.active,
enter_hook: c.cmd,
})
.collect();
self.config.set_clients(clients);
let authorized_keys = self.authorized_keys.read().expect("lock").clone();
self.config.set_authorized_keys(authorized_keys);
if let Err(e) = self.config.write_back() {
log::warn!("failed to write config: {e}");
}
}

Expand Down
Loading