mirror of
https://github.com/weyne85/rustdesk.git
synced 2025-10-29 17:00:05 +00:00
Merge pull request #3902 from fufesou/feat/linux_virtual_display
Feat/linux virtual display (headless linux)
This commit is contained in:
178
src/client.rs
178
src/client.rs
@@ -1578,7 +1578,12 @@ impl LoginConfigHandler {
|
||||
}
|
||||
|
||||
/// Create a [`Message`] for login.
|
||||
fn create_login_msg(&self, password: Vec<u8>) -> Message {
|
||||
fn create_login_msg(
|
||||
&self,
|
||||
os_username: String,
|
||||
os_password: String,
|
||||
password: Vec<u8>,
|
||||
) -> Message {
|
||||
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||
let my_id = Config::get_id_or(crate::common::DEVICE_ID.lock().unwrap().clone());
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
@@ -1591,6 +1596,12 @@ impl LoginConfigHandler {
|
||||
option: self.get_option_message(true).into(),
|
||||
session_id: self.session_id,
|
||||
version: crate::VERSION.to_string(),
|
||||
os_login: Some(OSLogin {
|
||||
username: os_username,
|
||||
password: os_password,
|
||||
..Default::default()
|
||||
})
|
||||
.into(),
|
||||
..Default::default()
|
||||
};
|
||||
match self.conn_type {
|
||||
@@ -1888,6 +1899,71 @@ fn _input_os_password(p: String, activate: bool, interface: impl Interface) {
|
||||
interface.send(Data::Message(msg_out));
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct LoginErrorMsgBox {
|
||||
msgtype: &'static str,
|
||||
title: &'static str,
|
||||
text: &'static str,
|
||||
link: &'static str,
|
||||
try_again: bool,
|
||||
}
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref LOGIN_ERROR_MAP: Arc<HashMap<&'static str, LoginErrorMsgBox>> = {
|
||||
use hbb_common::config::LINK_HEADLESS_LINUX_SUPPORT;
|
||||
let map = HashMap::from([(crate::server::LOGIN_MSG_DESKTOP_SESSION_NOT_READY, LoginErrorMsgBox{
|
||||
msgtype: "session-login",
|
||||
title: "",
|
||||
text: "",
|
||||
link: "",
|
||||
try_again: true,
|
||||
}), (crate::server::LOGIN_MSG_DESKTOP_XSESSION_FAILED, LoginErrorMsgBox{
|
||||
msgtype: "session-re-login",
|
||||
title: "xsession_failed_title_tip",
|
||||
text: "xsession_failed_text_tip",
|
||||
link: "",
|
||||
try_again: true,
|
||||
}), (crate::server::LOGIN_MSG_DESKTOP_SESSION_ANOTHER_USER, LoginErrorMsgBox{
|
||||
msgtype: "info-nocancel",
|
||||
title: "another_user_login_title_tip",
|
||||
text: "another_user_login_text_tip",
|
||||
link: "",
|
||||
try_again: false,
|
||||
}), (crate::server::LOGIN_MSG_DESKTOP_XORG_NOT_FOUND, LoginErrorMsgBox{
|
||||
msgtype: "info-nocancel",
|
||||
title: "xorg_not_found_title_tip",
|
||||
text: "xorg_not_found_text_tip",
|
||||
link: LINK_HEADLESS_LINUX_SUPPORT,
|
||||
try_again: true,
|
||||
}), (crate::server::LOGIN_MSG_DESKTOP_NO_DESKTOP, LoginErrorMsgBox{
|
||||
msgtype: "info-nocancel",
|
||||
title: "no_desktop_title_tip",
|
||||
text: "no_desktop_text_tip",
|
||||
link: LINK_HEADLESS_LINUX_SUPPORT,
|
||||
try_again: true,
|
||||
}), (crate::server::LOGIN_MSG_DESKTOP_SESSION_NOT_READY_PASSWORD_EMPTY, LoginErrorMsgBox{
|
||||
msgtype: "session-login-password",
|
||||
title: "session_not_ready_no_password_title_tip",
|
||||
text: "session_not_ready_no_password_text_tip",
|
||||
link: "",
|
||||
try_again: true,
|
||||
}), (crate::server::LOGIN_MSG_DESKTOP_SESSION_NOT_READY_PASSWORD_WRONG, LoginErrorMsgBox{
|
||||
msgtype: "session-login-re-password",
|
||||
title: "session_not_ready_wrong_password_title_tip",
|
||||
text: "session_not_ready_wrong_password_text_tip",
|
||||
link: "",
|
||||
try_again: true,
|
||||
}), (crate::server::LOGIN_MSG_NO_PASSWORD_ACCESS, LoginErrorMsgBox{
|
||||
msgtype: "wait-remote-accept-nook",
|
||||
title: "Prompt",
|
||||
text: "Please wait for the remote side to accept your session request...",
|
||||
link: "",
|
||||
try_again: true,
|
||||
})]);
|
||||
Arc::new(map)
|
||||
};
|
||||
}
|
||||
|
||||
/// Handle login error.
|
||||
/// Return true if the password is wrong, return false if there's an actual error.
|
||||
pub fn handle_login_error(
|
||||
@@ -1895,19 +1971,27 @@ pub fn handle_login_error(
|
||||
err: &str,
|
||||
interface: &impl Interface,
|
||||
) -> bool {
|
||||
if err == "Wrong Password" {
|
||||
if err == crate::server::LOGIN_MSG_PASSWORD_EMPTY {
|
||||
lc.write().unwrap().password = Default::default();
|
||||
interface.msgbox("input-password", "Password Required", "", "");
|
||||
true
|
||||
} else if err == crate::server::LOGIN_MSG_PASSWORD_WRONG {
|
||||
lc.write().unwrap().password = Default::default();
|
||||
interface.msgbox("re-input-password", err, "Do you want to enter again?", "");
|
||||
true
|
||||
} else if err == "No Password Access" {
|
||||
lc.write().unwrap().password = Default::default();
|
||||
interface.msgbox(
|
||||
"wait-remote-accept-nook",
|
||||
"Prompt",
|
||||
"Please wait for the remote side to accept your session request...",
|
||||
"",
|
||||
);
|
||||
true
|
||||
} else if LOGIN_ERROR_MAP.contains_key(err) {
|
||||
if let Some(msgbox_info) = LOGIN_ERROR_MAP.get(err) {
|
||||
interface.msgbox(
|
||||
msgbox_info.msgtype,
|
||||
msgbox_info.title,
|
||||
msgbox_info.text,
|
||||
msgbox_info.link,
|
||||
);
|
||||
msgbox_info.try_again
|
||||
} else {
|
||||
// unreachable!
|
||||
false
|
||||
}
|
||||
} else {
|
||||
if err.contains(SCRAP_X11_REQUIRED) {
|
||||
interface.msgbox("error", "Login Error", err, SCRAP_X11_REF_URL);
|
||||
@@ -1955,16 +2039,21 @@ pub async fn handle_hash(
|
||||
if password.is_empty() {
|
||||
password = lc.read().unwrap().config.password.clone();
|
||||
}
|
||||
if password.is_empty() {
|
||||
let password = if password.is_empty() {
|
||||
// login without password, the remote side can click accept
|
||||
send_login(lc.clone(), Vec::new(), peer).await;
|
||||
interface.msgbox("input-password", "Password Required", "", "");
|
||||
Vec::new()
|
||||
} else {
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(&password);
|
||||
hasher.update(&hash.challenge);
|
||||
send_login(lc.clone(), hasher.finalize()[..].into(), peer).await;
|
||||
}
|
||||
hasher.finalize()[..].into()
|
||||
};
|
||||
|
||||
let os_username = lc.read().unwrap().get_option("os-username");
|
||||
let os_password = lc.read().unwrap().get_option("os-password");
|
||||
|
||||
send_login(lc.clone(), os_username, os_password, password, peer).await;
|
||||
lc.write().unwrap().hash = hash;
|
||||
}
|
||||
|
||||
@@ -1973,10 +2062,21 @@ pub async fn handle_hash(
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `lc` - Login config.
|
||||
/// * `os_username` - OS username.
|
||||
/// * `os_password` - OS password.
|
||||
/// * `password` - Password.
|
||||
/// * `peer` - [`Stream`] for communicating with peer.
|
||||
async fn send_login(lc: Arc<RwLock<LoginConfigHandler>>, password: Vec<u8>, peer: &mut Stream) {
|
||||
let msg_out = lc.read().unwrap().create_login_msg(password);
|
||||
async fn send_login(
|
||||
lc: Arc<RwLock<LoginConfigHandler>>,
|
||||
os_username: String,
|
||||
os_password: String,
|
||||
password: Vec<u8>,
|
||||
peer: &mut Stream,
|
||||
) {
|
||||
let msg_out = lc
|
||||
.read()
|
||||
.unwrap()
|
||||
.create_login_msg(os_username, os_password, password);
|
||||
allow_err!(peer.send(&msg_out).await);
|
||||
}
|
||||
|
||||
@@ -1985,25 +2085,40 @@ async fn send_login(lc: Arc<RwLock<LoginConfigHandler>>, password: Vec<u8>, peer
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `lc` - Login config.
|
||||
/// * `os_username` - OS username.
|
||||
/// * `os_password` - OS password.
|
||||
/// * `password` - Password.
|
||||
/// * `remember` - Whether to remember password.
|
||||
/// * `peer` - [`Stream`] for communicating with peer.
|
||||
pub async fn handle_login_from_ui(
|
||||
lc: Arc<RwLock<LoginConfigHandler>>,
|
||||
os_username: String,
|
||||
os_password: String,
|
||||
password: String,
|
||||
remember: bool,
|
||||
peer: &mut Stream,
|
||||
) {
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(password);
|
||||
hasher.update(&lc.read().unwrap().hash.salt);
|
||||
let res = hasher.finalize();
|
||||
lc.write().unwrap().remember = remember;
|
||||
lc.write().unwrap().password = res[..].into();
|
||||
let mut hash_password = if password.is_empty() {
|
||||
let mut password2 = lc.read().unwrap().password.clone();
|
||||
if password2.is_empty() {
|
||||
password2 = lc.read().unwrap().config.password.clone();
|
||||
}
|
||||
password2
|
||||
} else {
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(password);
|
||||
hasher.update(&lc.read().unwrap().hash.salt);
|
||||
let res = hasher.finalize();
|
||||
lc.write().unwrap().remember = remember;
|
||||
lc.write().unwrap().password = res[..].into();
|
||||
res[..].into()
|
||||
};
|
||||
let mut hasher2 = Sha256::new();
|
||||
hasher2.update(&res[..]);
|
||||
hasher2.update(&hash_password[..]);
|
||||
hasher2.update(&lc.read().unwrap().hash.challenge);
|
||||
send_login(lc.clone(), hasher2.finalize()[..].into(), peer).await;
|
||||
hash_password = hasher2.finalize()[..].to_vec();
|
||||
|
||||
send_login(lc.clone(), os_username, os_password, hash_password, peer).await;
|
||||
}
|
||||
|
||||
async fn send_switch_login_request(
|
||||
@@ -2017,7 +2132,7 @@ async fn send_switch_login_request(
|
||||
lr: hbb_common::protobuf::MessageField::some(
|
||||
lc.read()
|
||||
.unwrap()
|
||||
.create_login_msg(vec![])
|
||||
.create_login_msg("".to_owned(), "".to_owned(), vec![])
|
||||
.login_request()
|
||||
.to_owned(),
|
||||
),
|
||||
@@ -2038,7 +2153,14 @@ pub trait Interface: Send + Clone + 'static + Sized {
|
||||
self.msgbox("error", "Error", err, "");
|
||||
}
|
||||
async fn handle_hash(&mut self, pass: &str, hash: Hash, peer: &mut Stream);
|
||||
async fn handle_login_from_ui(&mut self, password: String, remember: bool, peer: &mut Stream);
|
||||
async fn handle_login_from_ui(
|
||||
&mut self,
|
||||
os_username: String,
|
||||
os_password: String,
|
||||
password: String,
|
||||
remember: bool,
|
||||
peer: &mut Stream,
|
||||
);
|
||||
async fn handle_test_delay(&mut self, t: TestDelay, peer: &mut Stream);
|
||||
|
||||
fn get_login_config_handler(&self) -> Arc<RwLock<LoginConfigHandler>>;
|
||||
@@ -2058,7 +2180,7 @@ pub trait Interface: Send + Clone + 'static + Sized {
|
||||
#[derive(Clone)]
|
||||
pub enum Data {
|
||||
Close,
|
||||
Login((String, bool)),
|
||||
Login((String, String, String, bool)),
|
||||
Message(Message),
|
||||
SendFiles((i32, String, String, i32, bool, bool)),
|
||||
RemoveDirAll((i32, String, bool, bool)),
|
||||
|
||||
Reference in New Issue
Block a user