91 lines
2.8 KiB
Rust
91 lines
2.8 KiB
Rust
use {
|
|
crate::{
|
|
async_engine::AsyncEngine,
|
|
dbus::{DbusError, DbusHolder, DbusSocket, auth::handle_auth},
|
|
io_uring::IoUring,
|
|
utils::{
|
|
bufio::BufIo, errorfmt::ErrorFmt, numcell::NumCell, oserror::OsErrorExt2,
|
|
run_toplevel::RunToplevel,
|
|
},
|
|
wire_dbus::org,
|
|
},
|
|
std::{cell::Cell, rc::Rc},
|
|
uapi::c,
|
|
};
|
|
|
|
impl DbusHolder {
|
|
pub(super) async fn get(
|
|
self: &Rc<Self>,
|
|
eng: &Rc<AsyncEngine>,
|
|
ring: &Rc<IoUring>,
|
|
addr: &str,
|
|
name: &'static str,
|
|
) -> Result<Rc<DbusSocket>, DbusError> {
|
|
if let Some(c) = self.socket.get() {
|
|
if c.dead.get() {
|
|
self.socket.take();
|
|
} else {
|
|
return Ok(c);
|
|
}
|
|
}
|
|
let socket = connect(eng, ring, addr, name, &self.run_toplevel).await?;
|
|
self.socket.set(Some(socket.clone()));
|
|
Ok(socket)
|
|
}
|
|
}
|
|
|
|
async fn connect(
|
|
eng: &Rc<AsyncEngine>,
|
|
ring: &Rc<IoUring>,
|
|
addr: &str,
|
|
name: &'static str,
|
|
run_toplevel: &Rc<RunToplevel>,
|
|
) -> Result<Rc<DbusSocket>, DbusError> {
|
|
let fd = uapi::socket(c::AF_UNIX, c::SOCK_STREAM | c::SOCK_CLOEXEC, 0)
|
|
.map(Rc::new)
|
|
.map_os_err(DbusError::Socket)?;
|
|
let mut sadr: c::sockaddr_un = uapi::pod_zeroed();
|
|
sadr.sun_family = c::AF_UNIX as _;
|
|
let sun_path = uapi::as_bytes_mut(&mut sadr.sun_path[..]);
|
|
sun_path[..addr.len()].copy_from_slice(addr.as_bytes());
|
|
if let Err(e) = ring.connect(&fd, &sadr).await {
|
|
return Err(DbusError::Connect(e));
|
|
}
|
|
let socket = Rc::new(DbusSocket {
|
|
bus_name: name,
|
|
fd: fd.clone(),
|
|
ring: ring.clone(),
|
|
in_bufs: Default::default(),
|
|
bufio: Rc::new(BufIo::new(&fd, ring)),
|
|
eng: eng.clone(),
|
|
next_serial: NumCell::new(1),
|
|
unique_name: Default::default(),
|
|
reply_handlers: Default::default(),
|
|
incoming: Default::default(),
|
|
outgoing_: Default::default(),
|
|
auth: Default::default(),
|
|
dead: Cell::new(false),
|
|
headers: Default::default(),
|
|
run_toplevel: run_toplevel.clone(),
|
|
signal_handlers: Default::default(),
|
|
});
|
|
let skt = socket.clone();
|
|
socket.call(
|
|
"org.freedesktop.DBus",
|
|
"/org/freedesktop/dbus",
|
|
org::freedesktop::dbus::Hello,
|
|
move |res| match res {
|
|
Ok(name) => {
|
|
log::info!("{}: Acquired unique name {}", skt.bus_name, name.name);
|
|
let _ = skt.unique_name.set(Rc::new(name.name.to_string()));
|
|
}
|
|
Err(e) => {
|
|
log::error!("{}: Hello call failed: {}", skt.bus_name, ErrorFmt(e));
|
|
skt.kill();
|
|
}
|
|
},
|
|
);
|
|
let future = eng.spawn("dbus auth", handle_auth(socket.clone()));
|
|
socket.auth.set(Some(future));
|
|
Ok(socket)
|
|
}
|