Adds kordophoned, basic dbus interface
This commit is contained in:
18
kordophoned/Cargo.toml
Normal file
18
kordophoned/Cargo.toml
Normal file
@@ -0,0 +1,18 @@
|
||||
[package]
|
||||
name = "kordophoned"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
dbus = "0.9.7"
|
||||
dbus-crossroads = "0.5.2"
|
||||
dbus-tokio = "0.7.6"
|
||||
dbus-tree = "0.9.2"
|
||||
env_logger = "0.11.6"
|
||||
kordophone = { path = "../kordophone" }
|
||||
log = "0.4.25"
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
|
||||
[build-dependencies]
|
||||
dbus-codegen = "0.10.0"
|
||||
dbus-crossroads = "0.5.1"
|
||||
24
kordophoned/build.rs
Normal file
24
kordophoned/build.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
const KORDOPHONE_XML: &str = "include/net.buzzert.kordophonecd.Server.xml";
|
||||
|
||||
fn main() {
|
||||
let out_dir = std::env::var("OUT_DIR").unwrap();
|
||||
let out_path = std::path::Path::new(&out_dir).join("kordophone-server.rs");
|
||||
|
||||
let opts = dbus_codegen::GenOpts {
|
||||
connectiontype: dbus_codegen::ConnectionType::Nonblock,
|
||||
methodtype: None, // Set to None for crossroads
|
||||
crossroads: true,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let xml = std::fs::read_to_string(KORDOPHONE_XML)
|
||||
.expect("Error reading server dbus interface");
|
||||
|
||||
let output = dbus_codegen::generate(&xml, &opts)
|
||||
.expect("Error generating server dbus interface");
|
||||
|
||||
std::fs::write(out_path, output)
|
||||
.expect("Error writing server dbus code");
|
||||
|
||||
println!("cargo:rerun-if-changed={}", KORDOPHONE_XML);
|
||||
}
|
||||
8
kordophoned/include/net.buzzert.kordophonecd.Server.xml
Normal file
8
kordophoned/include/net.buzzert.kordophonecd.Server.xml
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<node name="/">
|
||||
<interface name="net.buzzert.kordophone.Server">
|
||||
<method name="GetVersion">
|
||||
<arg type="s" name="version" direction="out" />
|
||||
</method>
|
||||
</interface>
|
||||
</node>
|
||||
11
kordophoned/src/daemon/mod.rs
Normal file
11
kordophoned/src/daemon/mod.rs
Normal file
@@ -0,0 +1,11 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
pub struct Daemon {
|
||||
pub version: String,
|
||||
}
|
||||
|
||||
impl Daemon {
|
||||
pub fn new() -> Self {
|
||||
Self { version: "0.1.0".to_string() }
|
||||
}
|
||||
}
|
||||
93
kordophoned/src/dbus/endpoint.rs
Normal file
93
kordophoned/src/dbus/endpoint.rs
Normal file
@@ -0,0 +1,93 @@
|
||||
use crate::{dbus::interface::OBJECT_PATH, daemon::Daemon};
|
||||
|
||||
use crossroads::Crossroads;
|
||||
use dbus::{
|
||||
channel::{MatchingReceiver, Sender},
|
||||
message::MatchRule,
|
||||
nonblock::SyncConnection,
|
||||
Path,
|
||||
};
|
||||
|
||||
use dbus_crossroads as crossroads;
|
||||
use dbus_tokio::connection;
|
||||
use dbus_tree::{DataType, MethodErr};
|
||||
use log::info;
|
||||
use std::{future::Future, sync::Arc, thread};
|
||||
|
||||
mod dbus_interface {
|
||||
#![allow(unused)]
|
||||
include!(concat!(env!("OUT_DIR"), "/kordophone-server.rs"));
|
||||
}
|
||||
|
||||
use dbus_interface::NetBuzzertKordophoneServer;
|
||||
|
||||
pub struct Endpoint {
|
||||
connection: Arc<SyncConnection>,
|
||||
daemon: Arc<Daemon>,
|
||||
}
|
||||
|
||||
impl Endpoint {
|
||||
pub fn new(daemon: Arc<Daemon>) -> Self {
|
||||
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, daemon }
|
||||
}
|
||||
|
||||
pub async fn start(&self) {
|
||||
use crate::dbus::interface;
|
||||
|
||||
self.connection
|
||||
.request_name(interface::NAME, false, true, false)
|
||||
.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.
|
||||
let token = dbus_interface::register_net_buzzert_kordophone_server(&mut cr);
|
||||
cr.insert(OBJECT_PATH, &[token], self.daemon.clone());
|
||||
|
||||
// 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", "DBus server started");
|
||||
}
|
||||
|
||||
pub fn send_signal<S>(&self, signal: S) -> Result<u32, ()>
|
||||
where
|
||||
S: dbus::message::SignalArgs + dbus::arg::AppendAll,
|
||||
{
|
||||
let message = signal.to_emit_message(&Path::new(OBJECT_PATH).unwrap());
|
||||
self.connection.send(message)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl NetBuzzertKordophoneServer for Arc<Daemon> {
|
||||
fn get_version(&mut self) -> Result<String, MethodErr> {
|
||||
Ok(self.version.clone())
|
||||
}
|
||||
}
|
||||
6
kordophoned/src/dbus/mod.rs
Normal file
6
kordophoned/src/dbus/mod.rs
Normal file
@@ -0,0 +1,6 @@
|
||||
pub mod endpoint;
|
||||
|
||||
pub mod interface {
|
||||
pub static NAME: &str = "net.buzzert.kordophonecd";
|
||||
pub static OBJECT_PATH: &str = "/net/buzzert/kordophone/Server";
|
||||
}
|
||||
24
kordophoned/src/main.rs
Normal file
24
kordophoned/src/main.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
mod dbus;
|
||||
mod daemon;
|
||||
|
||||
use std::future;
|
||||
use std::sync::Arc;
|
||||
use log::LevelFilter;
|
||||
fn initialize_logging() {
|
||||
env_logger::Builder::from_default_env()
|
||||
.filter_level(LevelFilter::Info)
|
||||
.format_timestamp_secs()
|
||||
.init();
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
initialize_logging();
|
||||
|
||||
let daemon = Arc::new(daemon::Daemon::new());
|
||||
let endpoint = Arc::new(dbus::endpoint::Endpoint::new(daemon));
|
||||
endpoint.start().await;
|
||||
|
||||
future::pending::<()>().await;
|
||||
unreachable!()
|
||||
}
|
||||
Reference in New Issue
Block a user