…lines 1–165 unchanged (165 lines)
166#[derive(Debug, Copy, Clone, Eq, PartialEq)]
167pub enum AuthConnType {
168 Remote,
169 FileTransfer,
170 PortForward,
171 ViewCamera,
172 Terminal,
173}
174
175pub struct Connection {
176 inner: ConnInner,
177 display_idx: usize,
178 stream: super::Stream,
179 server: super::ServerPtrWeak,
180 hash: Hash,
181 read_jobs: Vec<fs::TransferJob>,
182 timer: crate::RustDeskInterval,
183 file_timer: crate::RustDeskInterval,
184 file_transfer: Option<(String, bool)>,
185 view_camera: bool,
186 terminal: bool,
187 port_forward_socket: Option<Framed<TcpStream, BytesCodec>>,
188 port_forward_address: String,
189 tx_to_cm: mpsc::UnboundedSender<ipc::Data>,
190 authorized: bool,
191 require_2fa: Option<totp_rs::TOTP>,
192 keyboard: bool,
…lines 193–248 unchanged (56 lines)
249 multi_ui_session: bool,
250 tx_from_authed: mpsc::UnboundedSender<ipc::Data>,
251 printer_data: Vec<(Instant, String, Vec<u8>)>,
252 // For post requests that need to be sent sequentially.
253 // eg. post_conn_audit
254 tx_post_seq: mpsc::UnboundedSender<(String, Value)>,
255 terminal_service_id: String,
256 terminal_persistent: bool,
257 terminal_generic_service: Option<Box<GenericService>>,
258}
259
260impl ConnInner {
261 pub fn new(id: i32, tx: Option<Sender>, tx_video: Option<Sender>) -> Self {
262 Self { id, tx, tx_video }
263 }
…lines 264–348 unchanged (85 lines)
349 hash,
350 read_jobs: Vec::new(),
351 timer: crate::rustdesk_interval(time::interval(SEC30)),
352 file_timer: crate::rustdesk_interval(time::interval(SEC30)),
353 file_transfer: None,
354 view_camera: false,
355 terminal: false,
356 port_forward_socket: None,
357 port_forward_address: "".to_owned(),
358 tx_to_cm,
359 authorized: false,
360 keyboard: Connection::permission("enable-keyboard"),
361 clipboard: Connection::permission("enable-clipboard"),
…lines 362–412 unchanged (51 lines)
413 delayed_read_dir: None,
414 #[cfg(target_os = "macos")]
415 retina: Retina::default(),
416 tx_from_authed,
417 printer_data: Vec::new(),
418 tx_post_seq,
419 terminal_service_id: "".to_owned(),
420 terminal_persistent: false,
421 terminal_generic_service: None,
422 };
423 let addr = hbb_common::try_into_v4(addr);
424 if !conn.on_open(addr).await {
425 conn.closed = true;
426 // sleep to ensure msg got received.
427 sleep(1.).await;
…lines 428–455 unchanged (28 lines)
456 }
457 let mut test_delay_timer =
458 crate::rustdesk_interval(time::interval_at(Instant::now(), TEST_DELAY_TIMEOUT));
459 let mut last_recv_time = Instant::now();
460
461 conn.stream.set_send_timeout(
462 if conn.file_transfer.is_some() || conn.port_forward_socket.is_some() || conn.terminal {
463 SEND_TIMEOUT_OTHER
464 } else {
465 SEND_TIMEOUT_VIDEO
466 },
467 );
468
469 #[cfg(not(any(target_os = "android", target_os = "ios")))]
470 std::thread::spawn(move || Self::handle_input(_rx_input, tx_cloned));
…lines 471–1258 unchanged (788 lines)
1259 let (conn_type, auth_conn_type) = if self.file_transfer.is_some() {
1260 (1, AuthConnType::FileTransfer)
1261 } else if self.port_forward_socket.is_some() {
1262 (2, AuthConnType::PortForward)
1263 } else if self.view_camera {
1264 (3, AuthConnType::ViewCamera)
1265 } else if self.terminal {
1266 (4, AuthConnType::Terminal)
1267 } else {
1268 (0, AuthConnType::Remote)
1269 };
1270 self.authed_conn_id = Some(self::raii::AuthedConnID::new(
1271 self.inner.id(),
1272 auth_conn_type,
1273 self.session_key(),
…lines 1274–1368 unchanged (95 lines)
1369 res.set_peer_info(pi);
1370 msg_out.set_login_response(res);
1371 self.send(msg_out).await;
1372 return;
1373 }
1374 #[cfg(target_os = "linux")]
1375 if self.is_remote() {
1376 let mut msg = "".to_string();
1377 if crate::platform::linux::is_login_screen_wayland() {
1378 msg = crate::client::LOGIN_SCREEN_WAYLAND.to_owned()
1379 } else {
1380 let dtype = crate::platform::linux::get_display_server();
1381 if dtype != crate::platform::linux::DISPLAY_SERVER_X11
1382 && dtype != crate::platform::linux::DISPLAY_SERVER_WAYLAND
1383 {
1384 msg = format!(
1385 "Unsupported display server type \"{}\", x11 or wayland expected",
1386 dtype
1387 );
1388 }
1389 }
1390 if !msg.is_empty() {
1391 res.set_error(msg);
1392 let mut msg_out = Message::new();
1393 msg_out.set_login_response(res);
1394 self.send(msg_out).await;
1395 return;
1396 }
1397 }
1398 #[allow(unused_mut)]
1399 let mut sas_enabled = false;
1400 #[cfg(windows)]
1401 if crate::platform::is_root() {
1402 sas_enabled = true;
1403 }
…lines 1404–1415 unchanged (12 lines)
1416 .insert(self.lr.my_id.clone(), self.tx_input.clone());
1417
1418 pi.username = username;
1419 pi.sas_enabled = sas_enabled;
1420 pi.features = Some(Features {
1421 privacy_mode: privacy_mode::is_privacy_mode_supported(),
1422 #[cfg(not(any(target_os = "android", target_os = "ios")))]
1423 terminal: true, // Terminal feature is supported on desktop only
1424 ..Default::default()
1425 })
1426 .into();
1427
1428 let mut sub_service = false;
1429 #[allow(unused_mut)]
1430 let mut wait_session_id_confirm = false;
1431 #[cfg(windows)]
1432 self.handle_windows_specific_session(&mut pi, &mut wait_session_id_confirm);
1433 if self.file_transfer.is_some() || self.terminal {
1434 res.set_peer_info(pi);
1435 } else if self.view_camera {
1436 let supported_encoding = scrap::codec::Encoder::supported_encoding();
1437 self.last_supported_encoding = Some(supported_encoding.clone());
1438 log::info!("peer info supported_encoding: {:?}", supported_encoding);
1439 pi.encoding = Some(supported_encoding).into();
1440
1441 pi.displays = camera::Cameras::all_info().unwrap_or(Vec::new());
…lines 1442–1518 unchanged (77 lines)
1519 };
1520 if !wait_session_id_confirm {
1521 self.read_dir(dir, show_hidden);
1522 } else {
1523 self.delayed_read_dir = Some((dir.to_owned(), show_hidden));
1524 }
1525 } else if self.terminal {
1526 self.keyboard = false;
1527 #[cfg(not(any(target_os = "android", target_os = "ios")))]
1528 self.init_terminal_service().await;
1529 } else if self.view_camera {
1530 if !wait_session_id_confirm {
1531 self.try_sub_camera_displays();
1532 }
1533 self.keyboard = false;
1534 self.send_permission(Permission::Keyboard, false).await;
1535 } else if sub_service {
…lines 1536–1544 unchanged (9 lines)
1545
1546 s.try_add_primary_camera_service();
1547 s.add_camera_connection(self.inner.clone());
1548 }
1549 }
1550
1551 #[inline]
1552 fn is_remote(&self) -> bool {
1553 self.file_transfer.is_none()
1554 && self.port_forward_socket.is_none()
1555 && !self.view_camera
1556 && !self.terminal
1557 }
1558
1559 fn try_sub_monitor_services(&mut self) {
1560 let is_remote = self.is_remote();
1561 if is_remote && !self.services_subed {
1562 self.services_subed = true;
1563 if let Some(s) = self.server.upgrade() {
1564 let mut noperms = Vec::new();
1565 if !self.peer_keyboard_enabled() && !self.show_remote_cursor {
1566 noperms.push(NAME_CURSOR);
…lines 1567–1671 unchanged (105 lines)
1672
1673 fn try_start_cm(&mut self, peer_id: String, name: String, authorized: bool) {
1674 self.send_to_cm(ipc::Data::Login {
1675 id: self.inner.id(),
1676 is_file_transfer: self.file_transfer.is_some(),
1677 is_view_camera: self.view_camera,
1678 is_terminal: self.terminal,
1679 port_forward: self.port_forward_address.clone(),
1680 peer_id,
1681 name,
1682 authorized,
1683 keyboard: self.keyboard,
1684 clipboard: self.clipboard,
…lines 1685–1923 unchanged (239 lines)
1924 .await;
1925 sleep(1.).await;
1926 return false;
1927 }
1928 self.view_camera = true;
1929 }
1930 Some(login_request::Union::Terminal(terminal)) => {
1931 if !Connection::permission(keys::OPTION_ENABLE_TERMINAL) {
1932 self.send_login_error("No permission of terminal").await;
1933 sleep(1.).await;
1934 return false;
1935 }
1936 self.terminal = true;
1937 if let Some(o) = self.options_in_login.as_ref() {
1938 self.terminal_persistent =
1939 o.terminal_persistent.enum_value() == Ok(BoolOption::Yes);
1940 }
1941 self.terminal_service_id = terminal.service_id;
1942 }
1943 Some(login_request::Union::PortForward(mut pf)) => {
1944 if !Connection::permission("enable-tunnel") {
1945 self.send_login_error("No permission of IP tunneling").await;
1946 sleep(1.).await;
1947 return false;
1948 }
…lines 1949–2825 unchanged (877 lines)
2826 if self.file_transfer.is_some() {
2827 if let Some((dir, show_hidden)) = self.delayed_read_dir.take() {
2828 self.read_dir(&dir, show_hidden);
2829 }
2830 } else if self.view_camera {
2831 self.try_sub_camera_displays();
2832 } else if !self.terminal {
2833 self.try_sub_monitor_services();
2834 }
2835 }
2836 }
2837 Some(misc::Union::MessageQuery(mq)) => {
2838 if let Some(msg_out) = video_service::make_display_changed_msg(
2839 mq.switch_display as _,
2840 None,
…lines 2841–2877 unchanged (37 lines)
2878 request.sid.clone(),
2879 tx,
2880 );
2881 self.refresh_video_display(Some(request.display as usize));
2882 }
2883 }
2884 Some(message::Union::TerminalAction(action)) => {
2885 #[cfg(not(any(target_os = "android", target_os = "ios")))]
2886 allow_err!(self.handle_terminal_action(action).await);
2887 #[cfg(any(target_os = "android", target_os = "ios"))]
2888 log::warn!("Terminal action received but not supported on this platform");
2889 }
2890 _ => {}
2891 }
2892 }
2893 true
2894 }
2895
…lines 2896–3411 unchanged (516 lines)
3412 if let Some(tx) = &self.inner.tx {
3413 Self::send_block_input_error(tx, state, "No permission".to_string());
3414 }
3415 }
3416 }
3417 }
3418 #[cfg(not(any(target_os = "android", target_os = "ios")))]
3419 if let Ok(q) = o.terminal_persistent.enum_value() {
3420 if q != BoolOption::NotSet {
3421 self.update_terminal_persistence(q == BoolOption::Yes).await;
3422 }
3423 }
3424 }
3425
3426 async fn turn_on_privacy(&mut self, impl_key: String) {
3427 let msg_out = if !privacy_mode::is_privacy_mode_supported() {
3428 crate::common::make_privacy_mode_msg_with_details(
3429 back_notification::PrivacyModeState::PrvNotSupported,
…lines 3430–3608 unchanged (179 lines)
3609 pub fn alive_conns() -> Vec<i32> {
3610 ALIVE_CONNS.lock().unwrap().clone()
3611 }
3612
3613 #[cfg(windows)]
3614 fn portable_check(&mut self) {
3615 if self.portable.is_installed || !self.is_remote() || !self.keyboard {
3616 return;
3617 }
3618 let running = portable_client::running();
3619 let show_elevation = !running;
3620 self.send_to_cm(ipc::Data::DataPortableService(
3621 ipc::DataPortableService::CmShowElevation(show_elevation),
3622 ));
3623 if self.authorized {
…lines 3624–3821 unchanged (198 lines)
3822 ..Default::default()
3823 };
3824 msg_out.set_message_box(res);
3825 self.send(msg_out).await;
3826 }
3827
3828 #[cfg(not(any(target_os = "android", target_os = "ios")))]
3829 async fn update_terminal_persistence(&mut self, persistent: bool) {
3830 self.terminal_persistent = persistent;
3831 terminal_service::set_persistent(&self.terminal_service_id, persistent).ok();
3832 }
3833
3834 #[cfg(not(any(target_os = "android", target_os = "ios")))]
3835 async fn init_terminal_service(&mut self) {
3836 if self.terminal_service_id.is_empty() {
3837 self.terminal_service_id = terminal_service::generate_service_id();
3838 }
3839 let s = Box::new(terminal_service::new(
3840 self.terminal_service_id.clone(),
3841 self.terminal_persistent,
3842 ));
3843 s.on_subscribe(self.inner.clone());
3844 self.terminal_generic_service = Some(s);
3845 }
3846
3847 #[cfg(not(any(target_os = "android", target_os = "ios")))]
3848 async fn handle_terminal_action(&mut self, action: TerminalAction) -> ResultType<()> {
3849 let mut proxy = terminal_service::TerminalServiceProxy::new(
3850 self.terminal_service_id.clone(),
3851 Some(self.terminal_persistent),
3852 );
3853
3854 match proxy.handle_action(&action) {
3855 Ok(Some(response)) => {
3856 let mut msg_out = Message::new();
3857 msg_out.set_terminal_response(response);
3858 self.send(msg_out).await;
3859 }
3860 Ok(None) => {
3861 // No response needed
3862 }
3863 Err(err) => {
3864 let mut response = TerminalResponse::new();
3865 let mut error = TerminalError::new();
3866 error.message = format!("Failed to handle action: {}", err);
3867 response.set_error(error);
3868 let mut msg_out = Message::new();
3869 msg_out.set_terminal_response(response);
3870 self.send(msg_out).await;
3871 }
3872 }
3873
3874 Ok(())
3875 }
3876}
3877
3878pub fn insert_switch_sides_uuid(id: String, uuid: uuid::Uuid) {
3879 SWITCH_SIDES_UUID
3880 .lock()
3881 .unwrap()
…lines 3882–4242 unchanged (361 lines)
4243
4244impl Drop for Connection {
4245 fn drop(&mut self) {
4246 #[cfg(not(any(target_os = "android", target_os = "ios")))]
4247 self.release_pressed_modifiers();
4248
4249 if let Some(s) = self.terminal_generic_service.as_ref() {
4250 s.join();
4251 }
4252 }
4253}
4254
4255#[cfg(target_os = "linux")]
4256struct LinuxHeadlessHandle {
4257 pub is_headless_allowed: bool,
…lines 4258–4594 unchanged (337 lines)