1//! Client-side rust implementation of a Wayland protocol backend
2
3use std::{
4 fmt,
5 os::unix::io::{BorrowedFd, OwnedFd},
6 os::unix::{
7 io::{AsRawFd, RawFd},
8 net::UnixStream,
9 },
10 sync::{Arc, Condvar, Mutex, MutexGuard, Weak},
11};
12
13use crate::{
14 core_interfaces::WL_DISPLAY_INTERFACE,
15 debug,
16 protocol::{
17 check_for_signature, same_interface, same_interface_or_anonymous, AllowNull, Argument,
18 ArgumentType, Interface, Message, ObjectInfo, ProtocolError, ANONYMOUS_INTERFACE,
19 INLINE_ARGS,
20 },
21};
22use smallvec::SmallVec;
23
24use super::{
25 client::*,
26 map::{Object, ObjectMap, SERVER_ID_LIMIT},
27 socket::{BufferedSocket, Socket},
28 wire::MessageParseError,
29};
30
31pub use crate::types::client::{InvalidId, NoWaylandLib, WaylandError};
32
33#[derive(Debug, Clone)]
34struct Data {
35 client_destroyed: bool,
36 server_destroyed: bool,
37 user_data: Arc<dyn ObjectData>,
38 serial: u32,
39}
40
41/// An ID representing a Wayland object
42#[derive(Clone)]
43pub struct InnerObjectId {
44 serial: u32,
45 id: u32,
46 interface: &'static Interface,
47}
48
49impl std::cmp::PartialEq for InnerObjectId {
50 fn eq(&self, other: &Self) -> bool {
51 self.id == other.id
52 && self.serial == other.serial
53 && same_interface(self.interface, b:other.interface)
54 }
55}
56
57impl std::cmp::Eq for InnerObjectId {}
58
59impl std::hash::Hash for InnerObjectId {
60 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
61 self.serial.hash(state);
62 self.id.hash(state);
63 }
64}
65
66impl fmt::Display for InnerObjectId {
67 #[cfg_attr(coverage, coverage(off))]
68 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
69 write!(f, "{}@{}", self.interface.name, self.id)
70 }
71}
72
73impl fmt::Debug for InnerObjectId {
74 #[cfg_attr(coverage, coverage(off))]
75 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76 write!(f, "ObjectId({}, {})", self, self.serial)
77 }
78}
79
80impl InnerObjectId {
81 pub fn is_null(&self) -> bool {
82 self.id == 0
83 }
84
85 pub fn interface(&self) -> &'static Interface {
86 self.interface
87 }
88
89 pub fn protocol_id(&self) -> u32 {
90 self.id
91 }
92}
93
94#[derive(Debug)]
95struct ProtocolState {
96 socket: BufferedSocket,
97 map: ObjectMap<Data>,
98 last_error: Option<WaylandError>,
99 last_serial: u32,
100 debug: bool,
101}
102
103#[derive(Debug)]
104struct ReadingState {
105 prepared_reads: usize,
106 read_condvar: Arc<Condvar>,
107 read_serial: usize,
108}
109
110#[derive(Debug)]
111pub struct ConnectionState {
112 protocol: Mutex<ProtocolState>,
113 read: Mutex<ReadingState>,
114}
115
116impl ConnectionState {
117 fn lock_protocol(&self) -> MutexGuard<ProtocolState> {
118 self.protocol.lock().unwrap()
119 }
120
121 fn lock_read(&self) -> MutexGuard<ReadingState> {
122 self.read.lock().unwrap()
123 }
124}
125
126#[derive(Clone, Debug)]
127pub struct InnerBackend {
128 state: Arc<ConnectionState>,
129}
130
131#[derive(Clone, Debug)]
132pub struct WeakInnerBackend {
133 state: Weak<ConnectionState>,
134}
135
136impl WeakInnerBackend {
137 pub fn upgrade(&self) -> Option<InnerBackend> {
138 Weak::upgrade(&self.state).map(|state: Arc| InnerBackend { state })
139 }
140}
141
142impl PartialEq for InnerBackend {
143 fn eq(&self, rhs: &Self) -> bool {
144 Arc::ptr_eq(&self.state, &rhs.state)
145 }
146}
147
148impl Eq for InnerBackend {}
149
150impl InnerBackend {
151 pub fn downgrade(&self) -> WeakInnerBackend {
152 WeakInnerBackend { state: Arc::downgrade(&self.state) }
153 }
154
155 pub fn connect(stream: UnixStream) -> Result<Self, NoWaylandLib> {
156 let socket = BufferedSocket::new(Socket::from(stream));
157 let mut map = ObjectMap::new();
158 map.insert_at(
159 1,
160 Object {
161 interface: &WL_DISPLAY_INTERFACE,
162 version: 1,
163 data: Data {
164 client_destroyed: false,
165 server_destroyed: false,
166 user_data: Arc::new(DumbObjectData),
167 serial: 0,
168 },
169 },
170 )
171 .unwrap();
172
173 let debug = debug::has_debug_client_env();
174
175 Ok(Self {
176 state: Arc::new(ConnectionState {
177 protocol: Mutex::new(ProtocolState {
178 socket,
179 map,
180 last_error: None,
181 last_serial: 0,
182 debug,
183 }),
184 read: Mutex::new(ReadingState {
185 prepared_reads: 0,
186 read_condvar: Arc::new(Condvar::new()),
187 read_serial: 0,
188 }),
189 }),
190 })
191 }
192
193 /// Flush all pending outgoing requests to the server
194 pub fn flush(&self) -> Result<(), WaylandError> {
195 let mut guard = self.state.lock_protocol();
196 guard.no_last_error()?;
197 if let Err(e) = guard.socket.flush() {
198 return Err(guard.store_if_not_wouldblock_and_return_error(e));
199 }
200 Ok(())
201 }
202
203 pub fn poll_fd(&self) -> BorrowedFd {
204 let raw_fd = self.state.lock_protocol().socket.as_raw_fd();
205 // This allows the lifetime of the BorrowedFd to be tied to &self rather than the lock guard,
206 // which is the real safety concern
207 unsafe { BorrowedFd::borrow_raw(raw_fd) }
208 }
209}
210
211#[derive(Debug)]
212pub struct InnerReadEventsGuard {
213 state: Arc<ConnectionState>,
214 done: bool,
215}
216
217impl InnerReadEventsGuard {
218 /// Create a new reading guard
219 ///
220 /// This call will not block, but event callbacks may be invoked in the process
221 /// of preparing the guard.
222 pub fn try_new(backend: InnerBackend) -> Option<Self> {
223 backend.state.lock_read().prepared_reads += 1;
224 Some(Self { state: backend.state, done: false })
225 }
226
227 /// Access the Wayland socket FD for polling
228 pub fn connection_fd(&self) -> BorrowedFd {
229 let raw_fd = self.state.lock_protocol().socket.as_raw_fd();
230 // This allows the lifetime of the BorrowedFd to be tied to &self rather than the lock guard,
231 // which is the real safety concern
232 unsafe { BorrowedFd::borrow_raw(raw_fd) }
233 }
234
235 /// Attempt to read events from the Wayland socket
236 ///
237 /// If multiple threads have a live reading guard, this method will block until all of them
238 /// are either dropped or have their `read()` method invoked, at which point on of the threads
239 /// will read events from the socket and invoke the callbacks for the received events. All
240 /// threads will then resume their execution.
241 ///
242 /// This returns the number of dispatched events, or `0` if an other thread handled the dispatching.
243 /// If no events are available to read from the socket, this returns a `WouldBlock` IO error.
244 pub fn read(mut self) -> Result<usize, WaylandError> {
245 let mut guard = self.state.lock_read();
246 guard.prepared_reads -= 1;
247 self.done = true;
248 if guard.prepared_reads == 0 {
249 // We should be the one reading
250 let ret = dispatch_events(self.state.clone());
251 // wake up other threads
252 guard.read_serial = guard.read_serial.wrapping_add(1);
253 guard.read_condvar.notify_all();
254 // forward the return value
255 ret
256 } else {
257 // We should wait for an other thread to read (or cancel)
258 let serial = guard.read_serial;
259 let condvar = guard.read_condvar.clone();
260 let _guard =
261 condvar.wait_while(guard, |backend| serial == backend.read_serial).unwrap();
262 self.state.lock_protocol().no_last_error()?;
263 Ok(0)
264 }
265 }
266}
267
268impl Drop for InnerReadEventsGuard {
269 fn drop(&mut self) {
270 if !self.done {
271 let mut guard: MutexGuard<'_, ReadingState> = self.state.lock_read();
272 guard.prepared_reads -= 1;
273 if guard.prepared_reads == 0 {
274 // Cancel the read
275 guard.read_serial = guard.read_serial.wrapping_add(1);
276 guard.read_condvar.notify_all();
277 }
278 }
279 }
280}
281
282impl InnerBackend {
283 pub fn display_id(&self) -> ObjectId {
284 ObjectId { id: InnerObjectId { serial: 0, id: 1, interface: &WL_DISPLAY_INTERFACE } }
285 }
286
287 pub fn last_error(&self) -> Option<WaylandError> {
288 self.state.lock_protocol().last_error.clone()
289 }
290
291 pub fn info(&self, id: ObjectId) -> Result<ObjectInfo, InvalidId> {
292 let object = self.state.lock_protocol().get_object(id.id.clone())?;
293 if object.data.client_destroyed {
294 Err(InvalidId)
295 } else {
296 Ok(ObjectInfo { id: id.id.id, interface: object.interface, version: object.version })
297 }
298 }
299
300 pub fn null_id() -> ObjectId {
301 ObjectId { id: InnerObjectId { serial: 0, id: 0, interface: &ANONYMOUS_INTERFACE } }
302 }
303
304 pub fn send_request(
305 &self,
306 Message { sender_id: ObjectId { id }, opcode, args }: Message<ObjectId, RawFd>,
307 data: Option<Arc<dyn ObjectData>>,
308 child_spec: Option<(&'static Interface, u32)>,
309 ) -> Result<ObjectId, InvalidId> {
310 let mut guard = self.state.lock_protocol();
311 let object = guard.get_object(id.clone())?;
312
313 let message_desc = match object.interface.requests.get(opcode as usize) {
314 Some(msg) => msg,
315 None => {
316 panic!("Unknown opcode {} for object {}@{}.", opcode, object.interface.name, id.id);
317 }
318 };
319
320 if object.data.client_destroyed {
321 if guard.debug {
322 debug::print_send_message(id.interface.name, id.id, message_desc.name, &args, true);
323 }
324 return Err(InvalidId);
325 }
326
327 if !check_for_signature(message_desc.signature, &args) {
328 panic!(
329 "Unexpected signature for request {}@{}.{}: expected {:?}, got {:?}.",
330 object.interface.name, id.id, message_desc.name, message_desc.signature, args
331 );
332 }
333
334 // Prepare the child object
335 let child_spec = if message_desc
336 .signature
337 .iter()
338 .any(|arg| matches!(arg, ArgumentType::NewId))
339 {
340 if let Some((iface, version)) = child_spec {
341 if let Some(child_interface) = message_desc.child_interface {
342 if !same_interface(child_interface, iface) {
343 panic!(
344 "Error when sending request {}@{}.{}: expected interface {} but got {}",
345 object.interface.name,
346 id.id,
347 message_desc.name,
348 child_interface.name,
349 iface.name
350 );
351 }
352 if version != object.version {
353 panic!(
354 "Error when sending request {}@{}.{}: expected version {} but got {}",
355 object.interface.name,
356 id.id,
357 message_desc.name,
358 object.version,
359 version
360 );
361 }
362 }
363 Some((iface, version))
364 } else if let Some(child_interface) = message_desc.child_interface {
365 Some((child_interface, object.version))
366 } else {
367 panic!(
368 "Error when sending request {}@{}.{}: target interface must be specified for a generic constructor.",
369 object.interface.name,
370 id.id,
371 message_desc.name
372 );
373 }
374 } else {
375 None
376 };
377
378 let child = if let Some((child_interface, child_version)) = child_spec {
379 let child_serial = guard.next_serial();
380
381 let child = Object {
382 interface: child_interface,
383 version: child_version,
384 data: Data {
385 client_destroyed: false,
386 server_destroyed: false,
387 user_data: Arc::new(DumbObjectData),
388 serial: child_serial,
389 },
390 };
391
392 let child_id = guard.map.client_insert_new(child);
393
394 guard
395 .map
396 .with(child_id, |obj| {
397 obj.data.user_data = data.expect(
398 "Sending a request creating an object without providing an object data.",
399 );
400 })
401 .unwrap();
402 Some((child_id, child_serial, child_interface))
403 } else {
404 None
405 };
406
407 // Prepare the message in a debug-compatible way
408 let args = args.into_iter().map(|arg| {
409 if let Argument::NewId(ObjectId { id: p }) = arg {
410 if !p.id == 0 {
411 panic!("The newid provided when sending request {}@{}.{} is not a placeholder.", object.interface.name, id.id, message_desc.name);
412 }
413 if let Some((child_id, child_serial, child_interface)) = child {
414 Argument::NewId(ObjectId { id: InnerObjectId { id: child_id, serial: child_serial, interface: child_interface}})
415 } else {
416 unreachable!();
417 }
418 } else {
419 arg
420 }
421 }).collect::<SmallVec<[_; INLINE_ARGS]>>();
422
423 if guard.debug {
424 debug::print_send_message(
425 object.interface.name,
426 id.id,
427 message_desc.name,
428 &args,
429 false,
430 );
431 }
432 #[cfg(feature = "log")]
433 crate::log_debug!("Sending {}.{} ({})", id, message_desc.name, debug::DisplaySlice(&args));
434
435 // Send the message
436
437 let mut msg_args = SmallVec::with_capacity(args.len());
438 let mut arg_interfaces = message_desc.arg_interfaces.iter();
439 for (i, arg) in args.into_iter().enumerate() {
440 msg_args.push(match arg {
441 Argument::Array(a) => Argument::Array(a),
442 Argument::Int(i) => Argument::Int(i),
443 Argument::Uint(u) => Argument::Uint(u),
444 Argument::Str(s) => Argument::Str(s),
445 Argument::Fixed(f) => Argument::Fixed(f),
446 Argument::NewId(nid) => Argument::NewId(nid.id.id),
447 Argument::Fd(f) => Argument::Fd(f),
448 Argument::Object(o) => {
449 let next_interface = arg_interfaces.next().unwrap();
450 if o.id.id != 0 {
451 let arg_object = guard.get_object(o.id.clone())?;
452 if !same_interface_or_anonymous(next_interface, arg_object.interface) {
453 panic!("Request {}@{}.{} expects an argument of interface {} but {} was provided instead.", object.interface.name, id.id, message_desc.name, next_interface.name, arg_object.interface.name);
454 }
455 } else if !matches!(message_desc.signature[i], ArgumentType::Object(AllowNull::Yes)) {
456 panic!("Request {}@{}.{} expects an non-null object argument.", object.interface.name, id.id, message_desc.name);
457 }
458 Argument::Object(o.id.id)
459 }
460 });
461 }
462
463 let msg = Message { sender_id: id.id, opcode, args: msg_args };
464
465 if let Err(err) = guard.socket.write_message(&msg) {
466 guard.last_error = Some(WaylandError::Io(err));
467 }
468
469 // Handle destruction if relevant
470 if message_desc.is_destructor {
471 guard
472 .map
473 .with(id.id, |obj| {
474 obj.data.client_destroyed = true;
475 })
476 .unwrap();
477 object.data.user_data.destroyed(ObjectId { id });
478 }
479 if let Some((child_id, child_serial, child_interface)) = child {
480 Ok(ObjectId {
481 id: InnerObjectId {
482 id: child_id,
483 serial: child_serial,
484 interface: child_interface,
485 },
486 })
487 } else {
488 Ok(Self::null_id())
489 }
490 }
491
492 pub fn get_data(&self, id: ObjectId) -> Result<Arc<dyn ObjectData>, InvalidId> {
493 let object = self.state.lock_protocol().get_object(id.id)?;
494 Ok(object.data.user_data)
495 }
496
497 pub fn set_data(&self, id: ObjectId, data: Arc<dyn ObjectData>) -> Result<(), InvalidId> {
498 self.state
499 .lock_protocol()
500 .map
501 .with(id.id.id, move |objdata| {
502 if objdata.data.serial != id.id.serial {
503 Err(InvalidId)
504 } else {
505 objdata.data.user_data = data;
506 Ok(())
507 }
508 })
509 .unwrap_or(Err(InvalidId))
510 }
511
512 // Nothing to do here, we don't have an inner queue
513 pub fn dispatch_inner_queue(&self) -> Result<usize, WaylandError> {
514 Ok(0)
515 }
516}
517
518impl ProtocolState {
519 fn next_serial(&mut self) -> u32 {
520 self.last_serial = self.last_serial.wrapping_add(1);
521 self.last_serial
522 }
523
524 #[inline]
525 fn no_last_error(&self) -> Result<(), WaylandError> {
526 if let Some(ref err) = self.last_error {
527 Err(err.clone())
528 } else {
529 Ok(())
530 }
531 }
532
533 #[inline]
534 fn store_and_return_error(&mut self, err: impl Into<WaylandError>) -> WaylandError {
535 let err = err.into();
536 crate::log_error!("{}", err);
537 self.last_error = Some(err.clone());
538 err
539 }
540
541 #[inline]
542 fn store_if_not_wouldblock_and_return_error(&mut self, e: std::io::Error) -> WaylandError {
543 if e.kind() != std::io::ErrorKind::WouldBlock {
544 self.store_and_return_error(e)
545 } else {
546 e.into()
547 }
548 }
549
550 fn get_object(&self, id: InnerObjectId) -> Result<Object<Data>, InvalidId> {
551 let object = self.map.find(id.id).ok_or(InvalidId)?;
552 if object.data.serial != id.serial {
553 return Err(InvalidId);
554 }
555 Ok(object)
556 }
557
558 fn handle_display_event(&mut self, message: Message<u32, OwnedFd>) -> Result<(), WaylandError> {
559 if self.debug {
560 debug::print_dispatched_message(
561 "wl_display",
562 message.sender_id,
563 if message.opcode == 0 { "error" } else { "delete_id" },
564 &message.args,
565 );
566 }
567 match message.opcode {
568 0 => {
569 // wl_display.error
570 if let [Argument::Object(obj), Argument::Uint(code), Argument::Str(Some(ref message))] =
571 message.args[..]
572 {
573 let object = self.map.find(obj);
574 let err = WaylandError::Protocol(ProtocolError {
575 code,
576 object_id: obj,
577 object_interface: object
578 .map(|obj| obj.interface.name)
579 .unwrap_or("<unknown>")
580 .into(),
581 message: message.to_string_lossy().into(),
582 });
583 return Err(self.store_and_return_error(err));
584 } else {
585 unreachable!()
586 }
587 }
588 1 => {
589 // wl_display.delete_id
590 if let [Argument::Uint(id)] = message.args[..] {
591 let client_destroyed = self
592 .map
593 .with(id, |obj| {
594 obj.data.server_destroyed = true;
595 obj.data.client_destroyed
596 })
597 .unwrap_or(false);
598 if client_destroyed {
599 self.map.remove(id);
600 }
601 } else {
602 unreachable!()
603 }
604 }
605 _ => unreachable!(),
606 }
607 Ok(())
608 }
609}
610
611fn dispatch_events(state: Arc<ConnectionState>) -> Result<usize, WaylandError> {
612 let backend = Backend { backend: InnerBackend { state } };
613 let mut guard = backend.backend.state.lock_protocol();
614 guard.no_last_error()?;
615 let mut dispatched = 0;
616 loop {
617 // Attempt to read a message
618 let ProtocolState { ref mut socket, ref map, .. } = *guard;
619 let message = match socket.read_one_message(|id, opcode| {
620 map.find(id)
621 .and_then(|o| o.interface.events.get(opcode as usize))
622 .map(|desc| desc.signature)
623 }) {
624 Ok(msg) => msg,
625 Err(MessageParseError::MissingData) | Err(MessageParseError::MissingFD) => {
626 // need to read more data
627 if let Err(e) = guard.socket.fill_incoming_buffers() {
628 if e.kind() != std::io::ErrorKind::WouldBlock {
629 return Err(guard.store_and_return_error(e));
630 } else if dispatched == 0 {
631 return Err(e.into());
632 } else {
633 break;
634 }
635 }
636 continue;
637 }
638 Err(MessageParseError::Malformed) => {
639 // malformed error, protocol error
640 let err = WaylandError::Protocol(ProtocolError {
641 code: 0,
642 object_id: 0,
643 object_interface: "".into(),
644 message: "Malformed Wayland message.".into(),
645 });
646 return Err(guard.store_and_return_error(err));
647 }
648 };
649
650 // We got a message, retrieve its associated object & details
651 // These lookups must succeed otherwise we would not have been able to parse this message
652 let receiver = guard.map.find(message.sender_id).unwrap();
653 let message_desc = receiver.interface.events.get(message.opcode as usize).unwrap();
654
655 // Short-circuit display-associated events
656 if message.sender_id == 1 {
657 guard.handle_display_event(message)?;
658 continue;
659 }
660
661 let mut created_id = None;
662
663 // Convert the arguments and create the new object if applicable
664 let mut args = SmallVec::with_capacity(message.args.len());
665 let mut arg_interfaces = message_desc.arg_interfaces.iter();
666 for arg in message.args.into_iter() {
667 args.push(match arg {
668 Argument::Array(a) => Argument::Array(a),
669 Argument::Int(i) => Argument::Int(i),
670 Argument::Uint(u) => Argument::Uint(u),
671 Argument::Str(s) => Argument::Str(s),
672 Argument::Fixed(f) => Argument::Fixed(f),
673 Argument::Fd(f) => Argument::Fd(f),
674 Argument::Object(o) => {
675 if o != 0 {
676 // Lookup the object to make the appropriate Id
677 let obj = match guard.map.find(o) {
678 Some(o) => o,
679 None => {
680 let err = WaylandError::Protocol(ProtocolError {
681 code: 0,
682 object_id: 0,
683 object_interface: "".into(),
684 message: format!("Unknown object {}.", o),
685 });
686 return Err(guard.store_and_return_error(err));
687 }
688 };
689 if let Some(next_interface) = arg_interfaces.next() {
690 if !same_interface_or_anonymous(next_interface, obj.interface) {
691 let err = WaylandError::Protocol(ProtocolError {
692 code: 0,
693 object_id: 0,
694 object_interface: "".into(),
695 message: format!(
696 "Protocol error: server sent object {} for interface {}, but it has interface {}.",
697 o, next_interface.name, obj.interface.name
698 ),
699 });
700 return Err(guard.store_and_return_error(err));
701 }
702 }
703 Argument::Object(ObjectId { id: InnerObjectId { id: o, serial: obj.data.serial, interface: obj.interface }})
704 } else {
705 Argument::Object(ObjectId { id: InnerObjectId { id: 0, serial: 0, interface: &ANONYMOUS_INTERFACE }})
706 }
707 }
708 Argument::NewId(new_id) => {
709 // An object should be created
710 let child_interface = match message_desc.child_interface {
711 Some(iface) => iface,
712 None => panic!("Received event {}@{}.{} which creates an object without specifying its interface, this is unsupported.", receiver.interface.name, message.sender_id, message_desc.name),
713 };
714
715 let child_udata = Arc::new(UninitObjectData);
716
717 // if this ID belonged to a now destroyed server object, we can replace it
718 if new_id >= SERVER_ID_LIMIT
719 && guard.map.with(new_id, |obj| obj.data.client_destroyed).unwrap_or(false)
720 {
721 guard.map.remove(new_id);
722 }
723
724 let child_obj = Object {
725 interface: child_interface,
726 version: receiver.version,
727 data: Data {
728 client_destroyed: receiver.data.client_destroyed,
729 server_destroyed: false,
730 user_data: child_udata,
731 serial: guard.next_serial(),
732 }
733 };
734
735 let child_id = InnerObjectId { id: new_id, serial: child_obj.data.serial, interface: child_obj.interface };
736 created_id = Some(child_id.clone());
737
738 if let Err(()) = guard.map.insert_at(new_id, child_obj) {
739 // abort parsing, this is an unrecoverable error
740 let err = WaylandError::Protocol(ProtocolError {
741 code: 0,
742 object_id: 0,
743 object_interface: "".into(),
744 message: format!(
745 "Protocol error: server tried to create \
746 an object \"{}\" with invalid id {}.",
747 child_interface.name, new_id
748 ),
749 });
750 return Err(guard.store_and_return_error(err));
751 }
752
753 Argument::NewId(ObjectId { id: child_id })
754 }
755 });
756 }
757
758 if guard.debug {
759 debug::print_dispatched_message(
760 receiver.interface.name,
761 message.sender_id,
762 message_desc.name,
763 &args,
764 );
765 }
766
767 // If this event is send to an already destroyed object (by the client), swallow it
768 if receiver.data.client_destroyed {
769 continue;
770 }
771
772 // Invoke the user callback
773 let id = InnerObjectId {
774 id: message.sender_id,
775 serial: receiver.data.serial,
776 interface: receiver.interface,
777 };
778
779 // unlock the mutex while we invoke the user callback
780 std::mem::drop(guard);
781 #[cfg(feature = "log")]
782 crate::log_debug!(
783 "Dispatching {}.{} ({})",
784 id,
785 receiver.version,
786 debug::DisplaySlice(&args)
787 );
788 let ret = receiver
789 .data
790 .user_data
791 .clone()
792 .event(&backend, Message { sender_id: ObjectId { id }, opcode: message.opcode, args });
793 // lock it again to resume dispatching
794 guard = backend.backend.state.lock_protocol();
795
796 // If this event is a destructor, destroy the object
797 if message_desc.is_destructor {
798 guard
799 .map
800 .with(message.sender_id, |obj| {
801 obj.data.server_destroyed = true;
802 obj.data.client_destroyed = true;
803 })
804 .unwrap();
805 receiver.data.user_data.destroyed(ObjectId {
806 id: InnerObjectId {
807 id: message.sender_id,
808 serial: receiver.data.serial,
809 interface: receiver.interface,
810 },
811 });
812 }
813
814 match (created_id, ret) {
815 (Some(child_id), Some(child_data)) => {
816 guard.map.with(child_id.id, |obj| obj.data.user_data = child_data).unwrap();
817 }
818 (None, None) => {}
819 (Some(child_id), None) => {
820 panic!("Callback creating object {} did not provide any object data.", child_id);
821 }
822 (None, Some(_)) => {
823 panic!("An object data was returned from a callback not creating any object");
824 }
825 }
826
827 dispatched += 1;
828 }
829 Ok(dispatched)
830}
831