wayland_backend/sys/server_impl/
mod.rs

1//! Server-side implementation of a Wayland protocol backend using `libwayland`
2
3use std::{
4    ffi::{CStr, CString},
5    os::raw::{c_int, c_void},
6    os::unix::{
7        io::{BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd},
8        net::UnixStream,
9    },
10    sync::{
11        atomic::{AtomicBool, Ordering},
12        Arc, Mutex, Weak,
13    },
14};
15
16use crate::protocol::{
17    check_for_signature, same_interface, AllowNull, Argument, ArgumentType, Interface, Message,
18    ObjectInfo, ANONYMOUS_INTERFACE,
19};
20use scoped_tls::scoped_thread_local;
21use smallvec::SmallVec;
22
23use wayland_sys::{common::*, ffi_dispatch, server::*};
24
25use super::{free_arrays, server::*, RUST_MANAGED};
26
27#[allow(unused_imports)]
28pub use crate::types::server::{Credentials, DisconnectReason, GlobalInfo, InitError, InvalidId};
29
30scoped_thread_local! {
31    // scoped_tls does not allow unsafe_op_in_unsafe_fn internally
32    #[allow(unsafe_op_in_unsafe_fn)]
33    static HANDLE: (Arc<Mutex<dyn ErasedState + Send>>, *mut c_void)
34}
35
36type PendingDestructor<D> = (Arc<dyn ObjectData<D>>, ClientId, ObjectId);
37
38// Pointer is &mut Vec<PendingDestructor<D>>
39scoped_thread_local! {
40    // scoped_tls does not allow unsafe_op_in_unsafe_fn internally
41    #[allow(unsafe_op_in_unsafe_fn)]
42    static PENDING_DESTRUCTORS: *mut c_void
43}
44
45/// An id of an object on a wayland server.
46#[derive(Clone)]
47pub struct InnerObjectId {
48    id: u32,
49    ptr: *mut wl_resource,
50    alive: Arc<AtomicBool>,
51    interface: &'static Interface,
52}
53
54unsafe impl Send for InnerObjectId {}
55unsafe impl Sync for InnerObjectId {}
56
57impl std::cmp::PartialEq for InnerObjectId {
58    fn eq(&self, other: &Self) -> bool {
59        Arc::ptr_eq(&self.alive, &other.alive)
60    }
61}
62
63impl std::cmp::Eq for InnerObjectId {}
64
65impl std::hash::Hash for InnerObjectId {
66    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
67        self.id.hash(state);
68        self.ptr.hash(state);
69        (&*self.alive as *const AtomicBool).hash(state);
70    }
71}
72
73impl std::fmt::Display for InnerObjectId {
74    #[cfg_attr(coverage, coverage(off))]
75    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
76        write!(f, "{}@{}", self.interface.name, self.id)
77    }
78}
79
80impl std::fmt::Debug for InnerObjectId {
81    #[cfg_attr(coverage, coverage(off))]
82    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
83        write!(f, "ObjectId({})", self)
84    }
85}
86
87impl InnerObjectId {
88    pub fn is_null(&self) -> bool {
89        self.ptr.is_null()
90    }
91
92    pub fn interface(&self) -> &'static Interface {
93        self.interface
94    }
95
96    pub fn same_client_as(&self, other: &Self) -> bool {
97        if !self.alive.load(Ordering::Acquire) || !other.alive.load(Ordering::Acquire) {
98            return false;
99        }
100        let my_client_ptr =
101            unsafe { ffi_dispatch!(wayland_server_handle(), wl_resource_get_client, self.ptr) };
102        let other_client_ptr =
103            unsafe { ffi_dispatch!(wayland_server_handle(), wl_resource_get_client, other.ptr) };
104        my_client_ptr == other_client_ptr
105    }
106
107    pub fn protocol_id(&self) -> u32 {
108        self.id
109    }
110
111    pub unsafe fn from_ptr(
112        interface: Option<&'static Interface>,
113        ptr: *mut wl_resource,
114    ) -> Result<InnerObjectId, InvalidId> {
115        let id = ffi_dispatch!(wayland_server_handle(), wl_resource_get_id, ptr);
116
117        // This is a horrible back to work around the fact that it is not possible to check if the
118        // resource implementation is RUST_MANAGED without knowing the interface of that object...
119        let is_rust_managed = {
120            // wl_resource_instance_of uses wl_interface_equals, which only checks that the interface name
121            // is correct, so we create a temporary dummy wl_interface with the correct name so that the
122            // check only actually verifies that the object is RUST_MANAGED
123            let iface_name = ffi_dispatch!(wayland_server_handle(), wl_resource_get_class, ptr);
124            let dummy_iface = wl_interface {
125                name: iface_name,
126                version: 0,
127                request_count: 0,
128                event_count: 0,
129                requests: std::ptr::null(),
130                events: std::ptr::null(),
131            };
132            ffi_dispatch!(
133                wayland_server_handle(),
134                wl_resource_instance_of,
135                ptr,
136                &dummy_iface,
137                &RUST_MANAGED as *const u8 as *const _
138            ) != 0
139        };
140
141        if is_rust_managed {
142            // Using () instead of the type parameter here is safe, because:
143            // 1) ResourceUserData is #[repr(C)], so its layout does not depend on D
144            // 2) we are only accessing the field `.alive`, which type is independent of D
145            //
146            let udata = ffi_dispatch!(wayland_server_handle(), wl_resource_get_user_data, ptr)
147                as *mut ResourceUserData<()>;
148            let alive = unsafe { (*udata).alive.clone() };
149            let udata_iface = unsafe { (*udata).interface };
150            if let Some(iface) = interface {
151                if !same_interface(iface, udata_iface) {
152                    return Err(InvalidId);
153                }
154            }
155            Ok(InnerObjectId { id, ptr, alive, interface: udata_iface })
156        } else if let Some(interface) = interface {
157            let iface_c_ptr =
158                interface.c_ptr.expect("[wayland-backend-sys] Cannot use Interface without c_ptr!");
159            // Safety: the provided pointer must be a valid wayland object
160            let ptr_iface_name = unsafe {
161                CStr::from_ptr(ffi_dispatch!(wayland_server_handle(), wl_resource_get_class, ptr))
162            };
163            // Safety: the code generated by wayland-scanner is valid
164            let provided_iface_name = unsafe { CStr::from_ptr(iface_c_ptr.name) };
165            if ptr_iface_name != provided_iface_name {
166                return Err(InvalidId);
167            }
168            // On external resource, we use the wl_resource_add_destroy_listener mechanism to track their liveness
169            let listener = ffi_dispatch!(
170                wayland_server_handle(),
171                wl_resource_get_destroy_listener,
172                ptr,
173                external_resource_destroy_notify
174            );
175            let alive = if listener.is_null() {
176                // The listener needs to be initialized
177                let alive = Arc::new(AtomicBool::new(true));
178                let data = Box::into_raw(Box::new(ExternalResourceData { alive: alive.clone() }));
179                let listener = signal::rust_listener_create(external_resource_destroy_notify);
180                // Safety: we just created listener and client_data, they are valid
181                unsafe {
182                    signal::rust_listener_set_user_data(listener, data as *mut c_void);
183                }
184                ffi_dispatch!(
185                    wayland_server_handle(),
186                    wl_resource_add_destroy_listener,
187                    ptr,
188                    listener
189                );
190                alive
191            } else {
192                unsafe {
193                    let data =
194                        signal::rust_listener_get_user_data(listener) as *mut ExternalResourceData;
195                    (*data).alive.clone()
196                }
197            };
198            Ok(InnerObjectId { id, ptr, alive, interface })
199        } else {
200            Err(InvalidId)
201        }
202    }
203
204    pub fn as_ptr(&self) -> *mut wl_resource {
205        if self.alive.load(Ordering::Acquire) {
206            self.ptr
207        } else {
208            std::ptr::null_mut()
209        }
210    }
211}
212
213struct ExternalResourceData {
214    alive: Arc<AtomicBool>,
215}
216
217unsafe extern "C" fn external_resource_destroy_notify(listener: *mut wl_listener, _: *mut c_void) {
218    // Safety: if this function is invoked by libwayland its arguments must be valid
219    let data = unsafe {
220        Box::from_raw(signal::rust_listener_get_user_data(listener) as *mut ExternalResourceData)
221    };
222    unsafe {
223        signal::rust_listener_destroy(listener);
224    }
225    data.alive.store(false, Ordering::Release);
226}
227
228/// An id of a client connected to the server.
229#[derive(Debug, Clone)]
230pub struct InnerClientId {
231    ptr: *mut wl_client,
232    alive: Arc<AtomicBool>,
233}
234
235unsafe impl Send for InnerClientId {}
236unsafe impl Sync for InnerClientId {}
237
238impl std::cmp::PartialEq for InnerClientId {
239    fn eq(&self, other: &Self) -> bool {
240        Arc::ptr_eq(&self.alive, &other.alive)
241    }
242}
243
244impl std::cmp::Eq for InnerClientId {}
245
246impl std::hash::Hash for InnerClientId {
247    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
248        (&*self.alive as *const AtomicBool).hash(state)
249    }
250}
251
252/// The ID of a global
253#[derive(Debug, Clone)]
254pub struct InnerGlobalId {
255    ptr: *mut wl_global,
256    alive: Arc<AtomicBool>,
257}
258
259unsafe impl Send for InnerGlobalId {}
260unsafe impl Sync for InnerGlobalId {}
261
262impl std::cmp::PartialEq for InnerGlobalId {
263    fn eq(&self, other: &Self) -> bool {
264        Arc::ptr_eq(&self.alive, &other.alive)
265    }
266}
267
268impl std::cmp::Eq for InnerGlobalId {}
269
270impl std::hash::Hash for InnerGlobalId {
271    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
272        (&*self.alive as *const AtomicBool).hash(state)
273    }
274}
275
276#[repr(C)]
277struct ResourceUserData<D> {
278    alive: Arc<AtomicBool>,
279    data: Arc<dyn ObjectData<D>>,
280    interface: &'static Interface,
281}
282
283struct ClientUserData {
284    data: Arc<dyn ClientData>,
285    alive: Arc<AtomicBool>,
286}
287
288struct GlobalUserData<D> {
289    handler: Arc<dyn GlobalHandler<D>>,
290    interface: &'static Interface,
291    version: u32,
292    disabled: bool,
293    alive: Arc<AtomicBool>,
294    ptr: *mut wl_global,
295}
296
297#[derive(Debug)]
298pub struct State<D: 'static> {
299    display: *mut wl_display,
300    pending_destructors: Vec<PendingDestructor<D>>,
301    timer_source: *mut wl_event_source,
302    _data: std::marker::PhantomData<fn(&mut D)>,
303    known_globals: Vec<InnerGlobalId>,
304}
305
306unsafe impl<D> Send for State<D> {}
307
308#[derive(Debug)]
309pub struct InnerBackend<D: 'static> {
310    state: Arc<Mutex<State<D>>>,
311    display_ptr: *mut wl_display,
312}
313
314unsafe impl<D> Send for InnerBackend<D> {}
315unsafe impl<D> Sync for InnerBackend<D> {}
316
317impl<D> InnerBackend<D> {
318    pub fn new() -> Result<Self, InitError> {
319        if !is_lib_available() {
320            return Err(InitError::NoWaylandLib);
321        }
322
323        let display = unsafe { ffi_dispatch!(wayland_server_handle(), wl_display_create) };
324        if display.is_null() {
325            panic!("[wayland-backend-sys] libwayland reported an allocation failure.");
326        }
327
328        #[cfg(feature = "log")]
329        unsafe {
330            ffi_dispatch!(
331                wayland_server_handle(),
332                wl_log_set_handler_server,
333                wl_log_trampoline_to_rust_server
334            )
335        };
336
337        unsafe {
338            ffi_dispatch!(
339                wayland_server_handle(),
340                wl_display_set_global_filter,
341                display,
342                global_filter::<D>,
343                std::ptr::null_mut()
344            );
345        }
346
347        // Insert a timer we can use to force wakeups of the libwayland inner event loop
348        extern "C" fn timer_noop_cb(_: *mut c_void) -> i32 {
349            0
350        }
351
352        let timer_source = unsafe {
353            let evl = ffi_dispatch!(wayland_server_handle(), wl_display_get_event_loop, display);
354
355            ffi_dispatch!(
356                wayland_server_handle(),
357                wl_event_loop_add_timer,
358                evl,
359                timer_noop_cb,
360                std::ptr::null_mut()
361            )
362        };
363
364        Ok(Self {
365            state: Arc::new(Mutex::new(State {
366                display,
367                pending_destructors: Vec::new(),
368                timer_source,
369                _data: std::marker::PhantomData,
370                known_globals: Vec::new(),
371            })),
372            display_ptr: display,
373        })
374    }
375
376    pub fn flush(&mut self, client: Option<ClientId>) -> std::io::Result<()> {
377        self.state.lock().unwrap().flush(client)
378    }
379
380    pub fn handle(&self) -> Handle {
381        Handle { handle: InnerHandle { state: self.state.clone() as Arc<_> } }
382    }
383
384    pub fn poll_fd(&self) -> BorrowedFd {
385        unsafe {
386            let evl_ptr =
387                ffi_dispatch!(wayland_server_handle(), wl_display_get_event_loop, self.display_ptr);
388            BorrowedFd::borrow_raw(ffi_dispatch!(
389                wayland_server_handle(),
390                wl_event_loop_get_fd,
391                evl_ptr
392            ))
393        }
394    }
395
396    pub fn dispatch_client(
397        &mut self,
398        data: &mut D,
399        _client_id: InnerClientId,
400    ) -> std::io::Result<usize> {
401        self.dispatch_all_clients(data)
402    }
403
404    pub fn dispatch_all_clients(&mut self, data: &mut D) -> std::io::Result<usize> {
405        let state = self.state.clone() as Arc<Mutex<dyn ErasedState + Send>>;
406        let display = self.display_ptr;
407        let ret = HANDLE.set(&(state, data as *mut _ as *mut c_void), || unsafe {
408            let evl_ptr =
409                ffi_dispatch!(wayland_server_handle(), wl_display_get_event_loop, display);
410            ffi_dispatch!(wayland_server_handle(), wl_event_loop_dispatch, evl_ptr, 0)
411        });
412
413        let pending_destructors =
414            std::mem::take(&mut self.state.lock().unwrap().pending_destructors);
415        for (object, client_id, object_id) in pending_destructors {
416            let handle = self.handle();
417            object.clone().destroyed(&handle, data, client_id, object_id);
418        }
419
420        if ret < 0 {
421            Err(std::io::Error::last_os_error())
422        } else {
423            Ok(ret as usize)
424        }
425    }
426}
427
428impl<D> Drop for State<D> {
429    fn drop(&mut self) {
430        // wl_display_destroy_clients may result in the destruction of some wayland objects. Pending
431        // destructors are queued up inside the PENDING_DESTRUCTORS scoped global. We need to set the scoped
432        // global in order for destructors to be queued up properly.
433        PENDING_DESTRUCTORS.set(&(&mut self.pending_destructors as *mut _ as *mut _), || unsafe {
434            ffi_dispatch!(wayland_server_handle(), wl_display_destroy_clients, self.display);
435        });
436
437        let known_globals = std::mem::take(&mut self.known_globals);
438        for global in known_globals {
439            unsafe {
440                let _ = Box::from_raw(ffi_dispatch!(
441                    wayland_server_handle(),
442                    wl_global_get_user_data,
443                    global.ptr
444                ) as *mut GlobalUserData<D>);
445                ffi_dispatch!(wayland_server_handle(), wl_global_destroy, global.ptr);
446            }
447        }
448
449        unsafe {
450            ffi_dispatch!(wayland_server_handle(), wl_display_destroy, self.display);
451        }
452    }
453}
454
455#[derive(Clone)]
456pub struct InnerHandle {
457    state: Arc<Mutex<dyn ErasedState + Send>>,
458}
459
460impl std::fmt::Debug for InnerHandle {
461    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
462        fmt.debug_struct("InnerHandle[sys]").finish_non_exhaustive()
463    }
464}
465
466#[derive(Clone)]
467pub struct WeakInnerHandle {
468    pub(crate) state: Weak<Mutex<dyn ErasedState + Send>>,
469}
470
471impl std::fmt::Debug for WeakInnerHandle {
472    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
473        fmt.debug_struct("WeakInnerHandle[sys]").finish_non_exhaustive()
474    }
475}
476
477impl WeakInnerHandle {
478    pub fn upgrade(&self) -> Option<InnerHandle> {
479        self.state.upgrade().map(|state| InnerHandle { state })
480    }
481}
482
483impl InnerHandle {
484    pub fn downgrade(&self) -> WeakInnerHandle {
485        WeakInnerHandle { state: Arc::downgrade(&self.state) }
486    }
487
488    pub fn object_info(&self, id: InnerObjectId) -> Result<ObjectInfo, InvalidId> {
489        self.state.lock().unwrap().object_info(id)
490    }
491
492    pub fn insert_client(
493        &self,
494        stream: UnixStream,
495        data: Arc<dyn ClientData>,
496    ) -> std::io::Result<InnerClientId> {
497        self.state.lock().unwrap().insert_client(stream, data)
498    }
499
500    pub fn get_client(&self, id: InnerObjectId) -> Result<ClientId, InvalidId> {
501        self.state.lock().unwrap().get_client(id)
502    }
503
504    pub fn get_client_data(&self, id: InnerClientId) -> Result<Arc<dyn ClientData>, InvalidId> {
505        self.state.lock().unwrap().get_client_data(id)
506    }
507
508    pub fn get_client_credentials(&self, id: InnerClientId) -> Result<Credentials, InvalidId> {
509        self.state.lock().unwrap().get_client_credentials(id)
510    }
511
512    pub fn with_all_clients(&self, mut f: impl FnMut(ClientId)) {
513        self.state.lock().unwrap().with_all_clients(&mut f)
514    }
515
516    pub fn with_all_objects_for(
517        &self,
518        client_id: InnerClientId,
519        mut f: impl FnMut(ObjectId),
520    ) -> Result<(), InvalidId> {
521        self.state.lock().unwrap().with_all_objects_for(client_id, &mut f)
522    }
523
524    pub fn object_for_protocol_id(
525        &self,
526        client_id: InnerClientId,
527        interface: &'static Interface,
528        protocol_id: u32,
529    ) -> Result<ObjectId, InvalidId> {
530        self.state.lock().unwrap().object_for_protocol_id(client_id, interface, protocol_id)
531    }
532
533    pub fn create_object<D: 'static>(
534        &self,
535        client: InnerClientId,
536        interface: &'static Interface,
537        version: u32,
538        data: Arc<dyn ObjectData<D>>,
539    ) -> Result<ObjectId, InvalidId> {
540        let mut state = self.state.lock().unwrap();
541        // Keep this guard alive while the code is run to protect the C state
542        let _state = (&mut *state as &mut dyn ErasedState)
543            .downcast_mut::<State<D>>()
544            .expect("Wrong type parameter passed to Handle::create_object().");
545
546        if !client.alive.load(Ordering::Acquire) {
547            return Err(InvalidId);
548        }
549
550        let interface_ptr =
551            interface.c_ptr.expect("Interface without c_ptr are unsupported by the sys backend.");
552
553        let resource = unsafe {
554            ffi_dispatch!(
555                wayland_server_handle(),
556                wl_resource_create,
557                client.ptr,
558                interface_ptr,
559                version as i32,
560                0
561            )
562        };
563
564        Ok(ObjectId { id: unsafe { init_resource(resource, interface, Some(data)).0 } })
565    }
566
567    pub fn null_id() -> ObjectId {
568        ObjectId {
569            id: InnerObjectId {
570                ptr: std::ptr::null_mut(),
571                id: 0,
572                alive: Arc::new(AtomicBool::new(false)),
573                interface: &ANONYMOUS_INTERFACE,
574            },
575        }
576    }
577
578    pub fn send_event(&self, msg: Message<ObjectId, RawFd>) -> Result<(), InvalidId> {
579        self.state.lock().unwrap().send_event(msg)
580    }
581
582    pub fn get_object_data<D: 'static>(
583        &self,
584        id: InnerObjectId,
585    ) -> Result<Arc<dyn ObjectData<D>>, InvalidId> {
586        let mut state = self.state.lock().unwrap();
587        // Keep this guard alive while the code is run to protect the C state
588        let _state = (&mut *state as &mut dyn ErasedState)
589            .downcast_mut::<State<D>>()
590            .expect("Wrong type parameter passed to Handle::get_object_data().");
591
592        if !id.alive.load(Ordering::Acquire) {
593            return Err(InvalidId);
594        }
595
596        let iface_c_ptr =
597            id.interface.c_ptr.expect("[wayland-backend-sys] Cannot use Interface without c_ptr!");
598        let is_managed = unsafe {
599            ffi_dispatch!(
600                wayland_server_handle(),
601                wl_resource_instance_of,
602                id.ptr,
603                iface_c_ptr,
604                &RUST_MANAGED as *const u8 as *const _
605            ) != 0
606        };
607        if !is_managed {
608            return Err(InvalidId);
609        }
610
611        let udata = unsafe {
612            &*(ffi_dispatch!(wayland_server_handle(), wl_resource_get_user_data, id.ptr)
613                as *mut ResourceUserData<D>)
614        };
615
616        Ok(udata.data.clone())
617    }
618
619    pub fn get_object_data_any(
620        &self,
621        id: InnerObjectId,
622    ) -> Result<Arc<dyn std::any::Any + Send + Sync>, InvalidId> {
623        self.state.lock().unwrap().get_object_data_any(id)
624    }
625
626    pub fn set_object_data<D: 'static>(
627        &self,
628        id: InnerObjectId,
629        data: Arc<dyn ObjectData<D>>,
630    ) -> Result<(), InvalidId> {
631        let mut state = self.state.lock().unwrap();
632        // Keep this guard alive while the code is run to protect the C state
633        let _state = (&mut *state as &mut dyn ErasedState)
634            .downcast_mut::<State<D>>()
635            .expect("Wrong type parameter passed to Handle::set_object_data().");
636
637        if !id.alive.load(Ordering::Acquire) {
638            return Err(InvalidId);
639        }
640
641        let iface_c_ptr =
642            id.interface.c_ptr.expect("[wayland-backend-sys] Cannot use Interface without c_ptr!");
643        let is_managed = unsafe {
644            ffi_dispatch!(
645                wayland_server_handle(),
646                wl_resource_instance_of,
647                id.ptr,
648                iface_c_ptr,
649                &RUST_MANAGED as *const u8 as *const _
650            ) != 0
651        };
652        if !is_managed {
653            return Err(InvalidId);
654        }
655
656        let udata = unsafe {
657            &mut *(ffi_dispatch!(wayland_server_handle(), wl_resource_get_user_data, id.ptr)
658                as *mut ResourceUserData<D>)
659        };
660
661        udata.data = data;
662
663        Ok(())
664    }
665
666    pub fn post_error(&self, object_id: InnerObjectId, error_code: u32, message: CString) {
667        self.state.lock().unwrap().post_error(object_id, error_code, message)
668    }
669
670    pub fn kill_client(&self, client_id: InnerClientId, reason: DisconnectReason) {
671        self.state.lock().unwrap().kill_client(client_id, reason)
672    }
673
674    pub fn create_global<D: 'static>(
675        &self,
676        interface: &'static Interface,
677        version: u32,
678        handler: Arc<dyn GlobalHandler<D>>,
679    ) -> InnerGlobalId {
680        let display = {
681            let mut state = self.state.lock().unwrap();
682            let state = (&mut *state as &mut dyn ErasedState)
683                .downcast_mut::<State<D>>()
684                .expect("Wrong type parameter passed to Handle::create_global().");
685            state.display
686        };
687
688        let alive = Arc::new(AtomicBool::new(true));
689
690        let interface_ptr =
691            interface.c_ptr.expect("Interface without c_ptr are unsupported by the sys backend.");
692
693        let udata = Box::into_raw(Box::new(GlobalUserData {
694            handler,
695            alive: alive.clone(),
696            interface,
697            version,
698            disabled: false,
699            ptr: std::ptr::null_mut(),
700        }));
701
702        let ret = HANDLE.set(&(self.state.clone(), std::ptr::null_mut()), || unsafe {
703            ffi_dispatch!(
704                wayland_server_handle(),
705                wl_global_create,
706                display,
707                interface_ptr,
708                version as i32,
709                udata as *mut c_void,
710                global_bind::<D>
711            )
712        });
713
714        if ret.is_null() {
715            // free the user data as global creation failed
716            let _ = unsafe { Box::from_raw(udata) };
717            panic!(
718                "[wayland-backend-sys] Invalid global specification or memory allocation failure."
719            );
720        }
721
722        unsafe {
723            (*udata).ptr = ret;
724        }
725
726        let mut state = self.state.lock().unwrap();
727        let state = (&mut *state as &mut dyn ErasedState)
728            .downcast_mut::<State<D>>()
729            .expect("Wrong type parameter passed to Handle::create_global().");
730
731        let id = InnerGlobalId { ptr: ret, alive };
732        state.known_globals.push(id.clone());
733        id
734    }
735
736    pub fn disable_global<D: 'static>(&self, id: InnerGlobalId) {
737        // check that `D` is correct
738        {
739            let mut state = self.state.lock().unwrap();
740            let _state = (&mut *state as &mut dyn ErasedState)
741                .downcast_mut::<State<D>>()
742                .expect("Wrong type parameter passed to Handle::disable_global().");
743        }
744
745        if !id.alive.load(Ordering::Acquire) {
746            return;
747        }
748
749        let udata = unsafe {
750            &mut *(ffi_dispatch!(wayland_server_handle(), wl_global_get_user_data, id.ptr)
751                as *mut GlobalUserData<D>)
752        };
753
754        // libwayland will abort if wl_global_remove is called more than once.
755        // This means we do nothing if the global is already disabled
756        if !udata.disabled {
757            udata.disabled = true;
758
759            // send the global_remove
760            HANDLE.set(&(self.state.clone(), std::ptr::null_mut()), || unsafe {
761                ffi_dispatch!(wayland_server_handle(), wl_global_remove, id.ptr);
762            });
763        }
764    }
765
766    pub fn remove_global<D: 'static>(&self, id: InnerGlobalId) {
767        {
768            let mut state = self.state.lock().unwrap();
769            let state = (&mut *state as &mut dyn ErasedState)
770                .downcast_mut::<State<D>>()
771                .expect("Wrong type parameter passed to Handle::remove_global().");
772            state.known_globals.retain(|g| g != &id);
773        }
774
775        if !id.alive.load(Ordering::Acquire) {
776            return;
777        }
778
779        let udata = unsafe {
780            Box::from_raw(ffi_dispatch!(wayland_server_handle(), wl_global_get_user_data, id.ptr)
781                as *mut GlobalUserData<D>)
782        };
783        udata.alive.store(false, Ordering::Release);
784
785        HANDLE.set(&(self.state.clone(), std::ptr::null_mut()), || unsafe {
786            ffi_dispatch!(wayland_server_handle(), wl_global_destroy, id.ptr);
787        });
788    }
789
790    pub fn global_info(&self, id: InnerGlobalId) -> Result<GlobalInfo, InvalidId> {
791        self.state.lock().unwrap().global_info(id)
792    }
793
794    /// Returns the handler which manages the visibility and notifies when a client has bound the global.
795    pub fn get_global_handler<D: 'static>(
796        &self,
797        id: InnerGlobalId,
798    ) -> Result<Arc<dyn GlobalHandler<D>>, InvalidId> {
799        let mut state = self.state.lock().unwrap();
800        // Keep this guard alive while the code is run to protect the C state
801        let _state = (&mut *state as &mut dyn ErasedState)
802            .downcast_mut::<State<D>>()
803            .expect("Wrong type parameter passed to Handle::set_object_data().");
804
805        if !id.alive.load(Ordering::Acquire) {
806            return Err(InvalidId);
807        }
808
809        let udata = unsafe {
810            Box::from_raw(ffi_dispatch!(wayland_server_handle(), wl_global_get_user_data, id.ptr)
811                as *mut GlobalUserData<D>)
812        };
813        Ok(udata.handler.clone())
814    }
815
816    pub fn flush(&mut self, client: Option<ClientId>) -> std::io::Result<()> {
817        self.state.lock().unwrap().flush(client)
818    }
819
820    pub fn display_ptr(&self) -> *mut wl_display {
821        self.state.lock().unwrap().display_ptr()
822    }
823}
824
825pub(crate) trait ErasedState: downcast_rs::Downcast {
826    fn object_info(&self, id: InnerObjectId) -> Result<ObjectInfo, InvalidId>;
827    fn insert_client(
828        &self,
829        stream: UnixStream,
830        data: Arc<dyn ClientData>,
831    ) -> std::io::Result<InnerClientId>;
832    fn get_client(&self, id: InnerObjectId) -> Result<ClientId, InvalidId>;
833    fn get_client_credentials(&self, id: InnerClientId) -> Result<Credentials, InvalidId>;
834    fn get_client_data(&self, id: InnerClientId) -> Result<Arc<dyn ClientData>, InvalidId>;
835    fn with_all_clients(&self, f: &mut dyn FnMut(ClientId));
836    fn with_all_objects_for(
837        &self,
838        client_id: InnerClientId,
839        f: &mut dyn FnMut(ObjectId),
840    ) -> Result<(), InvalidId>;
841    fn object_for_protocol_id(
842        &self,
843        client_id: InnerClientId,
844        interface: &'static Interface,
845        protocol_id: u32,
846    ) -> Result<ObjectId, InvalidId>;
847    fn get_object_data_any(
848        &self,
849        id: InnerObjectId,
850    ) -> Result<Arc<dyn std::any::Any + Send + Sync>, InvalidId>;
851    fn send_event(&mut self, msg: Message<ObjectId, RawFd>) -> Result<(), InvalidId>;
852    fn post_error(&mut self, object_id: InnerObjectId, error_code: u32, message: CString);
853    fn kill_client(&mut self, client_id: InnerClientId, reason: DisconnectReason);
854    fn global_info(&self, id: InnerGlobalId) -> Result<GlobalInfo, InvalidId>;
855    fn is_known_global(&self, global_ptr: *const wl_global) -> bool;
856    fn flush(&mut self, client: Option<ClientId>) -> std::io::Result<()>;
857    fn display_ptr(&self) -> *mut wl_display;
858}
859
860downcast_rs::impl_downcast!(ErasedState);
861
862impl<D: 'static> ErasedState for State<D> {
863    fn object_info(&self, id: InnerObjectId) -> Result<ObjectInfo, InvalidId> {
864        if !id.alive.load(Ordering::Acquire) {
865            return Err(InvalidId);
866        }
867
868        let version =
869            unsafe { ffi_dispatch!(wayland_server_handle(), wl_resource_get_version, id.ptr) }
870                as u32;
871
872        Ok(ObjectInfo { id: id.id, version, interface: id.interface })
873    }
874
875    fn insert_client(
876        &self,
877        stream: UnixStream,
878        data: Arc<dyn ClientData>,
879    ) -> std::io::Result<InnerClientId> {
880        let ret = unsafe {
881            ffi_dispatch!(
882                wayland_server_handle(),
883                wl_client_create,
884                self.display,
885                stream.into_raw_fd()
886            )
887        };
888
889        if ret.is_null() {
890            return Err(std::io::Error::last_os_error());
891        }
892
893        Ok(unsafe { init_client(ret, data) })
894    }
895
896    fn get_client(&self, id: InnerObjectId) -> Result<ClientId, InvalidId> {
897        if !id.alive.load(Ordering::Acquire) {
898            return Err(InvalidId);
899        }
900
901        unsafe {
902            let client_ptr = ffi_dispatch!(wayland_server_handle(), wl_resource_get_client, id.ptr);
903            client_id_from_ptr(client_ptr).ok_or(InvalidId).map(|id| ClientId { id })
904        }
905    }
906
907    fn get_client_data(&self, id: InnerClientId) -> Result<Arc<dyn ClientData>, InvalidId> {
908        if !id.alive.load(Ordering::Acquire) {
909            return Err(InvalidId);
910        }
911
912        let data = unsafe {
913            match client_user_data(id.ptr) {
914                Some(ptr) => &mut *ptr,
915                None => return Err(InvalidId),
916            }
917        };
918
919        Ok(data.data.clone())
920    }
921
922    fn get_client_credentials(&self, id: InnerClientId) -> Result<Credentials, InvalidId> {
923        if !id.alive.load(Ordering::Acquire) {
924            return Err(InvalidId);
925        }
926
927        let mut creds = Credentials { pid: 0, uid: 0, gid: 0 };
928
929        unsafe {
930            ffi_dispatch!(
931                wayland_server_handle(),
932                wl_client_get_credentials,
933                id.ptr,
934                &mut creds.pid,
935                &mut creds.uid,
936                &mut creds.gid
937            );
938        }
939
940        Ok(creds)
941    }
942
943    fn with_all_clients(&self, f: &mut dyn FnMut(ClientId)) {
944        let mut client_list = unsafe {
945            ffi_dispatch!(wayland_server_handle(), wl_display_get_client_list, self.display)
946        };
947        unsafe {
948            while (*client_list).next != client_list {
949                let client =
950                    ffi_dispatch!(wayland_server_handle(), wl_client_from_link, client_list);
951                if let Some(id) = client_id_from_ptr(client) {
952                    f(ClientId { id })
953                }
954
955                client_list = (*client_list).next;
956            }
957        }
958    }
959
960    fn with_all_objects_for(
961        &self,
962        client_id: InnerClientId,
963        mut f: &mut dyn FnMut(ObjectId),
964    ) -> Result<(), InvalidId> {
965        if !client_id.alive.load(Ordering::Acquire) {
966            return Err(InvalidId);
967        }
968
969        unsafe extern "C" fn iterator_func(
970            resource: *mut wl_resource,
971            user_data: *mut c_void,
972        ) -> c_int {
973            // the closure is passed by double-reference because we only have 1 pointer of user data
974            let closure = unsafe { &mut *(user_data as *mut &mut dyn FnMut(ObjectId)) };
975
976            // Only process objects that are RUST_MANAGED (we cannot guess the Interface for the others,
977            // and thus cannot create the ObjectId).
978            if let Ok(id) = unsafe { InnerObjectId::from_ptr(None, resource) } {
979                closure(ObjectId { id })
980            }
981
982            // return WL_ITERATOR_CONTINUE
983            1
984        }
985
986        unsafe {
987            ffi_dispatch!(
988                wayland_server_handle(),
989                wl_client_for_each_resource,
990                client_id.ptr,
991                iterator_func,
992                &mut f as *mut _ as *mut c_void,
993            )
994        }
995
996        Ok(())
997    }
998
999    fn object_for_protocol_id(
1000        &self,
1001        client_id: InnerClientId,
1002        interface: &'static Interface,
1003        protocol_id: u32,
1004    ) -> Result<ObjectId, InvalidId> {
1005        if !client_id.alive.load(Ordering::Acquire) {
1006            return Err(InvalidId);
1007        }
1008        let resource = unsafe {
1009            ffi_dispatch!(wayland_server_handle(), wl_client_get_object, client_id.ptr, protocol_id)
1010        };
1011        if resource.is_null() {
1012            Err(InvalidId)
1013        } else {
1014            unsafe { ObjectId::from_ptr(interface, resource) }
1015        }
1016    }
1017
1018    fn get_object_data_any(
1019        &self,
1020        id: InnerObjectId,
1021    ) -> Result<Arc<dyn std::any::Any + Send + Sync>, InvalidId> {
1022        if !id.alive.load(Ordering::Acquire) {
1023            return Err(InvalidId);
1024        }
1025
1026        let iface_c_ptr =
1027            id.interface.c_ptr.expect("[wayland-backend-sys] Cannot use Interface without c_ptr!");
1028        let is_managed = unsafe {
1029            ffi_dispatch!(
1030                wayland_server_handle(),
1031                wl_resource_instance_of,
1032                id.ptr,
1033                iface_c_ptr,
1034                &RUST_MANAGED as *const u8 as *const _
1035            ) != 0
1036        };
1037        if !is_managed {
1038            return Err(InvalidId);
1039        }
1040
1041        let udata = unsafe {
1042            &*(ffi_dispatch!(wayland_server_handle(), wl_resource_get_user_data, id.ptr)
1043                as *mut ResourceUserData<D>)
1044        };
1045
1046        Ok(udata.data.clone().into_any_arc())
1047    }
1048
1049    fn send_event(
1050        &mut self,
1051        Message { sender_id: ObjectId { id }, opcode, args }: Message<ObjectId, RawFd>,
1052    ) -> Result<(), InvalidId> {
1053        if !id.alive.load(Ordering::Acquire) || id.ptr.is_null() {
1054            return Err(InvalidId);
1055        }
1056
1057        // check that the argument list is valid
1058        let message_desc = match id.interface.events.get(opcode as usize) {
1059            Some(msg) => msg,
1060            None => {
1061                panic!("Unknown opcode {} for object {}@{}.", opcode, id.interface.name, id.id);
1062            }
1063        };
1064        if !check_for_signature(message_desc.signature, &args) {
1065            panic!(
1066                "Unexpected signature for request {}@{}.{}: expected {:?}, got {:?}.",
1067                id.interface.name, id.id, message_desc.name, message_desc.signature, args
1068            );
1069        }
1070
1071        let mut argument_list = SmallVec::<[wl_argument; 4]>::with_capacity(args.len());
1072        let mut arg_interfaces = message_desc.arg_interfaces.iter();
1073        for (i, arg) in args.iter().enumerate() {
1074            match *arg {
1075                Argument::Uint(u) => argument_list.push(wl_argument { u }),
1076                Argument::Int(i) => argument_list.push(wl_argument { i }),
1077                Argument::Fixed(f) => argument_list.push(wl_argument { f }),
1078                Argument::Fd(h) => argument_list.push(wl_argument { h }),
1079                Argument::Array(ref a) => {
1080                    let a = Box::new(wl_array {
1081                        size: a.len(),
1082                        alloc: a.len(),
1083                        data: a.as_ptr() as *mut _,
1084                    });
1085                    argument_list.push(wl_argument { a: Box::into_raw(a) })
1086                }
1087                Argument::Str(Some(ref s)) => argument_list.push(wl_argument { s: s.as_ptr() }),
1088                Argument::Str(None) => argument_list.push(wl_argument { s: std::ptr::null() }),
1089                Argument::Object(ref o) => {
1090                    let next_interface = arg_interfaces.next().unwrap();
1091                    if !o.id.ptr.is_null() {
1092                        if !o.id.alive.load(Ordering::Acquire) {
1093                            unsafe { free_arrays(message_desc.signature, &argument_list) };
1094                            return Err(InvalidId);
1095                        }
1096                        // check that the object belongs to the right client
1097                        if self.get_client(id.clone()).unwrap().id.ptr
1098                            != self.get_client(o.id.clone()).unwrap().id.ptr
1099                        {
1100                            panic!("Attempting to send an event with objects from wrong client.");
1101                        }
1102                        if !same_interface(next_interface, o.id.interface) {
1103                            panic!("Event {}@{}.{} expects an argument of interface {} but {} was provided instead.", id.interface.name, id.id, message_desc.name, next_interface.name, o.id.interface.name);
1104                        }
1105                    } else if !matches!(
1106                        message_desc.signature[i],
1107                        ArgumentType::Object(AllowNull::Yes)
1108                    ) {
1109                        panic!(
1110                            "Event {}@{}.{} expects an non-null object argument.",
1111                            id.interface.name, id.id, message_desc.name
1112                        );
1113                    }
1114                    argument_list.push(wl_argument { o: o.id.ptr as *const _ })
1115                }
1116                Argument::NewId(ref o) => {
1117                    if !o.id.ptr.is_null() {
1118                        if !id.alive.load(Ordering::Acquire) {
1119                            unsafe { free_arrays(message_desc.signature, &argument_list) };
1120                            return Err(InvalidId);
1121                        }
1122                        // check that the object belongs to the right client
1123                        if self.get_client(id.clone()).unwrap().id.ptr
1124                            != self.get_client(o.id.clone()).unwrap().id.ptr
1125                        {
1126                            panic!("Attempting to send an event with objects from wrong client.");
1127                        }
1128                        let child_interface = match message_desc.child_interface {
1129                            Some(iface) => iface,
1130                            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),
1131                        };
1132                        if !same_interface(child_interface, o.id.interface) {
1133                            panic!("Event {}@{}.{} expects an argument of interface {} but {} was provided instead.", id.interface.name, id.id, message_desc.name, child_interface.name, o.id.interface.name);
1134                        }
1135                    } else if !matches!(message_desc.signature[i], ArgumentType::NewId) {
1136                        panic!(
1137                            "Event {}@{}.{} expects an non-null object argument.",
1138                            id.interface.name, id.id, message_desc.name
1139                        );
1140                    }
1141                    argument_list.push(wl_argument { o: o.id.ptr as *const _ })
1142                }
1143            }
1144        }
1145
1146        unsafe {
1147            ffi_dispatch!(
1148                wayland_server_handle(),
1149                wl_resource_post_event_array,
1150                id.ptr,
1151                opcode as u32,
1152                argument_list.as_mut_ptr()
1153            );
1154        }
1155
1156        unsafe {
1157            free_arrays(message_desc.signature, &argument_list);
1158        }
1159
1160        if message_desc.is_destructor {
1161            // wl_resource_destroy invokes a destructor
1162            PENDING_DESTRUCTORS.set(
1163                &(&mut self.pending_destructors as *mut _ as *mut _),
1164                || unsafe {
1165                    ffi_dispatch!(wayland_server_handle(), wl_resource_destroy, id.ptr);
1166                },
1167            );
1168        }
1169
1170        Ok(())
1171    }
1172
1173    fn post_error(&mut self, id: InnerObjectId, error_code: u32, message: CString) {
1174        if !id.alive.load(Ordering::Acquire) {
1175            return;
1176        }
1177
1178        // Safety: at this point we already checked that the pointer is valid
1179        let client =
1180            unsafe { ffi_dispatch!(wayland_server_handle(), wl_resource_get_client, id.ptr) };
1181        let client_id = unsafe { client_id_from_ptr(client) }.unwrap();
1182        // mark the client as dead
1183        client_id.alive.store(false, Ordering::Release);
1184
1185        unsafe {
1186            ffi_dispatch!(
1187                wayland_server_handle(),
1188                wl_resource_post_error,
1189                id.ptr,
1190                error_code,
1191                message.as_ptr()
1192            )
1193        }
1194    }
1195
1196    fn kill_client(&mut self, client_id: InnerClientId, reason: DisconnectReason) {
1197        if !client_id.alive.load(Ordering::Acquire) {
1198            return;
1199        }
1200        if let Some(udata) = unsafe { client_user_data(client_id.ptr) } {
1201            let udata = unsafe { &*udata };
1202            udata.alive.store(false, Ordering::Release);
1203            udata.data.disconnected(ClientId { id: client_id.clone() }, reason);
1204        }
1205
1206        // wl_client_destroy invokes destructors
1207        PENDING_DESTRUCTORS.set(&(&mut self.pending_destructors as *mut _ as *mut _), || unsafe {
1208            ffi_dispatch!(wayland_server_handle(), wl_client_destroy, client_id.ptr);
1209        });
1210    }
1211
1212    fn global_info(&self, id: InnerGlobalId) -> Result<GlobalInfo, InvalidId> {
1213        if !id.alive.load(Ordering::Acquire) {
1214            return Err(InvalidId);
1215        }
1216        let udata = unsafe {
1217            &*(ffi_dispatch!(wayland_server_handle(), wl_global_get_user_data, id.ptr)
1218                as *mut GlobalUserData<D>)
1219        };
1220
1221        Ok(GlobalInfo {
1222            interface: udata.interface,
1223            version: udata.version,
1224            disabled: udata.disabled,
1225        })
1226    }
1227
1228    fn is_known_global(&self, global_ptr: *const wl_global) -> bool {
1229        self.known_globals.iter().any(|ginfo| (ginfo.ptr as *const wl_global) == global_ptr)
1230    }
1231
1232    fn flush(&mut self, client: Option<ClientId>) -> std::io::Result<()> {
1233        if let Some(ClientId { id: client_id }) = client {
1234            if client_id.alive.load(Ordering::Acquire) {
1235                unsafe { ffi_dispatch!(wayland_server_handle(), wl_client_flush, client_id.ptr) }
1236            }
1237        } else {
1238            // wl_display_flush_clients might invoke destructors
1239            PENDING_DESTRUCTORS.set(
1240                &(&mut self.pending_destructors as *mut _ as *mut _),
1241                || unsafe {
1242                    ffi_dispatch!(wayland_server_handle(), wl_display_flush_clients, self.display);
1243                },
1244            );
1245        }
1246        if !self.pending_destructors.is_empty() {
1247            // Arm the timer to trigger a wakeup of the inner event loop in 1ms, so that the user
1248            // is indicated to call dispatch_clients() and have the destructors run
1249            unsafe {
1250                ffi_dispatch!(
1251                    wayland_server_handle(),
1252                    wl_event_source_timer_update,
1253                    self.timer_source,
1254                    1
1255                )
1256            };
1257        }
1258        Ok(())
1259    }
1260
1261    fn display_ptr(&self) -> *mut wl_display {
1262        self.display
1263    }
1264}
1265
1266unsafe fn init_client(client: *mut wl_client, data: Arc<dyn ClientData>) -> InnerClientId {
1267    let alive = Arc::new(AtomicBool::new(true));
1268    let client_data = Box::into_raw(Box::new(ClientUserData { alive: alive.clone(), data }));
1269
1270    let listener = signal::rust_listener_create(client_destroy_notify);
1271    // Safety: we just created listener and client_data, they are valid
1272    unsafe {
1273        signal::rust_listener_set_user_data(listener, client_data as *mut c_void);
1274    }
1275
1276    ffi_dispatch!(wayland_server_handle(), wl_client_add_destroy_listener, client, listener);
1277
1278    InnerClientId { ptr: client, alive }
1279}
1280
1281unsafe fn client_id_from_ptr(client: *mut wl_client) -> Option<InnerClientId> {
1282    // Safety: the provided pointer is a valid and initialized wl_client for type parameter D
1283    unsafe {
1284        client_user_data(client)
1285            .map(|udata| InnerClientId { ptr: client, alive: (*udata).alive.clone() })
1286    }
1287}
1288
1289unsafe fn client_user_data(client: *mut wl_client) -> Option<*mut ClientUserData> {
1290    if client.is_null() {
1291        return None;
1292    }
1293    let listener = ffi_dispatch!(
1294        wayland_server_handle(),
1295        wl_client_get_destroy_listener,
1296        client,
1297        client_destroy_notify
1298    );
1299    if !listener.is_null() {
1300        // Safety: the pointer we got must be valid if the client is still alive
1301        unsafe { Some(signal::rust_listener_get_user_data(listener) as *mut ClientUserData) }
1302    } else {
1303        None
1304    }
1305}
1306
1307unsafe extern "C" fn client_destroy_notify(listener: *mut wl_listener, client_ptr: *mut c_void) {
1308    // Safety: if this function is invoked by libwayland its arguments must be valid
1309    let data = unsafe {
1310        Box::from_raw(signal::rust_listener_get_user_data(listener) as *mut ClientUserData)
1311    };
1312    unsafe {
1313        signal::rust_listener_destroy(listener);
1314    }
1315    // only notify the killing if it was not already
1316    if data.alive.load(Ordering::Acquire) {
1317        data.alive.store(false, Ordering::Release);
1318        data.data.disconnected(
1319            ClientId {
1320                id: InnerClientId { ptr: client_ptr as *mut wl_client, alive: data.alive.clone() },
1321            },
1322            DisconnectReason::ConnectionClosed,
1323        );
1324    }
1325}
1326
1327unsafe extern "C" fn global_bind<D: 'static>(
1328    client: *mut wl_client,
1329    data: *mut c_void,
1330    version: u32,
1331    id: u32,
1332) {
1333    // Safety: when this function is invoked, the data pointer provided by libwayland is the data we previously put there
1334    let global_udata = unsafe { &mut *(data as *mut GlobalUserData<D>) };
1335
1336    let global_id = InnerGlobalId { alive: global_udata.alive.clone(), ptr: global_udata.ptr };
1337
1338    // Safety: libwayland invoked us with a valid wl_client
1339    let client_id = match unsafe { client_id_from_ptr(client) } {
1340        Some(id) => id,
1341        None => return,
1342    };
1343
1344    // this must be Some(), checked at creation of the global
1345    let interface_ptr = global_udata.interface.c_ptr.unwrap();
1346
1347    HANDLE.with(|&(ref state_arc, data_ptr)| {
1348        // Safety: the data_ptr is a valid pointer that live outside code put there
1349        let data = unsafe { &mut *(data_ptr as *mut D) };
1350        // create the object
1351        let resource = ffi_dispatch!(
1352            wayland_server_handle(),
1353            wl_resource_create,
1354            client,
1355            interface_ptr,
1356            version as i32,
1357            id
1358        );
1359        // Safety: resource was just created, it must be valid
1360        let (object_id, udata) = unsafe { init_resource(resource, global_udata.interface, None) };
1361        let obj_data = global_udata.handler.clone().bind(
1362            &Handle { handle: InnerHandle { state: state_arc.clone() } },
1363            data,
1364            ClientId { id: client_id },
1365            GlobalId { id: global_id },
1366            ObjectId { id: object_id },
1367        );
1368        // Safety: udata was just created, it is valid
1369        unsafe { (*udata).data = obj_data };
1370    })
1371}
1372
1373unsafe extern "C" fn global_filter<D: 'static>(
1374    client: *const wl_client,
1375    global: *const wl_global,
1376    _: *mut c_void,
1377) -> bool {
1378    if !HANDLE.is_set() {
1379        // This happens if we are invoked during the global shutdown
1380        // at this point, we really don't care what we send to clients,
1381        // the compositor is shutting down anyway so they're all going to be killed
1382        // thus return false, so that nothing is sent to anybody
1383        return false;
1384    }
1385
1386    // Safety: skip processing globals that do not belong to us
1387    let is_known_global = HANDLE.with(|(state_arc, _)| {
1388        let guard = state_arc.lock().unwrap();
1389        guard.is_known_global(global)
1390    });
1391    if !is_known_global {
1392        return true;
1393    }
1394
1395    // Safety: if we are invoked here, the client is a valid client initialized by us
1396    let client_udata = match unsafe { client_user_data(client as *mut _) } {
1397        Some(id) => unsafe { &*id },
1398        None => return false,
1399    };
1400
1401    let client_id = InnerClientId { ptr: client as *mut _, alive: client_udata.alive.clone() };
1402
1403    // Safety: if we are invoked here, the global is a global client initialized by us
1404    let global_udata = unsafe {
1405        &*(ffi_dispatch!(wayland_server_handle(), wl_global_get_user_data, global)
1406            as *mut GlobalUserData<D>)
1407    };
1408
1409    let global_id =
1410        InnerGlobalId { ptr: global as *mut wl_global, alive: global_udata.alive.clone() };
1411
1412    global_udata.handler.can_view(
1413        ClientId { id: client_id },
1414        &client_udata.data,
1415        GlobalId { id: global_id },
1416    )
1417}
1418
1419unsafe fn init_resource<D: 'static>(
1420    resource: *mut wl_resource,
1421    interface: &'static Interface,
1422    data: Option<Arc<dyn ObjectData<D>>>,
1423) -> (InnerObjectId, *mut ResourceUserData<D>) {
1424    let alive = Arc::new(AtomicBool::new(true));
1425    let udata = Box::into_raw(Box::new(ResourceUserData {
1426        data: data.unwrap_or_else(|| Arc::new(UninitObjectData)),
1427        interface,
1428        alive: alive.clone(),
1429    }));
1430    let id = ffi_dispatch!(wayland_server_handle(), wl_resource_get_id, resource);
1431
1432    ffi_dispatch!(
1433        wayland_server_handle(),
1434        wl_resource_set_dispatcher,
1435        resource,
1436        resource_dispatcher::<D>,
1437        &RUST_MANAGED as *const u8 as *const c_void,
1438        udata as *mut c_void,
1439        Some(resource_destructor::<D>)
1440    );
1441
1442    (InnerObjectId { interface, alive, id, ptr: resource }, udata)
1443}
1444
1445unsafe extern "C" fn resource_dispatcher<D: 'static>(
1446    _: *const c_void,
1447    resource: *mut c_void,
1448    opcode: u32,
1449    _: *const wl_message,
1450    args: *const wl_argument,
1451) -> i32 {
1452    let resource = resource as *mut wl_resource;
1453    let udata_ptr = ffi_dispatch!(wayland_server_handle(), wl_resource_get_user_data, resource)
1454        as *mut ResourceUserData<D>;
1455    // Safety: if we are invoked, the resource is valid and rust-managed, so its user data is valid
1456    let udata = unsafe { &mut *udata_ptr };
1457    let client = ffi_dispatch!(wayland_server_handle(), wl_resource_get_client, resource);
1458    let resource_id = ffi_dispatch!(wayland_server_handle(), wl_resource_get_id, resource);
1459    let version = ffi_dispatch!(wayland_server_handle(), wl_resource_get_version, resource);
1460    let interface = udata.interface;
1461    let message_desc = match interface.requests.get(opcode as usize) {
1462        Some(desc) => desc,
1463        None => {
1464            crate::log_error!("Unknown event opcode {} for interface {}.", opcode, interface.name);
1465            return -1;
1466        }
1467    };
1468
1469    let mut parsed_args =
1470        SmallVec::<[Argument<ObjectId, OwnedFd>; 4]>::with_capacity(message_desc.signature.len());
1471    let mut arg_interfaces = message_desc.arg_interfaces.iter().copied();
1472    let mut created = None;
1473    // Safety (args deference): the args array provided by libwayland is well-formed
1474    for (i, typ) in message_desc.signature.iter().enumerate() {
1475        match typ {
1476            ArgumentType::Uint => parsed_args.push(Argument::Uint(unsafe { (*args.add(i)).u })),
1477            ArgumentType::Int => parsed_args.push(Argument::Int(unsafe { (*args.add(i)).i })),
1478            ArgumentType::Fixed => parsed_args.push(Argument::Fixed(unsafe { (*args.add(i)).f })),
1479            ArgumentType::Fd => {
1480                parsed_args.push(Argument::Fd(unsafe { OwnedFd::from_raw_fd((*args.add(i)).h) }))
1481            }
1482            ArgumentType::Array => {
1483                let array = unsafe { &*((*args.add(i)).a) };
1484                // Safety: the wl_array provided by libwayland is valid
1485                let content =
1486                    unsafe { std::slice::from_raw_parts(array.data as *mut u8, array.size) };
1487                parsed_args.push(Argument::Array(Box::new(content.into())));
1488            }
1489            ArgumentType::Str(_) => {
1490                let ptr = unsafe { (*args.add(i)).s };
1491                // Safety: the c-string provided by libwayland is valid
1492                if !ptr.is_null() {
1493                    let cstr = unsafe { std::ffi::CStr::from_ptr(ptr) };
1494                    parsed_args.push(Argument::Str(Some(Box::new(cstr.into()))));
1495                } else {
1496                    parsed_args.push(Argument::Str(None));
1497                }
1498            }
1499            ArgumentType::Object(_) => {
1500                let obj = unsafe { (*args.add(i)).o as *mut wl_resource };
1501                let next_interface = arg_interfaces.next().unwrap_or(&ANONYMOUS_INTERFACE);
1502                let id = if !obj.is_null() {
1503                    ObjectId {
1504                        id: unsafe { InnerObjectId::from_ptr(Some(next_interface), obj) }
1505                            .expect("Received an invalid ID when parsing a message."),
1506                    }
1507                } else {
1508                    // libwayland-server.so checks nulls for us
1509                    InnerHandle::null_id()
1510                };
1511                parsed_args.push(Argument::Object(id))
1512            }
1513            ArgumentType::NewId => {
1514                let new_id = unsafe { (*args.add(i)).n };
1515                // create the object
1516                if new_id != 0 {
1517                    let child_interface = match message_desc.child_interface {
1518                        Some(iface) => iface,
1519                        None => panic!("Received request {}@{}.{} which creates an object without specifying its interface, this is unsupported.", udata.interface.name, resource_id, message_desc.name),
1520                    };
1521                    // create the object
1522                    let resource = ffi_dispatch!(
1523                        wayland_server_handle(),
1524                        wl_resource_create,
1525                        client,
1526                        child_interface.c_ptr.unwrap(),
1527                        version,
1528                        new_id
1529                    );
1530                    // Safety: the resource has just been created and is valid
1531                    let (child_id, child_data_ptr) =
1532                        unsafe { init_resource::<D>(resource, child_interface, None) };
1533                    created = Some((child_id.clone(), child_data_ptr));
1534                    parsed_args.push(Argument::NewId(ObjectId { id: child_id }));
1535                } else {
1536                    parsed_args.push(Argument::NewId(InnerHandle::null_id()))
1537                }
1538            }
1539        }
1540    }
1541
1542    let object_id = ObjectId {
1543        id: InnerObjectId {
1544            ptr: resource,
1545            id: resource_id,
1546            interface: udata.interface,
1547            alive: udata.alive.clone(),
1548        },
1549    };
1550
1551    // Safety: the client ptr is valid and provided by libwayland
1552    let client_id = unsafe { client_id_from_ptr(client) }.unwrap();
1553
1554    let ret = HANDLE.with(|&(ref state_arc, data_ptr)| {
1555        // Safety: the data pointer has been set by outside code and is valid
1556        let data = unsafe { &mut *(data_ptr as *mut D) };
1557        udata.data.clone().request(
1558            &Handle { handle: InnerHandle { state: state_arc.clone() } },
1559            data,
1560            ClientId { id: client_id.clone() },
1561            Message { sender_id: object_id.clone(), opcode: opcode as u16, args: parsed_args },
1562        )
1563    });
1564
1565    if message_desc.is_destructor {
1566        ffi_dispatch!(wayland_server_handle(), wl_resource_destroy, resource);
1567    }
1568
1569    match (created, ret) {
1570        (Some((_, child_udata_ptr)), Some(child_data)) => unsafe {
1571            (*child_udata_ptr).data = child_data;
1572        },
1573        (Some((child_id, _)), None) => {
1574            // Accept a missing object data if a protocol error occurred (and the object is already dead)
1575            if client_id.alive.load(Ordering::Acquire) {
1576                panic!("Callback creating object {} did not provide any object data.", child_id);
1577            }
1578        }
1579        (None, Some(_)) => {
1580            panic!("An object data was returned from a callback not creating any object");
1581        }
1582        (None, None) => {}
1583    }
1584
1585    0
1586}
1587
1588unsafe extern "C" fn resource_destructor<D: 'static>(resource: *mut wl_resource) {
1589    // Safety: if this destructor is called resource is valid and initialized by us
1590    let udata = unsafe {
1591        Box::from_raw(ffi_dispatch!(wayland_server_handle(), wl_resource_get_user_data, resource)
1592            as *mut ResourceUserData<D>)
1593    };
1594    let id = ffi_dispatch!(wayland_server_handle(), wl_resource_get_id, resource);
1595    let client = ffi_dispatch!(wayland_server_handle(), wl_resource_get_client, resource);
1596    // if this destructor is invoked during cleanup, the client ptr is no longer valid and it'll return None
1597    let client_id = unsafe { client_id_from_ptr(client) }.unwrap_or(InnerClientId {
1598        ptr: std::ptr::null_mut(),
1599        alive: Arc::new(AtomicBool::new(false)),
1600    });
1601    udata.alive.store(false, Ordering::Release);
1602    let object_id =
1603        InnerObjectId { interface: udata.interface, ptr: resource, alive: udata.alive.clone(), id };
1604    // Due to reentrancy, it is possible that both HANDLE and PENDING_DESTRUCTORS are set at the same time
1605    // If this is the case, PENDING_DESTRUCTORS should have priority
1606    if !PENDING_DESTRUCTORS.is_set() {
1607        HANDLE.with(|&(ref state_arc, data_ptr)| {
1608            // Safety: the data pointer have been set by outside code and are valid
1609            let data = unsafe { &mut *(data_ptr as *mut D) };
1610            udata.data.destroyed(
1611                &Handle { handle: InnerHandle { state: state_arc.clone() } },
1612                data,
1613                ClientId { id: client_id },
1614                ObjectId { id: object_id },
1615            );
1616        });
1617    } else {
1618        PENDING_DESTRUCTORS.with(|&pending_ptr| {
1619            // Safety: the pending pointer have been set by outside code and are valid
1620            let pending = unsafe { &mut *(pending_ptr as *mut Vec<PendingDestructor<D>>) };
1621            pending.push((
1622                udata.data.clone(),
1623                ClientId { id: client_id },
1624                ObjectId { id: object_id },
1625            ));
1626        })
1627    }
1628}
1629
1630#[cfg(feature = "log")]
1631extern "C" {
1632    fn wl_log_trampoline_to_rust_server(fmt: *const std::os::raw::c_char, list: *const c_void);
1633}
1634
1635struct UninitObjectData;
1636
1637impl<D> ObjectData<D> for UninitObjectData {
1638    #[cfg_attr(coverage, coverage(off))]
1639    fn request(
1640        self: Arc<Self>,
1641        _: &Handle,
1642        _: &mut D,
1643        _: ClientId,
1644        msg: Message<ObjectId, OwnedFd>,
1645    ) -> Option<Arc<dyn ObjectData<D>>> {
1646        panic!("Received a message on an uninitialized object: {:?}", msg);
1647    }
1648
1649    #[cfg_attr(coverage, coverage(off))]
1650    fn destroyed(self: Arc<Self>, _: &Handle, _: &mut D, _: ClientId, _: ObjectId) {}
1651
1652    #[cfg_attr(coverage, coverage(off))]
1653    fn debug(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1654        f.debug_struct("UninitObjectData").finish()
1655    }
1656}