Private
Public Access
1
0
Files
Kordophone/kordophoned/src/dbus/endpoint.rs

88 lines
2.5 KiB
Rust
Raw Normal View History

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_crossroads::Crossroads;
use dbus_tokio::connection;
2025-02-11 23:15:24 -08:00
use dbus::{
message::MatchRule,
nonblock::SyncConnection,
channel::{Sender, MatchingReceiver},
2025-02-11 23:15:24 -08:00
Path,
};
pub struct Endpoint<T: Send + Clone + 'static> {
2025-02-11 23:15:24 -08:00
connection: Arc<SyncConnection>,
implementation: T,
2025-02-11 23:15:24 -08:00
}
impl<T: Send + Clone + 'static> Endpoint<T> {
pub fn new(implementation: T) -> Self {
2025-02-11 23:15:24 -08:00
let (resource, connection) = connection::new_session_sync().unwrap();
// The resource is a task that should be spawned onto a tokio compatible
// reactor ASAP. If the resource ever finishes, you lost connection to D-Bus.
//
// To shut down the connection, both call _handle.abort() and drop the connection.
let _handle = tokio::spawn(async {
let err = resource.await;
panic!("Lost connection to D-Bus: {}", err);
});
Self {
connection,
implementation
}
2025-02-11 23:15:24 -08:00
}
pub async fn register<F, R>(
&self,
name: &str,
path: &str,
register_fn: F
)
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
self.connection
.request_name(name, false, true, false)
2025-02-11 23:15:24 -08:00
.await
.expect("Unable to acquire dbus name");
let mut cr = Crossroads::new();
// Enable async support for the crossroads instance.
// (Currently irrelevant since dbus generates sync code)
cr.set_async_support(Some((
self.connection.clone(),
Box::new(|x| {
tokio::spawn(x);
}),
)));
// 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(),
Box::new(move |msg, conn|
cr.handle_message(msg, conn).is_ok()
),
);
info!(target: "dbus", "Registered endpoint at {} with {} interfaces", path, tokens.len());
2025-02-11 23:15:24 -08: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,
{
let message = signal.to_emit_message(&Path::new(path).unwrap());
2025-02-11 23:15:24 -08:00
self.connection.send(message)
}
}