Skip to main content

vnc/
config.rs

1use crate::VncError;
2use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
3
4/// All supported vnc encodings
5#[allow(dead_code)]
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7#[repr(i32)]
8pub enum VncEncoding {
9    Raw = 0,
10    CopyRect = 1,
11    // Rre = 2,
12    // Hextile = 5,
13    Tight = 7,
14    Trle = 15,
15    Zrle = 16,
16    CursorPseudo = -239,
17    DesktopSizePseudo = -223,
18    LastRectPseudo = -224,
19}
20
21impl From<u32> for VncEncoding {
22    fn from(num: u32) -> Self {
23        // Safe match instead of transmute — unknown encoding IDs fall back to Raw
24        // instead of causing UB (the original transmute is unsound for any value
25        // not matching a valid discriminant).
26        match num as i32 {
27            0 => VncEncoding::Raw,
28            1 => VncEncoding::CopyRect,
29            7 => VncEncoding::Tight,
30            15 => VncEncoding::Trle,
31            16 => VncEncoding::Zrle,
32            -239 => VncEncoding::CursorPseudo,
33            -223 => VncEncoding::DesktopSizePseudo,
34            -224 => VncEncoding::LastRectPseudo,
35            _ => VncEncoding::Raw,
36        }
37    }
38}
39
40impl From<VncEncoding> for u32 {
41    fn from(e: VncEncoding) -> Self {
42        e as u32
43    }
44}
45
46/// All supported vnc versions
47#[allow(dead_code)]
48#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq)]
49#[repr(u8)]
50pub enum VncVersion {
51    RFB33,
52    RFB37,
53    RFB38,
54}
55
56impl From<[u8; 12]> for VncVersion {
57    fn from(version: [u8; 12]) -> Self {
58        match &version {
59            b"RFB 003.003\n" => VncVersion::RFB33,
60            b"RFB 003.007\n" => VncVersion::RFB37,
61            b"RFB 003.008\n" => VncVersion::RFB38,
62            // https://www.rfc-editor.org/rfc/rfc6143#section-7.1.1
63            //  Other version numbers are reported by some servers and clients,
64            //  but should be interpreted as 3.3 since they do not implement the
65            //  different handshake in 3.7 or 3.8.
66            _ => VncVersion::RFB33,
67        }
68    }
69}
70
71impl From<VncVersion> for &[u8; 12] {
72    fn from(version: VncVersion) -> Self {
73        match version {
74            VncVersion::RFB33 => b"RFB 003.003\n",
75            VncVersion::RFB37 => b"RFB 003.007\n",
76            VncVersion::RFB38 => b"RFB 003.008\n",
77        }
78    }
79}
80
81impl VncVersion {
82    pub(crate) async fn read<S>(reader: &mut S) -> Result<Self, VncError>
83    where
84        S: AsyncRead + Unpin,
85    {
86        let mut buffer = [0_u8; 12];
87        reader.read_exact(&mut buffer).await?;
88        Ok(buffer.into())
89    }
90
91    pub(crate) async fn write<S>(self, writer: &mut S) -> Result<(), VncError>
92    where
93        S: AsyncWrite + Unpin,
94    {
95        writer
96            .write_all(&<VncVersion as Into<&[u8; 12]>>::into(self)[..])
97            .await?;
98        Ok(())
99    }
100}
101
102///  Pixel Format Data Structure according to [RFC6143](https://www.rfc-editor.org/rfc/rfc6143.html#section-7.4)
103///
104/// ```text
105/// +--------------+--------------+-----------------+
106/// | No. of bytes | Type [Value] | Description     |
107/// +--------------+--------------+-----------------+
108/// | 1            | U8           | bits-per-pixel  |
109/// | 1            | U8           | depth           |
110/// | 1            | U8           | big-endian-flag |
111/// | 1            | U8           | true-color-flag |
112/// | 2            | U16          | red-max         |
113/// | 2            | U16          | green-max       |
114/// | 2            | U16          | blue-max        |
115/// | 1            | U8           | red-shift       |
116/// | 1            | U8           | green-shift     |
117/// | 1            | U8           | blue-shift      |
118/// | 3            |              | padding         |
119/// +--------------+--------------+-----------------+
120/// ```
121#[derive(Debug, Clone, Copy)]
122pub struct PixelFormat {
123    /// the number of bits used for each pixel value on the wire
124    ///
125    /// 8, 16, 32(usually) only
126    ///
127    pub bits_per_pixel: u8,
128    /// Although the depth should
129    ///
130    /// be consistent with the bits-per-pixel and the various -max values,
131    ///
132    /// clients do not use it when interpreting pixel data.
133    ///
134    pub depth: u8,
135    /// true if multi-byte pixels are interpreted as big endian
136    ///
137    pub big_endian_flag: u8,
138    /// true then the last six items specify how to extract the red, green and blue intensities from the pixel value
139    ///
140    pub true_color_flag: u8,
141    /// the next three always in big-endian order
142    /// no matter how the `big_endian_flag` is set
143    ///
144    pub red_max: u16,
145    pub green_max: u16,
146    pub blue_max: u16,
147    /// the number of shifts needed to get the red value in a pixel to the least significant bit
148    ///
149    pub red_shift: u8,
150    pub green_shift: u8,
151    pub blue_shift: u8,
152    _padding_1: u8,
153    _padding_2: u8,
154    _padding_3: u8,
155}
156
157impl From<PixelFormat> for Vec<u8> {
158    fn from(pf: PixelFormat) -> Vec<u8> {
159        vec![
160            pf.bits_per_pixel,
161            pf.depth,
162            pf.big_endian_flag,
163            pf.true_color_flag,
164            (pf.red_max >> 8) as u8,
165            pf.red_max as u8,
166            (pf.green_max >> 8) as u8,
167            pf.green_max as u8,
168            (pf.blue_max >> 8) as u8,
169            pf.blue_max as u8,
170            pf.red_shift,
171            pf.green_shift,
172            pf.blue_shift,
173            pf._padding_1,
174            pf._padding_2,
175            pf._padding_3,
176        ]
177    }
178}
179
180impl TryFrom<[u8; 16]> for PixelFormat {
181    type Error = VncError;
182
183    fn try_from(pf: [u8; 16]) -> Result<Self, Self::Error> {
184        let bits_per_pixel = pf[0];
185        if bits_per_pixel != 8 && bits_per_pixel != 16 && bits_per_pixel != 32 {
186            return Err(VncError::WrongPixelFormat);
187        }
188        let depth = pf[1];
189        let big_endian_flag = pf[2];
190        let true_color_flag = pf[3];
191        let red_max = u16::from_be_bytes(pf[4..6].try_into().unwrap());
192        let green_max = u16::from_be_bytes(pf[6..8].try_into().unwrap());
193        let blue_max = u16::from_be_bytes(pf[8..10].try_into().unwrap());
194        let red_shift = pf[10];
195        let green_shift = pf[11];
196        let blue_shift = pf[12];
197        let _padding_1 = pf[13];
198        let _padding_2 = pf[14];
199        let _padding_3 = pf[15];
200        Ok(PixelFormat {
201            bits_per_pixel,
202            depth,
203            big_endian_flag,
204            true_color_flag,
205            red_max,
206            green_max,
207            blue_max,
208            red_shift,
209            green_shift,
210            blue_shift,
211            _padding_1,
212            _padding_2,
213            _padding_3,
214        })
215    }
216}
217
218impl Default for PixelFormat {
219    // by default the pixel transformed is (a << 24 | r << 16 || g << 8 | b) in le
220    // which is [b, g, r, a] in network
221    fn default() -> Self {
222        Self {
223            bits_per_pixel: 32,
224            depth: 24,
225            big_endian_flag: 0,
226            true_color_flag: 1,
227            red_max: 255,
228            green_max: 255,
229            blue_max: 255,
230            red_shift: 16,
231            green_shift: 8,
232            blue_shift: 0,
233            _padding_1: 0,
234            _padding_2: 0,
235            _padding_3: 0,
236        }
237    }
238}
239
240impl PixelFormat {
241    // (a << 24 | r << 16 || g << 8 | b) in le
242    // [b, g, r, a] in network
243    pub fn bgra() -> PixelFormat {
244        PixelFormat::default()
245    }
246
247    // (a << 24 | b << 16 | g << 8 | r) in le
248    // which is [r, g, b, a] in network
249    pub fn rgba() -> PixelFormat {
250        Self {
251            red_shift: 0,
252            blue_shift: 16,
253            ..Default::default()
254        }
255    }
256
257    pub(crate) async fn read<S>(reader: &mut S) -> Result<Self, VncError>
258    where
259        S: AsyncRead + Unpin,
260    {
261        let mut pixel_buffer = [0_u8; 16];
262        reader.read_exact(&mut pixel_buffer).await?;
263        pixel_buffer.try_into()
264    }
265}