1
0
Fork 0
forked from wry/wry

autocommit 2022-02-28 00:14:11 CET

This commit is contained in:
Julian Orth 2022-02-28 00:14:11 +01:00
parent db88f2db42
commit 0e9afcbfa5
22 changed files with 1013 additions and 239 deletions

View file

@ -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())),
));

View file

@ -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)?);
}

View file

@ -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)

View file

@ -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;

View file

@ -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[..],

View file

@ -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
View 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()
}
}

View file

@ -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(())
}
}

View file

@ -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);