This commit is contained in:
Jovi Hsu 2021-11-15 16:42:46 +08:00
parent 918878b0c5
commit 2de7b4b9ec
3 changed files with 483 additions and 535 deletions

View File

@ -125,8 +125,8 @@ impl Component for PageRemote {
true true
} }
RemoteMsg::Recv(v) => { RemoteMsg::Recv(v) => {
let out = self.handler.handle(&v); self.handler.do_input(v);
self.protocal_out_handler(out) self.protocal_out_handler()
} }
RemoteMsg::Send(v) => { RemoteMsg::Send(v) => {
self.ws_link self.ws_link
@ -147,19 +147,18 @@ impl Component for PageRemote {
RemoteMsg::SendCredential => { RemoteMsg::SendCredential => {
self.request_username = false; self.request_username = false;
self.request_password = false; self.request_password = false;
let out = self.handler.set_credential(&self.username, &self.password); self.handler.set_credential(&self.username, &self.password);
let _ = self.protocal_out_handler(out); self.protocal_out_handler()
true
} }
RemoteMsg::RequireFrame(incremental) => { RemoteMsg::RequireFrame(incremental) => {
let out = self.handler.require_frame(incremental); self.handler.require_frame(incremental);
if self.interval.is_none() { if self.interval.is_none() {
let link = self.link.clone(); let link = self.link.clone();
let tick = let tick =
Interval::new(250, move || link.send_message(RemoteMsg::RequireFrame(1))); Interval::new(250, move || link.send_message(RemoteMsg::RequireFrame(1)));
self.interval = Some(tick); self.interval = Some(tick);
} }
self.protocal_out_handler(out) self.protocal_out_handler()
} }
} }
} }
@ -199,8 +198,12 @@ impl Component for PageRemote {
// impl PageRemote // impl PageRemote
impl PageRemote { impl PageRemote {
fn protocal_out_handler(&mut self, out: ProtocalHandlerOutput) -> ShouldRender { fn protocal_out_handler(&mut self) -> ShouldRender {
match out { let out = self.handler.get_output();
let mut should_render = false;
if !out.is_empty() {
for o in out {
match o {
ProtocalHandlerOutput::Err(err) => { ProtocalHandlerOutput::Err(err) => {
self.error_msg = err.clone(); self.error_msg = err.clone();
self.ws_link self.ws_link
@ -208,18 +211,17 @@ impl PageRemote {
.as_mut() .as_mut()
.unwrap() .unwrap()
.send_message(WebsocketMsg::Disconnected); .send_message(WebsocketMsg::Disconnected);
true should_render = true;
} }
ProtocalHandlerOutput::Ok => false, ProtocalHandlerOutput::Ok => (),
ProtocalHandlerOutput::WsBuf(out) => { ProtocalHandlerOutput::WsBuf(out) => {
self.link.send_message(RemoteMsg::Send(out)); self.link.send_message(RemoteMsg::Send(out));
false
} }
ProtocalHandlerOutput::RequirePassword => { ProtocalHandlerOutput::RequirePassword => {
self.request_password = true; self.request_password = true;
true should_render = true;
} }
ProtocalHandlerOutput::RenderCanvas(crs) => { ProtocalHandlerOutput::RenderCanvas(cr) => {
let canvas = self.canvas.cast::<HtmlCanvasElement>().unwrap(); let canvas = self.canvas.cast::<HtmlCanvasElement>().unwrap();
let ctx = match &self.canvas_ctx { let ctx = match &self.canvas_ctx {
Some(ctx) => ctx, Some(ctx) => ctx,
@ -232,30 +234,43 @@ impl PageRemote {
} }
}; };
for cr in crs {
let data = ImageData::new_with_u8_clamped_array_and_sh( let data = ImageData::new_with_u8_clamped_array_and_sh(
Clamped(&cr.data), Clamped(&cr.data),
cr.width as u32, cr.width as u32,
cr.height as u32, cr.height as u32,
) )
.unwrap(); .unwrap();
ConsoleService::log(&format!( // ConsoleService::log(&format!(
"renderring at ({}, {}), width {}, height {}", // "renderring at ({}, {}), width {}, height {}",
cr.x, cr.y, cr.width, cr.height // cr.x, cr.y, cr.width, cr.height
)); // ));
let _ = ctx.put_image_data(&data, cr.x as f64, cr.y as f64); let _ = ctx.put_image_data(&data, cr.x as f64, cr.y as f64);
} should_render = true;
true
} }
ProtocalHandlerOutput::SetCanvas(width, height) => { ProtocalHandlerOutput::SetCanvas(width, height) => {
let canvas = self.canvas.cast::<HtmlCanvasElement>().unwrap(); let canvas = self.canvas.cast::<HtmlCanvasElement>().unwrap();
canvas.set_width(width as u32); canvas.set_width(width as u32);
canvas.set_height(height as u32); canvas.set_height(height as u32);
self.link.send_message(RemoteMsg::RequireFrame(0)); self.link.send_message(RemoteMsg::RequireFrame(1));
true let ctx = match &self.canvas_ctx {
Some(ctx) => ctx,
None => {
let ctx = CanvasRenderingContext2d::from(JsValue::from(
canvas.get_context("2d").unwrap().unwrap(),
));
self.canvas_ctx = Some(ctx);
self.canvas_ctx.as_ref().unwrap()
} }
_ => false, };
ctx.rect(0 as f64, 0 as f64, width as f64, height as f64);
ctx.fill();
should_render = true;
} }
_ => unimplemented!(),
}
}
}
should_render
} }
fn username_view(&self) -> Html { fn username_view(&self) -> Html {

View File

@ -1,5 +1,3 @@
use std::slice::Iter;
pub struct CanvasData { pub struct CanvasData {
pub x: u16, pub x: u16,
pub y: u16, pub y: u16,
@ -15,7 +13,7 @@ pub enum ProtocalHandlerOutput {
RequireUsername, RequireUsername,
RequirePassword, RequirePassword,
SetCanvas(u16, u16), SetCanvas(u16, u16),
RenderCanvas(Vec<CanvasData>), RenderCanvas(CanvasData),
} }
pub struct ProtocalHandler<T> pub struct ProtocalHandler<T>
@ -33,99 +31,91 @@ where
Self { inner: T::new() } Self { inner: T::new() }
} }
pub fn handle(&mut self, input: &[u8]) -> ProtocalHandlerOutput { pub fn do_input(&mut self, input: Vec<u8>) {
self.inner.handle(input) self.inner.do_input(input);
} }
pub fn set_credential(&mut self, username: &str, password: &str) -> ProtocalHandlerOutput { pub fn get_output(&mut self) -> Vec<ProtocalHandlerOutput> {
self.inner.set_credential(username, password) self.inner.get_output()
} }
pub fn require_frame(&mut self, incremental: u8) -> ProtocalHandlerOutput { pub fn set_credential(&mut self, username: &str, password: &str) {
self.inner.require_frame(incremental) self.inner.set_credential(username, password);
}
pub fn require_frame(&mut self, incremental: u8) {
self.inner.require_frame(incremental);
} }
} }
pub trait ProtocalImpl { pub trait ProtocalImpl {
fn new() -> Self; fn new() -> Self;
fn handle(&mut self, input: &[u8]) -> ProtocalHandlerOutput; fn do_input(&mut self, input: Vec<u8>);
fn set_credential(&mut self, username: &str, password: &str) -> ProtocalHandlerOutput; fn get_output(&mut self) -> Vec<ProtocalHandlerOutput>;
fn require_frame(&mut self, incremental: u8) -> ProtocalHandlerOutput; fn set_credential(&mut self, username: &str, password: &str);
fn require_frame(&mut self, incremental: u8);
} }
pub struct StreamReader<'a> { pub struct StreamReader {
inner: Iter<'a, u8>, inner: Vec<Vec<u8>>,
} }
impl<'a> StreamReader<'a> { #[allow(dead_code)]
pub fn new(data: &'a [u8]) -> Self { impl StreamReader {
Self { pub fn new(bufs: Vec<Vec<u8>>) -> Self {
inner: data.into_iter(), Self { inner: bufs }
}
pub fn append(&mut self, buf: Vec<u8>) {
self.inner.push(buf);
}
pub fn read_exact(&mut self, out_buf: &mut [u8], n: usize) {
let mut i = 0;
let mut left = 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) -> Option<u8> { pub fn read_u8(&mut self) -> u8 {
self.inner.next().map(|&b| b) let mut buf = [0u8; 1];
self.read_exact(&mut buf, 1);
buf[0]
} }
pub fn read_u16(&mut self) -> Option<u16> { pub fn read_u16(&mut self) -> u16 {
let mut buf = [0u8; 2]; let mut buf = [0u8; 2];
self.inner.by_ref().take(2).enumerate().for_each(|(i, b)| { self.read_exact(&mut buf, 2);
buf[i] = *b; u16::from_be_bytes(buf)
});
Some(u16::from_be_bytes(buf))
} }
pub fn read_u32(&mut self) -> Option<u32> { pub fn read_u32(&mut self) -> u32 {
let mut buf = [0u8; 4]; let mut buf = [0u8; 4];
self.inner.by_ref().take(4).enumerate().for_each(|(i, b)| { self.read_exact(&mut buf, 4);
buf[i] = *b; u32::from_be_bytes(buf)
});
Some(u32::from_be_bytes(buf))
} }
pub fn read_s8(&mut self) -> Option<i8> { pub fn read_u64(&mut self) -> u64 {
Some(Self::read_u8(self).map(|b| b as i8)?) let mut buf = [0u8; 8];
self.read_exact(&mut buf, 8);
u64::from_be_bytes(buf)
} }
pub fn read_s16(&mut self) -> Option<i16> { pub fn read_string(&mut self, len: usize) -> String {
Some(Self::read_u16(self).map(|b| b as i16)?) let mut buf = vec![0u8; len];
} self.read_exact(&mut buf, len);
String::from_utf8(buf).unwrap()
pub fn read_s32(&mut self) -> Option<i32> {
Some(Self::read_u32(self).map(|b| b as i32)?)
}
pub fn extract_slice(&mut self, len: usize, buf: &mut [u8]) {
for x in self.inner.by_ref().take(len).enumerate() {
buf[x.0] = *x.1;
}
}
pub fn read_string_with_len(&mut self, len: usize) -> Option<String> {
let mut buf = vec![0u8; len as usize];
self.inner
.by_ref()
.take(len as usize)
.enumerate()
.for_each(|(i, b)| {
buf[i] = *b;
});
Some(String::from_utf8(buf).unwrap())
}
pub fn read_string_l16(&mut self) -> Option<String> {
let len = self.read_u16()? as usize;
Some(self.read_string_with_len(len)?)
}
pub fn read_string_l32(&mut self) -> Option<String> {
let len = self.read_u32()? as usize;
Some(self.read_string_with_len(len)?)
}
pub fn eof(&mut self) -> bool {
self.inner.next().is_none()
} }
} }
@ -133,6 +123,7 @@ pub struct StreamWriter<'a> {
inner: &'a mut Vec<u8>, inner: &'a mut Vec<u8>,
} }
#[allow(dead_code)]
impl<'a> StreamWriter<'a> { impl<'a> StreamWriter<'a> {
pub fn new(buf: &'a mut Vec<u8>) -> Self { pub fn new(buf: &'a mut Vec<u8>) -> Self {
Self { inner: buf } Self { inner: buf }

View File

@ -1,3 +1,5 @@
use super::common::*; use super::common::*;
use super::des; use super::des;
use yew::services::ConsoleService; use yew::services::ConsoleService;
@ -22,31 +24,84 @@ pub enum SecurityType {
// VeNCrypt = 19, // VeNCrypt = 19,
} }
pub enum VncState {
Init,
Handshake,
Authing,
ServerInit,
Connected,
Disconnected,
}
pub struct VncHandler { pub struct VncHandler {
inner: Box<dyn VncState>, state: VncState,
security_type: SecurityType,
challenge: [u8; 16],
buf_num: usize,
reader: StreamReader,
require: usize,
width: u16,
height: u16,
pf: PixelFormat,
name: String,
server_init: bool,
during_update: bool,
num_rects_left: u16,
padding_rect: Option<VncRect>,
outs: Vec<ProtocalHandlerOutput>,
} }
impl ProtocalImpl for VncHandler { impl ProtocalImpl for VncHandler {
fn new() -> Self { fn new() -> Self {
Self { Self {
inner: Box::new(VncHandShake::default()), state: VncState::Init,
security_type: SecurityType::Invalid,
challenge: [0; 16],
buf_num: 0,
reader: StreamReader::new(Vec::with_capacity(10)),
require: 12, // the handleshake message length
width: 0,
height: 0,
pf: PixelFormat::default(),
name: String::new(),
server_init: false,
during_update: false,
num_rects_left: 0,
padding_rect: None,
outs: Vec::with_capacity(10),
} }
} }
fn handle(&mut self, input: &[u8]) -> ProtocalHandlerOutput { fn do_input(&mut self, input: Vec<u8>) {
if self.inner.done() { self.buf_num += input.len();
self.inner = self.inner.next(); ConsoleService::info(&format!(
"VNC input {}, left {}, require {}",
input.len(),
self.buf_num,
self.require
));
self.reader.append(input);
while self.buf_num >= self.require {
self.handle_input();
} }
self.inner.handle(input)
} }
fn set_credential(&mut self, _username: &str, password: &str) -> ProtocalHandlerOutput { fn get_output(&mut self) -> Vec<ProtocalHandlerOutput> {
let mut out = Vec::with_capacity(self.outs.len());
// ConsoleService::log(&format!("Get {} output", self.outs.len()));
for o in self.outs.drain(..) {
out.push(o);
}
out
}
fn set_credential(&mut self, _username: &str, password: &str) {
// referring // referring
// https://github.com/whitequark/rust-vnc/blob/0697238f2706dd34a9a95c1640e385f6d8c02961/src/client.rs // https://github.com/whitequark/rust-vnc/blob/0697238f2706dd34a9a95c1640e385f6d8c02961/src/client.rs
// strange behavior // strange behavior
let pass_len = password.len(); let pass_len = password.len();
let mut pass_bytes = [0u8; 8]; let mut key = [0u8; 8];
for i in 0..8 { for i in 0..8 {
let c = if i < pass_len { let c = if i < pass_len {
password.as_bytes()[i] password.as_bytes()[i]
@ -57,242 +112,85 @@ impl ProtocalImpl for VncHandler {
for j in 0..8 { for j in 0..8 {
cs |= ((c >> j) & 1) << (7 - j) cs |= ((c >> j) & 1) << (7 - j)
} }
pass_bytes[i] = cs; key[i] = cs;
} }
self.inner.handle(&pass_bytes) // ConsoleService::log(&format!("challenge {:x?}", self.challenge));
let output = des::encrypt(&self.challenge, &key);
self.outs
.push(ProtocalHandlerOutput::WsBuf(output.to_vec()));
self.state = VncState::Authing;
self.require = 4; // the auth result message length
} }
fn require_frame(&mut self, incremental: u8) -> ProtocalHandlerOutput { fn require_frame(&mut self, incremental: u8) {
self.inner.frame_require(incremental) if !self.during_update {
}
}
trait VncState {
fn handle(&mut self, _input: &[u8]) -> ProtocalHandlerOutput;
fn frame_require(&self, _incremental: u8) -> ProtocalHandlerOutput {
ProtocalHandlerOutput::Err(VNC_FAILED.to_string())
}
fn done(&self) -> bool;
fn next(&self) -> Box<dyn VncState>;
}
struct VncHandShake {
done: bool,
}
impl Default for VncHandShake {
fn default() -> Self {
Self { done: false }
}
}
impl VncState for VncHandShake {
fn handle(&mut self, rfbversion: &[u8]) -> ProtocalHandlerOutput {
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),
};
self.done = true;
if let Ok(support_version) = support_version {
ProtocalHandlerOutput::WsBuf(support_version.to_vec())
} else {
ProtocalHandlerOutput::Err(support_version.err().unwrap().to_string())
}
}
fn done(&self) -> bool {
self.done
}
fn next(&self) -> Box<dyn VncState> {
Box::new(VncAuthentiacator::default())
}
}
struct VncAuthentiacator {
challenge: [u8; 16],
security_type: SecurityType,
wait_password: bool,
done: bool,
}
impl Default for VncAuthentiacator {
fn default() -> Self {
Self {
challenge: [0u8; 16],
security_type: SecurityType::Invalid,
wait_password: true,
done: false,
}
}
}
impl VncState for VncAuthentiacator {
fn handle(&mut self, input: &[u8]) -> ProtocalHandlerOutput {
if self.security_type == SecurityType::VncAuth {
if self.wait_password {
self.continue_authenticate(input)
} else {
self.handle_auth_response(input)
}
} else {
self.start_authenticate(input)
}
}
fn done(&self) -> bool {
self.done
}
fn next(&self) -> Box<dyn VncState> {
Box::new(VncDrawing::default())
}
}
impl VncAuthentiacator {
fn start_authenticate(&mut self, auth: &[u8]) -> ProtocalHandlerOutput {
let mut sr = StreamReader::new(auth);
match sr.read_u32() {
Some(0) => {
let err_msg = sr.read_string_l32().unwrap();
ProtocalHandlerOutput::Err(err_msg)
}
Some(1) => {
self.security_type = SecurityType::None;
self.send_client_initilize()
}
Some(2) => {
self.security_type = SecurityType::VncAuth;
self.wait_password = true;
sr.extract_slice(16, &mut self.challenge);
ProtocalHandlerOutput::RequirePassword
}
_ => ProtocalHandlerOutput::Err(VNC_FAILED.to_string()),
}
}
fn handle_auth_response(&mut self, response: &[u8]) -> ProtocalHandlerOutput {
let mut sr = StreamReader::new(response);
match sr.read_u32() {
Some(0) => self.send_client_initilize(),
Some(1) => {
let err_msg = sr.read_string_l32().unwrap();
ProtocalHandlerOutput::Err(err_msg)
}
_ => ProtocalHandlerOutput::Err(VNC_FAILED.to_string()),
}
}
fn continue_authenticate(&mut self, key_: &[u8]) -> ProtocalHandlerOutput {
// let key: &[u8; 8] = key_.try_into().unwrap();
let key = unsafe { std::mem::transmute(key_.as_ptr()) };
let output = des::encrypt(&self.challenge, key);
self.wait_password = false;
ProtocalHandlerOutput::WsBuf(output.to_vec())
}
fn send_client_initilize(&mut self) -> ProtocalHandlerOutput {
let shared_flag = 1;
self.done = true;
ProtocalHandlerOutput::WsBuf(vec![shared_flag].into())
}
}
struct VncDrawing {
width: u16,
height: u16,
pf: PixelFormat,
name: String,
server_init: bool,
buffer: Vec<u8>,
rects: Vec<VncRect>,
num_rects_left: u16,
}
impl Default for VncDrawing {
fn default() -> Self {
Self {
width: 0,
height: 0,
pf: PixelFormat::default(),
name: "".to_string(),
server_init: false,
buffer: Vec::with_capacity(50),
rects: Vec::new(),
num_rects_left: 0,
}
}
}
impl VncState for VncDrawing {
fn handle(&mut self, input: &[u8]) -> ProtocalHandlerOutput {
if self.server_init {
let mut sr = StreamReader::new(input);
if self.num_rects_left > 0 {
// still in the previous update frame request
self.extract_rects(&mut sr);
self.render_rects()
} else {
let msg_type = sr.read_u8().unwrap();
match msg_type {
0 => self.handle_framebuffer_update(&mut sr),
1 => self.handle_set_colour_map(&mut sr),
2 => self.handle_bell(&mut sr),
3 => self.handle_server_cut_text(&mut sr),
_ => ProtocalHandlerOutput::Err(VNC_FAILED.to_string()),
}
}
} else {
self.handle_server_init(input)
}
}
fn frame_require(&self, incremental: u8) -> ProtocalHandlerOutput {
if self.num_rects_left > 0 {
ProtocalHandlerOutput::Ok
} else {
self.framebuffer_update_request(incremental) self.framebuffer_update_request(incremental)
} }
} }
}
fn done(&self) -> bool { #[allow(dead_code)]
false impl VncHandler {
fn read_u8(&mut self) -> u8 {
self.buf_num -= 1;
self.reader.read_u8()
} }
fn next(&self) -> Box<dyn VncState> { fn read_u16(&mut self) -> u16 {
Box::new(VncEnds) self.buf_num -= 2;
self.reader.read_u16()
}
fn read_u32(&mut self) -> u32 {
self.buf_num -= 4;
self.reader.read_u32()
}
fn read_u64(&mut self) -> u64 {
self.buf_num -= 8;
self.reader.read_u64()
}
fn read_exact(&mut self, buf: &mut [u8], len: usize) {
self.buf_num -= len;
self.reader.read_exact(buf, len)
}
fn read_string_l8(&mut self) -> String {
let len = self.read_u8() as usize;
self.buf_num -= len;
self.reader.read_string(len)
}
fn read_string_l16(&mut self) -> String {
let len = self.read_u16() as usize;
self.buf_num -= len;
self.reader.read_string(len)
}
fn read_string_l32(&mut self) -> String {
let len = self.read_u32() as usize;
self.buf_num -= len;
self.reader.read_string(len)
} }
} }
impl VncDrawing { impl VncHandler {
// example fn disconnect_with_err(&mut self, err: &str) {
// [7, 128, 4, 176, 32, 24, 0, 1, 0, 255, 0, 255, 0, 255, 16, 8, 0, 0, 0, 0, 0, 0, 0, 14, 54, 122, 122, 100, 114, 113, 50, 45, 106, 105, 97, 120, 117, 0] ConsoleService::error(err);
// No. of bytes Type [Value] Description self.state = VncState::Disconnected;
// 2 CARD16 framebuffer-width self.outs.push(ProtocalHandlerOutput::Err(err.to_string()));
// 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, init: &[u8]) -> ProtocalHandlerOutput {
self.buffer.extend_from_slice(init);
if self.buffer.len() > 24 {
let mut sr = StreamReader::new(init);
self.width = sr.read_u16().unwrap();
self.height = sr.read_u16().unwrap();
let mut pfb: [u8; 16] = [0u8; 16];
sr.extract_slice(16, &mut pfb);
// This pixel format will be used unless the client requests a different format using the SetPixelFormat message
self.pf = (&pfb).into();
self.name = sr.read_string_l32().unwrap();
ConsoleService::log(&format!("VNC: {}x{}", self.width, self.height));
self.server_init = true;
ProtocalHandlerOutput::SetCanvas(self.width, self.height)
} else {
ProtocalHandlerOutput::Ok
} }
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.outs
.push(ProtocalHandlerOutput::WsBuf(vec![shared_flag].into()));
} }
// No. of bytes Type [Value] Description // No. of bytes Type [Value] Description
@ -302,8 +200,9 @@ impl VncDrawing {
// 2 CARD16 y-position // 2 CARD16 y-position
// 2 CARD16 width // 2 CARD16 width
// 2 CARD16 height // 2 CARD16 height
fn framebuffer_update_request(&self, incremental: u8) -> ProtocalHandlerOutput { fn framebuffer_update_request(&mut self, incremental: u8) {
// ConsoleService::log(&format!("VNC: framebuffer_update_request {}", incremental)); // ConsoleService::log(&format!("VNC: framebuffer_update_request {}", incremental));
self.during_update = true;
let mut out: Vec<u8> = Vec::new(); let mut out: Vec<u8> = Vec::new();
let mut sw = StreamWriter::new(&mut out); let mut sw = StreamWriter::new(&mut out);
sw.write_u8(3); sw.write_u8(3);
@ -312,7 +211,111 @@ impl VncDrawing {
sw.write_u16(0); sw.write_u16(0);
sw.write_u16(self.width); sw.write_u16(self.width);
sw.write_u16(self.height); sw.write_u16(self.height);
ProtocalHandlerOutput::WsBuf(out) self.outs.push(ProtocalHandlerOutput::WsBuf(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(),
_ => unimplemented!(),
}
}
fn do_handshake(&mut self) {
let mut rfbversion: [u8; 12] = [0; 12];
self.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.outs.push(ProtocalHandlerOutput::WsBuf(v.to_vec()));
}
Err(e) => self.disconnect_with_err(e),
}
}
fn do_authenticate(&mut self) {
if self.security_type == SecurityType::Invalid {
let auth_type = self.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.read_exact(&mut challenge, 16);
self.challenge = challenge;
self.outs.push(ProtocalHandlerOutput::RequirePassword);
}
}
fn handle_auth_result(&mut self) {
let response = self.read_u32();
ConsoleService::log(&format!("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.read_u16();
self.height = self.read_u16();
let mut pfb: [u8; 16] = [0u8; 16];
self.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();
ConsoleService::log(&format!("VNC: {}x{}", self.width, self.height));
self.name = self.read_string_l32();
self.state = VncState::Connected;
self.require = 1; // any message from sever will be handled
self.outs
.push(ProtocalHandlerOutput::SetCanvas(self.width, self.height));
}
fn handle_server_message(&mut self) {
if self.num_rects_left > 0 {
self.read_rect();
} else {
let msg_type = self.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 // No. of bytes Type [Value] Description
@ -320,163 +323,115 @@ impl VncDrawing {
// 1 padding // 1 padding
// 2 CARD16 number-of-rectangles // 2 CARD16 number-of-rectangles
// This is followed by number-of-rectanglesrectangles of pixel data. // This is followed by number-of-rectanglesrectangles of pixel data.
fn handle_framebuffer_update(&mut self, sr: &mut StreamReader) -> ProtocalHandlerOutput { fn handle_framebuffer_update(&mut self) {
let _padding = sr.read_u8().unwrap(); let _padding = self.read_u8();
self.num_rects_left = sr.read_u16().unwrap(); self.num_rects_left = self.read_u16();
self.rects = Vec::with_capacity(self.num_rects_left as usize); ConsoleService::log(&format!("VNC: {} rects", self.num_rects_left));
self.extract_rects(sr); self.require = 12; // the length of the first rectangle
self.render_rects()
} }
fn handle_set_colour_map(&mut self, _sr: &mut StreamReader) -> ProtocalHandlerOutput { //Each rectangle consists of:
unimplemented!() // 2 CARD16 x-position
} // 2 CARD16 y-position
// 2 CARD16 width
fn handle_bell(&mut self, _sr: &mut StreamReader) -> ProtocalHandlerOutput { // 2 CARD16 height
unimplemented!() // 4 CARD32 encoding-type:
} // 0 raw encoding
// 1 copy rectangle encoding
fn handle_server_cut_text(&mut self, _sr: &mut StreamReader) -> ProtocalHandlerOutput { // 2 RRE encoding
unimplemented!() // 4 CoRRE encoding
} // 5 Hextile encoding
fn read_rect(&mut self) {
fn extract_rects(&mut self, sr: &mut StreamReader) { if self.padding_rect.is_none() {
while self.num_rects_left > 0 { // a brand new rectangle
// we always keep the last rect in the vec let x = self.read_u16();
// and all the rects that has already been re-assembly should already been rendered let y = self.read_u16();
if self.rects.len() > 0 && self.rects.last().unwrap().left_data > 0 { let width = self.read_u16();
// which means that there is one rects that has not been re-assembly let height = self.read_u16();
let last_rect = self.rects.last_mut().unwrap(); let encoding_type = self.read_u32();
while let Some(v) = sr.read_u8() {
last_rect.encoding_data.push(v);
last_rect.left_data -= 1;
if last_rect.left_data == 0 {
// at the end of the rect
self.num_rects_left -= 1;
break;
}
}
ConsoleService::log(&format!(
"VNC read: {}, pending {}",
last_rect.encoding_data.len(),
last_rect.left_data
));
if last_rect.left_data == 0 {
// there is still some data left
// start a new rect
// it must be handled in the else branch
continue;
} else {
// break the while loop
// render as much as we can
break;
}
} else {
// a brand new rects
let x = sr.read_u16().unwrap();
let y = sr.read_u16().unwrap();
let width = sr.read_u16().unwrap();
let height = sr.read_u16().unwrap();
let encoding_type = sr.read_u32().unwrap();
match encoding_type { match encoding_type {
0 => self.handle_raw_encoding(x, y, width, height),
1 => self.handle_copy_rect_encoding(x, y, width, height),
2 => self.handle_rre_encoding(x, y, width, height),
4 => self.handle_corre_encoding(x, y, width, height),
5 => self.handle_hextile_encoding(x, y, width, height),
_ => self.disconnect_with_err(VNC_FAILED),
}
} else {
// we now have an entire rectangle
let rect = self.padding_rect.take().unwrap();
let mut image_data: Vec<u8> = Vec::with_capacity(self.require);
match rect.encoding_type {
0 => { 0 => {
let mut left_data = width as u32 * height as u32 * 4; for _ in 0..rect.height {
let mut encoding_data: Vec<u8> = Vec::with_capacity(left_data as usize); for _ in 0..rect.width {
while let Some(v) = sr.read_u8() { let mut pixel = [0u8; 4];
// read as much as we can self.read_exact(&mut pixel, 4);
encoding_data.push(v); let b = pixel[0];
if encoding_data.len() == left_data as usize { let g = pixel[1];
break; let r = pixel[2];
let a = pixel[3];
image_data.extend_from_slice(&[r, g, b, a]);
} }
} }
left_data -= encoding_data.len() as u32; }
if left_data == 0 { _ => unimplemented!(),
}
self.outs
.push(ProtocalHandlerOutput::RenderCanvas(CanvasData {
x: rect.x,
y: rect.y,
width: rect.width,
height: rect.height,
data: image_data,
}));
self.num_rects_left -= 1; self.num_rects_left -= 1;
} }
// ConsoleService::log(&format!("VNC read new: {}", encoding_data.len())); if 0 == self.num_rects_left {
self.rects.push(VncRect { self.during_update = false;
self.require = 1;
}
ConsoleService::log(&format!("{} rects left", self.num_rects_left));
}
fn handle_set_colour_map(&mut self) {
unimplemented!()
}
fn handle_bell(&mut self) {
unimplemented!()
}
fn handle_server_cut_text(&mut self) {
unimplemented!()
}
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, x,
y, y,
width, width,
height, height,
encoding_data, encoding_type: 0,
encoding_type, encoding_data: Vec::new(), // we donnot need to store the data
left_data,
}); });
// break the while loop
// render as much as we can
break;
} }
_ => {
ConsoleService::log(&format!( fn handle_copy_rect_encoding(&mut self, _x: u16, _y: u16, _width: u16, _height: u16) {
"VNC: unknown encoding type {}",
encoding_type
));
ConsoleService::log(&format!(
"VNC: x:{}, y:{}, w:{}, h:{}",
x, y, width, height
));
ConsoleService::log(&format!("VNC: left_data:{:x?}", sr.read_u32()));
unimplemented!() unimplemented!()
} }
}
} fn handle_rre_encoding(&mut self, _x: u16, _y: u16, _width: u16, _height: u16) {
} unimplemented!()
} }
fn render_rects(&mut self) -> ProtocalHandlerOutput { fn handle_corre_encoding(&mut self, _x: u16, _y: u16, _width: u16, _height: u16) {
let mut out: Vec<CanvasData> = Vec::new(); unimplemented!()
if self.rects.len() > 1 || self.num_rects_left == 0 {
let drain_len = {
if self.num_rects_left != 0 {
self.rects.len() - 1
} else {
self.rects.len()
}
};
ConsoleService::log(&format!("VNC render {} rects", drain_len));
for x in self.rects.drain(0..drain_len) {
let mut data: Vec<u8> = Vec::with_capacity(x.encoding_data.len());
for i in 0..x.width {
for j in 0..x.height {
let idx = (i as usize + j as usize * x.width as usize) * 4;
let b = x.encoding_data[idx + 0];
let g = x.encoding_data[idx + 1];
let r = x.encoding_data[idx + 2];
let a = x.encoding_data[idx + 3];
data.extend_from_slice(&[r, g, b, a]);
}
}
out.push(CanvasData {
x: x.x,
y: x.y,
width: x.width,
height: x.height,
data,
});
}
} }
ProtocalHandlerOutput::RenderCanvas(out) fn handle_hextile_encoding(&mut self, _x: u16, _y: u16, _width: u16, _height: u16) {
} unimplemented!()
}
struct VncEnds;
impl VncState for VncEnds {
fn handle(&mut self, _input: &[u8]) -> ProtocalHandlerOutput {
ProtocalHandlerOutput::Err(VNC_FAILED.to_string())
}
fn done(&self) -> bool {
false
}
fn next(&self) -> Box<dyn VncState> {
Box::new(VncEnds)
} }
} }
@ -541,20 +496,19 @@ impl From<PixelFormat> for Vec<u8> {
impl From<&[u8; 16]> for PixelFormat { impl From<&[u8; 16]> for PixelFormat {
fn from(pf: &[u8; 16]) -> Self { fn from(pf: &[u8; 16]) -> Self {
let mut sr = StreamReader::new(pf); let bits_per_pixel = pf[0];
let bits_per_pixel = sr.read_u8().unwrap(); let depth = pf[1];
let depth = sr.read_u8().unwrap(); let big_endian_flag = pf[2];
let big_endian_flag = sr.read_u8().unwrap(); let true_color_flag = pf[3];
let true_color_flag = sr.read_u8().unwrap(); let red_max = pf[4] as u16 | ((pf[5] as u16) << 8);
let red_max = sr.read_u16().unwrap(); let green_max = pf[6] as u16 | ((pf[7] as u16) << 8);
let green_max = sr.read_u16().unwrap(); let blue_max = pf[8] as u16 | ((pf[9] as u16) << 8);
let blue_max = sr.read_u16().unwrap(); let red_shift = pf[10];
let red_shift = sr.read_u8().unwrap(); let green_shift = pf[11];
let green_shift = sr.read_u8().unwrap(); let blue_shift = pf[12];
let blue_shift = sr.read_u8().unwrap(); let padding_1 = pf[13];
let padding_1 = sr.read_u8().unwrap(); let padding_2 = pf[14];
let padding_2 = sr.read_u8().unwrap(); let padding_3 = pf[15];
let padding_3 = sr.read_u8().unwrap();
Self { Self {
bits_per_pixel, bits_per_pixel,
depth, depth,
@ -593,17 +547,6 @@ impl Default for PixelFormat {
} }
} }
//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
struct VncRect { struct VncRect {
x: u16, x: u16,
y: u16, y: u16,
@ -611,5 +554,4 @@ struct VncRect {
height: u16, height: u16,
encoding_type: u32, encoding_type: u32,
encoding_data: Vec<u8>, encoding_data: Vec<u8>,
left_data: u32,
} }