…lines 1–81 unchanged (81 lines)
82#[derive(Default)]
83struct ParsedPeerInfo {
84 platform: String,
85 is_installed: bool,
86 idd_impl: String,
87 support_view_camera: bool,
88 support_terminal: bool,
89}
90
91impl ParsedPeerInfo {
92 fn is_support_virtual_display(&self) -> bool {
93 self.is_installed
94 && self.platform == "Windows"
…lines 95–128 unchanged (34 lines)
129 }
130
131 pub async fn io_loop(&mut self, key: &str, token: &str, round: u32) {
132 #[cfg(target_os = "windows")]
133 let _file_clip_context_holder = {
134 // `is_port_forward()` will not reach here, but we still check it for clarity.
135 if self.handler.is_default() {
136 // It is ok to call this function multiple times.
137 ContextSend::enable(true);
138 Some(crate::SimpleCallOnReturn {
139 b: true,
140 f: Box::new(|| {
141 // No need to call `enable(false)` for sciter version, because each client of sciter version is a new process.
142 // It's better to check if the peers are windows(support file copy&paste), but it's not necessary.
143 #[cfg(feature = "flutter")]
144 if !crate::flutter::sessions::has_sessions_running(ConnType::DEFAULT_CONN) {
145 ContextSend::enable(false);
146 };
147 }),
148 })
149 } else {
150 None
151 }
152 };
153
154 let mut last_recv_time = Instant::now();
155 let mut received = false;
156 let conn_type = if self.handler.is_file_transfer() {
157 ConnType::FILE_TRANSFER
158 } else if self.handler.is_view_camera() {
159 ConnType::VIEW_CAMERA
160 } else if self.handler.is_terminal() {
161 ConnType::TERMINAL
162 } else {
163 ConnType::default()
164 };
165
166 match Client::start(
167 &self.handler.get_id(),
168 key,
…lines 169–191 unchanged (23 lines)
192 #[cfg(any(target_os = "windows", feature = "unix-file-copy-paste"))]
193 let (_tx_holder, rx) = mpsc::unbounded_channel();
194 #[cfg(any(target_os = "windows", feature = "unix-file-copy-paste"))]
195 let mut rx_clip_client_holder = (Arc::new(TokioMutex::new(rx)), None);
196 #[cfg(any(target_os = "windows", feature = "unix-file-copy-paste"))]
197 {
198 if self.handler.is_default() {
199 (self.client_conn_id, rx_clip_client_holder.0) =
200 clipboard::get_rx_cliprdr_client(&self.handler.get_id());
201 log::debug!("get cliprdr client for conn_id {}", self.client_conn_id);
202 let client_conn_id = self.client_conn_id;
203 rx_clip_client_holder.1 = Some(crate::SimpleCallOnReturn {
204 b: true,
205 f: Box::new(move || {
206 clipboard::remove_channel_by_conn_id(client_conn_id);
207 }),
208 });
209 };
210 }
211 #[cfg(any(target_os = "windows", feature = "unix-file-copy-paste"))]
212 let mut rx_clip_client = rx_clip_client_holder.0.lock().await;
213
214 let mut status_timer =
215 crate::rustdesk_interval(time::interval(Duration::new(1, 0)));
…lines 216–330 unchanged (115 lines)
331 .connection_round_state
332 .lock()
333 .unwrap()
334 .set_disconnected(round);
335
336 #[cfg(not(target_os = "ios"))]
337 if self.handler.is_default() && _set_disconnected_ok {
338 Client::try_stop_clipboard();
339 }
340
341 #[cfg(any(target_os = "windows", feature = "unix-file-copy-paste"))]
342 if self.handler.is_default() && _set_disconnected_ok {
343 crate::clipboard::try_empty_clipboard_files(ClipboardSide::Client, self.client_conn_id);
344 }
345 }
346
347 #[cfg(any(target_os = "windows", feature = "unix-file-copy-paste"))]
348 async fn handle_local_clipboard_msg(
349 &self,
350 peer: &mut Stream,
…lines 351–430 unchanged (80 lines)
431 }
432 }
433
434 // Start a voice call recorder, records audio and send to remote
435 fn start_voice_call(&mut self) -> Option<std::sync::mpsc::Sender<()>> {
436 if self.handler.is_file_transfer()
437 || self.handler.is_port_forward()
438 || self.handler.is_terminal()
439 {
440 return None;
441 }
442 // iOS does not have this server.
443 #[cfg(not(any(target_os = "ios")))]
444 {
445 // NOTE:
446 // The client server and --server both use the same sound input device.
447 // It's better to distinguish the server side and client side.
…lines 448–1225 unchanged (778 lines)
1226 } else {
1227 self.handler.on_error("view_camera_unsupported_tip");
1228 }
1229 return false;
1230 }
1231
1232 fn check_terminal_support(&self, peer_version: &str) -> bool {
1233 if self.peer_info.support_terminal {
1234 return true;
1235 }
1236 if hbb_common::get_version_number(&peer_version) < hbb_common::get_version_number("1.4.1") {
1237 self.handler.msgbox(
1238 "error",
1239 "Remote terminal not supported",
1240 "Remote terminal is not supported by the remote side. Please upgrade to version 1.4.1 or higher.",
1241 "",
1242 );
1243 } else {
1244 self.handler
1245 .on_error("Remote terminal is not supported by the remote side");
1246 }
1247 return false;
1248 }
1249
1250 async fn handle_msg_from_peer(&mut self, data: &[u8], peer: &mut Stream) -> bool {
1251 if let Ok(msg_in) = Message::parse_from_bytes(&data) {
1252 match msg_in.union {
1253 Some(message::Union::VideoFrame(vf)) => {
1254 if !self.first_frame {
…lines 1255–1303 unchanged (49 lines)
1304 if self.handler.is_view_camera() {
1305 if !self.check_view_camera_support(&peer_version, &peer_platform) {
1306 self.handler.lc.write().unwrap().handle_peer_info(&pi);
1307 return false;
1308 }
1309 }
1310 if self.handler.is_terminal() {
1311 if !self.check_terminal_support(&peer_version) {
1312 self.handler.lc.write().unwrap().handle_peer_info(&pi);
1313 return false;
1314 }
1315 }
1316 self.handler.handle_peer_info(pi);
1317 #[cfg(all(target_os = "windows", not(feature = "flutter")))]
1318 self.check_clipboard_file_context();
1319 if self.handler.is_default() {
1320 #[cfg(feature = "flutter")]
1321 #[cfg(not(target_os = "ios"))]
1322 let rx = Client::try_start_clipboard(None);
1323 #[cfg(not(feature = "flutter"))]
1324 #[cfg(not(any(target_os = "android", target_os = "ios")))]
1325 let rx = Client::try_start_clipboard(Some(
1326 crate::client::ClientClipboardContext {
1327 cfg: self.handler.get_permission_config(),
1328 tx: self.sender.clone(),
1329 #[cfg(feature = "unix-file-copy-paste")]
1330 is_file_supported: crate::is_support_file_copy_paste(
1331 &peer_version,
1332 ),
1333 },
1334 ));
1335 // To make sure current text clipboard data is updated.
1336 #[cfg(not(target_os = "ios"))]
1337 if let Some(mut rx) = rx {
1338 timeout(CLIPBOARD_INTERVAL, rx.recv()).await.ok();
1339 }
1340
1341 #[cfg(not(any(target_os = "android", target_os = "ios")))]
1342 if self.handler.lc.read().unwrap().sync_init_clipboard.v {
1343 if let Some(msg_out) = crate::clipboard::get_current_clipboard_msg(
1344 &peer_version,
1345 &peer_platform,
1346 crate::clipboard::ClipboardSide::Client,
1347 ) {
1348 let sender = self.sender.clone();
1349 let permission_config = self.handler.get_permission_config();
1350 tokio::spawn(async move {
1351 if permission_config.is_text_clipboard_required() {
1352 sender.send(Data::Message(msg_out)).ok();
1353 }
1354 });
1355 }
1356 }
1357 // to-do: Android, is `sync_init_clipboard` really needed?
1358 // https://github.com/rustdesk/rustdesk/discussions/9010
1359
1360 #[cfg(feature = "flutter")]
1361 #[cfg(not(target_os = "ios"))]
1362 crate::flutter::update_text_clipboard_required();
1363
1364 #[cfg(all(feature = "flutter", feature = "unix-file-copy-paste"))]
1365 crate::flutter::update_file_clipboard_required();
1366
1367 // on connection established client
1368 #[cfg(all(feature = "flutter", feature = "plugin_framework"))]
1369 #[cfg(not(any(target_os = "android", target_os = "ios")))]
1370 crate::plugin::handle_listen_event(
1371 crate::plugin::EVENT_ON_CONN_CLIENT.to_owned(),
1372 self.handler.get_id(),
1373 );
1374 }
1375
1376 if self.handler.is_file_transfer() {
1377 self.handler.load_last_jobs();
1378 }
1379
1380 self.is_connected = true;
…lines 1381–1677 unchanged (297 lines)
1678 try_empty_clipboard_files(
1679 ClipboardSide::Client,
1680 self.client_conn_id,
1681 );
1682 }
1683 }
1684 Ok(Permission::Restart) => {
1685 self.handler.set_permission("restart", p.enabled);
1686 }
1687 Ok(Permission::Recording) => {
1688 self.handler.lc.write().unwrap().record_permission = p.enabled;
1689 self.update_record_state();
1690 self.handler.set_permission("recording", p.enabled);
…lines 1691–1936 unchanged (246 lines)
1937 }
1938 Some(message::Union::ScreenshotResponse(response)) => {
1939 crate::client::screenshot::set_screenshot(response.data);
1940 self.handler
1941 .handle_screenshot_resp(response.sid, response.msg);
1942 }
1943 Some(message::Union::TerminalResponse(response)) => {
1944 use hbb_common::message_proto::terminal_response::Union;
1945 if let Some(Union::Opened(opened)) = &response.union {
1946 if opened.success && !opened.service_id.is_empty() {
1947 self.handler.lc.write().unwrap().set_option(
1948 "terminal-service-id".to_owned(),
1949 opened.service_id.clone(),
1950 );
1951 }
1952 }
1953 self.handler.handle_terminal_response(response);
1954 }
1955 _ => {}
1956 }
1957 }
1958 true
1959 }
1960
1961 fn set_peer_info(&mut self, pi: &PeerInfo) {
1962 self.peer_info.platform = pi.platform.clone();
1963
1964 // Check features field for terminal support
1965 if let Some(features) = pi.features.as_ref() {
1966 self.peer_info.support_terminal = features.terminal;
1967 }
1968
1969 if let Ok(platform_additions) =
1970 serde_json::from_str::<HashMap<String, serde_json::Value>>(&pi.platform_additions)
1971 {
1972 self.peer_info.is_installed = platform_additions
1973 .get("is_installed")
…lines 1974–2377 unchanged (404 lines)