x11rb/rust_connection/
packet_reader.rs

1//! Read X11 packets from a reader
2
3use std::io::{Error, ErrorKind, Result};
4use std::{cmp, fmt};
5
6use super::Stream;
7use crate::utils::RawFdContainer;
8use x11rb_protocol::packet_reader::PacketReader as ProtoPacketReader;
9
10/// A wrapper around a reader that reads X11 packet.
11pub(crate) struct PacketReader {
12    /// The read buffer to store incoming bytes in.
13    read_buffer: Box<[u8]>,
14    /// The inner reader that breaks these bytes into packets.
15    inner: ProtoPacketReader,
16}
17
18impl fmt::Debug for PacketReader {
19    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
20        f.debug_struct("PacketReader")
21            .field(
22                "read_buffer",
23                &format_args!("[buffer of size {}]", self.read_buffer.len()),
24            )
25            .field("inner", &self.inner)
26            .finish()
27    }
28}
29
30impl PacketReader {
31    /// Create a new `PacketReader` that reads from the given stream.
32    pub(crate) fn new() -> Self {
33        Self {
34            // Buffer size chosen by checking what libxcb does
35            read_buffer: vec![0; 4096].into_boxed_slice(),
36            inner: ProtoPacketReader::new(),
37        }
38    }
39
40    /// Reads as many packets as possible from stream reader without blocking.
41    pub(crate) fn try_read_packets(
42        &mut self,
43        stream: &impl Stream,
44        out_packets: &mut Vec<Vec<u8>>,
45        fd_storage: &mut Vec<RawFdContainer>,
46    ) -> Result<()> {
47        let original_length = out_packets.len();
48        loop {
49            // if the necessary packet size is larger than our buffer, just fill straight
50            // into the buffer
51            if self.inner.remaining_capacity() >= self.read_buffer.len() {
52                crate::trace!(
53                    "Trying to read large packet with {} bytes remaining",
54                    self.inner.remaining_capacity()
55                );
56                match stream.read(self.inner.buffer(), fd_storage) {
57                    Ok(0) => {
58                        crate::error!("Large read returned zero");
59                        return Err(Error::new(
60                            ErrorKind::UnexpectedEof,
61                            "The X11 server closed the connection",
62                        ));
63                    }
64                    Ok(n) => {
65                        crate::trace!("Read {} bytes directly into large packet", n);
66                        if let Some(packet) = self.inner.advance(n) {
67                            out_packets.push(packet);
68                        }
69                    }
70                    Err(ref e) if e.kind() == ErrorKind::WouldBlock => break,
71                    Err(e) => return Err(e),
72                }
73            } else {
74                // read into our buffer
75                let nread = match stream.read(&mut self.read_buffer, fd_storage) {
76                    Ok(0) => {
77                        crate::error!("Buffered read returned zero");
78                        return Err(Error::new(
79                            ErrorKind::UnexpectedEof,
80                            "The X11 server closed the connection",
81                        ));
82                    }
83                    Ok(n) => n,
84                    Err(ref e) if e.kind() == ErrorKind::WouldBlock => break,
85                    Err(e) => return Err(e),
86                };
87                crate::trace!("Read {} bytes into read buffer", nread);
88
89                // begin reading that data into packets
90                let mut src = &self.read_buffer[..nread];
91                while !src.is_empty() {
92                    let dest = self.inner.buffer();
93                    let amt_to_read = cmp::min(src.len(), dest.len());
94
95                    // copy slices over
96                    dest[..amt_to_read].copy_from_slice(&src[..amt_to_read]);
97
98                    // reborrow src
99                    src = &src[amt_to_read..];
100
101                    // advance by the given amount
102                    if let Some(packet) = self.inner.advance(amt_to_read) {
103                        out_packets.push(packet);
104                    }
105                }
106            }
107        }
108        crate::trace!(
109            "Read {} complete packet(s)",
110            out_packets.len() - original_length
111        );
112
113        Ok(())
114    }
115}
116
117#[cfg(test)]
118mod tests {
119    use super::PacketReader;
120    use crate::rust_connection::{PollMode, Stream};
121    use crate::utils::RawFdContainer;
122    use std::cell::RefCell;
123    use std::cmp;
124    use std::io::{Error, ErrorKind, Result};
125
126    // make a Stream that just reads from a Vec<u8>
127    struct TestStream {
128        data: RefCell<Vec<u8>>,
129    }
130
131    impl TestStream {
132        fn new(data: Vec<u8>) -> Self {
133            Self {
134                data: RefCell::new(data),
135            }
136        }
137    }
138
139    impl Stream for TestStream {
140        fn read(&self, buf: &mut [u8], _: &mut Vec<RawFdContainer>) -> Result<usize> {
141            let mut data = self.data.borrow_mut();
142            if data.len() == 0 {
143                return Err(Error::from(ErrorKind::WouldBlock));
144            }
145
146            let nread = cmp::min(data.len(), buf.len());
147            buf[..nread].copy_from_slice(&data[..nread]);
148            let _ = data.drain(..nread);
149            Ok(nread)
150        }
151
152        fn poll(&self, _: PollMode) -> Result<()> {
153            Ok(())
154        }
155
156        fn write(&self, _: &[u8], _: &mut Vec<RawFdContainer>) -> Result<usize> {
157            unreachable!()
158        }
159    }
160
161    fn test_packet(packet: Vec<u8>) {
162        let mut reader = PacketReader::new();
163        let original_packet = packet.clone();
164        let stream = TestStream::new(packet);
165
166        let mut packets = Vec::new();
167        let mut fd_storage = Vec::new();
168
169        reader
170            .try_read_packets(&stream, &mut packets, &mut fd_storage)
171            .unwrap();
172
173        assert_eq!(packets.len(), 1);
174        assert_eq!(packets[0], original_packet);
175    }
176
177    #[test]
178    fn fixed_size_packet() {
179        let packet = vec![0; 32];
180        test_packet(packet);
181    }
182
183    #[test]
184    fn variable_size_packet() {
185        let mut len = 120;
186        let mut packet = vec![0; len];
187        len = (len - 32) / 4;
188
189        // copy len to 4..8
190        packet[4..8].copy_from_slice(&(len as u32).to_ne_bytes());
191        packet[0] = 1;
192
193        test_packet(packet);
194    }
195
196    #[test]
197    fn very_large_packet() {
198        let mut len = 4800;
199        let mut packet = vec![0; len];
200        len = (len - 32) / 4;
201
202        // copy len to 4..8
203        packet[4..8].copy_from_slice(&(len as u32).to_ne_bytes());
204        packet[0] = 1;
205
206        test_packet(packet);
207    }
208}