dummy
This commit is contained in:
parent
a0b1157c04
commit
c8bb376d80
@ -1,3 +1,4 @@
|
||||
use super::input::Input;
|
||||
use anyhow;
|
||||
use serde_json::{json, Value};
|
||||
use std::fmt::Debug;
|
||||
@ -116,28 +117,19 @@ impl Component for AuthComponents {
|
||||
fn view(&self) -> Html {
|
||||
let link = &self.link;
|
||||
|
||||
let update_uname = link.callback(|e: ChangeData| match e {
|
||||
ChangeData::Value(val) => AuthMsg::UpdateUsername(val),
|
||||
_ => panic!("unexpected message"),
|
||||
});
|
||||
let update_uname = link.callback(|v| AuthMsg::UpdateUsername(v));
|
||||
|
||||
let update_pword = link.callback(|e: ChangeData| match e {
|
||||
ChangeData::Value(val) => AuthMsg::UpdatePassword(val),
|
||||
_ => panic!("unexpected message"),
|
||||
});
|
||||
let update_pword = link.callback(|v| AuthMsg::UpdatePassword(v));
|
||||
|
||||
let auth_post = link.callback(|_| {
|
||||
// ConsoleService::log("Auth post");
|
||||
AuthMsg::AuthRequest
|
||||
});
|
||||
let auth_post = link.callback(|_| AuthMsg::AuthRequest);
|
||||
|
||||
html! {
|
||||
<div class="horizontal-centre vertical-centre">
|
||||
<label for="username">{"Username: "}</label>
|
||||
<input id="username" type="text" placeholder="Username" onchange={update_uname} />
|
||||
<Input id="username" type_="text" placeholder="Username" on_change={update_uname} />
|
||||
<br />
|
||||
<label for="password">{"Password: "}</label>
|
||||
<input id="password" type="password" placeholder="Password" onchange={update_pword} />
|
||||
<Input id="password" type_="password" placeholder="Password" on_change={update_pword} />
|
||||
<br />
|
||||
<button type="submit" onclick={auth_post}>{"Login"}</button>
|
||||
<br />
|
||||
|
68
frontend/src/components/input.rs
Normal file
68
frontend/src/components/input.rs
Normal file
@ -0,0 +1,68 @@
|
||||
use yew::prelude::*;
|
||||
|
||||
// message on update
|
||||
pub enum InputMsg {
|
||||
Update(String),
|
||||
}
|
||||
|
||||
// props on_change
|
||||
#[derive(Clone, PartialEq, Properties)]
|
||||
pub struct InputProps {
|
||||
pub on_change: Callback<String>,
|
||||
pub id: String,
|
||||
pub type_: String,
|
||||
pub placeholder: String,
|
||||
}
|
||||
|
||||
// component input
|
||||
pub struct Input {
|
||||
link: ComponentLink<Self>,
|
||||
on_change: Callback<String>,
|
||||
id: String,
|
||||
type_: String,
|
||||
placeholder: String,
|
||||
}
|
||||
|
||||
impl Component for Input {
|
||||
type Message = InputMsg;
|
||||
type Properties = InputProps;
|
||||
|
||||
fn create(props: Self::Properties, link: ComponentLink<Self>) -> Self {
|
||||
Input {
|
||||
link,
|
||||
on_change: props.on_change,
|
||||
id: props.id,
|
||||
type_: props.type_,
|
||||
placeholder: props.placeholder,
|
||||
}
|
||||
}
|
||||
|
||||
fn update(&mut self, msg: Self::Message) -> ShouldRender {
|
||||
match msg {
|
||||
InputMsg::Update(text) => {
|
||||
self.on_change.emit(text);
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn change(&mut self, _props: Self::Properties) -> ShouldRender {
|
||||
false
|
||||
}
|
||||
|
||||
fn view(&self) -> Html {
|
||||
let on_change = self.link.callback(|e: ChangeData| match e {
|
||||
ChangeData::Value(v) => InputMsg::Update(v),
|
||||
_ => panic!("unexpected message"),
|
||||
});
|
||||
|
||||
html! {
|
||||
<input
|
||||
id={self.id.clone()}
|
||||
type={self.type_.clone()}
|
||||
placeholder={self.placeholder.clone()}
|
||||
onchange={on_change}
|
||||
/>
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
pub mod auth;
|
||||
pub mod host;
|
||||
pub mod input;
|
||||
pub mod ws;
|
||||
|
@ -104,6 +104,7 @@ impl Component for WebsocketCtx {
|
||||
|
||||
fn rendered(&mut self, first_render: bool) {
|
||||
if first_render && self.ws.is_none() {
|
||||
ConsoleService::log(&format!("Start websocket"));
|
||||
self.link.send_message(WebsocketMsg::Connect);
|
||||
}
|
||||
}
|
||||
|
@ -9,9 +9,8 @@ use yew::{
|
||||
},
|
||||
};
|
||||
|
||||
use crate::components::ws::WebsocketMsg;
|
||||
use crate::{
|
||||
components,
|
||||
components::{self, input::Input, ws::WebsocketMsg},
|
||||
protocal::{common::*, vnc::VncHandler},
|
||||
utils::WeakComponentLink,
|
||||
};
|
||||
@ -24,6 +23,10 @@ pub struct PageRemote {
|
||||
connected: bool,
|
||||
handler: ProtocalHandler<VncHandler>,
|
||||
ws_link: WeakComponentLink<components::ws::WebsocketCtx>,
|
||||
request_username: bool,
|
||||
request_password: bool,
|
||||
username: String,
|
||||
password: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Properties)]
|
||||
@ -35,6 +38,9 @@ pub enum RemoteMsg {
|
||||
Connected,
|
||||
Recv(Vec<u8>),
|
||||
Send(Vec<u8>),
|
||||
UpdateUsername(String),
|
||||
UpdatePassword(String),
|
||||
SendCredential,
|
||||
}
|
||||
|
||||
impl Component for PageRemote {
|
||||
@ -50,6 +56,10 @@ impl Component for PageRemote {
|
||||
connected: false,
|
||||
handler: ProtocalHandler::new(),
|
||||
ws_link: WeakComponentLink::default(),
|
||||
request_username: false,
|
||||
request_password: false,
|
||||
username: String::from(""),
|
||||
password: String::from(""),
|
||||
}
|
||||
}
|
||||
|
||||
@ -115,6 +125,11 @@ impl Component for PageRemote {
|
||||
self.link.send_message(RemoteMsg::Send(out));
|
||||
false
|
||||
}
|
||||
ProtocalHandlerOutput::RequirePassword => {
|
||||
self.request_password = true;
|
||||
true
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
RemoteMsg::Send(v) => {
|
||||
@ -125,6 +140,20 @@ impl Component for PageRemote {
|
||||
.send_message(WebsocketMsg::Send(Ok(v)));
|
||||
false
|
||||
}
|
||||
RemoteMsg::UpdateUsername(username) => {
|
||||
self.username = username;
|
||||
true
|
||||
}
|
||||
RemoteMsg::UpdatePassword(password) => {
|
||||
self.password = password;
|
||||
true
|
||||
}
|
||||
RemoteMsg::SendCredential => {
|
||||
self.request_username = false;
|
||||
self.request_password = false;
|
||||
self.handler.set_credential(&self.username, &self.password);
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -146,11 +175,61 @@ impl Component for PageRemote {
|
||||
let ws_link = &self.ws_link;
|
||||
html! {
|
||||
<>
|
||||
<div class="horizontal-centre vertical-centre">
|
||||
{self.username_view()}
|
||||
{self.password_view()}
|
||||
{self.button_connect_view()}
|
||||
<components::ws::WebsocketCtx
|
||||
weak_link=ws_link onrecv=recv_msg/>
|
||||
{self.error_msg.clone()}
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// impl PageRemote
|
||||
impl PageRemote {
|
||||
fn username_view(&self) -> Html {
|
||||
if self.request_username {
|
||||
let update_username = self.link.callback(|v| RemoteMsg::UpdateUsername(v));
|
||||
html! {
|
||||
<>
|
||||
<Input id="username" type_="text" placeholder="username" on_change={update_username}/>
|
||||
<br/>
|
||||
</>
|
||||
}
|
||||
} else {
|
||||
html! {}
|
||||
}
|
||||
}
|
||||
|
||||
fn password_view(&self) -> Html {
|
||||
if self.request_password {
|
||||
let update_password = self.link.callback(|v| RemoteMsg::UpdatePassword(v));
|
||||
html! {
|
||||
<>
|
||||
<Input id="password" type_="password" placeholder="password" on_change={update_password}/>
|
||||
<br/>
|
||||
</>
|
||||
}
|
||||
} else {
|
||||
html! {}
|
||||
}
|
||||
}
|
||||
|
||||
fn button_connect_view(&self) -> Html {
|
||||
if self.request_username || self.request_password {
|
||||
let send_credential = self.link.callback(|_| RemoteMsg::SendCredential);
|
||||
html! {
|
||||
<>
|
||||
<button type="submit" onclick={send_credential}>{"Connect"}</button>
|
||||
<br/>
|
||||
</>
|
||||
}
|
||||
} else {
|
||||
html! {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,8 @@ pub enum ProtocalHandlerOutput {
|
||||
Ok,
|
||||
WsBuf(Vec<u8>),
|
||||
Err(String),
|
||||
RequireUsername,
|
||||
RequirePassword,
|
||||
}
|
||||
|
||||
pub struct ProtocalHandler<T>
|
||||
@ -23,11 +25,16 @@ where
|
||||
pub fn handle(&mut self, input: &[u8]) -> ProtocalHandlerOutput {
|
||||
self.inner.handle(input)
|
||||
}
|
||||
|
||||
pub fn set_credential(&mut self, username: &str, password: &str) -> ProtocalHandlerOutput {
|
||||
self.inner.set_credential(username, password)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ProtocalImpl {
|
||||
fn new() -> Self;
|
||||
fn handle(&mut self, input: &[u8]) -> ProtocalHandlerOutput;
|
||||
fn set_credential(&mut self, username: &str, password: &str) -> ProtocalHandlerOutput;
|
||||
}
|
||||
|
||||
pub struct StreamReader<'a> {
|
||||
@ -73,6 +80,12 @@ impl<'a> StreamReader<'a> {
|
||||
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
|
||||
@ -85,11 +98,16 @@ impl<'a> StreamReader<'a> {
|
||||
Some(String::from_utf8(buf).unwrap())
|
||||
}
|
||||
|
||||
pub fn read_string(&mut self) -> Option<String> {
|
||||
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()
|
||||
}
|
||||
|
@ -6,31 +6,42 @@ 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";
|
||||
|
||||
enum VncState {
|
||||
Handshake,
|
||||
Authentication,
|
||||
ClientInit, // auth done
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[repr(u8)]
|
||||
pub enum SecurityType {
|
||||
Unknown(u8),
|
||||
Invalid,
|
||||
None,
|
||||
VncAuth,
|
||||
AppleRdp,
|
||||
Invalid = 0,
|
||||
None = 1,
|
||||
VncAuth = 2,
|
||||
RA2 = 5,
|
||||
RA2ne = 6,
|
||||
Tight = 16,
|
||||
Ultra = 17,
|
||||
TLS = 18,
|
||||
VeNCrypt = 19,
|
||||
}
|
||||
|
||||
pub struct VncHandler {
|
||||
state: VncState,
|
||||
// output: Vec<u8>,
|
||||
challenge: [u8; 16],
|
||||
security_type: SecurityType,
|
||||
password: String,
|
||||
}
|
||||
|
||||
impl ProtocalImpl for VncHandler {
|
||||
fn new() -> Self {
|
||||
VncHandler {
|
||||
state: VncState::Handshake,
|
||||
// output: Vec::new(),
|
||||
challenge: [0u8; 16],
|
||||
security_type: SecurityType::Invalid,
|
||||
password: String::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,11 +58,19 @@ impl ProtocalImpl for VncHandler {
|
||||
}
|
||||
VncState::Authentication => {
|
||||
ConsoleService::log(&format!("{:?}", input));
|
||||
return ProtocalHandlerOutput::Ok;
|
||||
return self.start_authenticate(input);
|
||||
}
|
||||
_ => panic!("unsupported version"),
|
||||
}
|
||||
}
|
||||
|
||||
fn set_credential(&mut self, _username: &str, password: &str) -> ProtocalHandlerOutput {
|
||||
ConsoleService::log(&format!("{:?}", password));
|
||||
ConsoleService::log(&format!("{:?}", self.challenge));
|
||||
// since vnc do not require username, so we just ignore it
|
||||
self.password = password.to_string();
|
||||
self.continue_authenticate()
|
||||
}
|
||||
}
|
||||
|
||||
// private methods
|
||||
@ -59,17 +78,35 @@ impl VncHandler {
|
||||
fn handle_handshake(&self, rfbversion: &[u8]) -> Result<&'static [u8], &'static str> {
|
||||
match rfbversion {
|
||||
b"RFB 003.003\n" => Ok(VNC_RFB33),
|
||||
b"RFB 003.007\n" => Ok(VNC_RFB37),
|
||||
b"RFB 003.008\n" => Ok(VNC_RFB38),
|
||||
b"RFB 003.007\n" => Ok(VNC_RFB33),
|
||||
b"RFB 003.008\n" => Ok(VNC_RFB33),
|
||||
_ => Err(VNC_VER_UNSUPPORTED),
|
||||
}
|
||||
}
|
||||
fn handle_authenticate(&mut self, auth: &[u8]) -> Result<&'static [u8], &'static str> {
|
||||
match auth {
|
||||
b"NONE\n" => Ok(b"\x00"),
|
||||
b"VNCAUTH\n" => Ok(b"\x01"),
|
||||
b"APPLETALK\n" => Ok(b"\x02"),
|
||||
_ => Err(VNC_VER_UNSUPPORTED),
|
||||
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.state = VncState::ClientInit;
|
||||
self.client_initialisation()
|
||||
}
|
||||
Some(2) => {
|
||||
sr.extract_slice(16, &mut self.challenge);
|
||||
ProtocalHandlerOutput::RequirePassword
|
||||
}
|
||||
_ => ProtocalHandlerOutput::Err(VNC_FAILED.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
fn client_initialisation(&mut self) -> ProtocalHandlerOutput {
|
||||
ProtocalHandlerOutput::Ok
|
||||
}
|
||||
|
||||
fn continue_authenticate(&mut self) -> ProtocalHandlerOutput {
|
||||
ProtocalHandlerOutput::Ok
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user