1
0
Fork 0
forked from wry/wry

refactor: split cargo workspace

This commit is contained in:
kossLAN 2026-06-05 11:56:21 -04:00
parent 5db14936e7
commit 1c21bd1259
695 changed files with 32023 additions and 44964 deletions

View file

@ -1,145 +1,39 @@
pub use types::*;
pub use jay_dbus_core::*;
use {
crate::{
async_engine::{AsyncEngine, SpawnedFuture},
dbus::{
property::{Get, GetReply},
types::{ObjectPath, Signature, Variant},
},
io_uring::{IoUring, IoUringError},
io_uring::IoUring,
utils::{
buf::DynamicBuf,
bufio::{BufIo, BufIoError},
bufio::BufIo,
clonecell::CloneCell,
copyhashmap::CopyHashMap,
numcell::NumCell,
oserror::OsError,
run_toplevel::RunToplevel,
stack::Stack,
vecstorage::VecStorage,
xrd::{XRD, xrd},
},
wire_dbus::{
org,
org::freedesktop::dbus::properties::{GetAll, GetAllReply, PropertiesChanged},
},
},
ahash::AHashMap,
std::{
borrow::{Borrow, Cow},
borrow::Cow,
cell::{Cell, RefCell},
fmt::{Debug, Display},
fmt::Debug,
future::Future,
marker::PhantomData,
mem,
ops::Deref,
pin::Pin,
rc::Rc,
task::{Context, Poll, Waker},
},
thiserror::Error,
uapi::OwnedFd,
};
mod auth;
mod dynamic_type;
mod formatter;
mod holder;
mod incoming;
mod outgoing;
mod parser;
mod property;
mod socket;
mod types;
#[derive(Debug)]
pub struct CallError {
pub name: String,
pub msg: Option<String>,
}
impl Display for CallError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some(msg) = &self.msg {
write!(f, "{}: {}", self.name, msg)
} else {
write!(f, "{}", self.name)
}
}
}
#[derive(Debug, Error)]
pub enum DbusError {
#[error("Encountered an unknown type in a signature")]
UnknownType,
#[error("Function call reply does not contain a reply serial")]
NoReplySerial,
#[error("Signal message contains no interface or member or path")]
MissingSignalHeaders,
#[error("Method call message contains no interface or member or path")]
MissingMethodCallHeaders,
#[error("Error has no error name")]
NoErrorName,
#[error("The socket was killed")]
Killed,
#[error("{0}")]
CallError(CallError),
#[error("FD index is out of bounds")]
OobFds,
#[error("Variant has an invalid type")]
InvalidVariantType,
#[error("Could not create a socket")]
Socket(#[source] OsError),
#[error("Could not connect")]
Connect(#[source] IoUringError),
#[error("Could not write to the dbus socket")]
WriteError(#[source] IoUringError),
#[error("Could not read from the dbus socket")]
ReadError(#[source] IoUringError),
#[error("timeout")]
IoUringError(#[source] Box<IoUringError>),
#[error("Server did not send auth challenge")]
NoChallenge,
#[error("Server did not accept our authentication")]
Auth,
#[error("Array length is not a multiple of the element size")]
PodArrayLength,
#[error("Peer did not send enough fds")]
TooFewFds,
#[error("Variant signature is not a single type")]
TrailingVariantSignature,
#[error("Dict signature does not contain a terminating '}}'")]
UnterminatedDict,
#[error("Struct signature does not contain a terminating '}}'")]
UnterminatedStruct,
#[error("Dict signature contains trailing types")]
DictTrailing,
#[error("String does not contain valid UTF-8")]
InvalidUtf8,
#[error("Unexpected end of message")]
UnexpectedEof,
#[error("Boolean value was not 0 or 1")]
InvalidBoolValue,
#[error("Signature is empty")]
EmptySignature,
#[error("The session bus address is not set")]
SessionBusAddressNotSet,
#[error("Server does not support FD passing")]
UnixFd,
#[error("Server message has a different endianess than ourselves")]
InvalidEndianess,
#[error("Server speaks an unexpected protocol version")]
InvalidProtocol,
#[error("Signature contains an invalid type")]
InvalidSignatureType,
#[error("The signal already has a handler")]
AlreadyHandled,
#[error(transparent)]
BufIoError(#[from] BufIoError),
#[error(transparent)]
DbusError(Rc<DbusError>),
}
efrom!(DbusError, IoUringError);
const DBUS_SESSION_BUS_ADDRESS: &str = "DBUS_SESSION_BUS_ADDRESS";
@ -280,42 +174,8 @@ pub struct DbusSocket {
headers: RefCell<VecStorage<(u8, Variant<'static>)>>,
run_toplevel: Rc<RunToplevel>,
signal_handlers: RefCell<AHashMap<(&'static str, &'static str), InterfaceSignalHandlers>>,
objects: CopyHashMap<Cow<'static, str>, Rc<DbusObjectData>>,
}
#[derive(Hash, Eq, PartialEq)]
struct MemberHandlerOwnedKey {
key: MemberHandlerKey<'static>,
}
#[derive(Hash, Eq, PartialEq)]
struct MemberHandlerKey<'a> {
interface: &'a str,
member: &'a str,
}
impl<'a> Borrow<MemberHandlerKey<'a>> for MemberHandlerOwnedKey {
fn borrow(&self) -> &MemberHandlerKey<'a> {
&self.key
}
}
const TY_BYTE: u8 = b'y';
const TY_BOOLEAN: u8 = b'b';
const TY_INT16: u8 = b'n';
const TY_UINT16: u8 = b'q';
const TY_INT32: u8 = b'i';
const TY_UINT32: u8 = b'u';
const TY_INT64: u8 = b'x';
const TY_UINT64: u8 = b't';
const TY_DOUBLE: u8 = b'd';
const TY_STRING: u8 = b's';
const TY_OBJECT_PATH: u8 = b'o';
const TY_SIGNATURE: u8 = b'g';
const TY_ARRAY: u8 = b'a';
const TY_VARIANT: u8 = b'v';
const TY_UNIX_FD: u8 = b'h';
const HDR_PATH: u8 = 1;
const HDR_INTERFACE: u8 = 2;
const HDR_MEMBER: u8 = 3;
@ -337,20 +197,6 @@ const NO_AUTO_START: u8 = 0x2;
#[expect(dead_code)]
const ALLOW_INTERACTIVE_AUTHORIZATION: u8 = 0x4;
#[expect(dead_code)]
pub const DBUS_NAME_FLAG_ALLOW_REPLACEMENT: u32 = 0x1;
#[expect(dead_code)]
pub const DBUS_NAME_FLAG_REPLACE_EXISTING: u32 = 0x2;
pub const DBUS_NAME_FLAG_DO_NOT_QUEUE: u32 = 0x4;
pub const DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER: u32 = 1;
#[expect(dead_code)]
pub const DBUS_REQUEST_NAME_REPLY_IN_QUEUE: u32 = 2;
#[expect(dead_code)]
pub const DBUS_REQUEST_NAME_REPLY_EXISTS: u32 = 3;
#[expect(dead_code)]
pub const DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER: u32 = 4;
pub const BUS_DEST: &str = "org.freedesktop.DBus";
pub const BUS_PATH: &str = "/org/freedesktop/DBus";
@ -397,102 +243,6 @@ impl Drop for DbusHolder {
}
}
#[derive(Clone, Debug)]
pub enum DynamicType {
U8,
Bool,
I16,
U16,
I32,
U32,
I64,
U64,
F64,
String,
ObjectPath,
Signature,
Variant,
Fd,
Array(Box<DynamicType>),
DictEntry(Box<DynamicType>, Box<DynamicType>),
Struct(Vec<DynamicType>),
}
pub struct Parser<'a> {
buf: &'a [u8],
pos: usize,
fds: &'a [Rc<OwnedFd>],
}
pub struct Formatter<'a> {
fds: &'a mut Vec<Rc<OwnedFd>>,
buf: &'a mut DynamicBuf,
}
pub unsafe trait Message<'a>: Sized + 'a {
const SIGNATURE: &'static str;
const INTERFACE: &'static str;
const MEMBER: &'static str;
type Generic<'b>: Message<'b>;
fn marshal(&self, w: &mut Formatter);
fn unmarshal(p: &mut Parser<'a>) -> Result<Self, DbusError>;
fn num_fds(&self) -> u32;
}
pub struct ErrorMessage<'a> {
pub msg: Cow<'a, str>,
}
unsafe impl<'a> Message<'a> for ErrorMessage<'a> {
const SIGNATURE: &'static str = "s";
const INTERFACE: &'static str = "";
const MEMBER: &'static str = "";
type Generic<'b> = ErrorMessage<'b>;
fn marshal(&self, w: &mut Formatter) {
self.msg.marshal(w)
}
fn unmarshal(p: &mut Parser<'a>) -> Result<Self, DbusError> {
Ok(Self {
msg: p.unmarshal()?,
})
}
fn num_fds(&self) -> u32 {
0
}
}
pub trait Property {
const INTERFACE: &'static str;
const PROPERTY: &'static str;
type Type: DbusType<'static>;
}
pub trait Signal<'a>: Message<'a> {}
pub trait MethodCall<'a>: Message<'a> {
type Reply: Message<'static>;
}
pub unsafe trait DbusType<'a>: Clone + 'a {
const ALIGNMENT: usize;
const IS_POD: bool;
type Generic<'b>: DbusType<'b> + 'b;
fn consume_signature(s: &mut &[u8]) -> Result<(), DbusError>;
#[allow(clippy::allow_attributes, dead_code)]
fn write_signature(w: &mut Vec<u8>);
fn marshal(&self, fmt: &mut Formatter);
fn unmarshal(parser: &mut Parser<'a>) -> Result<Self, DbusError>;
fn num_fds(&self) -> u32 {
0
}
}
pub struct Reply<T: Message<'static>> {
socket: Rc<DbusSocket>,
buf: Vec<u8>,
@ -649,278 +399,3 @@ struct InterfaceSignalHandlers {
unconditional: Option<Rc<dyn SignalHandlerApi>>,
conditional: AHashMap<String, Rc<dyn SignalHandlerApi>>,
}
struct DbusObjectData {
path: Cow<'static, str>,
methods: CopyHashMap<MemberHandlerOwnedKey, Rc<dyn MethodHandlerApi>>,
properties: CopyHashMap<MemberHandlerOwnedKey, Rc<dyn PropertyHandlerApi>>,
}
pub struct DbusObject {
socket: Rc<DbusSocket>,
data: Rc<DbusObjectData>,
}
impl Drop for DbusObject {
fn drop(&mut self) {
self.socket.objects.remove(&self.data.path);
}
}
impl DbusObject {
pub fn add_method<T, F>(&self, handler: F)
where
T: MethodCall<'static>,
F: for<'a> Fn(T::Generic<'a>, PendingReply<T::Reply>) + 'static,
{
let rhd = Rc::new(MethodHandlerData {
handler,
_phantom: Default::default(),
});
let key = MemberHandlerOwnedKey {
key: MemberHandlerKey {
interface: T::INTERFACE,
member: T::MEMBER,
},
};
self.data.methods.set(key, rhd);
}
pub fn set_property<T>(&self, value: Variant<'static>)
where
T: Property + 'static,
{
self.emit_signal(&PropertiesChanged {
interface_name: T::INTERFACE.into(),
changed_properties: Cow::Borrowed(&[DictEntry {
key: T::PROPERTY.into(),
value: value.borrow(),
}]),
invalidated_properties: Default::default(),
});
let phd = Rc::new(PropertyHandlerData::<T> {
data: value,
_phantom: Default::default(),
});
let key = MemberHandlerOwnedKey {
key: MemberHandlerKey {
interface: T::INTERFACE,
member: T::PROPERTY,
},
};
self.data.properties.set(key, phd);
}
pub fn emit_signal<'a, T: Signal<'a>>(&self, signal: &T) {
self.socket.emit_signal(&self.data.path, signal);
}
pub fn path(&self) -> &str {
&self.data.path
}
}
trait PropertyHandlerApi {
fn interface(&self) -> &'static str;
fn member(&self) -> &'static str;
fn value<'a>(&'a self) -> Variant<'a>;
}
struct PropertyHandlerData<T> {
data: Variant<'static>,
_phantom: PhantomData<T>,
}
impl<T> PropertyHandlerApi for PropertyHandlerData<T>
where
T: Property,
{
fn interface(&self) -> &'static str {
T::INTERFACE
}
fn member(&self) -> &'static str {
T::PROPERTY
}
fn value<'a>(&'a self) -> Variant<'a> {
self.data.borrow()
}
}
pub struct PendingReply<T> {
reply_expected: bool,
socket: Rc<DbusSocket>,
destination: String,
serial: u32,
_phantom: PhantomData<T>,
}
impl<T> PendingReply<T> {
#[expect(dead_code)]
pub fn reply_expected(&self) -> bool {
self.reply_expected
}
pub fn err(&self, msg: &str) {
if self.reply_expected {
self.socket.send_error(&self.destination, self.serial, msg);
}
}
}
impl<T> PendingReply<T>
where
T: Message<'static>,
{
pub fn ok<'a>(&self, msg: &T::Generic<'a>) {
if self.reply_expected {
self.socket.send_reply(&self.destination, self.serial, msg);
}
}
#[expect(dead_code)]
pub fn complete<'a>(&self, res: Result<&T::Generic<'a>, &str>) {
match res {
Ok(m) => self.ok(m),
Err(e) => self.err(e),
}
}
}
trait MethodHandlerApi {
fn signature(&self) -> &'static str;
fn handle(
&self,
object: &DbusObjectData,
socket: &Rc<DbusSocket>,
dest: &str,
serial: u32,
reply_expected: bool,
parser: &mut Parser,
) -> Result<(), DbusError>;
}
struct MethodHandlerData<T, F> {
handler: F,
_phantom: PhantomData<T>,
}
impl<T, F> MethodHandlerApi for MethodHandlerData<T, F>
where
T: MethodCall<'static>,
F: for<'a> Fn(T::Generic<'a>, PendingReply<T::Reply>) + 'static,
{
fn signature(&self) -> &'static str {
T::SIGNATURE
}
fn handle<'a>(
&self,
_object: &DbusObjectData,
socket: &Rc<DbusSocket>,
dest: &str,
serial: u32,
reply_expected: bool,
parser: &mut Parser<'a>,
) -> Result<(), DbusError> {
let msg = T::Generic::<'a>::unmarshal(parser)?;
let pr = PendingReply {
reply_expected,
socket: socket.clone(),
destination: dest.to_string(),
serial,
_phantom: Default::default(),
};
(self.handler)(msg, pr);
Ok(())
}
}
struct PropertyGetHandlerProxy;
impl MethodHandlerApi for PropertyGetHandlerProxy {
fn signature(&self) -> &'static str {
Get::<u32>::SIGNATURE
}
fn handle<'a>(
&self,
object: &DbusObjectData,
socket: &Rc<DbusSocket>,
dest: &str,
serial: u32,
reply_expected: bool,
parser: &mut Parser<'a>,
) -> Result<(), DbusError> {
if !reply_expected {
return Ok(());
}
let msg = org::freedesktop::dbus::properties::Get::unmarshal(parser)?;
let key = MemberHandlerKey {
interface: msg.interface_name.deref(),
member: msg.property_name.deref(),
};
match object.properties.get(&key) {
Some(h) => socket.send_reply(
dest,
serial,
&org::freedesktop::dbus::properties::GetReply { value: h.value() },
),
_ => socket.send_error(dest, serial, "Property does not exist"),
};
Ok(())
}
}
struct PropertyGetAllHandlerProxy;
impl MethodHandlerApi for PropertyGetAllHandlerProxy {
fn signature(&self) -> &'static str {
GetAll::SIGNATURE
}
fn handle<'a>(
&self,
object: &DbusObjectData,
socket: &Rc<DbusSocket>,
dest: &str,
serial: u32,
reply_expected: bool,
parser: &mut Parser<'a>,
) -> Result<(), DbusError> {
if !reply_expected {
return Ok(());
}
let msg = GetAll::unmarshal(parser)?;
let all_props = object.properties.lock();
let mut props = vec![];
for property in all_props.values() {
if property.interface() == msg.interface_name {
props.push(DictEntry {
key: property.member().into(),
value: property.value(),
});
}
}
socket.send_reply(
dest,
serial,
&GetAllReply {
props: props.into(),
},
);
Ok(())
}
}
pub mod prelude {
pub use {
super::{
DbusError, DbusType, Formatter, Message, MethodCall, Parser, Property, Signal,
types::{Bool, DictEntry, ObjectPath, Variant},
},
std::{borrow::Cow, rc::Rc},
uapi::OwnedFd,
};
}