1 use std::cell::RefCell;
2 use std::os::unix::io::{FromRawFd, RawFd};
3 use std::sync::{Arc, Mutex};
4 
5 use nix::Result as NixResult;
6 
7 use wayland_commons::map::{Object, ObjectMap, SERVER_ID_LIMIT};
8 use wayland_commons::socket::{BufferedSocket, Socket};
9 use wayland_commons::wire::{Argument, ArgumentType, Message, MessageParseError};
10 
11 use super::proxy::ObjectMeta;
12 use super::queues::QueueBuffer;
13 
14 use crate::ProtocolError;
15 
16 #[derive(Clone, Debug)]
17 pub(crate) enum Error {
18     Protocol(ProtocolError),
19     Parse(MessageParseError),
20     Nix(::nix::Error),
21 }
22 
23 pub(crate) struct Connection {
24     pub(crate) socket: BufferedSocket,
25     pub(crate) map: Arc<Mutex<ObjectMap<ObjectMeta>>>,
26     pub(crate) last_error: Arc<Mutex<Option<Error>>>,
27     pub(crate) display_buffer: QueueBuffer,
28 }
29 
30 impl Connection {
new(fd: RawFd, display_object: Object<ObjectMeta>) -> Connection31     pub(crate) unsafe fn new(fd: RawFd, display_object: Object<ObjectMeta>) -> Connection {
32         let socket = BufferedSocket::new(Socket::from_raw_fd(fd));
33 
34         let mut map = ObjectMap::new();
35         // Insert first pre-existing object
36         let display_buffer = display_object.meta.buffer.clone();
37         map.insert_at(1, display_object).unwrap();
38 
39         Connection {
40             socket,
41             map: Arc::new(Mutex::new(map)),
42             last_error: Arc::new(Mutex::new(None)),
43             display_buffer,
44         }
45     }
46 
write_message(&mut self, msg: &Message) -> NixResult<()>47     pub(crate) fn write_message(&mut self, msg: &Message) -> NixResult<()> {
48         self.socket.write_message(msg)
49     }
50 
flush(&mut self) -> NixResult<()>51     pub(crate) fn flush(&mut self) -> NixResult<()> {
52         self.socket.flush()
53     }
54 
read_events(&mut self) -> Result<usize, Error>55     pub(crate) fn read_events(&mut self) -> Result<usize, Error> {
56         if let Some(ref err) = *self.last_error.lock().unwrap() {
57             return Err(err.clone());
58         }
59         // acquire the map lock, this means no objects can be created nor destroyed while we
60         // are reading events
61         let mut map = self.map.lock().unwrap();
62         // wrap it in a RefCell for cheap sharing in the two closures below
63         let map = RefCell::new(&mut *map);
64         let mut last_error = self.last_error.lock().unwrap();
65         // read messages
66         let ret = self.socket.read_messages(
67             |id, opcode| {
68                 map.borrow()
69                     .find(id)
70                     .and_then(|o| o.events.get(opcode as usize))
71                     .map(|desc| desc.signature)
72             },
73             |msg| {
74                 // Early exit on protocol error
75                 if msg.sender_id == 1 && msg.opcode == 0 {
76                     if let [Argument::Object(faulty_id), Argument::Uint(error_code), Argument::Str(ref error_msg)] = &msg.args[..] {
77                         let error_msg = error_msg.to_string_lossy().into_owned();
78                         let faulty_interface = map.borrow().find(*faulty_id).map(|obj| obj.interface).unwrap_or("unknown");
79                         // abort parsing, this is an unrecoverable error
80                         *last_error = Some(Error::Protocol(ProtocolError {
81                             code: *error_code,
82                             object_id: *faulty_id,
83                             object_interface: faulty_interface,
84                             message: error_msg
85                         }));
86                     } else {
87                         unreachable!();
88                     }
89                     return false;
90                 }
91 
92                 // dispatch the message to the proper object
93                 let mut map = map.borrow_mut();
94                 let object = map.find(msg.sender_id);
95 
96                 // create a new object if applicable
97                 if let Some((mut child, dead_parent)) = object
98                     .as_ref()
99                     .and_then(|o| o.event_child(msg.opcode).map(|c| (c, o.meta.client_destroyed)))
100                 {
101                     let new_id = msg
102                         .args
103                         .iter()
104                         .flat_map(|a| if let Argument::NewId(nid) = *a { Some(nid) } else { None })
105                         .next()
106                         .unwrap();
107                     let child_interface = child.interface;
108                     // if this ID belonged to a now destroyed server object, we can replace it
109                     if new_id >= SERVER_ID_LIMIT
110                         && map.with(new_id, |obj| obj.meta.client_destroyed).unwrap_or(false)
111                     {
112                         map.remove(new_id)
113                     }
114                     // if the parent object is already destroyed, the user will never see this
115                     // object, so we set it as client_destroyed to ignore all future messages to it
116                     if dead_parent {
117                         child.meta.client_destroyed = true;
118                     }
119                     if let Err(()) = map.insert_at(new_id, child) {
120                         // abort parsing, this is an unrecoverable error
121                         *last_error = Some(Error::Protocol(ProtocolError {
122                             code: 0,
123                             object_id: 0,
124                             object_interface: "",
125                             message: format!(
126                                 "Protocol error: server tried to create \
127                                 an object \"{}\" with invalid id \"{}\".",
128                                 child_interface, new_id
129                             ),
130                         }));
131                         return false;
132                     }
133                 } else {
134                     // debug assert: if this opcode does not define a child, then there should be no
135                     // NewId argument
136                     debug_assert!(!msg.args.iter().any(|a| a.get_type() == ArgumentType::NewId));
137                 }
138 
139                 // send the message to the appropriate pending queue
140                 match object {
141                     Some(Object { meta: ObjectMeta { client_destroyed: true, .. }, .. }) | None => {
142                         // this is a message sent to a destroyed object
143                         // to avoid dying because of races, we just consume it into void
144                         // closing any associated FDs
145                         for a in msg.args {
146                             if let Argument::Fd(fd) = a {
147                                 let _ = ::nix::unistd::close(fd);
148                             }
149                         }
150                     }
151                     Some(obj) => {
152                         obj.meta.buffer.lock().unwrap().push_back(msg);
153                     }
154                 };
155 
156                 // continue parsing
157                 true
158             },
159         );
160 
161         if let Some(ref e) = *last_error {
162             // a protocol error was generated, don't lose it, it is the source of any subsequent error
163             return Err(e.clone());
164         }
165 
166         match ret {
167             Ok(Ok(n)) => Ok(n),
168             Ok(Err(e)) => {
169                 *last_error = Some(Error::Parse(e.clone()));
170                 Err(Error::Parse(e))
171             }
172             // non-fatal error
173             Err(e @ ::nix::Error::Sys(::nix::errno::Errno::EAGAIN)) => Err(Error::Nix(e)),
174             // fatal errors
175             Err(e) => {
176                 *last_error = Some(Error::Nix(e));
177                 Err(Error::Nix(e))
178             }
179         }
180     }
181 }
182