vnc start auth

This commit is contained in:
Jovi Hsu 2021-11-10 06:57:41 +08:00
parent d350dbe0bf
commit 999edd10e7
7 changed files with 177 additions and 9 deletions

View File

@ -3,6 +3,8 @@ use yew::services::websocket::{WebSocketService, WebSocketStatus, WebSocketTask}
use yew::services::ConsoleService; use yew::services::ConsoleService;
use yew::{format::Binary, utils::host}; use yew::{format::Binary, utils::host};
use crate::utils::WeakComponentLink;
pub struct WebsocketCtx { pub struct WebsocketCtx {
ws: Option<WebSocketTask>, ws: Option<WebSocketTask>,
link: ComponentLink<Self>, link: ComponentLink<Self>,
@ -14,6 +16,7 @@ pub struct WebsocketCtx {
pub struct WebsocketProps { pub struct WebsocketProps {
#[prop_or_default] #[prop_or_default]
pub onrecv: Callback<Vec<u8>>, pub onrecv: Callback<Vec<u8>>,
pub weak_link: WeakComponentLink<WebsocketCtx>,
} }
pub enum WebsocketMsg { pub enum WebsocketMsg {
@ -29,6 +32,7 @@ impl Component for WebsocketCtx {
type Properties = WebsocketProps; type Properties = WebsocketProps;
fn create(props: Self::Properties, link: ComponentLink<Self>) -> Self { fn create(props: Self::Properties, link: ComponentLink<Self>) -> Self {
props.weak_link.borrow_mut().replace(link.clone());
Self { Self {
ws: None, ws: None,
link: link, link: link,

View File

@ -1,6 +1,7 @@
mod app; mod app;
mod components; mod components;
mod pages; mod pages;
mod protocal;
mod utils; mod utils;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;

View File

@ -1,6 +1,7 @@
use serde_json::{json, Value}; use serde_json::{json, Value};
use yew::{ use yew::{
format::Json, format::Json,
html,
prelude::*, prelude::*,
services::{ services::{
fetch::{FetchTask, Request, Response}, 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 { pub struct PageRemote {
link: ComponentLink<Self>, link: ComponentLink<Self>,
@ -16,18 +22,24 @@ pub struct PageRemote {
error_msg: String, error_msg: String,
fetch_task: Option<FetchTask>, fetch_task: Option<FetchTask>,
connected: bool, connected: bool,
handler: ProtocalHandler<VncHandler>,
ws_link: WeakComponentLink<components::ws::WebsocketCtx>,
} }
#[derive(Clone, PartialEq, Properties)]
pub struct RemoteProps {}
pub enum RemoteMsg { pub enum RemoteMsg {
Connect((String, u16)), Connect((String, u16)),
ConnectResp(Result<Value, anyhow::Error>), ConnectResp(Result<Value, anyhow::Error>),
Connected, Connected,
Recv(Vec<u8>), Recv(Vec<u8>),
Send(Vec<u8>),
} }
impl Component for PageRemote { impl Component for PageRemote {
type Message = RemoteMsg; type Message = RemoteMsg;
type Properties = (); type Properties = RemoteProps;
fn create(_: Self::Properties, link: ComponentLink<Self>) -> Self { fn create(_: Self::Properties, link: ComponentLink<Self>) -> Self {
PageRemote { PageRemote {
@ -36,6 +48,8 @@ impl Component for PageRemote {
error_msg: String::from(""), error_msg: String::from(""),
fetch_task: None, fetch_task: None,
connected: false, connected: false,
handler: ProtocalHandler::new(),
ws_link: WeakComponentLink::default(),
} }
} }
@ -90,9 +104,27 @@ impl Component for PageRemote {
true true
} }
RemoteMsg::Recv(v) => { RemoteMsg::Recv(v) => {
self.error_msg = String::from_utf8(v).unwrap(); let out = self.handler.handle(&v);
match out {
ProtocalHandlerOutput::Err(err) => {
self.error_msg = err.clone();
true 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 { } else {
let recv_msg = self.link.callback(|v| RemoteMsg::Recv(v)); let recv_msg = self.link.callback(|v| RemoteMsg::Recv(v));
let ws_link = &self.ws_link;
html! { html! {
<> <>
<components::ws::WebsocketCtx <components::ws::WebsocketCtx
onrecv=recv_msg/> weak_link=ws_link onrecv=recv_msg/>
{self.error_msg.clone()} {self.error_msg.clone()}
</> </>
} }

View File

@ -0,0 +1,30 @@
pub enum ProtocalHandlerOutput {
Ok,
WsBuf(Vec<u8>),
Err(String),
}
pub struct ProtocalHandler<T>
where
T: ProtocalImpl,
{
inner: T,
}
impl<T> ProtocalHandler<T>
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;
}

View File

@ -1 +1,2 @@
pub mod common;
pub mod vnc; pub mod vnc;

View File

@ -1,5 +1,66 @@
pub struct VncHandler {
wsFrame: Vec<u8>,
imageFrame: Vec<u8>, use yew::services::ConsoleService;
outputFrame: Vec<u8>,
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<u8>,
}
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"),
}
}
} }

View File

@ -1,3 +1,9 @@
use std::{cell::RefCell, ops::Deref, rc::Rc};
use yew::{
html::{ComponentLink, ImplicitClone},
Component,
};
#[allow(dead_code)] #[allow(dead_code)]
pub fn set_panic_hook() { pub fn set_panic_hook() {
// When the `console_error_panic_hook` feature is enabled, we can call the // 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")] #[cfg(feature = "console_error_panic_hook")]
console_error_panic_hook::set_once(); 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<COMP: Component>(Rc<RefCell<Option<ComponentLink<COMP>>>>);
impl<COMP: Component> Clone for WeakComponentLink<COMP> {
fn clone(&self) -> Self {
Self(Rc::clone(&self.0))
}
}
impl<COMP: Component> ImplicitClone for WeakComponentLink<COMP> {}
impl<COMP: Component> Default for WeakComponentLink<COMP> {
fn default() -> Self {
Self(Rc::default())
}
}
impl<COMP: Component> Deref for WeakComponentLink<COMP> {
type Target = Rc<RefCell<Option<ComponentLink<COMP>>>>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<COMP: Component> PartialEq for WeakComponentLink<COMP> {
fn eq(&self, other: &Self) -> bool {
Rc::ptr_eq(&self.0, &other.0)
}
}