1use 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 #[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
38scoped_thread_local! {
40 #[allow(unsafe_op_in_unsafe_fn)]
42 static PENDING_DESTRUCTORS: *mut c_void
43}
44
45#[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 let is_rust_managed = {
120 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 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 let ptr_iface_name = unsafe {
161 CStr::from_ptr(ffi_dispatch!(wayland_server_handle(), wl_resource_get_class, ptr))
162 };
163 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 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 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 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 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#[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#[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 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 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 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 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 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 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 {
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 if !udata.disabled {
757 udata.disabled = true;
758
759 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 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 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 let closure = unsafe { &mut *(user_data as *mut &mut dyn FnMut(ObjectId)) };
975
976 if let Ok(id) = unsafe { InnerObjectId::from_ptr(None, resource) } {
979 closure(ObjectId { id })
980 }
981
982 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 let client_id = match unsafe { client_id_from_ptr(client) } {
1340 Some(id) => id,
1341 None => return,
1342 };
1343
1344 let interface_ptr = global_udata.interface.c_ptr.unwrap();
1346
1347 HANDLE.with(|&(ref state_arc, data_ptr)| {
1348 let data = unsafe { &mut *(data_ptr as *mut D) };
1350 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 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 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 return false;
1384 }
1385
1386 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 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 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 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 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 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 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 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 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 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 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 let client_id = unsafe { client_id_from_ptr(client) }.unwrap();
1553
1554 let ret = HANDLE.with(|&(ref state_arc, data_ptr)| {
1555 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 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 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 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 if !PENDING_DESTRUCTORS.is_set() {
1607 HANDLE.with(|&(ref state_arc, data_ptr)| {
1608 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 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}