2025-02-12 00:26:32 -08:00
|
|
|
use log::info;
|
2025-04-28 16:06:51 -07:00
|
|
|
use std::sync::Arc;
|
2025-02-11 23:15:24 -08:00
|
|
|
|
|
|
|
|
use dbus::{
|
2025-05-25 18:52:18 -07:00
|
|
|
channel::{MatchingReceiver, Sender},
|
2025-02-11 23:15:24 -08:00
|
|
|
message::MatchRule,
|
|
|
|
|
nonblock::SyncConnection,
|
|
|
|
|
Path,
|
|
|
|
|
};
|
2025-05-25 18:52:18 -07:00
|
|
|
use dbus_crossroads::Crossroads;
|
2025-02-11 23:15:24 -08:00
|
|
|
|
2025-05-25 18:52:18 -07:00
|
|
|
#[derive(Clone)]
|
2025-04-25 18:02:54 -07:00
|
|
|
pub struct Endpoint<T: Send + Clone + 'static> {
|
2025-02-11 23:15:24 -08:00
|
|
|
connection: Arc<SyncConnection>,
|
2025-04-25 18:02:54 -07:00
|
|
|
implementation: T,
|
2025-02-11 23:15:24 -08:00
|
|
|
}
|
|
|
|
|
|
2025-04-25 18:02:54 -07:00
|
|
|
impl<T: Send + Clone + 'static> Endpoint<T> {
|
2025-05-25 18:52:18 -07:00
|
|
|
pub fn new(connection: Arc<SyncConnection>, implementation: T) -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
connection,
|
|
|
|
|
implementation,
|
2025-04-25 16:54:37 -07:00
|
|
|
}
|
2025-02-11 23:15:24 -08:00
|
|
|
}
|
|
|
|
|
|
2025-05-25 18:52:18 -07:00
|
|
|
pub async fn register_object<F, R>(&self, path: &str, register_fn: F)
|
2025-04-25 18:02:54 -07:00
|
|
|
where
|
|
|
|
|
F: Fn(&mut Crossroads) -> R,
|
|
|
|
|
R: IntoIterator<Item = dbus_crossroads::IfaceToken<T>>,
|
|
|
|
|
{
|
|
|
|
|
let dbus_path = String::from(path);
|
2025-02-11 23:15:24 -08:00
|
|
|
|
2025-05-25 18:52:18 -07:00
|
|
|
// Enable async support for the crossroads instance.
|
2025-02-11 23:15:24 -08:00
|
|
|
// (Currently irrelevant since dbus generates sync code)
|
2025-05-25 18:52:18 -07:00
|
|
|
let mut cr = Crossroads::new();
|
2025-02-11 23:15:24 -08:00
|
|
|
cr.set_async_support(Some((
|
|
|
|
|
self.connection.clone(),
|
|
|
|
|
Box::new(|x| {
|
|
|
|
|
tokio::spawn(x);
|
|
|
|
|
}),
|
|
|
|
|
)));
|
|
|
|
|
|
2025-04-25 18:02:54 -07:00
|
|
|
// Register the daemon as a D-Bus object with multiple interfaces
|
|
|
|
|
let tokens: Vec<_> = register_fn(&mut cr).into_iter().collect();
|
|
|
|
|
cr.insert(dbus_path, &tokens, self.implementation.clone());
|
2025-02-11 23:15:24 -08:00
|
|
|
|
|
|
|
|
// Start receiving messages.
|
|
|
|
|
self.connection.start_receive(
|
|
|
|
|
MatchRule::new_method_call(),
|
2025-05-25 18:52:18 -07:00
|
|
|
Box::new(move |msg, conn| cr.handle_message(msg, conn).is_ok()),
|
2025-02-11 23:15:24 -08:00
|
|
|
);
|
|
|
|
|
|
2025-04-25 18:02:54 -07:00
|
|
|
info!(target: "dbus", "Registered endpoint at {} with {} interfaces", path, tokens.len());
|
2025-02-11 23:15:24 -08:00
|
|
|
}
|
|
|
|
|
|
2025-04-25 18:02:54 -07:00
|
|
|
pub fn send_signal<S>(&self, path: &str, signal: S) -> Result<u32, ()>
|
2025-02-11 23:15:24 -08:00
|
|
|
where
|
|
|
|
|
S: dbus::message::SignalArgs + dbus::arg::AppendAll,
|
|
|
|
|
{
|
2025-04-25 18:02:54 -07:00
|
|
|
let message = signal.to_emit_message(&Path::new(path).unwrap());
|
2025-02-11 23:15:24 -08:00
|
|
|
self.connection.send(message)
|
|
|
|
|
}
|
|
|
|
|
}
|