Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ jobs:
env:
PKG_CONFIG_PATH: "${{ github.workspace }}/wayland-install/lib/x86_64-linux-gnu/pkgconfig"
LD_LIBRARY_PATH: "${{ github.workspace }}/wayland-install/lib/x86_64-linux-gnu"
run: cargo test -p wayland-tests --features client_system,libwayland_client_1_23
run: cargo test -p wayland-tests --features client_system,libwayland_client_1_23,libwayland_server_1_23

check-redox:
needs:
Expand Down Expand Up @@ -338,7 +338,7 @@ jobs:
fail-fast: false
matrix:
client_feature: ["libwayland_client_1_23", "client_system"]
server_feature: ["libwayland_server_1_22", "server_system", "server_system,libwayland_server_1_22"]
server_feature: ["libwayland_server_1_23", "server_system", "server_system,libwayland_server_1_22"]

steps:
- name: Checkout sources
Expand Down
2 changes: 2 additions & 0 deletions wayland-backend/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
- client: Added `display_ptr` method to `ObjectId`
- server: Addded `Handle::global_name`
* Requires `libwayland_server_1_22` feature
- client: Added `set_max_buffer_size` method
- server: Added `set_default_max_buffer_size` and `set_max_buffer_size` methods

## 0.3.12 -- 2025-12-30

Expand Down
2 changes: 2 additions & 0 deletions wayland-backend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ scoped-tls = "1.0"
client_system = ["wayland-sys/client", "dep:scoped-tls"]
server_system = ["wayland-sys/server", "dep:scoped-tls"]
dlopen = ["wayland-sys/dlopen"]
libwayland_client_1_23 = ["wayland-sys/libwayland_client_1_23"]
libwayland_server_1_22 = ["wayland-sys/libwayland_server_1_22"]
libwayland_server_1_23 = ["wayland-sys/libwayland_server_1_23", "libwayland_server_1_22"]

[package.metadata.docs.rs]
all-features = true
Expand Down
6 changes: 6 additions & 0 deletions wayland-backend/src/client_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,12 @@ impl Backend {
pub fn dispatch_inner_queue(&self) -> Result<usize, WaylandError> {
self.backend.dispatch_inner_queue()
}

/// Set maximum buffer size for connection
#[cfg(feature = "libwayland_client_1_23")]
pub fn set_max_buffer_size(&self, max_buffer_size: Option<usize>) {
self.backend.set_max_buffer_size(max_buffer_size);
}
}

/// Guard for synchronizing event reading across multiple threads
Expand Down
8 changes: 7 additions & 1 deletion wayland-backend/src/rs/client_impl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ impl InnerBackend {
}

pub fn connect(stream: UnixStream) -> Result<Self, NoWaylandLib> {
let socket = BufferedSocket::new(Socket::from(stream), true);
let socket = BufferedSocket::new(Socket::from(stream), None);
let mut map = ObjectMap::new();
map.insert_at(
1,
Expand Down Expand Up @@ -527,6 +527,12 @@ impl InnerBackend {
pub fn dispatch_inner_queue(&self) -> Result<usize, WaylandError> {
Ok(0)
}

#[allow(dead_code)]
pub fn set_max_buffer_size(&self, max_buffer_size: Option<usize>) {
let mut guard = self.state.lock_protocol();
guard.socket.set_max_buffer_size(max_buffer_size);
}
}

impl ProtocolState {
Expand Down
3 changes: 3 additions & 0 deletions wayland-backend/src/rs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ mod map;
pub(crate) mod socket;
mod wire;

// Matches `WL_BUFFER_DEFAULT_MAX_SIZE` in `libwayland`
pub(crate) const DEFAULT_MAX_BUFFER_SIZE: usize = 4096;

/// Client-side rust implementation of a Wayland protocol backend
///
/// The main entrypoint is the [`Backend::connect()`][client::Backend::connect()] method.
Expand Down
8 changes: 5 additions & 3 deletions wayland-backend/src/rs/server_impl/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ pub(crate) enum DisplayError {

#[derive(Debug)]
pub(crate) struct Client<D: 'static> {
socket: BufferedSocket,
pub(crate) socket: BufferedSocket,
pub(crate) map: ObjectMap<Data<D>>,
debug: bool,
last_serial: u32,
Expand All @@ -68,8 +68,9 @@ impl<D> Client<D> {
id: InnerClientId,
debug: bool,
data: Arc<dyn ClientData>,
buffer_size: usize,
) -> Self {
let socket = BufferedSocket::new(Socket::from(stream), false);
let socket = BufferedSocket::new(Socket::from(stream), Some(buffer_size));
let mut map = ObjectMap::new();
map.insert_at(
1,
Expand Down Expand Up @@ -709,6 +710,7 @@ impl<D> ClientStore<D> {
&mut self,
stream: UnixStream,
data: Arc<dyn ClientData>,
buffer_size: usize,
) -> InnerClientId {
let serial = self.next_serial();
// Find the next free place
Expand All @@ -722,7 +724,7 @@ impl<D> ClientStore<D> {

let id = InnerClientId { id: id as u32, serial };

*place = Some(Client::new(stream, id.clone(), self.debug, data));
*place = Some(Client::new(stream, id.clone(), self.debug, data, buffer_size));

id
}
Expand Down
9 changes: 8 additions & 1 deletion wayland-backend/src/rs/server_impl/common_poll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use super::{
use crate::{
core_interfaces::{WL_DISPLAY_INTERFACE, WL_REGISTRY_INTERFACE},
protocol::{same_interface, Argument, Message},
rs::map::Object,
rs::{map::Object, DEFAULT_MAX_BUFFER_SIZE},
types::server::InitError,
};

Expand Down Expand Up @@ -326,6 +326,13 @@ impl<D> InnerBackend<D> {
}
Ok(dispatched)
}

#[allow(dead_code)]
pub fn set_default_max_buffer_size(&self, size: usize) {
let size =
size.checked_next_power_of_two().unwrap_or(usize::MAX).max(DEFAULT_MAX_BUFFER_SIZE);
self.state.lock().unwrap().default_max_buffer_size = size;
}
}

enum DispatchAction<D: 'static> {
Expand Down
21 changes: 20 additions & 1 deletion wayland-backend/src/rs/server_impl/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use std::{

use crate::{
protocol::{same_interface, Interface, Message, ObjectInfo, ANONYMOUS_INTERFACE},
rs::DEFAULT_MAX_BUFFER_SIZE,
types::server::{DisconnectReason, GlobalInfo, InvalidId},
};

Expand All @@ -25,6 +26,7 @@ pub struct State<D: 'static> {
pub(crate) registry: Registry<D>,
pub(crate) pending_destructors: Vec<PendingDestructor<D>>,
pub(crate) poll_fd: OwnedFd,
pub(crate) default_max_buffer_size: usize,
}

impl<D> State<D> {
Expand All @@ -36,6 +38,7 @@ impl<D> State<D> {
registry: Registry::new(),
pending_destructors: Vec::new(),
poll_fd,
default_max_buffer_size: DEFAULT_MAX_BUFFER_SIZE,
}
}

Expand Down Expand Up @@ -70,6 +73,12 @@ impl<D> State<D> {
Ok(())
}
}

fn set_max_buffer_size(&mut self, client: InnerClientId, max_buffer_size: usize) {
if let Ok(client) = self.clients.get_client_mut(client) {
client.socket.set_max_buffer_size(Some(max_buffer_size));
}
}
}

#[derive(Clone)]
Expand Down Expand Up @@ -281,6 +290,11 @@ impl InnerHandle {
pub fn flush(&mut self, client: Option<ClientId>) -> std::io::Result<()> {
self.state.lock().unwrap().flush(client)
}

#[allow(dead_code)]
pub fn set_max_buffer_size(&mut self, client: InnerClientId, max_buffer_size: usize) {
self.state.lock().unwrap().set_max_buffer_size(client, max_buffer_size)
}
}

pub(crate) trait ErasedState: downcast_rs::Downcast {
Expand Down Expand Up @@ -315,6 +329,7 @@ pub(crate) trait ErasedState: downcast_rs::Downcast {
fn global_info(&self, id: InnerGlobalId) -> Result<GlobalInfo, InvalidId>;
fn global_name(&self, global: InnerGlobalId, client: InnerClientId) -> Option<u32>;
fn flush(&mut self, client: Option<ClientId>) -> std::io::Result<()>;
fn set_max_buffer_size(&mut self, client: InnerClientId, max_buffer_size: usize);
}

downcast_rs::impl_downcast!(ErasedState);
Expand All @@ -329,7 +344,7 @@ impl<D> ErasedState for State<D> {
stream: UnixStream,
data: Arc<dyn ClientData>,
) -> std::io::Result<InnerClientId> {
let id = self.clients.create_client(stream, data);
let id = self.clients.create_client(stream, data, self.default_max_buffer_size);
let client = self.clients.get_client(id.clone()).unwrap();

// register the client to the internal epoll
Expand Down Expand Up @@ -474,4 +489,8 @@ impl<D> ErasedState for State<D> {
fn flush(&mut self, client: Option<ClientId>) -> std::io::Result<()> {
self.flush(client)
}

fn set_max_buffer_size(&mut self, client: InnerClientId, max_buffer_size: usize) {
self.set_max_buffer_size(client, max_buffer_size)
}
}
36 changes: 21 additions & 15 deletions wayland-backend/src/rs/socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use rustix::net::{
};

use crate::protocol::{ArgumentType, Message};
use crate::rs::DEFAULT_MAX_BUFFER_SIZE;

use super::wire::{parse_message, write_to_buffers, MessageParseError, MessageWriteError};

Expand Down Expand Up @@ -134,19 +135,19 @@ pub struct BufferedSocket {
in_fds: VecDeque<OwnedFd>,
out_data: Buffer<u8>,
out_fds: Vec<OwnedFd>,
unbounded: bool,
max_buffer_size: Option<usize>,
}

impl BufferedSocket {
/// Wrap a Socket into a Buffered Socket
pub fn new(socket: Socket, unbounded: bool) -> Self {
pub fn new(socket: Socket, max_buffer_size: Option<usize>) -> Self {
Self {
socket,
in_data: Buffer::new(2 * MAX_BYTES_OUT), // Incoming buffers are twice as big in order to be
in_fds: VecDeque::new(), // able to store leftover data if needed
out_data: Buffer::new(MAX_BYTES_OUT),
in_data: Buffer::new(DEFAULT_MAX_BUFFER_SIZE),
in_fds: VecDeque::new(),
out_data: Buffer::new(DEFAULT_MAX_BUFFER_SIZE),
out_fds: Vec::new(),
unbounded,
max_buffer_size,
}
}

Expand Down Expand Up @@ -217,7 +218,7 @@ impl BufferedSocket {
}
Err(MessageWriteError::BufferTooSmall) => {
self.out_fds.truncate(fds_len);
if !self.unbounded {
if self.max_buffer_size.is_some_and(|s| s <= self.out_data.storage.len()) {
return Ok(false);
}
self.out_data.increase_capacity();
Expand Down Expand Up @@ -307,6 +308,11 @@ impl BufferedSocket {

Ok(msg)
}

pub fn set_max_buffer_size(&mut self, max_buffer_size: Option<usize>) {
// TODO: what if it decreases?
self.max_buffer_size = max_buffer_size;
}
}

impl AsRawFd for BufferedSocket {
Expand Down Expand Up @@ -437,8 +443,8 @@ mod tests {
};

let (client, server) = ::std::os::unix::net::UnixStream::pair().unwrap();
let mut client = BufferedSocket::new(Socket::from(client), false);
let mut server = BufferedSocket::new(Socket::from(server), false);
let mut client = BufferedSocket::new(Socket::from(client), Some(DEFAULT_MAX_BUFFER_SIZE));
let mut server = BufferedSocket::new(Socket::from(server), Some(DEFAULT_MAX_BUFFER_SIZE));

client.write_message(&msg).unwrap();
client.flush().unwrap();
Expand Down Expand Up @@ -481,8 +487,8 @@ mod tests {
};

let (client, server) = ::std::os::unix::net::UnixStream::pair().unwrap();
let mut client = BufferedSocket::new(Socket::from(client), false);
let mut server = BufferedSocket::new(Socket::from(server), false);
let mut client = BufferedSocket::new(Socket::from(client), Some(DEFAULT_MAX_BUFFER_SIZE));
let mut server = BufferedSocket::new(Socket::from(server), Some(DEFAULT_MAX_BUFFER_SIZE));

client.write_message(&msg).unwrap();
client.flush().unwrap();
Expand Down Expand Up @@ -540,8 +546,8 @@ mod tests {
];

let (client, server) = ::std::os::unix::net::UnixStream::pair().unwrap();
let mut client = BufferedSocket::new(Socket::from(client), false);
let mut server = BufferedSocket::new(Socket::from(server), false);
let mut client = BufferedSocket::new(Socket::from(client), Some(DEFAULT_MAX_BUFFER_SIZE));
let mut server = BufferedSocket::new(Socket::from(server), Some(DEFAULT_MAX_BUFFER_SIZE));

for msg in &messages {
client.write_message(msg).unwrap();
Expand Down Expand Up @@ -579,8 +585,8 @@ mod tests {
};

let (client, server) = ::std::os::unix::net::UnixStream::pair().unwrap();
let mut client = BufferedSocket::new(Socket::from(client), false);
let mut server = BufferedSocket::new(Socket::from(server), false);
let mut client = BufferedSocket::new(Socket::from(client), Some(DEFAULT_MAX_BUFFER_SIZE));
let mut server = BufferedSocket::new(Socket::from(server), Some(DEFAULT_MAX_BUFFER_SIZE));

client.write_message(&msg).unwrap();
client.flush().unwrap();
Expand Down
14 changes: 14 additions & 0 deletions wayland-backend/src/server_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,12 @@ impl Handle {
pub fn flush(&mut self, client: Option<ClientId>) -> std::io::Result<()> {
self.handle.flush(client)
}

/// Set maximum buffer size for client.
#[cfg(feature = "libwayland_server_1_23")]
pub fn set_max_buffer_size(&mut self, client: ClientId, max_buffer_size: usize) {
self.handle.set_max_buffer_size(client.id, max_buffer_size);
}
}

/// A backend object that represents the state of a wayland server.
Expand Down Expand Up @@ -603,6 +609,14 @@ impl<D> Backend<D> {
pub fn dispatch_all_clients(&mut self, data: &mut D) -> std::io::Result<usize> {
self.backend.dispatch_all_clients(data)
}

/// Set default client max buffer size.
///
/// This method will only affect connections created after the method call.
#[cfg(feature = "libwayland_server_1_23")]
pub fn set_default_max_buffer_size(&mut self, max_buffer_size: usize) {
self.backend.set_default_max_buffer_size(max_buffer_size);
}
}

// Workaround: Some versions of rustc throw a `struct is never constructed`-warning here,
Expand Down
13 changes: 13 additions & 0 deletions wayland-backend/src/sys/client_impl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,19 @@ impl InnerBackend {
pub fn dispatch_inner_queue(&self) -> Result<usize, WaylandError> {
self.inner.dispatch_lock.lock().unwrap().dispatch_pending(self.inner.clone())
}

#[cfg(feature = "libwayland_client_1_23")]
pub fn set_max_buffer_size(&self, max_buffer_size: Option<usize>) {
let guard = self.lock_state();
unsafe {
ffi_dispatch!(
wayland_client_handle(),
wl_display_set_max_buffer_size,
guard.display,
max_buffer_size.unwrap_or(0)
)
}
}
}

impl ConnectionState {
Expand Down
Loading
Loading