autocommit 2022-02-28 00:14:11 CET
This commit is contained in:
parent
db88f2db42
commit
0e9afcbfa5
22 changed files with 1013 additions and 239 deletions
|
|
@ -30,12 +30,15 @@ struct Auth {
|
|||
impl Auth {
|
||||
async fn run(&mut self) {
|
||||
if let Err(e) = self.handle_auth().await {
|
||||
log::error!("Could not authenticate to dbus socket: {}", ErrorFmt(e));
|
||||
self.socket.dead.set(true);
|
||||
self.socket.auth.take();
|
||||
log::error!(
|
||||
"{}: Could not authenticate to dbus socket: {}",
|
||||
self.socket.bus_name,
|
||||
ErrorFmt(e)
|
||||
);
|
||||
self.socket.kill();
|
||||
return;
|
||||
}
|
||||
log::info!("Authenticated");
|
||||
log::info!("{}: Authenticated", self.socket.bus_name);
|
||||
self.socket.incoming.set(Some(
|
||||
self.socket.eng.spawn(handle_incoming(self.socket.clone())),
|
||||
));
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ impl DynamicType {
|
|||
DynamicType::Fd => Variant::Fd(parser.read_fd()?),
|
||||
DynamicType::Array(el) => {
|
||||
let len: u32 = parser.read_pod()?;
|
||||
parser.align_to(el.alignment());
|
||||
parser.align_to(el.alignment())?;
|
||||
let len = len as usize;
|
||||
if parser.buf.len() - parser.pos < len {
|
||||
return Err(DbusError::UnexpectedEof);
|
||||
|
|
@ -165,12 +165,12 @@ impl DynamicType {
|
|||
Variant::Array(el.deref().clone(), vals)
|
||||
}
|
||||
DynamicType::DictEntry(k, v) => {
|
||||
parser.align_to(8);
|
||||
parser.align_to(8)?;
|
||||
Variant::DictEntry(Box::new(k.parse(parser)?), Box::new(v.parse(parser)?))
|
||||
}
|
||||
DynamicType::Struct(fields) => {
|
||||
let mut vals = vec![];
|
||||
parser.align_to(8);
|
||||
parser.align_to(8)?;
|
||||
for field in fields {
|
||||
vals.push(field.parse(parser)?);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::dbus::auth::handle_auth;
|
||||
use crate::dbus::{DbusError, DbusHolder, DbusSocket};
|
||||
use crate::{AsyncEngine, NumCell};
|
||||
use crate::{org, AsyncEngine, ErrorFmt, NumCell, RunToplevel};
|
||||
use std::cell::Cell;
|
||||
use std::rc::Rc;
|
||||
use uapi::c;
|
||||
|
|
@ -10,6 +10,7 @@ impl DbusHolder {
|
|||
self: &Rc<Self>,
|
||||
eng: &Rc<AsyncEngine>,
|
||||
addr: &str,
|
||||
name: &'static str,
|
||||
) -> Result<Rc<DbusSocket>, DbusError> {
|
||||
if let Some(c) = self.socket.get() {
|
||||
if c.dead.get() {
|
||||
|
|
@ -18,13 +19,18 @@ impl DbusHolder {
|
|||
return Ok(c);
|
||||
}
|
||||
}
|
||||
let socket = connect(eng, addr)?;
|
||||
let socket = connect(eng, addr, name, &self.run_toplevel)?;
|
||||
self.socket.set(Some(socket.clone()));
|
||||
Ok(socket)
|
||||
}
|
||||
}
|
||||
|
||||
fn connect(eng: &Rc<AsyncEngine>, addr: &str) -> Result<Rc<DbusSocket>, DbusError> {
|
||||
fn connect(
|
||||
eng: &Rc<AsyncEngine>,
|
||||
addr: &str,
|
||||
name: &'static str,
|
||||
run_toplevel: &Rc<RunToplevel>,
|
||||
) -> Result<Rc<DbusSocket>, DbusError> {
|
||||
let socket = match uapi::socket(
|
||||
c::AF_UNIX,
|
||||
c::SOCK_STREAM | c::SOCK_NONBLOCK | c::SOCK_CLOEXEC,
|
||||
|
|
@ -41,19 +47,37 @@ fn connect(eng: &Rc<AsyncEngine>, addr: &str) -> Result<Rc<DbusSocket>, DbusErro
|
|||
return Err(DbusError::Connect(e.into()));
|
||||
}
|
||||
let socket = Rc::new(DbusSocket {
|
||||
bus_name: name,
|
||||
fd: eng.fd(&Rc::new(socket))?,
|
||||
eng: eng.clone(),
|
||||
next_serial: NumCell::new(1),
|
||||
bufs: Default::default(),
|
||||
unique_name: Default::default(),
|
||||
outgoing: Default::default(),
|
||||
waiters: Default::default(),
|
||||
replies: 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(),
|
||||
});
|
||||
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(handle_auth(socket.clone()));
|
||||
socket.auth.set(Some(future));
|
||||
Ok(socket)
|
||||
|
|
|
|||
|
|
@ -2,17 +2,21 @@ use super::{
|
|||
HDR_DESTINATION, HDR_ERROR_NAME, HDR_INTERFACE, HDR_MEMBER, HDR_PATH, HDR_REPLY_SERIAL,
|
||||
HDR_SENDER, HDR_SIGNATURE, HDR_UNIX_FDS,
|
||||
};
|
||||
use crate::dbus::{DbusError, DbusSocket, DynamicType, Headers, Parser};
|
||||
use crate::dbus::{
|
||||
CallError, DbusError, DbusSocket, Headers, Parser, MSG_ERROR, MSG_METHOD_RETURN,
|
||||
};
|
||||
use crate::utils::ptr_ext::{MutPtrExt, PtrExt};
|
||||
use crate::ErrorFmt;
|
||||
use std::cell::UnsafeCell;
|
||||
use std::collections::VecDeque;
|
||||
use std::mem::MaybeUninit;
|
||||
use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
use uapi::{c, Errno, MaybeUninitSliceExt, MsghdrMut, OwnedFd};
|
||||
|
||||
pub async fn handle_incoming(socket: Rc<DbusSocket>) {
|
||||
let mut incoming = Incoming {
|
||||
socket,
|
||||
msg_buf: vec![],
|
||||
buf: Box::new([MaybeUninit::uninit(); 4096]),
|
||||
buf_start: 0,
|
||||
buf_end: 0,
|
||||
|
|
@ -25,7 +29,6 @@ pub async fn handle_incoming(socket: Rc<DbusSocket>) {
|
|||
pub struct Incoming {
|
||||
socket: Rc<DbusSocket>,
|
||||
|
||||
msg_buf: Vec<u8>,
|
||||
buf: Box<[MaybeUninit<u8>; 4096]>,
|
||||
buf_start: usize,
|
||||
buf_end: usize,
|
||||
|
|
@ -36,36 +39,46 @@ pub struct Incoming {
|
|||
impl Incoming {
|
||||
async fn run(&mut self) {
|
||||
loop {
|
||||
if self.socket.dead.get() {
|
||||
return;
|
||||
}
|
||||
if let Err(e) = self.handle_msg().await {
|
||||
log::error!("Could not process an incoming message: {}", ErrorFmt(e));
|
||||
self.socket.incoming.take();
|
||||
self.socket.outgoing_.take();
|
||||
log::error!(
|
||||
"{}: Could not process an incoming message: {}",
|
||||
self.socket.bus_name,
|
||||
ErrorFmt(e)
|
||||
);
|
||||
self.socket.kill();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_msg(&mut self) -> Result<(), DbusError> {
|
||||
self.msg_buf.clear();
|
||||
let msg_buf_data = UnsafeCell::new(self.socket.bufs.pop().unwrap_or_default());
|
||||
let msg_buf = unsafe { msg_buf_data.get().deref_mut() };
|
||||
msg_buf.clear();
|
||||
const FIXED_HEADER_SIZE: usize = 16;
|
||||
self.fill_msg_buf(FIXED_HEADER_SIZE).await?;
|
||||
let endianess = self.msg_buf[0];
|
||||
self.fill_msg_buf(FIXED_HEADER_SIZE, msg_buf).await?;
|
||||
let endianess = msg_buf[0];
|
||||
if (endianess == b'l') != cfg!(target_endian = "little") {
|
||||
return Err(DbusError::InvalidEndianess);
|
||||
}
|
||||
let msg_ty = self.msg_buf[1];
|
||||
let flags = self.msg_buf[2];
|
||||
let protocol = self.msg_buf[3];
|
||||
let msg_ty = msg_buf[1];
|
||||
let _flags = msg_buf[2];
|
||||
let protocol = msg_buf[3];
|
||||
if protocol != 1 {
|
||||
return Err(DbusError::InvalidEndianess);
|
||||
return Err(DbusError::InvalidProtocol);
|
||||
}
|
||||
let mut fields2 = [0u32; 3];
|
||||
uapi::pod_write(&self.msg_buf[4..], &mut fields2[..]).unwrap();
|
||||
let [body_len, serial, headers_len] = fields2;
|
||||
uapi::pod_write(&msg_buf[4..], &mut fields2[..]).unwrap();
|
||||
let [body_len, _serial, headers_len] = fields2;
|
||||
let dyn_header_len = headers_len + (headers_len.wrapping_neg() & 7);
|
||||
let remaining = dyn_header_len + body_len;
|
||||
self.fill_msg_buf(remaining as usize).await?;
|
||||
let headers = &self.msg_buf[FIXED_HEADER_SIZE..FIXED_HEADER_SIZE + headers_len as usize];
|
||||
self.fill_msg_buf(remaining as usize, msg_buf).await?;
|
||||
drop(msg_buf);
|
||||
let msg_buf = unsafe { msg_buf_data.get().deref().deref() };
|
||||
let headers = &msg_buf[FIXED_HEADER_SIZE..FIXED_HEADER_SIZE + headers_len as usize];
|
||||
let headers = self.parse_headers(headers)?;
|
||||
let unix_fds = headers.unix_fds.unwrap_or(0) as usize;
|
||||
if self.fds.len() < unix_fds {
|
||||
|
|
@ -73,19 +86,60 @@ impl Incoming {
|
|||
}
|
||||
let fds: Vec<_> = self.fds.drain(..unix_fds).collect();
|
||||
let mut parser = Parser {
|
||||
buf: &self.msg_buf,
|
||||
buf: &msg_buf,
|
||||
pos: FIXED_HEADER_SIZE + dyn_header_len as usize,
|
||||
fds: &fds,
|
||||
};
|
||||
log::info!("headers = {:?}", headers);
|
||||
if let Some(sig) = headers.signature {
|
||||
let mut sig = sig.0.as_bytes();
|
||||
while sig.len() > 0 {
|
||||
let (dt, rem) = DynamicType::from_signature(sig)?;
|
||||
sig = rem;
|
||||
let val = dt.parse(&mut parser)?;
|
||||
log::info!("{:?}", val);
|
||||
match msg_ty {
|
||||
MSG_METHOD_RETURN | MSG_ERROR => {
|
||||
let serial = match headers.reply_serial {
|
||||
Some(s) => s,
|
||||
_ => return Err(DbusError::NoReplySerial),
|
||||
};
|
||||
if let Some(reply) = self.socket.reply_handlers.remove(&serial) {
|
||||
if msg_ty == MSG_ERROR {
|
||||
let ename = match headers.error_name {
|
||||
Some(n) => n.into_owned(),
|
||||
_ => return Err(DbusError::NoErrorName),
|
||||
};
|
||||
let mut emsg = None;
|
||||
if let Some(sig) = headers.signature {
|
||||
if sig.0.starts_with("s") {
|
||||
emsg = Some(parser.read_string()?.into_owned());
|
||||
}
|
||||
}
|
||||
let error = CallError {
|
||||
name: ename,
|
||||
msg: emsg,
|
||||
};
|
||||
reply.handle_error(&self.socket, DbusError::CallError(error));
|
||||
} else {
|
||||
let sig = headers.signature.as_deref().unwrap_or("");
|
||||
if sig != reply.signature() {
|
||||
log::error!(
|
||||
"{}: Message reply has an invalid signature: expected: {}, actual: {}",
|
||||
self.socket.bus_name,
|
||||
sig,
|
||||
reply.signature()
|
||||
);
|
||||
} else {
|
||||
let buf = unsafe { std::mem::take(msg_buf_data.get().deref_mut()) };
|
||||
if let Err(e) = reply.handle(&self.socket, &headers, &mut parser, buf) {
|
||||
log::error!(
|
||||
"{}: Could not handle reply: {}",
|
||||
self.socket.bus_name,
|
||||
ErrorFmt(e)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
let msg_buf = msg_buf_data.into_inner();
|
||||
if msg_buf.capacity() > 0 {
|
||||
self.socket.bufs.push(msg_buf);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -113,7 +167,7 @@ impl Incoming {
|
|||
Ok(headers)
|
||||
}
|
||||
|
||||
async fn fill_msg_buf(&mut self, mut n: usize) -> Result<(), DbusError> {
|
||||
async fn fill_msg_buf(&mut self, mut n: usize, buf: &mut Vec<u8>) -> Result<(), DbusError> {
|
||||
while n > 0 {
|
||||
if self.buf_start == self.buf_end {
|
||||
while let Err(e) = self.recvmsg() {
|
||||
|
|
@ -129,17 +183,9 @@ impl Incoming {
|
|||
let read = n.min(self.buf_end - self.buf_start);
|
||||
let buf_start = self.buf_start % self.buf.len();
|
||||
unsafe {
|
||||
if buf_start + read <= self.buf.len() {
|
||||
self.msg_buf.extend_from_slice(
|
||||
self.buf[buf_start..buf_start + read].slice_assume_init_ref(),
|
||||
);
|
||||
} else {
|
||||
self.msg_buf
|
||||
.extend_from_slice(self.buf[buf_start..].slice_assume_init_ref());
|
||||
self.msg_buf.extend_from_slice(
|
||||
self.buf[..read - (self.buf.len() - buf_start)].slice_assume_init_ref(),
|
||||
);
|
||||
}
|
||||
buf.extend_from_slice(
|
||||
self.buf[buf_start..buf_start + read].slice_assume_init_ref(),
|
||||
);
|
||||
}
|
||||
n -= read;
|
||||
self.buf_start += read;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
use crate::dbus::{DbusMessage, DbusSocket};
|
||||
use crate::utils::vec_ext::VecExt;
|
||||
use crate::utils::vec_ext::{UninitVecExt, VecExt};
|
||||
use crate::utils::vecstorage::VecStorage;
|
||||
use crate::ErrorFmt;
|
||||
use std::collections::VecDeque;
|
||||
use std::mem;
|
||||
use std::mem::MaybeUninit;
|
||||
use std::ptr::NonNull;
|
||||
use std::rc::Rc;
|
||||
use uapi::{c, Errno, Msghdr};
|
||||
|
|
@ -27,7 +29,7 @@ struct Outgoing {
|
|||
socket: Rc<DbusSocket>,
|
||||
|
||||
msgs: VecDeque<DbusMessageOffset>,
|
||||
cmsg: Vec<u8>,
|
||||
cmsg: Vec<MaybeUninit<u8>>,
|
||||
fds: Vec<c::c_int>,
|
||||
iovecs: VecStorage<NonNull<[u8]>>,
|
||||
}
|
||||
|
|
@ -37,7 +39,15 @@ impl Outgoing {
|
|||
loop {
|
||||
self.socket.outgoing.non_empty().await;
|
||||
while let Err(e) = self.try_flush() {
|
||||
if e != Errno(c::EAGAIN) {}
|
||||
if e != Errno(c::EAGAIN) {
|
||||
log::error!(
|
||||
"{}: Could not send a message to the bus: {}",
|
||||
self.socket.bus_name,
|
||||
ErrorFmt(e)
|
||||
);
|
||||
self.socket.kill();
|
||||
return;
|
||||
}
|
||||
let _ = self.socket.fd.writable().await;
|
||||
}
|
||||
}
|
||||
|
|
@ -68,16 +78,14 @@ impl Outgoing {
|
|||
self.fds.extend(fds.iter().map(|f| f.raw()));
|
||||
let cmsg_space = uapi::cmsg_space(fds.len() * mem::size_of::<c::c_int>());
|
||||
self.cmsg.reserve(cmsg_space);
|
||||
let (_, mut spare) = self.cmsg.split_at_spare_mut_ext();
|
||||
let (_, mut spare) = self.cmsg.split_at_spare_mut_bytes_ext();
|
||||
let hdr = c::cmsghdr {
|
||||
cmsg_len: 0,
|
||||
cmsg_level: c::SOL_SOCKET,
|
||||
cmsg_type: c::SCM_RIGHTS,
|
||||
};
|
||||
let len = uapi::cmsg_write(&mut spare, hdr, &self.fds).unwrap();
|
||||
unsafe {
|
||||
self.cmsg.set_len(len);
|
||||
}
|
||||
self.cmsg.set_len_safe(len);
|
||||
}
|
||||
let msg = Msghdr {
|
||||
iov: &iovecs[..],
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
pub fn read_pod<'b, T: DbusType<'b> + Pod>(&mut self) -> Result<T, DbusError> {
|
||||
self.align_to(T::ALIGNMENT);
|
||||
self.align_to(T::ALIGNMENT)?;
|
||||
match uapi::pod_read_init(&self.buf[self.pos..]) {
|
||||
Ok(v) => {
|
||||
self.pos += mem::size_of::<T>();
|
||||
|
|
@ -74,7 +74,7 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
fn read_string_(&mut self, len: usize) -> Result<&'a str, DbusError> {
|
||||
if self.buf.len() - self.pos < len + 1 {
|
||||
if len == usize::MAX || self.buf.len() - self.pos < len + 1 {
|
||||
return Err(DbusError::UnexpectedEof);
|
||||
}
|
||||
let s = &self.buf[self.pos..self.pos + len];
|
||||
|
|
@ -128,4 +128,14 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
parser.parse(self)
|
||||
}
|
||||
|
||||
pub fn read_variant_as<T: DbusType<'a>>(&mut self) -> Result<T, DbusError> {
|
||||
let sig = self.read_signature()?;
|
||||
let mut sig = sig.0.as_bytes();
|
||||
T::consume_signature(&mut sig)?;
|
||||
if sig.len() > 0 {
|
||||
return Err(DbusError::TrailingVariantSignature);
|
||||
}
|
||||
T::unmarshal(self)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
66
src/dbus/property.rs
Normal file
66
src/dbus/property.rs
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
use crate::dbus::{DbusError, DbusType, Formatter, Message, MethodCall, Parser};
|
||||
use std::borrow::Cow;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Get<'a, T: DbusType<'static>> {
|
||||
pub interface_name: Cow<'a, str>,
|
||||
pub property_name: Cow<'a, str>,
|
||||
pub _phantom: PhantomData<T>,
|
||||
}
|
||||
|
||||
unsafe impl<'a, T: DbusType<'static>> Message<'a> for Get<'a, T> {
|
||||
const SIGNATURE: &'static str = "ss";
|
||||
const INTERFACE: &'static str = "org.freedesktop.DBus.Properties";
|
||||
const MEMBER: &'static str = "Get";
|
||||
type Generic<'b> = Get<'b, T>;
|
||||
|
||||
fn marshal(&self, fmt: &mut Formatter) {
|
||||
fmt.marshal(&self.interface_name);
|
||||
fmt.marshal(&self.property_name);
|
||||
}
|
||||
|
||||
fn unmarshal(parser: &mut Parser<'a>) -> Result<Self, DbusError> {
|
||||
Ok(Self {
|
||||
interface_name: parser.unmarshal()?,
|
||||
property_name: parser.unmarshal()?,
|
||||
_phantom: Default::default(),
|
||||
})
|
||||
}
|
||||
|
||||
fn num_fds(&self) -> u32 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: DbusType<'static>> MethodCall<'a> for Get<'a, T> {
|
||||
type Reply = GetReply<'static, T>;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct GetReply<'a, T: DbusType<'a>> {
|
||||
pub value: T,
|
||||
pub _phantom: PhantomData<&'a ()>,
|
||||
}
|
||||
|
||||
unsafe impl<'a, T: DbusType<'a>> Message<'a> for GetReply<'a, T> {
|
||||
const SIGNATURE: &'static str = "v";
|
||||
const INTERFACE: &'static str = "org.freedesktop.DBus.Properties";
|
||||
const MEMBER: &'static str = "Get";
|
||||
type Generic<'b> = GetReply<'b, T::Generic<'b>>;
|
||||
|
||||
fn marshal(&self, _fmt: &mut Formatter) {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
fn unmarshal(parser: &mut Parser<'a>) -> Result<Self, DbusError> {
|
||||
Ok(Self {
|
||||
value: parser.read_variant_as()?,
|
||||
_phantom: Default::default(),
|
||||
})
|
||||
}
|
||||
|
||||
fn num_fds(&self) -> u32 {
|
||||
self.value.num_fds()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,39 +1,150 @@
|
|||
use crate::dbus::property::Get;
|
||||
use crate::dbus::types::{ObjectPath, Signature, Variant};
|
||||
use crate::dbus::{
|
||||
DbusMessage, DbusSocket, DbusType, Formatter, Message, MethodCall, HDR_DESTINATION,
|
||||
HDR_INTERFACE, HDR_MEMBER, HDR_PATH, HDR_SIGNATURE, HDR_UNIX_FDS,
|
||||
AsyncProperty, AsyncReply, AsyncReplySlot, DbusError, DbusMessage, DbusSocket, DbusType,
|
||||
Formatter, Headers, Message, MethodCall, Parser, Property, Reply, ReplyHandler,
|
||||
HDR_DESTINATION, HDR_INTERFACE, HDR_MEMBER, HDR_PATH, HDR_SIGNATURE, HDR_UNIX_FDS,
|
||||
MSG_METHOD_CALL, NO_REPLY_EXPECTED,
|
||||
};
|
||||
|
||||
const MESSAGE_CALL: u8 = 1;
|
||||
const MESSAGE_RETURN: u8 = 2;
|
||||
const ERROR: u8 = 3;
|
||||
const SIGNAL: u8 = 4;
|
||||
use std::cell::Cell;
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::ops::DerefMut;
|
||||
use std::rc::Rc;
|
||||
use uapi::c;
|
||||
|
||||
impl DbusSocket {
|
||||
pub fn new() -> Self {
|
||||
todo!();
|
||||
pub(super) fn kill(self: &Rc<Self>) {
|
||||
self.dead.set(true);
|
||||
self.auth.take();
|
||||
self.incoming.take();
|
||||
self.outgoing_.take();
|
||||
let _ = uapi::shutdown(self.fd.raw(), c::SHUT_RDWR);
|
||||
let replies = mem::take(self.reply_handlers.lock().deref_mut());
|
||||
for (_, handler) in replies {
|
||||
handler.handle_error(self, DbusError::Killed);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn call_noreply<'a, T: MethodCall<'a>>(&self, destination: &str, path: &str, msg: T) {
|
||||
let (msg, _) = self.format_call(path, Some(destination), &msg);
|
||||
if !self.dead.get() {
|
||||
self.send_call(path, destination, NO_REPLY_EXPECTED, &msg);
|
||||
}
|
||||
}
|
||||
|
||||
fn serial(&self) -> u32 {
|
||||
self.next_serial.fetch_add(1)
|
||||
}
|
||||
|
||||
pub fn call<'a, T, F>(&self, destination: &str, path: &str, msg: T, f: F)
|
||||
where
|
||||
T: MethodCall<'a>,
|
||||
F: for<'b> FnOnce(Result<&<T::Reply as Message<'static>>::Generic<'b>, DbusError>)
|
||||
+ 'static,
|
||||
{
|
||||
if self.dead.get() {
|
||||
self.run_toplevel
|
||||
.schedule(move || f(Err(DbusError::Killed)));
|
||||
return;
|
||||
}
|
||||
let serial = self.send_call(path, destination, 0, &msg);
|
||||
self.reply_handlers
|
||||
.set(serial, Box::new(SyncReplyHandler(f, PhantomData)));
|
||||
}
|
||||
|
||||
pub fn call_async<'a, T>(
|
||||
self: &Rc<Self>,
|
||||
destination: &str,
|
||||
path: &str,
|
||||
msg: T,
|
||||
) -> AsyncReply<T::Reply>
|
||||
where
|
||||
T: MethodCall<'a>,
|
||||
{
|
||||
if self.dead.get() {
|
||||
return AsyncReply {
|
||||
socket: self.clone(),
|
||||
serial: self.serial(),
|
||||
slot: Rc::new(AsyncReplySlot {
|
||||
data: Cell::new(Some(Err(DbusError::Killed))),
|
||||
waker: Cell::new(None),
|
||||
}),
|
||||
};
|
||||
}
|
||||
let serial = self.send_call(path, destination, 0, &msg);
|
||||
let slot = Rc::new(AsyncReplySlot {
|
||||
data: Cell::new(None),
|
||||
waker: Cell::new(None),
|
||||
});
|
||||
self.reply_handlers
|
||||
.set(serial, Box::new(AsyncReplyHandler(slot.clone())));
|
||||
AsyncReply {
|
||||
socket: self.clone(),
|
||||
serial,
|
||||
slot,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get<T, F>(&self, destination: &str, path: &str, f: F)
|
||||
where
|
||||
T: Property,
|
||||
F: for<'b> FnOnce(Result<&<T::Type as DbusType<'static>>::Generic<'b>, DbusError>)
|
||||
+ 'static,
|
||||
{
|
||||
let msg: Get<T::Type> = Get {
|
||||
interface_name: T::INTERFACE.into(),
|
||||
property_name: T::PROPERTY.into(),
|
||||
_phantom: PhantomData,
|
||||
};
|
||||
self.call(destination, path, msg, move |res| {
|
||||
f(res.map(|v| &v.value));
|
||||
});
|
||||
}
|
||||
|
||||
pub fn get_async<T: Property>(
|
||||
self: &Rc<Self>,
|
||||
destination: &str,
|
||||
path: &str,
|
||||
) -> AsyncProperty<T> {
|
||||
let msg: Get<T::Type> = Get {
|
||||
interface_name: T::INTERFACE.into(),
|
||||
property_name: T::PROPERTY.into(),
|
||||
_phantom: PhantomData,
|
||||
};
|
||||
AsyncProperty {
|
||||
reply: self.call_async(destination, path, msg),
|
||||
}
|
||||
}
|
||||
|
||||
fn send_call<'a, T: Message<'a>>(
|
||||
&self,
|
||||
path: &str,
|
||||
destination: &str,
|
||||
flags: u8,
|
||||
msg: &T,
|
||||
) -> u32 {
|
||||
let (msg, serial) = self.format_call(path, destination, flags, msg);
|
||||
self.outgoing.push(msg);
|
||||
serial
|
||||
}
|
||||
|
||||
fn format_call<'a, T: Message<'a>>(
|
||||
&self,
|
||||
path: &str,
|
||||
destination: Option<&str>,
|
||||
destination: &str,
|
||||
flags: u8,
|
||||
msg: &T,
|
||||
) -> (DbusMessage, u32) {
|
||||
let num_fds = msg.num_fds();
|
||||
let mut fds = Vec::with_capacity(num_fds as _);
|
||||
let serial = self.next_serial.fetch_add(1);
|
||||
let serial = self.serial();
|
||||
let mut buf = self.bufs.pop().unwrap_or_default();
|
||||
buf.clear();
|
||||
let mut fmt = Formatter::new(&mut fds, &mut buf);
|
||||
self.format_header(
|
||||
&mut fmt,
|
||||
MESSAGE_CALL,
|
||||
MSG_METHOD_CALL,
|
||||
flags,
|
||||
serial,
|
||||
path,
|
||||
T::INTERFACE,
|
||||
|
|
@ -53,11 +164,12 @@ impl DbusSocket {
|
|||
&self,
|
||||
fmt: &mut Formatter,
|
||||
ty: u8,
|
||||
flags: u8,
|
||||
serial: u32,
|
||||
path: &str,
|
||||
interface: &str,
|
||||
member: &str,
|
||||
destination: Option<&str>,
|
||||
destination: &str,
|
||||
signature: &str,
|
||||
fds: u32,
|
||||
) {
|
||||
|
|
@ -66,7 +178,7 @@ impl DbusSocket {
|
|||
#[cfg(not(target_endian = "little"))]
|
||||
b'b'.marshal(fmt);
|
||||
ty.marshal(fmt);
|
||||
0u8.marshal(fmt);
|
||||
flags.marshal(fmt);
|
||||
1u8.marshal(fmt);
|
||||
0u32.marshal(fmt);
|
||||
serial.marshal(fmt);
|
||||
|
|
@ -75,9 +187,7 @@ impl DbusSocket {
|
|||
headers.push((HDR_PATH, Variant::ObjectPath(ObjectPath(path.into()))));
|
||||
headers.push((HDR_INTERFACE, Variant::String(interface.into())));
|
||||
headers.push((HDR_MEMBER, Variant::String(member.into())));
|
||||
if let Some(dst) = destination {
|
||||
headers.push((HDR_DESTINATION, Variant::String(dst.into())));
|
||||
}
|
||||
headers.push((HDR_DESTINATION, Variant::String(destination.into())));
|
||||
if signature.len() > 0 {
|
||||
headers.push((
|
||||
HDR_SIGNATURE,
|
||||
|
|
@ -91,3 +201,72 @@ impl DbusSocket {
|
|||
fmt.pad_to(8);
|
||||
}
|
||||
}
|
||||
|
||||
struct SyncReplyHandler<T, F>(F, PhantomData<T>);
|
||||
|
||||
unsafe impl<T, F> ReplyHandler for SyncReplyHandler<T, F>
|
||||
where
|
||||
T: Message<'static>,
|
||||
F: for<'b> FnOnce(Result<&T::Generic<'b>, DbusError>),
|
||||
{
|
||||
fn signature(&self) -> &str {
|
||||
T::SIGNATURE
|
||||
}
|
||||
|
||||
fn handle_error(self: Box<Self>, _socket: &Rc<DbusSocket>, error: DbusError) {
|
||||
(self.0)(Err(error))
|
||||
}
|
||||
|
||||
fn handle<'a>(
|
||||
self: Box<Self>,
|
||||
socket: &Rc<DbusSocket>,
|
||||
_headers: &Headers,
|
||||
parser: &mut Parser<'a>,
|
||||
buf: Vec<u8>,
|
||||
) -> Result<(), DbusError> {
|
||||
let msg = <T::Generic<'a> as Message>::unmarshal(parser)?;
|
||||
(self.0)(Ok(&msg));
|
||||
socket.bufs.push(buf);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
struct AsyncReplyHandler<T: Message<'static>>(Rc<AsyncReplySlot<T>>);
|
||||
|
||||
unsafe impl<T> ReplyHandler for AsyncReplyHandler<T>
|
||||
where
|
||||
T: Message<'static>,
|
||||
{
|
||||
fn signature(&self) -> &str {
|
||||
T::SIGNATURE
|
||||
}
|
||||
|
||||
fn handle_error(self: Box<Self>, _socket: &Rc<DbusSocket>, error: DbusError) {
|
||||
self.0.data.set(Some(Err(error)));
|
||||
if let Some(waker) = self.0.waker.take() {
|
||||
waker.wake();
|
||||
}
|
||||
}
|
||||
|
||||
fn handle<'a>(
|
||||
self: Box<Self>,
|
||||
socket: &Rc<DbusSocket>,
|
||||
_headers: &Headers,
|
||||
parser: &mut Parser<'a>,
|
||||
buf: Vec<u8>,
|
||||
) -> Result<(), DbusError> {
|
||||
let msg = <T::Generic<'static> as Message<'static>>::unmarshal(unsafe {
|
||||
mem::transmute::<&mut Parser<'a>, &mut Parser<'static>>(parser)
|
||||
})?;
|
||||
let reply = Reply {
|
||||
socket: socket.clone(),
|
||||
buf,
|
||||
t: msg,
|
||||
};
|
||||
self.0.data.set(Some(Ok(reply)));
|
||||
if let Some(waker) = self.0.waker.take() {
|
||||
waker.wake();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,13 +9,37 @@ use std::ops::Deref;
|
|||
use std::rc::Rc;
|
||||
use uapi::{OwnedFd, Packed, Pod};
|
||||
|
||||
macro_rules! consume_signature_body {
|
||||
($s:expr, $ty:expr) => {{
|
||||
if $s.is_empty() {
|
||||
return Err(DbusError::EmptySignature);
|
||||
}
|
||||
if $s[0] != $ty {
|
||||
return Err(DbusError::InvalidSignatureType);
|
||||
}
|
||||
*$s = &(*$s)[1..];
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! signature {
|
||||
($ty:expr) => {
|
||||
fn consume_signature(s: &mut &[u8]) -> Result<(), DbusError> {
|
||||
consume_signature_body!(s, $ty);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_signature(w: &mut Vec<u8>) {
|
||||
w.push(TY_BYTE);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
unsafe impl<'a> DbusType<'a> for u8 {
|
||||
const ALIGNMENT: usize = 1;
|
||||
const IS_POD: bool = true;
|
||||
type Generic<'b> = Self;
|
||||
|
||||
fn write_signature(w: &mut Vec<u8>) {
|
||||
w.push(TY_BYTE);
|
||||
}
|
||||
signature!(TY_BYTE);
|
||||
|
||||
fn marshal(&self, fmt: &mut Formatter) {
|
||||
fmt.write_packed(self);
|
||||
|
|
@ -38,10 +62,9 @@ unsafe impl Packed for Bool {}
|
|||
unsafe impl<'a> DbusType<'a> for Bool {
|
||||
const ALIGNMENT: usize = 4;
|
||||
const IS_POD: bool = true;
|
||||
type Generic<'b> = Self;
|
||||
|
||||
fn write_signature(w: &mut Vec<u8>) {
|
||||
w.push(TY_BOOLEAN);
|
||||
}
|
||||
signature!(TY_BOOLEAN);
|
||||
|
||||
fn marshal(&self, fmt: &mut Formatter) {
|
||||
fmt.write_packed(self);
|
||||
|
|
@ -55,10 +78,9 @@ unsafe impl<'a> DbusType<'a> for Bool {
|
|||
unsafe impl<'a> DbusType<'a> for i16 {
|
||||
const ALIGNMENT: usize = 2;
|
||||
const IS_POD: bool = true;
|
||||
type Generic<'b> = Self;
|
||||
|
||||
fn write_signature(w: &mut Vec<u8>) {
|
||||
w.push(TY_INT16);
|
||||
}
|
||||
signature!(TY_INT16);
|
||||
|
||||
fn marshal(&self, fmt: &mut Formatter) {
|
||||
fmt.write_packed(self);
|
||||
|
|
@ -72,10 +94,9 @@ unsafe impl<'a> DbusType<'a> for i16 {
|
|||
unsafe impl<'a> DbusType<'a> for u16 {
|
||||
const ALIGNMENT: usize = 2;
|
||||
const IS_POD: bool = true;
|
||||
type Generic<'b> = Self;
|
||||
|
||||
fn write_signature(w: &mut Vec<u8>) {
|
||||
w.push(TY_UINT16)
|
||||
}
|
||||
signature!(TY_UINT16);
|
||||
|
||||
fn marshal(&self, fmt: &mut Formatter) {
|
||||
fmt.write_packed(self);
|
||||
|
|
@ -89,10 +110,9 @@ unsafe impl<'a> DbusType<'a> for u16 {
|
|||
unsafe impl<'a> DbusType<'a> for i32 {
|
||||
const ALIGNMENT: usize = 4;
|
||||
const IS_POD: bool = true;
|
||||
type Generic<'b> = Self;
|
||||
|
||||
fn write_signature(w: &mut Vec<u8>) {
|
||||
w.push(TY_INT32)
|
||||
}
|
||||
signature!(TY_INT32);
|
||||
|
||||
fn marshal(&self, fmt: &mut Formatter) {
|
||||
fmt.write_packed(self);
|
||||
|
|
@ -106,10 +126,9 @@ unsafe impl<'a> DbusType<'a> for i32 {
|
|||
unsafe impl<'a> DbusType<'a> for u32 {
|
||||
const ALIGNMENT: usize = 4;
|
||||
const IS_POD: bool = true;
|
||||
type Generic<'b> = Self;
|
||||
|
||||
fn write_signature(w: &mut Vec<u8>) {
|
||||
w.push(TY_UINT32)
|
||||
}
|
||||
signature!(TY_UINT32);
|
||||
|
||||
fn marshal(&self, fmt: &mut Formatter) {
|
||||
fmt.write_packed(self);
|
||||
|
|
@ -123,10 +142,9 @@ unsafe impl<'a> DbusType<'a> for u32 {
|
|||
unsafe impl<'a> DbusType<'a> for AlignedI64 {
|
||||
const ALIGNMENT: usize = 8;
|
||||
const IS_POD: bool = true;
|
||||
type Generic<'b> = Self;
|
||||
|
||||
fn write_signature(w: &mut Vec<u8>) {
|
||||
w.push(TY_INT64)
|
||||
}
|
||||
signature!(TY_INT64);
|
||||
|
||||
fn marshal(&self, fmt: &mut Formatter) {
|
||||
fmt.write_packed(self);
|
||||
|
|
@ -140,10 +158,9 @@ unsafe impl<'a> DbusType<'a> for AlignedI64 {
|
|||
unsafe impl<'a> DbusType<'a> for AlignedU64 {
|
||||
const ALIGNMENT: usize = 8;
|
||||
const IS_POD: bool = true;
|
||||
type Generic<'b> = Self;
|
||||
|
||||
fn write_signature(w: &mut Vec<u8>) {
|
||||
w.push(TY_UINT64)
|
||||
}
|
||||
signature!(TY_UINT64);
|
||||
|
||||
fn marshal(&self, fmt: &mut Formatter) {
|
||||
fmt.write_packed(self);
|
||||
|
|
@ -157,10 +174,9 @@ unsafe impl<'a> DbusType<'a> for AlignedU64 {
|
|||
unsafe impl<'a> DbusType<'a> for AlignedF64 {
|
||||
const ALIGNMENT: usize = 8;
|
||||
const IS_POD: bool = true;
|
||||
type Generic<'b> = Self;
|
||||
|
||||
fn write_signature(w: &mut Vec<u8>) {
|
||||
w.push(TY_DOUBLE)
|
||||
}
|
||||
signature!(TY_DOUBLE);
|
||||
|
||||
fn marshal(&self, fmt: &mut Formatter) {
|
||||
fmt.write_packed(self);
|
||||
|
|
@ -174,10 +190,9 @@ unsafe impl<'a> DbusType<'a> for AlignedF64 {
|
|||
unsafe impl<'a> DbusType<'a> for Cow<'a, str> {
|
||||
const ALIGNMENT: usize = 4;
|
||||
const IS_POD: bool = false;
|
||||
type Generic<'b> = Cow<'b, str>;
|
||||
|
||||
fn write_signature(w: &mut Vec<u8>) {
|
||||
w.push(TY_STRING)
|
||||
}
|
||||
signature!(TY_STRING);
|
||||
|
||||
fn marshal(&self, fmt: &mut Formatter) {
|
||||
fmt.write_str(self);
|
||||
|
|
@ -191,13 +206,20 @@ unsafe impl<'a> DbusType<'a> for Cow<'a, str> {
|
|||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct Signature<'a>(pub Cow<'a, str>);
|
||||
|
||||
impl<'a> Deref for Signature<'a> {
|
||||
type Target = str;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'a> DbusType<'a> for Signature<'a> {
|
||||
const ALIGNMENT: usize = 1;
|
||||
const IS_POD: bool = false;
|
||||
type Generic<'b> = Signature<'b>;
|
||||
|
||||
fn write_signature(w: &mut Vec<u8>) {
|
||||
w.push(TY_SIGNATURE)
|
||||
}
|
||||
signature!(TY_SIGNATURE);
|
||||
|
||||
fn marshal(&self, fmt: &mut Formatter) {
|
||||
fmt.write_signature(self.0.as_bytes());
|
||||
|
|
@ -211,13 +233,20 @@ unsafe impl<'a> DbusType<'a> for Signature<'a> {
|
|||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct ObjectPath<'a>(pub Cow<'a, str>);
|
||||
|
||||
impl<'a> Deref for ObjectPath<'a> {
|
||||
type Target = str;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'a> DbusType<'a> for ObjectPath<'a> {
|
||||
const ALIGNMENT: usize = 4;
|
||||
const IS_POD: bool = false;
|
||||
type Generic<'b> = ObjectPath<'b>;
|
||||
|
||||
fn write_signature(w: &mut Vec<u8>) {
|
||||
w.push(TY_OBJECT_PATH)
|
||||
}
|
||||
signature!(TY_OBJECT_PATH);
|
||||
|
||||
fn marshal(&self, fmt: &mut Formatter) {
|
||||
fmt.write_str(&self.0);
|
||||
|
|
@ -228,9 +257,35 @@ unsafe impl<'a> DbusType<'a> for ObjectPath<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl<'a> DbusType<'a> for Rc<OwnedFd> {
|
||||
const ALIGNMENT: usize = 4;
|
||||
const IS_POD: bool = false;
|
||||
type Generic<'b> = Self;
|
||||
|
||||
signature!(TY_UNIX_FD);
|
||||
|
||||
fn marshal(&self, fmt: &mut Formatter) {
|
||||
fmt.write_fd(self)
|
||||
}
|
||||
|
||||
fn unmarshal(parser: &mut Parser<'a>) -> Result<Self, DbusError> {
|
||||
parser.read_fd()
|
||||
}
|
||||
|
||||
fn num_fds(&self) -> u32 {
|
||||
1
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'a, T: DbusType<'a>> DbusType<'a> for Cow<'a, [T]> {
|
||||
const ALIGNMENT: usize = 4;
|
||||
const IS_POD: bool = false;
|
||||
type Generic<'b> = Cow<'b, [T::Generic<'b>]>;
|
||||
|
||||
fn consume_signature(s: &mut &[u8]) -> Result<(), DbusError> {
|
||||
consume_signature_body!(s, TY_ARRAY);
|
||||
T::consume_signature(s)
|
||||
}
|
||||
|
||||
fn write_signature(w: &mut Vec<u8>) {
|
||||
w.push(TY_ARRAY);
|
||||
|
|
@ -263,6 +318,15 @@ pub struct DictEntry<K, V> {
|
|||
unsafe impl<'a, K: DbusType<'a>, V: DbusType<'a>> DbusType<'a> for DictEntry<K, V> {
|
||||
const ALIGNMENT: usize = 8;
|
||||
const IS_POD: bool = false;
|
||||
type Generic<'b> = DictEntry<K::Generic<'b>, V::Generic<'b>>;
|
||||
|
||||
fn consume_signature(s: &mut &[u8]) -> Result<(), DbusError> {
|
||||
consume_signature_body!(s, b'{');
|
||||
K::consume_signature(s)?;
|
||||
V::consume_signature(s)?;
|
||||
consume_signature_body!(s, b'}');
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_signature(w: &mut Vec<u8>) {
|
||||
w.push(b'{');
|
||||
|
|
@ -292,6 +356,16 @@ macro_rules! tuple {
|
|||
unsafe impl<'a, $($p: DbusType<'a>),*> DbusType<'a> for ($($p,)*) {
|
||||
const ALIGNMENT: usize = 8;
|
||||
const IS_POD: bool = false;
|
||||
type Generic<'b> = ($($p::Generic<'b>,)*);
|
||||
|
||||
fn consume_signature(s: &mut &[u8]) -> Result<(), DbusError> {
|
||||
consume_signature_body!(s, b'(');
|
||||
$(
|
||||
$p::consume_signature(s)?;
|
||||
)*
|
||||
consume_signature_body!(s, b')');
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_signature(w: &mut Vec<u8>) {
|
||||
w.push(b'(');
|
||||
|
|
@ -429,10 +503,9 @@ impl<'a> Variant<'a> {
|
|||
unsafe impl<'a> DbusType<'a> for Variant<'a> {
|
||||
const ALIGNMENT: usize = 1;
|
||||
const IS_POD: bool = false;
|
||||
type Generic<'b> = Variant<'b>;
|
||||
|
||||
fn write_signature(w: &mut Vec<u8>) {
|
||||
w.push(TY_VARIANT);
|
||||
}
|
||||
signature!(TY_VARIANT);
|
||||
|
||||
fn marshal(&self, fmt: &mut Formatter) {
|
||||
fmt.write_variant(self);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue