simple privacy demo

Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
fufesou 2022-01-14 00:32:09 +08:00
parent 8f998771c9
commit a1c4b08535
3 changed files with 102 additions and 23 deletions

View File

@ -1013,11 +1013,10 @@ fn run_cmds(cmds: String, show: bool) -> ResultType<()> {
Ok(())
}
pub fn toggle_privacy_mode(v: bool) {
pub fn toggle_blank_screen(v: bool) {
let v = if v { TRUE } else { FALSE };
unsafe {
blank_screen(v);
BlockInput(v);
}
}

View File

@ -15,6 +15,7 @@ use hbb_common::{
tokio_util::codec::{BytesCodec, Framed},
};
use sha2::{Digest, Sha256};
use std::sync::mpsc::{sync_channel, Receiver, SyncSender};
pub type Sender = mpsc::UnboundedSender<(Instant, Arc<Message>)>;
@ -84,6 +85,14 @@ const MILLI1: Duration = Duration::from_millis(1);
const SEND_TIMEOUT_VIDEO: u64 = 12_000;
const SEND_TIMEOUT_OTHER: u64 = SEND_TIMEOUT_VIDEO * 10;
type SyncFunc = Box<dyn Send + FnMut()>;
enum BlankChannelMsg {
On,
Off,
Exit,
}
impl Connection {
pub async fn start(
addr: SocketAddr,
@ -157,6 +166,12 @@ impl Connection {
},
);
let (input_sender, input_receiver) = sync_channel(1);
let (blank_sender, blank_receiver) = sync_channel(1);
let _ = std::thread::spawn(move || Self::handle_input(input_receiver));
let blank_handler = std::thread::spawn(move || Self::handle_blank(blank_receiver));
loop {
tokio::select! {
biased; // video has higher priority
@ -232,7 +247,7 @@ impl Connection {
Ok(bytes) => {
last_recv_time = Instant::now();
if let Ok(msg_in) = Message::parse_from_bytes(&bytes) {
if !conn.on_message(msg_in).await {
if !conn.on_message(msg_in, input_sender.clone(), blank_sender.clone()).await {
break;
}
}
@ -297,6 +312,14 @@ impl Connection {
}
}
blank_sender.send(BlankChannelMsg::Exit).unwrap();
if let Err(e) = blank_handler.join() {
log::error!("Failed to join blank thread, {:?}", e);
};
crate::platform::block_input(false);
crate::platform::toggle_blank_screen(false);
video_service::notify_video_frame_feched(id, None);
super::video_service::update_test_latency(id, 0);
super::video_service::update_image_quality(id, None);
@ -305,6 +328,44 @@ impl Connection {
}
}
// TODO:
// 1. Send "Block Input" and "Privacy Mode" when connection established.
// 2. Ctrl + Alt + Del will break "Block Input"
fn handle_input(receiver: Receiver<SyncFunc>) {
loop {
match receiver.recv() {
Ok(mut f) => {
f();
}
_ => break,
}
}
}
fn handle_blank(receiver: Receiver<BlankChannelMsg>) {
let mut last_privacy = false;
loop {
match receiver.recv_timeout(std::time::Duration::from_millis(500)) {
Ok(v) => match v {
BlankChannelMsg::On => {
crate::platform::toggle_blank_screen(true);
last_privacy = true;
}
BlankChannelMsg::Off => {
crate::platform::toggle_blank_screen(false);
last_privacy = false;
}
_ => break,
},
_ => {
if last_privacy {
crate::platform::toggle_blank_screen(true);
}
}
}
}
}
async fn try_port_forward_loop(
&mut self,
rx_from_cm: &mut mpsc::UnboundedReceiver<Data>,
@ -536,10 +597,15 @@ impl Connection {
self.send(msg_out).await;
}
async fn on_message(&mut self, msg: Message) -> bool {
async fn on_message(
&mut self,
msg: Message,
input_sender: SyncSender<SyncFunc>,
blank_sender: SyncSender<BlankChannelMsg>,
) -> bool {
if let Some(message::Union::login_request(lr)) = msg.union {
if let Some(o) = lr.option.as_ref() {
self.update_option(o);
self.update_option(o, input_sender, blank_sender);
}
if self.authorized {
return true;
@ -654,7 +720,8 @@ impl Connection {
match msg.union {
Some(message::Union::mouse_event(me)) => {
if self.keyboard {
handle_mouse(&me, self.inner.id());
let conn_id = self.inner.id();
input_sender.send(Box::new(move || handle_mouse(&me, conn_id))).unwrap();
}
}
Some(message::Union::key_event(mut me)) => {
@ -669,17 +736,19 @@ impl Connection {
};
if is_press {
if let Some(key_event::Union::unicode(_)) = me.union {
handle_key(&me);
input_sender.send(Box::new(move || handle_key(&me))).unwrap();
} else if let Some(key_event::Union::seq(_)) = me.union {
handle_key(&me);
input_sender.send(Box::new(move || handle_key(&me))).unwrap();
} else {
me.down = true;
handle_key(&me);
me.down = false;
handle_key(&me);
input_sender.send(Box::new(move || {
me.down = true;
handle_key(&me);
me.down = false;
handle_key(&me);
})).unwrap();
}
} else {
handle_key(&me);
input_sender.send(Box::new(move || handle_key(&me))).unwrap();
}
}
}
@ -782,7 +851,7 @@ impl Connection {
self.send_to_cm(ipc::Data::ChatMessage { text: c.text });
}
Some(misc::Union::option(o)) => {
self.update_option(&o);
self.update_option(&o, input_sender, blank_sender);
}
Some(misc::Union::refresh_video(r)) => {
if r {
@ -797,7 +866,12 @@ impl Connection {
true
}
fn update_option(&mut self, o: &OptionMessage) {
fn update_option(
&mut self,
o: &OptionMessage,
input_sender: SyncSender<SyncFunc>,
blank_sender: SyncSender<BlankChannelMsg>,
) {
log::info!("Option update: {:?}", o);
if let Ok(q) = o.image_quality.enum_value() {
self.image_quality = q.value();
@ -857,15 +931,23 @@ impl Connection {
if let Ok(q) = o.privacy_mode.enum_value() {
if q != BoolOption::NotSet {
self.privacy_mode = q == BoolOption::Yes;
if self.privacy_mode && self.keyboard {
crate::platform::toggle_privacy_mode(true);
if self.keyboard {
if self.privacy_mode {
input_sender.send(Box::new(move||{crate::platform::block_input(true)})).unwrap();
blank_sender.send(BlankChannelMsg::On).unwrap();
} else {
input_sender.send(Box::new(move||{crate::platform::block_input(false)})).unwrap();
blank_sender.send(BlankChannelMsg::Off).unwrap();
}
}
}
}
if self.keyboard {
if let Ok(q) = o.block_input.enum_value() {
if q != BoolOption::NotSet {
crate::platform::block_input(q == BoolOption::Yes);
input_sender.send(Box::new(move || {
crate::platform::block_input(q == BoolOption::Yes)
})).unwrap();
}
}
}
@ -880,9 +962,6 @@ impl Connection {
crate::platform::lock_screen();
super::video_service::switch_to_primary();
}
if self.privacy_mode {
crate::platform::toggle_privacy_mode(false);
}
self.port_forward_socket.take();
}

View File

@ -130,7 +130,8 @@ class Header: Reactor.Component {
{audio_enabled ? <li #disable-audio .toggle-option><span>{svg_checkmark}</span>{translate('Mute')}</li> : ""}
{keyboard_enabled && clipboard_enabled ? <li #disable-clipboard .toggle-option><span>{svg_checkmark}</span>{translate('Disable clipboard')}</li> : ""}
{keyboard_enabled ? <li #lock-after-session-end .toggle-option><span>{svg_checkmark}</span>{translate('Lock after session end')}</li> : ""}
{false && pi.platform == "Windows" ? <li #privacy-mode .toggle-option><span>{svg_checkmark}</span>{translate('Privacy mode')}</li> : ""}
{pi.platform == "Windows" ? <li #block-input>Block user input </li> : ""}
{pi.platform == "Windows" ? <li #privacy-mode .toggle-option><span>{svg_checkmark}</span>{translate('Privacy mode')}</li> : ""}
</menu>
</popup>;
}
@ -144,7 +145,7 @@ class Header: Reactor.Component {
{keyboard_enabled && (pi.platform == "Linux" || pi.sas_enabled) ? <li #ctrl-alt-del>{translate('Insert')} Ctrl + Alt + Del</li> : ""}
<div .separator />
{keyboard_enabled ? <li #lock-screen>{translate('Insert Lock')}</li> : ""}
{false && pi.platform == "Windows" ? <li #block-input>Block user input </li> : ""}
{pi.platform == "Windows" ? <li #block-input>Block user input </li> : ""}
{handler.support_refresh() ? <li #refresh>{translate('Refresh')}</li> : ""}
</menu>
</popup>;