2022-01-15 16:31:21 +08:00
|
|
|
use super::{input_service::*, *};
|
2022-02-22 14:17:50 +08:00
|
|
|
#[cfg(windows)]
|
2022-02-24 14:40:33 +08:00
|
|
|
use crate::clipboard_file::*;
|
2022-05-12 17:35:25 +08:00
|
|
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
|
|
|
use crate::common::update_clipboard;
|
2022-06-23 17:42:30 +08:00
|
|
|
use crate::video_service;
|
2022-05-12 17:35:25 +08:00
|
|
|
#[cfg(any(target_os = "android", target_os = "ios"))]
|
2022-08-08 22:27:27 +08:00
|
|
|
use crate::{common::DEVICE_NAME, flutter::connection_manager::start_channel};
|
2022-05-13 14:46:37 +08:00
|
|
|
use crate::{ipc, VERSION};
|
2022-11-22 23:42:36 +08:00
|
|
|
use cidr_utils::cidr::IpCidr;
|
2021-03-29 15:59:14 +08:00
|
|
|
use hbb_common::{
|
|
|
|
config::Config,
|
|
|
|
fs,
|
2022-07-30 02:01:40 +08:00
|
|
|
fs::can_enable_overwrite_detection,
|
2021-06-25 19:42:51 +08:00
|
|
|
futures::{SinkExt, StreamExt},
|
2022-09-11 21:46:53 +08:00
|
|
|
get_time, get_version_number,
|
2022-01-17 16:53:17 +08:00
|
|
|
message_proto::{option_message::BoolOption, permission_info::Permission},
|
2022-11-21 15:29:00 +08:00
|
|
|
password_security::{self as password, ApproveMode},
|
|
|
|
sleep, timeout,
|
2021-03-29 15:59:14 +08:00
|
|
|
tokio::{
|
|
|
|
net::TcpStream,
|
|
|
|
sync::mpsc,
|
|
|
|
time::{self, Duration, Instant, Interval},
|
|
|
|
},
|
|
|
|
tokio_util::codec::{BytesCodec, Framed},
|
|
|
|
};
|
2022-05-12 17:35:25 +08:00
|
|
|
#[cfg(any(target_os = "android", target_os = "ios"))]
|
2022-06-01 21:14:02 +08:00
|
|
|
use scrap::android::call_main_service_mouse_input;
|
2022-12-20 10:22:28 +08:00
|
|
|
use serde::Deserialize;
|
2022-05-12 17:35:25 +08:00
|
|
|
use serde_json::{json, value::Value};
|
2021-03-29 15:59:14 +08:00
|
|
|
use sha2::{Digest, Sha256};
|
2022-07-25 19:35:15 +08:00
|
|
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
2022-11-13 18:11:13 +08:00
|
|
|
use std::sync::atomic::Ordering;
|
2022-11-15 16:49:55 +08:00
|
|
|
use std::sync::{atomic::AtomicI64, mpsc as std_mpsc};
|
2022-11-13 18:11:13 +08:00
|
|
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
2022-07-25 19:35:15 +08:00
|
|
|
use system_shutdown;
|
2021-03-29 15:59:14 +08:00
|
|
|
|
|
|
|
pub type Sender = mpsc::UnboundedSender<(Instant, Arc<Message>)>;
|
|
|
|
|
|
|
|
lazy_static::lazy_static! {
|
|
|
|
static ref LOGIN_FAILURES: Arc::<Mutex<HashMap<String, (i32, i32, i32)>>> = Default::default();
|
2022-07-18 14:03:52 +08:00
|
|
|
static ref SESSIONS: Arc::<Mutex<HashMap<String, Session>>> = Default::default();
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
2022-05-12 17:35:25 +08:00
|
|
|
pub static CLICK_TIME: AtomicI64 = AtomicI64::new(0);
|
|
|
|
pub static MOUSE_MOVE_TIME: AtomicI64 = AtomicI64::new(0);
|
2021-03-29 15:59:14 +08:00
|
|
|
|
|
|
|
#[derive(Clone, Default)]
|
|
|
|
pub struct ConnInner {
|
|
|
|
id: i32,
|
|
|
|
tx: Option<Sender>,
|
2021-12-20 15:10:51 +08:00
|
|
|
tx_video: Option<Sender>,
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
|
|
|
|
2022-01-15 16:31:21 +08:00
|
|
|
enum MessageInput {
|
2022-01-15 22:03:17 +08:00
|
|
|
Mouse((MouseEvent, i32)),
|
|
|
|
Key((KeyEvent, bool)),
|
2022-01-15 16:31:21 +08:00
|
|
|
BlockOn,
|
|
|
|
BlockOff,
|
|
|
|
}
|
|
|
|
|
2022-07-18 14:03:52 +08:00
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
struct Session {
|
|
|
|
name: String,
|
|
|
|
session_id: u64,
|
|
|
|
last_recv_time: Arc<Mutex<Instant>>,
|
|
|
|
random_password: String,
|
|
|
|
}
|
|
|
|
|
2021-03-29 15:59:14 +08:00
|
|
|
pub struct Connection {
|
|
|
|
inner: ConnInner,
|
|
|
|
stream: super::Stream,
|
|
|
|
server: super::ServerPtrWeak,
|
|
|
|
hash: Hash,
|
|
|
|
read_jobs: Vec<fs::TransferJob>,
|
|
|
|
timer: Interval,
|
2022-12-18 17:00:10 +08:00
|
|
|
file_timer: Interval,
|
|
|
|
http_timer: Interval,
|
2021-03-29 15:59:14 +08:00
|
|
|
file_transfer: Option<(String, bool)>,
|
|
|
|
port_forward_socket: Option<Framed<TcpStream, BytesCodec>>,
|
|
|
|
port_forward_address: String,
|
|
|
|
tx_to_cm: mpsc::UnboundedSender<ipc::Data>,
|
|
|
|
authorized: bool,
|
|
|
|
keyboard: bool,
|
|
|
|
clipboard: bool,
|
|
|
|
audio: bool,
|
2022-02-15 14:46:08 +08:00
|
|
|
file: bool,
|
2022-07-25 19:35:15 +08:00
|
|
|
restart: bool,
|
2022-09-22 09:55:34 +08:00
|
|
|
recording: bool,
|
2021-03-29 15:59:14 +08:00
|
|
|
last_test_delay: i64,
|
|
|
|
lock_after_session_end: bool,
|
|
|
|
show_remote_cursor: bool, // by peer
|
|
|
|
ip: String,
|
2022-01-30 21:37:46 +08:00
|
|
|
disable_clipboard: bool, // by peer
|
|
|
|
disable_audio: bool, // by peer
|
2022-02-15 14:46:08 +08:00
|
|
|
enable_file_transfer: bool, // by peer
|
2022-01-30 21:34:34 +08:00
|
|
|
tx_input: std_mpsc::Sender<MessageInput>, // handle input messages
|
2022-02-04 22:18:48 +08:00
|
|
|
video_ack_required: bool,
|
2022-05-12 17:35:25 +08:00
|
|
|
peer_info: (String, String),
|
2022-12-18 16:17:10 +08:00
|
|
|
server_audit_conn: String,
|
|
|
|
server_audit_file: String,
|
2022-07-18 14:03:52 +08:00
|
|
|
lr: LoginRequest,
|
|
|
|
last_recv_time: Arc<Mutex<Instant>>,
|
2022-10-08 20:15:02 +08:00
|
|
|
chat_unanswered: bool,
|
|
|
|
close_manually: bool,
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Subscriber for ConnInner {
|
|
|
|
#[inline]
|
|
|
|
fn id(&self) -> i32 {
|
|
|
|
self.id
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn send(&mut self, msg: Arc<Message>) {
|
2021-12-23 11:11:48 +08:00
|
|
|
match &msg.union {
|
2022-07-14 17:20:01 +08:00
|
|
|
Some(message::Union::VideoFrame(_)) => {
|
2021-12-23 11:11:48 +08:00
|
|
|
self.tx_video.as_mut().map(|tx| {
|
|
|
|
allow_err!(tx.send((Instant::now(), msg)));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
self.tx.as_mut().map(|tx| {
|
|
|
|
allow_err!(tx.send((Instant::now(), msg)));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
2021-12-20 15:10:51 +08:00
|
|
|
}
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
|
|
|
|
2022-06-23 17:42:30 +08:00
|
|
|
const TEST_DELAY_TIMEOUT: Duration = Duration::from_secs(1);
|
2021-03-29 15:59:14 +08:00
|
|
|
const SEC30: Duration = Duration::from_secs(30);
|
|
|
|
const H1: Duration = Duration::from_secs(3600);
|
|
|
|
const MILLI1: Duration = Duration::from_millis(1);
|
2021-12-24 19:13:11 +08:00
|
|
|
const SEND_TIMEOUT_VIDEO: u64 = 12_000;
|
|
|
|
const SEND_TIMEOUT_OTHER: u64 = SEND_TIMEOUT_VIDEO * 10;
|
2022-07-18 14:03:52 +08:00
|
|
|
const SESSION_TIMEOUT: Duration = Duration::from_secs(30);
|
2021-03-29 15:59:14 +08:00
|
|
|
|
|
|
|
impl Connection {
|
|
|
|
pub async fn start(
|
|
|
|
addr: SocketAddr,
|
|
|
|
stream: super::Stream,
|
|
|
|
id: i32,
|
|
|
|
server: super::ServerPtrWeak,
|
|
|
|
) {
|
|
|
|
let hash = Hash {
|
|
|
|
salt: Config::get_salt(),
|
2022-07-24 16:41:12 +08:00
|
|
|
challenge: Config::get_auto_password(6),
|
2021-03-29 15:59:14 +08:00
|
|
|
..Default::default()
|
|
|
|
};
|
2022-03-03 20:46:27 +08:00
|
|
|
let (tx_from_cm_holder, mut rx_from_cm) = mpsc::unbounded_channel::<ipc::Data>();
|
|
|
|
// holding tx_from_cm_holde to avoid cpu burning of rx_from_cm.recv when all sender closed
|
|
|
|
let tx_from_cm = tx_from_cm_holder.clone();
|
2021-03-29 15:59:14 +08:00
|
|
|
let (tx_to_cm, rx_to_cm) = mpsc::unbounded_channel::<ipc::Data>();
|
|
|
|
let (tx, mut rx) = mpsc::unbounded_channel::<(Instant, Arc<Message>)>();
|
2021-12-20 15:10:51 +08:00
|
|
|
let (tx_video, mut rx_video) = mpsc::unbounded_channel::<(Instant, Arc<Message>)>();
|
2022-01-30 21:34:34 +08:00
|
|
|
let (tx_input, rx_input) = std_mpsc::channel();
|
2022-01-15 16:31:21 +08:00
|
|
|
|
2022-01-15 21:33:20 +08:00
|
|
|
let tx_cloned = tx.clone();
|
2021-03-29 15:59:14 +08:00
|
|
|
let mut conn = Self {
|
2021-12-20 15:10:51 +08:00
|
|
|
inner: ConnInner {
|
|
|
|
id,
|
|
|
|
tx: Some(tx),
|
|
|
|
tx_video: Some(tx_video),
|
|
|
|
},
|
2021-03-29 15:59:14 +08:00
|
|
|
stream,
|
|
|
|
server,
|
|
|
|
hash,
|
|
|
|
read_jobs: Vec::new(),
|
|
|
|
timer: time::interval(SEC30),
|
2022-12-18 17:00:10 +08:00
|
|
|
file_timer: time::interval(SEC30),
|
|
|
|
http_timer: time::interval(Duration::from_secs(3)),
|
2021-03-29 15:59:14 +08:00
|
|
|
file_transfer: None,
|
|
|
|
port_forward_socket: None,
|
|
|
|
port_forward_address: "".to_owned(),
|
|
|
|
tx_to_cm,
|
|
|
|
authorized: false,
|
2022-10-17 14:35:44 +08:00
|
|
|
keyboard: Connection::permission("enable-keyboard"),
|
|
|
|
clipboard: Connection::permission("enable-clipboard"),
|
|
|
|
audio: Connection::permission("enable-audio"),
|
|
|
|
file: Connection::permission("enable-file-transfer"),
|
|
|
|
restart: Connection::permission("enable-remote-restart"),
|
|
|
|
recording: Connection::permission("enable-record-session"),
|
2021-03-29 15:59:14 +08:00
|
|
|
last_test_delay: 0,
|
|
|
|
lock_after_session_end: false,
|
|
|
|
show_remote_cursor: false,
|
|
|
|
ip: "".to_owned(),
|
|
|
|
disable_audio: false,
|
2022-02-15 14:46:08 +08:00
|
|
|
enable_file_transfer: false,
|
2021-03-29 15:59:14 +08:00
|
|
|
disable_clipboard: false,
|
2022-01-15 16:31:21 +08:00
|
|
|
tx_input,
|
2022-02-04 22:18:48 +08:00
|
|
|
video_ack_required: false,
|
2022-05-12 17:35:25 +08:00
|
|
|
peer_info: Default::default(),
|
2022-12-18 16:17:10 +08:00
|
|
|
server_audit_conn: "".to_owned(),
|
|
|
|
server_audit_file: "".to_owned(),
|
2022-07-18 14:03:52 +08:00
|
|
|
lr: Default::default(),
|
|
|
|
last_recv_time: Arc::new(Mutex::new(Instant::now())),
|
2022-10-08 20:15:02 +08:00
|
|
|
chat_unanswered: false,
|
|
|
|
close_manually: false,
|
2021-03-29 15:59:14 +08:00
|
|
|
};
|
2022-05-12 17:35:25 +08:00
|
|
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
2021-03-29 15:59:14 +08:00
|
|
|
tokio::spawn(async move {
|
|
|
|
if let Err(err) = start_ipc(rx_to_cm, tx_from_cm).await {
|
|
|
|
log::error!("ipc to connection manager exit: {}", err);
|
|
|
|
}
|
|
|
|
});
|
2022-05-12 17:35:25 +08:00
|
|
|
#[cfg(target_os = "android")]
|
|
|
|
start_channel(rx_to_cm, tx_from_cm);
|
|
|
|
|
2021-03-29 15:59:14 +08:00
|
|
|
if !conn.on_open(addr).await {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if !conn.keyboard {
|
2021-11-14 23:31:34 +08:00
|
|
|
conn.send_permission(Permission::Keyboard, false).await;
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
|
|
|
if !conn.clipboard {
|
2021-11-14 23:31:34 +08:00
|
|
|
conn.send_permission(Permission::Clipboard, false).await;
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
|
|
|
if !conn.audio {
|
2021-11-14 23:31:34 +08:00
|
|
|
conn.send_permission(Permission::Audio, false).await;
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
2022-02-15 14:46:08 +08:00
|
|
|
if !conn.file {
|
|
|
|
conn.send_permission(Permission::File, false).await;
|
|
|
|
}
|
2022-07-25 19:35:15 +08:00
|
|
|
if !conn.restart {
|
|
|
|
conn.send_permission(Permission::Restart, false).await;
|
|
|
|
}
|
2022-09-22 09:55:34 +08:00
|
|
|
if !conn.recording {
|
|
|
|
conn.send_permission(Permission::Recording, false).await;
|
|
|
|
}
|
2021-03-29 15:59:14 +08:00
|
|
|
let mut test_delay_timer =
|
|
|
|
time::interval_at(Instant::now() + TEST_DELAY_TIMEOUT, TEST_DELAY_TIMEOUT);
|
|
|
|
let mut last_recv_time = Instant::now();
|
2021-12-20 15:10:51 +08:00
|
|
|
|
2021-12-24 19:13:11 +08:00
|
|
|
conn.stream.set_send_timeout(
|
|
|
|
if conn.file_transfer.is_some() || conn.port_forward_socket.is_some() {
|
|
|
|
SEND_TIMEOUT_OTHER
|
|
|
|
} else {
|
|
|
|
SEND_TIMEOUT_VIDEO
|
|
|
|
},
|
|
|
|
);
|
|
|
|
|
2022-05-12 17:35:25 +08:00
|
|
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
2022-02-12 11:50:39 +08:00
|
|
|
std::thread::spawn(move || Self::handle_input(rx_input, tx_cloned));
|
2022-09-27 13:30:49 +08:00
|
|
|
let mut second_timer = time::interval(Duration::from_secs(1));
|
2022-11-10 10:27:13 +08:00
|
|
|
#[cfg(windows)]
|
2022-09-28 20:48:14 +08:00
|
|
|
let mut last_uac = false;
|
2022-11-10 10:27:13 +08:00
|
|
|
#[cfg(windows)]
|
2022-09-28 20:48:14 +08:00
|
|
|
let mut last_foreground_window_elevated = false;
|
2022-11-10 10:27:13 +08:00
|
|
|
#[cfg(windows)]
|
|
|
|
let is_installed = crate::platform::is_installed();
|
2022-01-14 00:32:09 +08:00
|
|
|
|
2021-03-29 15:59:14 +08:00
|
|
|
loop {
|
|
|
|
tokio::select! {
|
2022-12-26 01:21:13 +08:00
|
|
|
// biased; // video has higher priority // causing test_delay_timer failed while transferring big file
|
2021-12-20 15:10:51 +08:00
|
|
|
|
2021-03-29 15:59:14 +08:00
|
|
|
Some(data) = rx_from_cm.recv() => {
|
|
|
|
match data {
|
|
|
|
ipc::Data::Authorize => {
|
|
|
|
conn.send_logon_response().await;
|
|
|
|
if conn.port_forward_socket.is_some() {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ipc::Data::Close => {
|
2022-12-20 10:22:28 +08:00
|
|
|
conn.on_close_manually("connection manager", "peer").await;
|
2021-03-29 15:59:14 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
ipc::Data::ChatMessage{text} => {
|
|
|
|
let mut misc = Misc::new();
|
|
|
|
misc.set_chat_message(ChatMessage {
|
|
|
|
text,
|
|
|
|
..Default::default()
|
|
|
|
});
|
|
|
|
let mut msg_out = Message::new();
|
|
|
|
msg_out.set_misc(misc);
|
|
|
|
conn.send(msg_out).await;
|
2022-10-08 20:15:02 +08:00
|
|
|
conn.chat_unanswered = false;
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
|
|
|
ipc::Data::SwitchPermission{name, enabled} => {
|
|
|
|
log::info!("Change permission {} -> {}", name, enabled);
|
|
|
|
if &name == "keyboard" {
|
|
|
|
conn.keyboard = enabled;
|
2021-11-14 23:31:34 +08:00
|
|
|
conn.send_permission(Permission::Keyboard, enabled).await;
|
2021-03-29 15:59:14 +08:00
|
|
|
if let Some(s) = conn.server.upgrade() {
|
|
|
|
s.write().unwrap().subscribe(
|
|
|
|
NAME_CURSOR,
|
|
|
|
conn.inner.clone(), enabled || conn.show_remote_cursor);
|
|
|
|
}
|
|
|
|
} else if &name == "clipboard" {
|
|
|
|
conn.clipboard = enabled;
|
2021-11-14 23:31:34 +08:00
|
|
|
conn.send_permission(Permission::Clipboard, enabled).await;
|
2021-03-29 15:59:14 +08:00
|
|
|
if let Some(s) = conn.server.upgrade() {
|
|
|
|
s.write().unwrap().subscribe(
|
|
|
|
super::clipboard_service::NAME,
|
|
|
|
conn.inner.clone(), conn.clipboard_enabled() && conn.keyboard);
|
|
|
|
}
|
|
|
|
} else if &name == "audio" {
|
|
|
|
conn.audio = enabled;
|
2021-11-14 23:31:34 +08:00
|
|
|
conn.send_permission(Permission::Audio, enabled).await;
|
2021-03-29 15:59:14 +08:00
|
|
|
if let Some(s) = conn.server.upgrade() {
|
|
|
|
s.write().unwrap().subscribe(
|
|
|
|
super::audio_service::NAME,
|
|
|
|
conn.inner.clone(), conn.audio_enabled());
|
|
|
|
}
|
2022-02-15 14:46:08 +08:00
|
|
|
} else if &name == "file" {
|
|
|
|
conn.file = enabled;
|
|
|
|
conn.send_permission(Permission::File, enabled).await;
|
2022-02-22 22:26:22 +08:00
|
|
|
conn.send_to_cm(ipc::Data::ClipboardFileEnabled(conn.file_transfer_enabled()));
|
2022-07-25 19:35:15 +08:00
|
|
|
} else if &name == "restart" {
|
|
|
|
conn.restart = enabled;
|
|
|
|
conn.send_permission(Permission::Restart, enabled).await;
|
2022-09-22 09:55:34 +08:00
|
|
|
} else if &name == "recording" {
|
|
|
|
conn.recording = enabled;
|
|
|
|
conn.send_permission(Permission::Recording, enabled).await;
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
ipc::Data::RawMessage(bytes) => {
|
2022-04-29 00:42:06 +08:00
|
|
|
allow_err!(conn.stream.send_raw(bytes).await);
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
2022-05-12 17:35:25 +08:00
|
|
|
#[cfg(windows)]
|
2022-02-22 14:17:50 +08:00
|
|
|
ipc::Data::ClipbaordFile(_clip) => {
|
|
|
|
if conn.file_transfer_enabled() {
|
|
|
|
allow_err!(conn.stream.send(&clip_2_msg(_clip)).await);
|
|
|
|
}
|
|
|
|
}
|
2022-04-25 12:28:28 +08:00
|
|
|
ipc::Data::PrivacyModeState((_, state)) => {
|
|
|
|
let msg_out = match state {
|
|
|
|
ipc::PrivacyModeState::OffSucceeded => {
|
|
|
|
video_service::set_privacy_mode_conn_id(0);
|
|
|
|
crate::common::make_privacy_mode_msg(
|
2022-07-31 22:31:17 +08:00
|
|
|
back_notification::PrivacyModeState::PrvOffSucceeded,
|
2022-04-25 12:28:28 +08:00
|
|
|
)
|
|
|
|
}
|
|
|
|
ipc::PrivacyModeState::OffFailed => {
|
|
|
|
crate::common::make_privacy_mode_msg(
|
2022-07-31 22:31:17 +08:00
|
|
|
back_notification::PrivacyModeState::PrvOffFailed,
|
2022-04-25 12:28:28 +08:00
|
|
|
)
|
|
|
|
}
|
|
|
|
ipc::PrivacyModeState::OffByPeer => {
|
|
|
|
video_service::set_privacy_mode_conn_id(0);
|
|
|
|
crate::common::make_privacy_mode_msg(
|
2022-07-31 22:31:17 +08:00
|
|
|
back_notification::PrivacyModeState::PrvOffByPeer,
|
2022-04-25 12:28:28 +08:00
|
|
|
)
|
|
|
|
}
|
|
|
|
ipc::PrivacyModeState::OffUnknown => {
|
|
|
|
video_service::set_privacy_mode_conn_id(0);
|
|
|
|
crate::common::make_privacy_mode_msg(
|
2022-07-31 22:31:17 +08:00
|
|
|
back_notification::PrivacyModeState::PrvOffUnknown,
|
2022-04-25 12:28:28 +08:00
|
|
|
)
|
|
|
|
}
|
|
|
|
};
|
|
|
|
conn.send(msg_out).await;
|
|
|
|
}
|
2022-11-10 10:27:13 +08:00
|
|
|
#[cfg(windows)]
|
|
|
|
ipc::Data::DataPortableService(ipc::DataPortableService::RequestStart) => {
|
|
|
|
if let Err(e) = crate::portable_service::client::start_portable_service() {
|
|
|
|
log::error!("Failed to start portable service from cm:{:?}", e);
|
|
|
|
}
|
|
|
|
}
|
2021-03-29 15:59:14 +08:00
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
res = conn.stream.next() => {
|
|
|
|
if let Some(res) = res {
|
|
|
|
match res {
|
|
|
|
Err(err) => {
|
2022-07-07 01:27:21 +08:00
|
|
|
conn.on_close(&err.to_string(), true).await;
|
2021-03-29 15:59:14 +08:00
|
|
|
break;
|
|
|
|
},
|
|
|
|
Ok(bytes) => {
|
|
|
|
last_recv_time = Instant::now();
|
2022-07-18 14:03:52 +08:00
|
|
|
*conn.last_recv_time.lock().unwrap() = Instant::now();
|
2021-03-29 15:59:14 +08:00
|
|
|
if let Ok(msg_in) = Message::parse_from_bytes(&bytes) {
|
2022-01-15 16:31:21 +08:00
|
|
|
if !conn.on_message(msg_in).await {
|
2021-03-29 15:59:14 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2022-07-07 01:27:21 +08:00
|
|
|
conn.on_close("Reset by the peer", true).await;
|
2021-03-29 15:59:14 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
},
|
2022-12-18 17:00:10 +08:00
|
|
|
_ = conn.file_timer.tick() => {
|
2021-03-29 15:59:14 +08:00
|
|
|
if !conn.read_jobs.is_empty() {
|
|
|
|
if let Err(err) = fs::handle_read_jobs(&mut conn.read_jobs, &mut conn.stream).await {
|
2022-07-07 01:27:21 +08:00
|
|
|
conn.on_close(&err.to_string(), false).await;
|
2021-03-29 15:59:14 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
2022-12-18 17:00:10 +08:00
|
|
|
conn.file_timer = time::interval_at(Instant::now() + SEC30, SEC30);
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
2022-12-18 17:00:10 +08:00
|
|
|
}
|
|
|
|
_ = conn.http_timer.tick() => {
|
2022-12-20 10:22:28 +08:00
|
|
|
if let Err(_) = Connection::post_heartbeat(conn.server_audit_conn.clone(), conn.inner.id).await {
|
|
|
|
conn.on_close_manually("web console", "web console").await;
|
|
|
|
break;
|
|
|
|
}
|
2021-12-20 15:10:51 +08:00
|
|
|
},
|
|
|
|
Some((instant, value)) = rx_video.recv() => {
|
2022-02-04 22:18:48 +08:00
|
|
|
if !conn.video_ack_required {
|
|
|
|
video_service::notify_video_frame_feched(id, Some(instant.into()));
|
|
|
|
}
|
2021-12-20 15:10:51 +08:00
|
|
|
if let Err(err) = conn.stream.send(&value as &Message).await {
|
2022-07-07 01:27:21 +08:00
|
|
|
conn.on_close(&err.to_string(), false).await;
|
2021-12-20 15:10:51 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
Some((instant, value)) = rx.recv() => {
|
|
|
|
let latency = instant.elapsed().as_millis() as i64;
|
|
|
|
let msg: &Message = &value;
|
|
|
|
|
|
|
|
if latency > 1000 {
|
|
|
|
match &msg.union {
|
2022-07-14 17:20:01 +08:00
|
|
|
Some(message::Union::AudioFrame(_)) => {
|
2021-12-21 00:11:12 +08:00
|
|
|
// log::info!("audio frame latency {}", instant.elapsed().as_secs_f32());
|
2021-12-20 15:10:51 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
2022-11-09 17:28:47 +08:00
|
|
|
match &msg.union {
|
|
|
|
Some(message::Union::Misc(m)) => {
|
|
|
|
match &m.union {
|
|
|
|
Some(misc::Union::StopService(_)) => {
|
2022-12-20 10:22:28 +08:00
|
|
|
conn.on_close_manually("stop service", "peer").await;
|
2022-11-09 17:28:47 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
_ => {},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
2021-12-20 15:10:51 +08:00
|
|
|
if let Err(err) = conn.stream.send(msg).await {
|
2022-07-07 01:27:21 +08:00
|
|
|
conn.on_close(&err.to_string(), false).await;
|
2021-12-20 15:10:51 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
},
|
2022-09-27 13:30:49 +08:00
|
|
|
_ = second_timer.tick() => {
|
2022-11-10 10:27:13 +08:00
|
|
|
#[cfg(windows)]
|
|
|
|
{
|
2022-11-11 11:40:23 +08:00
|
|
|
if !is_installed {
|
|
|
|
let portable_service_running = crate::portable_service::client::PORTABLE_SERVICE_RUNNING.lock().unwrap().clone();
|
|
|
|
let uac = crate::video_service::IS_UAC_RUNNING.lock().unwrap().clone();
|
|
|
|
if last_uac != uac {
|
|
|
|
last_uac = uac;
|
2022-11-15 16:49:55 +08:00
|
|
|
if !uac || !portable_service_running{
|
2022-11-11 11:40:23 +08:00
|
|
|
let mut misc = Misc::new();
|
|
|
|
misc.set_uac(uac);
|
|
|
|
let mut msg = Message::new();
|
|
|
|
msg.set_misc(misc);
|
|
|
|
conn.inner.send(msg.into());
|
|
|
|
}
|
2022-11-10 10:27:13 +08:00
|
|
|
}
|
2022-11-11 11:40:23 +08:00
|
|
|
let foreground_window_elevated = crate::video_service::IS_FOREGROUND_WINDOW_ELEVATED.lock().unwrap().clone();
|
|
|
|
if last_foreground_window_elevated != foreground_window_elevated {
|
|
|
|
last_foreground_window_elevated = foreground_window_elevated;
|
2022-11-15 16:49:55 +08:00
|
|
|
if !foreground_window_elevated || !portable_service_running {
|
2022-11-11 11:40:23 +08:00
|
|
|
let mut misc = Misc::new();
|
|
|
|
misc.set_foreground_window_elevated(foreground_window_elevated);
|
|
|
|
let mut msg = Message::new();
|
|
|
|
msg.set_misc(misc);
|
|
|
|
conn.inner.send(msg.into());
|
|
|
|
}
|
2022-11-10 10:27:13 +08:00
|
|
|
}
|
2022-11-11 11:40:23 +08:00
|
|
|
let show_elevation = !portable_service_running;
|
2022-11-10 10:27:13 +08:00
|
|
|
conn.send_to_cm(ipc::Data::DataPortableService(ipc::DataPortableService::CmShowElevation(show_elevation)));
|
|
|
|
|
|
|
|
}
|
2022-09-27 13:30:49 +08:00
|
|
|
}
|
|
|
|
}
|
2021-03-29 15:59:14 +08:00
|
|
|
_ = test_delay_timer.tick() => {
|
|
|
|
if last_recv_time.elapsed() >= SEC30 {
|
2022-07-07 01:27:21 +08:00
|
|
|
conn.on_close("Timeout", true).await;
|
2021-03-29 15:59:14 +08:00
|
|
|
break;
|
|
|
|
}
|
2022-09-11 21:46:53 +08:00
|
|
|
let time = get_time();
|
2021-03-29 15:59:14 +08:00
|
|
|
if time > 0 && conn.last_test_delay == 0 {
|
|
|
|
conn.last_test_delay = time;
|
|
|
|
let mut msg_out = Message::new();
|
2022-06-23 17:42:30 +08:00
|
|
|
let qos = video_service::VIDEO_QOS.lock().unwrap();
|
2021-03-29 15:59:14 +08:00
|
|
|
msg_out.set_test_delay(TestDelay{
|
|
|
|
time,
|
2022-06-23 17:42:30 +08:00
|
|
|
last_delay:qos.current_delay,
|
|
|
|
target_bitrate:qos.target_bitrate,
|
2021-03-29 15:59:14 +08:00
|
|
|
..Default::default()
|
|
|
|
});
|
|
|
|
conn.inner.send(msg_out.into());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-12-20 15:10:51 +08:00
|
|
|
|
2022-05-31 15:54:21 +08:00
|
|
|
let video_privacy_conn_id = video_service::get_privacy_mode_conn_id();
|
|
|
|
if video_privacy_conn_id == id {
|
2022-04-25 12:28:28 +08:00
|
|
|
video_service::set_privacy_mode_conn_id(0);
|
2022-05-31 15:54:21 +08:00
|
|
|
let _ = privacy_mode::turn_off_privacy(id);
|
|
|
|
} else if video_privacy_conn_id == 0 {
|
|
|
|
let _ = privacy_mode::turn_off_privacy(0);
|
2022-04-25 12:28:28 +08:00
|
|
|
}
|
2022-01-15 21:33:20 +08:00
|
|
|
video_service::notify_video_frame_feched(id, None);
|
2022-06-01 18:40:28 +08:00
|
|
|
scrap::codec::Encoder::update_video_encoder(id, scrap::codec::EncoderUpdate::Remove);
|
2022-06-23 17:42:30 +08:00
|
|
|
video_service::VIDEO_QOS.lock().unwrap().reset();
|
2022-07-24 16:41:12 +08:00
|
|
|
if conn.authorized {
|
|
|
|
password::update_temporary_password();
|
|
|
|
}
|
2022-01-15 21:33:20 +08:00
|
|
|
if let Err(err) = conn.try_port_forward_loop(&mut rx_from_cm).await {
|
2022-07-07 01:27:21 +08:00
|
|
|
conn.on_close(&err.to_string(), false).await;
|
2022-01-15 21:33:20 +08:00
|
|
|
}
|
|
|
|
|
2022-12-18 16:17:10 +08:00
|
|
|
conn.post_conn_audit(json!({
|
2022-05-12 17:35:25 +08:00
|
|
|
"action": "close",
|
|
|
|
}));
|
2022-02-09 16:06:44 +08:00
|
|
|
log::info!("#{} connection loop exited", id);
|
2021-12-24 19:13:11 +08:00
|
|
|
}
|
|
|
|
|
2022-05-12 17:35:25 +08:00
|
|
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
2022-01-30 21:34:34 +08:00
|
|
|
fn handle_input(receiver: std_mpsc::Receiver<MessageInput>, tx: Sender) {
|
2022-01-15 16:31:21 +08:00
|
|
|
let mut block_input_mode = false;
|
2022-12-03 21:23:19 +08:00
|
|
|
#[cfg(target_os = "windows")]
|
|
|
|
{
|
|
|
|
rdev::set_dw_mouse_extra_info(enigo::ENIGO_INPUT_EXTRA_VALUE);
|
|
|
|
rdev::set_dw_keyboard_extra_info(enigo::ENIGO_INPUT_EXTRA_VALUE);
|
|
|
|
}
|
2022-01-14 00:32:09 +08:00
|
|
|
loop {
|
2022-01-15 16:31:21 +08:00
|
|
|
match receiver.recv_timeout(std::time::Duration::from_millis(500)) {
|
|
|
|
Ok(v) => match v {
|
2022-01-15 22:03:17 +08:00
|
|
|
MessageInput::Mouse((msg, id)) => {
|
|
|
|
handle_mouse(&msg, id);
|
|
|
|
}
|
|
|
|
MessageInput::Key((mut msg, press)) => {
|
2022-07-18 11:34:08 +08:00
|
|
|
// todo: press and down have similar meanings.
|
2022-07-19 15:43:13 +08:00
|
|
|
if press && msg.mode.unwrap() == KeyboardMode::Legacy {
|
2022-07-18 11:59:14 +08:00
|
|
|
msg.down = true;
|
|
|
|
}
|
2022-01-15 22:03:17 +08:00
|
|
|
handle_key(&msg);
|
2022-07-19 15:43:13 +08:00
|
|
|
if press && msg.mode.unwrap() == KeyboardMode::Legacy {
|
2022-07-18 11:59:14 +08:00
|
|
|
msg.down = false;
|
|
|
|
handle_key(&msg);
|
|
|
|
}
|
2022-01-15 16:31:21 +08:00
|
|
|
}
|
|
|
|
MessageInput::BlockOn => {
|
|
|
|
if crate::platform::block_input(true) {
|
|
|
|
block_input_mode = true;
|
|
|
|
} else {
|
2022-04-25 12:28:28 +08:00
|
|
|
Self::send_block_input_error(
|
|
|
|
&tx,
|
2022-07-31 22:31:17 +08:00
|
|
|
back_notification::BlockInputState::BlkOnFailed,
|
2022-04-25 12:28:28 +08:00
|
|
|
);
|
2022-01-15 16:31:21 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
MessageInput::BlockOff => {
|
|
|
|
if crate::platform::block_input(false) {
|
|
|
|
block_input_mode = false;
|
|
|
|
} else {
|
2022-04-25 12:28:28 +08:00
|
|
|
Self::send_block_input_error(
|
|
|
|
&tx,
|
2022-07-31 22:31:17 +08:00
|
|
|
back_notification::BlockInputState::BlkOffFailed,
|
2022-04-25 12:28:28 +08:00
|
|
|
);
|
2022-01-15 16:31:21 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
2022-03-07 22:26:34 +08:00
|
|
|
Err(err) => {
|
2022-05-12 17:35:25 +08:00
|
|
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
2022-01-15 16:31:21 +08:00
|
|
|
if block_input_mode {
|
|
|
|
let _ = crate::platform::block_input(true);
|
|
|
|
}
|
2022-03-07 22:26:34 +08:00
|
|
|
if std_mpsc::RecvTimeoutError::Disconnected == err {
|
|
|
|
break;
|
|
|
|
}
|
2022-01-14 00:32:09 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-02-11 14:39:41 +08:00
|
|
|
log::info!("Input thread exited");
|
2022-01-14 00:32:09 +08:00
|
|
|
}
|
|
|
|
|
2021-12-24 19:13:11 +08:00
|
|
|
async fn try_port_forward_loop(
|
|
|
|
&mut self,
|
|
|
|
rx_from_cm: &mut mpsc::UnboundedReceiver<Data>,
|
|
|
|
) -> ResultType<()> {
|
|
|
|
let mut last_recv_time = Instant::now();
|
2022-05-12 17:35:25 +08:00
|
|
|
if let Some(mut forward) = self.port_forward_socket.take() {
|
2021-03-29 15:59:14 +08:00
|
|
|
log::info!("Running port forwarding loop");
|
2021-12-24 19:13:11 +08:00
|
|
|
self.stream.set_raw();
|
2021-03-29 15:59:14 +08:00
|
|
|
loop {
|
|
|
|
tokio::select! {
|
|
|
|
Some(data) = rx_from_cm.recv() => {
|
|
|
|
match data {
|
|
|
|
ipc::Data::Close => {
|
2021-12-24 19:13:11 +08:00
|
|
|
bail!("Close requested from selfection manager");
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
res = forward.next() => {
|
|
|
|
if let Some(res) = res {
|
2021-12-24 19:13:11 +08:00
|
|
|
last_recv_time = Instant::now();
|
|
|
|
self.stream.send_bytes(res?.into()).await?;
|
2021-03-29 15:59:14 +08:00
|
|
|
} else {
|
2021-12-24 19:13:11 +08:00
|
|
|
bail!("Forward reset by the peer");
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
|
|
|
},
|
2021-12-24 19:13:11 +08:00
|
|
|
res = self.stream.next() => {
|
2021-03-29 15:59:14 +08:00
|
|
|
if let Some(res) = res {
|
2021-12-24 19:13:11 +08:00
|
|
|
last_recv_time = Instant::now();
|
2022-07-15 01:29:52 +08:00
|
|
|
timeout(SEND_TIMEOUT_OTHER, forward.send(res?)).await??;
|
2021-03-29 15:59:14 +08:00
|
|
|
} else {
|
2021-12-24 19:13:11 +08:00
|
|
|
bail!("Stream reset by the peer");
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
|
|
|
},
|
2021-12-24 19:13:11 +08:00
|
|
|
_ = self.timer.tick() => {
|
2021-03-29 15:59:14 +08:00
|
|
|
if last_recv_time.elapsed() >= H1 {
|
2021-12-24 19:13:11 +08:00
|
|
|
bail!("Timeout");
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
2022-12-20 10:22:28 +08:00
|
|
|
Connection::post_heartbeat(self.server_audit_conn.clone(), self.inner.id).await?;
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-12-24 19:13:11 +08:00
|
|
|
Ok(())
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
|
|
|
|
2021-11-14 23:31:34 +08:00
|
|
|
async fn send_permission(&mut self, permission: Permission, enabled: bool) {
|
2021-03-29 15:59:14 +08:00
|
|
|
let mut misc = Misc::new();
|
|
|
|
misc.set_permission_info(PermissionInfo {
|
|
|
|
permission: permission.into(),
|
|
|
|
enabled,
|
|
|
|
..Default::default()
|
|
|
|
});
|
|
|
|
let mut msg_out = Message::new();
|
|
|
|
msg_out.set_misc(misc);
|
|
|
|
self.send(msg_out).await;
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn on_open(&mut self, addr: SocketAddr) -> bool {
|
|
|
|
log::debug!("#{} Connection opened from {}.", self.inner.id, addr);
|
|
|
|
let whitelist: Vec<String> = Config::get_option("whitelist")
|
|
|
|
.split(",")
|
|
|
|
.filter(|x| !x.is_empty())
|
|
|
|
.map(|x| x.to_owned())
|
|
|
|
.collect();
|
|
|
|
if !whitelist.is_empty()
|
|
|
|
&& whitelist
|
|
|
|
.iter()
|
|
|
|
.filter(|x| x == &"0.0.0.0")
|
|
|
|
.next()
|
|
|
|
.is_none()
|
|
|
|
&& whitelist
|
|
|
|
.iter()
|
2022-11-23 01:09:49 +08:00
|
|
|
.filter(|x| IpCidr::from_str(x).map_or(false, |y| y.contains(addr.ip())))
|
2021-03-29 15:59:14 +08:00
|
|
|
.next()
|
|
|
|
.is_none()
|
|
|
|
{
|
|
|
|
self.send_login_error("Your ip is blocked by the peer")
|
|
|
|
.await;
|
2022-12-20 16:20:42 +08:00
|
|
|
Self::post_alarm_audit(
|
|
|
|
AlarmAuditType::IpWhiltelist, //"ip whiltelist",
|
|
|
|
true,
|
|
|
|
json!({
|
|
|
|
"ip":addr.ip(),
|
|
|
|
}),
|
|
|
|
);
|
2021-03-29 15:59:14 +08:00
|
|
|
sleep(1.).await;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
self.ip = addr.ip().to_string();
|
|
|
|
let mut msg_out = Message::new();
|
|
|
|
msg_out.set_hash(self.hash.clone());
|
|
|
|
self.send(msg_out).await;
|
2022-05-12 17:35:25 +08:00
|
|
|
self.get_api_server();
|
2022-12-18 16:17:10 +08:00
|
|
|
self.post_conn_audit(json!({
|
2022-05-12 17:35:25 +08:00
|
|
|
"ip": addr.ip(),
|
|
|
|
"action": "new",
|
|
|
|
}));
|
2021-03-29 15:59:14 +08:00
|
|
|
true
|
|
|
|
}
|
|
|
|
|
2022-05-12 17:35:25 +08:00
|
|
|
fn get_api_server(&mut self) {
|
2022-12-18 16:17:10 +08:00
|
|
|
self.server_audit_conn = crate::get_audit_server(
|
2022-05-12 17:35:25 +08:00
|
|
|
Config::get_option("api-server"),
|
|
|
|
Config::get_option("custom-rendezvous-server"),
|
2022-12-18 16:17:10 +08:00
|
|
|
"conn".to_owned(),
|
|
|
|
);
|
|
|
|
self.server_audit_file = crate::get_audit_server(
|
|
|
|
Config::get_option("api-server"),
|
|
|
|
Config::get_option("custom-rendezvous-server"),
|
|
|
|
"file".to_owned(),
|
2022-05-12 17:35:25 +08:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-12-18 16:17:10 +08:00
|
|
|
fn post_conn_audit(&self, v: Value) {
|
|
|
|
if self.server_audit_conn.is_empty() {
|
2022-05-12 17:35:25 +08:00
|
|
|
return;
|
|
|
|
}
|
2022-12-18 16:17:10 +08:00
|
|
|
let url = self.server_audit_conn.clone();
|
2022-05-12 17:35:25 +08:00
|
|
|
let mut v = v;
|
|
|
|
v["id"] = json!(Config::get_id());
|
2022-06-20 10:41:46 +08:00
|
|
|
v["uuid"] = json!(base64::encode(hbb_common::get_uuid()));
|
2022-12-23 10:36:18 +08:00
|
|
|
v["conn_id"] = json!(self.inner.id);
|
2022-05-12 17:35:25 +08:00
|
|
|
tokio::spawn(async move {
|
|
|
|
allow_err!(Self::post_audit_async(url, v).await);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-12-20 10:22:28 +08:00
|
|
|
async fn post_heartbeat(server_audit_conn: String, conn_id: i32) -> ResultType<()> {
|
|
|
|
if server_audit_conn.is_empty() {
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
let url = server_audit_conn.clone();
|
|
|
|
let mut v = Value::default();
|
|
|
|
v["id"] = json!(Config::get_id());
|
|
|
|
v["uuid"] = json!(base64::encode(hbb_common::get_uuid()));
|
2022-12-23 10:36:18 +08:00
|
|
|
v["conn_id"] = json!(conn_id);
|
2022-12-20 10:22:28 +08:00
|
|
|
if let Ok(rsp) = Self::post_audit_async(url, v).await {
|
|
|
|
if let Ok(rsp) = serde_json::from_str::<ConnAuditResponse>(&rsp) {
|
|
|
|
if rsp.action == "disconnect" {
|
|
|
|
bail!("disconnect by server");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
|
2022-12-23 10:36:18 +08:00
|
|
|
fn post_file_audit(
|
|
|
|
&self,
|
|
|
|
r#type: FileAuditType,
|
|
|
|
path: &str,
|
|
|
|
files: Vec<(String, i64)>,
|
|
|
|
info: Value,
|
|
|
|
) {
|
2022-12-18 16:17:10 +08:00
|
|
|
if self.server_audit_file.is_empty() {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
let url = self.server_audit_file.clone();
|
|
|
|
let file_num = files.len();
|
|
|
|
let mut files = files;
|
|
|
|
files.sort_by(|a, b| b.1.cmp(&a.1));
|
|
|
|
files.truncate(10);
|
2022-12-23 10:36:18 +08:00
|
|
|
let is_file = files.len() == 1 && files[0].0.is_empty();
|
2022-12-18 16:17:10 +08:00
|
|
|
let mut info = info;
|
|
|
|
info["ip"] = json!(self.ip.clone());
|
|
|
|
info["name"] = json!(self.lr.my_name.clone());
|
|
|
|
info["num"] = json!(file_num);
|
|
|
|
info["files"] = json!(files);
|
|
|
|
let v = json!({
|
|
|
|
"id":json!(Config::get_id()),
|
|
|
|
"uuid":json!(base64::encode(hbb_common::get_uuid())),
|
|
|
|
"peer_id":json!(self.lr.my_id),
|
2022-12-23 10:36:18 +08:00
|
|
|
"type": r#type as i8,
|
2022-12-18 16:17:10 +08:00
|
|
|
"path":path,
|
|
|
|
"is_file":is_file,
|
|
|
|
"info":json!(info).to_string(),
|
|
|
|
});
|
|
|
|
tokio::spawn(async move {
|
|
|
|
allow_err!(Self::post_audit_async(url, v).await);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-12-20 16:20:42 +08:00
|
|
|
pub fn post_alarm_audit(typ: AlarmAuditType, from_remote: bool, info: Value) {
|
|
|
|
let url = crate::get_audit_server(
|
|
|
|
Config::get_option("api-server"),
|
|
|
|
Config::get_option("custom-rendezvous-server"),
|
|
|
|
"alarm".to_owned(),
|
|
|
|
);
|
|
|
|
if url.is_empty() {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
let mut v = Value::default();
|
|
|
|
v["id"] = json!(Config::get_id());
|
|
|
|
v["uuid"] = json!(base64::encode(hbb_common::get_uuid()));
|
|
|
|
v["typ"] = json!(typ as i8);
|
|
|
|
v["from_remote"] = json!(from_remote);
|
|
|
|
v["info"] = serde_json::Value::String(info.to_string());
|
|
|
|
tokio::spawn(async move {
|
|
|
|
allow_err!(Self::post_audit_async(url, v).await);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-05-12 17:35:25 +08:00
|
|
|
#[inline]
|
2022-12-20 10:22:28 +08:00
|
|
|
async fn post_audit_async(url: String, v: Value) -> ResultType<String> {
|
|
|
|
crate::post_request(url, v.to_string(), "").await
|
2022-05-12 17:35:25 +08:00
|
|
|
}
|
|
|
|
|
2021-03-29 15:59:14 +08:00
|
|
|
async fn send_logon_response(&mut self) {
|
|
|
|
if self.authorized {
|
|
|
|
return;
|
|
|
|
}
|
2022-05-12 17:35:25 +08:00
|
|
|
let conn_type = if self.file_transfer.is_some() {
|
|
|
|
1
|
|
|
|
} else if self.port_forward_socket.is_some() {
|
|
|
|
2
|
|
|
|
} else {
|
|
|
|
0
|
|
|
|
};
|
2022-12-23 10:36:18 +08:00
|
|
|
self.post_conn_audit(json!({"peer": self.peer_info, "type": conn_type}));
|
2021-03-29 15:59:14 +08:00
|
|
|
#[allow(unused_mut)]
|
|
|
|
let mut username = crate::platform::get_active_username();
|
|
|
|
let mut res = LoginResponse::new();
|
2022-05-12 17:35:25 +08:00
|
|
|
let mut pi = PeerInfo {
|
|
|
|
username: username.clone(),
|
|
|
|
conn_id: self.inner.id,
|
2022-09-02 16:20:48 +08:00
|
|
|
version: VERSION.to_owned(),
|
2022-05-12 17:35:25 +08:00
|
|
|
..Default::default()
|
|
|
|
};
|
|
|
|
|
|
|
|
#[cfg(not(target_os = "android"))]
|
|
|
|
{
|
|
|
|
pi.hostname = whoami::hostname();
|
|
|
|
pi.platform = whoami::platform().to_string();
|
|
|
|
}
|
|
|
|
#[cfg(target_os = "android")]
|
|
|
|
{
|
2022-08-08 22:27:27 +08:00
|
|
|
pi.hostname = DEVICE_NAME.lock().unwrap().clone();
|
2022-05-12 17:35:25 +08:00
|
|
|
pi.platform = "Android".into();
|
|
|
|
}
|
2022-07-09 20:17:10 +08:00
|
|
|
#[cfg(feature = "hwcodec")]
|
|
|
|
{
|
|
|
|
let (h264, h265) = scrap::codec::Encoder::supported_encoding();
|
|
|
|
pi.encoding = Some(SupportedEncoding {
|
|
|
|
h264,
|
|
|
|
h265,
|
|
|
|
..Default::default()
|
|
|
|
})
|
|
|
|
.into();
|
|
|
|
}
|
2022-05-12 17:35:25 +08:00
|
|
|
|
2021-03-29 15:59:14 +08:00
|
|
|
if self.port_forward_socket.is_some() {
|
|
|
|
let mut msg_out = Message::new();
|
2022-05-12 17:35:25 +08:00
|
|
|
res.set_peer_info(pi);
|
2021-03-29 15:59:14 +08:00
|
|
|
msg_out.set_login_response(res);
|
|
|
|
self.send(msg_out).await;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#[cfg(target_os = "linux")]
|
2022-03-12 12:38:41 +08:00
|
|
|
if !self.file_transfer.is_some() && !self.port_forward_socket.is_some() {
|
2021-03-29 15:59:14 +08:00
|
|
|
let dtype = crate::platform::linux::get_display_server();
|
2022-07-07 01:27:21 +08:00
|
|
|
if dtype != "x11" && dtype != "wayland" {
|
2021-03-29 15:59:14 +08:00
|
|
|
res.set_error(format!(
|
2022-07-07 01:27:21 +08:00
|
|
|
"Unsupported display server type {}, x11 or wayland expected",
|
2021-03-29 15:59:14 +08:00
|
|
|
dtype
|
|
|
|
));
|
|
|
|
let mut msg_out = Message::new();
|
|
|
|
msg_out.set_login_response(res);
|
|
|
|
self.send(msg_out).await;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#[allow(unused_mut)]
|
|
|
|
let mut sas_enabled = false;
|
|
|
|
#[cfg(windows)]
|
|
|
|
if crate::platform::is_root() {
|
|
|
|
sas_enabled = true;
|
|
|
|
}
|
2022-05-12 17:35:25 +08:00
|
|
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
2021-03-29 15:59:14 +08:00
|
|
|
if self.file_transfer.is_some() {
|
|
|
|
if crate::platform::is_prelogin() || self.tx_to_cm.send(ipc::Data::Test).is_err() {
|
|
|
|
username = "".to_owned();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
self.authorized = true;
|
2022-04-25 12:28:28 +08:00
|
|
|
|
2022-06-08 22:35:06 +08:00
|
|
|
pi.username = username;
|
|
|
|
pi.sas_enabled = sas_enabled;
|
|
|
|
pi.features = Some(Features {
|
|
|
|
privacy_mode: video_service::is_privacy_mode_supported(),
|
2022-04-25 12:28:28 +08:00
|
|
|
..Default::default()
|
2022-06-08 22:35:06 +08:00
|
|
|
})
|
|
|
|
.into();
|
|
|
|
|
2021-03-29 15:59:14 +08:00
|
|
|
let mut sub_service = false;
|
|
|
|
if self.file_transfer.is_some() {
|
|
|
|
res.set_peer_info(pi);
|
|
|
|
} else {
|
|
|
|
try_activate_screen();
|
2022-10-14 11:19:49 +08:00
|
|
|
if let Some(msg_out) = super::video_service::is_inited_msg() {
|
|
|
|
self.send(msg_out).await;
|
|
|
|
}
|
|
|
|
|
2022-07-07 01:27:21 +08:00
|
|
|
match super::video_service::get_displays().await {
|
2021-03-29 15:59:14 +08:00
|
|
|
Err(err) => {
|
2022-10-17 09:41:02 +08:00
|
|
|
res.set_error(format!("{}", err));
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
|
|
|
Ok((current, displays)) => {
|
|
|
|
pi.displays = displays.into();
|
|
|
|
pi.current_display = current as _;
|
|
|
|
res.set_peer_info(pi);
|
|
|
|
sub_service = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let mut msg_out = Message::new();
|
|
|
|
msg_out.set_login_response(res);
|
|
|
|
self.send(msg_out).await;
|
|
|
|
if let Some((dir, show_hidden)) = self.file_transfer.clone() {
|
|
|
|
let dir = if !dir.is_empty() && std::path::Path::new(&dir).is_dir() {
|
|
|
|
&dir
|
|
|
|
} else {
|
|
|
|
""
|
|
|
|
};
|
|
|
|
self.read_dir(dir, show_hidden);
|
|
|
|
} else if sub_service {
|
|
|
|
if let Some(s) = self.server.upgrade() {
|
|
|
|
let mut noperms = Vec::new();
|
|
|
|
if !self.keyboard && !self.show_remote_cursor {
|
|
|
|
noperms.push(NAME_CURSOR);
|
|
|
|
}
|
|
|
|
if !self.show_remote_cursor {
|
|
|
|
noperms.push(NAME_POS);
|
|
|
|
}
|
|
|
|
if !self.clipboard_enabled() || !self.keyboard {
|
|
|
|
noperms.push(super::clipboard_service::NAME);
|
|
|
|
}
|
|
|
|
if !self.audio_enabled() {
|
|
|
|
noperms.push(super::audio_service::NAME);
|
|
|
|
}
|
|
|
|
s.write()
|
|
|
|
.unwrap()
|
|
|
|
.add_connection(self.inner.clone(), &noperms);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn clipboard_enabled(&self) -> bool {
|
|
|
|
self.clipboard && !self.disable_clipboard
|
|
|
|
}
|
|
|
|
|
|
|
|
fn audio_enabled(&self) -> bool {
|
|
|
|
self.audio && !self.disable_audio
|
|
|
|
}
|
|
|
|
|
2022-02-15 14:46:08 +08:00
|
|
|
fn file_transfer_enabled(&self) -> bool {
|
|
|
|
self.file && self.enable_file_transfer
|
|
|
|
}
|
|
|
|
|
2022-05-12 17:35:25 +08:00
|
|
|
fn try_start_cm(&mut self, peer_id: String, name: String, authorized: bool) {
|
|
|
|
self.peer_info = (peer_id.clone(), name.clone());
|
2021-03-29 15:59:14 +08:00
|
|
|
self.send_to_cm(ipc::Data::Login {
|
|
|
|
id: self.inner.id(),
|
|
|
|
is_file_transfer: self.file_transfer.is_some(),
|
|
|
|
port_forward: self.port_forward_address.clone(),
|
|
|
|
peer_id,
|
|
|
|
name,
|
|
|
|
authorized,
|
|
|
|
keyboard: self.keyboard,
|
|
|
|
clipboard: self.clipboard,
|
|
|
|
audio: self.audio,
|
2022-02-15 14:46:08 +08:00
|
|
|
file: self.file,
|
2022-02-22 22:26:22 +08:00
|
|
|
file_transfer_enabled: self.file_transfer_enabled(),
|
2022-07-25 19:35:15 +08:00
|
|
|
restart: self.restart,
|
2022-09-22 09:55:34 +08:00
|
|
|
recording: self.recording,
|
2021-03-29 15:59:14 +08:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn send_to_cm(&mut self, data: ipc::Data) {
|
|
|
|
self.tx_to_cm.send(data).ok();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn send_fs(&mut self, data: ipc::FS) {
|
|
|
|
self.send_to_cm(ipc::Data::FS(data));
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn send_login_error<T: std::string::ToString>(&mut self, err: T) {
|
|
|
|
let mut msg_out = Message::new();
|
|
|
|
let mut res = LoginResponse::new();
|
|
|
|
res.set_error(err.to_string());
|
|
|
|
msg_out.set_login_response(res);
|
|
|
|
self.send(msg_out).await;
|
|
|
|
}
|
|
|
|
|
2022-04-25 12:28:28 +08:00
|
|
|
#[inline]
|
|
|
|
pub fn send_block_input_error(s: &Sender, state: back_notification::BlockInputState) {
|
2022-01-15 16:31:21 +08:00
|
|
|
let mut misc = Misc::new();
|
2022-04-25 12:28:28 +08:00
|
|
|
let mut back_notification = BackNotification::new();
|
|
|
|
back_notification.set_block_input_state(state);
|
|
|
|
misc.set_back_notification(back_notification);
|
|
|
|
let mut msg_out = Message::new();
|
2022-01-15 16:31:21 +08:00
|
|
|
msg_out.set_misc(misc);
|
2022-01-15 21:33:20 +08:00
|
|
|
s.send((Instant::now(), Arc::new(msg_out))).ok();
|
2022-01-15 16:31:21 +08:00
|
|
|
}
|
|
|
|
|
2022-01-15 22:03:17 +08:00
|
|
|
#[inline]
|
|
|
|
fn input_mouse(&self, msg: MouseEvent, conn_id: i32) {
|
|
|
|
self.tx_input.send(MessageInput::Mouse((msg, conn_id))).ok();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn input_key(&self, msg: KeyEvent, press: bool) {
|
|
|
|
self.tx_input.send(MessageInput::Key((msg, press))).ok();
|
|
|
|
}
|
|
|
|
|
2022-07-18 14:03:52 +08:00
|
|
|
fn validate_one_password(&self, password: String) -> bool {
|
|
|
|
if password.len() == 0 {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
let mut hasher = Sha256::new();
|
|
|
|
hasher.update(password);
|
|
|
|
hasher.update(&self.hash.salt);
|
|
|
|
let mut hasher2 = Sha256::new();
|
|
|
|
hasher2.update(&hasher.finalize()[..]);
|
|
|
|
hasher2.update(&self.hash.challenge);
|
|
|
|
hasher2.finalize()[..] == self.lr.password[..]
|
|
|
|
}
|
|
|
|
|
|
|
|
fn validate_password(&mut self) -> bool {
|
2022-07-24 16:41:12 +08:00
|
|
|
if password::temporary_enabled() {
|
|
|
|
let password = password::temporary_password();
|
2022-07-18 14:03:52 +08:00
|
|
|
if self.validate_one_password(password.clone()) {
|
|
|
|
SESSIONS.lock().unwrap().insert(
|
|
|
|
self.lr.my_id.clone(),
|
|
|
|
Session {
|
|
|
|
name: self.lr.my_name.clone(),
|
|
|
|
session_id: self.lr.session_id,
|
|
|
|
last_recv_time: self.last_recv_time.clone(),
|
|
|
|
random_password: password,
|
|
|
|
},
|
|
|
|
);
|
2022-06-20 10:41:46 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2022-07-24 16:41:12 +08:00
|
|
|
if password::permanent_enabled() {
|
|
|
|
if self.validate_one_password(Config::get_permanent_password()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2022-07-18 14:03:52 +08:00
|
|
|
false
|
|
|
|
}
|
2022-06-20 10:41:46 +08:00
|
|
|
|
2022-07-18 14:03:52 +08:00
|
|
|
fn is_of_recent_session(&mut self) -> bool {
|
|
|
|
let session = SESSIONS
|
|
|
|
.lock()
|
|
|
|
.unwrap()
|
|
|
|
.get(&self.lr.my_id)
|
|
|
|
.map(|s| s.to_owned());
|
|
|
|
if let Some(session) = session {
|
|
|
|
if session.name == self.lr.my_name
|
|
|
|
&& session.session_id == self.lr.session_id
|
|
|
|
&& !self.lr.password.is_empty()
|
|
|
|
&& self.validate_one_password(session.random_password.clone())
|
|
|
|
&& session.last_recv_time.lock().unwrap().elapsed() < SESSION_TIMEOUT
|
|
|
|
{
|
|
|
|
SESSIONS.lock().unwrap().insert(
|
|
|
|
self.lr.my_id.clone(),
|
|
|
|
Session {
|
|
|
|
name: self.lr.my_name.clone(),
|
|
|
|
session_id: self.lr.session_id,
|
|
|
|
last_recv_time: self.last_recv_time.clone(),
|
|
|
|
random_password: session.random_password,
|
|
|
|
},
|
|
|
|
);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2022-06-20 10:41:46 +08:00
|
|
|
false
|
|
|
|
}
|
|
|
|
|
2022-10-17 14:35:44 +08:00
|
|
|
pub fn permission(enable_prefix_option: &str) -> bool {
|
|
|
|
#[cfg(feature = "flutter")]
|
|
|
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
|
|
|
{
|
|
|
|
let access_mode = Config::get_option("access-mode");
|
|
|
|
if access_mode == "full" {
|
|
|
|
return true;
|
|
|
|
} else if access_mode == "view" {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Config::get_option(enable_prefix_option).is_empty();
|
|
|
|
}
|
|
|
|
|
2022-01-15 16:31:21 +08:00
|
|
|
async fn on_message(&mut self, msg: Message) -> bool {
|
2022-07-14 17:20:01 +08:00
|
|
|
if let Some(message::Union::LoginRequest(lr)) = msg.union {
|
2022-07-18 14:03:52 +08:00
|
|
|
self.lr = lr.clone();
|
2021-03-29 15:59:14 +08:00
|
|
|
if let Some(o) = lr.option.as_ref() {
|
2022-01-15 16:31:21 +08:00
|
|
|
self.update_option(o).await;
|
2022-06-02 07:21:21 +08:00
|
|
|
if let Some(q) = o.video_codec_state.clone().take() {
|
|
|
|
scrap::codec::Encoder::update_video_encoder(
|
|
|
|
self.inner.id(),
|
|
|
|
scrap::codec::EncoderUpdate::State(q),
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
scrap::codec::Encoder::update_video_encoder(
|
|
|
|
self.inner.id(),
|
|
|
|
scrap::codec::EncoderUpdate::DisableHwIfNotExist,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
scrap::codec::Encoder::update_video_encoder(
|
|
|
|
self.inner.id(),
|
|
|
|
scrap::codec::EncoderUpdate::DisableHwIfNotExist,
|
|
|
|
);
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
2022-02-05 01:19:24 +08:00
|
|
|
self.video_ack_required = lr.video_ack_required;
|
2021-03-29 15:59:14 +08:00
|
|
|
if self.authorized {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
match lr.union {
|
2022-07-14 17:20:01 +08:00
|
|
|
Some(login_request::Union::FileTransfer(ft)) => {
|
2022-10-17 14:35:44 +08:00
|
|
|
if !Connection::permission("enable-file-transfer") {
|
2021-03-29 15:59:14 +08:00
|
|
|
self.send_login_error("No permission of file transfer")
|
|
|
|
.await;
|
|
|
|
sleep(1.).await;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
self.file_transfer = Some((ft.dir, ft.show_hidden));
|
|
|
|
}
|
2022-07-14 17:20:01 +08:00
|
|
|
Some(login_request::Union::PortForward(mut pf)) => {
|
2021-03-29 15:59:14 +08:00
|
|
|
let mut is_rdp = false;
|
|
|
|
if pf.host == "RDP" && pf.port == 0 {
|
|
|
|
pf.host = "localhost".to_owned();
|
|
|
|
pf.port = 3389;
|
|
|
|
is_rdp = true;
|
|
|
|
}
|
2022-10-17 14:35:44 +08:00
|
|
|
if is_rdp && !Connection::permission("enable-rdp")
|
|
|
|
|| !is_rdp && !Connection::permission("enable-tunnel")
|
2022-09-08 21:40:43 +08:00
|
|
|
{
|
|
|
|
if is_rdp {
|
|
|
|
self.send_login_error("No permission of RDP").await;
|
|
|
|
} else {
|
|
|
|
self.send_login_error("No permission of IP tunneling").await;
|
|
|
|
}
|
|
|
|
sleep(1.).await;
|
|
|
|
return false;
|
|
|
|
}
|
2021-03-29 15:59:14 +08:00
|
|
|
if pf.host.is_empty() {
|
|
|
|
pf.host = "localhost".to_owned();
|
|
|
|
}
|
|
|
|
let mut addr = format!("{}:{}", pf.host, pf.port);
|
|
|
|
self.port_forward_address = addr.clone();
|
|
|
|
match timeout(3000, TcpStream::connect(&addr)).await {
|
|
|
|
Ok(Ok(sock)) => {
|
|
|
|
self.port_forward_socket = Some(Framed::new(sock, BytesCodec::new()));
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
if is_rdp {
|
|
|
|
addr = "RDP".to_owned();
|
|
|
|
}
|
|
|
|
self.send_login_error(format!(
|
|
|
|
"Failed to access remote {}, please make sure if it is open",
|
|
|
|
addr
|
|
|
|
))
|
|
|
|
.await;
|
2022-08-29 19:45:06 +08:00
|
|
|
return false;
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
2022-12-28 13:52:13 +08:00
|
|
|
if !hbb_common::is_ipv4_str(&lr.username) && lr.username != Config::get_id() {
|
2021-03-29 15:59:14 +08:00
|
|
|
self.send_login_error("Offline").await;
|
2022-11-21 15:29:00 +08:00
|
|
|
} else if password::approve_mode() == ApproveMode::Click
|
|
|
|
|| password::approve_mode() == ApproveMode::Both && !password::has_valid_password()
|
|
|
|
{
|
2022-11-20 15:53:08 +08:00
|
|
|
self.try_start_cm(lr.my_id, lr.my_name, false);
|
|
|
|
if hbb_common::get_version_number(&lr.version)
|
|
|
|
>= hbb_common::get_version_number("1.2.0")
|
|
|
|
{
|
|
|
|
self.send_login_error("No Password Access").await;
|
|
|
|
}
|
|
|
|
return true;
|
2022-11-21 15:29:00 +08:00
|
|
|
} else if password::approve_mode() == ApproveMode::Password
|
|
|
|
&& !password::has_valid_password()
|
|
|
|
{
|
|
|
|
self.send_login_error("Connection not allowed").await;
|
|
|
|
return false;
|
2022-07-18 14:03:52 +08:00
|
|
|
} else if self.is_of_recent_session() {
|
|
|
|
self.try_start_cm(lr.my_id, lr.my_name, true);
|
|
|
|
self.send_logon_response().await;
|
|
|
|
if self.port_forward_socket.is_some() {
|
|
|
|
return false;
|
|
|
|
}
|
2021-03-29 15:59:14 +08:00
|
|
|
} else if lr.password.is_empty() {
|
2022-05-12 17:35:25 +08:00
|
|
|
self.try_start_cm(lr.my_id, lr.my_name, false);
|
2021-03-29 15:59:14 +08:00
|
|
|
} else {
|
|
|
|
let mut failure = LOGIN_FAILURES
|
|
|
|
.lock()
|
|
|
|
.unwrap()
|
|
|
|
.get(&self.ip)
|
|
|
|
.map(|x| x.clone())
|
|
|
|
.unwrap_or((0, 0, 0));
|
2022-09-11 21:46:53 +08:00
|
|
|
let time = (get_time() / 60_000) as i32;
|
2021-03-29 15:59:14 +08:00
|
|
|
if failure.2 > 30 {
|
|
|
|
self.send_login_error("Too many wrong password attempts")
|
|
|
|
.await;
|
2022-12-20 16:20:42 +08:00
|
|
|
Self::post_alarm_audit(
|
|
|
|
AlarmAuditType::ManyWrongPassword,
|
|
|
|
true,
|
|
|
|
json!({
|
|
|
|
"ip":self.ip,
|
|
|
|
}),
|
|
|
|
);
|
2021-03-29 15:59:14 +08:00
|
|
|
} else if time == failure.0 && failure.1 > 6 {
|
|
|
|
self.send_login_error("Please try 1 minute later").await;
|
2022-12-20 16:20:42 +08:00
|
|
|
Self::post_alarm_audit(
|
|
|
|
AlarmAuditType::FrequentAttempt,
|
|
|
|
true,
|
|
|
|
json!({
|
|
|
|
"ip":self.ip,
|
|
|
|
}),
|
|
|
|
);
|
2022-07-18 14:03:52 +08:00
|
|
|
} else if !self.validate_password() {
|
2021-03-29 15:59:14 +08:00
|
|
|
if failure.0 == time {
|
|
|
|
failure.1 += 1;
|
|
|
|
failure.2 += 1;
|
|
|
|
} else {
|
|
|
|
failure.0 = time;
|
|
|
|
failure.1 = 1;
|
|
|
|
failure.2 += 1;
|
|
|
|
}
|
|
|
|
LOGIN_FAILURES
|
|
|
|
.lock()
|
|
|
|
.unwrap()
|
|
|
|
.insert(self.ip.clone(), failure);
|
|
|
|
self.send_login_error("Wrong Password").await;
|
2022-05-12 17:35:25 +08:00
|
|
|
self.try_start_cm(lr.my_id, lr.my_name, false);
|
2021-03-29 15:59:14 +08:00
|
|
|
} else {
|
|
|
|
if failure.0 != 0 {
|
|
|
|
LOGIN_FAILURES.lock().unwrap().remove(&self.ip);
|
|
|
|
}
|
2022-05-12 17:35:25 +08:00
|
|
|
self.try_start_cm(lr.my_id, lr.my_name, true);
|
2021-03-29 15:59:14 +08:00
|
|
|
self.send_logon_response().await;
|
|
|
|
if self.port_forward_socket.is_some() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-07-14 17:20:01 +08:00
|
|
|
} else if let Some(message::Union::TestDelay(t)) = msg.union {
|
2021-03-29 15:59:14 +08:00
|
|
|
if t.from_client {
|
|
|
|
let mut msg_out = Message::new();
|
|
|
|
msg_out.set_test_delay(t);
|
|
|
|
self.inner.send(msg_out.into());
|
|
|
|
} else {
|
|
|
|
self.last_test_delay = 0;
|
2022-09-11 21:46:53 +08:00
|
|
|
let new_delay = (get_time() - t.time) as u32;
|
2022-06-23 17:42:30 +08:00
|
|
|
video_service::VIDEO_QOS
|
|
|
|
.lock()
|
|
|
|
.unwrap()
|
|
|
|
.update_network_delay(new_delay);
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
|
|
|
} else if self.authorized {
|
|
|
|
match msg.union {
|
2022-07-14 17:20:01 +08:00
|
|
|
Some(message::Union::MouseEvent(me)) => {
|
2022-05-12 17:35:25 +08:00
|
|
|
#[cfg(any(target_os = "android", target_os = "ios"))]
|
2022-06-01 21:14:02 +08:00
|
|
|
if let Err(e) = call_main_service_mouse_input(me.mask, me.x, me.y) {
|
|
|
|
log::debug!("call_main_service_mouse_input fail:{}", e);
|
2022-05-12 17:35:25 +08:00
|
|
|
}
|
|
|
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
2021-03-29 15:59:14 +08:00
|
|
|
if self.keyboard {
|
2022-05-12 17:35:25 +08:00
|
|
|
if is_left_up(&me) {
|
2022-09-11 21:46:53 +08:00
|
|
|
CLICK_TIME.store(get_time(), Ordering::SeqCst);
|
2022-05-12 17:35:25 +08:00
|
|
|
} else {
|
2022-09-11 21:46:53 +08:00
|
|
|
MOUSE_MOVE_TIME.store(get_time(), Ordering::SeqCst);
|
2022-05-12 17:35:25 +08:00
|
|
|
}
|
2022-01-15 22:03:17 +08:00
|
|
|
self.input_mouse(me, self.inner.id());
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
|
|
|
}
|
2022-07-14 17:20:01 +08:00
|
|
|
Some(message::Union::KeyEvent(me)) => {
|
2022-05-12 17:35:25 +08:00
|
|
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
2021-03-29 15:59:14 +08:00
|
|
|
if self.keyboard {
|
2022-05-12 17:35:25 +08:00
|
|
|
if is_enter(&me) {
|
2022-09-11 21:46:53 +08:00
|
|
|
CLICK_TIME.store(get_time(), Ordering::SeqCst);
|
2022-05-12 17:35:25 +08:00
|
|
|
}
|
2021-08-06 14:23:50 +08:00
|
|
|
// handle all down as press
|
|
|
|
// fix unexpected repeating key on remote linux, seems also fix abnormal alt/shift, which
|
|
|
|
// make sure all key are released
|
2021-08-08 17:29:39 +08:00
|
|
|
let is_press = if cfg!(target_os = "linux") {
|
|
|
|
(me.press || me.down) && !crate::is_modifier(&me)
|
|
|
|
} else {
|
|
|
|
me.press
|
|
|
|
};
|
|
|
|
if is_press {
|
2022-01-15 22:03:17 +08:00
|
|
|
match me.union {
|
2022-07-14 17:20:01 +08:00
|
|
|
Some(key_event::Union::Unicode(_))
|
|
|
|
| Some(key_event::Union::Seq(_)) => {
|
2022-01-15 22:03:17 +08:00
|
|
|
self.input_key(me, false);
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
self.input_key(me, true);
|
|
|
|
}
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
|
|
|
} else {
|
2022-01-15 22:03:17 +08:00
|
|
|
self.input_key(me, false);
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-07-14 17:20:01 +08:00
|
|
|
Some(message::Union::Clipboard(cb)) =>
|
2022-05-12 17:35:25 +08:00
|
|
|
{
|
|
|
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
2021-03-29 15:59:14 +08:00
|
|
|
if self.clipboard {
|
|
|
|
update_clipboard(cb, None);
|
|
|
|
}
|
|
|
|
}
|
2022-07-14 17:20:01 +08:00
|
|
|
Some(message::Union::Cliprdr(_clip)) => {
|
2022-02-22 14:17:50 +08:00
|
|
|
if self.file_transfer_enabled() {
|
|
|
|
#[cfg(windows)]
|
|
|
|
if let Some(clip) = msg_2_clip(_clip) {
|
|
|
|
self.send_to_cm(ipc::Data::ClipbaordFile(clip))
|
|
|
|
}
|
|
|
|
}
|
2022-02-14 17:34:09 +08:00
|
|
|
}
|
2022-07-14 17:20:01 +08:00
|
|
|
Some(message::Union::FileAction(fa)) => {
|
2021-03-29 15:59:14 +08:00
|
|
|
if self.file_transfer.is_some() {
|
|
|
|
match fa.union {
|
2022-07-14 17:20:01 +08:00
|
|
|
Some(file_action::Union::ReadDir(rd)) => {
|
2021-03-29 15:59:14 +08:00
|
|
|
self.read_dir(&rd.path, rd.include_hidden);
|
|
|
|
}
|
2022-07-14 17:20:01 +08:00
|
|
|
Some(file_action::Union::AllFiles(f)) => {
|
2021-03-29 15:59:14 +08:00
|
|
|
match fs::get_recursive_files(&f.path, f.include_hidden) {
|
|
|
|
Err(err) => {
|
|
|
|
self.send(fs::new_error(f.id, err, -1)).await;
|
|
|
|
}
|
|
|
|
Ok(files) => {
|
2022-05-12 17:35:25 +08:00
|
|
|
self.send(fs::new_dir(f.id, f.path, files)).await;
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-07-14 17:20:01 +08:00
|
|
|
Some(file_action::Union::Send(s)) => {
|
2021-03-29 15:59:14 +08:00
|
|
|
let id = s.id;
|
2022-08-01 09:50:23 +08:00
|
|
|
let od = can_enable_overwrite_detection(get_version_number(
|
|
|
|
&self.lr.version,
|
|
|
|
));
|
2022-05-13 14:46:37 +08:00
|
|
|
let path = s.path.clone();
|
|
|
|
match fs::TransferJob::new_read(
|
|
|
|
id,
|
|
|
|
"".to_string(),
|
|
|
|
path.clone(),
|
|
|
|
s.file_num,
|
|
|
|
s.include_hidden,
|
|
|
|
false,
|
|
|
|
od,
|
|
|
|
) {
|
2021-03-29 15:59:14 +08:00
|
|
|
Err(err) => {
|
|
|
|
self.send(fs::new_error(id, err, 0)).await;
|
|
|
|
}
|
|
|
|
Ok(job) => {
|
2022-05-12 17:35:25 +08:00
|
|
|
self.send(fs::new_dir(id, path, job.files().to_vec()))
|
|
|
|
.await;
|
2022-12-18 16:17:10 +08:00
|
|
|
let mut files = job.files().to_owned();
|
2021-03-29 15:59:14 +08:00
|
|
|
self.read_jobs.push(job);
|
2022-12-18 17:00:10 +08:00
|
|
|
self.file_timer = time::interval(MILLI1);
|
2022-12-18 16:17:10 +08:00
|
|
|
self.post_file_audit(
|
2022-12-23 10:36:18 +08:00
|
|
|
FileAuditType::RemoteSend,
|
2022-12-18 16:17:10 +08:00
|
|
|
&s.path,
|
|
|
|
files
|
|
|
|
.drain(..)
|
|
|
|
.map(|f| (f.name, f.size as _))
|
|
|
|
.collect(),
|
|
|
|
json!({}),
|
|
|
|
);
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-07-14 17:20:01 +08:00
|
|
|
Some(file_action::Union::Receive(r)) => {
|
2022-08-01 09:50:23 +08:00
|
|
|
// note: 1.1.10 introduced identical file detection, which breaks original logic of send/recv files
|
|
|
|
// whenever got send/recv request, check peer version to ensure old version of rustdesk
|
|
|
|
let od = can_enable_overwrite_detection(get_version_number(
|
|
|
|
&self.lr.version,
|
|
|
|
));
|
2021-03-29 15:59:14 +08:00
|
|
|
self.send_fs(ipc::FS::NewWrite {
|
2022-12-18 16:17:10 +08:00
|
|
|
path: r.path.clone(),
|
2021-03-29 15:59:14 +08:00
|
|
|
id: r.id,
|
2022-05-13 11:23:30 +08:00
|
|
|
file_num: r.file_num,
|
2021-03-29 15:59:14 +08:00
|
|
|
files: r
|
|
|
|
.files
|
|
|
|
.to_vec()
|
|
|
|
.drain(..)
|
|
|
|
.map(|f| (f.name, f.modified_time))
|
|
|
|
.collect(),
|
2022-08-01 09:50:23 +08:00
|
|
|
overwrite_detection: od,
|
2021-03-29 15:59:14 +08:00
|
|
|
});
|
2022-12-18 16:17:10 +08:00
|
|
|
self.post_file_audit(
|
2022-12-23 10:36:18 +08:00
|
|
|
FileAuditType::RemoteReceive,
|
2022-12-18 16:17:10 +08:00
|
|
|
&r.path,
|
|
|
|
r.files
|
|
|
|
.to_vec()
|
|
|
|
.drain(..)
|
|
|
|
.map(|f| (f.name, f.size as _))
|
|
|
|
.collect(),
|
|
|
|
json!({}),
|
|
|
|
);
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
2022-07-14 17:20:01 +08:00
|
|
|
Some(file_action::Union::RemoveDir(d)) => {
|
2021-03-29 15:59:14 +08:00
|
|
|
self.send_fs(ipc::FS::RemoveDir {
|
|
|
|
path: d.path,
|
|
|
|
id: d.id,
|
|
|
|
recursive: d.recursive,
|
|
|
|
});
|
|
|
|
}
|
2022-07-14 17:20:01 +08:00
|
|
|
Some(file_action::Union::RemoveFile(f)) => {
|
2021-03-29 15:59:14 +08:00
|
|
|
self.send_fs(ipc::FS::RemoveFile {
|
|
|
|
path: f.path,
|
|
|
|
id: f.id,
|
|
|
|
file_num: f.file_num,
|
|
|
|
});
|
|
|
|
}
|
2022-07-14 17:20:01 +08:00
|
|
|
Some(file_action::Union::Create(c)) => {
|
2021-03-29 15:59:14 +08:00
|
|
|
self.send_fs(ipc::FS::CreateDir {
|
|
|
|
path: c.path,
|
|
|
|
id: c.id,
|
|
|
|
});
|
|
|
|
}
|
2022-07-14 17:20:01 +08:00
|
|
|
Some(file_action::Union::Cancel(c)) => {
|
2021-03-29 15:59:14 +08:00
|
|
|
self.send_fs(ipc::FS::CancelWrite { id: c.id });
|
|
|
|
fs::remove_job(c.id, &mut self.read_jobs);
|
|
|
|
}
|
2022-07-14 17:20:01 +08:00
|
|
|
Some(file_action::Union::SendConfirm(r)) => {
|
2022-04-27 10:45:20 +08:00
|
|
|
if let Some(job) = fs::get_job(r.id, &mut self.read_jobs) {
|
|
|
|
job.confirm(&r);
|
2022-04-26 16:33:54 +08:00
|
|
|
}
|
2022-04-26 16:21:34 +08:00
|
|
|
}
|
2021-03-29 15:59:14 +08:00
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-07-14 17:20:01 +08:00
|
|
|
Some(message::Union::FileResponse(fr)) => match fr.union {
|
|
|
|
Some(file_response::Union::Block(block)) => {
|
2021-03-29 15:59:14 +08:00
|
|
|
self.send_fs(ipc::FS::WriteBlock {
|
|
|
|
id: block.id,
|
|
|
|
file_num: block.file_num,
|
|
|
|
data: block.data,
|
|
|
|
compressed: block.compressed,
|
|
|
|
});
|
|
|
|
}
|
2022-07-14 17:20:01 +08:00
|
|
|
Some(file_response::Union::Done(d)) => {
|
2021-03-29 15:59:14 +08:00
|
|
|
self.send_fs(ipc::FS::WriteDone {
|
|
|
|
id: d.id,
|
|
|
|
file_num: d.file_num,
|
|
|
|
});
|
|
|
|
}
|
2022-07-14 17:20:01 +08:00
|
|
|
Some(file_response::Union::Digest(d)) => self.send_fs(ipc::FS::CheckDigest {
|
2022-04-27 10:45:20 +08:00
|
|
|
id: d.id,
|
|
|
|
file_num: d.file_num,
|
|
|
|
file_size: d.file_size,
|
2022-04-29 16:47:45 +08:00
|
|
|
last_modified: d.last_modified,
|
2022-04-28 17:42:22 +08:00
|
|
|
is_upload: true,
|
2022-04-27 10:45:20 +08:00
|
|
|
}),
|
2022-12-06 12:11:26 +08:00
|
|
|
Some(file_response::Union::Error(e)) => {
|
|
|
|
self.send_fs(ipc::FS::WriteError {
|
|
|
|
id: e.id,
|
|
|
|
file_num: e.file_num,
|
|
|
|
err: e.error,
|
|
|
|
});
|
|
|
|
}
|
2021-03-29 15:59:14 +08:00
|
|
|
_ => {}
|
|
|
|
},
|
2022-07-14 17:20:01 +08:00
|
|
|
Some(message::Union::Misc(misc)) => match misc.union {
|
|
|
|
Some(misc::Union::SwitchDisplay(s)) => {
|
2022-07-07 01:27:21 +08:00
|
|
|
video_service::switch_display(s.display).await;
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
2022-07-14 17:20:01 +08:00
|
|
|
Some(misc::Union::ChatMessage(c)) => {
|
2021-03-29 15:59:14 +08:00
|
|
|
self.send_to_cm(ipc::Data::ChatMessage { text: c.text });
|
2022-10-08 20:15:02 +08:00
|
|
|
self.chat_unanswered = true;
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
2022-07-14 17:20:01 +08:00
|
|
|
Some(misc::Union::Option(o)) => {
|
2022-01-15 16:31:21 +08:00
|
|
|
self.update_option(&o).await;
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
2022-07-14 17:20:01 +08:00
|
|
|
Some(misc::Union::RefreshVideo(r)) => {
|
2021-03-29 15:59:14 +08:00
|
|
|
if r {
|
2022-07-07 01:27:21 +08:00
|
|
|
super::video_service::refresh();
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
|
|
|
}
|
2022-07-14 17:20:01 +08:00
|
|
|
Some(misc::Union::VideoReceived(_)) => {
|
2022-02-09 16:06:44 +08:00
|
|
|
video_service::notify_video_frame_feched(
|
|
|
|
self.inner.id,
|
|
|
|
Some(Instant::now().into()),
|
|
|
|
);
|
2022-02-04 22:18:48 +08:00
|
|
|
}
|
2022-07-18 11:05:19 +08:00
|
|
|
Some(misc::Union::CloseReason(_)) => {
|
2022-07-07 01:27:21 +08:00
|
|
|
self.on_close("Peer close", true).await;
|
2022-07-18 14:03:52 +08:00
|
|
|
SESSIONS.lock().unwrap().remove(&self.lr.my_id);
|
2022-07-18 11:05:19 +08:00
|
|
|
return false;
|
|
|
|
}
|
2022-07-25 19:35:15 +08:00
|
|
|
|
|
|
|
Some(misc::Union::RestartRemoteDevice(_)) =>
|
|
|
|
{
|
|
|
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
|
|
|
if self.restart {
|
|
|
|
match system_shutdown::reboot() {
|
|
|
|
Ok(_) => log::info!("Restart by the peer"),
|
|
|
|
Err(e) => log::error!("Failed to restart:{}", e),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-03-29 15:59:14 +08:00
|
|
|
_ => {}
|
|
|
|
},
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
true
|
|
|
|
}
|
|
|
|
|
2022-01-15 16:31:21 +08:00
|
|
|
async fn update_option(&mut self, o: &OptionMessage) {
|
2021-03-29 15:59:14 +08:00
|
|
|
log::info!("Option update: {:?}", o);
|
|
|
|
if let Ok(q) = o.image_quality.enum_value() {
|
2022-06-27 22:24:56 +08:00
|
|
|
let image_quality;
|
2022-06-23 17:42:30 +08:00
|
|
|
if let ImageQuality::NotSet = q {
|
|
|
|
if o.custom_image_quality > 0 {
|
2022-06-27 22:24:56 +08:00
|
|
|
image_quality = o.custom_image_quality;
|
|
|
|
} else {
|
2022-10-19 10:19:49 +08:00
|
|
|
image_quality = -1;
|
2022-06-23 17:42:30 +08:00
|
|
|
}
|
|
|
|
} else {
|
2022-06-27 22:24:56 +08:00
|
|
|
image_quality = q.value();
|
2022-06-23 17:42:30 +08:00
|
|
|
}
|
2022-10-19 10:19:49 +08:00
|
|
|
if image_quality > 0 {
|
|
|
|
video_service::VIDEO_QOS
|
|
|
|
.lock()
|
|
|
|
.unwrap()
|
|
|
|
.update_image_quality(image_quality);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if o.custom_fps > 0 {
|
2022-06-23 17:42:30 +08:00
|
|
|
video_service::VIDEO_QOS
|
|
|
|
.lock()
|
|
|
|
.unwrap()
|
2022-10-19 10:19:49 +08:00
|
|
|
.update_user_fps(o.custom_fps as _);
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
2022-10-19 10:19:49 +08:00
|
|
|
|
2021-03-29 15:59:14 +08:00
|
|
|
if let Ok(q) = o.lock_after_session_end.enum_value() {
|
|
|
|
if q != BoolOption::NotSet {
|
|
|
|
self.lock_after_session_end = q == BoolOption::Yes;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if let Ok(q) = o.show_remote_cursor.enum_value() {
|
|
|
|
if q != BoolOption::NotSet {
|
|
|
|
self.show_remote_cursor = q == BoolOption::Yes;
|
|
|
|
if let Some(s) = self.server.upgrade() {
|
|
|
|
s.write().unwrap().subscribe(
|
|
|
|
NAME_CURSOR,
|
|
|
|
self.inner.clone(),
|
|
|
|
self.keyboard || self.show_remote_cursor,
|
|
|
|
);
|
|
|
|
s.write().unwrap().subscribe(
|
|
|
|
NAME_POS,
|
|
|
|
self.inner.clone(),
|
|
|
|
self.show_remote_cursor,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if let Ok(q) = o.disable_audio.enum_value() {
|
|
|
|
if q != BoolOption::NotSet {
|
|
|
|
self.disable_audio = q == BoolOption::Yes;
|
|
|
|
if let Some(s) = self.server.upgrade() {
|
|
|
|
s.write().unwrap().subscribe(
|
2021-08-04 15:30:47 +08:00
|
|
|
super::audio_service::NAME,
|
2021-03-29 15:59:14 +08:00
|
|
|
self.inner.clone(),
|
|
|
|
self.audio_enabled(),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-02-15 14:46:08 +08:00
|
|
|
#[cfg(windows)]
|
|
|
|
if let Ok(q) = o.enable_file_transfer.enum_value() {
|
|
|
|
if q != BoolOption::NotSet {
|
|
|
|
self.enable_file_transfer = q == BoolOption::Yes;
|
2022-05-12 17:35:25 +08:00
|
|
|
self.send_to_cm(ipc::Data::ClipboardFileEnabled(
|
|
|
|
self.file_transfer_enabled(),
|
|
|
|
));
|
2022-02-15 14:46:08 +08:00
|
|
|
}
|
|
|
|
}
|
2021-03-29 15:59:14 +08:00
|
|
|
if let Ok(q) = o.disable_clipboard.enum_value() {
|
|
|
|
if q != BoolOption::NotSet {
|
|
|
|
self.disable_clipboard = q == BoolOption::Yes;
|
|
|
|
if let Some(s) = self.server.upgrade() {
|
|
|
|
s.write().unwrap().subscribe(
|
2021-08-04 15:30:47 +08:00
|
|
|
super::clipboard_service::NAME,
|
2021-03-29 15:59:14 +08:00
|
|
|
self.inner.clone(),
|
|
|
|
self.clipboard_enabled() && self.keyboard,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if let Ok(q) = o.privacy_mode.enum_value() {
|
2022-01-15 16:31:21 +08:00
|
|
|
if self.keyboard {
|
|
|
|
match q {
|
|
|
|
BoolOption::Yes => {
|
2022-04-25 12:28:28 +08:00
|
|
|
let msg_out = if !video_service::is_privacy_mode_supported() {
|
|
|
|
crate::common::make_privacy_mode_msg(
|
2022-07-31 22:31:17 +08:00
|
|
|
back_notification::PrivacyModeState::PrvNotSupported,
|
2022-04-25 12:28:28 +08:00
|
|
|
)
|
|
|
|
} else {
|
|
|
|
match privacy_mode::turn_on_privacy(self.inner.id) {
|
|
|
|
Ok(true) => {
|
2022-05-31 15:54:21 +08:00
|
|
|
if video_service::test_create_capturer(self.inner.id, 5_000) {
|
|
|
|
video_service::set_privacy_mode_conn_id(self.inner.id);
|
|
|
|
crate::common::make_privacy_mode_msg(
|
2022-07-31 22:31:17 +08:00
|
|
|
back_notification::PrivacyModeState::PrvOnSucceeded,
|
2022-05-31 15:54:21 +08:00
|
|
|
)
|
|
|
|
} else {
|
|
|
|
log::error!(
|
|
|
|
"Wait privacy mode timeout, turn off privacy mode"
|
|
|
|
);
|
|
|
|
video_service::set_privacy_mode_conn_id(0);
|
|
|
|
let _ = privacy_mode::turn_off_privacy(self.inner.id);
|
|
|
|
crate::common::make_privacy_mode_msg(
|
2022-07-31 22:31:17 +08:00
|
|
|
back_notification::PrivacyModeState::PrvOnFailed,
|
2022-05-31 15:54:21 +08:00
|
|
|
)
|
|
|
|
}
|
2022-04-25 12:28:28 +08:00
|
|
|
}
|
2022-05-31 15:54:21 +08:00
|
|
|
Ok(false) => crate::common::make_privacy_mode_msg(
|
2022-07-31 22:31:17 +08:00
|
|
|
back_notification::PrivacyModeState::PrvOnFailedPlugin,
|
2022-05-31 15:54:21 +08:00
|
|
|
),
|
2022-04-25 12:28:28 +08:00
|
|
|
Err(e) => {
|
|
|
|
log::error!("Failed to turn on privacy mode. {}", e);
|
2022-05-31 15:54:21 +08:00
|
|
|
if video_service::get_privacy_mode_conn_id() == 0 {
|
|
|
|
let _ = privacy_mode::turn_off_privacy(0);
|
|
|
|
}
|
2022-04-25 12:28:28 +08:00
|
|
|
crate::common::make_privacy_mode_msg(
|
2022-07-31 22:31:17 +08:00
|
|
|
back_notification::PrivacyModeState::PrvOnFailed,
|
2022-04-25 12:28:28 +08:00
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
self.send(msg_out).await;
|
2022-01-14 00:32:09 +08:00
|
|
|
}
|
2022-01-15 16:31:21 +08:00
|
|
|
BoolOption::No => {
|
2022-04-25 12:28:28 +08:00
|
|
|
let msg_out = if !video_service::is_privacy_mode_supported() {
|
|
|
|
crate::common::make_privacy_mode_msg(
|
2022-07-31 22:31:17 +08:00
|
|
|
back_notification::PrivacyModeState::PrvNotSupported,
|
2022-04-25 12:28:28 +08:00
|
|
|
)
|
|
|
|
} else {
|
|
|
|
video_service::set_privacy_mode_conn_id(0);
|
2022-05-31 15:54:21 +08:00
|
|
|
privacy_mode::turn_off_privacy(self.inner.id)
|
2022-04-25 12:28:28 +08:00
|
|
|
};
|
|
|
|
self.send(msg_out).await;
|
2022-01-15 16:31:21 +08:00
|
|
|
}
|
|
|
|
_ => {}
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if self.keyboard {
|
|
|
|
if let Ok(q) = o.block_input.enum_value() {
|
2022-01-15 16:31:21 +08:00
|
|
|
match q {
|
|
|
|
BoolOption::Yes => {
|
2022-01-15 19:11:19 +08:00
|
|
|
self.tx_input.send(MessageInput::BlockOn).ok();
|
2022-01-15 16:31:21 +08:00
|
|
|
}
|
|
|
|
BoolOption::No => {
|
2022-01-15 19:11:19 +08:00
|
|
|
self.tx_input.send(MessageInput::BlockOff).ok();
|
2022-01-15 16:31:21 +08:00
|
|
|
}
|
|
|
|
_ => {}
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-07-09 20:17:10 +08:00
|
|
|
if let Some(q) = o.video_codec_state.clone().take() {
|
|
|
|
scrap::codec::Encoder::update_video_encoder(
|
|
|
|
self.inner.id(),
|
|
|
|
scrap::codec::EncoderUpdate::State(q),
|
|
|
|
);
|
|
|
|
}
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
|
|
|
|
2022-07-07 01:27:21 +08:00
|
|
|
async fn on_close(&mut self, reason: &str, lock: bool) {
|
2021-03-29 15:59:14 +08:00
|
|
|
if let Some(s) = self.server.upgrade() {
|
|
|
|
s.write().unwrap().remove_connection(&self.inner);
|
|
|
|
}
|
|
|
|
log::info!("#{} Connection closed: {}", self.inner.id(), reason);
|
|
|
|
if lock && self.lock_after_session_end && self.keyboard {
|
2022-05-12 17:35:25 +08:00
|
|
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
2022-07-07 01:27:21 +08:00
|
|
|
lock_screen().await;
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
2022-10-08 20:15:02 +08:00
|
|
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
|
|
|
let data = if self.chat_unanswered && !self.close_manually {
|
|
|
|
ipc::Data::Disconnected
|
|
|
|
} else {
|
|
|
|
ipc::Data::Close
|
|
|
|
};
|
|
|
|
#[cfg(any(target_os = "android", target_os = "ios"))]
|
|
|
|
let data = ipc::Data::Close;
|
|
|
|
self.tx_to_cm.send(data).ok();
|
2021-03-29 15:59:14 +08:00
|
|
|
self.port_forward_socket.take();
|
|
|
|
}
|
|
|
|
|
2022-12-20 10:22:28 +08:00
|
|
|
async fn on_close_manually(&mut self, close_from: &str, close_by: &str) {
|
2022-11-09 17:28:47 +08:00
|
|
|
self.close_manually = true;
|
|
|
|
let mut misc = Misc::new();
|
2022-12-20 10:22:28 +08:00
|
|
|
misc.set_close_reason(format!("Closed manually by the {}", close_by));
|
2022-11-09 17:28:47 +08:00
|
|
|
let mut msg_out = Message::new();
|
|
|
|
msg_out.set_misc(misc);
|
|
|
|
self.send(msg_out).await;
|
|
|
|
self.on_close(&format!("Close requested from {}", close_from), false)
|
|
|
|
.await;
|
|
|
|
SESSIONS.lock().unwrap().remove(&self.lr.my_id);
|
|
|
|
}
|
|
|
|
|
2021-03-29 15:59:14 +08:00
|
|
|
fn read_dir(&mut self, dir: &str, include_hidden: bool) {
|
|
|
|
let dir = dir.to_string();
|
|
|
|
self.send_fs(ipc::FS::ReadDir {
|
|
|
|
dir,
|
|
|
|
include_hidden,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
async fn send(&mut self, msg: Message) {
|
|
|
|
allow_err!(self.stream.send(&msg).await);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-12 17:35:25 +08:00
|
|
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
2021-03-29 15:59:14 +08:00
|
|
|
async fn start_ipc(
|
|
|
|
mut rx_to_cm: mpsc::UnboundedReceiver<ipc::Data>,
|
|
|
|
tx_from_cm: mpsc::UnboundedSender<ipc::Data>,
|
|
|
|
) -> ResultType<()> {
|
2022-01-15 02:16:00 +08:00
|
|
|
loop {
|
|
|
|
if !crate::platform::is_prelogin() {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
sleep(1.).await;
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
|
|
|
let mut stream = None;
|
|
|
|
if let Ok(s) = crate::ipc::connect(1000, "_cm").await {
|
|
|
|
stream = Some(s);
|
|
|
|
} else {
|
2022-11-27 12:31:53 +08:00
|
|
|
let mut args = vec!["--cm"];
|
|
|
|
if password::hide_cm() {
|
|
|
|
args.push("--hide");
|
|
|
|
};
|
2021-03-29 15:59:14 +08:00
|
|
|
let run_done;
|
|
|
|
if crate::platform::is_root() {
|
|
|
|
let mut res = Ok(None);
|
|
|
|
for _ in 0..10 {
|
2022-10-17 22:55:14 +08:00
|
|
|
#[cfg(not(target_os = "linux"))]
|
|
|
|
{
|
2022-11-27 12:31:53 +08:00
|
|
|
res = crate::platform::run_as_user(args.clone());
|
2022-10-17 22:55:14 +08:00
|
|
|
}
|
|
|
|
#[cfg(target_os = "linux")]
|
|
|
|
{
|
2022-11-27 12:31:53 +08:00
|
|
|
res = crate::platform::run_as_user(args.clone(), None);
|
2022-10-17 22:55:14 +08:00
|
|
|
}
|
2021-03-29 15:59:14 +08:00
|
|
|
if res.is_ok() {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
sleep(1.).await;
|
|
|
|
}
|
|
|
|
if let Some(task) = res? {
|
|
|
|
super::CHILD_PROCESS.lock().unwrap().push(task);
|
|
|
|
}
|
|
|
|
run_done = true;
|
|
|
|
} else {
|
|
|
|
run_done = false;
|
|
|
|
}
|
|
|
|
if !run_done {
|
|
|
|
super::CHILD_PROCESS
|
|
|
|
.lock()
|
|
|
|
.unwrap()
|
2022-11-23 09:41:05 +08:00
|
|
|
.push(crate::run_me(args)?);
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
|
|
|
for _ in 0..10 {
|
|
|
|
sleep(0.3).await;
|
|
|
|
if let Ok(s) = crate::ipc::connect(1000, "_cm").await {
|
|
|
|
stream = Some(s);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if stream.is_none() {
|
|
|
|
bail!("Failed to connect to connection manager");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let mut stream = stream.unwrap();
|
|
|
|
loop {
|
|
|
|
tokio::select! {
|
|
|
|
res = stream.next() => {
|
|
|
|
match res {
|
|
|
|
Err(err) => {
|
|
|
|
return Err(err.into());
|
|
|
|
}
|
|
|
|
Ok(Some(data)) => {
|
2022-05-12 17:35:25 +08:00
|
|
|
match data {
|
|
|
|
ipc::Data::ClickTime(_)=> {
|
|
|
|
let ct = CLICK_TIME.load(Ordering::SeqCst);
|
|
|
|
let data = ipc::Data::ClickTime(ct);
|
|
|
|
stream.send(&data).await?;
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
tx_from_cm.send(data)?;
|
|
|
|
}
|
|
|
|
}
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
res = rx_to_cm.recv() => {
|
|
|
|
match res {
|
|
|
|
Some(data) => {
|
2022-03-26 03:05:15 +08:00
|
|
|
if let Data::FS(ipc::FS::WriteBlock{id,
|
|
|
|
file_num,
|
|
|
|
data,
|
|
|
|
compressed}) = data {
|
2022-11-16 17:53:32 +08:00
|
|
|
stream.send(&Data::FS(ipc::FS::WriteBlock{id, file_num, data: Bytes::new(), compressed})).await?;
|
|
|
|
stream.send_raw(data).await?;
|
2022-03-26 03:05:15 +08:00
|
|
|
} else {
|
|
|
|
stream.send(&data).await?;
|
|
|
|
}
|
2021-03-29 15:59:14 +08:00
|
|
|
}
|
|
|
|
None => {
|
|
|
|
bail!("expected");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// in case screen is sleep and blank, here to activate it
|
|
|
|
fn try_activate_screen() {
|
|
|
|
#[cfg(windows)]
|
|
|
|
std::thread::spawn(|| {
|
|
|
|
mouse_move_relative(-6, -6);
|
|
|
|
std::thread::sleep(std::time::Duration::from_millis(30));
|
|
|
|
mouse_move_relative(6, 6);
|
|
|
|
});
|
|
|
|
}
|
2022-04-25 12:28:28 +08:00
|
|
|
|
|
|
|
mod privacy_mode {
|
|
|
|
use super::*;
|
|
|
|
|
2022-05-31 15:54:21 +08:00
|
|
|
pub(super) fn turn_off_privacy(_conn_id: i32) -> Message {
|
2022-04-25 12:28:28 +08:00
|
|
|
#[cfg(windows)]
|
|
|
|
{
|
|
|
|
use crate::ui::win_privacy::*;
|
|
|
|
|
|
|
|
let res = turn_off_privacy(_conn_id, None);
|
|
|
|
match res {
|
|
|
|
Ok(_) => crate::common::make_privacy_mode_msg(
|
2022-07-31 22:31:17 +08:00
|
|
|
back_notification::PrivacyModeState::PrvOffSucceeded,
|
2022-04-25 12:28:28 +08:00
|
|
|
),
|
|
|
|
Err(e) => {
|
2022-05-31 10:00:11 +08:00
|
|
|
log::error!("Failed to turn off privacy mode {}", e);
|
2022-04-25 12:28:28 +08:00
|
|
|
crate::common::make_privacy_mode_msg(
|
2022-07-31 22:31:17 +08:00
|
|
|
back_notification::PrivacyModeState::PrvOffFailed,
|
2022-04-25 12:28:28 +08:00
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#[cfg(not(windows))]
|
|
|
|
{
|
2022-07-31 22:41:24 +08:00
|
|
|
crate::common::make_privacy_mode_msg(back_notification::PrivacyModeState::PrvOffFailed)
|
2022-04-25 12:28:28 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(super) fn turn_on_privacy(_conn_id: i32) -> ResultType<bool> {
|
|
|
|
#[cfg(windows)]
|
|
|
|
{
|
|
|
|
let plugin_exitst = crate::ui::win_privacy::turn_on_privacy(_conn_id)?;
|
|
|
|
Ok(plugin_exitst)
|
|
|
|
}
|
|
|
|
#[cfg(not(windows))]
|
|
|
|
{
|
|
|
|
Ok(true)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-12-20 10:22:28 +08:00
|
|
|
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
|
|
struct ConnAuditResponse {
|
|
|
|
#[allow(dead_code)]
|
|
|
|
ret: bool,
|
|
|
|
action: String,
|
|
|
|
}
|
2022-12-20 16:20:42 +08:00
|
|
|
|
|
|
|
pub enum AlarmAuditType {
|
|
|
|
IpWhiltelist = 0,
|
|
|
|
ManyWrongPassword = 1,
|
|
|
|
FrequentAttempt = 2,
|
|
|
|
}
|
2022-12-23 10:36:18 +08:00
|
|
|
|
|
|
|
pub enum FileAuditType {
|
|
|
|
RemoteSend = 0,
|
|
|
|
RemoteReceive = 1,
|
|
|
|
}
|