From 999edd10e7dc0fa13eeff38c2eec16ebd1824a09 Mon Sep 17 00:00:00 2001 From: Jovi Hsu Date: Wed, 10 Nov 2021 06:57:41 +0800 Subject: [PATCH] vnc start auth --- frontend/src/components/ws.rs | 4 ++ frontend/src/lib.rs | 1 + frontend/src/pages/page_remote.rs | 43 ++++++++++++++++--- frontend/src/protocal/common.rs | 30 ++++++++++++++ frontend/src/protocal/mod.rs | 1 + frontend/src/protocal/vnc.rs | 69 +++++++++++++++++++++++++++++-- frontend/src/utils.rs | 38 +++++++++++++++++ 7 files changed, 177 insertions(+), 9 deletions(-) create mode 100644 frontend/src/protocal/common.rs diff --git a/frontend/src/components/ws.rs b/frontend/src/components/ws.rs index fe475dc..101b78b 100644 --- a/frontend/src/components/ws.rs +++ b/frontend/src/components/ws.rs @@ -3,6 +3,8 @@ use yew::services::websocket::{WebSocketService, WebSocketStatus, WebSocketTask} use yew::services::ConsoleService; use yew::{format::Binary, utils::host}; +use crate::utils::WeakComponentLink; + pub struct WebsocketCtx { ws: Option, link: ComponentLink, @@ -14,6 +16,7 @@ pub struct WebsocketCtx { pub struct WebsocketProps { #[prop_or_default] pub onrecv: Callback>, + pub weak_link: WeakComponentLink, } pub enum WebsocketMsg { @@ -29,6 +32,7 @@ impl Component for WebsocketCtx { type Properties = WebsocketProps; fn create(props: Self::Properties, link: ComponentLink) -> Self { + props.weak_link.borrow_mut().replace(link.clone()); Self { ws: None, link: link, diff --git a/frontend/src/lib.rs b/frontend/src/lib.rs index cd81849..d70e508 100644 --- a/frontend/src/lib.rs +++ b/frontend/src/lib.rs @@ -1,6 +1,7 @@ mod app; mod components; mod pages; +mod protocal; mod utils; use wasm_bindgen::prelude::*; diff --git a/frontend/src/pages/page_remote.rs b/frontend/src/pages/page_remote.rs index a72e62f..e0d4d31 100644 --- a/frontend/src/pages/page_remote.rs +++ b/frontend/src/pages/page_remote.rs @@ -1,6 +1,7 @@ use serde_json::{json, Value}; use yew::{ format::Json, + html, prelude::*, services::{ fetch::{FetchTask, Request, Response}, @@ -8,7 +9,12 @@ use yew::{ }, }; -use crate::components; +use crate::components::ws::WebsocketMsg; +use crate::{ + components, + protocal::{common::*, vnc::VncHandler}, + utils::WeakComponentLink, +}; pub struct PageRemote { link: ComponentLink, @@ -16,18 +22,24 @@ pub struct PageRemote { error_msg: String, fetch_task: Option, connected: bool, + handler: ProtocalHandler, + ws_link: WeakComponentLink, } +#[derive(Clone, PartialEq, Properties)] +pub struct RemoteProps {} + pub enum RemoteMsg { Connect((String, u16)), ConnectResp(Result), Connected, Recv(Vec), + Send(Vec), } impl Component for PageRemote { type Message = RemoteMsg; - type Properties = (); + type Properties = RemoteProps; fn create(_: Self::Properties, link: ComponentLink) -> Self { PageRemote { @@ -36,6 +48,8 @@ impl Component for PageRemote { error_msg: String::from(""), fetch_task: None, connected: false, + handler: ProtocalHandler::new(), + ws_link: WeakComponentLink::default(), } } @@ -90,8 +104,26 @@ impl Component for PageRemote { true } RemoteMsg::Recv(v) => { - self.error_msg = String::from_utf8(v).unwrap(); - true + let out = self.handler.handle(&v); + match out { + ProtocalHandlerOutput::Err(err) => { + self.error_msg = err.clone(); + true + } + ProtocalHandlerOutput::Ok => false, + ProtocalHandlerOutput::WsBuf(out) => { + self.link.send_message(RemoteMsg::Send(out)); + false + } + } + } + RemoteMsg::Send(v) => { + self.ws_link + .borrow() + .as_ref() + .unwrap() + .send_message(WebsocketMsg::Send(Ok(v))); + false } } } @@ -111,10 +143,11 @@ impl Component for PageRemote { } } else { let recv_msg = self.link.callback(|v| RemoteMsg::Recv(v)); + let ws_link = &self.ws_link; html! { <> + weak_link=ws_link onrecv=recv_msg/> {self.error_msg.clone()} } diff --git a/frontend/src/protocal/common.rs b/frontend/src/protocal/common.rs new file mode 100644 index 0000000..7619419 --- /dev/null +++ b/frontend/src/protocal/common.rs @@ -0,0 +1,30 @@ +pub enum ProtocalHandlerOutput { + Ok, + WsBuf(Vec), + Err(String), +} + +pub struct ProtocalHandler +where + T: ProtocalImpl, +{ + inner: T, +} + +impl ProtocalHandler +where + T: ProtocalImpl, +{ + pub fn new() -> Self { + Self { inner: T::new() } + } + + pub fn handle(&mut self, input: &[u8]) -> ProtocalHandlerOutput { + self.inner.handle(input) + } +} + +pub trait ProtocalImpl { + fn new() -> Self; + fn handle(&mut self, input: &[u8]) -> ProtocalHandlerOutput; +} diff --git a/frontend/src/protocal/mod.rs b/frontend/src/protocal/mod.rs index 7391015..227f6f1 100644 --- a/frontend/src/protocal/mod.rs +++ b/frontend/src/protocal/mod.rs @@ -1 +1,2 @@ +pub mod common; pub mod vnc; diff --git a/frontend/src/protocal/vnc.rs b/frontend/src/protocal/vnc.rs index d88a901..bcbbe5c 100644 --- a/frontend/src/protocal/vnc.rs +++ b/frontend/src/protocal/vnc.rs @@ -1,5 +1,66 @@ -pub struct VncHandler { - wsFrame: Vec, - imageFrame: Vec, - outputFrame: Vec, + + +use yew::services::ConsoleService; + +use super::common::*; + +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"; + +enum VncState { + Handshake, + Authentication, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum SecurityType { + Unknown(u8), + Invalid, + None, + VncAuth, + AppleRdp, +} + +pub struct VncHandler { + state: VncState, + output: Vec, +} + +impl ProtocalImpl for VncHandler { + fn new() -> Self { + VncHandler { + state: VncState::Handshake, + output: Vec::new(), + } + } + + fn handle(&mut self, input: &[u8]) -> ProtocalHandlerOutput { + match self.state { + VncState::Handshake => { + self.handle_handshake(input); + self.state = VncState::Authentication; + return ProtocalHandlerOutput::WsBuf(self.output.clone()); + } + VncState::Authentication => { + ConsoleService::log(&format!("{:?}", input)); + return ProtocalHandlerOutput::Ok; + } + _ => panic!("unsupported version"), + } + } +} + +// private methods +impl VncHandler { + fn handle_handshake(&mut self, rfbversion: &[u8]) { + match rfbversion { + b"RFB 003.008\n" => { + for b in VNC_RFB33 { + self.output.push(*b); + } + } + _ => panic!("unsupported version"), + } + } } diff --git a/frontend/src/utils.rs b/frontend/src/utils.rs index c4be847..70136d0 100644 --- a/frontend/src/utils.rs +++ b/frontend/src/utils.rs @@ -1,3 +1,9 @@ +use std::{cell::RefCell, ops::Deref, rc::Rc}; +use yew::{ + html::{ComponentLink, ImplicitClone}, + Component, +}; + #[allow(dead_code)] pub fn set_panic_hook() { // When the `console_error_panic_hook` feature is enabled, we can call the @@ -9,3 +15,35 @@ pub fn set_panic_hook() { #[cfg(feature = "console_error_panic_hook")] console_error_panic_hook::set_once(); } + +// ComponentLink for sending message +// Option to be default none, later assign a vaule +// RefCell for container, mutable reference +// Rc for multiple ownership +pub struct WeakComponentLink(Rc>>>); +impl Clone for WeakComponentLink { + fn clone(&self) -> Self { + Self(Rc::clone(&self.0)) + } +} +impl ImplicitClone for WeakComponentLink {} + +impl Default for WeakComponentLink { + fn default() -> Self { + Self(Rc::default()) + } +} + +impl Deref for WeakComponentLink { + type Target = Rc>>>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl PartialEq for WeakComponentLink { + fn eq(&self, other: &Self) -> bool { + Rc::ptr_eq(&self.0, &other.0) + } +}