1//! Read X11 packets from a reader
2
3use std::io::{Error, ErrorKind, Result};
4use std::{cmp, fmt, io};
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&mut DebugStruct<'_, '_>.debug_struct("PacketReader")
21 .field(
22 "read_buffer",
23 &format_args!("[buffer of size {}]", self.read_buffer.len()),
24 )
25 .field(name:"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() == io::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() == io::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}
209