Refactor ends, remove obsolete files
This commit is contained in:
parent
5032a3c86a
commit
49ca82b0b6
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "webvnc"
|
||||
version = "0.1.0"
|
||||
version = "0.2.0"
|
||||
authors = ["Jovi Hsu <jv.hsu@outlook.com>"]
|
||||
edition = "2021"
|
||||
|
||||
|
@ -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>) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
@ -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,
|
||||
}),
|
||||
]))
|
||||
}
|
||||
}
|
@ -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(())
|
||||
}
|
||||
}
|
@ -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",
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
@ -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))
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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,
|
||||
}
|
Loading…
Reference in New Issue
Block a user