1 | //! Client-side rust implementation of a Wayland protocol backend |
2 | |
3 | use 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 | |
13 | use 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 | }; |
22 | use smallvec::SmallVec; |
23 | |
24 | use super::{ |
25 | client::*, |
26 | map::{Object, ObjectMap, SERVER_ID_LIMIT}, |
27 | socket::{BufferedSocket, Socket}, |
28 | wire::MessageParseError, |
29 | }; |
30 | |
31 | pub use crate::types::client::{InvalidId, NoWaylandLib, WaylandError}; |
32 | |
33 | #[derive (Debug, Clone)] |
34 | struct 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)] |
43 | pub struct InnerObjectId { |
44 | serial: u32, |
45 | id: u32, |
46 | interface: &'static Interface, |
47 | } |
48 | |
49 | impl 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 | |
57 | impl std::cmp::Eq for InnerObjectId {} |
58 | |
59 | impl 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 | |
66 | impl 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 | |
73 | impl 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 | |
80 | impl 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)] |
95 | struct 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)] |
104 | struct ReadingState { |
105 | prepared_reads: usize, |
106 | read_condvar: Arc<Condvar>, |
107 | read_serial: usize, |
108 | } |
109 | |
110 | #[derive (Debug)] |
111 | pub struct ConnectionState { |
112 | protocol: Mutex<ProtocolState>, |
113 | read: Mutex<ReadingState>, |
114 | } |
115 | |
116 | impl 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)] |
127 | pub struct InnerBackend { |
128 | state: Arc<ConnectionState>, |
129 | } |
130 | |
131 | #[derive (Clone, Debug)] |
132 | pub struct WeakInnerBackend { |
133 | state: Weak<ConnectionState>, |
134 | } |
135 | |
136 | impl WeakInnerBackend { |
137 | pub fn upgrade(&self) -> Option<InnerBackend> { |
138 | Weak::upgrade(&self.state).map(|state: Arc| InnerBackend { state }) |
139 | } |
140 | } |
141 | |
142 | impl PartialEq for InnerBackend { |
143 | fn eq(&self, rhs: &Self) -> bool { |
144 | Arc::ptr_eq(&self.state, &rhs.state) |
145 | } |
146 | } |
147 | |
148 | impl Eq for InnerBackend {} |
149 | |
150 | impl 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)] |
212 | pub struct InnerReadEventsGuard { |
213 | state: Arc<ConnectionState>, |
214 | done: bool, |
215 | } |
216 | |
217 | impl 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 | |
268 | impl 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 | |
282 | impl 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 | |
518 | impl 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 | |
611 | fn 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 | |