Merge remote-tracking branch 'rd/master' into feat/x11/clipboard-file/init
Signed-off-by: ClSlaid <cailue@bupt.edu.cn>
This commit is contained in:
@@ -1,4 +1,7 @@
|
||||
use crate::input::{MOUSE_BUTTON_LEFT, MOUSE_TYPE_DOWN, MOUSE_TYPE_UP, MOUSE_TYPE_WHEEL};
|
||||
use async_trait::async_trait;
|
||||
use bytes::Bytes;
|
||||
use rdev::{Event, EventType::*, KeyCode};
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
use std::{collections::HashMap, sync::atomic::AtomicBool};
|
||||
use std::{
|
||||
@@ -10,10 +13,6 @@ use std::{
|
||||
},
|
||||
time::SystemTime,
|
||||
};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use bytes::Bytes;
|
||||
use rdev::{Event, EventType::*, KeyCode};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[cfg(not(feature = "flutter"))]
|
||||
@@ -62,6 +61,7 @@ pub struct Session<T: InvokeUiSession> {
|
||||
pub server_file_transfer_enabled: Arc<RwLock<bool>>,
|
||||
pub server_clipboard_enabled: Arc<RwLock<bool>>,
|
||||
pub last_change_display: Arc<Mutex<ChangeDisplayRecord>>,
|
||||
pub connection_round_state: Arc<Mutex<ConnectionRoundState>>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -79,6 +79,56 @@ pub struct ChangeDisplayRecord {
|
||||
height: i32,
|
||||
}
|
||||
|
||||
enum ConnectionState {
|
||||
Connecting,
|
||||
Connected,
|
||||
Disconnected,
|
||||
}
|
||||
|
||||
/// ConnectionRoundState is used to control the reconnecting logic.
|
||||
pub struct ConnectionRoundState {
|
||||
round: u32,
|
||||
state: ConnectionState,
|
||||
}
|
||||
|
||||
impl ConnectionRoundState {
|
||||
pub fn new_round(&mut self) -> u32 {
|
||||
self.round += 1;
|
||||
self.state = ConnectionState::Connecting;
|
||||
self.round
|
||||
}
|
||||
|
||||
pub fn set_connected(&mut self) {
|
||||
self.state = ConnectionState::Connected;
|
||||
}
|
||||
|
||||
pub fn is_round_gt(&self, round: u32) -> bool {
|
||||
if round == u32::MAX && self.round == 0 {
|
||||
true
|
||||
} else {
|
||||
round < self.round
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_disconnected(&mut self, round: u32) -> bool {
|
||||
if self.is_round_gt(round) {
|
||||
false
|
||||
} else {
|
||||
self.state = ConnectionState::Disconnected;
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ConnectionRoundState {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
round: 0,
|
||||
state: ConnectionState::Connecting,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ChangeDisplayRecord {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
@@ -181,7 +231,7 @@ impl<T: InvokeUiSession> Session<T> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn save_keyboard_mode(&mut self, value: String) {
|
||||
pub fn save_keyboard_mode(&self, value: String) {
|
||||
self.lc.write().unwrap().save_keyboard_mode(value);
|
||||
}
|
||||
|
||||
@@ -189,19 +239,19 @@ impl<T: InvokeUiSession> Session<T> {
|
||||
self.lc.read().unwrap().reverse_mouse_wheel.clone()
|
||||
}
|
||||
|
||||
pub fn save_reverse_mouse_wheel(&mut self, value: String) {
|
||||
pub fn save_reverse_mouse_wheel(&self, value: String) {
|
||||
self.lc.write().unwrap().save_reverse_mouse_wheel(value);
|
||||
}
|
||||
|
||||
pub fn save_view_style(&mut self, value: String) {
|
||||
pub fn save_view_style(&self, value: String) {
|
||||
self.lc.write().unwrap().save_view_style(value);
|
||||
}
|
||||
|
||||
pub fn save_scroll_style(&mut self, value: String) {
|
||||
pub fn save_scroll_style(&self, value: String) {
|
||||
self.lc.write().unwrap().save_scroll_style(value);
|
||||
}
|
||||
|
||||
pub fn save_flutter_option(&mut self, k: String, v: String) {
|
||||
pub fn save_flutter_option(&self, k: String, v: String) {
|
||||
self.lc.write().unwrap().save_ui_flutter(k, v);
|
||||
}
|
||||
|
||||
@@ -209,7 +259,7 @@ impl<T: InvokeUiSession> Session<T> {
|
||||
self.lc.read().unwrap().get_ui_flutter(&k)
|
||||
}
|
||||
|
||||
pub fn toggle_option(&mut self, name: String) {
|
||||
pub fn toggle_option(&self, name: String) {
|
||||
let msg = self.lc.write().unwrap().toggle_option(name.clone());
|
||||
#[cfg(not(feature = "flutter"))]
|
||||
if name == "enable-file-transfer" {
|
||||
@@ -252,7 +302,7 @@ impl<T: InvokeUiSession> Session<T> {
|
||||
self.send(Data::Message(msg));
|
||||
}
|
||||
|
||||
pub fn save_custom_image_quality(&mut self, custom_image_quality: i32) {
|
||||
pub fn save_custom_image_quality(&self, custom_image_quality: i32) {
|
||||
let msg = self
|
||||
.lc
|
||||
.write()
|
||||
@@ -261,14 +311,14 @@ impl<T: InvokeUiSession> Session<T> {
|
||||
self.send(Data::Message(msg));
|
||||
}
|
||||
|
||||
pub fn save_image_quality(&mut self, value: String) {
|
||||
pub fn save_image_quality(&self, value: String) {
|
||||
let msg = self.lc.write().unwrap().save_image_quality(value);
|
||||
if let Some(msg) = msg {
|
||||
self.send(Data::Message(msg));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_custom_fps(&mut self, custom_fps: i32) {
|
||||
pub fn set_custom_fps(&self, custom_fps: i32) {
|
||||
let msg = self.lc.write().unwrap().set_custom_fps(custom_fps);
|
||||
self.send(Data::Message(msg));
|
||||
}
|
||||
@@ -372,7 +422,7 @@ impl<T: InvokeUiSession> Session<T> {
|
||||
self.send(Data::RemovePortForward(port));
|
||||
}
|
||||
|
||||
pub fn add_port_forward(&mut self, port: i32, remote_host: String, remote_port: i32) {
|
||||
pub fn add_port_forward(&self, port: i32, remote_host: String, remote_port: i32) {
|
||||
let mut config = self.load_config();
|
||||
if config
|
||||
.port_forwards
|
||||
@@ -833,16 +883,30 @@ impl<T: InvokeUiSession> Session<T> {
|
||||
}
|
||||
|
||||
pub fn reconnect(&self, force_relay: bool) {
|
||||
self.send(Data::Close);
|
||||
// 1. If current session is connecting, do not reconnect.
|
||||
// 2. If the connection is established, send `Data::Close`.
|
||||
// 3. If the connection is disconnected, do nothing.
|
||||
let mut connection_round_state_lock = self.connection_round_state.lock().unwrap();
|
||||
if self.thread.lock().unwrap().is_some() {
|
||||
match connection_round_state_lock.state {
|
||||
ConnectionState::Connecting => return,
|
||||
ConnectionState::Connected => self.send(Data::Close),
|
||||
ConnectionState::Disconnected => {}
|
||||
}
|
||||
}
|
||||
let round = connection_round_state_lock.new_round();
|
||||
drop(connection_round_state_lock);
|
||||
|
||||
let cloned = self.clone();
|
||||
// override only if true
|
||||
if true == force_relay {
|
||||
cloned.lc.write().unwrap().force_relay = true;
|
||||
self.lc.write().unwrap().force_relay = true;
|
||||
}
|
||||
let mut lock = self.thread.lock().unwrap();
|
||||
lock.take().map(|t| t.join());
|
||||
// No need to join the previous thread, because it will exit automatically.
|
||||
// And the previous thread will not change important states.
|
||||
*lock = Some(std::thread::spawn(move || {
|
||||
io_loop(cloned);
|
||||
io_loop(cloned, round);
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -1151,11 +1215,11 @@ impl<T: InvokeUiSession> Interface for Session<T> {
|
||||
self.ui_handler.msgbox(msgtype, title, text, link, retry);
|
||||
}
|
||||
|
||||
fn handle_login_error(&mut self, err: &str) -> bool {
|
||||
fn handle_login_error(&self, err: &str) -> bool {
|
||||
handle_login_error(self.lc.clone(), err, self)
|
||||
}
|
||||
|
||||
fn handle_peer_info(&mut self, mut pi: PeerInfo) {
|
||||
fn handle_peer_info(&self, mut pi: PeerInfo) {
|
||||
log::debug!("handle_peer_info :{:?}", pi);
|
||||
pi.username = self.lc.read().unwrap().get_username(&pi);
|
||||
if pi.current_display as usize >= pi.displays.len() {
|
||||
@@ -1217,12 +1281,12 @@ impl<T: InvokeUiSession> Interface for Session<T> {
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_hash(&mut self, pass: &str, hash: Hash, peer: &mut Stream) {
|
||||
async fn handle_hash(&self, pass: &str, hash: Hash, peer: &mut Stream) {
|
||||
handle_hash(self.lc.clone(), pass, hash, self, peer).await;
|
||||
}
|
||||
|
||||
async fn handle_login_from_ui(
|
||||
&mut self,
|
||||
&self,
|
||||
os_username: String,
|
||||
os_password: String,
|
||||
password: String,
|
||||
@@ -1240,7 +1304,7 @@ impl<T: InvokeUiSession> Interface for Session<T> {
|
||||
.await;
|
||||
}
|
||||
|
||||
async fn handle_test_delay(&mut self, t: TestDelay, peer: &mut Stream) {
|
||||
async fn handle_test_delay(&self, t: TestDelay, peer: &mut Stream) {
|
||||
if !t.from_client {
|
||||
self.update_quality_status(QualityStatus {
|
||||
delay: Some(t.last_delay as _),
|
||||
@@ -1283,7 +1347,7 @@ impl<T: InvokeUiSession> Session<T> {
|
||||
}
|
||||
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
pub async fn io_loop<T: InvokeUiSession>(handler: Session<T>) {
|
||||
pub async fn io_loop<T: InvokeUiSession>(handler: Session<T>, round: u32) {
|
||||
// It is ok to call this function multiple times.
|
||||
#[cfg(any(target_os = "windows", target_os = "linux"))]
|
||||
if !handler.is_file_transfer() && !handler.is_port_forward() {
|
||||
@@ -1402,7 +1466,7 @@ pub async fn io_loop<T: InvokeUiSession>(handler: Session<T>) {
|
||||
frame_count,
|
||||
decode_fps,
|
||||
);
|
||||
remote.io_loop(&key, &token).await;
|
||||
remote.io_loop(&key, &token, round).await;
|
||||
remote.sync_jobs_status_to_local().await;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user