1
0
Fork 0
forked from wry/wry

xcon: move wire core into workspace crate

This commit is contained in:
kossLAN 2026-05-29 11:02:40 -04:00
parent 61ec13def0
commit d8380b3dce
No known key found for this signature in database
11 changed files with 138 additions and 99 deletions

View file

@ -1,21 +1,18 @@
pub use crate::xcon::{
formatter::Formatter,
parser::Parser,
wire_type::{Message, Request, XEvent},
pub use jay_xcon::{
consts, xauthority, Formatter, Message, Parser, Request, SendEvent, XEvent, XconError,
};
use {
crate::{
async_engine::{Phase, SpawnedFuture},
compositor::DISPLAY,
io_uring::IoUringError,
state::State,
utils::{
buf::DynamicBuf,
bufio::{BufIo, BufIoError, BufIoMessage},
bufio::{BufIo, BufIoMessage},
clonecell::CloneCell,
errorfmt::ErrorFmt,
numcell::NumCell,
oserror::{OsError, OsErrorExt2},
oserror::OsErrorExt2,
queue::AsyncQueue,
stack::Stack,
vec_ext::VecExt,
@ -29,7 +26,6 @@ use {
consts::{IMAGE_FORMAT_Z_PIXMAP, RENDER_PICT_TYPE_DIRECT},
incoming::handle_incoming,
outgoing::handle_outgoing,
wire_type::SendEvent,
xauthority::{LOCAL, MIT_MAGIC_COOKIE, XAuthority},
},
},
@ -49,93 +45,11 @@ use {
rc::{Rc, Weak},
task::{Context, Poll, Waker},
},
thiserror::Error,
uapi::{OwnedFd, c},
};
pub mod consts;
mod formatter;
mod incoming;
mod outgoing;
mod parser;
mod wire_type;
mod xauthority;
#[derive(Debug, Error)]
pub enum XconError {
#[error("Unexpected EOF")]
UnexpectedEof,
#[error("Buffer slice is not properly aligned")]
UnalignedSlice,
#[error("Neither XAUTHORITY nor HOME is set")]
HomeNotSet,
#[error("Could not read Xauthority file")]
ReadXAuthority(#[source] std::io::Error),
#[error("Display field in Xauthority could not be parsed")]
InvalidAuthorityDisplay,
#[error("The DISPLAY is not set")]
DisplayNotSet,
#[error("DISPLAY contains an invalid value")]
InvalidDisplayFormat,
#[error("Could not create a unix socket")]
CreateSocket(#[source] OsError),
#[error("Could not connect to Xserver")]
ConnectSocket(#[source] IoUringError),
#[error("Could not retrive the hostname")]
Hostname(#[source] OsError),
#[error("Server did not send enough fds")]
NotEnoughFds,
#[error("Server rejected our connection attempt: {0}")]
Connect(BString),
#[error("Server requires additional authentication: {0}")]
Authenticate(BString),
#[error(transparent)]
BufIoError(#[from] BufIoError),
#[error("The server did not send a reply to a request")]
MissingReply,
#[error("The server did not send fds with a reply")]
MissingFds,
#[error("The server sent a message with an excessive size")]
ExcessiveMessageSize,
#[error(transparent)]
XconError(Rc<XconError>),
#[error("The server does not support the `{0}` extension")]
ExtensionUnavailable(&'static str),
#[error("The server returned error {0}")]
CoreError(u8),
#[error("The extension `{}` returned error {}", .0.name(), .1)]
ExtensionError(Extension, u8),
#[error("The connection to the server has already been closed")]
Dead,
#[error("Could not query the `{0}` extension")]
QueryExtension(BString, #[source] Box<XconError>),
#[error("All available xids have been used")]
XidExhausted,
#[error("Enum contains an unknown variant")]
UnknownEnumVariant,
#[error("Could not query the render pict formats")]
QueryPictFormats(#[source] Box<XconError>),
#[error("The server does not support the picture format for cursors")]
CursorFormatNotSupported,
#[error("Could not create a pixmap")]
CreatePixmap(#[source] Box<XconError>),
#[error("Could not create a graphics context")]
CreateGc(#[source] Box<XconError>),
#[error("Could not upload an image")]
PutImage(#[source] Box<XconError>),
#[error("Could not create a picture")]
CreatePicture(#[source] Box<XconError>),
#[error("Could not create a cursor")]
CreateCursor(#[source] Box<XconError>),
#[error("Property has an invalid type")]
InvalidPropertyType,
#[error("Property has an invalid format. Expected: {0}; Actual: {1}")]
InvalidPropertyFormat(u8, u8),
#[error("Length of the property data is not a multiple of its format")]
IrregularPropertyLength,
#[error("The property is not set")]
PropertyUnavailable,
}
#[derive(Debug)]
struct ExtensionIdRange {

View file

@ -1,275 +0,0 @@
#![allow(dead_code)]
pub const XGE_EVENT: u8 = 35;
pub const INPUT_DEVICE_ALL: u16 = 0;
pub const INPUT_DEVICE_ALL_MASTER: u16 = 1;
pub const WINDOW_CLASS_INPUT_OUTPUT: u16 = 1;
pub const ATOM_NONE: u32 = 0;
pub const ATOM_ANY: u32 = 0;
pub const ATOM_PRIMARY: u32 = 1;
pub const ATOM_SECONDARY: u32 = 2;
pub const ATOM_ARC: u32 = 3;
pub const ATOM_ATOM: u32 = 4;
pub const ATOM_BITMAP: u32 = 5;
pub const ATOM_CARDINAL: u32 = 6;
pub const ATOM_COLORMAP: u32 = 7;
pub const ATOM_CURSOR: u32 = 8;
pub const ATOM_CUT_BUFFER0: u32 = 9;
pub const ATOM_CUT_BUFFER1: u32 = 10;
pub const ATOM_CUT_BUFFER2: u32 = 11;
pub const ATOM_CUT_BUFFER3: u32 = 12;
pub const ATOM_CUT_BUFFER4: u32 = 13;
pub const ATOM_CUT_BUFFER5: u32 = 14;
pub const ATOM_CUT_BUFFER6: u32 = 15;
pub const ATOM_CUT_BUFFER7: u32 = 16;
pub const ATOM_DRAWABLE: u32 = 17;
pub const ATOM_FONT: u32 = 18;
pub const ATOM_INTEGER: u32 = 19;
pub const ATOM_PIXMAP: u32 = 20;
pub const ATOM_POINT: u32 = 21;
pub const ATOM_RECTANGLE: u32 = 22;
pub const ATOM_RESOURCE_MANAGER: u32 = 23;
pub const ATOM_RGB_COLOR_MAP: u32 = 24;
pub const ATOM_RGB_BEST_MAP: u32 = 25;
pub const ATOM_RGB_BLUE_MAP: u32 = 26;
pub const ATOM_RGB_DEFAULT_MAP: u32 = 27;
pub const ATOM_RGB_GRAY_MAP: u32 = 28;
pub const ATOM_RGB_GREEN_MAP: u32 = 29;
pub const ATOM_RGB_RED_MAP: u32 = 30;
pub const ATOM_STRING: u32 = 31;
pub const ATOM_VISUALID: u32 = 32;
pub const ATOM_WINDOW: u32 = 33;
pub const ATOM_WM_COMMAND: u32 = 34;
pub const ATOM_WM_HINTS: u32 = 35;
pub const ATOM_WM_CLIENT_MACHINE: u32 = 36;
pub const ATOM_WM_ICON_NAME: u32 = 37;
pub const ATOM_WM_ICON_SIZE: u32 = 38;
pub const ATOM_WM_NAME: u32 = 39;
pub const ATOM_WM_NORMAL_HINTS: u32 = 40;
pub const ATOM_WM_SIZE_HINTS: u32 = 41;
pub const ATOM_WM_ZOOM_HINTS: u32 = 42;
pub const ATOM_MIN_SPACE: u32 = 43;
pub const ATOM_NORM_SPACE: u32 = 44;
pub const ATOM_MAX_SPACE: u32 = 45;
pub const ATOM_END_SPACE: u32 = 46;
pub const ATOM_SUPERSCRIPT_X: u32 = 47;
pub const ATOM_SUPERSCRIPT_Y: u32 = 48;
pub const ATOM_SUBSCRIPT_X: u32 = 49;
pub const ATOM_SUBSCRIPT_Y: u32 = 50;
pub const ATOM_UNDERLINE_POSITION: u32 = 51;
pub const ATOM_UNDERLINE_THICKNESS: u32 = 52;
pub const ATOM_STRIKEOUT_ASCENT: u32 = 53;
pub const ATOM_STRIKEOUT_DESCENT: u32 = 54;
pub const ATOM_ITALIC_ANGLE: u32 = 55;
pub const ATOM_X_HEIGHT: u32 = 56;
pub const ATOM_QUAD_WIDTH: u32 = 57;
pub const ATOM_WEIGHT: u32 = 58;
pub const ATOM_POINT_SIZE: u32 = 59;
pub const ATOM_RESOLUTION: u32 = 60;
pub const ATOM_COPYRIGHT: u32 = 61;
pub const ATOM_NOTICE: u32 = 62;
pub const ATOM_FONT_NAME: u32 = 63;
pub const ATOM_FAMILY_NAME: u32 = 64;
pub const ATOM_FULL_NAME: u32 = 65;
pub const ATOM_CAP_HEIGHT: u32 = 66;
pub const ATOM_WM_CLASS: u32 = 67;
pub const ATOM_WM_TRANSIENT_FOR: u32 = 68;
pub const EVENT_MASK_NO_EVENT: u32 = 0;
pub const EVENT_MASK_KEY_PRESS: u32 = 1;
pub const EVENT_MASK_KEY_RELEASE: u32 = 2;
pub const EVENT_MASK_BUTTON_PRESS: u32 = 4;
pub const EVENT_MASK_BUTTON_RELEASE: u32 = 8;
pub const EVENT_MASK_ENTER_WINDOW: u32 = 16;
pub const EVENT_MASK_LEAVE_WINDOW: u32 = 32;
pub const EVENT_MASK_POINTER_MOTION: u32 = 64;
pub const EVENT_MASK_POINTER_MOTION_HINT: u32 = 128;
pub const EVENT_MASK_BUTTON_1_MOTION: u32 = 256;
pub const EVENT_MASK_BUTTON_2_MOTION: u32 = 512;
pub const EVENT_MASK_BUTTON_3_MOTION: u32 = 1024;
pub const EVENT_MASK_BUTTON_4_MOTION: u32 = 2048;
pub const EVENT_MASK_BUTTON_5_MOTION: u32 = 4096;
pub const EVENT_MASK_BUTTON_MOTION: u32 = 8192;
pub const EVENT_MASK_KEYMAP_STATE: u32 = 16384;
pub const EVENT_MASK_EXPOSURE: u32 = 32768;
pub const EVENT_MASK_VISIBILITY_CHANGE: u32 = 65536;
pub const EVENT_MASK_STRUCTURE_NOTIFY: u32 = 131072;
pub const EVENT_MASK_RESIZE_REDIRECT: u32 = 262144;
pub const EVENT_MASK_SUBSTRUCTURE_NOTIFY: u32 = 524288;
pub const EVENT_MASK_SUBSTRUCTURE_REDIRECT: u32 = 1048576;
pub const EVENT_MASK_FOCUS_CHANGE: u32 = 2097152;
pub const EVENT_MASK_PROPERTY_CHANGE: u32 = 4194304;
pub const EVENT_MASK_COLOR_MAP_CHANGE: u32 = 8388608;
pub const EVENT_MASK_OWNER_GRAB_BUTTON: u32 = 16777216;
pub const XI_EVENT_MASK_DEVICE_CHANGED: u32 = 2;
pub const XI_EVENT_MASK_KEY_PRESS: u32 = 4;
pub const XI_EVENT_MASK_KEY_RELEASE: u32 = 8;
pub const XI_EVENT_MASK_BUTTON_PRESS: u32 = 16;
pub const XI_EVENT_MASK_BUTTON_RELEASE: u32 = 32;
pub const XI_EVENT_MASK_MOTION: u32 = 64;
pub const XI_EVENT_MASK_ENTER: u32 = 128;
pub const XI_EVENT_MASK_LEAVE: u32 = 256;
pub const XI_EVENT_MASK_FOCUS_IN: u32 = 512;
pub const XI_EVENT_MASK_FOCUS_OUT: u32 = 1024;
pub const XI_EVENT_MASK_HIERARCHY: u32 = 2048;
pub const XI_EVENT_MASK_PROPERTY: u32 = 4096;
pub const XI_EVENT_MASK_RAW_KEY_PRESS: u32 = 8192;
pub const XI_EVENT_MASK_RAW_KEY_RELEASE: u32 = 16384;
pub const XI_EVENT_MASK_RAW_BUTTON_PRESS: u32 = 32768;
pub const XI_EVENT_MASK_RAW_BUTTON_RELEASE: u32 = 65536;
pub const XI_EVENT_MASK_RAW_MOTION: u32 = 131072;
pub const XI_EVENT_MASK_TOUCH_BEGIN: u32 = 262144;
pub const XI_EVENT_MASK_TOUCH_UPDATE: u32 = 524288;
pub const XI_EVENT_MASK_TOUCH_END: u32 = 1048576;
pub const XI_EVENT_MASK_TOUCH_OWNERSHIP: u32 = 2097152;
pub const XI_EVENT_MASK_RAW_TOUCH_BEGIN: u32 = 4194304;
pub const XI_EVENT_MASK_RAW_TOUCH_UPDATE: u32 = 8388608;
pub const XI_EVENT_MASK_RAW_TOUCH_END: u32 = 16777216;
pub const XI_EVENT_MASK_BARRIER_HIT: u32 = 33554432;
pub const XI_EVENT_MASK_BARRIER_LEAVE: u32 = 67108864;
pub const PRESENT_EVENT_MASK_NO_EVENT: u32 = 0;
pub const PRESENT_EVENT_MASK_CONFIGURE_NOTIFY: u32 = 1;
pub const PRESENT_EVENT_MASK_COMPLETE_NOTIFY: u32 = 2;
pub const PRESENT_EVENT_MASK_IDLE_NOTIFY: u32 = 4;
pub const PRESENT_EVENT_MASK_REDIRECT_NOTIFY: u32 = 8;
pub const INPUT_DEVICE_TYPE_MASTER_POINTER: u16 = 1;
pub const INPUT_DEVICE_TYPE_MASTER_KEYBOARD: u16 = 2;
pub const INPUT_DEVICE_TYPE_SLAVE_POINTER: u16 = 3;
pub const INPUT_DEVICE_TYPE_SLAVE_KEYBOARD: u16 = 4;
pub const INPUT_DEVICE_TYPE_FLOATING_SLAVE: u16 = 5;
pub const XKB_PER_CLIENT_FLAG_DETECTABLE_AUTO_REPEAT: u32 = 1;
pub const XKB_PER_CLIENT_FLAG_GRABS_USE_XKB_STATE: u32 = 2;
pub const XKB_PER_CLIENT_FLAG_AUTO_RESET_CONTROLS: u32 = 4;
pub const XKB_PER_CLIENT_FLAG_LOOKUP_STATE_WHEN_GRABBED: u32 = 8;
pub const XKB_PER_CLIENT_FLAG_SEND_EVENT_USES_XKB_STATE: u32 = 16;
pub const INPUT_HIERARCHY_MASK_MASTER_ADDED: u32 = 1;
pub const INPUT_HIERARCHY_MASK_MASTER_REMOVED: u32 = 2;
pub const INPUT_HIERARCHY_MASK_SLAVE_ADDED: u32 = 4;
pub const INPUT_HIERARCHY_MASK_SLAVE_REMOVED: u32 = 8;
pub const INPUT_HIERARCHY_MASK_SLAVE_ATTACHED: u32 = 16;
pub const INPUT_HIERARCHY_MASK_SLAVE_DETACHED: u32 = 32;
pub const INPUT_HIERARCHY_MASK_DEVICE_ENABLED: u32 = 64;
pub const INPUT_HIERARCHY_MASK_DEVICE_DISABLED: u32 = 128;
pub const GRAB_MODE_SYNC: u8 = 0;
pub const GRAB_MODE_ASYNC: u8 = 1;
pub const GRAB_STATUS_SUCCESS: u8 = 0;
pub const GRAB_STATUS_ALREADY_GRABBED: u8 = 1;
pub const GRAB_STATUS_INVALID_TIME: u8 = 2;
pub const GRAB_STATUS_NOT_VIEWABLE: u8 = 3;
pub const GRAB_STATUS_FROZEN: u8 = 4;
pub const IMAGE_FORMAT_XY_BITMAP: u8 = 0;
pub const IMAGE_FORMAT_XY_PIXMAP: u8 = 1;
pub const IMAGE_FORMAT_Z_PIXMAP: u8 = 2;
pub const COMPOSITE_REDIRECT_AUTOMATIC: u8 = 0;
pub const COMPOSITE_REDIRECT_MANUAL: u8 = 1;
pub const RENDER_PICT_TYPE_INDEXED: u8 = 0;
pub const RENDER_PICT_TYPE_DIRECT: u8 = 1;
pub const PROP_MODE_REPLACE: u8 = 0;
pub const PROP_MODE_PREPEND: u8 = 1;
pub const PROP_MODE_APPEND: u8 = 2;
pub const ICCCM_WM_HINT_INPUT: i32 = 1 << 0;
pub const ICCCM_WM_HINT_STATE: i32 = 1 << 1;
pub const ICCCM_WM_HINT_ICON_PIXMAP: i32 = 1 << 2;
pub const ICCCM_WM_HINT_ICON_WINDOW: i32 = 1 << 3;
pub const ICCCM_WM_HINT_ICON_POSITION: i32 = 1 << 4;
pub const ICCCM_WM_HINT_ICON_MASK: i32 = 1 << 5;
pub const ICCCM_WM_HINT_WINDOW_GROUP: i32 = 1 << 6;
pub const ICCCM_WM_HINT_X_URGENCY: i32 = 1 << 8;
pub const ICCCM_SIZE_HINT_US_POSITION: u32 = 1 << 0;
pub const ICCCM_SIZE_HINT_US_SIZE: u32 = 1 << 1;
pub const ICCCM_SIZE_HINT_P_POSITION: u32 = 1 << 2;
pub const ICCCM_SIZE_HINT_P_SIZE: u32 = 1 << 3;
pub const ICCCM_SIZE_HINT_P_MIN_SIZE: u32 = 1 << 4;
pub const ICCCM_SIZE_HINT_P_MAX_SIZE: u32 = 1 << 5;
pub const ICCCM_SIZE_HINT_P_RESIZE_INC: u32 = 1 << 6;
pub const ICCCM_SIZE_HINT_P_ASPECT: u32 = 1 << 7;
pub const ICCCM_SIZE_HINT_BASE_SIZE: u32 = 1 << 8;
pub const ICCCM_SIZE_HINT_P_WIN_GRAVITY: u32 = 1 << 9;
pub const MWM_HINTS_FLAGS_FIELD: usize = 0;
pub const MWM_HINTS_DECORATIONS_FIELD: usize = 2;
pub const MWM_HINTS_DECORATIONS: u32 = 1 << 1;
pub const MWM_DECOR_ALL: u32 = 1 << 0;
pub const MWM_DECOR_BORDER: u32 = 1 << 1;
pub const MWM_DECOR_TITLE: u32 = 1 << 3;
pub const RES_CLIENT_ID_MASK_CLIENT_XID: u32 = 1;
pub const RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID: u32 = 2;
pub const INPUT_FOCUS_NONE: u8 = 0;
pub const INPUT_FOCUS_POINTER_ROOT: u8 = 1;
pub const INPUT_FOCUS_PARENT: u8 = 2;
pub const INPUT_FOCUS_FOLLOW_KEYBOARD: u8 = 3;
pub const NOTIFY_MODE_NORMAL: u8 = 0;
pub const NOTIFY_MODE_GRAB: u8 = 1;
pub const NOTIFY_MODE_UNGRAB: u8 = 2;
pub const NOTIFY_MODE_WHILE_GRABBED: u8 = 3;
pub const NOTIFY_DETAIL_ANCESTOR: u8 = 0;
pub const NOTIFY_DETAIL_VIRTUAL: u8 = 1;
pub const NOTIFY_DETAIL_INFERIOR: u8 = 2;
pub const NOTIFY_DETAIL_NONLINEAR: u8 = 3;
pub const NOTIFY_DETAIL_NONLINEAR_VIRTUAL: u8 = 4;
pub const NOTIFY_DETAIL_POINTER: u8 = 5;
pub const NOTIFY_DETAIL_POINTER_ROOT: u8 = 6;
pub const NOTIFY_DETAIL_NONE: u8 = 7;
pub const ICCCM_WM_STATE_WITHDRAWN: u32 = 0;
pub const ICCCM_WM_STATE_NORMAL: u32 = 1;
pub const ICCCM_WM_STATE_ICONIC: u32 = 3;
pub const _NET_WM_STATE_REMOVE: u32 = 0;
pub const _NET_WM_STATE_ADD: u32 = 1;
pub const _NET_WM_STATE_TOGGLE: u32 = 2;
pub const _NET_WM_MOVERESIZE_SIZE_TOPLEFT: u32 = 0;
pub const _NET_WM_MOVERESIZE_SIZE_TOP: u32 = 1;
pub const _NET_WM_MOVERESIZE_SIZE_TOPRIGHT: u32 = 2;
pub const _NET_WM_MOVERESIZE_SIZE_RIGHT: u32 = 3;
pub const _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT: u32 = 4;
pub const _NET_WM_MOVERESIZE_SIZE_BOTTOM: u32 = 5;
pub const _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT: u32 = 6;
pub const _NET_WM_MOVERESIZE_SIZE_LEFT: u32 = 7;
pub const _NET_WM_MOVERESIZE_MOVE: u32 = 8;
pub const _NET_WM_MOVERESIZE_SIZE_KEYBOARD: u32 = 9;
pub const _NET_WM_MOVERESIZE_MOVE_KEYBOARD: u32 = 10;
pub const _NET_WM_MOVERESIZE_CANCEL: u32 = 11;
pub const STACK_MODE_ABOVE: u32 = 0;
pub const STACK_MODE_BELOW: u32 = 1;
pub const STACK_MODE_TOP_IF: u32 = 2;
pub const STACK_MODE_BOTTOM_IF: u32 = 3;
pub const STACK_MODE_OPPOSITE: u32 = 4;
pub const CONFIG_WINDOW_X: u16 = 1;
pub const CONFIG_WINDOW_Y: u16 = 2;
pub const CONFIG_WINDOW_WIDTH: u16 = 4;
pub const CONFIG_WINDOW_HEIGHT: u16 = 8;
pub const CONFIG_WINDOW_BORDER_WIDTH: u16 = 16;
pub const CONFIG_WINDOW_SIBLING: u16 = 32;
pub const CONFIG_WINDOW_STACK_MODE: u16 = 64;
pub const SET_SELECTION_OWNER: u8 = 0;
pub const SELECTION_WINDOW_DESTROY: u8 = 1;
pub const SELECTION_CLIENT_CLOSE: u8 = 2;
pub const SET_SELECTION_OWNER_MASK: u32 = 1;
pub const SELECTION_WINDOW_DESTROY_MASK: u32 = 2;
pub const SELECTION_CLIENT_CLOSE_MASK: u32 = 4;

View file

@ -1,72 +0,0 @@
use {
crate::{utils::buf::DynamicBuf, xcon::Message},
std::rc::Rc,
uapi::{AssertPacked, OwnedFd, Packed},
};
pub struct Formatter<'a> {
fds: &'a mut Vec<Rc<OwnedFd>>,
buf: &'a mut DynamicBuf,
ext_opcode: u8,
}
impl<'a> Formatter<'a> {
pub fn new(fds: &'a mut Vec<Rc<OwnedFd>>, buf: &'a mut DynamicBuf, ext_opcode: u8) -> Self {
Self {
fds,
buf,
ext_opcode,
}
}
pub fn ext_opcode(&self) -> u8 {
self.ext_opcode
}
pub fn pad(&mut self, pad: usize) {
static BUF: [u8; 8] = [0; 8];
self.buf.extend_from_slice(&BUF[..pad]);
}
pub fn pad_to(&mut self, size: usize) {
static BUF: [u8; 8] = [0; 8];
while self.buf.len() < size {
let len = (size - self.buf.len()).min(8);
self.buf.extend_from_slice(&BUF[..len]);
}
}
pub fn align(&mut self, alignment: usize) {
static BUF: [u8; 8] = [0; 8];
let len = self.buf.len().wrapping_neg() & (alignment - 1);
self.buf.extend_from_slice(&BUF[..len]);
}
pub fn write_packed<T: Packed + ?Sized>(&mut self, t: &T) {
self.buf.extend_from_slice(uapi::as_bytes(t));
}
pub fn write_list<'b, T: Message<'b>>(&mut self, t: &[T]) {
if T::IS_POD {
self.buf
.extend_from_slice(uapi::as_bytes(unsafe { AssertPacked::new(t) }));
} else {
for t in t {
t.serialize(self);
}
}
}
pub fn write_bytes(&mut self, b: &[u8]) {
self.buf.extend_from_slice(b);
}
pub fn write_request_length(&mut self) {
let len: u16 = (self.buf.len() / 4) as u16;
self.buf[2..4].copy_from_slice(&len.to_ne_bytes());
}
pub fn add_fd(&mut self, fd: &Rc<OwnedFd>) {
self.fds.push(fd.clone());
}
}

View file

@ -99,7 +99,7 @@ impl Incoming {
break 'handle_error;
};
let e = match ext {
Some(e) => XconError::ExtensionError(e, code),
Some(e) => XconError::ExtensionError(e.name(), code),
_ => XconError::CoreError(code),
};
if let Some(first) = reply_handlers.front()

View file

@ -1,139 +0,0 @@
use {
crate::{
utils::ptr_ext::PtrExt,
xcon::{XconError, wire_type::Message},
},
bstr::{BStr, ByteSlice},
std::{borrow::Cow, rc::Rc},
uapi::{OwnedFd, Pod},
};
pub struct Parser<'a> {
pos: usize,
buf: &'a [u8],
fds_pos: usize,
fds: Vec<Rc<OwnedFd>>,
}
impl<'a> Parser<'a> {
pub fn new(buf: &'a [u8], fds: Vec<Rc<OwnedFd>>) -> Self {
Self {
buf,
pos: 0,
fds,
fds_pos: 0,
}
}
pub fn eof(&self) -> bool {
self.pos == self.buf.len()
}
fn rem(&self) -> usize {
self.buf.len() - self.pos
}
pub fn unmarshal<T: Message<'a>>(&mut self) -> Result<T, XconError> {
T::deserialize(self)
}
pub fn pad(&mut self, new: usize) -> Result<(), XconError> {
if new > self.buf.len() - self.pos {
return Err(XconError::UnexpectedEof);
}
self.pos += new;
Ok(())
}
pub fn align(&mut self, n: usize) -> Result<(), XconError> {
let new = self.pos + (self.pos.wrapping_neg() & (n - 1));
if new > self.buf.len() {
return Err(XconError::UnexpectedEof);
}
self.pos = new;
Ok(())
}
pub fn read_fd(&mut self) -> Result<Rc<OwnedFd>, XconError> {
if self.fds_pos >= self.fds.len() {
return Err(XconError::NotEnoughFds);
}
self.fds_pos += 1;
Ok(self.fds[self.fds_pos - 1].clone())
}
pub fn read_pod<T: Pod>(&mut self) -> Result<T, XconError> {
match uapi::pod_read_init(&self.buf[self.pos..]) {
Ok(v) => {
self.pos += size_of::<T>();
Ok(v)
}
_ => Err(XconError::UnexpectedEof),
}
}
pub fn read_list_slice<T: Message<'a> + Pod>(
&mut self,
n: Option<usize>,
) -> Result<&'a [T], XconError> {
let n = match n {
Some(n) => n,
_ => self.rem() / size_of::<T>(),
};
let len = size_of::<T>() * n;
if len > self.rem() {
return Err(XconError::UnexpectedEof);
}
if self.buf[self.pos..].as_ptr() as usize & (align_of::<T>() - 1) != 0 {
return Err(XconError::UnalignedSlice);
}
let res =
unsafe { std::slice::from_raw_parts(self.buf.as_ptr().add(self.pos) as *const T, n) };
self.pos += len;
Ok(res)
}
pub fn read_list<T: Message<'a> + Clone>(
&mut self,
n: Option<usize>,
) -> Result<Cow<'a, [T]>, XconError> {
let mut res = vec![];
if let Some(n) = n {
for _ in 0..n {
res.push(T::deserialize(self)?);
}
} else {
while !self.eof() {
res.push(T::deserialize(self)?);
}
}
Ok(res.into())
}
pub fn read_bytes<const N: usize>(&mut self) -> Result<&'a [u8; N], XconError> {
if N > self.rem() {
return Err(XconError::UnexpectedEof);
}
let res = unsafe { self.buf.as_ptr().add(self.pos).cast::<[u8; N]>().deref() };
self.pos += N;
Ok(res)
}
pub fn read_slice(&mut self, n: usize) -> Result<&'a [u8], XconError> {
if n > self.rem() {
return Err(XconError::UnexpectedEof);
}
let res = &self.buf[self.pos..self.pos + n];
self.pos += n;
Ok(res)
}
pub fn read_string(&mut self, n: usize) -> Result<&'a BStr, XconError> {
if n > self.rem() {
return Err(XconError::UnexpectedEof);
}
let res = &self.buf[self.pos..self.pos + n];
self.pos += n;
Ok(res.as_bstr())
}
}

View file

@ -1,153 +0,0 @@
use {
crate::xcon::{XconError, formatter::Formatter, parser::Parser},
bstr::{BStr, ByteSlice},
std::{borrow::Cow, fmt::Debug, rc::Rc},
uapi::OwnedFd,
};
#[cold]
fn unimplemented() -> ! {
unimplemented!();
}
pub unsafe trait Message<'a>: Clone + Debug + 'a {
type Generic<'b>: Message<'b>;
const IS_POD: bool;
const HAS_FDS: bool;
fn serialize(&self, formatter: &mut Formatter) {
let _ = formatter;
unimplemented()
}
fn deserialize(parser: &mut Parser<'a>) -> Result<Self, XconError> {
let _ = parser;
unimplemented()
}
}
pub trait Request<'a>: Message<'a> {
type Reply: Message<'static>;
const EXTENSION: Option<usize>;
const IS_VOID: bool;
}
pub trait XEvent<'a>: Message<'a> {
const EXTENSION: Option<usize>;
const OPCODE: u16;
}
macro_rules! simple {
($ty:ty) => {
unsafe impl Message<'_> for $ty {
type Generic<'b> = $ty;
const IS_POD: bool = true;
const HAS_FDS: bool = false;
fn serialize(&self, formatter: &mut Formatter) {
formatter.write_packed(self);
}
fn deserialize(parser: &mut Parser<'_>) -> Result<Self, XconError> {
parser.read_pod()
}
}
};
}
simple!(u8);
simple!(i8);
simple!(u16);
simple!(i16);
simple!(u32);
simple!(i32);
simple!(u64);
simple!(i64);
unsafe impl<'a> Message<'a> for () {
type Generic<'b> = ();
const IS_POD: bool = false;
const HAS_FDS: bool = false;
}
unsafe impl<'a> Message<'a> for &'a BStr {
type Generic<'b> = &'b BStr;
const IS_POD: bool = true;
const HAS_FDS: bool = false;
fn serialize(&self, formatter: &mut Formatter) {
formatter.write_packed(self.as_bytes())
}
}
unsafe impl<'a, T: Message<'a>> Message<'a> for &'a [T] {
type Generic<'b> = &'b [T::Generic<'b>];
const IS_POD: bool = false;
const HAS_FDS: bool = false;
fn serialize(&self, formatter: &mut Formatter) {
formatter.write_list(self);
}
}
unsafe impl<'a, T> Message<'a> for Cow<'a, [T]>
where
T: Message<'a>,
{
type Generic<'b> = Cow<'b, [T::Generic<'b>]>;
const IS_POD: bool = false;
const HAS_FDS: bool = false;
fn serialize(&self, formatter: &mut Formatter) {
formatter.write_list(self);
}
}
unsafe impl<'a> Message<'a> for Rc<OwnedFd> {
type Generic<'b> = Rc<OwnedFd>;
const IS_POD: bool = false;
const HAS_FDS: bool = true;
fn serialize(&self, formatter: &mut Formatter) {
formatter.add_fd(self);
}
fn deserialize(parser: &mut Parser<'a>) -> Result<Self, XconError> {
parser.read_fd()
}
}
#[derive(Debug, Clone)]
pub(super) struct SendEvent {
pub propagate: u8,
pub destination: u32,
pub event_mask: u32,
}
unsafe impl<'a> Message<'a> for SendEvent {
type Generic<'b> = SendEvent;
const IS_POD: bool = false;
const HAS_FDS: bool = false;
fn serialize(&self, formatter: &mut Formatter) {
{
let propagate_bytes = self.propagate.to_ne_bytes();
let destination_bytes = self.destination.to_ne_bytes();
let event_mask_bytes = self.event_mask.to_ne_bytes();
formatter.write_bytes(&[
25,
propagate_bytes[0],
0,
0,
destination_bytes[0],
destination_bytes[1],
destination_bytes[2],
destination_bytes[3],
event_mask_bytes[0],
event_mask_bytes[1],
event_mask_bytes[2],
event_mask_bytes[3],
]);
}
}
}

View file

@ -1,97 +0,0 @@
use {
crate::xcon::XconError,
bstr::{BString, ByteSlice},
std::{fs::File, io::Read},
};
pub const LOCAL: u16 = 256;
pub const MIT_MAGIC_COOKIE: &[u8] = b"MIT-MAGIC-COOKIE-1";
#[derive(Debug)]
pub struct XAuthority {
pub family: u16,
pub host: BString,
pub display: u32,
pub method: BString,
pub value: BString,
}
impl XAuthority {
pub fn load() -> Result<Vec<XAuthority>, XconError> {
let path = 'path: {
if let Ok(p) = std::env::var("XAUTHORITY") {
break 'path p;
}
if let Ok(home) = std::env::var("HOME") {
break 'path format!("{home}/.Xauthority");
}
return Err(XconError::HomeNotSet);
};
let mut buf = vec![];
if let Err(e) = File::open(path).and_then(|mut f| f.read_to_end(&mut buf)) {
return Err(XconError::ReadXAuthority(e));
}
Parser::parse(&buf)
}
}
struct Parser<'a> {
pos: usize,
buf: &'a [u8],
}
impl<'a> Parser<'a> {
fn parse(buf: &[u8]) -> Result<Vec<XAuthority>, XconError> {
let mut slf = Parser { pos: 0, buf };
let mut res = vec![];
while slf.rem() > 0 {
res.push(slf.parse_one()?);
}
Ok(res)
}
fn rem(&self) -> usize {
self.buf.len() - self.pos
}
fn parse_one(&mut self) -> Result<XAuthority, XconError> {
Ok(XAuthority {
family: self.read_u16()?,
host: self.read_string()?,
display: {
let s = self.read_string()?;
match s.to_str() {
Ok(s) => match s.parse() {
Ok(v) => v,
_ => return Err(XconError::InvalidAuthorityDisplay),
},
_ => return Err(XconError::InvalidAuthorityDisplay),
}
},
method: self.read_string()?,
value: self.read_string()?,
})
}
fn read_u16(&mut self) -> Result<u16, XconError> {
if self.rem() < 2 {
return Err(XconError::UnexpectedEof);
}
let bytes = [self.buf[self.pos], self.buf[self.pos + 1]];
self.pos += 2;
Ok(u16::from_be_bytes(bytes))
}
fn read_string(&mut self) -> Result<BString, XconError> {
let len = self.read_u16()? as usize;
if self.rem() < len {
log::info!("rem = {}; len = {}", self.rem(), len);
return Err(XconError::UnexpectedEof);
}
let res = self.buf[self.pos..self.pos + len].to_vec();
self.pos += len;
let res = res.into();
Ok(res)
}
}