rfb/
rfb.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4//
5// Copyright 2022 Oxide Computer Company
6
7use bitflags::bitflags;
8use futures::future::BoxFuture;
9use futures::FutureExt;
10use thiserror::Error;
11use tokio::io::{AsyncReadExt, AsyncWriteExt};
12use tokio::io::{AsyncRead,AsyncWrite};
13
14use crate::encodings::{Encoding, EncodingType};
15use crate::keysym::KeySym;
16use crate::pixel_formats::rgb_888;
17
18#[derive(Debug, Error)]
19pub enum ProtocolError {
20    #[error("invalid protocol version message")]
21    InvalidProtocolVersion,
22
23    #[error("invalid security type message ({0})")]
24    InvalidSecurityType(u8),
25
26    #[error("invalid text encoding")]
27    InvalidTextEncoding,
28
29    #[error("unknown client message type ({0})")]
30    UnknownClientMessageType(u8),
31
32    #[error(transparent)]
33    KeySymError(#[from] crate::keysym::KeySymError),
34
35    #[error("I/O error: {0}")]
36    Io(#[from] std::io::Error),
37}
38
39pub trait ReadMessage {
40    fn read_from<'a>(stream: &'a mut (impl AsyncRead + AsyncWrite + Unpin + Send + Sync)) -> BoxFuture<'a, Result<Self, ProtocolError>>
41    where
42        Self: Sized;
43}
44
45pub trait WriteMessage {
46    fn write_to<'a>(self, stream: &'a mut (impl AsyncRead + AsyncWrite + Unpin + Send + Sync)) -> BoxFuture<'a, Result<(), ProtocolError>>;
47}
48
49#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
50pub enum ProtoVersion {
51    Rfb33,
52    Rfb37,
53    Rfb38,
54}
55
56impl ReadMessage for ProtoVersion {
57    fn read_from<'a>(stream: &'a mut (impl AsyncRead + AsyncWrite + Unpin + Send + Sync)) -> BoxFuture<'a, Result<Self, ProtocolError>> {
58        async move {
59            let mut buf = [0u8; 12];
60            stream.read_exact(&mut buf).await?;
61
62            match &buf {
63                b"RFB 003.003\n" => Ok(ProtoVersion::Rfb33),
64                b"RFB 003.007\n" => Ok(ProtoVersion::Rfb37),
65                b"RFB 003.008\n" => Ok(ProtoVersion::Rfb38),
66                _ => Err(ProtocolError::InvalidProtocolVersion),
67            }
68        }
69        .boxed()
70    }
71}
72
73impl WriteMessage for ProtoVersion {
74    fn write_to<'a>(self, stream: &'a mut (impl AsyncRead + AsyncWrite + Unpin + Send + Sync)) -> BoxFuture<'a, Result<(), ProtocolError>> {
75        async move {
76            let s = match self {
77                ProtoVersion::Rfb33 => b"RFB 003.003\n",
78                ProtoVersion::Rfb37 => b"RFB 003.007\n",
79                ProtoVersion::Rfb38 => b"RFB 003.008\n",
80            };
81
82            Ok(stream.write_all(s).await?)
83        }
84        .boxed()
85    }
86}
87
88// Section 7.1.2
89#[derive(Debug, Clone)]
90pub struct SecurityTypes(pub Vec<SecurityType>);
91
92#[derive(Clone, PartialEq, Debug)]
93pub enum SecurityType {
94    None,
95    VncAuthentication,
96}
97
98impl WriteMessage for SecurityTypes {
99    fn write_to<'a>(self, stream: &'a mut (impl AsyncRead + AsyncWrite + Unpin + Send + Sync)) -> BoxFuture<'a, Result<(), ProtocolError>> {
100        async move {
101            // TODO: fix cast
102            stream.write_u8(self.0.len() as u8).await?;
103            for t in self.0.into_iter() {
104                t.write_to(stream).await?;
105            }
106
107            Ok(())
108        }
109        .boxed()
110    }
111}
112
113impl ReadMessage for SecurityType {
114    fn read_from<'a>(stream: &'a mut (impl AsyncRead + AsyncWrite + Unpin + Send + Sync)) -> BoxFuture<'a, Result<Self, ProtocolError>> {
115        async move {
116            let t = stream.read_u8().await?;
117            match t {
118                1 => Ok(SecurityType::None),
119                2 => Ok(SecurityType::VncAuthentication),
120                v => Err(ProtocolError::InvalidSecurityType(v)),
121            }
122        }
123        .boxed()
124    }
125}
126
127impl WriteMessage for SecurityType {
128    fn write_to<'a>(self, stream: &'a mut (impl AsyncRead + AsyncWrite + Unpin + Send + Sync)) -> BoxFuture<'a, Result<(), ProtocolError>> {
129        async move {
130            let val = match self {
131                SecurityType::None => 0,
132                SecurityType::VncAuthentication => 1,
133            };
134            stream.write_u8(val).await?;
135
136            Ok(())
137        }
138        .boxed()
139    }
140}
141
142// Section 7.1.3
143pub enum SecurityResult {
144    Success,
145    Failure(String),
146}
147
148impl WriteMessage for SecurityResult {
149    fn write_to<'a>(self, stream: &'a mut (impl AsyncRead + AsyncWrite + Unpin + Send + Sync)) -> BoxFuture<'a, Result<(), ProtocolError>> {
150        async move {
151            match self {
152                SecurityResult::Success => {
153                    stream.write_u32(0).await?;
154                }
155                SecurityResult::Failure(s) => {
156                    stream.write_u32(1).await?;
157                    stream.write_all(s.as_bytes()).await?;
158                }
159            };
160
161            Ok(())
162        }
163        .boxed()
164    }
165}
166
167// Section 7.3.1
168#[derive(Debug)]
169pub struct ClientInit {
170    pub shared: bool,
171}
172
173impl ReadMessage for ClientInit {
174    fn read_from<'a>(stream: &'a mut (impl AsyncRead + AsyncWrite + Unpin + Send + Sync)) -> BoxFuture<'a, Result<Self, ProtocolError>> {
175        async {
176            let flag = stream.read_u8().await?;
177            match flag {
178                0 => Ok(ClientInit { shared: false }),
179                _ => Ok(ClientInit { shared: true }),
180            }
181        }
182        .boxed()
183    }
184}
185
186// Section 7.3.2
187#[derive(Debug)]
188pub struct ServerInit {
189    initial_res: Resolution,
190    pixel_format: PixelFormat,
191    name: String,
192}
193
194impl ServerInit {
195    pub fn new(width: u16, height: u16, name: String, pixel_format: PixelFormat) -> Self {
196        Self {
197            initial_res: Resolution { width, height },
198            pixel_format,
199            name,
200        }
201    }
202}
203
204impl WriteMessage for ServerInit {
205    fn write_to<'a>(self, stream: &'a mut (impl AsyncRead + AsyncWrite + Unpin + Send + Sync)) -> BoxFuture<'a, Result<(), ProtocolError>> {
206        async move {
207            self.initial_res.write_to(stream).await?;
208            self.pixel_format.write_to(stream).await?;
209
210            // TODO: cast properly
211            stream.write_u32(self.name.len() as u32).await?;
212            stream.write_all(self.name.as_bytes()).await?;
213
214            Ok(())
215        }
216        .boxed()
217    }
218}
219
220pub enum _ServerMessage {
221    FramebufferUpdate(FramebufferUpdate),
222    SetColorMapEntries(SetColorMapEntries),
223    Bell,
224    ServerCutText(CutText),
225}
226
227pub struct FramebufferUpdate {
228    rectangles: Vec<Rectangle>,
229}
230
231impl FramebufferUpdate {
232    pub fn new(rectangles: Vec<Rectangle>) -> Self {
233        FramebufferUpdate { rectangles }
234    }
235
236    pub fn transform(&self, input_pf: &PixelFormat, output_pf: &PixelFormat) -> Self {
237        let mut rectangles = Vec::new();
238
239        for r in self.rectangles.iter() {
240            rectangles.push(r.transform(input_pf, output_pf));
241        }
242
243        FramebufferUpdate { rectangles }
244    }
245}
246
247#[derive(Debug, Copy, Clone)]
248pub(crate) struct Position {
249    x: u16,
250    y: u16,
251}
252
253impl ReadMessage for Position {
254    fn read_from<'a>(stream: &'a mut (impl AsyncRead + AsyncWrite + Unpin + Send + Sync)) -> BoxFuture<'a, Result<Self, ProtocolError>> {
255        async {
256            let x = stream.read_u16().await?;
257            let y = stream.read_u16().await?;
258
259            Ok(Position { x, y })
260        }
261        .boxed()
262    }
263}
264
265#[derive(Debug, Copy, Clone)]
266pub(crate) struct Resolution {
267    width: u16,
268    height: u16,
269}
270
271impl ReadMessage for Resolution {
272    fn read_from<'a>(stream: &'a mut (impl AsyncRead + AsyncWrite + Unpin + Send + Sync)) -> BoxFuture<'a, Result<Self, ProtocolError>> {
273        async {
274            let width = stream.read_u16().await?;
275            let height = stream.read_u16().await?;
276
277            Ok(Resolution { width, height })
278        }
279        .boxed()
280    }
281}
282
283impl WriteMessage for Resolution {
284    fn write_to<'a>(self, stream: &'a mut (impl AsyncRead + AsyncWrite + Unpin + Send + Sync)) -> BoxFuture<'a, Result<(), ProtocolError>> {
285        async move {
286            stream.write_u16(self.width).await?;
287            stream.write_u16(self.height).await?;
288            Ok(())
289        }
290        .boxed()
291    }
292}
293
294pub struct Rectangle {
295    position: Position,
296    dimensions: Resolution,
297    data: Box<dyn Encoding>,
298}
299
300impl Rectangle {
301    pub fn new(x: u16, y: u16, width: u16, height: u16, data: Box<dyn Encoding>) -> Self {
302        Rectangle {
303            position: Position { x, y },
304            dimensions: Resolution { width, height },
305            data,
306        }
307    }
308
309    pub fn transform(&self, input_pf: &PixelFormat, output_pf: &PixelFormat) -> Self {
310        Rectangle {
311            position: self.position,
312            dimensions: self.dimensions,
313            data: self.data.transform(input_pf, output_pf),
314        }
315    }
316}
317
318impl WriteMessage for Rectangle {
319    fn write_to<'a>(self, stream: &'a mut (impl AsyncRead + AsyncWrite + Unpin + Send + Sync)) -> BoxFuture<'a, Result<(), ProtocolError>> {
320        async move {
321            let encoding_type: i32 = self.data.get_type().into();
322
323            stream.write_u16(self.position.x).await?;
324            stream.write_u16(self.position.y).await?;
325            stream.write_u16(self.dimensions.width).await?;
326            stream.write_u16(self.dimensions.height).await?;
327            stream.write_i32(encoding_type).await?;
328
329            let data = self.data.encode();
330            stream.write_all(data).await?;
331
332            Ok(())
333        }
334        .boxed()
335    }
336}
337
338impl WriteMessage for FramebufferUpdate {
339    fn write_to<'a>(self, stream: &'a mut (impl AsyncRead + AsyncWrite + Unpin + Send + Sync)) -> BoxFuture<'a, Result<(), ProtocolError>> {
340        async move {
341            // TODO: type function?
342            stream.write_u8(0).await?;
343
344            // 1 byte of padding
345            stream.write_u8(0).await?;
346
347            // number of rectangles
348            let n_rect = self.rectangles.len() as u16;
349            stream.write_u16(n_rect).await?;
350
351            // rectangles
352            for r in self.rectangles.into_iter() {
353                r.write_to(stream).await?;
354            }
355
356            Ok(())
357        }
358        .boxed()
359    }
360}
361
362#[derive(Debug)]
363pub struct SetColorMapEntries {
364    _colors: Vec<_ColorMapEntry>,
365}
366
367#[derive(Debug)]
368pub struct _ColorMapEntry {
369    _color: u16,
370    _red: u16,
371    _blue: u16,
372    _green: u16,
373}
374
375// TODO: only ISO 8859-1 (Latin-1) text supported
376// used for client and server
377#[derive(Debug)]
378pub struct CutText {
379    _text: String,
380}
381
382// Section 7.4
383#[derive(Debug, Clone, PartialEq)]
384pub struct PixelFormat {
385    pub bits_per_pixel: u8, // TODO: must be 8, 16, or 32
386    pub depth: u8,          // TODO: must be < bits_per_pixel
387    pub big_endian: bool,
388    pub color_spec: ColorSpecification,
389}
390
391impl PixelFormat {
392    /// Constructor for a PixelFormat that uses a color format to specify colors.
393    pub fn new_colorformat(
394        bbp: u8,
395        depth: u8,
396        big_endian: bool,
397        red_shift: u8,
398        red_max: u16,
399        green_shift: u8,
400        green_max: u16,
401        blue_shift: u8,
402        blue_max: u16,
403    ) -> Self {
404        PixelFormat {
405            bits_per_pixel: bbp,
406            depth,
407            big_endian,
408            color_spec: ColorSpecification::ColorFormat(ColorFormat {
409                red_max,
410                green_max,
411                blue_max,
412                red_shift,
413                green_shift,
414                blue_shift,
415            }),
416        }
417    }
418
419    /// Returns true if the pixel format is RGB888 (8-bits per color and 32 bits per pixel).
420    pub fn is_rgb_888(&self) -> bool {
421        if self.bits_per_pixel != rgb_888::BITS_PER_PIXEL || self.depth != rgb_888::DEPTH {
422            return false;
423        }
424
425        match &self.color_spec {
426            ColorSpecification::ColorFormat(cf) => {
427                (cf.red_max == rgb_888::MAX_VALUE)
428                    && (cf.green_max == rgb_888::MAX_VALUE)
429                    && (cf.blue_max == rgb_888::MAX_VALUE)
430                    && (rgb_888::valid_shift(cf.red_shift))
431                    && (rgb_888::valid_shift(cf.green_shift))
432                    && (rgb_888::valid_shift(cf.blue_shift))
433            }
434            ColorSpecification::ColorMap(_) => false,
435        }
436    }
437}
438
439impl ReadMessage for PixelFormat {
440    fn read_from<'a>(stream: &'a mut (impl AsyncRead + AsyncWrite + Unpin + Send + Sync)) -> BoxFuture<'a, Result<Self, ProtocolError>> {
441        async {
442            let bits_per_pixel = stream.read_u8().await?;
443            let depth = stream.read_u8().await?;
444            let be_flag = stream.read_u8().await?;
445            let big_endian = match be_flag {
446                0 => false,
447                _ => true,
448            };
449            let color_spec = ColorSpecification::read_from(stream).await?;
450
451            // 3 bytes of padding
452            let mut buf = [0u8; 3];
453            stream.read_exact(&mut buf).await?;
454
455            Ok(Self {
456                bits_per_pixel,
457                depth,
458                big_endian,
459                color_spec,
460            })
461        }
462        .boxed()
463    }
464}
465
466impl WriteMessage for PixelFormat {
467    fn write_to<'a>(self, stream: &'a mut (impl AsyncRead + AsyncWrite + Unpin + Send + Sync)) -> BoxFuture<'a, Result<(), ProtocolError>> {
468        async move {
469            stream.write_u8(self.bits_per_pixel).await?;
470            stream.write_u8(self.depth).await?;
471            stream.write_u8(if self.big_endian { 1 } else { 0 }).await?;
472            self.color_spec.write_to(stream).await?;
473
474            // 3 bytes of padding
475            let buf = [0u8; 3];
476            stream.write_all(&buf).await?;
477
478            Ok(())
479        }
480        .boxed()
481    }
482}
483
484#[derive(Debug, Clone, PartialEq)]
485#[allow(dead_code)]
486pub enum ColorSpecification {
487    ColorFormat(ColorFormat),
488    ColorMap(ColorMap), // TODO: implement
489}
490
491#[derive(Debug, Clone, PartialEq)]
492pub struct ColorFormat {
493    // TODO: maxes must be 2^N - 1 for N bits per color
494    pub red_max: u16,
495    pub green_max: u16,
496    pub blue_max: u16,
497    pub red_shift: u8,
498    pub green_shift: u8,
499    pub blue_shift: u8,
500}
501
502#[derive(Debug, Clone, PartialEq)]
503pub struct ColorMap {}
504
505impl ReadMessage for ColorSpecification {
506    fn read_from<'a>(stream: &'a mut (impl AsyncRead + AsyncWrite + Unpin + Send + Sync)) -> BoxFuture<'a, Result<Self, ProtocolError>> {
507        async {
508            let tc_flag = stream.read_u8().await?;
509            match tc_flag {
510                0 => {
511                    // ColorMap
512                    unimplemented!()
513                }
514                _ => {
515                    // ColorFormat
516                    let red_max = stream.read_u16().await?;
517                    let green_max = stream.read_u16().await?;
518                    let blue_max = stream.read_u16().await?;
519
520                    let red_shift = stream.read_u8().await?;
521                    let green_shift = stream.read_u8().await?;
522                    let blue_shift = stream.read_u8().await?;
523
524                    Ok(ColorSpecification::ColorFormat(ColorFormat {
525                        red_max,
526                        green_max,
527                        blue_max,
528                        red_shift,
529                        green_shift,
530                        blue_shift,
531                    }))
532                }
533            }
534        }
535        .boxed()
536    }
537}
538
539impl WriteMessage for ColorSpecification {
540    fn write_to<'a>(self, stream: &'a mut (impl AsyncRead + AsyncWrite + Unpin + Send + Sync)) -> BoxFuture<'a, Result<(), ProtocolError>> {
541        async move {
542            match self {
543                ColorSpecification::ColorFormat(cf) => {
544                    stream.write_u8(1).await?; // true color
545                    stream.write_u16(cf.red_max).await?;
546                    stream.write_u16(cf.green_max).await?;
547                    stream.write_u16(cf.blue_max).await?;
548
549                    stream.write_u8(cf.red_shift).await?;
550                    stream.write_u8(cf.green_shift).await?;
551                    stream.write_u8(cf.blue_shift).await?;
552                }
553                ColorSpecification::ColorMap(_cm) => {
554                    unimplemented!()
555                }
556            };
557
558            Ok(())
559        }
560        .boxed()
561    }
562}
563
564// Section 7.5
565pub enum ClientMessage {
566    SetPixelFormat(PixelFormat),
567    SetEncodings(Vec<EncodingType>),
568    FramebufferUpdateRequest(FramebufferUpdateRequest),
569    KeyEvent(KeyEvent),
570    PointerEvent(PointerEvent),
571    ClientCutText(String),
572}
573
574impl ReadMessage for ClientMessage {
575    fn read_from<'a>(
576        stream: &'a mut (impl AsyncRead + AsyncWrite + Unpin + Send + Sync),
577    ) -> BoxFuture<'a, Result<ClientMessage, ProtocolError>> {
578        async {
579            let t = stream.read_u8().await?;
580            let res = match t {
581                0 => {
582                    // SetPixelFormat
583                    let mut padding = [0u8; 3];
584                    stream.read_exact(&mut padding).await?;
585                    let pixel_format = PixelFormat::read_from(stream).await?;
586                    Ok(ClientMessage::SetPixelFormat(pixel_format))
587                }
588
589                2 => {
590                    // SetEncodings
591                    stream.read_u8().await?; // 1 byte of padding
592                    let num_encodings = stream.read_u16().await?;
593
594                    // TODO: what to do if num_encodings is 0
595
596                    let mut encodings = Vec::new();
597                    for _ in 0..num_encodings {
598                        let e: EncodingType = stream.read_i32().await?.into();
599                        encodings.push(e);
600                    }
601
602                    Ok(ClientMessage::SetEncodings(encodings))
603                }
604                3 => {
605                    // FramebufferUpdateRequest
606                    let incremental = match stream.read_u8().await? {
607                        0 => false,
608                        _ => true,
609                    };
610                    let position = Position::read_from(stream).await?;
611                    let resolution = Resolution::read_from(stream).await?;
612
613                    let fbu_req = FramebufferUpdateRequest {
614                        incremental,
615                        position,
616                        resolution,
617                    };
618
619                    Ok(ClientMessage::FramebufferUpdateRequest(fbu_req))
620                }
621                4 => {
622                    // KeyEvent
623                    let is_pressed = match stream.read_u8().await? {
624                        0 => false,
625                        _ => true,
626                    };
627
628                    // 2 bytes of padding
629                    stream.read_u16().await?;
630
631                    let keysym_raw = stream.read_u32().await?;
632                    let keysym = KeySym::try_from(keysym_raw)?;
633
634                    let key_event = KeyEvent {
635                        is_pressed,
636                        keysym,
637                        keysym_raw,
638                    };
639
640                    Ok(ClientMessage::KeyEvent(key_event))
641                }
642                5 => {
643                    // PointerEvent
644                    let pointer_event = PointerEvent::read_from(stream).await?;
645                    Ok(ClientMessage::PointerEvent(pointer_event))
646                }
647                6 => {
648                    // ClientCutText
649
650                    // 3 bytes of padding
651                    let mut padding = [0u8; 3];
652                    stream.read_exact(&mut padding).await?;
653
654                    let len = stream.read_u32().await?;
655                    let mut buf: Vec<u8> = Vec::with_capacity(len as usize);
656                    stream.read_exact(&mut buf).await?;
657
658                    // TODO: The encoding RFB uses is ISO 8859-1 (Latin-1), which is a subset of
659                    // utf-8. Determine if this is the right approach.
660                    let text =
661                        String::from_utf8(buf).map_err(|_| ProtocolError::InvalidTextEncoding)?;
662
663                    Ok(ClientMessage::ClientCutText(text))
664                }
665                unknown => Err(ProtocolError::UnknownClientMessageType(unknown)),
666            };
667
668            res
669        }
670        .boxed()
671    }
672}
673
674#[derive(Debug)]
675#[allow(dead_code)]
676pub struct FramebufferUpdateRequest {
677    incremental: bool,
678    position: Position,
679    resolution: Resolution,
680}
681
682#[derive(Debug, Copy, Clone)]
683pub struct KeyEvent {
684    is_pressed: bool,
685    keysym: KeySym,
686    keysym_raw: u32,
687}
688
689impl KeyEvent {
690    pub fn keysym_raw(&self) -> u32 {
691        self.keysym_raw
692    }
693
694    pub fn keysym(&self) -> KeySym {
695        self.keysym
696    }
697
698    pub fn is_pressed(&self) -> bool {
699        self.is_pressed
700    }
701}
702
703bitflags! {
704    #[derive(Debug)]
705    struct MouseButtons: u8 {
706        const LEFT = 1 << 0;
707        const MIDDLE = 1 << 1;
708        const RIGHT = 1 << 2;
709        const SCROLL_A = 1 << 3;
710        const SCROLL_B = 1 << 4;
711        const SCROLL_C = 1 << 5;
712        const SCROLL_D = 1 << 6;
713    }
714}
715
716#[derive(Debug)]
717#[allow(dead_code)]
718pub struct PointerEvent {
719    position: Position,
720    pressed: MouseButtons,
721}
722
723impl ReadMessage for PointerEvent {
724    fn read_from<'a>(stream: &'a mut (impl AsyncRead + AsyncWrite + Unpin + Send + Sync)) -> BoxFuture<'a, Result<Self, ProtocolError>> {
725        async {
726            let button_mask = stream.read_u8().await?;
727            let pressed = MouseButtons::from_bits_truncate(button_mask);
728            let position = Position::read_from(stream).await?;
729
730            Ok(PointerEvent { position, pressed })
731        }
732        .boxed()
733    }
734}