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