mirror of
https://github.com/feschber/lan-mouse.git
synced 2026-03-07 11:59:59 +03:00
168 lines
5.5 KiB
Rust
168 lines
5.5 KiB
Rust
use clap::{Args, Parser, Subcommand};
|
|
use futures::StreamExt;
|
|
|
|
use std::{net::IpAddr, time::Duration};
|
|
use thiserror::Error;
|
|
|
|
use lan_mouse_ipc::{
|
|
connect_async, ClientHandle, ConnectionError, FrontendEvent, FrontendRequest, IpcError,
|
|
Position,
|
|
};
|
|
|
|
#[derive(Debug, Error)]
|
|
pub enum CliError {
|
|
/// is the service running?
|
|
#[error("could not connect: `{0}` - is the service running?")]
|
|
ServiceNotRunning(#[from] ConnectionError),
|
|
#[error("error communicating with service: {0}")]
|
|
Ipc(#[from] IpcError),
|
|
}
|
|
|
|
#[derive(Parser, Debug, PartialEq, Eq)]
|
|
#[command(name = "lan-mouse-cli", about = "LanMouse CLI interface")]
|
|
pub struct CliArgs {
|
|
#[command(subcommand)]
|
|
command: CliSubcommand,
|
|
}
|
|
|
|
#[derive(Args, Clone, Debug, PartialEq, Eq)]
|
|
struct Client {
|
|
#[arg(long)]
|
|
hostname: Option<String>,
|
|
#[arg(long)]
|
|
port: Option<u16>,
|
|
#[arg(long)]
|
|
ips: Option<Vec<IpAddr>>,
|
|
#[arg(long)]
|
|
enter_hook: Option<String>,
|
|
}
|
|
|
|
#[derive(Subcommand, Debug, PartialEq, Eq)]
|
|
enum CliSubcommand {
|
|
/// add a new client
|
|
AddClient(Client),
|
|
/// remove an existing client
|
|
RemoveClient { id: ClientHandle },
|
|
/// activate a client
|
|
Activate { id: ClientHandle },
|
|
/// deactivate a client
|
|
Deactivate { id: ClientHandle },
|
|
/// list configured clients
|
|
List,
|
|
/// change hostname
|
|
SetHost {
|
|
id: ClientHandle,
|
|
host: Option<String>,
|
|
},
|
|
/// change port
|
|
SetPort { id: ClientHandle, port: u16 },
|
|
/// set position
|
|
SetPosition { id: ClientHandle, pos: Position },
|
|
/// set ips
|
|
SetIps { id: ClientHandle, ips: Vec<IpAddr> },
|
|
/// re-enable capture
|
|
EnableCapture,
|
|
/// re-enable emulation
|
|
EnableEmulation,
|
|
/// authorize a public key
|
|
AuthorizeKey {
|
|
description: String,
|
|
sha256_fingerprint: String,
|
|
},
|
|
/// deauthorize a public key
|
|
RemoveAuthorizedKey { sha256_fingerprint: String },
|
|
}
|
|
|
|
pub async fn run(args: CliArgs) -> Result<(), CliError> {
|
|
execute(args.command).await?;
|
|
Ok(())
|
|
}
|
|
|
|
async fn execute(cmd: CliSubcommand) -> Result<(), CliError> {
|
|
let (mut rx, mut tx) = connect_async(Some(Duration::from_millis(500))).await?;
|
|
match cmd {
|
|
CliSubcommand::AddClient(Client {
|
|
hostname,
|
|
port,
|
|
ips,
|
|
enter_hook,
|
|
}) => {
|
|
tx.request(FrontendRequest::Create).await?;
|
|
while let Some(e) = rx.next().await {
|
|
if let FrontendEvent::Created(handle, _, _) = e? {
|
|
if let Some(hostname) = hostname {
|
|
tx.request(FrontendRequest::UpdateHostname(handle, Some(hostname)))
|
|
.await?;
|
|
}
|
|
if let Some(port) = port {
|
|
tx.request(FrontendRequest::UpdatePort(handle, port))
|
|
.await?;
|
|
}
|
|
if let Some(ips) = ips {
|
|
tx.request(FrontendRequest::UpdateFixIps(handle, ips))
|
|
.await?;
|
|
}
|
|
if let Some(enter_hook) = enter_hook {
|
|
tx.request(FrontendRequest::UpdateEnterHook(handle, Some(enter_hook)))
|
|
.await?;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
CliSubcommand::RemoveClient { id } => tx.request(FrontendRequest::Delete(id)).await?,
|
|
CliSubcommand::Activate { id } => tx.request(FrontendRequest::Activate(id, true)).await?,
|
|
CliSubcommand::Deactivate { id } => {
|
|
tx.request(FrontendRequest::Activate(id, false)).await?
|
|
}
|
|
CliSubcommand::List => {
|
|
tx.request(FrontendRequest::Enumerate()).await?;
|
|
while let Some(e) = rx.next().await {
|
|
if let FrontendEvent::Enumerate(clients) = e? {
|
|
for (handle, config, state) in clients {
|
|
let host = config.hostname.unwrap_or("unknown".to_owned());
|
|
let port = config.port;
|
|
let pos = config.pos;
|
|
let active = state.active;
|
|
let ips = state.ips;
|
|
println!(
|
|
"id {handle}: {host}:{port} ({pos}) active: {active}, ips: {ips:?}"
|
|
);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
CliSubcommand::SetHost { id, host } => {
|
|
tx.request(FrontendRequest::UpdateHostname(id, host))
|
|
.await?
|
|
}
|
|
CliSubcommand::SetPort { id, port } => {
|
|
tx.request(FrontendRequest::UpdatePort(id, port)).await?
|
|
}
|
|
CliSubcommand::SetPosition { id, pos } => {
|
|
tx.request(FrontendRequest::UpdatePosition(id, pos)).await?
|
|
}
|
|
CliSubcommand::SetIps { id, ips } => {
|
|
tx.request(FrontendRequest::UpdateFixIps(id, ips)).await?
|
|
}
|
|
CliSubcommand::EnableCapture => tx.request(FrontendRequest::EnableCapture).await?,
|
|
CliSubcommand::EnableEmulation => tx.request(FrontendRequest::EnableEmulation).await?,
|
|
CliSubcommand::AuthorizeKey {
|
|
description,
|
|
sha256_fingerprint,
|
|
} => {
|
|
tx.request(FrontendRequest::AuthorizeKey(
|
|
description,
|
|
sha256_fingerprint,
|
|
))
|
|
.await?
|
|
}
|
|
CliSubcommand::RemoveAuthorizedKey { sha256_fingerprint } => {
|
|
tx.request(FrontendRequest::RemoveAuthorizedKey(sha256_fingerprint))
|
|
.await?
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|