1 //! Read X11 packets from a reader
2
3 use std::convert::TryInto;
4 use std::io::{Error, ErrorKind, Result};
5
6 use super::Stream;
7 use crate::utils::RawFdContainer;
8
9 /// Minimal length of an X11 packet
10 const MINIMAL_PACKET_LENGTH: usize = 32;
11
12 /// A wrapper around a reader that reads X11 packet.
13 #[derive(Debug)]
14 pub(crate) struct PacketReader {
15 read_buffer: Box<[u8]>,
16
17 // A packet that was partially read.
18 pending_packet: Vec<u8>,
19 // Up to where the packet is already read.
20 already_read: usize,
21 }
22
23 impl PacketReader {
24 /// Create a new `PacketReader` that reads from the given stream.
new() -> Self25 pub(crate) fn new() -> Self {
26 Self {
27 // Buffer size chosen by checking what libxcb does
28 read_buffer: vec![0; 4096].into_boxed_slice(),
29 pending_packet: vec![0; MINIMAL_PACKET_LENGTH],
30 already_read: 0,
31 }
32 }
33
34 /// To be called after `nread` bytes have been writen into `pending_packet`.
handle_partial_read(&mut self, nread: usize, out_packets: &mut Vec<Vec<u8>>)35 fn handle_partial_read(&mut self, nread: usize, out_packets: &mut Vec<Vec<u8>>) {
36 self.already_read += nread;
37 // Do we still need to compute the length field? (length == MINIMAL_PACKET_LENGTH)
38 if self.already_read == MINIMAL_PACKET_LENGTH {
39 // Yes, then compute the packet length and resize the `Vec` to its final size.
40 let extra = extra_length(self.pending_packet[..].try_into().unwrap());
41 self.pending_packet.reserve_exact(extra);
42 self.pending_packet.resize(MINIMAL_PACKET_LENGTH + extra, 0);
43 }
44
45 // Has the packet been completely read?
46 if self.already_read == self.pending_packet.len() {
47 // Check that we really read the whole packet
48 let initial_packet = &self.pending_packet[0..MINIMAL_PACKET_LENGTH]
49 .try_into()
50 .unwrap();
51 let extra = extra_length(&initial_packet);
52 assert_eq!(self.pending_packet.len(), MINIMAL_PACKET_LENGTH + extra);
53
54 out_packets.push(std::mem::replace(
55 &mut self.pending_packet,
56 vec![0; MINIMAL_PACKET_LENGTH],
57 ));
58 self.already_read = 0;
59 }
60 }
61
62 /// Reads as many packets as possible from stream reader without blocking.
try_read_packets( &mut self, stream: &impl Stream, out_packets: &mut Vec<Vec<u8>>, fd_storage: &mut Vec<RawFdContainer>, ) -> Result<()>63 pub(crate) fn try_read_packets(
64 &mut self,
65 stream: &impl Stream,
66 out_packets: &mut Vec<Vec<u8>>,
67 fd_storage: &mut Vec<RawFdContainer>,
68 ) -> Result<()> {
69 loop {
70 if (self.pending_packet.len() - self.already_read) >= self.read_buffer.len() {
71 assert_ne!(self.already_read, self.pending_packet.len());
72 // Bypass the read buffer
73 match stream.read(&mut self.pending_packet[self.already_read..], fd_storage) {
74 Ok(0) => {
75 return Err(Error::new(
76 ErrorKind::UnexpectedEof,
77 "The X11 server closed the connection",
78 ));
79 }
80 Ok(nread) => self.handle_partial_read(nread, out_packets),
81 Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => break,
82 Err(e) => return Err(e),
83 }
84 } else {
85 // Fill the read buffer
86 match stream.read(&mut self.read_buffer, fd_storage) {
87 Ok(0) => {
88 return Err(Error::new(
89 ErrorKind::UnexpectedEof,
90 "The X11 server closed the connection",
91 ));
92 }
93 Ok(nread) => {
94 let mut used_from_buffer = 0;
95 // Take packets from `read_buffer`.
96 while used_from_buffer != nread {
97 let rem_read_buffer = &self.read_buffer[used_from_buffer..nread];
98 let rem_packet = &mut self.pending_packet[self.already_read..];
99 let to_copy = rem_read_buffer.len().min(rem_packet.len());
100 assert_ne!(to_copy, 0);
101 rem_packet[..to_copy].copy_from_slice(&rem_read_buffer[..to_copy]);
102 used_from_buffer += to_copy;
103 self.handle_partial_read(to_copy, out_packets);
104 }
105 }
106 Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => break,
107 Err(e) => return Err(e),
108 }
109 }
110 }
111
112 Ok(())
113 }
114 }
115
116 // Compute the length beyond `MINIMAL_PACKET_LENGTH` of an X11 packet.
extra_length(buffer: &[u8; MINIMAL_PACKET_LENGTH]) -> usize117 fn extra_length(buffer: &[u8; MINIMAL_PACKET_LENGTH]) -> usize {
118 use crate::protocol::xproto::GE_GENERIC_EVENT;
119
120 let response_type = buffer[0];
121
122 const REPLY: u8 = 1;
123 if response_type == REPLY || response_type & 0x7f == GE_GENERIC_EVENT {
124 let length_field = buffer[4..8].try_into().unwrap();
125 let length_field = u32::from_ne_bytes(length_field) as usize;
126 4 * length_field
127 } else {
128 // Fixed size packet: error or event that is not GE_GENERIC_EVENT
129 0
130 }
131 }
132