mirror of
https://github.com/joleuger/vuinputd.git
synced 2026-07-18 00:45:07 +00:00
Some refactorings to prepare the switch from calling a lambda function from the forked process to reinvoking the whole process with the job description as json
This commit is contained in:
parent
364b86a190
commit
d86a90e2b1
13 changed files with 125 additions and 46 deletions
|
|
@ -13,8 +13,6 @@ use std::mem::{self, size_of, zeroed};
|
|||
use std::os::fd::AsRawFd;
|
||||
use std::os::raw::{c_char, c_void};
|
||||
use std::ptr;
|
||||
use std::thread::sleep;
|
||||
use std::time::Duration;
|
||||
pub use uinput_ioctls::*;
|
||||
|
||||
// Constants (same numeric values as in linux headers)
|
||||
|
|
|
|||
|
|
@ -27,3 +27,5 @@ futures = "0.3.31"
|
|||
async-io = "2.6.0"
|
||||
anyhow = "1.0.100"
|
||||
clap = { version = "4", features = ["derive"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
|
|
|
|||
27
vuinputd/src/actions/action.rs
Normal file
27
vuinputd/src/actions/action.rs
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// Author: Johannes Leupolz <dev@leupolz.eu>
|
||||
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
#[derive(Serialize,Deserialize)]
|
||||
#[serde(tag = "action")]
|
||||
pub enum Action {
|
||||
#[serde(rename = "mknod-device")]
|
||||
MknodDevice {
|
||||
path: String,
|
||||
major: u32,
|
||||
minor: u32,
|
||||
mode: u32,
|
||||
},
|
||||
|
||||
#[serde(rename = "announce-via-netlink")]
|
||||
AnnounceViaNetlink {
|
||||
message: String,
|
||||
},
|
||||
|
||||
#[serde(rename = "remove-device")]
|
||||
RemoveDevice {
|
||||
path: String,
|
||||
},
|
||||
}
|
||||
30
vuinputd/src/actions/handle_action.rs
Normal file
30
vuinputd/src/actions/handle_action.rs
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// Author: Johannes Leupolz <dev@leupolz.eu>
|
||||
|
||||
use super::action::Action;
|
||||
|
||||
pub fn handle_cli_action(json: String) -> i32 {
|
||||
let action: Action = serde_json::from_str(&json)
|
||||
.expect("invalid action JSON");
|
||||
handle_action(action).unwrap_or_else(|err|
|
||||
{
|
||||
panic!("Error handling action: {}",err);
|
||||
});
|
||||
0
|
||||
}
|
||||
|
||||
fn handle_action(action: Action) -> Result<(), String> {
|
||||
|
||||
match action {
|
||||
Action::MknodDevice { .. } => {
|
||||
Ok(())
|
||||
}
|
||||
Action::AnnounceViaNetlink { .. } => {
|
||||
Ok(())
|
||||
}
|
||||
Action::RemoveDevice { .. } => {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
9
vuinputd/src/actions/mod.rs
Normal file
9
vuinputd/src/actions/mod.rs
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// Author: Johannes Leupolz <dev@leupolz.eu>
|
||||
|
||||
pub mod action;
|
||||
pub mod handle_action;
|
||||
pub mod mknod_input_device;
|
||||
pub mod netlink_message;
|
||||
pub mod runtime_data;
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
|
||||
use crate::job_engine::job::{Dispatcher, Job, JobTarget};
|
||||
use super::job::{Job, JobTarget};
|
||||
|
||||
pub struct ClosureJob {
|
||||
desc: String,
|
||||
|
|
@ -55,34 +55,40 @@ impl Job for ClosureJob {
|
|||
}
|
||||
}
|
||||
|
||||
/// Example usage
|
||||
#[test]
|
||||
pub fn example() {
|
||||
let mut dispatcher = Dispatcher::new();
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::super::job::{Dispatcher, JobTarget};
|
||||
use super::ClosureJob;
|
||||
|
||||
// Send a Host job
|
||||
dispatcher.dispatch(Box::new(ClosureJob::new(
|
||||
"Host maintenance",
|
||||
JobTarget::Host,
|
||||
false,
|
||||
Box::new(|job: &ClosureJob| {
|
||||
let target = job.target.clone();
|
||||
Box::pin(async move {
|
||||
println!("Running host job on {:?}", target);
|
||||
})
|
||||
}),
|
||||
)));
|
||||
/// Example usage
|
||||
#[test]
|
||||
pub fn example() {
|
||||
let mut dispatcher = Dispatcher::new();
|
||||
|
||||
// Sending a Container job works the same
|
||||
// dispatcher.dispatch(Job::new(JobTarget::Container(ns.clone()), "Container task", false, |target| async move {
|
||||
// println!("Running container job for {:?}", target);
|
||||
// }));
|
||||
// Send a Host job
|
||||
dispatcher.dispatch(Box::new(ClosureJob::new(
|
||||
"Host maintenance",
|
||||
JobTarget::Host,
|
||||
false,
|
||||
Box::new(|job: &ClosureJob| {
|
||||
let target = job.target.clone();
|
||||
Box::pin(async move {
|
||||
println!("Running host job on {:?}", target);
|
||||
})
|
||||
}),
|
||||
)));
|
||||
|
||||
//
|
||||
// JOB_DISPATCHER.get().unwrap().lock().unwrap().dispatch(Box::new(ClosureJob::new("Monitor udev events", JobTarget::BackgroundLoop,false,
|
||||
// Box::new(move |_target| Box::pin(monitor_udev::udev_monitor_loop(cancel_token.clone()))))));
|
||||
// Sending a Container job works the same
|
||||
// dispatcher.dispatch(Job::new(JobTarget::Container(ns.clone()), "Container task", false, |target| async move {
|
||||
// println!("Running container job for {:?}", target);
|
||||
// }));
|
||||
|
||||
// Allow loops to run briefly before dropping all senders -> graceful shutdown
|
||||
dispatcher.close();
|
||||
dispatcher.wait_until_finished();
|
||||
//
|
||||
// JOB_DISPATCHER.get().unwrap().lock().unwrap().dispatch(Box::new(ClosureJob::new("Monitor udev events", JobTarget::BackgroundLoop,false,
|
||||
// Box::new(move |_target| Box::pin(monitor_udev::udev_monitor_loop(cancel_token.clone()))))));
|
||||
|
||||
// Allow loops to run briefly before dropping all senders -> graceful shutdown
|
||||
dispatcher.close();
|
||||
dispatcher.wait_until_finished();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,14 +14,7 @@ use async_io::Timer;
|
|||
use log::debug;
|
||||
|
||||
use crate::{
|
||||
job_engine::job::{Job, JobTarget},
|
||||
jobs::{
|
||||
mknod_input_device::ensure_input_device,
|
||||
monitor_udev_job::EVENT_STORE,
|
||||
netlink_message::send_udev_monitor_message_with_properties,
|
||||
runtime_data::{ensure_udev_structure, read_udev_data, write_udev_data},
|
||||
},
|
||||
process_tools::{await_process, run_in_net_and_mnt_namespace, Pid, RequestingProcess},
|
||||
actions::{mknod_input_device::ensure_input_device, netlink_message::send_udev_monitor_message_with_properties, runtime_data::{ensure_udev_structure, read_udev_data, write_udev_data}}, job_engine::job::{Job, JobTarget}, jobs::monitor_udev_job::EVENT_STORE, process_tools::{Pid, RequestingProcess, await_process, run_in_net_and_mnt_namespace}
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug, Copy, PartialOrd, PartialEq)]
|
||||
|
|
|
|||
|
|
@ -3,8 +3,5 @@
|
|||
// Author: Johannes Leupolz <dev@leupolz.eu>
|
||||
|
||||
pub mod inject_in_container_job;
|
||||
pub mod mknod_input_device;
|
||||
pub mod monitor_udev_job;
|
||||
pub mod netlink_message;
|
||||
pub mod remove_from_container_job;
|
||||
pub mod runtime_data;
|
||||
|
|
|
|||
|
|
@ -11,12 +11,7 @@ use std::{
|
|||
use log::debug;
|
||||
|
||||
use crate::{
|
||||
job_engine::job::{Job, JobTarget},
|
||||
jobs::{
|
||||
mknod_input_device::remove_input_device, monitor_udev_job::EVENT_STORE,
|
||||
netlink_message::send_udev_monitor_message_with_properties, runtime_data::delete_udev_data,
|
||||
},
|
||||
process_tools::{await_process, run_in_net_and_mnt_namespace, Pid, RequestingProcess},
|
||||
actions::{mknod_input_device::remove_input_device, netlink_message::send_udev_monitor_message_with_properties, runtime_data::delete_udev_data}, job_engine::job::{Job, JobTarget}, jobs::monitor_udev_job::EVENT_STORE, process_tools::{Pid, RequestingProcess, await_process, run_in_net_and_mnt_namespace}
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug, Copy, PartialOrd, PartialEq)]
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ pub mod job_engine;
|
|||
use crate::job_engine::{job::*, JOB_DISPATCHER};
|
||||
use crate::process_tools::*;
|
||||
|
||||
pub mod actions;
|
||||
|
||||
pub mod jobs;
|
||||
|
||||
use clap::Parser;
|
||||
|
|
@ -58,9 +60,24 @@ struct Args {
|
|||
/// Device name (without /dev/)
|
||||
#[arg(long)]
|
||||
devname: Option<String>,
|
||||
|
||||
/// Action to execute (JSON encoded). Note that this excludes all other options.
|
||||
#[arg(long, value_name = "JSON")]
|
||||
pub action: Option<String>,
|
||||
}
|
||||
|
||||
fn validate_args(args: &Args) -> Result<(), String> {
|
||||
// action might only occur alone
|
||||
match (&args.major,&args.minor,&args.devname,&args.action) {
|
||||
(None,None,None,Some(_)) => {},
|
||||
(_,_,_,None) => {},
|
||||
_ => {
|
||||
return Err(
|
||||
"--action must not be used in combination with any other argument".into(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// major/minor must appear together
|
||||
match (&args.major, &args.minor) {
|
||||
(Some(_), Some(_)) | (None, None) => {}
|
||||
|
|
@ -97,6 +114,11 @@ fn main() -> std::io::Result<()> {
|
|||
std::process::exit(2);
|
||||
}
|
||||
|
||||
if args.action.is_some() {
|
||||
let error_code=actions::handle_action::handle_cli_action(args.action.unwrap());
|
||||
std::process::exit(error_code);
|
||||
}
|
||||
|
||||
|
||||
initialize_vuinput_state();
|
||||
VUINPUT_COUNTER.set(AtomicU64::new(3)).expect(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue