Refactor ends, remove obsolete files

This commit is contained in:
Jovi Hsu 2022-10-31 06:02:23 +00:00
parent 5032a3c86a
commit 49ca82b0b6
11 changed files with 23 additions and 2398 deletions

View File

@ -1,6 +1,6 @@
[package]
name = "webvnc"
version = "0.1.0"
version = "0.2.0"
authors = ["Jovi Hsu <jv.hsu@outlook.com>"]
edition = "2021"

View File

@ -4,11 +4,8 @@ use crate::{
x11cursor::MouseUtils,
x11keyboard::{self, KeyboardUtils},
};
use fluvio_wasm_timer::Instant;
use std::{
cell::{Cell, RefCell},
rc::Rc,
};
use std::rc::Rc;
use tokio::sync::mpsc;
use vnc::{Rect, X11Event};
use wasm_bindgen::prelude::*;
@ -18,20 +15,14 @@ use web_sys::{
KeyboardEvent, MouseEvent,
};
const MILLIS_IN_SEC: u32 = 1000;
struct Canvas {
canvas: HtmlCanvasElement,
ctx: CanvasRenderingContext2d,
output: mpsc::Sender<X11Event>,
refresh_interval: u32,
video_mem: RefCell<Vec<u8>>,
timer: Cell<Instant>,
resolution: Cell<(u32, u32)>,
}
impl Canvas {
fn new(sender: mpsc::Sender<X11Event>, refresh_rate: u16) -> Self {
fn new(sender: mpsc::Sender<X11Event>) -> Self {
let document = web_sys::window().unwrap().document().unwrap();
let canvas = document.get_element_by_id("vnc-canvas").unwrap();
let canvas: HtmlCanvasElement = canvas
@ -48,10 +39,6 @@ impl Canvas {
canvas,
ctx,
output: sender,
refresh_interval: MILLIS_IN_SEC / refresh_rate as u32,
video_mem: RefCell::new(Vec::new()),
timer: Cell::new(Instant::now()),
resolution: Cell::new((0, 0)),
}
}
@ -59,11 +46,7 @@ impl Canvas {
// set hight & width
self.canvas.set_height(height);
self.canvas.set_width(width);
self.video_mem
.borrow_mut()
.resize(height as usize * width as usize * 4, 0xff);
self.ctx.rect(0_f64, 0_f64, width as f64, height as f64);
self.resolution.set((width, height));
self.ctx.fill();
}
@ -243,56 +226,17 @@ impl Canvas {
.add_event_listener_with_callback("contextmenu", cb.as_ref().unchecked_ref())
.unwrap();
cb.forget();
// initilize the timer
self.timer.set(Instant::now());
}
fn draw(&self, rect: Rect, data: Vec<u8>) {
let mut y = 0;
let mut x;
// only update the vedio buffer
let mut video = self.video_mem.borrow_mut();
while y < rect.height {
x = 0;
let mut idx = (y as usize * rect.width as usize) * 4;
let mut d_idx =
((y + rect.y) as usize * self.resolution.get().0 as usize + rect.x as usize) * 4;
while x < rect.width {
video[d_idx] = data[idx];
video[d_idx + 1] = data[idx + 1];
video[d_idx + 2] = data[idx + 2];
idx += 4;
d_idx += 4;
x += 1;
}
y += 1;
}
if self.timer.get().elapsed().as_millis() < self.refresh_interval as u128 {
// if the time elapsed has not exceeded the refresh_interval
// return to decrease the calling of render
return;
} else {
self.timer.set(Instant::now());
}
// let data = web_sys::ImageData::new_with_u8_clamped_array_and_sh(
// Clamped(&data),
// rect.width as u32,
// rect.height as u32,
// );
// let data = data.unwrap();
// let _ = self.ctx.put_image_data(&data, rect.x as f64, rect.y as f64);
let data = web_sys::ImageData::new_with_u8_clamped_array_and_sh(
Clamped(&video),
self.resolution.get().0,
self.resolution.get().1,
Clamped(&data),
rect.width as u32,
rect.height as u32,
);
let data = data.unwrap();
let _ = self.ctx.put_image_data(&data, 0_f64, 0_f64);
let _ = self.ctx.put_image_data(&data, rect.x as f64, rect.y as f64);
}
fn copy(&self, dst: Rect, src: Rect) {
@ -335,26 +279,32 @@ impl Canvas {
pub struct CanvasUtils {
inner: Rc<Canvas>,
bind: bool,
}
impl Clone for CanvasUtils {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
bind: self.bind,
}
}
}
impl CanvasUtils {
pub fn new(sender: mpsc::Sender<X11Event>, refresh_rate: u16) -> Self {
pub fn new(sender: mpsc::Sender<X11Event>) -> Self {
Self {
inner: Rc::new(Canvas::new(sender, refresh_rate)),
inner: Rc::new(Canvas::new(sender)),
bind: false,
}
}
pub fn init(&self, width: u32, height: u32) {
pub fn init(&mut self, width: u32, height: u32) {
self.inner.as_ref().set_resolution(width, height);
self.inner.as_ref().bind();
if !self.bind {
self.inner.as_ref().bind();
self.bind = true;
}
}
pub fn draw(&self, rect: Rect, data: Vec<u8>) {

View File

@ -47,9 +47,8 @@ fn run() -> Result<(), JsValue> {
.add_encoding(VncEncoding::Zrle)
.add_encoding(VncEncoding::CopyRect)
.add_encoding(VncEncoding::Raw)
// does not need
// .add_encoding(VncEncoding::CursorPseudo)
// .add_encoding(VncEncoding::DesktopSizePseudo)
.add_encoding(VncEncoding::DesktopSizePseudo)
.allow_shared(true)
.set_pixel_format(PixelFormat::rgba())
.set_version(vnc::VncVersion::RFB33)
@ -76,9 +75,9 @@ fn run() -> Result<(), JsValue> {
.await
.unwrap()
});
let canvas = CanvasUtils::new(x11_events_sender.clone(), 60);
let mut canvas = CanvasUtils::new(x11_events_sender.clone());
fn hande_vnc_event(event: VncEvent, canvas: &CanvasUtils) {
fn hande_vnc_event(event: VncEvent, canvas: &mut CanvasUtils) {
match event {
VncEvent::SetResolution(screen) => {
info!("Resize {:?}", screen);
@ -110,9 +109,9 @@ fn run() -> Result<(), JsValue> {
}
while let Some(event) = vnc_events_receiver.recv().await {
hande_vnc_event(event, &canvas);
hande_vnc_event(event, &mut canvas);
while let Ok(e) = vnc_events_receiver.try_recv() {
hande_vnc_event(e, &canvas);
hande_vnc_event(e, &mut canvas);
}
let _ = x11_events_sender.send(X11Event::Refresh).await;
}

View File

@ -1,7 +0,0 @@
mod raw;
mod tight;
mod zlib;
mod zrle;
pub use raw::Decoder as RawDecoder;
pub use tight::Decoder as TightDecoder;
pub use zrle::Decoder as ZrleDecoder;

View File

@ -1,51 +0,0 @@
use super::super::vnc_impl::{PixelFormat, VncRect};
use super::super::{ImageData, ImageType, StreamReader};
use std::io::Result;
#[derive(Default)]
pub struct Decoder {}
impl Decoder {
pub fn new() -> Self {
Self {}
}
pub fn decode(
&mut self,
format: &PixelFormat,
rect: &VncRect,
input: &mut StreamReader,
out_wait: &mut usize,
) -> Result<Option<Vec<ImageData>>> {
let len = rect.width as usize * rect.height as usize * format.bits_per_pixel as usize / 8;
if len > input.remain {
*out_wait = len;
return Ok(None);
}
let mut image_data = Vec::with_capacity(len);
input.read_exact_vec(&mut image_data, len);
let mut y = 0;
let mut x = 0;
while y < rect.height {
while x < rect.width {
let idx = (y as usize * rect.width as usize + x as usize) * 4;
image_data.swap(idx, idx + 2);
x += 1;
}
x = 0;
y += 1;
}
Ok(Some(vec![
(ImageData {
type_: ImageType::Raw,
x: rect.x,
y: rect.y,
width: rect.width,
height: rect.height,
data: image_data,
}),
]))
}
}

View File

@ -1,416 +0,0 @@
use super::super::vnc_impl::{PixelFormat, VncRect};
use super::super::{ImageData, ImageType, StreamReader};
use super::zlib::ZlibReader;
use std::io::{Error, ErrorKind, Read, Result};
const MAX_PALETTE: usize = 256;
#[derive(Default)]
pub struct Decoder {
zlibs: [Option<flate2::Decompress>; 4],
ctrl: Option<u8>,
filter: Option<u8>,
len: usize,
num_colors: usize,
palette: Vec<u8>,
}
impl Decoder {
pub fn new() -> Self {
let mut new = Self {
palette: Vec::with_capacity(MAX_PALETTE * 4),
..Default::default()
};
for i in 0..4 {
let decompressor = flate2::Decompress::new(true);
new.zlibs[i] = Some(decompressor);
}
new
}
pub fn decode(
&mut self,
format: &PixelFormat,
rect: &VncRect,
input: &mut StreamReader,
out_wait: &mut usize,
) -> Result<Option<Vec<ImageData>>> {
if self.ctrl.is_none() {
if input.remain < 1 {
*out_wait = 1;
return Ok(None);
}
let ctrl = input.read_u8();
for i in 0..4 {
if (ctrl >> i) & 1 == 1 {
self.zlibs[i].as_mut().unwrap().reset(true);
}
}
// Figure out filter
self.ctrl = Some(ctrl >> 4);
}
let mut ret = Vec::new();
match self.ctrl.as_ref().unwrap() {
8 => {
// fill Rect
self.fill_rect(format, rect, input, out_wait, &mut ret)?
}
9 => {
// jpeg Rect
self.jpeg_rect(format, rect, input, out_wait, &mut ret)?
}
10 => {
// png Rect
return Err(Error::new(
ErrorKind::InvalidData,
"PNG received in standard Tight rect",
));
}
x if x & 0x8 == 0 => {
// basic Rect
self.basic_rect(format, rect, input, out_wait, &mut ret)?
}
_ => {
let err_msg = format!(
"Illegal tight compression received ({})",
self.ctrl.as_ref().unwrap()
);
return Err(Error::new(ErrorKind::InvalidData, err_msg));
}
}
if !ret.is_empty() {
self.ctrl = None;
Ok(Some(ret))
} else {
Ok(None)
}
}
fn read_data(&mut self, input: &mut StreamReader, wait: &mut usize) -> Option<Vec<u8>> {
if self.len == 0 {
if input.remain < 3 {
*wait = 3;
return None;
}
let mut byte = input.read_u8() as usize;
self.len = byte & 0x7f;
if byte & 0x80 == 0x80 {
byte = input.read_u8() as usize;
self.len |= (byte & 0x7f) << 7;
if byte & 0x80 == 0x80 {
byte = input.read_u8() as usize;
self.len |= (byte as usize) << 14;
}
}
}
if input.remain < self.len {
*wait = self.len;
None
} else {
let mut data = Vec::with_capacity(self.len);
input.read_exact_vec(&mut data, self.len);
self.len = 0;
Some(data)
}
}
fn fill_rect(
&mut self,
_format: &PixelFormat,
rect: &VncRect,
input: &mut StreamReader,
wait: &mut usize,
out: &mut Vec<ImageData>,
) -> Result<()> {
if input.remain < 3 {
*wait = 3;
} else {
let mut rgb = [0; 3];
input.read_exact(&mut rgb, 3);
rgb.swap(0, 2);
out.push(ImageData {
type_: ImageType::Fill,
x: rect.x,
y: rect.y,
width: rect.width,
height: rect.height,
data: rgb.to_vec(),
})
}
Ok(())
}
fn jpeg_rect(
&mut self,
_format: &PixelFormat,
rect: &VncRect,
input: &mut StreamReader,
wait: &mut usize,
out: &mut Vec<ImageData>,
) -> Result<()> {
if let Some(d) = self.read_data(input, wait) {
out.push(ImageData {
type_: ImageType::Jpeg,
x: rect.x,
y: rect.y,
width: rect.width,
height: rect.height,
data: d,
});
}
Ok(())
}
fn basic_rect(
&mut self,
format: &PixelFormat,
rect: &VncRect,
input: &mut StreamReader,
wait: &mut usize,
out: &mut Vec<ImageData>,
) -> Result<()> {
if self.filter.is_none() {
let filter;
if self.ctrl.as_ref().unwrap() & 0x4 == 4 {
if input.remain < 1 {
*wait = 1;
return Ok(());
}
filter = input.read_u8();
} else {
// Implicit CopyFilter
filter = 0;
}
self.filter = Some(filter);
}
let stream_id = self.ctrl.as_ref().unwrap() & 0x3;
match self.filter.as_ref().unwrap() {
0 => {
// copy filter
self.copy_filter(stream_id, format, rect, input, wait, out)?;
}
1 => {
// palette
self.palette_filter(stream_id, format, rect, input, wait, out)?
}
2 => {
// gradient
return Err(Error::new(
ErrorKind::InvalidData,
"Gradient filter not implemented",
));
}
_ => {
let err_msg = format!(
"Illegal tight filter received (filter: {})",
self.filter.as_ref().unwrap()
);
return Err(Error::new(ErrorKind::InvalidData, err_msg));
}
}
if !out.is_empty() {
self.filter = None;
}
Ok(())
}
fn copy_filter(
&mut self,
stream: u8,
_format: &PixelFormat,
rect: &VncRect,
input: &mut StreamReader,
wait: &mut usize,
out: &mut Vec<ImageData>,
) -> Result<()> {
let uncompressed_size = rect.width as usize * rect.height as usize * 3;
if uncompressed_size == 0 {
return Ok(());
};
let mut data;
if uncompressed_size < 12 {
if input.remain < uncompressed_size {
*wait = uncompressed_size;
return Ok(());
}
data = Vec::with_capacity(uncompressed_size);
input.read_exact_vec(&mut data, uncompressed_size);
} else if let Some(d) = self.read_data(input, wait) {
let mut reader = ZlibReader::new(self.zlibs[stream as usize].take().unwrap(), &d);
data = Vec::with_capacity(uncompressed_size);
unsafe { data.set_len(uncompressed_size) }
reader.read_exact(&mut data)?;
self.zlibs[stream as usize] = Some(reader.into_inner()?);
} else {
return Ok(());
}
let mut image = Vec::with_capacity(uncompressed_size / 3 * 4);
let mut j = 0;
while j < uncompressed_size {
image.extend_from_slice(&data[j..j + 3]);
image.push(255);
j += 3;
}
out.push(ImageData {
type_: ImageType::Raw,
x: rect.x,
y: rect.y,
width: rect.width,
height: rect.height,
data: image,
});
Ok(())
}
fn palette_filter(
&mut self,
stream: u8,
_format: &PixelFormat,
rect: &VncRect,
input: &mut StreamReader,
wait: &mut usize,
out: &mut Vec<ImageData>,
) -> Result<()> {
if self.num_colors == 0 {
if input.remain < 1 {
*wait = 1;
return Ok(());
}
self.num_colors = input.read_u8() as usize + 1;
}
let palette_size = self.num_colors * 3;
if self.palette.is_empty() {
if input.remain < palette_size {
*wait = palette_size;
return Ok(());
}
input.read_exact_vec(&mut self.palette, palette_size);
}
let bpp = if self.num_colors <= 2 { 1 } else { 8 };
let row_size = (rect.width as usize * bpp + 7) / 8;
let uncompressed_size = rect.height as usize * row_size;
if uncompressed_size == 0 {
return Ok(());
}
let mut data;
if uncompressed_size < 12 {
if input.remain < uncompressed_size {
*wait = uncompressed_size;
return Ok(());
}
data = Vec::with_capacity(uncompressed_size);
input.read_exact_vec(&mut data, uncompressed_size);
} else if let Some(d) = self.read_data(input, wait) {
let mut reader = ZlibReader::new(self.zlibs[stream as usize].take().unwrap(), &d);
data = Vec::with_capacity(uncompressed_size);
unsafe { data.set_len(uncompressed_size) }
reader.read_exact(&mut data)?;
self.zlibs[stream as usize] = Some(reader.into_inner()?);
} else {
return Ok(());
}
if self.num_colors == 2 {
self.mono_rect(data, rect, out)?
} else {
self.palette_rect(data, rect, out)?
}
self.num_colors = 0;
self.palette.clear();
Ok(())
}
fn mono_rect(&mut self, data: Vec<u8>, rect: &VncRect, out: &mut Vec<ImageData>) -> Result<()> {
// Convert indexed (palette based) image data to RGB
// TODO: reduce number of calculations inside loop
let total = rect.width as usize * rect.height as usize * 4;
let mut image = Vec::with_capacity(total);
unsafe { image.set_len(total) }
let w = (rect.width as usize + 7) / 8;
let w1 = rect.width as usize / 8;
for y in 0..rect.height as usize {
let mut dp;
let mut sp;
for x in 0..w1 {
for b in (0..=7).rev() {
dp = (y * rect.width as usize + x * 8 + 7 - b) * 4;
sp = (data[y * w + x] as usize >> b & 1) * 3;
image[dp] = self.palette[sp];
image[dp + 1] = self.palette[sp + 1];
image[dp + 2] = self.palette[sp + 2];
image[dp + 3] = 255;
}
}
let x = w1;
let mut b = 7;
while b >= 8 - rect.width as usize % 8 {
dp = (y * rect.width as usize + x * 8 + 7 - b) * 4;
sp = (data[y * w + x] as usize >> b & 1) * 3;
image[dp] = self.palette[sp];
image[dp + 1] = self.palette[sp + 1];
image[dp + 2] = self.palette[sp + 2];
image[dp + 3] = 255;
b -= 1;
}
}
out.push(ImageData {
type_: ImageType::Raw,
x: rect.x,
y: rect.y,
width: rect.width,
height: rect.height,
data: image,
});
Ok(())
}
fn palette_rect(
&mut self,
data: Vec<u8>,
rect: &VncRect,
out: &mut Vec<ImageData>,
) -> Result<()> {
// Convert indexed (palette based) image data to RGB
let total = rect.width as usize * rect.height as usize * 4;
let mut image = Vec::with_capacity(total);
let mut i = 0;
let mut j = 0;
while i < total {
let sp = data[j] as usize * 3;
image.extend_from_slice(&self.palette[sp..sp + 3]);
image.push(255);
i += 4;
j += 1;
}
out.push(ImageData {
type_: ImageType::Raw,
x: rect.x,
y: rect.y,
width: rect.width,
height: rect.height,
data: image,
});
Ok(())
}
}

View File

@ -1,77 +0,0 @@
/*
Copyright (c) 2016 whitequark <whitequark@whitequark.org>
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
use std::io::{Read, Result};
pub struct ZlibReader<'a> {
decompressor: flate2::Decompress,
input: &'a [u8],
}
impl<'a> ZlibReader<'a> {
pub fn new(decompressor: flate2::Decompress, input: &'a [u8]) -> ZlibReader<'a> {
ZlibReader {
decompressor,
input,
}
}
pub fn into_inner(self) -> Result<flate2::Decompress> {
if self.input.is_empty() {
Ok(self.decompressor)
} else {
Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"leftover zlib byte data",
))
}
// Ok(self.decompressor)
}
}
impl<'a> Read for ZlibReader<'a> {
fn read(&mut self, output: &mut [u8]) -> std::io::Result<usize> {
let in_before = self.decompressor.total_in();
let out_before = self.decompressor.total_out();
let result =
self.decompressor
.decompress(self.input, output, flate2::FlushDecompress::None);
let consumed = (self.decompressor.total_in() - in_before) as usize;
let produced = (self.decompressor.total_out() - out_before) as usize;
self.input = &self.input[consumed..];
match result {
Ok(flate2::Status::Ok) => Ok(produced),
Ok(flate2::Status::BufError) => Ok(0),
Err(error) => Err(std::io::Error::new(std::io::ErrorKind::InvalidData, error)),
Ok(flate2::Status::StreamEnd) => Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"zlib stream end",
)),
}
}
}

View File

@ -1,319 +0,0 @@
/*
Copyright (c) 2016 whitequark <whitequark@whitequark.org>
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
use super::super::vnc_impl::*;
use super::super::{ImageData, ImageType, StreamReader};
use super::zlib::ZlibReader;
use byteorder::ReadBytesExt;
use std::io::{Read, Result};
struct BitReader<T: Read> {
reader: T,
buffer: u8,
position: usize,
}
impl<T: Read> BitReader<T> {
fn new(reader: T) -> BitReader<T> {
BitReader {
reader,
buffer: 0,
position: 8,
}
}
fn into_inner(self) -> Result<T> {
if self.position == 8 {
Ok(self.reader)
} else {
Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"leftover ZRLE bit data",
))
}
}
fn read_bits(&mut self, count: usize) -> std::io::Result<u8> {
assert!(count > 0 && count <= 8);
if self.position == 8 {
self.buffer = self.reader.read_u8()?;
self.position = 0;
}
if self.position + count <= 8 {
let shift = 8 - (count + self.position);
let mask = (1 << count) - 1;
let result = (self.buffer >> shift) & mask;
self.position += count;
Ok(result)
} else {
Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"unaligned ZRLE bit read",
))
}
}
fn read_bit(&mut self) -> std::io::Result<bool> {
Ok(self.read_bits(1)? != 0)
}
fn align(&mut self) {
self.position = 8;
}
}
impl<T: Read> Read for BitReader<T> {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
if self.position == 8 {
self.reader.read(buf)
} else {
Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"unaligned ZRLE byte read",
))
}
}
}
pub struct Decoder {
padding_len: u32,
decompressor: Option<flate2::Decompress>,
}
impl Decoder {
pub fn new() -> Decoder {
Decoder {
decompressor: Some(flate2::Decompress::new(/*zlib_header*/ true)),
padding_len: 0,
}
}
pub fn decode(
&mut self,
format: &PixelFormat,
rect: &VncRect,
input: &mut StreamReader,
out_wait: &mut usize,
) -> Result<Option<Vec<ImageData>>> {
fn read_run_length(reader: &mut dyn Read) -> Result<usize> {
let mut run_length_part;
let mut run_length = 1;
loop {
run_length_part = reader.read_u8()?;
run_length += run_length_part as usize;
if 255 != run_length_part {
break;
}
}
Ok(run_length)
}
fn copy_true_color(
reader: &mut dyn Read,
pixels: &mut Vec<u8>,
pad: bool,
compressed_bpp: usize,
bpp: usize,
) -> Result<()> {
let mut buf = [255; 4];
reader.read_exact(&mut buf[pad as usize..pad as usize + compressed_bpp])?;
buf.swap(0, 2);
pixels.extend_from_slice(&buf[..bpp]);
Ok(())
}
fn copy_indexed(palette: &[u8], pixels: &mut Vec<u8>, bpp: usize, index: u8) {
let start = index as usize * bpp;
pixels.extend_from_slice(&palette[start..start + bpp])
}
if self.padding_len == 0 {
if input.remain < 4 {
*out_wait = 4;
return Ok(None);
} else {
self.padding_len = input.read_u32();
}
}
if input.remain < self.padding_len as usize {
*out_wait = self.padding_len as usize;
return Ok(None);
}
let mut ret = Vec::new();
let mut image_data = Vec::with_capacity(self.padding_len as usize);
input.read_exact_vec(&mut image_data, self.padding_len as usize);
let bpp = format.bits_per_pixel as usize / 8;
let pixel_mask = (format.red_max as u32) << format.red_shift
| (format.green_max as u32) << format.green_shift
| (format.blue_max as u32) << format.blue_shift;
let (compressed_bpp, pad_pixel) =
if format.bits_per_pixel == 32 && format.true_color_flag > 0 && format.depth <= 24 {
if pixel_mask & 0x000000ff == 0 {
(3, format.big_endian_flag > 0)
} else if pixel_mask & 0xff000000 == 0 {
(3, format.big_endian_flag == 0)
} else {
(4, false)
}
} else {
(bpp, false)
};
let mut palette = Vec::with_capacity(128 * bpp);
let mut reader = BitReader::new(ZlibReader::new(
self.decompressor.take().unwrap(),
&image_data,
));
let mut y = 0;
while y < rect.height {
let height = if y + 64 > rect.height {
rect.height - y
} else {
64
};
let mut x = 0;
while x < rect.width {
let width = if x + 64 > rect.width {
rect.width - x
} else {
64
};
let pixel_count = height as usize * width as usize;
let is_rle = reader.read_bit()?;
let palette_size = reader.read_bits(7)?;
palette.truncate(0);
for _ in 0..palette_size {
copy_true_color(&mut reader, &mut palette, pad_pixel, compressed_bpp, bpp)?
}
let mut pixels = Vec::with_capacity(pixel_count * bpp);
match (is_rle, palette_size) {
(false, 0) => {
// True Color pixels
for _ in 0..pixel_count {
copy_true_color(
&mut reader,
&mut pixels,
pad_pixel,
compressed_bpp,
bpp,
)?
}
}
(false, 1) => {
// Color fill
for _ in 0..pixel_count {
copy_indexed(&palette, &mut pixels, bpp, 0)
}
}
(false, 2) | (false, 3..=4) | (false, 5..=16) => {
// Indexed pixels
let bits_per_index = match palette_size {
2 => 1,
3..=4 => 2,
5..=16 => 4,
_ => unreachable!(),
};
for _ in 0..height {
for _ in 0..width {
let index = reader.read_bits(bits_per_index)?;
copy_indexed(&palette, &mut pixels, bpp, index)
}
reader.align();
}
}
(true, 0) => {
// True Color RLE
let mut count = 0;
let mut pixel = Vec::new();
while count < pixel_count {
pixel.truncate(0);
copy_true_color(
&mut reader,
&mut pixel,
pad_pixel,
compressed_bpp,
bpp,
)?;
let run_length = read_run_length(&mut reader)?;
for _ in 0..run_length {
pixels.extend(&pixel)
}
count += run_length;
}
}
(true, 2..=127) => {
// Indexed RLE
let mut count = 0;
while count < pixel_count {
let longer_than_one = reader.read_bit()?;
let index = reader.read_bits(7)?;
let run_length = if longer_than_one {
read_run_length(&mut reader)?
} else {
1
};
for _ in 0..run_length {
copy_indexed(&palette, &mut pixels, bpp, index);
}
count += run_length;
}
}
_ => {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"ZRLE subencoding",
))
}
}
ret.push(ImageData {
data: pixels,
height,
width,
x: rect.x + x,
y: rect.y + y,
type_: ImageType::Raw,
});
x += width;
}
y += height;
}
self.decompressor = Some(reader.into_inner()?.into_inner()?);
self.padding_len = 0;
Ok(Some(ret))
}
}

View File

@ -1,323 +0,0 @@
/*
* Copyright (c) 2016 Boucher, Antoni <bouanto@zoho.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#![allow(dead_code)]
pub type Key = [u8; 8];
const FIRST_BIT: u64 = 1 << 63;
const HALF_KEY_SIZE: i64 = KEY_SIZE / 2;
const KEY_SIZE: i64 = 56;
/// Do a circular left shift on a width of HALF_KEY_SIZE.
fn circular_left_shift(n1: u64, n2: u64, shift_count: i64) -> (u64, u64) {
let mut new_value1 = n1;
let mut new_value2 = n2;
for _ in 0..shift_count {
let first_bit = new_value1 & FIRST_BIT;
new_value1 = (new_value1 << 1) | (first_bit >> (HALF_KEY_SIZE - 1));
let first_bit = new_value2 & FIRST_BIT;
new_value2 = (new_value2 << 1) | (first_bit >> (HALF_KEY_SIZE - 1));
}
(new_value1, new_value2)
}
/// Create the 16 subkeys.
fn compute_subkeys(key: u64) -> Vec<u64> {
let table = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1];
let k0 = pc1(key);
let mut subkeys = vec![k0];
for shift_count in &table {
let last_key = subkeys.last().unwrap();
let last_ci = last_key & 0xFFFFFFF000000000;
let last_di = last_key << HALF_KEY_SIZE;
let (ci, di) = circular_left_shift(last_ci, last_di, *shift_count);
let current_key = ci | (di >> HALF_KEY_SIZE);
subkeys.push(current_key);
}
subkeys.remove(0);
subkeys.iter().map(|&n| pc2(n)).collect()
}
/// Swap bits using the E table.
fn e(block: u64) -> u64 {
let table = [
32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, 8, 9, 10, 11, 12, 13, 12, 13, 14, 15, 16, 17, 16, 17,
18, 19, 20, 21, 20, 21, 22, 23, 24, 25, 24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32, 1,
];
swap_bits(block, &table)
}
/// Decrypt `message` using the `key`.
pub fn decrypt(cipher: &[u8], key: &Key) -> Vec<u8> {
let key = key_to_u64(key);
let mut subkeys = compute_subkeys(key);
subkeys.reverse();
des(cipher, subkeys)
}
/// Encrypt `message` using `subkeys`.
fn des(message: &[u8], subkeys: Vec<u64>) -> Vec<u8> {
let blocks = message_to_u64s(message);
let mut cipher = vec![];
for block in blocks {
let permuted = ip(block);
let mut li = permuted & 0xFFFFFFFF00000000;
let mut ri = permuted << 32;
for subkey in &subkeys {
let last_li = li;
li = ri;
ri = last_li ^ feistel(ri, *subkey);
}
let r16l16 = ri | (li >> 32);
cipher.append(&mut to_u8_vec(fp(r16l16)));
}
cipher
}
/// Encrypt `message` using the `key`.
pub fn encrypt(message: &[u8], key: &Key) -> Vec<u8> {
let key = key_to_u64(key);
let subkeys = compute_subkeys(key);
des(message, subkeys)
}
/// Feistel function.
fn feistel(half_block: u64, subkey: u64) -> u64 {
let expanded = e(half_block);
let mut intermediate = expanded ^ subkey;
let mut result = 0;
for i in 0..8 {
let block = (intermediate & 0xFC00000000000000) >> 58;
intermediate <<= 6;
result <<= 4;
result |= s(i, block);
}
p(result << 32)
}
/// Swap bits using the IP table.
fn ip(message: u64) -> u64 {
let table = [
58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, 62, 54, 46, 38, 30, 22, 14,
6, 64, 56, 48, 40, 32, 24, 16, 8, 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11,
3, 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7,
];
swap_bits(message, &table)
}
/// Convert a `Key` to a 64-bits integer.
fn key_to_u64(key: &Key) -> u64 {
let mut result = 0;
for &part in key {
result <<= 8;
result += part as u64;
}
result
}
/// Convert a message to a vector of 64-bits integer.
fn message_to_u64s(message: &[u8]) -> Vec<u64> {
message.chunks(8).map(|m| key_to_u64(&to_key(m))).collect()
}
/// Swap bits using the P table.
fn p(block: u64) -> u64 {
let table = [
16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, 2, 8, 24, 14, 32, 27, 3, 9,
19, 13, 30, 6, 22, 11, 4, 25,
];
swap_bits(block, &table)
}
/// Swap bits using the PC-1 table.
fn pc1(key: u64) -> u64 {
let table = [
57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, 27, 19, 11, 3,
60, 52, 44, 36, 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45,
37, 29, 21, 13, 5, 28, 20, 12, 4,
];
swap_bits(key, &table)
}
/// Swap bits using the PC-2 table.
fn pc2(key: u64) -> u64 {
let table = [
14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, 41,
52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48, 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32,
];
swap_bits(key, &table)
}
/// Swap bits using the reverse FP table.
fn fp(message: u64) -> u64 {
let table = [
40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31, 38, 6, 46, 14, 54, 22, 62,
30, 37, 5, 45, 13, 53, 21, 61, 29, 36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19,
59, 27, 34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41, 9, 49, 17, 57, 25,
];
swap_bits(message, &table)
}
/// Produce 4-bits using an S box.
fn s(box_id: usize, block: u64) -> u64 {
let tables = [
[
[14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7],
[0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8],
[4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0],
[15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13],
],
[
[15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10],
[3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5],
[0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15],
[13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9],
],
[
[10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8],
[13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1],
[13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7],
[1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12],
],
[
[7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15],
[13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9],
[10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4],
[3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14],
],
[
[2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9],
[14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6],
[4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14],
[11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3],
],
[
[12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11],
[10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8],
[9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6],
[4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13],
],
[
[4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1],
[13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6],
[1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2],
[6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12],
],
[
[13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7],
[1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2],
[7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8],
[2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11],
],
];
let i = ((block & 0x20) >> 4 | (block & 1)) as usize;
let j = ((block & 0x1E) >> 1) as usize;
tables[box_id][i][j]
}
/// Swap bits using a table.
fn swap_bits(key: u64, table: &[u64]) -> u64 {
let mut result = 0;
for (pos, index) in table.iter().enumerate() {
let bit = (key << (index - 1)) & FIRST_BIT;
result |= bit >> pos;
}
result
}
/// Convert a slice to a `Key`.
fn to_key(slice: &[u8]) -> Key {
let mut vec: Vec<u8> = slice.to_vec();
let mut key = [0; 8];
let diff = key.len() - vec.len();
if diff > 0 {
vec.append(&mut vec![0; diff]);
}
key.clone_from_slice(&vec);
key
}
/// Convert a `u64` to a `Vec<u8>`.
fn to_u8_vec(num: u64) -> Vec<u8> {
vec![
((num & 0xFF00000000000000) >> 56) as u8,
((num & 0x00FF000000000000) >> 48) as u8,
((num & 0x0000FF0000000000) >> 40) as u8,
((num & 0x000000FF00000000) >> 32) as u8,
((num & 0x00000000FF000000) >> 24) as u8,
((num & 0x0000000000FF0000) >> 16) as u8,
((num & 0x000000000000FF00) >> 8) as u8,
(num & 0x00000000000000FF) as u8,
]
}
#[cfg(test)]
mod tests {
use super::{decrypt, encrypt};
#[test]
fn test_encrypt_decrypt() {
let key = [0x13, 0x34, 0x57, 0x79, 0x9B, 0xBC, 0xDF, 0xF1];
let message = [0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF];
let expected_cipher = vec![0x85, 0xE8, 0x13, 0x54, 0x0F, 0x0A, 0xB4, 0x05];
let cipher = encrypt(&message, &key);
assert_eq!(cipher, expected_cipher);
let cipher = expected_cipher;
let expected_message = message;
let message = decrypt(&cipher, &key);
assert_eq!(message, expected_message);
let message = [
0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB,
0xCD, 0xEF,
];
let expected_cipher = vec![
0x85, 0xE8, 0x13, 0x54, 0x0F, 0x0A, 0xB4, 0x05, 0x85, 0xE8, 0x13, 0x54, 0x0F, 0x0A,
0xB4, 0x05,
];
let cipher = encrypt(&message, &key);
assert_eq!(cipher, expected_cipher);
let cipher = expected_cipher;
let expected_message = message;
let message = decrypt(&cipher, &key);
assert_eq!(message, expected_message);
}
}

View File

@ -1,241 +0,0 @@
mod decoder;
mod des;
mod vnc_impl;
mod x11cursor;
mod x11keyboard;
pub enum MouseEventType {
Down,
Up,
Move,
}
use std::{rc::Rc, sync::Mutex};
pub struct ImageData {
pub type_: ImageType,
pub x: u16,
pub y: u16,
pub width: u16,
pub height: u16,
pub data: Vec<u8>,
}
#[allow(dead_code)]
pub enum ImageType {
Raw,
Copy,
Fill,
Jpeg,
}
pub enum VncOutput {
WsBuf(Vec<u8>),
Err(String),
RequirePassword,
SetResolution(u16, u16),
RenderImage(ImageData),
SetClipboard(String),
}
pub struct Vnc {
inner: Rc<Mutex<vnc_impl::Vnc>>,
}
impl Vnc {
pub fn new() -> Self {
Self {
inner: Rc::new(Mutex::new(vnc_impl::Vnc::new())),
}
}
pub fn do_input(&self, input: Vec<u8>) {
self.inner.lock().unwrap().do_input(input);
}
pub fn get_output(&self) -> Vec<VncOutput> {
self.inner.lock().unwrap().get_output()
}
pub fn set_credential(&self, password: &str) {
self.inner.lock().unwrap().set_credential(password);
}
pub fn set_clipboard(&self, text: &str) {
self.inner.lock().unwrap().set_clipboard(text);
}
pub fn require_frame(&self, incremental: u8) {
self.inner.lock().unwrap().require_frame(incremental);
}
pub fn key_press(&self, key: web_sys::KeyboardEvent, down: bool) {
self.inner.lock().unwrap().key_press(key, down);
}
pub fn mouse_event(&self, mouse: web_sys::MouseEvent, et: MouseEventType) {
self.inner.lock().unwrap().mouse_event(mouse, et);
}
pub fn ctrl_alt_del(&self) {
self.inner.lock().unwrap().ctrl_alt_del();
}
pub fn close(&self) {
self.inner.lock().unwrap().close();
}
}
impl Clone for Vnc {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
}
}
}
pub struct StreamReader {
inner: Vec<Vec<u8>>,
remain: usize,
}
#[allow(dead_code)]
impl StreamReader {
pub fn new(bufs: Vec<Vec<u8>>, len: usize) -> Self {
Self {
inner: bufs,
remain: len,
}
}
pub fn append(&mut self, buf: Vec<u8>) {
self.remain += buf.len();
self.inner.push(buf);
}
pub fn remain(&self) -> usize {
self.remain
}
pub fn read_exact_vec(&mut self, out_vec: &mut Vec<u8>, n: usize) {
let mut i = 0;
let mut left = n;
self.remain -= n;
while i < n {
if self.inner[0].len() > left {
for it in self.inner[0].drain(0..left) {
out_vec.push(it);
}
i += left;
left = 0;
} else {
out_vec.extend(&self.inner[0]);
left -= self.inner[0].len();
i += self.inner[0].len();
self.inner.remove(0);
}
}
}
pub fn read_exact(&mut self, out_buf: &mut [u8], n: usize) {
let mut i = 0;
let mut left = n;
self.remain -= n;
while i < n {
if self.inner[0].len() > left {
out_buf[i..i + left].copy_from_slice(&self.inner[0][0..left]);
self.inner[0].drain(0..left);
i += left;
left = 0;
} else {
out_buf[i..i + self.inner[0].len()].copy_from_slice(&self.inner[0]);
left -= self.inner[0].len();
i += self.inner[0].len();
self.inner.remove(0);
}
}
}
pub fn read_u8(&mut self) -> u8 {
let mut buf = [0u8; 1];
self.read_exact(&mut buf, 1);
buf[0]
}
pub fn read_u16(&mut self) -> u16 {
let mut buf = [0u8; 2];
self.read_exact(&mut buf, 2);
u16::from_be_bytes(buf)
}
pub fn read_u32(&mut self) -> u32 {
let mut buf = [0u8; 4];
self.read_exact(&mut buf, 4);
u32::from_be_bytes(buf)
}
pub fn read_u64(&mut self) -> u64 {
let mut buf = [0u8; 8];
self.read_exact(&mut buf, 8);
u64::from_be_bytes(buf)
}
pub fn read_string(&mut self, len: usize) -> String {
let mut buf = vec![0u8; len];
self.read_exact(&mut buf, len);
String::from_utf8(buf).unwrap()
}
}
pub struct StreamWriter<'a> {
inner: &'a mut Vec<u8>,
}
#[allow(dead_code)]
impl<'a> StreamWriter<'a> {
pub fn new(buf: &'a mut Vec<u8>) -> Self {
Self { inner: buf }
}
pub fn write_u8(&mut self, b: u8) {
self.inner.push(b);
}
pub fn write_u16(&mut self, b: u16) {
self.inner.extend_from_slice(&b.to_be_bytes());
}
pub fn write_u32(&mut self, b: u32) {
self.inner.extend_from_slice(&b.to_be_bytes());
}
pub fn write_s8(&mut self, b: i8) {
self.write_u8(b as u8);
}
pub fn write_s16(&mut self, b: i16) {
self.write_u16(b as u16);
}
pub fn write_s32(&mut self, b: i32) {
self.write_u32(b as u32);
}
pub fn write_string(&mut self, s: &str) {
self.inner.extend_from_slice(s.as_bytes());
}
pub fn write_string_l16(&mut self, s: &str) {
self.write_u16(s.len() as u16);
self.write_string(s);
}
pub fn write_string_l32(&mut self, s: &str) {
self.write_u32(s.len() as u32);
self.write_string(s);
}
pub fn write_slice(&mut self, s: &[u8]) {
self.inner.extend_from_slice(s);
}
}

View File

@ -1,890 +0,0 @@
use super::*;
use super::{decoder, des, x11cursor::MouseUtils, x11keyboard, MouseEventType};
use crate::{console_log, log};
const VNC_RFB33: &[u8; 12] = b"RFB 003.003\n";
// const VNC_RFB37: &[u8; 12] = b"RFB 003.007\n";
// const VNC_RFB38: &[u8; 12] = b"RFB 003.008\n";
const VNC_VER_UNSUPPORTED: &str = "unsupported version";
const VNC_FAILED: &str = "Connection failed with unknow reason";
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum SecurityType {
Invalid = 0,
None = 1,
VncAuth = 2,
// RA2 = 5,
// RA2ne = 6,
// Tight = 16,
// Ultra = 17,
// TLS = 18,
// VeNCrypt = 19,
}
#[allow(dead_code)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(i32)]
#[allow(clippy::upper_case_acronyms)]
pub enum VncEncoding {
Raw = 0,
CopyRect = 1,
RRE = 2,
Hextile = 5,
Tight = 7,
TRLE = 15,
ZRLE = 16,
CursorPseudo = -239,
DesktopSizePseudo = -223,
}
impl From<u32> for VncEncoding {
fn from(num: u32) -> Self {
unsafe { std::mem::transmute(num) }
}
}
impl From<VncEncoding> for u32 {
fn from(e: VncEncoding) -> Self {
e as u32
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum VncState {
Init,
Handshake,
Authing,
ServerInit,
Connected,
Disconnected,
}
pub enum ServerMessage {
FramebufferUpdate,
SetColourMap,
ServerCutText,
None,
}
pub struct Vnc {
state: VncState,
// supported_versions: Vec<u8>,
supported_encodings: Vec<VncEncoding>,
security_type: SecurityType,
challenge: [u8; 16],
reader: StreamReader,
mouse: MouseUtils,
require: usize,
width: u16,
height: u16,
pf: PixelFormat,
name: String,
msg_handling: ServerMessage,
num_rect_left: u16,
padding_rect: Option<VncRect>,
outbuf: Vec<u8>,
outs: Vec<VncOutput>,
raw: Option<decoder::RawDecoder>,
zrle: Option<decoder::ZrleDecoder>,
tight: Option<decoder::TightDecoder>,
}
impl Vnc {
pub fn new() -> Self {
Self {
state: VncState::Init,
supported_encodings: vec![
VncEncoding::Tight,
VncEncoding::ZRLE,
VncEncoding::Raw,
VncEncoding::CopyRect,
// VncEncoding::RRE,
// VncEncoding::Hextile,
// VncEncoding::TRLE,
// VncEncoding::CursorPseudo,
// VncEncoding::DesktopSizePseudo,
],
security_type: SecurityType::Invalid,
challenge: [0; 16],
reader: StreamReader::new(Vec::with_capacity(10), 0),
mouse: MouseUtils::new(),
require: 12, // the handleshake message length
width: 0,
height: 0,
pf: PixelFormat::default(),
name: String::new(),
msg_handling: ServerMessage::None,
num_rect_left: 0,
padding_rect: None,
outbuf: Vec::with_capacity(128),
outs: Vec::with_capacity(10),
raw: None,
zrle: None,
tight: None,
}
}
pub fn do_input(&mut self, input: Vec<u8>) {
if let VncState::Disconnected = self.state {
return;
}
// console_log!(
// "VNC input {}, left {}, require {}",
// input.len(),
// self.reader.remain(),
// self.require
// );
self.reader.append(input);
while self.reader.remain() >= self.require {
self.handle_input();
// console_log!("left {}, require {}", self.reader.remain(), self.require);
if let VncState::Disconnected = self.state {
break;
}
}
}
pub fn get_output(&mut self) -> Vec<VncOutput> {
if let ServerMessage::None = self.msg_handling {
let mut out = Vec::with_capacity(self.outs.len());
// console_log!("Get {} output", self.outs.len());
for o in self.outs.drain(..) {
out.push(o);
}
if !self.outbuf.is_empty() {
out.push(VncOutput::WsBuf(self.outbuf.clone()));
self.outbuf.clear();
}
return out;
};
Vec::new()
}
pub fn set_credential(&mut self, password: &str) {
// referring
// https://github.com/whitequark/rust-vnc/blob/0697238f2706dd34a9a95c1640e385f6d8c02961/src/client.rs
// strange behavior
let pass_len = password.len();
let mut key = [0u8; 8];
for (i, key_i) in key.iter_mut().enumerate() {
let c = if i < pass_len {
password.as_bytes()[i]
} else {
0
};
let mut cs = 0u8;
for j in 0..8 {
cs |= ((c >> j) & 1) << (7 - j)
}
*key_i = cs;
}
// console_log!("challenge {:x?}", self.challenge);
let output = des::encrypt(&self.challenge, &key);
self.outbuf.extend_from_slice(&output);
self.state = VncState::Authing;
self.require = 4; // the auth result message length
}
pub fn set_clipboard(&mut self, text: &str) {
if self.state != VncState::Connected {
return;
}
self.send_client_cut_text(text);
}
pub fn key_press(&mut self, key: web_sys::KeyboardEvent, down: bool) {
if self.state != VncState::Connected {
return;
}
let key = x11keyboard::KeyboardUtils::get_keysym(key);
self.send_key_event(key, down);
}
pub fn ctrl_alt_del(&mut self) {
self.send_key_event(x11keyboard::XK_Control_L, true);
self.send_key_event(x11keyboard::XK_Alt_L, true);
self.send_key_event(x11keyboard::XK_Delete, true);
self.send_key_event(x11keyboard::XK_Control_L, false);
self.send_key_event(x11keyboard::XK_Alt_L, false);
self.send_key_event(x11keyboard::XK_Delete, false);
}
pub fn mouse_event(&mut self, mouse: web_sys::MouseEvent, et: MouseEventType) {
if self.state != VncState::Connected {
return;
}
let (x, y, mask) = self.mouse.get_mouse_sym(mouse, et);
self.send_pointer_event(x, y, mask);
}
pub fn require_frame(&mut self, incremental: u8) {
if self.state != VncState::Connected {
return;
}
if 0 == incremental {
// first frame
// set the client encoding
self.send_client_encodings();
}
if let ServerMessage::None = self.msg_handling {
self.framebuffer_update_request(incremental)
}
}
pub fn close(&mut self) {
self.state = VncState::Disconnected;
}
}
#[allow(dead_code)]
impl Vnc {
fn read_string_l8(&mut self) -> String {
let len = self.reader.read_u8() as usize;
self.reader.read_string(len)
}
fn read_string_l16(&mut self) -> String {
let len = self.reader.read_u16() as usize;
self.reader.read_string(len)
}
fn read_string_l32(&mut self) -> String {
let len = self.reader.read_u32() as usize;
self.reader.read_string(len)
}
}
impl Vnc {
fn disconnect_with_err(&mut self, err: &str) {
console_log!("{:#?}", err);
self.state = VncState::Disconnected;
self.outs.push(VncOutput::Err(err.to_string()));
}
fn send_client_initilize(&mut self) {
self.state = VncState::ServerInit;
self.require = 25; // the minimal length of server_init message
// send client_init message
let shared_flag = 1;
self.outbuf.push(shared_flag);
}
// +--------------+--------------+---------------------+
// | No. of bytes | Type [Value] | Description |
// +--------------+--------------+---------------------+
// | 1 | U8 [2] | message-type |
// | 1 | | padding |
// | 2 | U16 | number-of-encodings |
// +--------------+--------------+---------------------+
// This is followed by number-of-encodings repetitions of the following:
// +--------------+--------------+---------------+
// | No. of bytes | Type [Value] | Description |
// +--------------+--------------+---------------+
// | 4 | S32 | encoding-type |
// +--------------+--------------+---------------+
fn send_client_encodings(&mut self) {
let mut out = Vec::with_capacity(10);
let mut sw = StreamWriter::new(&mut out);
sw.write_u8(2); // message-type
sw.write_u8(0); // padding
sw.write_u16(self.supported_encodings.len().try_into().unwrap()); // number-of-encodings
for i in &self.supported_encodings {
sw.write_u32(*i as u32);
}
self.outbuf.extend_from_slice(&out);
}
// +--------------+--------------+--------------+
// | No. of bytes | Type [Value] | Description |
// +--------------+--------------+--------------+
// | 1 | U8 [4] | message-type |
// | 1 | U8 | down-flag |
// | 2 | | padding |
// | 4 | U32 | key |
// +--------------+--------------+--------------+
fn send_key_event(&mut self, key: u32, down: bool) {
let mut out = Vec::with_capacity(10);
let mut sw = StreamWriter::new(&mut out);
sw.write_u8(4); // message-type
sw.write_u8(if down { 1 } else { 0 }); // down
sw.write_u16(0); // padding
sw.write_u32(key); // key
// console_log!("send key event {:x?} {:?}", key, down);
self.outbuf.extend_from_slice(&out);
}
// +--------------+--------------+--------------+
// | No. of bytes | Type [Value] | Description |
// +--------------+--------------+--------------+
// | 1 | U8 [5] | message-type |
// | 1 | U8 | button-mask |
// | 2 | U16 | x-position |
// | 2 | U16 | y-position |
// +--------------+--------------+--------------+
fn send_pointer_event(&mut self, x: u16, y: u16, mask: u8) {
let mut out = Vec::with_capacity(10);
let mut sw = StreamWriter::new(&mut out);
sw.write_u8(5); // message-type
sw.write_u8(mask); // mask
sw.write_u16(x); // x
sw.write_u16(y); // y
// console_log!("send mouse event {:x?} {:x?} {:#08b}", x, y, mask);
self.outbuf.extend_from_slice(&out);
}
// +--------------+--------------+--------------+
// | No. of bytes | Type [Value] | Description |
// +--------------+--------------+--------------+
// | 1 | U8 [6] | message-type |
// | 3 | | padding |
// | 4 | U32 | length |
// | length | U8 array | text |
// +--------------+--------------+--------------+
fn send_client_cut_text(&mut self, text: &str) {
let mut out = Vec::with_capacity(10);
let mut sw = StreamWriter::new(&mut out);
let len: u32 = text.len().try_into().unwrap_or(0);
sw.write_u8(6); // message-type
sw.write_u8(0); // padding
sw.write_u16(0); // padding
sw.write_u32(len); // length
sw.write_string(text); // text
// console_log!("send client cut text {:?}", len);
self.outbuf.extend_from_slice(&out);
}
// No. of bytes Type [Value] Description
// 1 CARD8 3 message-type
// 1 CARD8 incremental
// 2 CARD16 x-position
// 2 CARD16 y-position
// 2 CARD16 width
// 2 CARD16 height
fn framebuffer_update_request(&mut self, incremental: u8) {
// console_log!("VNC: framebuffer_update_request {}", incremental);
let mut out: Vec<u8> = Vec::new();
let mut sw = StreamWriter::new(&mut out);
sw.write_u8(3);
sw.write_u8(incremental);
sw.write_u16(0);
sw.write_u16(0);
sw.write_u16(self.width);
sw.write_u16(self.height);
self.outbuf.extend_from_slice(&out);
}
fn handle_input(&mut self) {
match self.state {
VncState::Init => self.do_handshake(),
VncState::Handshake => self.do_authenticate(),
VncState::Authing => self.handle_auth_result(),
VncState::ServerInit => self.handle_server_init(),
VncState::Connected => self.handle_server_message(),
VncState::Disconnected => (),
}
}
fn do_handshake(&mut self) {
let mut rfbversion: [u8; 12] = [0; 12];
self.reader.read_exact(&mut rfbversion, 12);
let support_version = match &rfbversion {
b"RFB 003.003\n" => Ok(VNC_RFB33),
b"RFB 003.007\n" => Ok(VNC_RFB33),
b"RFB 003.008\n" => Ok(VNC_RFB33),
_ => Err(VNC_VER_UNSUPPORTED),
};
match support_version {
Ok(v) => {
self.state = VncState::Handshake;
self.require = 4; // the length of the security type message
self.outbuf.extend_from_slice(v);
}
Err(e) => self.disconnect_with_err(e),
}
}
fn do_authenticate(&mut self) {
// console_log!("VNC: do_authenticate {}", self.reader.remain());
if self.security_type == SecurityType::Invalid {
let auth_type = self.reader.read_u32();
match auth_type {
1 => {
self.security_type = SecurityType::None;
self.send_client_initilize();
}
2 => {
self.security_type = SecurityType::VncAuth;
self.require = 16; // the length of server challenge
}
_ => self.disconnect_with_err(VNC_FAILED),
}
} else {
let mut challenge = [0u8; 16];
self.reader.read_exact(&mut challenge, 16);
self.challenge = challenge;
self.outs.push(VncOutput::RequirePassword);
}
}
fn handle_auth_result(&mut self) {
let response = self.reader.read_u32();
console_log!("Auth resp {}", response);
match response {
0 => self.send_client_initilize(),
1 => {
let err_msg = self.read_string_l32();
self.disconnect_with_err(&err_msg);
}
_ => self.disconnect_with_err(VNC_FAILED),
}
}
// No. of bytes Type [Value] Description
// 2 CARD16 framebuffer-width
// 2 CARD16 framebuffer-height
// 16 PIXEL_FORMAT server-pixel-format
// 4 CARD32 name-length
// name-length CARD8 array name-string
fn handle_server_init(&mut self) {
self.width = self.reader.read_u16();
self.height = self.reader.read_u16();
let mut pfb: [u8; 16] = [0u8; 16];
self.reader.read_exact(&mut pfb, 16);
// This pixel format will be used unless the client requests a different format using the SetPixelFormat message
self.pf = (&pfb).into();
console_log!(
"VNC: {}x{}\nPixel Format {:#?}",
self.width,
self.height,
self.pf
);
self.name = self.read_string_l32();
self.state = VncState::Connected;
self.require = 1; // any message from sever will be handled
self.outs
.push(VncOutput::SetResolution(self.width, self.height));
}
fn handle_server_message(&mut self) {
match self.msg_handling {
ServerMessage::SetColourMap => self.read_colour_map(),
ServerMessage::ServerCutText => self.read_cut_text(),
ServerMessage::FramebufferUpdate => self.read_rect(),
ServerMessage::None => {
let msg_type = self.reader.read_u8();
match msg_type {
0 => self.handle_framebuffer_update(),
1 => self.handle_set_colour_map(),
2 => self.handle_bell(),
3 => self.handle_server_cut_text(),
_ => self.disconnect_with_err(VNC_FAILED),
}
}
}
}
// No. of bytes Type [Value] Description
// 1 CARD8 0 message-type
// 1 padding
// 2 CARD16 number-of-rectangles
// This is followed by number-of-rectanglesrectangles of pixel data.
fn handle_framebuffer_update(&mut self) {
let _padding = self.reader.read_u8();
self.num_rect_left = self.reader.read_u16();
// console_log!("VNC: {} rects", self.num_rect_left);
self.require = 12; // the length of the first rectangle hdr
self.msg_handling = ServerMessage::FramebufferUpdate;
}
//Each rectangle consists of:
// 2 CARD16 x-position
// 2 CARD16 y-position
// 2 CARD16 width
// 2 CARD16 height
// 4 CARD32 encoding-type:
// 0 raw encoding
// 1 copy rectangle encoding
// 2 RRE encoding
// 4 CoRRE encoding
// 5 Hextile encoding
fn read_rect(&mut self) {
if self.padding_rect.is_none() {
// a brand new rectangle
let x = self.reader.read_u16();
let y = self.reader.read_u16();
let width = self.reader.read_u16();
let height = self.reader.read_u16();
let encoding_type = self.reader.read_u32().into();
match encoding_type {
VncEncoding::Raw => self.handle_raw_encoding(x, y, width, height),
VncEncoding::CopyRect => self.handle_copy_rect_encoding(x, y, width, height),
VncEncoding::RRE => self.handle_rre_encoding(x, y, width, height),
VncEncoding::Hextile => self.handle_hextile_encoding(x, y, width, height),
VncEncoding::Tight => self.handle_tight_encoding(x, y, width, height),
VncEncoding::TRLE => self.handle_trle_encoding(x, y, width, height),
VncEncoding::ZRLE => self.handle_zrle_encoding(x, y, width, height),
VncEncoding::CursorPseudo => {
self.handle_cursor_pseudo_encoding(x, y, width, height)
}
VncEncoding::DesktopSizePseudo => {
self.handle_desktop_size_pseudo_encoding(x, y, width, height)
}
}
} else {
let rect = self.padding_rect.as_ref().unwrap();
match rect.encoding_type {
VncEncoding::Raw => {
// raw
let mut decoder = if self.raw.is_none() {
decoder::RawDecoder::new()
} else {
self.raw.take().unwrap()
};
match decoder.decode(&self.pf, rect, &mut self.reader, &mut self.require) {
Ok(images) => {
if let Some(images) = images {
for i in images {
self.outs.push(VncOutput::RenderImage(i));
}
self.read_rect_end();
}
}
Err(e) => {
self.disconnect_with_err(&format!("{:?}", e));
}
}
self.raw = Some(decoder);
}
VncEncoding::CopyRect => {
// copy rectangle
let mut image_data: Vec<u8> = Vec::with_capacity(self.require);
self.reader.read_exact_vec(&mut image_data, self.require);
self.outs.push(VncOutput::RenderImage(ImageData {
type_: ImageType::Copy,
x: rect.x,
y: rect.y,
width: rect.width,
height: rect.height,
data: image_data,
}));
self.read_rect_end();
}
VncEncoding::Tight => {
// Tight
let mut decoder = if self.tight.is_none() {
decoder::TightDecoder::new()
} else {
self.tight.take().unwrap()
};
match decoder.decode(&self.pf, rect, &mut self.reader, &mut self.require) {
Ok(images) => {
if let Some(images) = images {
for i in images {
self.outs.push(VncOutput::RenderImage(i));
}
self.read_rect_end();
}
}
Err(e) => {
self.disconnect_with_err(&format!("{:?}", e));
}
}
self.tight = Some(decoder);
}
VncEncoding::ZRLE => {
// ZRLE
let mut decoder = if self.zrle.is_none() {
decoder::ZrleDecoder::new()
} else {
self.zrle.take().unwrap()
};
match decoder.decode(&self.pf, rect, &mut self.reader, &mut self.require) {
Ok(images) => {
if let Some(images) = images {
for i in images {
self.outs.push(VncOutput::RenderImage(i));
}
self.read_rect_end();
}
}
Err(e) => {
self.disconnect_with_err(&format!("{:?}", e));
}
}
self.zrle = Some(decoder);
}
_ => unimplemented!("Unknow encoding {}", rect.encoding_type as u32),
}
}
}
fn read_rect_end(&mut self) {
self.padding_rect.take();
self.num_rect_left -= 1;
if 0 == self.num_rect_left {
self.msg_handling = ServerMessage::None;
self.require = 1; // any message from sever will be handled
} else {
self.require = 12; // the length of the next rectangle hdr
}
}
// Currently there is little or no support for colour maps. Some preliminary work was done
// on this, but is incomplete. It was intended to be something like this:
// When the pixel format uses a “colour map”, this message tells the client
// that the specified pixel values should be mapped to the given RGB intensities.
// The server may only specify pixel values for which the client has
// not already set the RGB intensities using FixColourMapEntries (section
// 5.2.2).
// No. of bytes Type [Value] Description
// 1 CARD8 1 message-type
// 1 padding
// 2 CARD16 first-colour
// 2 CARD16 number-of-colours
fn handle_set_colour_map(&mut self) {
let _padding = self.reader.read_u8();
let _first_colour = self.reader.read_u16();
self.require = self.reader.read_u16() as usize * 6;
self.msg_handling = ServerMessage::SetColourMap;
}
// No. of bytes Type [Value] Description
// 2 CARD16 red
// 2 CARD16 green
// 2 CARD16 blue
fn read_colour_map(&mut self) {
// while self.num_block_left > 0 {
// let _r = self.read_u16();
// let _g = self.read_u16();
// let _b = self.read_u16();
// self.num_block_left -= 1;
// }
// just consume the data
let mut v = Vec::with_capacity(self.require);
self.reader.read_exact_vec(&mut v, self.require);
self.require = 1;
self.msg_handling = ServerMessage::None;
}
// Ring a bell on the client if it has one
fn handle_bell(&mut self) {
// just do nothing
}
// The server has new ASCII text in its cut buffer. End of lines are represented by the
// linefeed / newline character (ASCII value 10) alone. No carriage-return (ASCII value
// 13) is needed.
// No. of bytes Type [Value] Description
// 1 CARD8 3 message-type
// 3 padding
// 4 CARD32 length
// length CARD8 array text
fn handle_server_cut_text(&mut self) {
for _ in 0..3 {
self.reader.read_u8();
}
self.require = self.reader.read_u32() as usize;
self.msg_handling = ServerMessage::ServerCutText;
console_log!("VNC: ServerCutText {} bytes", self.require);
}
fn read_cut_text(&mut self) {
let text = self.reader.read_string(self.require);
self.require = 1;
self.msg_handling = ServerMessage::None;
self.outs.push(VncOutput::SetClipboard(text));
}
fn handle_raw_encoding(&mut self, x: u16, y: u16, width: u16, height: u16) {
self.require = width as usize * height as usize * self.pf.bits_per_pixel as usize / 8;
self.padding_rect = Some(VncRect {
x,
y,
width,
height,
encoding_type: VncEncoding::Raw,
});
}
fn handle_copy_rect_encoding(&mut self, x: u16, y: u16, width: u16, height: u16) {
console_log!("VNC: CopyRect {} {} {} {}", x, y, width, height);
self.require = 4;
self.padding_rect = Some(VncRect {
x,
y,
width,
height,
encoding_type: VncEncoding::CopyRect,
});
}
fn handle_rre_encoding(&mut self, _x: u16, _y: u16, _width: u16, _height: u16) {
// Note: RRE encoding is obsolescent. In general, ZRLE and TRLE
// encodings are more compact.
unimplemented!()
}
fn handle_hextile_encoding(&mut self, _x: u16, _y: u16, _width: u16, _height: u16) {
// Note: Hextile encoding is obsolescent. In general, ZRLE and TRLE
// encodings are more compact.
unimplemented!()
}
fn handle_tight_encoding(&mut self, x: u16, y: u16, width: u16, height: u16) {
self.require = 1;
self.padding_rect = Some(VncRect {
x,
y,
width,
height,
encoding_type: VncEncoding::Tight,
})
}
fn handle_trle_encoding(&mut self, _x: u16, _y: u16, _width: u16, _height: u16) {
unimplemented!()
}
fn handle_zrle_encoding(&mut self, x: u16, y: u16, width: u16, height: u16) {
self.require = 4;
self.padding_rect = Some(VncRect {
x,
y,
width,
height,
encoding_type: VncEncoding::ZRLE,
})
}
fn handle_cursor_pseudo_encoding(&mut self, _x: u16, _y: u16, _width: u16, _height: u16) {
unimplemented!()
}
fn handle_desktop_size_pseudo_encoding(&mut self, _x: u16, _y: u16, _width: u16, _height: u16) {
unimplemented!()
}
}
// No. of bytes Type [Value] Description
// 1 CARD8 bits-per-pixel
// 1 CARD8 depth
// 1 CARD8 big-endian-flag
// 1 CARD8 true-color-flag
// 2 CARD16 red-max
// 2 CARD16 green-max
// 2 CARD16 blue-max
// 1 CARD8 red-shift
// 1 CARD8 green-shift
// 1 CARD8 blue-shift
// 1 CARD8 padding
#[derive(Debug, Clone, Copy, Default)]
pub struct PixelFormat {
// the number of bits used for each pixel value on the wire
// 8, 16, 32(usually) only
pub bits_per_pixel: u8,
pub depth: u8,
// true if multi-byte pixels are interpreted as big endian
pub big_endian_flag: u8,
// true then the last six items specify how to extract the red, green and blue intensities from the pixel value
pub true_color_flag: u8,
// the next three always in big-endian order
// no matter how the `big_endian_flag` is set
pub red_max: u16,
pub green_max: u16,
pub blue_max: u16,
// the number of shifts needed to get the red value in a pixel to the least significant bit
pub red_shift: u8,
pub green_shift: u8,
pub blue_shift: u8,
padding_1: u8,
padding_2: u8,
padding_3: u8,
}
impl From<PixelFormat> for Vec<u8> {
fn from(pf: PixelFormat) -> Vec<u8> {
vec![
pf.bits_per_pixel,
pf.depth,
pf.big_endian_flag,
pf.true_color_flag,
(pf.red_max >> 8) as u8,
pf.red_max as u8,
(pf.green_max >> 8) as u8,
pf.green_max as u8,
(pf.blue_max >> 8) as u8,
pf.blue_max as u8,
pf.red_shift,
pf.green_shift,
pf.blue_shift,
pf.padding_1,
pf.padding_2,
pf.padding_3,
]
}
}
impl From<&[u8; 16]> for PixelFormat {
fn from(pf: &[u8; 16]) -> Self {
let bits_per_pixel = pf[0];
let depth = pf[1];
let big_endian_flag = pf[2];
let true_color_flag = pf[3];
let red_max = pf[4] as u16 | ((pf[5] as u16) << 8);
let green_max = pf[6] as u16 | ((pf[7] as u16) << 8);
let blue_max = pf[8] as u16 | ((pf[9] as u16) << 8);
let red_shift = pf[10];
let green_shift = pf[11];
let blue_shift = pf[12];
let padding_1 = pf[13];
let padding_2 = pf[14];
let padding_3 = pf[15];
Self {
bits_per_pixel,
depth,
big_endian_flag,
true_color_flag,
red_max,
green_max,
blue_max,
red_shift,
green_shift,
blue_shift,
padding_1,
padding_2,
padding_3,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct VncRect {
pub x: u16,
pub y: u16,
pub width: u16,
pub height: u16,
pub encoding_type: VncEncoding,
}