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