1 //! Server-side implementation of a Wayland protocol backend using `libwayland`
2 
3 use std::{
4     ffi::{CStr, CString},
5     os::raw::{c_char, c_void},
6     os::unix::{
7         io::{IntoRawFd, RawFd},
8         net::UnixStream,
9     },
10     sync::{
11         atomic::{AtomicBool, Ordering},
12         Arc,
13     },
14 };
15 
16 use crate::protocol::{
17     check_for_signature, same_interface, AllowNull, Argument, ArgumentType, Interface, Message,
18     ObjectInfo, ANONYMOUS_INTERFACE,
19 };
20 use scoped_tls::scoped_thread_local;
21 use smallvec::SmallVec;
22 
23 use wayland_sys::{common::*, ffi_dispatch, server::*};
24 
25 use super::{free_arrays, RUST_MANAGED};
26 
27 pub use crate::types::server::{Credentials, DisconnectReason, GlobalInfo, InitError, InvalidId};
28 
29 // First pointer is &mut Handle<D>, and second pointer is &mut D
30 scoped_thread_local!(static HANDLE: (*mut c_void, *mut c_void));
31 
32 type PendingDestructor<D> = (Arc<dyn ObjectData<D>>, ClientId, ObjectId);
33 
34 // Pointer is &mut Vec<PendingDestructor<D>>
35 scoped_thread_local!(static PENDING_DESTRUCTORS: *mut c_void);
36 
37 /// A trait representing your data associated to an object
38 ///
39 /// You will only be given access to it as a `&` reference, so you
40 /// need to handle interior mutability by yourself.
41 ///
42 /// The methods of this trait will be invoked internally every time a
43 /// new object is created to initialize its data.
44 pub trait ObjectData<D>: downcast_rs::DowncastSync {
45     /// Dispatch a request for the associated object
46     ///
47     /// If the request has a NewId argument, the callback must return the object data
48     /// for the newly created object
request( self: Arc<Self>, handle: &mut Handle<D>, data: &mut D, client_id: ClientId, msg: Message<ObjectId>, ) -> Option<Arc<dyn ObjectData<D>>>49     fn request(
50         self: Arc<Self>,
51         handle: &mut Handle<D>,
52         data: &mut D,
53         client_id: ClientId,
54         msg: Message<ObjectId>,
55     ) -> Option<Arc<dyn ObjectData<D>>>;
56     /// Notification that the object has been destroyed and is no longer active
destroyed(&self, _: &mut D, client_id: ClientId, object_id: ObjectId)57     fn destroyed(&self, _: &mut D, client_id: ClientId, object_id: ObjectId);
58     /// Helper for forwarding a Debug implementation of your `ObjectData` type
59     ///
60     /// By default will just print `ObjectData { ... }`
debug(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result61     fn debug(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
62         f.debug_struct("ObjectData").finish_non_exhaustive()
63     }
64 }
65 
66 downcast_rs::impl_downcast!(sync ObjectData<D>);
67 
68 #[cfg(not(tarpaulin_include))]
69 impl<D> std::fmt::Debug for dyn ObjectData<D> {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result70     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71         self.debug(f)
72     }
73 }
74 
75 /// A trait representing the handling of new bound globals
76 pub trait GlobalHandler<D>: downcast_rs::DowncastSync {
77     /// Check if given client is allowed to interact with given global
78     ///
79     /// If this function returns false, the client will not be notified of the existence
80     /// of this global, and any attempt to bind it will result in a protocol error as if
81     /// the global did not exist.
82     ///
83     /// Default implementation always return true.
can_view( &self, _client_id: ClientId, _client_data: &Arc<dyn ClientData<D>>, _global_id: GlobalId, ) -> bool84     fn can_view(
85         &self,
86         _client_id: ClientId,
87         _client_data: &Arc<dyn ClientData<D>>,
88         _global_id: GlobalId,
89     ) -> bool {
90         true
91     }
92     /// A global has been bound
93     ///
94     /// Given client bound given global, creating given object.
95     ///
96     /// The method must return the object data for the newly created object.
bind( self: Arc<Self>, handle: &mut Handle<D>, data: &mut D, client_id: ClientId, global_id: GlobalId, object_id: ObjectId, ) -> Arc<dyn ObjectData<D>>97     fn bind(
98         self: Arc<Self>,
99         handle: &mut Handle<D>,
100         data: &mut D,
101         client_id: ClientId,
102         global_id: GlobalId,
103         object_id: ObjectId,
104     ) -> Arc<dyn ObjectData<D>>;
105     /// Helper for forwarding a Debug implementation of your `GlobalHandler` type
106     ///
107     /// By default will just print `GlobalHandler { ... }`
debug(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result108     fn debug(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
109         f.debug_struct("GlobalHandler").finish_non_exhaustive()
110     }
111 }
112 
113 #[cfg(not(tarpaulin_include))]
114 impl<D> std::fmt::Debug for dyn GlobalHandler<D> {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result115     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
116         self.debug(f)
117     }
118 }
119 
120 downcast_rs::impl_downcast!(sync GlobalHandler<D>);
121 
122 /// A trait representing your data associated to a clientObjectData
123 pub trait ClientData<D>: downcast_rs::DowncastSync {
124     /// Notification that a client was initialized
initialized(&self, client_id: ClientId)125     fn initialized(&self, client_id: ClientId);
126 
127     /// Notification that a client is disconnected
disconnected(&self, client_id: ClientId, reason: DisconnectReason)128     fn disconnected(&self, client_id: ClientId, reason: DisconnectReason);
129     /// Helper for forwarding a Debug implementation of your `ClientData` type
130     ///
131     /// By default will just print `GlobalHandler { ... }`
debug(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result132     fn debug(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
133         f.debug_struct("ClientData").finish_non_exhaustive()
134     }
135 }
136 
137 #[cfg(not(tarpaulin_include))]
138 impl<D> std::fmt::Debug for dyn ClientData<D> {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result139     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
140         self.debug(f)
141     }
142 }
143 
144 downcast_rs::impl_downcast!(sync ClientData<D>);
145 
146 /// An id of an object on a wayland server.
147 #[derive(Clone)]
148 pub struct ObjectId {
149     id: u32,
150     ptr: *mut wl_resource,
151     alive: Option<Arc<AtomicBool>>,
152     interface: &'static Interface,
153 }
154 
155 unsafe impl Send for ObjectId {}
156 unsafe impl Sync for ObjectId {}
157 
158 impl std::cmp::PartialEq for ObjectId {
eq(&self, other: &ObjectId) -> bool159     fn eq(&self, other: &ObjectId) -> bool {
160         match (&self.alive, &other.alive) {
161             (Some(ref a), Some(ref b)) => {
162                 // this is an object we manage
163                 Arc::ptr_eq(a, b)
164             }
165             (None, None) => {
166                 // this is an external object
167                 self.ptr == other.ptr
168                     && self.id == other.id
169                     && same_interface(self.interface, other.interface)
170             }
171             _ => false,
172         }
173     }
174 }
175 
176 impl std::cmp::Eq for ObjectId {}
177 
178 #[cfg(not(tarpaulin_include))]
179 impl std::fmt::Display for ObjectId {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result180     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
181         write!(f, "{}@{}", self.interface.name, self.id)
182     }
183 }
184 
185 #[cfg(not(tarpaulin_include))]
186 impl std::fmt::Debug for ObjectId {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result187     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
188         write!(f, "ObjectId({})", self)
189     }
190 }
191 
192 impl ObjectId {
193     /// Returns whether this object is a null object.
is_null(&self) -> bool194     pub fn is_null(&self) -> bool {
195         self.ptr.is_null()
196     }
197 
198     /// Returns the interface of this object.
interface(&self) -> &'static Interface199     pub fn interface(&self) -> &'static Interface {
200         self.interface
201     }
202 
203     /// Check if two object IDs are associated with the same client
204     ///
205     /// *Note:* This may spuriously return `false` if one (or both) of the objects to compare
206     /// is no longer valid.
same_client_as(&self, other: &ObjectId) -> bool207     pub fn same_client_as(&self, other: &ObjectId) -> bool {
208         let my_client_ptr = match self.alive {
209             Some(ref alive) if !alive.load(Ordering::Acquire) => {
210                 return false;
211             }
212             _ => unsafe { ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_get_client, self.ptr) },
213         };
214         let other_client_ptr = match other.alive {
215             Some(ref alive) if !alive.load(Ordering::Acquire) => {
216                 return false;
217             }
218             _ => unsafe { ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_get_client, other.ptr) },
219         };
220 
221         my_client_ptr == other_client_ptr
222     }
223 
224     /// Return the protocol-level numerical ID of this object
225     ///
226     /// Protocol IDs are reused after object destruction, so this should not be used as a
227     /// unique identifier,
protocol_id(&self) -> u32228     pub fn protocol_id(&self) -> u32 {
229         self.id
230     }
231 
232     /// Creates an object from a C pointer.
233     ///
234     /// # Errors
235     ///
236     /// This function returns an [`InvalidId`] error if the interface of the resource does not match the
237     /// provided interface.
238     ///
239     /// # Safety
240     ///
241     /// The provided pointer must be a valid pointer to a `wl_resource` and remain valid for as
242     /// long as the retrieved `ObjectId` is used.
from_ptr( interface: &'static Interface, ptr: *mut wl_resource, ) -> Result<ObjectId, InvalidId>243     pub unsafe fn from_ptr(
244         interface: &'static Interface,
245         ptr: *mut wl_resource,
246     ) -> Result<ObjectId, InvalidId> {
247         let iface_c_ptr =
248             interface.c_ptr.expect("[wayland-backend-sys] Cannot use Interface without c_ptr!");
249         let ptr_iface_name =
250             CStr::from_ptr(ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_get_class, ptr));
251         let provided_iface_name = CStr::from_ptr(iface_c_ptr.name);
252         if ptr_iface_name != provided_iface_name {
253             return Err(InvalidId);
254         }
255 
256         let id = ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_get_id, ptr);
257 
258         let is_rust_managed = ffi_dispatch!(
259             WAYLAND_SERVER_HANDLE,
260             wl_resource_instance_of,
261             ptr,
262             iface_c_ptr,
263             &RUST_MANAGED as *const u8 as *const _
264         ) != 0;
265 
266         let alive = if is_rust_managed {
267             // Using () instead of the type parameter here is safe, because:
268             // 1) ResourceUserData is #[repr(C)], so its layout does not depend on D
269             // 2) we are only accessing the field `.alive`, which type is independent of D
270             //
271             let udata = ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_get_user_data, ptr)
272                 as *mut ResourceUserData<()>;
273             Some((*udata).alive.clone())
274         } else {
275             None
276         };
277 
278         Ok(ObjectId { id, ptr, alive, interface })
279     }
280 
281     /// Returns the pointer that represents this object.
282     ///
283     /// The pointer may be used to interoperate with libwayland.
as_ptr(&self) -> *mut wl_resource284     pub fn as_ptr(&self) -> *mut wl_resource {
285         if self.alive.as_ref().map(|alive| alive.load(Ordering::Acquire)).unwrap_or(true) {
286             self.ptr
287         } else {
288             std::ptr::null_mut()
289         }
290     }
291 }
292 
293 /// An id of a client connected to the server.
294 #[derive(Debug, Clone)]
295 pub struct ClientId {
296     ptr: *mut wl_client,
297     alive: Arc<AtomicBool>,
298 }
299 
300 unsafe impl Send for ClientId {}
301 unsafe impl Sync for ClientId {}
302 
303 impl std::cmp::PartialEq for ClientId {
eq(&self, other: &ClientId) -> bool304     fn eq(&self, other: &ClientId) -> bool {
305         Arc::ptr_eq(&self.alive, &other.alive)
306     }
307 }
308 
309 impl std::cmp::Eq for ClientId {}
310 
311 /// The ID of a global
312 #[derive(Debug, Clone)]
313 pub struct GlobalId {
314     ptr: *mut wl_global,
315     alive: Arc<AtomicBool>,
316 }
317 
318 unsafe impl Send for GlobalId {}
319 unsafe impl Sync for GlobalId {}
320 
321 impl std::cmp::PartialEq for GlobalId {
eq(&self, other: &GlobalId) -> bool322     fn eq(&self, other: &GlobalId) -> bool {
323         Arc::ptr_eq(&self.alive, &other.alive)
324     }
325 }
326 
327 impl std::cmp::Eq for GlobalId {}
328 
329 #[repr(C)]
330 struct ResourceUserData<D> {
331     alive: Arc<AtomicBool>,
332     data: Arc<dyn ObjectData<D>>,
333     interface: &'static Interface,
334 }
335 
336 struct ClientUserData<D> {
337     data: Arc<dyn ClientData<D>>,
338     alive: Arc<AtomicBool>,
339 }
340 
341 struct GlobalUserData<D> {
342     handler: Arc<dyn GlobalHandler<D>>,
343     interface: &'static Interface,
344     version: u32,
345     disabled: bool,
346     alive: Arc<AtomicBool>,
347     ptr: *mut wl_global,
348 }
349 
350 /// Main handle of a backend to the Wayland protocol
351 ///
352 /// This type hosts most of the protocol-related functionality of the backend, and is the
353 /// main entry point for manipulating Wayland objects. It can be retrieved both from
354 /// the backend via [`Backend::handle()`](Backend::handle), and is given to you as argument
355 /// in most event callbacks.
356 #[derive(Debug)]
357 pub struct Handle<D> {
358     display: *mut wl_display,
359     pending_destructors: Vec<PendingDestructor<D>>,
360     _data: std::marker::PhantomData<fn(&mut D)>,
361 }
362 
363 /// A backend object that represents the state of a wayland server.
364 ///
365 /// A backend is used to drive a wayland server by receiving requests, dispatching messages to the appropriate
366 /// handlers and flushes requests to be sent back to the client.
367 #[derive(Debug)]
368 pub struct Backend<D> {
369     handle: Handle<D>,
370 }
371 
372 unsafe impl<D> Send for Backend<D> {}
373 unsafe impl<D> Sync for Backend<D> {}
374 
375 impl<D> Backend<D> {
376     /// Initialize a new Wayland backend
new() -> Result<Self, InitError>377     pub fn new() -> Result<Self, InitError> {
378         if !is_lib_available() {
379             return Err(InitError::NoWaylandLib);
380         }
381 
382         let display = unsafe { ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_display_create,) };
383         if display.is_null() {
384             panic!("[wayland-backend-sys] libwayland reported an allocation failure.");
385         }
386 
387         unsafe {
388             ffi_dispatch!(
389                 WAYLAND_SERVER_HANDLE,
390                 wl_log_set_handler_server,
391                 wl_log_trampoline_to_rust_server
392             )
393         };
394 
395         unsafe {
396             ffi_dispatch!(
397                 WAYLAND_SERVER_HANDLE,
398                 wl_display_set_global_filter,
399                 display,
400                 global_filter::<D>,
401                 std::ptr::null_mut()
402             );
403         }
404 
405         Ok(Backend {
406             handle: Handle {
407                 display,
408                 pending_destructors: Vec::new(),
409                 _data: std::marker::PhantomData,
410             },
411         })
412     }
413 
414     /// Initializes a connection to a client.
415     ///
416     /// The `data` parameter contains data that will be associated with the client.
insert_client( &mut self, stream: UnixStream, data: Arc<dyn ClientData<D>>, ) -> std::io::Result<ClientId>417     pub fn insert_client(
418         &mut self,
419         stream: UnixStream,
420         data: Arc<dyn ClientData<D>>,
421     ) -> std::io::Result<ClientId> {
422         let ret = unsafe {
423             ffi_dispatch!(
424                 WAYLAND_SERVER_HANDLE,
425                 wl_client_create,
426                 self.handle.display,
427                 stream.into_raw_fd()
428             )
429         };
430 
431         if ret.is_null() {
432             return Err(std::io::Error::last_os_error());
433         }
434 
435         Ok(unsafe { init_client::<D>(ret, data) })
436     }
437 
438     /// Flushes pending events destined for a client.
439     ///
440     /// If no client is specified, all pending events are flushed to all clients.
flush(&mut self, client: Option<ClientId>) -> std::io::Result<()>441     pub fn flush(&mut self, client: Option<ClientId>) -> std::io::Result<()> {
442         if let Some(client_id) = client {
443             if client_id.alive.load(Ordering::Acquire) {
444                 unsafe { ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_client_flush, client_id.ptr) }
445             }
446         } else {
447             // wl_display_flush_clients might invoke destructors
448             PENDING_DESTRUCTORS.set(
449                 &(&mut self.handle.pending_destructors as *mut _ as *mut _),
450                 || unsafe {
451                     ffi_dispatch!(
452                         WAYLAND_SERVER_HANDLE,
453                         wl_display_flush_clients,
454                         self.handle.display
455                     );
456                 },
457             );
458         }
459         Ok(())
460     }
461 
462     /// Returns a handle which represents the server side state of the backend.
463     ///
464     /// The handle provides a variety of functionality, such as querying information about wayland objects,
465     /// obtaining data associated with a client and it's objects, and creating globals.
handle(&mut self) -> &mut Handle<D>466     pub fn handle(&mut self) -> &mut Handle<D> {
467         &mut self.handle
468     }
469 
470     /// Returns the underlying file descriptor.
471     ///
472     /// The file descriptor may be monitored for activity with a polling mechanism such as epoll or kqueue.
473     /// When it becomes readable, this means there are pending messages that would be dispatched if you call
474     /// [`Backend::dispatch_all_clients`].
475     ///
476     /// The file descriptor should not be used for any other purpose than monitoring it.
poll_fd(&self) -> RawFd477     pub fn poll_fd(&self) -> RawFd {
478         unsafe {
479             let evl_ptr = ffi_dispatch!(
480                 WAYLAND_SERVER_HANDLE,
481                 wl_display_get_event_loop,
482                 self.handle.display
483             );
484             ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_event_loop_get_fd, evl_ptr)
485         }
486     }
487 
488     /// Dispatches all pending messages from the specified client.
489     ///
490     /// This method will not block if there are no pending messages.
491     ///
492     /// The provided `data` will be provided to the handler of messages received from the client.
493     ///
494     /// For performance reasons, use of this function should be integrated with an event loop, monitoring the
495     /// file descriptor associated with the client and only calling this method when messages are available.
496     ///
497     /// # Backend specific
498     ///
499     /// The `sys` backend may also dispatch other clients than the client being dispatched.
dispatch_client( &mut self, data: &mut D, _client_id: ClientId, ) -> std::io::Result<usize>500     pub fn dispatch_client(
501         &mut self,
502         data: &mut D,
503         _client_id: ClientId,
504     ) -> std::io::Result<usize> {
505         self.dispatch_all_clients(data)
506     }
507 
508     /// Dispatches all pending messages from all clients.
509     ///
510     /// This method will not block if there are no pending messages.
511     ///
512     /// The provided `data` will be provided to the handler of messages received from the clients.
513     ///
514     /// For performance reasons, use of this function should be integrated with an event loop, monitoring the
515     /// file descriptor retrieved by [`Backend::poll_fd`] and only calling this method when messages are
516     /// available.
dispatch_all_clients(&mut self, data: &mut D) -> std::io::Result<usize>517     pub fn dispatch_all_clients(&mut self, data: &mut D) -> std::io::Result<usize> {
518         let display = self.handle.display;
519         let pointers = (&mut self.handle as *mut _ as *mut c_void, data as *mut _ as *mut c_void);
520         let ret = HANDLE.set(&pointers, || unsafe {
521             let evl_ptr = ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_display_get_event_loop, display);
522             ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_event_loop_dispatch, evl_ptr, 0)
523         });
524 
525         for (object, client_id, object_id) in self.handle.pending_destructors.drain(..) {
526             object.destroyed(data, client_id, object_id);
527         }
528 
529         if ret < 0 {
530             Err(std::io::Error::last_os_error())
531         } else {
532             Ok(ret as usize)
533         }
534     }
535 
536     /// Access the underlying `*mut wl_display` pointer
display_ptr(&self) -> *mut wl_display537     pub fn display_ptr(&self) -> *mut wl_display {
538         self.handle.display
539     }
540 }
541 
542 impl<D> Handle<D> {
543     /// Returns information about some object.
object_info(&self, id: ObjectId) -> Result<ObjectInfo, InvalidId>544     pub fn object_info(&self, id: ObjectId) -> Result<ObjectInfo, InvalidId> {
545         if !id.alive.as_ref().map(|alive| alive.load(Ordering::Acquire)).unwrap_or(true) {
546             return Err(InvalidId);
547         }
548 
549         let version =
550             unsafe { ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_get_version, id.ptr) } as u32;
551 
552         Ok(ObjectInfo { id: id.id, version, interface: id.interface })
553     }
554 
555     /// Returns the id of the client which owns the object.
get_client(&self, id: ObjectId) -> Result<ClientId, InvalidId>556     pub fn get_client(&self, id: ObjectId) -> Result<ClientId, InvalidId> {
557         if !id.alive.map(|alive| alive.load(Ordering::Acquire)).unwrap_or(true) {
558             return Err(InvalidId);
559         }
560 
561         unsafe {
562             let client_ptr = ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_get_client, id.ptr);
563             client_id_from_ptr::<D>(client_ptr).ok_or(InvalidId)
564         }
565     }
566 
567     /// Returns the data associated with a client.
get_client_data(&self, id: ClientId) -> Result<Arc<dyn ClientData<D>>, InvalidId>568     pub fn get_client_data(&self, id: ClientId) -> Result<Arc<dyn ClientData<D>>, InvalidId> {
569         if !id.alive.load(Ordering::Acquire) {
570             return Err(InvalidId);
571         }
572 
573         let data = unsafe {
574             match client_user_data::<D>(id.ptr) {
575                 Some(ptr) => &mut *ptr,
576                 None => return Err(InvalidId),
577             }
578         };
579 
580         Ok(data.data.clone())
581     }
582 
583     /// Retrive the [`Credentials`] of a client
get_client_credentials(&self, id: ClientId) -> Result<Credentials, InvalidId>584     pub fn get_client_credentials(&self, id: ClientId) -> Result<Credentials, InvalidId> {
585         if !id.alive.load(Ordering::Acquire) {
586             return Err(InvalidId);
587         }
588 
589         let mut creds = Credentials { pid: 0, uid: 0, gid: 0 };
590 
591         unsafe {
592             ffi_dispatch!(
593                 WAYLAND_SERVER_HANDLE,
594                 wl_client_get_credentials,
595                 id.ptr,
596                 &mut creds.pid,
597                 &mut creds.uid,
598                 &mut creds.gid
599             );
600         }
601 
602         Ok(creds)
603     }
604 
605     /// Returns an iterator over all clients connected to the server.
all_clients<'a>(&'a self) -> Box<dyn Iterator<Item = ClientId> + 'a>606     pub fn all_clients<'a>(&'a self) -> Box<dyn Iterator<Item = ClientId> + 'a> {
607         let mut client_list = unsafe {
608             ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_display_get_client_list, self.display)
609         };
610         Box::new(std::iter::from_fn(move || {
611             if client_list.is_null() {
612                 None
613             } else {
614                 unsafe {
615                     let client =
616                         ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_client_from_link, client_list);
617                     let id = client_id_from_ptr::<D>(client);
618 
619                     let next = (*client_list).next;
620                     if client_list == next {
621                         client_list = std::ptr::null_mut();
622                     } else {
623                         client_list = next;
624                     }
625 
626                     id
627                 }
628             }
629         }))
630     }
631 
632     /// Returns an iterator over all objects owned by a client.
all_objects_for<'a>( &'a self, _client_id: ClientId, ) -> Result<Box<dyn Iterator<Item = ObjectId> + 'a>, InvalidId>633     pub fn all_objects_for<'a>(
634         &'a self,
635         _client_id: ClientId,
636     ) -> Result<Box<dyn Iterator<Item = ObjectId> + 'a>, InvalidId> {
637         todo!()
638     }
639 
640     /// Retrieve the `ObjectId` for a wayland object given its protocol numerical ID
object_for_protocol_id( &self, client_id: ClientId, interface: &'static Interface, protocol_id: u32, ) -> Result<ObjectId, InvalidId>641     pub fn object_for_protocol_id(
642         &self,
643         client_id: ClientId,
644         interface: &'static Interface,
645         protocol_id: u32,
646     ) -> Result<ObjectId, InvalidId> {
647         if !client_id.alive.load(Ordering::Acquire) {
648             return Err(InvalidId);
649         }
650         let resource = unsafe {
651             ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_client_get_object, client_id.ptr, protocol_id)
652         };
653         if resource.is_null() {
654             Err(InvalidId)
655         } else {
656             unsafe { ObjectId::from_ptr(interface, resource) }
657         }
658     }
659 
660     /// Create a new object for given client
661     ///
662     /// To ensure state coherence of the protocol, the created object should be immediately
663     /// sent as a "New ID" argument in an event to the client.
create_object( &mut self, client: ClientId, interface: &'static Interface, version: u32, data: Arc<dyn ObjectData<D>>, ) -> Result<ObjectId, InvalidId>664     pub fn create_object(
665         &mut self,
666         client: ClientId,
667         interface: &'static Interface,
668         version: u32,
669         data: Arc<dyn ObjectData<D>>,
670     ) -> Result<ObjectId, InvalidId> {
671         if !client.alive.load(Ordering::Acquire) {
672             return Err(InvalidId);
673         }
674 
675         let interface_ptr =
676             interface.c_ptr.expect("Interface without c_ptr are unsupported by the sys backend.");
677 
678         let resource = unsafe {
679             ffi_dispatch!(
680                 WAYLAND_SERVER_HANDLE,
681                 wl_resource_create,
682                 client.ptr,
683                 interface_ptr,
684                 version as i32,
685                 0
686             )
687         };
688 
689         Ok(unsafe { init_resource(resource, interface, Some(data)).0 })
690     }
691 
692     /// Returns an object id that represents a null object.
null_id(&mut self) -> ObjectId693     pub fn null_id(&mut self) -> ObjectId {
694         ObjectId { ptr: std::ptr::null_mut(), id: 0, alive: None, interface: &ANONYMOUS_INTERFACE }
695     }
696 
697     /// Send an event to the client
698     ///
699     /// Returns an error if the sender ID of the provided message is no longer valid.
700     ///
701     /// **Panic:**
702     ///
703     /// Checks against the protocol specification are done, and this method will panic if they do
704     /// not pass:
705     ///
706     /// - the message opcode must be valid for the sender interface
707     /// - the argument list must match the prototype for the message associated with this opcode
708     pub fn send_event(
709         &mut self,
710         Message { sender_id: id, opcode, args }: Message<ObjectId>,
711     ) -> Result<(), InvalidId> {
712         if !id.alive.as_ref().map(|a| a.load(Ordering::Acquire)).unwrap_or(true) || id.ptr.is_null()
713         {
714             return Err(InvalidId);
715         }
716 
717         // check that the argument list is valid
718         let message_desc = match id.interface.events.get(opcode as usize) {
719             Some(msg) => msg,
720             None => {
721                 panic!("Unknown opcode {} for object {}@{}.", opcode, id.interface.name, id.id);
722             }
723         };
724         if !check_for_signature(message_desc.signature, &args) {
725             panic!(
726                 "Unexpected signature for request {}@{}.{}: expected {:?}, got {:?}.",
727                 id.interface.name, id.id, message_desc.name, message_desc.signature, args
728             );
729         }
730 
731         let mut argument_list = SmallVec::<[wl_argument; 4]>::with_capacity(args.len());
732         let mut arg_interfaces = message_desc.arg_interfaces.iter();
733         for (i, arg) in args.iter().enumerate() {
734             match *arg {
735                 Argument::Uint(u) => argument_list.push(wl_argument { u }),
736                 Argument::Int(i) => argument_list.push(wl_argument { i }),
737                 Argument::Fixed(f) => argument_list.push(wl_argument { f }),
738                 Argument::Fd(h) => argument_list.push(wl_argument { h }),
739                 Argument::Array(ref a) => {
740                     let a = Box::new(wl_array {
741                         size: a.len(),
742                         alloc: a.len(),
743                         data: a.as_ptr() as *mut _,
744                     });
745                     argument_list.push(wl_argument { a: Box::into_raw(a) })
746                 }
747                 Argument::Str(ref s) => argument_list.push(wl_argument { s: s.as_ptr() }),
748                 Argument::Object(ref o) => {
749                     if !o.ptr.is_null() {
750                         if !id.alive.as_ref().map(|a| a.load(Ordering::Acquire)).unwrap_or(true) {
751                             unsafe { free_arrays(message_desc.signature, &argument_list) };
752                             return Err(InvalidId);
753                         }
754                         // check that the object belongs to the right client
755                         if self.get_client(id.clone()).unwrap().ptr
756                             != self.get_client(o.clone()).unwrap().ptr
757                         {
758                             panic!("Attempting to send an event with objects from wrong client.");
759                         }
760                         let next_interface = arg_interfaces.next().unwrap();
761                         if !same_interface(next_interface, o.interface) {
762                             panic!("Event {}@{}.{} expects an argument of interface {} but {} was provided instead.", id.interface.name, id.id, message_desc.name, next_interface.name, o.interface.name);
763                         }
764                     } else if !matches!(
765                         message_desc.signature[i],
766                         ArgumentType::Object(AllowNull::Yes)
767                     ) {
768                         panic!(
769                             "Event {}@{}.{} expects an non-null object argument.",
770                             id.interface.name, id.id, message_desc.name
771                         );
772                     }
773                     argument_list.push(wl_argument { o: o.ptr as *const _ })
774                 }
775                 Argument::NewId(ref o) => {
776                     if !o.ptr.is_null() {
777                         if !id.alive.as_ref().map(|a| a.load(Ordering::Acquire)).unwrap_or(true) {
778                             unsafe { free_arrays(message_desc.signature, &argument_list) };
779                             return Err(InvalidId);
780                         }
781                         // check that the object belongs to the right client
782                         if self.get_client(id.clone()).unwrap().ptr
783                             != self.get_client(o.clone()).unwrap().ptr
784                         {
785                             panic!("Attempting to send an event with objects from wrong client.");
786                         }
787                         let child_interface = match message_desc.child_interface {
788                             Some(iface) => iface,
789                             None => panic!("Trying to send event {}@{}.{} which creates an object without specifying its interface, this is unsupported.", id.interface.name, id.id, message_desc.name),
790                         };
791                         if !same_interface(child_interface, o.interface) {
792                             panic!("Event {}@{}.{} expects an argument of interface {} but {} was provided instead.", id.interface.name, id.id, message_desc.name, child_interface.name, o.interface.name);
793                         }
794                     } else if !matches!(
795                         message_desc.signature[i],
796                         ArgumentType::NewId(AllowNull::Yes)
797                     ) {
798                         panic!(
799                             "Event {}@{}.{} expects an non-null object argument.",
800                             id.interface.name, id.id, message_desc.name
801                         );
802                     }
803                     argument_list.push(wl_argument { o: o.ptr as *const _ })
804                 }
805             }
806         }
807 
808         unsafe {
809             ffi_dispatch!(
810                 WAYLAND_SERVER_HANDLE,
811                 wl_resource_post_event_array,
812                 id.ptr,
813                 opcode as u32,
814                 argument_list.as_mut_ptr()
815             );
816         }
817 
818         unsafe {
819             free_arrays(message_desc.signature, &argument_list);
820         }
821 
822         if message_desc.is_destructor {
823             // wl_resource_destroy invokes a destructor
824             PENDING_DESTRUCTORS.set(
825                 &(&mut self.pending_destructors as *mut _ as *mut _),
826                 || unsafe {
827                     ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_destroy, id.ptr);
828                 },
829             );
830         }
831 
832         Ok(())
833     }
834 
835     /// Returns the data associated with an object.
get_object_data(&self, id: ObjectId) -> Result<Arc<dyn ObjectData<D>>, InvalidId>836     pub fn get_object_data(&self, id: ObjectId) -> Result<Arc<dyn ObjectData<D>>, InvalidId> {
837         if !id.alive.as_ref().map(|alive| alive.load(Ordering::Acquire)).unwrap_or(false) {
838             return Err(InvalidId);
839         }
840 
841         let udata = unsafe {
842             &*(ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_get_user_data, id.ptr)
843                 as *mut ResourceUserData<D>)
844         };
845 
846         Ok(udata.data.clone())
847     }
848 
849     /// Sets the data associated with some object.
set_object_data( &mut self, id: ObjectId, data: Arc<dyn ObjectData<D>>, ) -> Result<(), InvalidId>850     pub fn set_object_data(
851         &mut self,
852         id: ObjectId,
853         data: Arc<dyn ObjectData<D>>,
854     ) -> Result<(), InvalidId> {
855         if !id.alive.as_ref().map(|alive| alive.load(Ordering::Acquire)).unwrap_or(false) {
856             return Err(InvalidId);
857         }
858 
859         let udata = unsafe {
860             &mut *(ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_get_user_data, id.ptr)
861                 as *mut ResourceUserData<D>)
862         };
863 
864         udata.data = data;
865 
866         Ok(())
867     }
868 
869     /// Posts an error on an object. This will also disconnect the client which created the object.
post_error(&mut self, id: ObjectId, error_code: u32, message: CString)870     pub fn post_error(&mut self, id: ObjectId, error_code: u32, message: CString) {
871         if !id.alive.as_ref().map(|alive| alive.load(Ordering::Acquire)).unwrap_or(true) {
872             return;
873         }
874 
875         unsafe {
876             ffi_dispatch!(
877                 WAYLAND_SERVER_HANDLE,
878                 wl_resource_post_error,
879                 id.ptr,
880                 error_code,
881                 message.as_ptr()
882             )
883         }
884     }
885 
886     /// Kills the connection to a client.
887     ///
888     /// The disconnection reason determines the error message that is sent to the client (if any).
kill_client(&mut self, client_id: ClientId, reason: DisconnectReason)889     pub fn kill_client(&mut self, client_id: ClientId, reason: DisconnectReason) {
890         if !client_id.alive.load(Ordering::Acquire) {
891             return;
892         }
893         if let Some(udata) = unsafe { client_user_data::<D>(client_id.ptr) } {
894             let udata = unsafe { &*udata };
895             udata.alive.store(false, Ordering::Release);
896             udata.data.disconnected(client_id.clone(), reason);
897         }
898 
899         unsafe {
900             ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_client_destroy, client_id.ptr);
901         }
902     }
903 
904     /// Creates a global of the specified interface and version and then advertises it to clients.
905     ///
906     /// The clients which the global is advertised to is determined by the implementation of the [`GlobalHandler`].
create_global( &mut self, interface: &'static Interface, version: u32, handler: Arc<dyn GlobalHandler<D>>, ) -> GlobalId907     pub fn create_global(
908         &mut self,
909         interface: &'static Interface,
910         version: u32,
911         handler: Arc<dyn GlobalHandler<D>>,
912     ) -> GlobalId {
913         let alive = Arc::new(AtomicBool::new(true));
914 
915         let interface_ptr =
916             interface.c_ptr.expect("Interface without c_ptr are unsupported by the sys backend.");
917 
918         let udata = Box::into_raw(Box::new(GlobalUserData {
919             handler,
920             alive: alive.clone(),
921             interface,
922             version,
923             disabled: false,
924             ptr: std::ptr::null_mut(),
925         }));
926 
927         let ret = unsafe {
928             ffi_dispatch!(
929                 WAYLAND_SERVER_HANDLE,
930                 wl_global_create,
931                 self.display,
932                 interface_ptr,
933                 version as i32,
934                 udata as *mut c_void,
935                 global_bind::<D>
936             )
937         };
938 
939         if ret.is_null() {
940             panic!(
941                 "[wayland-backend-sys] Invalid global specification or memory allocation failure."
942             );
943         }
944 
945         unsafe {
946             (*udata).ptr = ret;
947         }
948 
949         GlobalId { ptr: ret, alive }
950     }
951 
952     /// Disables a global object that is currently active.
953     ///
954     /// The global removal will be signaled to all currently connected clients. New clients will not know of the global,
955     /// but the associated state and callbacks will not be freed. As such, clients that still try to bind the global
956     /// afterwards (because they have not yet realized it was removed) will succeed.
disable_global(&mut self, id: GlobalId)957     pub fn disable_global(&mut self, id: GlobalId) {
958         if !id.alive.load(Ordering::Acquire) {
959             return;
960         }
961 
962         let udata = unsafe {
963             &mut *(ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_global_get_user_data, id.ptr)
964                 as *mut GlobalUserData<D>)
965         };
966         udata.disabled = true;
967 
968         unsafe {
969             ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_global_remove, id.ptr);
970         }
971     }
972 
973     /// Removes a global object and free its resources.
974     ///
975     /// The global object will no longer be considered valid by the server, clients trying to bind it will be killed,
976     /// and the global ID is freed for re-use.
977     ///
978     /// It is advised to first disable a global and wait some amount of time before removing it, to ensure all clients
979     /// are correctly aware of its removal. Note that clients will generally not expect globals that represent a capability
980     /// of the server to be removed, as opposed to globals representing peripherals (like `wl_output` or `wl_seat`).
remove_global(&mut self, id: GlobalId)981     pub fn remove_global(&mut self, id: GlobalId) {
982         if !id.alive.load(Ordering::Acquire) {
983             return;
984         }
985 
986         let udata = unsafe {
987             Box::from_raw(ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_global_get_user_data, id.ptr)
988                 as *mut GlobalUserData<D>)
989         };
990         udata.alive.store(false, Ordering::Release);
991 
992         unsafe {
993             ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_global_destroy, id.ptr);
994         }
995     }
996 
997     /// Returns information about a global.
global_info(&self, id: GlobalId) -> Result<GlobalInfo, InvalidId>998     pub fn global_info(&self, id: GlobalId) -> Result<GlobalInfo, InvalidId> {
999         if !id.alive.load(Ordering::Acquire) {
1000             return Err(InvalidId);
1001         }
1002         let udata = unsafe {
1003             &*(ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_global_get_user_data, id.ptr)
1004                 as *mut GlobalUserData<D>)
1005         };
1006 
1007         Ok(GlobalInfo {
1008             interface: udata.interface,
1009             version: udata.version,
1010             disabled: udata.disabled,
1011         })
1012     }
1013 
1014     /// Returns the handler which manages the visibility and notifies when a client has bound the global.
get_global_handler(&self, id: GlobalId) -> Result<Arc<dyn GlobalHandler<D>>, InvalidId>1015     pub fn get_global_handler(&self, id: GlobalId) -> Result<Arc<dyn GlobalHandler<D>>, InvalidId> {
1016         if !id.alive.load(Ordering::Acquire) {
1017             return Err(InvalidId);
1018         }
1019 
1020         let udata = unsafe {
1021             Box::from_raw(ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_global_get_user_data, id.ptr)
1022                 as *mut GlobalUserData<D>)
1023         };
1024         Ok(udata.handler.clone())
1025     }
1026 }
1027 
init_client<D>(client: *mut wl_client, data: Arc<dyn ClientData<D>>) -> ClientId1028 unsafe fn init_client<D>(client: *mut wl_client, data: Arc<dyn ClientData<D>>) -> ClientId {
1029     let alive = Arc::new(AtomicBool::new(true));
1030     let client_data = Box::into_raw(Box::new(ClientUserData { alive: alive.clone(), data }));
1031 
1032     let listener = signal::rust_listener_create(client_destroy_notify::<D>);
1033     signal::rust_listener_set_user_data(listener, client_data as *mut c_void);
1034 
1035     ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_client_add_destroy_listener, client, listener);
1036 
1037     ClientId { ptr: client, alive }
1038 }
1039 
client_id_from_ptr<D>(client: *mut wl_client) -> Option<ClientId>1040 unsafe fn client_id_from_ptr<D>(client: *mut wl_client) -> Option<ClientId> {
1041     client_user_data::<D>(client)
1042         .map(|udata| ClientId { ptr: client, alive: (*udata).alive.clone() })
1043 }
1044 
client_user_data<D>(client: *mut wl_client) -> Option<*mut ClientUserData<D>>1045 unsafe fn client_user_data<D>(client: *mut wl_client) -> Option<*mut ClientUserData<D>> {
1046     if client.is_null() {
1047         return None;
1048     }
1049     let listener = ffi_dispatch!(
1050         WAYLAND_SERVER_HANDLE,
1051         wl_client_get_destroy_listener,
1052         client,
1053         client_destroy_notify::<D>
1054     );
1055     if !listener.is_null() {
1056         Some(signal::rust_listener_get_user_data(listener) as *mut ClientUserData<D>)
1057     } else {
1058         None
1059     }
1060 }
1061 
client_destroy_notify<D>(listener: *mut wl_listener, client_ptr: *mut c_void)1062 unsafe extern "C" fn client_destroy_notify<D>(listener: *mut wl_listener, client_ptr: *mut c_void) {
1063     let data =
1064         Box::from_raw(signal::rust_listener_get_user_data(listener) as *mut ClientUserData<D>);
1065     signal::rust_listener_destroy(listener);
1066     // only notify the killing if it was not already
1067     if data.alive.load(Ordering::Acquire) {
1068         data.alive.store(false, Ordering::Release);
1069         data.data.disconnected(
1070             ClientId { ptr: client_ptr as *mut wl_client, alive: data.alive.clone() },
1071             DisconnectReason::ConnectionClosed,
1072         );
1073     }
1074 }
1075 
global_bind<D>( client: *mut wl_client, data: *mut c_void, version: u32, id: u32, )1076 unsafe extern "C" fn global_bind<D>(
1077     client: *mut wl_client,
1078     data: *mut c_void,
1079     version: u32,
1080     id: u32,
1081 ) {
1082     let global_udata = &mut *(data as *mut GlobalUserData<D>);
1083 
1084     let global_id = GlobalId { alive: global_udata.alive.clone(), ptr: global_udata.ptr };
1085 
1086     let client_id = match client_id_from_ptr::<D>(client) {
1087         Some(id) => id,
1088         None => return,
1089     };
1090 
1091     // this must be Some(), checked at creation of the global
1092     let interface_ptr = global_udata.interface.c_ptr.unwrap();
1093 
1094     HANDLE.with(|&(handle_ptr, data_ptr)| {
1095         let handle = &mut *(handle_ptr as *mut Handle<D>);
1096         let data = &mut *(data_ptr as *mut D);
1097         // create the object
1098         let resource = ffi_dispatch!(
1099             WAYLAND_SERVER_HANDLE,
1100             wl_resource_create,
1101             client,
1102             interface_ptr,
1103             version as i32,
1104             id
1105         );
1106         let (object_id, udata) = init_resource(resource, global_udata.interface, None);
1107         let obj_data =
1108             global_udata.handler.clone().bind(handle, data, client_id, global_id, object_id);
1109         (*udata).data = obj_data;
1110     })
1111 }
1112 
global_filter<D>( client: *const wl_client, global: *const wl_global, _: *mut c_void, ) -> bool1113 unsafe extern "C" fn global_filter<D>(
1114     client: *const wl_client,
1115     global: *const wl_global,
1116     _: *mut c_void,
1117 ) -> bool {
1118     let client_udata = match client_user_data::<D>(client as *mut _) {
1119         Some(id) => &*id,
1120         None => return false,
1121     };
1122 
1123     let client_id = ClientId { ptr: client as *mut _, alive: client_udata.alive.clone() };
1124 
1125     let global_udata = &*(ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_global_get_user_data, global)
1126         as *mut GlobalUserData<D>);
1127 
1128     let global_id = GlobalId { ptr: global as *mut wl_global, alive: global_udata.alive.clone() };
1129 
1130     global_udata.handler.can_view(client_id, &client_udata.data, global_id)
1131 }
1132 
init_resource<D>( resource: *mut wl_resource, interface: &'static Interface, data: Option<Arc<dyn ObjectData<D>>>, ) -> (ObjectId, *mut ResourceUserData<D>)1133 unsafe fn init_resource<D>(
1134     resource: *mut wl_resource,
1135     interface: &'static Interface,
1136     data: Option<Arc<dyn ObjectData<D>>>,
1137 ) -> (ObjectId, *mut ResourceUserData<D>) {
1138     let alive = Arc::new(AtomicBool::new(true));
1139     let udata = Box::into_raw(Box::new(ResourceUserData {
1140         data: data.unwrap_or_else(|| Arc::new(UninitObjectData)),
1141         interface,
1142         alive: alive.clone(),
1143     }));
1144     let id = ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_get_id, resource);
1145 
1146     ffi_dispatch!(
1147         WAYLAND_SERVER_HANDLE,
1148         wl_resource_set_dispatcher,
1149         resource,
1150         resource_dispatcher::<D>,
1151         &RUST_MANAGED as *const u8 as *const c_void,
1152         udata as *mut c_void,
1153         Some(resource_destructor::<D>)
1154     );
1155 
1156     (ObjectId { interface, alive: Some(alive), id, ptr: resource }, udata)
1157 }
1158 
resource_dispatcher<D>( _: *const c_void, resource: *mut c_void, opcode: u32, _: *const wl_message, args: *const wl_argument, ) -> i321159 unsafe extern "C" fn resource_dispatcher<D>(
1160     _: *const c_void,
1161     resource: *mut c_void,
1162     opcode: u32,
1163     _: *const wl_message,
1164     args: *const wl_argument,
1165 ) -> i32 {
1166     let resource = resource as *mut wl_resource;
1167     let udata_ptr = ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_get_user_data, resource)
1168         as *mut ResourceUserData<D>;
1169     let udata = &mut *udata_ptr;
1170     let client = ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_get_client, resource);
1171     let resource_id = ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_get_id, resource);
1172     let version = ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_get_version, resource);
1173     let interface = udata.interface;
1174     let message_desc = match interface.requests.get(opcode as usize) {
1175         Some(desc) => desc,
1176         None => {
1177             log::error!("Unknown event opcode {} for interface {}.", opcode, interface.name);
1178             return -1;
1179         }
1180     };
1181 
1182     let mut parsed_args =
1183         SmallVec::<[Argument<ObjectId>; 4]>::with_capacity(message_desc.signature.len());
1184     let mut arg_interfaces = message_desc.arg_interfaces.iter().copied();
1185     let mut created = None;
1186     for (i, typ) in message_desc.signature.iter().enumerate() {
1187         match typ {
1188             ArgumentType::Uint => parsed_args.push(Argument::Uint((*args.add(i)).u)),
1189             ArgumentType::Int => parsed_args.push(Argument::Int((*args.add(i)).i)),
1190             ArgumentType::Fixed => parsed_args.push(Argument::Fixed((*args.add(i)).f)),
1191             ArgumentType::Fd => parsed_args.push(Argument::Fd((*args.add(i)).h)),
1192             ArgumentType::Array(_) => {
1193                 let array = &*((*args.add(i)).a);
1194                 let content = std::slice::from_raw_parts(array.data as *mut u8, array.size);
1195                 parsed_args.push(Argument::Array(Box::new(content.into())));
1196             }
1197             ArgumentType::Str(_) => {
1198                 let ptr = (*args.add(i)).s;
1199                 let cstr = std::ffi::CStr::from_ptr(ptr);
1200                 parsed_args.push(Argument::Str(Box::new(cstr.into())));
1201             }
1202             ArgumentType::Object(_) => {
1203                 let obj = (*args.add(i)).o as *mut wl_resource;
1204                 if !obj.is_null() {
1205                     // retrieve the object relevant info
1206                     let obj_id = ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_get_id, obj);
1207                     // check if this is a local or distant proxy
1208                     let next_interface = arg_interfaces.next().unwrap_or(&ANONYMOUS_INTERFACE);
1209                     let ret = ffi_dispatch!(
1210                         WAYLAND_SERVER_HANDLE,
1211                         wl_resource_instance_of,
1212                         obj,
1213                         next_interface.c_ptr.unwrap(),
1214                         &RUST_MANAGED as *const u8 as *const c_void
1215                     );
1216                     if ret == 0 {
1217                         // distant
1218                         parsed_args.push(Argument::Object(ObjectId {
1219                             alive: None,
1220                             id: obj_id,
1221                             ptr: obj,
1222                             interface: next_interface,
1223                         }));
1224                     } else {
1225                         // local
1226                         let obj_udata = &mut *(ffi_dispatch!(
1227                             WAYLAND_SERVER_HANDLE,
1228                             wl_resource_get_user_data,
1229                             obj
1230                         )
1231                             as *mut ResourceUserData<D>);
1232                         parsed_args.push(Argument::Object(ObjectId {
1233                             alive: Some(obj_udata.alive.clone()),
1234                             ptr: obj,
1235                             id: obj_id,
1236                             interface: obj_udata.interface,
1237                         }));
1238                     }
1239                 } else {
1240                     // libwayland-server.so checks nulls for us
1241                     parsed_args.push(Argument::Object(ObjectId {
1242                         alive: None,
1243                         id: 0,
1244                         ptr: std::ptr::null_mut(),
1245                         interface: &ANONYMOUS_INTERFACE,
1246                     }))
1247                 }
1248             }
1249             ArgumentType::NewId(_) => {
1250                 let new_id = (*args.add(i)).n;
1251                 // create the object
1252                 if new_id != 0 {
1253                     let child_interface = match message_desc.child_interface {
1254                         Some(iface) => iface,
1255                         None => panic!("Received request {}@{}.{} which creates an object without specifying its interface, this is unsupported.", udata.interface.name, resource_id, message_desc.name),
1256                     };
1257                     let (child_id, child_data_ptr) = HANDLE.with(|&(_handle_ptr, _)| {
1258                         // create the object
1259                         let resource = ffi_dispatch!(
1260                             WAYLAND_SERVER_HANDLE,
1261                             wl_resource_create,
1262                             client,
1263                             child_interface.c_ptr.unwrap(),
1264                             version,
1265                             new_id
1266                         );
1267                         init_resource::<D>(resource, child_interface, None)
1268                     });
1269                     created = Some((child_id.clone(), child_data_ptr));
1270                     parsed_args.push(Argument::NewId(child_id));
1271                 } else {
1272                     parsed_args.push(Argument::NewId(ObjectId {
1273                         alive: None,
1274                         id: 0,
1275                         ptr: std::ptr::null_mut(),
1276                         interface: &ANONYMOUS_INTERFACE,
1277                     }))
1278                 }
1279             }
1280         }
1281     }
1282 
1283     let object_id = ObjectId {
1284         ptr: resource,
1285         id: resource_id,
1286         interface: udata.interface,
1287         alive: Some(udata.alive.clone()),
1288     };
1289 
1290     let client_id = client_id_from_ptr::<D>(client).unwrap();
1291 
1292     let ret = HANDLE.with(|&(handle_ptr, data_ptr)| {
1293         let handle = &mut *(handle_ptr as *mut Handle<D>);
1294         let data = &mut *(data_ptr as *mut D);
1295         udata.data.clone().request(
1296             handle,
1297             data,
1298             client_id.clone(),
1299             Message { sender_id: object_id.clone(), opcode: opcode as u16, args: parsed_args },
1300         )
1301     });
1302 
1303     if message_desc.is_destructor {
1304         ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_destroy, resource);
1305     }
1306 
1307     match (created, ret) {
1308         (Some((_, child_udata_ptr)), Some(child_data)) => {
1309             (*child_udata_ptr).data = child_data;
1310         }
1311         (Some((child_id, _)), None) => {
1312             panic!("Callback creating object {} did not provide any object data.", child_id);
1313         }
1314         (None, Some(_)) => {
1315             panic!("An object data was returned from a callback not creating any object");
1316         }
1317         (None, None) => {}
1318     }
1319 
1320     0
1321 }
1322 
resource_destructor<D>(resource: *mut wl_resource)1323 unsafe extern "C" fn resource_destructor<D>(resource: *mut wl_resource) {
1324     let udata =
1325         Box::from_raw(ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_get_user_data, resource)
1326             as *mut ResourceUserData<D>);
1327     let id = ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_get_id, resource);
1328     let client = ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_get_client, resource);
1329     // if this destructor is invoked during cleanup, the client ptr is no longer valid
1330     let client_id = client_id_from_ptr::<D>(client)
1331         .unwrap_or(ClientId { ptr: std::ptr::null_mut(), alive: Arc::new(AtomicBool::new(false)) });
1332     udata.alive.store(false, Ordering::Release);
1333     let object_id = ObjectId {
1334         interface: udata.interface,
1335         ptr: resource,
1336         alive: Some(udata.alive.clone()),
1337         id,
1338     };
1339     if HANDLE.is_set() {
1340         HANDLE.with(|&(_, data_ptr)| {
1341             let data = &mut *(data_ptr as *mut D);
1342             udata.data.destroyed(data, client_id, object_id);
1343         });
1344     } else {
1345         PENDING_DESTRUCTORS.with(|&pending_ptr| {
1346             let pending = &mut *(pending_ptr as *mut Vec<PendingDestructor<D>>);
1347             pending.push((udata.data.clone(), client_id, object_id));
1348         })
1349     }
1350 }
1351 
1352 extern "C" {
wl_log_trampoline_to_rust_server(fmt: *const c_char, list: *const c_void)1353     fn wl_log_trampoline_to_rust_server(fmt: *const c_char, list: *const c_void);
1354 }
1355 
1356 struct UninitObjectData;
1357 
1358 impl<D> ObjectData<D> for UninitObjectData {
request( self: Arc<Self>, _: &mut Handle<D>, _: &mut D, _: ClientId, msg: Message<ObjectId>, ) -> Option<Arc<dyn ObjectData<D>>>1359     fn request(
1360         self: Arc<Self>,
1361         _: &mut Handle<D>,
1362         _: &mut D,
1363         _: ClientId,
1364         msg: Message<ObjectId>,
1365     ) -> Option<Arc<dyn ObjectData<D>>> {
1366         panic!("Received a message on an uninitialized object: {:?}", msg);
1367     }
1368 
destroyed(&self, _: &mut D, _: ClientId, _: ObjectId)1369     fn destroyed(&self, _: &mut D, _: ClientId, _: ObjectId) {}
1370 
debug(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result1371     fn debug(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1372         f.debug_struct("UninitObjectData").finish()
1373     }
1374 }
1375