From b7d62ed24232a007eb511c8576c48dd46ccd6451 Mon Sep 17 00:00:00 2001 From: Przemko Robakowski Date: Wed, 7 Feb 2024 21:57:47 +0100 Subject: [PATCH 01/24] Resize --- Cargo.lock | 16 ++--- Cargo.toml | 31 ++++++--- lib/srv/desktop/rdp/rdpclient/Cargo.toml | 2 + lib/srv/desktop/rdp/rdpclient/src/client.rs | 69 +++++++++++++++++--- lib/srv/desktop/rdp/rdpclient/src/cliprdr.rs | 23 +++---- 5 files changed, 98 insertions(+), 43 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8e9ad483ff3b..5f550ee313e6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1225,7 +1225,6 @@ dependencies = [ [[package]] name = "ironrdp-async" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=c944674ecbb0952f9e7ecb964a6c79cdca669a08#c944674ecbb0952f9e7ecb964a6c79cdca669a08" dependencies = [ "bytes", "ironrdp-connector", @@ -1236,7 +1235,6 @@ dependencies = [ [[package]] name = "ironrdp-cliprdr" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=c944674ecbb0952f9e7ecb964a6c79cdca669a08#c944674ecbb0952f9e7ecb964a6c79cdca669a08" dependencies = [ "bitflags 2.4.2", "ironrdp-pdu", @@ -1248,7 +1246,6 @@ dependencies = [ [[package]] name = "ironrdp-connector" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=c944674ecbb0952f9e7ecb964a6c79cdca669a08#c944674ecbb0952f9e7ecb964a6c79cdca669a08" dependencies = [ "ironrdp-error", "ironrdp-pdu", @@ -1263,12 +1260,10 @@ dependencies = [ [[package]] name = "ironrdp-error" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=c944674ecbb0952f9e7ecb964a6c79cdca669a08#c944674ecbb0952f9e7ecb964a6c79cdca669a08" [[package]] name = "ironrdp-graphics" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=c944674ecbb0952f9e7ecb964a6c79cdca669a08#c944674ecbb0952f9e7ecb964a6c79cdca669a08" dependencies = [ "bit_field", "bitflags 2.4.2", @@ -1285,7 +1280,6 @@ dependencies = [ [[package]] name = "ironrdp-pdu" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=c944674ecbb0952f9e7ecb964a6c79cdca669a08#c944674ecbb0952f9e7ecb964a6c79cdca669a08" dependencies = [ "bit_field", "bitflags 2.4.2", @@ -1301,13 +1295,13 @@ dependencies = [ "sha1", "tap", "thiserror", + "tracing", "x509-cert", ] [[package]] name = "ironrdp-rdpdr" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=c944674ecbb0952f9e7ecb964a6c79cdca669a08#c944674ecbb0952f9e7ecb964a6c79cdca669a08" dependencies = [ "bitflags 2.4.2", "ironrdp-error", @@ -1319,7 +1313,6 @@ dependencies = [ [[package]] name = "ironrdp-rdpsnd" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=c944674ecbb0952f9e7ecb964a6c79cdca669a08#c944674ecbb0952f9e7ecb964a6c79cdca669a08" dependencies = [ "ironrdp-pdu", "ironrdp-svc", @@ -1328,9 +1321,9 @@ dependencies = [ [[package]] name = "ironrdp-session" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=c944674ecbb0952f9e7ecb964a6c79cdca669a08#c944674ecbb0952f9e7ecb964a6c79cdca669a08" dependencies = [ "bitflags 2.4.2", + "byteorder", "ironrdp-connector", "ironrdp-error", "ironrdp-graphics", @@ -1342,7 +1335,6 @@ dependencies = [ [[package]] name = "ironrdp-svc" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=c944674ecbb0952f9e7ecb964a6c79cdca669a08#c944674ecbb0952f9e7ecb964a6c79cdca669a08" dependencies = [ "bitflags 2.4.2", "ironrdp-pdu", @@ -1351,7 +1343,6 @@ dependencies = [ [[package]] name = "ironrdp-tls" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=c944674ecbb0952f9e7ecb964a6c79cdca669a08#c944674ecbb0952f9e7ecb964a6c79cdca669a08" dependencies = [ "tokio", "tokio-rustls", @@ -1361,7 +1352,6 @@ dependencies = [ [[package]] name = "ironrdp-tokio" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=c944674ecbb0952f9e7ecb964a6c79cdca669a08#c944674ecbb0952f9e7ecb964a6c79cdca669a08" dependencies = [ "bytes", "ironrdp-async", @@ -2033,6 +2023,8 @@ dependencies = [ "tempfile", "tokio", "tokio-boring", + "tracing", + "tracing-subscriber", "utf16string", "uuid", ] diff --git a/Cargo.toml b/Cargo.toml index c98ec9bd3f26..d7deff7eb39e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,13 +23,24 @@ codegen-units = 1 [workspace.dependencies] # Note: To use a local IronRDP repository as a crate (for example, ironrdp-cliprdr), define the dependency as follows: # ironrdp-cliprdr = { path = "/path/to/local/IronRDP/crates/ironrdp-cliprdr" } -ironrdp-cliprdr = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } -ironrdp-connector = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } -ironrdp-graphics = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } -ironrdp-pdu = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } -ironrdp-rdpdr = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } -ironrdp-rdpsnd = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } -ironrdp-session = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } -ironrdp-svc = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } -ironrdp-tls = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08", features = ["rustls"]} -ironrdp-tokio = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } +#ironrdp-cliprdr = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } +#ironrdp-connector = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } +#ironrdp-graphics = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } +#ironrdp-pdu = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } +#ironrdp-rdpdr = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } +#ironrdp-rdpsnd = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } +#ironrdp-session = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } +#ironrdp-svc = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } +#ironrdp-tls = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08", features = ["rustls"]} +#ironrdp-tokio = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } + +ironrdp-cliprdr = { path = "/Users/ibeckermayer/gravitational/probakowski/IronRDP/crates/ironrdp-cliprdr" } +ironrdp-connector = { path = "/Users/ibeckermayer/gravitational/probakowski/IronRDP/crates/ironrdp-connector" } +ironrdp-graphics = { path = "/Users/ibeckermayer/gravitational/probakowski/IronRDP/crates/ironrdp-graphics" } +ironrdp-pdu = { path = "/Users/ibeckermayer/gravitational/probakowski/IronRDP/crates/ironrdp-pdu" } +ironrdp-rdpdr = { path = "/Users/ibeckermayer/gravitational/probakowski/IronRDP/crates/ironrdp-rdpdr" } +ironrdp-rdpsnd = { path = "/Users/ibeckermayer/gravitational/probakowski/IronRDP/crates/ironrdp-rdpsnd" } +ironrdp-session = { path = "/Users/ibeckermayer/gravitational/probakowski/IronRDP/crates/ironrdp-session" } +ironrdp-svc = { path = "/Users/ibeckermayer/gravitational/probakowski/IronRDP/crates/ironrdp-svc" } +ironrdp-tls = { path = "/Users/ibeckermayer/gravitational/probakowski/IronRDP/crates/ironrdp-tls", features = ["rustls"]} +ironrdp-tokio = { path = "/Users/ibeckermayer/gravitational/probakowski/IronRDP/crates/ironrdp-tokio" } diff --git a/lib/srv/desktop/rdp/rdpclient/Cargo.toml b/lib/srv/desktop/rdp/rdpclient/Cargo.toml index 6f959e891f2d..824c46d11508 100644 --- a/lib/srv/desktop/rdp/rdpclient/Cargo.toml +++ b/lib/srv/desktop/rdp/rdpclient/Cargo.toml @@ -36,6 +36,8 @@ tokio = { version = "1.36", features = ["full"] } tokio-boring = { git = "https://github.com/gravitational/boring", rev="605253d99d5e363e178bcf97e1d4622e33844cd5", optional = true } utf16string = "0.2.0" uuid = { version = "1.7.0", features = ["v4"] } +tracing-subscriber = "0.3.17" +tracing = { version = "0.1", features = ["log-always" ] } [build-dependencies] cbindgen = "0.26.0" diff --git a/lib/srv/desktop/rdp/rdpclient/src/client.rs b/lib/srv/desktop/rdp/rdpclient/src/client.rs index c63c5bf4796e..ee1721c6ec3c 100644 --- a/lib/srv/desktop/rdp/rdpclient/src/client.rs +++ b/lib/srv/desktop/rdp/rdpclient/src/client.rs @@ -20,11 +20,14 @@ use crate::{ CGOErrCode, CGOKeyboardEvent, CGOMousePointerEvent, CGOPointerButton, CGOPointerWheel, CGOSyncKeys, CgoHandle, }; +use bitflags::Flags; #[cfg(feature = "fips")] use boring::error::ErrorStack; use bytes::BytesMut; -use ironrdp_cliprdr::{Client as ClientRole, Cliprdr, CliprdrSvcMessages}; +use ironrdp_cliprdr::{Client as ClientRole, Cliprdr, CliprdrClient, CliprdrSvcMessages}; use ironrdp_connector::{Config, ConnectorError, Credentials}; +use ironrdp_dvc::DrdynvcClient; +use ironrdp_pdu::dvc::display::{ClientPdu, Monitor, MonitorFlags, MonitorLayoutPdu, Orientation}; use ironrdp_pdu::input::fast_path::{ FastPathInput, FastPathInputEvent, KeyboardFlags, SynchronizeFlags, }; @@ -33,12 +36,13 @@ use ironrdp_pdu::input::{InputEventError, MousePdu}; use ironrdp_pdu::mcs::DisconnectReason; use ironrdp_pdu::rdp::capability_sets::MajorPlatformType; use ironrdp_pdu::rdp::RdpError; -use ironrdp_pdu::{custom_err, function, PduError, PduParsing}; +use ironrdp_pdu::write_buf::WriteBuf; +use ironrdp_pdu::{custom_err, dvc, function, PduError, PduParsing}; use ironrdp_rdpdr::pdu::efs::ClientDeviceListAnnounce; use ironrdp_rdpdr::pdu::RdpdrPdu; use ironrdp_rdpdr::Rdpdr; use ironrdp_rdpsnd::Rdpsnd; -use ironrdp_session::x224::{self, ProcessorOutput}; +use ironrdp_session::x224::{Processor as X224Processor, Processor, ProcessorOutput}; use ironrdp_session::SessionErrorKind::Reason; use ironrdp_session::{reason_err, SessionError, SessionResult}; use ironrdp_svc::{SvcMessage, SvcProcessor, SvcProcessorMessages}; @@ -152,7 +156,8 @@ impl Client { let mut connector = ironrdp_connector::ClientConnector::new(connector_config) .with_server_addr(server_socket_addr) .with_static_channel(Rdpsnd::new()) // required for rdpdr to work - .with_static_channel(rdpdr); + .with_static_channel(rdpdr) + .with_static_channel(DrdynvcClient::new()); if params.allow_clipboard { connector = connector.with_static_channel(Cliprdr::new(Box::new( @@ -180,7 +185,6 @@ impl Client { server_addr.into(), server_public_key, None, - None, ) .await?; @@ -337,10 +341,59 @@ impl Client { x224_processor: Arc>, ) -> tokio::task::JoinHandle> { global::TOKIO_RT.spawn(async move { + let mut width = 800; + let mut height = 600; loop { match write_receiver.recv().await { Some(write_request) => match write_request { ClientFunction::WriteRdpKey(args) => { + debug!("Scan code: {}", args.code); + if args.code == 0x1E && args.down { + width = 1800 - width; + height = 1400 - height; + debug!("Trying to resize: {}", args.code); + + let mut buf = WriteBuf::new(); + let monitor_layout_pdu = + ClientPdu::DisplayControlMonitorLayout(MonitorLayoutPdu { + monitors: vec![Monitor { + flags: MonitorFlags::PRIMARY, + left: 0, + top: 0, + width: width as u32, + height: height as u32, + physical_width: 800 as u32, + physical_height: 600 as u32, + orientation: Orientation::Landscape, + desktop_scale_factor: 100, + device_scale_factor: 100, + }], + }); + monitor_layout_pdu.to_buffer(&mut buf); + + let prcessor = x224_processor.clone(); + let res: ClientResult = global::TOKIO_RT + .spawn_blocking(move || { + let mut buf2 = WriteBuf::new(); + let x224_processor = Self::x224_lock(&prcessor)?; + x224_processor.encode_dynamic( + &mut buf2, + dvc::display::CHANNEL_NAME, + buf.filled(), + )?; + Ok(buf2) + }) + .await?; + match res { + Ok(buf2) => { + debug!("Sending resize {}x{}", width, height); + write_stream.write_all(buf2.filled()).await?; + } + Err(e) => { + debug!("Not OK {:?}", e); + } + } + } Client::write_rdp_key(&mut write_stream, args).await?; } ClientFunction::WriteRdpPointer(args) => { @@ -444,10 +497,10 @@ impl Client { fun: Box, ) -> ClientResult<()> { let processor = x224_processor.clone(); - let messages: ClientResult> = global::TOKIO_RT + let messages: ClientResult> = global::TOKIO_RT .spawn_blocking(move || { let mut x224_processor = Self::x224_lock(&processor)?; - let cliprdr = Self::get_svc_processor::>(&mut x224_processor)?; + let cliprdr = Self::get_svc_processor::(&mut x224_processor)?; Ok(fun.call(cliprdr)?) }) .await?; @@ -800,7 +853,7 @@ impl Client { x224_processor: &mut x224::Processor, ) -> ClientResult<&mut TeleportCliprdrBackend> { x224_processor - .get_svc_processor_mut::>() + .get_svc_processor_mut::() .and_then(|c| c.downcast_backend_mut::()) .ok_or(ClientError::InternalError( "cliprdr_backend returned None".to_string(), diff --git a/lib/srv/desktop/rdp/rdpclient/src/cliprdr.rs b/lib/srv/desktop/rdp/rdpclient/src/cliprdr.rs index 62912d8d9b71..26d750d00f81 100644 --- a/lib/srv/desktop/rdp/rdpclient/src/cliprdr.rs +++ b/lib/srv/desktop/rdp/rdpclient/src/cliprdr.rs @@ -21,7 +21,7 @@ use ironrdp_cliprdr::pdu::{ ClipboardFormat, ClipboardFormatId, ClipboardGeneralCapabilityFlags, FileContentsRequest, FileContentsResponse, FormatDataRequest, FormatDataResponse, LockDataId, }; -use ironrdp_cliprdr::{Client as ClientRole, Cliprdr, CliprdrSvcMessages}; +use ironrdp_cliprdr::{Client, CliprdrClient as Cliprdr, CliprdrSvcMessages}; use ironrdp_pdu::PduResult; use ironrdp_svc::impl_as_any; use log::{debug, error, info, trace, warn}; @@ -57,7 +57,7 @@ impl TeleportCliprdrBackend { fn send(&self, name: &'static str, f: F) where - F: Fn(&Cliprdr) -> PduResult> + Send + 'static, + F: Fn(&Cliprdr) -> PduResult> + Send + 'static, { let res = self .client_handle @@ -189,24 +189,21 @@ impl CliprdrBackend for TeleportCliprdrBackend { impl_as_any!(TeleportCliprdrBackend); pub trait ClipboardFn: Send + Debug + 'static { - fn call(&self, cliprdr: &Cliprdr) -> PduResult>; + fn call(&self, cliprdr: &Cliprdr) -> PduResult>; } impl ClipboardFn for F where - F: Fn(&Cliprdr) -> PduResult> - + Send - + Debug - + 'static, + F: Fn(&Cliprdr) -> PduResult> + Send + Debug + 'static, { - fn call(&self, cliprdr: &Cliprdr) -> PduResult> { + fn call(&self, cliprdr: &Cliprdr) -> PduResult> { (self)(cliprdr) } } struct ClipboardFnInternal where - F: Fn(&Cliprdr) -> PduResult> + Send + 'static, + F: Fn(&Cliprdr) -> PduResult> + Send + 'static, { name: &'static str, closure: F, @@ -214,7 +211,7 @@ where impl ClipboardFnInternal where - F: Fn(&Cliprdr) -> PduResult> + Send + 'static, + F: Fn(&Cliprdr) -> PduResult> + Send + 'static, { fn new(name: &'static str, closure: F) -> Self { Self { name, closure } @@ -223,7 +220,7 @@ where impl Debug for ClipboardFnInternal where - F: Fn(&Cliprdr) -> PduResult> + Send + 'static, + F: Fn(&Cliprdr) -> PduResult> + Send + 'static, { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "{}", &self.name) @@ -232,9 +229,9 @@ where impl ClipboardFn for ClipboardFnInternal where - F: Fn(&Cliprdr) -> PduResult> + Send + 'static, + F: Fn(&Cliprdr) -> PduResult> + Send + 'static, { - fn call(&self, cliprdr: &Cliprdr) -> PduResult> { + fn call(&self, cliprdr: &Cliprdr) -> PduResult> { (self.closure)(cliprdr) } } From 72c4ba4422764c51bdb0e8b63dde7d1d6df508af Mon Sep 17 00:00:00 2001 From: Przemko Robakowski Date: Wed, 21 Feb 2024 20:44:04 +0100 Subject: [PATCH 02/24] ??? --- lib/srv/desktop/rdp/rdpclient/client.go | 2 +- lib/srv/desktop/rdp/rdpclient/src/client.rs | 9 +++++---- web/packages/teleport/src/ironrdp/src/lib.rs | 5 +++++ 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/srv/desktop/rdp/rdpclient/client.go b/lib/srv/desktop/rdp/rdpclient/client.go index 920c8ba3c29e..702605e5c8fc 100644 --- a/lib/srv/desktop/rdp/rdpclient/client.go +++ b/lib/srv/desktop/rdp/rdpclient/client.go @@ -222,7 +222,7 @@ func (c *Client) readClientUsername() error { } u, ok := msg.(tdp.ClientUsername) if !ok { - c.cfg.Log.Debugf("Expected ClientUsername message, got %T", msg) + c.cfg.Log.Debugf("Expected ClientUsername message, got %T ", msg) continue } c.cfg.Log.Debugf("Got RDP username %q", u.Username) diff --git a/lib/srv/desktop/rdp/rdpclient/src/client.rs b/lib/srv/desktop/rdp/rdpclient/src/client.rs index ee1721c6ec3c..ff7ec2215636 100644 --- a/lib/srv/desktop/rdp/rdpclient/src/client.rs +++ b/lib/srv/desktop/rdp/rdpclient/src/client.rs @@ -362,8 +362,8 @@ impl Client { top: 0, width: width as u32, height: height as u32, - physical_width: 800 as u32, - physical_height: 600 as u32, + physical_width: width as u32, + physical_height: height as u32, orientation: Orientation::Landscape, desktop_scale_factor: 100, device_scale_factor: 100, @@ -386,8 +386,9 @@ impl Client { .await?; match res { Ok(buf2) => { - debug!("Sending resize {}x{}", width, height); - write_stream.write_all(buf2.filled()).await?; + let x = buf2.filled(); + debug!("Sending resize {}x{}, {:?}", width, height, x); + write_stream.write_all(x).await?; } Err(e) => { debug!("Not OK {:?}", e); diff --git a/web/packages/teleport/src/ironrdp/src/lib.rs b/web/packages/teleport/src/ironrdp/src/lib.rs index bb4c8a517d1f..fc908431b336 100644 --- a/web/packages/teleport/src/ironrdp/src/lib.rs +++ b/web/packages/teleport/src/ironrdp/src/lib.rs @@ -171,6 +171,11 @@ impl FastPathProcessor { } } + pub fn resize(&mut self, width: u16, height: u16) -> Result<(), JsValue> { + self.image = DecodedImage::new(PixelFormat::RgbA32, width, height); + Ok(()) + } + /// `tdp_fast_path_frame: Uint8Array` /// /// `cb_context: tdp.Client` From fc064c2a1bd597831113503ec03e3b2063ddde22 Mon Sep 17 00:00:00 2001 From: Przemko Robakowski Date: Mon, 26 Feb 2024 00:26:41 +0100 Subject: [PATCH 03/24] ??? --- lib/srv/desktop/rdp/rdpclient/client.go | 2 +- lib/srv/desktop/rdp/rdpclient/src/client.rs | 85 ++++++++++++++++++--- 2 files changed, 75 insertions(+), 12 deletions(-) diff --git a/lib/srv/desktop/rdp/rdpclient/client.go b/lib/srv/desktop/rdp/rdpclient/client.go index 702605e5c8fc..e59b6b061acf 100644 --- a/lib/srv/desktop/rdp/rdpclient/client.go +++ b/lib/srv/desktop/rdp/rdpclient/client.go @@ -731,7 +731,7 @@ func cgo_handle_remote_copy(handle C.uintptr_t, data *C.uint8_t, length C.uint32 // handleRemoteCopy is called from Rust when data is copied // on the remote desktop func (c *Client) handleRemoteCopy(data []byte) C.CGOErrCode { - c.cfg.Log.Debugf("Received %d bytes of clipboard data from Windows desktop", len(data)) + c.cfg.Log.Debugf("Received %d bytes of clipboard data from Windows desktop ", len(data)) if err := c.cfg.Conn.WriteMessage(tdp.ClipboardData(data)); err != nil { c.cfg.Log.Errorf("failed handling remote copy: %v", err) diff --git a/lib/srv/desktop/rdp/rdpclient/src/client.rs b/lib/srv/desktop/rdp/rdpclient/src/client.rs index ff7ec2215636..ff8c88c82f4c 100644 --- a/lib/srv/desktop/rdp/rdpclient/src/client.rs +++ b/lib/srv/desktop/rdp/rdpclient/src/client.rs @@ -24,8 +24,12 @@ use bitflags::Flags; #[cfg(feature = "fips")] use boring::error::ErrorStack; use bytes::BytesMut; -use ironrdp_cliprdr::{Client as ClientRole, Cliprdr, CliprdrClient, CliprdrSvcMessages}; -use ironrdp_connector::{Config, ConnectorError, Credentials}; +use ironrdp_cliprdr::{Cliprdr, CliprdrClient, CliprdrSvcMessages}; +use ironrdp_connector::legacy::DeactivateAllError; +use ironrdp_connector::ClientConnectorState::CapabilitiesExchange; +use ironrdp_connector::{ + ClientConnector, ClientConnectorState, Config, ConnectorError, Credentials, +}; use ironrdp_dvc::DrdynvcClient; use ironrdp_pdu::dvc::display::{ClientPdu, Monitor, MonitorFlags, MonitorLayoutPdu, Orientation}; use ironrdp_pdu::input::fast_path::{ @@ -42,13 +46,14 @@ use ironrdp_rdpdr::pdu::efs::ClientDeviceListAnnounce; use ironrdp_rdpdr::pdu::RdpdrPdu; use ironrdp_rdpdr::Rdpdr; use ironrdp_rdpsnd::Rdpsnd; -use ironrdp_session::x224::{Processor as X224Processor, Processor, ProcessorOutput}; +use ironrdp_session::x224::{self, Processor, ProcessorOutput}; use ironrdp_session::SessionErrorKind::Reason; use ironrdp_session::{reason_err, SessionError, SessionResult}; use ironrdp_svc::{SvcMessage, SvcProcessor, SvcProcessorMessages}; -use ironrdp_tokio::{Framed, TokioStream}; -use log::debug; +use ironrdp_tokio::{connect_finalize_no_credssp, single_connect_step_read, Framed, TokioStream}; +use log::{debug, warn}; use rand::{Rng, SeedableRng}; +use std::error::Error; use std::fmt::{Debug, Display, Formatter}; use std::io::{Error as IoError, ErrorKind as IoErrorKind}; use std::net::ToSocketAddrs; @@ -65,6 +70,7 @@ use crate::rdpdr::TeleportRdpdrBackend; use crate::ssl::TlsStream; #[cfg(feature = "fips")] use tokio_boring::{HandshakeError, SslStream}; +use tracing::field::debug; const RDP_CONNECT_TIMEOUT: Duration = Duration::from_secs(5); @@ -77,6 +83,9 @@ pub struct Client { write_stream: Option, function_receiver: Option, x224_processor: Arc>, + connector_config: Config, + io_channel_id: u16, + user_channel_id: u16, } impl Client { @@ -153,7 +162,7 @@ impl Client { debug!("creating rdpdr client with directory sharing disabled") } - let mut connector = ironrdp_connector::ClientConnector::new(connector_config) + let mut connector = ironrdp_connector::ClientConnector::new(connector_config.clone()) .with_server_addr(server_socket_addr) .with_static_channel(Rdpsnd::new()) // required for rdpdr to work .with_static_channel(rdpdr) @@ -179,12 +188,12 @@ impl Client { let mut rdp_stream = ironrdp_tokio::TokioFramed::new(upgraded_stream); let connection_result = ironrdp_tokio::connect_finalize( - upgraded, &mut rdp_stream, connector, server_addr.into(), server_public_key, None, + None, ) .await?; @@ -222,6 +231,9 @@ impl Client { write_stream: Some(write_stream), function_receiver: Some(function_receiver), x224_processor: Arc::new(Mutex::new(x224_processor)), + connector_config, + io_channel_id: connection_result.io_channel_id, + user_channel_id: connection_result.user_channel_id, }) } @@ -264,6 +276,9 @@ impl Client { read_stream, self.x224_processor.clone(), self.client_handle.clone(), + self.connector_config.clone(), + self.io_channel_id, + self.user_channel_id, ); let mut write_loop_handle = Client::run_write_loop( @@ -295,7 +310,11 @@ impl Client { mut read_stream: RdpReadStream, x224_processor: Arc>, write_requester: ClientHandle, - ) -> tokio::task::JoinHandle>> { + config: Config, + io_channel_id: u16, + user_channel_id: u16, + ) -> tokio::task::JoinHandle> { + // ) -> tokio::task::JoinHandle>> { global::TOKIO_RT.spawn(async move { loop { let (action, mut frame) = read_stream.read_pdu().await?; @@ -316,7 +335,51 @@ impl Client { ironrdp_pdu::Action::X224 => { // X224 PDU, process it and send any immediate response frames to the write loop // for writing to the RDP server. - let res = Client::x224_process(x224_processor.clone(), frame).await?; + let res = match Client::x224_process(x224_processor.clone(), frame).await { + Ok(res) => res, + Err(e) => { + if let Some(ee) = e.source() { + if ee.is::() { + warn!("Deactivate"); + let mut connector = ClientConnector { + config: config.clone(), + state: CapabilitiesExchange { + io_channel_id, + user_channel_id, + }, + server_addr: None, + static_channels: Default::default(), + }; + + let mut buf = WriteBuf::new(); + loop { + let written = single_connect_step_read( + &mut read_stream, + &mut connector, + &mut buf, + ) + .await?; + if let Some(_) = written.size() { + write_requester + .write_raw_pdu_async(buf.filled().to_vec()) + .await?; + } + if let ClientConnectorState::Connected { result } = + connector.state + { + break; + } + } + Vec::new() + } else { + return Err(e.into()); + } + } else { + return Err(e.into()); + } + } + }; + // Send response frames to write loop for writing to RDP server. for output in res { match output { ProcessorOutput::ResponseFrame(frame) => { @@ -362,8 +425,8 @@ impl Client { top: 0, width: width as u32, height: height as u32, - physical_width: width as u32, - physical_height: height as u32, + physical_width: 0, + physical_height: 0, orientation: Orientation::Landscape, desktop_scale_factor: 100, device_scale_factor: 100, From 5e2489c02799279c593ba3870b2bcd0938b839de Mon Sep 17 00:00:00 2001 From: Isaiah Becker-Mayer Date: Fri, 1 Mar 2024 15:11:43 -0800 Subject: [PATCH 04/24] Fixes to compile --- Cargo.lock | 11 +++++++++++ Cargo.toml | 1 + lib/srv/desktop/rdp/rdpclient/Cargo.toml | 1 + lib/srv/desktop/rdp/rdpclient/src/client.rs | 11 ++++------- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5f550ee313e6..934735467c85 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1257,6 +1257,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "ironrdp-dvc" +version = "0.1.0" +dependencies = [ + "ironrdp-pdu", + "ironrdp-svc", + "slab", + "tracing", +] + [[package]] name = "ironrdp-error" version = "0.1.0" @@ -2004,6 +2014,7 @@ dependencies = [ "env_logger", "ironrdp-cliprdr", "ironrdp-connector", + "ironrdp-dvc", "ironrdp-pdu", "ironrdp-rdpdr", "ironrdp-rdpsnd", diff --git a/Cargo.toml b/Cargo.toml index d7deff7eb39e..770a7324bc58 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,5 +42,6 @@ ironrdp-rdpdr = { path = "/Users/ibeckermayer/gravitational/probakowski/IronRDP/ ironrdp-rdpsnd = { path = "/Users/ibeckermayer/gravitational/probakowski/IronRDP/crates/ironrdp-rdpsnd" } ironrdp-session = { path = "/Users/ibeckermayer/gravitational/probakowski/IronRDP/crates/ironrdp-session" } ironrdp-svc = { path = "/Users/ibeckermayer/gravitational/probakowski/IronRDP/crates/ironrdp-svc" } +ironrdp-dvc = { path = "/Users/ibeckermayer/gravitational/probakowski/IronRDP/crates/ironrdp-dvc" } ironrdp-tls = { path = "/Users/ibeckermayer/gravitational/probakowski/IronRDP/crates/ironrdp-tls", features = ["rustls"]} ironrdp-tokio = { path = "/Users/ibeckermayer/gravitational/probakowski/IronRDP/crates/ironrdp-tokio" } diff --git a/lib/srv/desktop/rdp/rdpclient/Cargo.toml b/lib/srv/desktop/rdp/rdpclient/Cargo.toml index 824c46d11508..a91173523f99 100644 --- a/lib/srv/desktop/rdp/rdpclient/Cargo.toml +++ b/lib/srv/desktop/rdp/rdpclient/Cargo.toml @@ -21,6 +21,7 @@ ironrdp-rdpdr.workspace = true ironrdp-rdpsnd.workspace = true ironrdp-session.workspace = true ironrdp-svc.workspace = true +ironrdp-dvc.workspace = true ironrdp-tls.workspace = true ironrdp-tokio.workspace = true iso7816 = "0.1.2" diff --git a/lib/srv/desktop/rdp/rdpclient/src/client.rs b/lib/srv/desktop/rdp/rdpclient/src/client.rs index ff8c88c82f4c..74a86ae5f6c5 100644 --- a/lib/srv/desktop/rdp/rdpclient/src/client.rs +++ b/lib/srv/desktop/rdp/rdpclient/src/client.rs @@ -20,7 +20,6 @@ use crate::{ CGOErrCode, CGOKeyboardEvent, CGOMousePointerEvent, CGOPointerButton, CGOPointerWheel, CGOSyncKeys, CgoHandle, }; -use bitflags::Flags; #[cfg(feature = "fips")] use boring::error::ErrorStack; use bytes::BytesMut; @@ -46,11 +45,11 @@ use ironrdp_rdpdr::pdu::efs::ClientDeviceListAnnounce; use ironrdp_rdpdr::pdu::RdpdrPdu; use ironrdp_rdpdr::Rdpdr; use ironrdp_rdpsnd::Rdpsnd; -use ironrdp_session::x224::{self, Processor, ProcessorOutput}; +use ironrdp_session::x224::{self, ProcessorOutput}; use ironrdp_session::SessionErrorKind::Reason; use ironrdp_session::{reason_err, SessionError, SessionResult}; use ironrdp_svc::{SvcMessage, SvcProcessor, SvcProcessorMessages}; -use ironrdp_tokio::{connect_finalize_no_credssp, single_connect_step_read, Framed, TokioStream}; +use ironrdp_tokio::{single_connect_step_read, Framed, TokioStream}; use log::{debug, warn}; use rand::{Rng, SeedableRng}; use std::error::Error; @@ -70,7 +69,6 @@ use crate::rdpdr::TeleportRdpdrBackend; use crate::ssl::TlsStream; #[cfg(feature = "fips")] use tokio_boring::{HandshakeError, SslStream}; -use tracing::field::debug; const RDP_CONNECT_TIMEOUT: Duration = Duration::from_secs(5); @@ -182,7 +180,7 @@ impl Client { ssl::upgrade(initial_stream, &server_socket_addr.ip().to_string()).await?; // Upgrade the stream - let upgraded = ironrdp_tokio::mark_as_upgraded(should_upgrade, &mut connector); + let _upgraded = ironrdp_tokio::mark_as_upgraded(should_upgrade, &mut connector); // Frame the stream again for use by connect_finalize let mut rdp_stream = ironrdp_tokio::TokioFramed::new(upgraded_stream); @@ -313,8 +311,7 @@ impl Client { config: Config, io_channel_id: u16, user_channel_id: u16, - ) -> tokio::task::JoinHandle> { - // ) -> tokio::task::JoinHandle>> { + ) -> tokio::task::JoinHandle>> { global::TOKIO_RT.spawn(async move { loop { let (action, mut frame) = read_stream.read_pdu().await?; From 7c2e8668dfdb2d96f58e76b5186c064cf5b287dc Mon Sep 17 00:00:00 2001 From: Isaiah Becker-Mayer Date: Thu, 7 Mar 2024 16:18:59 -0800 Subject: [PATCH 05/24] Updates to latest IronRDP with dvc fix, cleans up some of the debug code --- Cargo.lock | 15 +++- Cargo.toml | 33 +++------ lib/srv/desktop/rdp/rdpclient/src/client.rs | 80 +++------------------ 3 files changed, 34 insertions(+), 94 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 934735467c85..7d596456a1ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1225,6 +1225,7 @@ dependencies = [ [[package]] name = "ironrdp-async" version = "0.1.0" +source = "git+https://github.com/Devolutions/IronRDP?rev=def44ec32cd98e133635b143becfc23f9804a782#def44ec32cd98e133635b143becfc23f9804a782" dependencies = [ "bytes", "ironrdp-connector", @@ -1235,6 +1236,7 @@ dependencies = [ [[package]] name = "ironrdp-cliprdr" version = "0.1.0" +source = "git+https://github.com/Devolutions/IronRDP?rev=def44ec32cd98e133635b143becfc23f9804a782#def44ec32cd98e133635b143becfc23f9804a782" dependencies = [ "bitflags 2.4.2", "ironrdp-pdu", @@ -1246,6 +1248,7 @@ dependencies = [ [[package]] name = "ironrdp-connector" version = "0.1.0" +source = "git+https://github.com/Devolutions/IronRDP?rev=def44ec32cd98e133635b143becfc23f9804a782#def44ec32cd98e133635b143becfc23f9804a782" dependencies = [ "ironrdp-error", "ironrdp-pdu", @@ -1260,6 +1263,7 @@ dependencies = [ [[package]] name = "ironrdp-dvc" version = "0.1.0" +source = "git+https://github.com/Devolutions/IronRDP?rev=def44ec32cd98e133635b143becfc23f9804a782#def44ec32cd98e133635b143becfc23f9804a782" dependencies = [ "ironrdp-pdu", "ironrdp-svc", @@ -1270,10 +1274,12 @@ dependencies = [ [[package]] name = "ironrdp-error" version = "0.1.0" +source = "git+https://github.com/Devolutions/IronRDP?rev=def44ec32cd98e133635b143becfc23f9804a782#def44ec32cd98e133635b143becfc23f9804a782" [[package]] name = "ironrdp-graphics" version = "0.1.0" +source = "git+https://github.com/Devolutions/IronRDP?rev=def44ec32cd98e133635b143becfc23f9804a782#def44ec32cd98e133635b143becfc23f9804a782" dependencies = [ "bit_field", "bitflags 2.4.2", @@ -1290,6 +1296,7 @@ dependencies = [ [[package]] name = "ironrdp-pdu" version = "0.1.0" +source = "git+https://github.com/Devolutions/IronRDP?rev=def44ec32cd98e133635b143becfc23f9804a782#def44ec32cd98e133635b143becfc23f9804a782" dependencies = [ "bit_field", "bitflags 2.4.2", @@ -1305,13 +1312,13 @@ dependencies = [ "sha1", "tap", "thiserror", - "tracing", "x509-cert", ] [[package]] name = "ironrdp-rdpdr" version = "0.1.0" +source = "git+https://github.com/Devolutions/IronRDP?rev=def44ec32cd98e133635b143becfc23f9804a782#def44ec32cd98e133635b143becfc23f9804a782" dependencies = [ "bitflags 2.4.2", "ironrdp-error", @@ -1323,6 +1330,7 @@ dependencies = [ [[package]] name = "ironrdp-rdpsnd" version = "0.1.0" +source = "git+https://github.com/Devolutions/IronRDP?rev=def44ec32cd98e133635b143becfc23f9804a782#def44ec32cd98e133635b143becfc23f9804a782" dependencies = [ "ironrdp-pdu", "ironrdp-svc", @@ -1331,9 +1339,9 @@ dependencies = [ [[package]] name = "ironrdp-session" version = "0.1.0" +source = "git+https://github.com/Devolutions/IronRDP?rev=def44ec32cd98e133635b143becfc23f9804a782#def44ec32cd98e133635b143becfc23f9804a782" dependencies = [ "bitflags 2.4.2", - "byteorder", "ironrdp-connector", "ironrdp-error", "ironrdp-graphics", @@ -1345,6 +1353,7 @@ dependencies = [ [[package]] name = "ironrdp-svc" version = "0.1.0" +source = "git+https://github.com/Devolutions/IronRDP?rev=def44ec32cd98e133635b143becfc23f9804a782#def44ec32cd98e133635b143becfc23f9804a782" dependencies = [ "bitflags 2.4.2", "ironrdp-pdu", @@ -1353,6 +1362,7 @@ dependencies = [ [[package]] name = "ironrdp-tls" version = "0.1.0" +source = "git+https://github.com/Devolutions/IronRDP?rev=def44ec32cd98e133635b143becfc23f9804a782#def44ec32cd98e133635b143becfc23f9804a782" dependencies = [ "tokio", "tokio-rustls", @@ -1362,6 +1372,7 @@ dependencies = [ [[package]] name = "ironrdp-tokio" version = "0.1.0" +source = "git+https://github.com/Devolutions/IronRDP?rev=def44ec32cd98e133635b143becfc23f9804a782#def44ec32cd98e133635b143becfc23f9804a782" dependencies = [ "bytes", "ironrdp-async", diff --git a/Cargo.toml b/Cargo.toml index 770a7324bc58..643d45d391e7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,25 +23,14 @@ codegen-units = 1 [workspace.dependencies] # Note: To use a local IronRDP repository as a crate (for example, ironrdp-cliprdr), define the dependency as follows: # ironrdp-cliprdr = { path = "/path/to/local/IronRDP/crates/ironrdp-cliprdr" } -#ironrdp-cliprdr = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } -#ironrdp-connector = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } -#ironrdp-graphics = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } -#ironrdp-pdu = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } -#ironrdp-rdpdr = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } -#ironrdp-rdpsnd = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } -#ironrdp-session = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } -#ironrdp-svc = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } -#ironrdp-tls = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08", features = ["rustls"]} -#ironrdp-tokio = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } - -ironrdp-cliprdr = { path = "/Users/ibeckermayer/gravitational/probakowski/IronRDP/crates/ironrdp-cliprdr" } -ironrdp-connector = { path = "/Users/ibeckermayer/gravitational/probakowski/IronRDP/crates/ironrdp-connector" } -ironrdp-graphics = { path = "/Users/ibeckermayer/gravitational/probakowski/IronRDP/crates/ironrdp-graphics" } -ironrdp-pdu = { path = "/Users/ibeckermayer/gravitational/probakowski/IronRDP/crates/ironrdp-pdu" } -ironrdp-rdpdr = { path = "/Users/ibeckermayer/gravitational/probakowski/IronRDP/crates/ironrdp-rdpdr" } -ironrdp-rdpsnd = { path = "/Users/ibeckermayer/gravitational/probakowski/IronRDP/crates/ironrdp-rdpsnd" } -ironrdp-session = { path = "/Users/ibeckermayer/gravitational/probakowski/IronRDP/crates/ironrdp-session" } -ironrdp-svc = { path = "/Users/ibeckermayer/gravitational/probakowski/IronRDP/crates/ironrdp-svc" } -ironrdp-dvc = { path = "/Users/ibeckermayer/gravitational/probakowski/IronRDP/crates/ironrdp-dvc" } -ironrdp-tls = { path = "/Users/ibeckermayer/gravitational/probakowski/IronRDP/crates/ironrdp-tls", features = ["rustls"]} -ironrdp-tokio = { path = "/Users/ibeckermayer/gravitational/probakowski/IronRDP/crates/ironrdp-tokio" } +ironrdp-cliprdr = { git = "https://github.com/Devolutions/IronRDP", rev = "def44ec32cd98e133635b143becfc23f9804a782" } +ironrdp-connector = { git = "https://github.com/Devolutions/IronRDP", rev = "def44ec32cd98e133635b143becfc23f9804a782" } +ironrdp-graphics = { git = "https://github.com/Devolutions/IronRDP", rev = "def44ec32cd98e133635b143becfc23f9804a782" } +ironrdp-pdu = { git = "https://github.com/Devolutions/IronRDP", rev = "def44ec32cd98e133635b143becfc23f9804a782" } +ironrdp-rdpdr = { git = "https://github.com/Devolutions/IronRDP", rev = "def44ec32cd98e133635b143becfc23f9804a782" } +ironrdp-rdpsnd = { git = "https://github.com/Devolutions/IronRDP", rev = "def44ec32cd98e133635b143becfc23f9804a782" } +ironrdp-session = { git = "https://github.com/Devolutions/IronRDP", rev = "def44ec32cd98e133635b143becfc23f9804a782" } +ironrdp-svc = { git = "https://github.com/Devolutions/IronRDP", rev = "def44ec32cd98e133635b143becfc23f9804a782" } +ironrdp-dvc = { git = "https://github.com/Devolutions/IronRDP", rev = "def44ec32cd98e133635b143becfc23f9804a782" } +ironrdp-tls = { git = "https://github.com/Devolutions/IronRDP", rev = "def44ec32cd98e133635b143becfc23f9804a782", features = ["rustls"]} +ironrdp-tokio = { git = "https://github.com/Devolutions/IronRDP", rev = "def44ec32cd98e133635b143becfc23f9804a782" } diff --git a/lib/srv/desktop/rdp/rdpclient/src/client.rs b/lib/srv/desktop/rdp/rdpclient/src/client.rs index 74a86ae5f6c5..1dbf8b0f64bd 100644 --- a/lib/srv/desktop/rdp/rdpclient/src/client.rs +++ b/lib/srv/desktop/rdp/rdpclient/src/client.rs @@ -24,11 +24,7 @@ use crate::{ use boring::error::ErrorStack; use bytes::BytesMut; use ironrdp_cliprdr::{Cliprdr, CliprdrClient, CliprdrSvcMessages}; -use ironrdp_connector::legacy::DeactivateAllError; -use ironrdp_connector::ClientConnectorState::CapabilitiesExchange; -use ironrdp_connector::{ - ClientConnector, ClientConnectorState, Config, ConnectorError, Credentials, -}; +use ironrdp_connector::{Config, ConnectorError, Credentials}; use ironrdp_dvc::DrdynvcClient; use ironrdp_pdu::dvc::display::{ClientPdu, Monitor, MonitorFlags, MonitorLayoutPdu, Orientation}; use ironrdp_pdu::input::fast_path::{ @@ -49,10 +45,9 @@ use ironrdp_session::x224::{self, ProcessorOutput}; use ironrdp_session::SessionErrorKind::Reason; use ironrdp_session::{reason_err, SessionError, SessionResult}; use ironrdp_svc::{SvcMessage, SvcProcessor, SvcProcessorMessages}; -use ironrdp_tokio::{single_connect_step_read, Framed, TokioStream}; -use log::{debug, warn}; +use ironrdp_tokio::{Framed, TokioStream}; +use log::debug; use rand::{Rng, SeedableRng}; -use std::error::Error; use std::fmt::{Debug, Display, Formatter}; use std::io::{Error as IoError, ErrorKind as IoErrorKind}; use std::net::ToSocketAddrs; @@ -81,9 +76,6 @@ pub struct Client { write_stream: Option, function_receiver: Option, x224_processor: Arc>, - connector_config: Config, - io_channel_id: u16, - user_channel_id: u16, } impl Client { @@ -162,9 +154,9 @@ impl Client { let mut connector = ironrdp_connector::ClientConnector::new(connector_config.clone()) .with_server_addr(server_socket_addr) + .with_static_channel(DrdynvcClient::new()) .with_static_channel(Rdpsnd::new()) // required for rdpdr to work - .with_static_channel(rdpdr) - .with_static_channel(DrdynvcClient::new()); + .with_static_channel(rdpdr); if params.allow_clipboard { connector = connector.with_static_channel(Cliprdr::new(Box::new( @@ -180,12 +172,13 @@ impl Client { ssl::upgrade(initial_stream, &server_socket_addr.ip().to_string()).await?; // Upgrade the stream - let _upgraded = ironrdp_tokio::mark_as_upgraded(should_upgrade, &mut connector); + let upgraded = ironrdp_tokio::mark_as_upgraded(should_upgrade, &mut connector); // Frame the stream again for use by connect_finalize let mut rdp_stream = ironrdp_tokio::TokioFramed::new(upgraded_stream); let connection_result = ironrdp_tokio::connect_finalize( + upgraded, &mut rdp_stream, connector, server_addr.into(), @@ -229,9 +222,6 @@ impl Client { write_stream: Some(write_stream), function_receiver: Some(function_receiver), x224_processor: Arc::new(Mutex::new(x224_processor)), - connector_config, - io_channel_id: connection_result.io_channel_id, - user_channel_id: connection_result.user_channel_id, }) } @@ -274,9 +264,6 @@ impl Client { read_stream, self.x224_processor.clone(), self.client_handle.clone(), - self.connector_config.clone(), - self.io_channel_id, - self.user_channel_id, ); let mut write_loop_handle = Client::run_write_loop( @@ -308,9 +295,6 @@ impl Client { mut read_stream: RdpReadStream, x224_processor: Arc>, write_requester: ClientHandle, - config: Config, - io_channel_id: u16, - user_channel_id: u16, ) -> tokio::task::JoinHandle>> { global::TOKIO_RT.spawn(async move { loop { @@ -332,51 +316,7 @@ impl Client { ironrdp_pdu::Action::X224 => { // X224 PDU, process it and send any immediate response frames to the write loop // for writing to the RDP server. - let res = match Client::x224_process(x224_processor.clone(), frame).await { - Ok(res) => res, - Err(e) => { - if let Some(ee) = e.source() { - if ee.is::() { - warn!("Deactivate"); - let mut connector = ClientConnector { - config: config.clone(), - state: CapabilitiesExchange { - io_channel_id, - user_channel_id, - }, - server_addr: None, - static_channels: Default::default(), - }; - - let mut buf = WriteBuf::new(); - loop { - let written = single_connect_step_read( - &mut read_stream, - &mut connector, - &mut buf, - ) - .await?; - if let Some(_) = written.size() { - write_requester - .write_raw_pdu_async(buf.filled().to_vec()) - .await?; - } - if let ClientConnectorState::Connected { result } = - connector.state - { - break; - } - } - Vec::new() - } else { - return Err(e.into()); - } - } else { - return Err(e.into()); - } - } - }; - // Send response frames to write loop for writing to RDP server. + let res = Client::x224_process(x224_processor.clone(), frame).await?; for output in res { match output { ProcessorOutput::ResponseFrame(frame) => { @@ -425,8 +365,8 @@ impl Client { physical_width: 0, physical_height: 0, orientation: Orientation::Landscape, - desktop_scale_factor: 100, - device_scale_factor: 100, + desktop_scale_factor: 100, // percent; todo: can this be zero? + device_scale_factor: 100, // percent; todo: can this be zero? }], }); monitor_layout_pdu.to_buffer(&mut buf); From e259dbd504b6992224fe79eccf23406044a83a5f Mon Sep 17 00:00:00 2001 From: Isaiah Becker-Mayer Date: Thu, 7 Mar 2024 16:20:47 -0800 Subject: [PATCH 06/24] Hooks up resize listener on the client and sends changes as ClientScreenSpecs to the backend. Currently just gets logged in the WDS --- lib/srv/desktop/rdp/rdpclient/client.go | 4 ++ .../src/DesktopSession/DesktopSession.tsx | 2 + .../src/DesktopSession/useTdpClientCanvas.tsx | 41 ++++++++++--------- .../TdpClientCanvas/TdpClientCanvas.tsx | 17 ++++++++ 4 files changed, 44 insertions(+), 20 deletions(-) diff --git a/lib/srv/desktop/rdp/rdpclient/client.go b/lib/srv/desktop/rdp/rdpclient/client.go index e59b6b061acf..6c8ac1e38f68 100644 --- a/lib/srv/desktop/rdp/rdpclient/client.go +++ b/lib/srv/desktop/rdp/rdpclient/client.go @@ -393,6 +393,10 @@ func (c *Client) startInputStreaming(stopCh chan struct{}) error { c.UpdateClientActivity() switch m := msg.(type) { + case tdp.ClientScreenSpec: + // The client has changed its screen size. + c.cfg.Log.Debugf("Client changed screen size to %dx%d", m.Width, m.Height) + // TODO: send a message to the Rust client to resize the window. case tdp.MouseMove: mouseX, mouseY = m.X, m.Y if errCode := C.client_write_rdp_pointer( diff --git a/web/packages/teleport/src/DesktopSession/DesktopSession.tsx b/web/packages/teleport/src/DesktopSession/DesktopSession.tsx index a67cb1dfcddc..1c7054a2ff01 100644 --- a/web/packages/teleport/src/DesktopSession/DesktopSession.tsx +++ b/web/packages/teleport/src/DesktopSession/DesktopSession.tsx @@ -77,6 +77,7 @@ export function DesktopSession(props: State) { canvasOnMouseUp, canvasOnMouseWheelScroll, canvasOnContextMenu, + windowOnResize, clientScreenSpecToRequest, clipboardSharingState, onShareDirectory, @@ -169,6 +170,7 @@ export function DesktopSession(props: State) { canvasOnMouseUp={canvasOnMouseUp} canvasOnMouseWheelScroll={canvasOnMouseWheelScroll} canvasOnContextMenu={canvasOnContextMenu} + windowOnResize={windowOnResize} updatePointer={true} /> diff --git a/web/packages/teleport/src/DesktopSession/useTdpClientCanvas.tsx b/web/packages/teleport/src/DesktopSession/useTdpClientCanvas.tsx index 22bfae686050..05654b13c645 100644 --- a/web/packages/teleport/src/DesktopSession/useTdpClientCanvas.tsx +++ b/web/packages/teleport/src/DesktopSession/useTdpClientCanvas.tsx @@ -20,6 +20,7 @@ import { useState, useEffect, useRef } from 'react'; import { Attempt } from 'shared/hooks/useAttemptNext'; import { NotificationItem } from 'shared/components/Notification'; +import { throttle } from 'shared/utils/highbar'; import { TdpClient, ButtonState, ScrollAxis } from 'teleport/lib/tdp'; import { @@ -88,15 +89,12 @@ export default function useTdpClientCanvas(props: Props) { setTdpClient(new TdpClient(addr)); }, [clusterId, username, desktopName]); - const syncCanvasResolutionAndSize = (canvas: HTMLCanvasElement) => { - const { width, height } = getDisplaySize(); - - // Set a fixed canvas resolution and display size. This ensures - // that neither of these change when the user resizes the browser - // window. Instead, the canvas will remain the same size and the - // browser will add scrollbars if necessary. This is the behavior - // we want until https://github.com/gravitational/teleport/issues/9702 - // is resolved. + /** + * Synchronize the canvas resolution and display size with the + * given ClientScreenSpec. + */ + const syncCanvas = (canvas: HTMLCanvasElement, spec: ClientScreenSpec) => { + const { width, height } = spec; canvas.width = width; canvas.height = height; console.debug(`set canvas.width x canvas.height to ${width} x ${height}`); @@ -114,7 +112,7 @@ export default function useTdpClientCanvas(props: Props) { ) => { // The first image fragment we see signals a successful TDP connection. if (!initialTdpConnectionSucceeded.current) { - syncCanvasResolutionAndSize(ctx.canvas); + syncCanvas(ctx.canvas, getDisplaySize()); setTdpConnection({ status: 'success' }); initialTdpConnectionSucceeded.current = true; } @@ -128,7 +126,7 @@ export default function useTdpClientCanvas(props: Props) { ) => { // The first image fragment we see signals a successful TDP connection. if (!initialTdpConnectionSucceeded.current) { - syncCanvasResolutionAndSize(ctx.canvas); + syncCanvas(ctx.canvas, getDisplaySize()); setTdpConnection({ status: 'success' }); initialTdpConnectionSucceeded.current = true; } @@ -141,15 +139,7 @@ export default function useTdpClientCanvas(props: Props) { canvas: HTMLCanvasElement, spec: ClientScreenSpec ) => { - const { width, height } = spec; - canvas.width = width; - canvas.height = height; - console.debug(`set canvas.width x canvas.height to ${width} x ${height}`); - canvas.style.width = `${width}px`; - canvas.style.height = `${height}px`; - console.debug( - `set canvas.style.width x canvas.style.height to ${width} x ${height}` - ); + syncCanvas(canvas, spec); }; // Default TdpClientEvent.TDP_CLIPBOARD_DATA handler. @@ -282,6 +272,16 @@ export default function useTdpClientCanvas(props: Props) { // on the remote machine. const canvasOnContextMenu = () => false; + const windowOnResize = throttle( + (cli: TdpClient, canvas: HTMLCanvasElement) => { + // TODO: probably need to clear the canvas + const spec = getDisplaySize(); + syncCanvas(canvas, spec); + cli.sendClientScreenSpec(spec); + }, + 250 + ); + const sendLocalClipboardToRemote = async (cli: TdpClient) => { if (await sysClipboardGuard(clipboardSharingState, 'read')) { navigator.clipboard.readText().then(text => { @@ -317,6 +317,7 @@ export default function useTdpClientCanvas(props: Props) { canvasOnMouseUp, canvasOnMouseWheelScroll, canvasOnContextMenu, + windowOnResize, }; } diff --git a/web/packages/teleport/src/components/TdpClientCanvas/TdpClientCanvas.tsx b/web/packages/teleport/src/components/TdpClientCanvas/TdpClientCanvas.tsx index a03c1e05bc50..b4e12b6f9ee2 100644 --- a/web/packages/teleport/src/components/TdpClientCanvas/TdpClientCanvas.tsx +++ b/web/packages/teleport/src/components/TdpClientCanvas/TdpClientCanvas.tsx @@ -17,6 +17,7 @@ */ import React, { memo, useEffect, useRef } from 'react'; +import { DebouncedFunc } from 'shared/utils/highbar'; import { TdpClientEvent, TdpClient } from 'teleport/lib/tdp'; import { BitmapFrame } from 'teleport/lib/tdp/client'; @@ -50,6 +51,7 @@ function TdpClientCanvas(props: Props) { canvasOnMouseUp, canvasOnMouseWheelScroll, canvasOnContextMenu, + windowOnResize, style, updatePointer, } = props; @@ -372,6 +374,18 @@ function TdpClientCanvas(props: Props) { }; }, [client, canvasOnFocusOut]); + useEffect(() => { + if (client && windowOnResize) { + const canvas = canvasRef.current; + const _onresize = () => windowOnResize(client, canvas); + window.addEventListener('resize', _onresize); + return () => { + windowOnResize.cancel(); + window.removeEventListener('resize', _onresize); + }; + } + }, [client, windowOnResize]); + useEffect(() => { if (client) { const canvas = canvasRef.current; @@ -439,6 +453,9 @@ export type Props = { canvasOnMouseUp?: (cli: TdpClient, e: MouseEvent) => void; canvasOnMouseWheelScroll?: (cli: TdpClient, e: WheelEvent) => void; canvasOnContextMenu?: () => boolean; + windowOnResize?: DebouncedFunc< + (cli: TdpClient, canvas: HTMLCanvasElement) => void + >; style?: CSSProperties; updatePointer?: boolean; }; From 8ad9b6368acae90b914642185fd9394f9e0459a2 Mon Sep 17 00:00:00 2001 From: Isaiah Becker-Mayer Date: Sun, 10 Mar 2024 21:31:41 -0700 Subject: [PATCH 07/24] Handles the new DeactivateAll ProcessorOutput --- Cargo.lock | 13 -------- Cargo.toml | 33 ++++++++++++++------- lib/srv/desktop/rdp/rdpclient/src/client.rs | 28 +++++++++++++++-- web/packages/teleport/src/lib/tdp/client.ts | 3 ++ 4 files changed, 50 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7d596456a1ee..09e3bc2cdcc1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1225,7 +1225,6 @@ dependencies = [ [[package]] name = "ironrdp-async" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=def44ec32cd98e133635b143becfc23f9804a782#def44ec32cd98e133635b143becfc23f9804a782" dependencies = [ "bytes", "ironrdp-connector", @@ -1236,7 +1235,6 @@ dependencies = [ [[package]] name = "ironrdp-cliprdr" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=def44ec32cd98e133635b143becfc23f9804a782#def44ec32cd98e133635b143becfc23f9804a782" dependencies = [ "bitflags 2.4.2", "ironrdp-pdu", @@ -1248,7 +1246,6 @@ dependencies = [ [[package]] name = "ironrdp-connector" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=def44ec32cd98e133635b143becfc23f9804a782#def44ec32cd98e133635b143becfc23f9804a782" dependencies = [ "ironrdp-error", "ironrdp-pdu", @@ -1263,7 +1260,6 @@ dependencies = [ [[package]] name = "ironrdp-dvc" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=def44ec32cd98e133635b143becfc23f9804a782#def44ec32cd98e133635b143becfc23f9804a782" dependencies = [ "ironrdp-pdu", "ironrdp-svc", @@ -1274,12 +1270,10 @@ dependencies = [ [[package]] name = "ironrdp-error" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=def44ec32cd98e133635b143becfc23f9804a782#def44ec32cd98e133635b143becfc23f9804a782" [[package]] name = "ironrdp-graphics" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=def44ec32cd98e133635b143becfc23f9804a782#def44ec32cd98e133635b143becfc23f9804a782" dependencies = [ "bit_field", "bitflags 2.4.2", @@ -1296,7 +1290,6 @@ dependencies = [ [[package]] name = "ironrdp-pdu" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=def44ec32cd98e133635b143becfc23f9804a782#def44ec32cd98e133635b143becfc23f9804a782" dependencies = [ "bit_field", "bitflags 2.4.2", @@ -1318,7 +1311,6 @@ dependencies = [ [[package]] name = "ironrdp-rdpdr" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=def44ec32cd98e133635b143becfc23f9804a782#def44ec32cd98e133635b143becfc23f9804a782" dependencies = [ "bitflags 2.4.2", "ironrdp-error", @@ -1330,7 +1322,6 @@ dependencies = [ [[package]] name = "ironrdp-rdpsnd" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=def44ec32cd98e133635b143becfc23f9804a782#def44ec32cd98e133635b143becfc23f9804a782" dependencies = [ "ironrdp-pdu", "ironrdp-svc", @@ -1339,7 +1330,6 @@ dependencies = [ [[package]] name = "ironrdp-session" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=def44ec32cd98e133635b143becfc23f9804a782#def44ec32cd98e133635b143becfc23f9804a782" dependencies = [ "bitflags 2.4.2", "ironrdp-connector", @@ -1353,7 +1343,6 @@ dependencies = [ [[package]] name = "ironrdp-svc" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=def44ec32cd98e133635b143becfc23f9804a782#def44ec32cd98e133635b143becfc23f9804a782" dependencies = [ "bitflags 2.4.2", "ironrdp-pdu", @@ -1362,7 +1351,6 @@ dependencies = [ [[package]] name = "ironrdp-tls" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=def44ec32cd98e133635b143becfc23f9804a782#def44ec32cd98e133635b143becfc23f9804a782" dependencies = [ "tokio", "tokio-rustls", @@ -1372,7 +1360,6 @@ dependencies = [ [[package]] name = "ironrdp-tokio" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=def44ec32cd98e133635b143becfc23f9804a782#def44ec32cd98e133635b143becfc23f9804a782" dependencies = [ "bytes", "ironrdp-async", diff --git a/Cargo.toml b/Cargo.toml index 643d45d391e7..f3d85216d13c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,14 +23,25 @@ codegen-units = 1 [workspace.dependencies] # Note: To use a local IronRDP repository as a crate (for example, ironrdp-cliprdr), define the dependency as follows: # ironrdp-cliprdr = { path = "/path/to/local/IronRDP/crates/ironrdp-cliprdr" } -ironrdp-cliprdr = { git = "https://github.com/Devolutions/IronRDP", rev = "def44ec32cd98e133635b143becfc23f9804a782" } -ironrdp-connector = { git = "https://github.com/Devolutions/IronRDP", rev = "def44ec32cd98e133635b143becfc23f9804a782" } -ironrdp-graphics = { git = "https://github.com/Devolutions/IronRDP", rev = "def44ec32cd98e133635b143becfc23f9804a782" } -ironrdp-pdu = { git = "https://github.com/Devolutions/IronRDP", rev = "def44ec32cd98e133635b143becfc23f9804a782" } -ironrdp-rdpdr = { git = "https://github.com/Devolutions/IronRDP", rev = "def44ec32cd98e133635b143becfc23f9804a782" } -ironrdp-rdpsnd = { git = "https://github.com/Devolutions/IronRDP", rev = "def44ec32cd98e133635b143becfc23f9804a782" } -ironrdp-session = { git = "https://github.com/Devolutions/IronRDP", rev = "def44ec32cd98e133635b143becfc23f9804a782" } -ironrdp-svc = { git = "https://github.com/Devolutions/IronRDP", rev = "def44ec32cd98e133635b143becfc23f9804a782" } -ironrdp-dvc = { git = "https://github.com/Devolutions/IronRDP", rev = "def44ec32cd98e133635b143becfc23f9804a782" } -ironrdp-tls = { git = "https://github.com/Devolutions/IronRDP", rev = "def44ec32cd98e133635b143becfc23f9804a782", features = ["rustls"]} -ironrdp-tokio = { git = "https://github.com/Devolutions/IronRDP", rev = "def44ec32cd98e133635b143becfc23f9804a782" } +#ironrdp-cliprdr = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } +#ironrdp-connector = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } +#ironrdp-graphics = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } +#ironrdp-pdu = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } +#ironrdp-rdpdr = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } +#ironrdp-rdpsnd = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } +#ironrdp-session = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } +#ironrdp-svc = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } +#ironrdp-tls = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08", features = ["rustls"]} +#ironrdp-tokio = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } + +ironrdp-cliprdr = { path = "/Users/ibeckermayer/Devolutions/IronRDP/crates/ironrdp-cliprdr" } +ironrdp-connector = { path = "/Users/ibeckermayer/Devolutions/IronRDP/crates/ironrdp-connector" } +ironrdp-graphics = { path = "/Users/ibeckermayer/Devolutions/IronRDP/crates/ironrdp-graphics" } +ironrdp-pdu = { path = "/Users/ibeckermayer/Devolutions/IronRDP/crates/ironrdp-pdu" } +ironrdp-rdpdr = { path = "/Users/ibeckermayer/Devolutions/IronRDP/crates/ironrdp-rdpdr" } +ironrdp-rdpsnd = { path = "/Users/ibeckermayer/Devolutions/IronRDP/crates/ironrdp-rdpsnd" } +ironrdp-session = { path = "/Users/ibeckermayer/Devolutions/IronRDP/crates/ironrdp-session" } +ironrdp-svc = { path = "/Users/ibeckermayer/Devolutions/IronRDP/crates/ironrdp-svc" } +ironrdp-dvc = { path = "/Users/ibeckermayer/Devolutions/IronRDP/crates/ironrdp-dvc" } +ironrdp-tls = { path = "/Users/ibeckermayer/Devolutions/IronRDP/crates/ironrdp-tls", features = ["rustls"]} +ironrdp-tokio = { path = "/Users/ibeckermayer/Devolutions/IronRDP/crates/ironrdp-tokio" } diff --git a/lib/srv/desktop/rdp/rdpclient/src/client.rs b/lib/srv/desktop/rdp/rdpclient/src/client.rs index 1dbf8b0f64bd..7263013dbbb9 100644 --- a/lib/srv/desktop/rdp/rdpclient/src/client.rs +++ b/lib/srv/desktop/rdp/rdpclient/src/client.rs @@ -24,6 +24,7 @@ use crate::{ use boring::error::ErrorStack; use bytes::BytesMut; use ironrdp_cliprdr::{Cliprdr, CliprdrClient, CliprdrSvcMessages}; +use ironrdp_connector::connection_activation::ConnectionActivationState; use ironrdp_connector::{Config, ConnectorError, Credentials}; use ironrdp_dvc::DrdynvcClient; use ironrdp_pdu::dvc::display::{ClientPdu, Monitor, MonitorFlags, MonitorLayoutPdu, Orientation}; @@ -45,7 +46,7 @@ use ironrdp_session::x224::{self, ProcessorOutput}; use ironrdp_session::SessionErrorKind::Reason; use ironrdp_session::{reason_err, SessionError, SessionResult}; use ironrdp_svc::{SvcMessage, SvcProcessor, SvcProcessorMessages}; -use ironrdp_tokio::{Framed, TokioStream}; +use ironrdp_tokio::{single_connect_step_read, Framed, TokioStream}; use log::debug; use rand::{Rng, SeedableRng}; use std::fmt::{Debug, Display, Formatter}; @@ -213,6 +214,7 @@ impl Client { connection_result.io_channel_id, None, None, + connection_result.connection_activation, ); Ok(Self { @@ -316,8 +318,7 @@ impl Client { ironrdp_pdu::Action::X224 => { // X224 PDU, process it and send any immediate response frames to the write loop // for writing to the RDP server. - let res = Client::x224_process(x224_processor.clone(), frame).await?; - for output in res { + for output in Client::x224_process(x224_processor.clone(), frame).await? { match output { ProcessorOutput::ResponseFrame(frame) => { // Send response frames to write loop for writing to RDP server. @@ -326,6 +327,27 @@ impl Client { ProcessorOutput::Disconnect(reason) => { return Ok(Some(reason)); } + ProcessorOutput::DeactivateAll(mut sequence) => { + let mut buf = WriteBuf::new(); + loop { + let written = single_connect_step_read( + &mut read_stream, + &mut sequence, + &mut buf, + ) + .await?; + if let Some(_) = written.size() { + write_requester + .write_raw_pdu_async(buf.filled().to_vec()) + .await?; + } + if let ConnectionActivationState::Finalized { .. } = + sequence.state + { + break; + } + } + } } } } diff --git a/web/packages/teleport/src/lib/tdp/client.ts b/web/packages/teleport/src/lib/tdp/client.ts index 8781b4c1d7c0..c7745f7873dd 100644 --- a/web/packages/teleport/src/lib/tdp/client.ts +++ b/web/packages/teleport/src/lib/tdp/client.ts @@ -258,6 +258,7 @@ export default class Client extends EventEmitterWebAuthnSender { this.logger.warn(`received unsupported message type ${messageType}`); } } catch (err) { + console.error('Error in processMessage', err); this.handleError(err, TdpClientEvent.CLIENT_ERROR); } } @@ -364,6 +365,7 @@ export default class Client extends EventEmitterWebAuthnSender { } ); } catch (e) { + console.error('Error in handleRDPFastPathPDU', e); this.handleError(e, TdpClientEvent.CLIENT_ERROR); } } @@ -580,6 +582,7 @@ export default class Client extends EventEmitterWebAuthnSender { try { this.socket.send(data); } catch (e) { + console.error('Error in send', e); this.handleError(e, TdpClientEvent.CLIENT_ERROR); } return; From 7f262aae5d998ed55269838dc687e6f96782d75f Mon Sep 17 00:00:00 2001 From: Isaiah Becker-Mayer Date: Mon, 11 Mar 2024 17:55:13 -0700 Subject: [PATCH 08/24] hooks up client_write_screen_resize --- lib/srv/desktop/rdp/rdpclient/client.go | 9 +- lib/srv/desktop/rdp/rdpclient/src/client.rs | 127 ++++++++++++-------- lib/srv/desktop/rdp/rdpclient/src/lib.rs | 16 +++ 3 files changed, 99 insertions(+), 53 deletions(-) diff --git a/lib/srv/desktop/rdp/rdpclient/client.go b/lib/srv/desktop/rdp/rdpclient/client.go index 6c8ac1e38f68..0b44a0d5a0ca 100644 --- a/lib/srv/desktop/rdp/rdpclient/client.go +++ b/lib/srv/desktop/rdp/rdpclient/client.go @@ -394,9 +394,14 @@ func (c *Client) startInputStreaming(stopCh chan struct{}) error { switch m := msg.(type) { case tdp.ClientScreenSpec: - // The client has changed its screen size. c.cfg.Log.Debugf("Client changed screen size to %dx%d", m.Width, m.Height) - // TODO: send a message to the Rust client to resize the window. + if errCode := C.client_write_screen_resize( + C.ulong(c.handle), + C.uint32_t(m.Width), + C.uint32_t(m.Height), + ); errCode != C.ErrCodeSuccess { + return trace.Errorf("ClientScreenSpec: client_write_screen_resize: %v", errCode) + } case tdp.MouseMove: mouseX, mouseY = m.X, m.Y if errCode := C.client_write_rdp_pointer( diff --git a/lib/srv/desktop/rdp/rdpclient/src/client.rs b/lib/srv/desktop/rdp/rdpclient/src/client.rs index 7263013dbbb9..2e81a81cc1cf 100644 --- a/lib/srv/desktop/rdp/rdpclient/src/client.rs +++ b/lib/srv/desktop/rdp/rdpclient/src/client.rs @@ -27,7 +27,9 @@ use ironrdp_cliprdr::{Cliprdr, CliprdrClient, CliprdrSvcMessages}; use ironrdp_connector::connection_activation::ConnectionActivationState; use ironrdp_connector::{Config, ConnectorError, Credentials}; use ironrdp_dvc::DrdynvcClient; -use ironrdp_pdu::dvc::display::{ClientPdu, Monitor, MonitorFlags, MonitorLayoutPdu, Orientation}; +use ironrdp_pdu::dvc::display::{ + ClientPdu, DisplayPipelineError, Monitor, MonitorFlags, MonitorLayoutPdu, Orientation, +}; use ironrdp_pdu::input::fast_path::{ FastPathInput, FastPathInputEvent, KeyboardFlags, SynchronizeFlags, }; @@ -363,60 +365,10 @@ impl Client { x224_processor: Arc>, ) -> tokio::task::JoinHandle> { global::TOKIO_RT.spawn(async move { - let mut width = 800; - let mut height = 600; loop { match write_receiver.recv().await { Some(write_request) => match write_request { ClientFunction::WriteRdpKey(args) => { - debug!("Scan code: {}", args.code); - if args.code == 0x1E && args.down { - width = 1800 - width; - height = 1400 - height; - debug!("Trying to resize: {}", args.code); - - let mut buf = WriteBuf::new(); - let monitor_layout_pdu = - ClientPdu::DisplayControlMonitorLayout(MonitorLayoutPdu { - monitors: vec![Monitor { - flags: MonitorFlags::PRIMARY, - left: 0, - top: 0, - width: width as u32, - height: height as u32, - physical_width: 0, - physical_height: 0, - orientation: Orientation::Landscape, - desktop_scale_factor: 100, // percent; todo: can this be zero? - device_scale_factor: 100, // percent; todo: can this be zero? - }], - }); - monitor_layout_pdu.to_buffer(&mut buf); - - let prcessor = x224_processor.clone(); - let res: ClientResult = global::TOKIO_RT - .spawn_blocking(move || { - let mut buf2 = WriteBuf::new(); - let x224_processor = Self::x224_lock(&prcessor)?; - x224_processor.encode_dynamic( - &mut buf2, - dvc::display::CHANNEL_NAME, - buf.filled(), - )?; - Ok(buf2) - }) - .await?; - match res { - Ok(buf2) => { - let x = buf2.filled(); - debug!("Sending resize {}x{}, {:?}", width, height, x); - write_stream.write_all(x).await?; - } - Err(e) => { - debug!("Not OK {:?}", e); - } - } - } Client::write_rdp_key(&mut write_stream, args).await?; } ClientFunction::WriteRdpPointer(args) => { @@ -432,6 +384,15 @@ impl Client { Client::write_rdpdr(&mut write_stream, x224_processor.clone(), args) .await?; } + ClientFunction::WriteScreenResize(width, height) => { + Client::write_screen_resize( + &mut write_stream, + x224_processor.clone(), + width, + height, + ) + .await?; + } ClientFunction::HandleTdpSdAnnounce(sda) => { Client::handle_tdp_sd_announce( &mut write_stream, @@ -648,6 +609,51 @@ impl Client { Ok(()) } + /// Sends a screen resize to the RDP server. + async fn write_screen_resize( + write_stream: &mut RdpWriteStream, + x224_processor: Arc>, + width: u32, + height: u32, + ) -> ClientResult<()> { + let monitor_layout_buf = { + let mut monitor_layout_buf = WriteBuf::new(); + let monitor_layout_pdu = ClientPdu::DisplayControlMonitorLayout(MonitorLayoutPdu { + monitors: vec![Monitor { + flags: MonitorFlags::PRIMARY, + left: 0, + top: 0, + width, + height, + physical_width: 0, + physical_height: 0, + orientation: Orientation::Landscape, + desktop_scale_factor: 100, // percent; todo: can this be zero? + device_scale_factor: 100, // percent; todo: can this be zero? + }], + }); + monitor_layout_pdu.to_buffer(&mut monitor_layout_buf)?; + + Ok::<_, ClientError>(monitor_layout_buf) + }?; + + let full_dvc_buf = global::TOKIO_RT + .spawn_blocking(move || { + let mut full_dvc_buf = WriteBuf::new(); + let x224_processor = Self::x224_lock(&x224_processor)?; + x224_processor.encode_dynamic( + &mut full_dvc_buf, + dvc::display::CHANNEL_NAME, + monitor_layout_buf.filled(), + )?; + Ok::<_, ClientError>(full_dvc_buf) + }) + .await??; + + write_stream.write_all(full_dvc_buf.filled()).await?; + Ok(()) + } + async fn handle_tdp_sd_announce( write_stream: &mut RdpWriteStream, x224_processor: Arc>, @@ -918,6 +924,8 @@ enum ClientFunction { WriteRawPdu(Vec), /// Corresponds to [`Client::write_rdpdr`] WriteRdpdr(RdpdrPdu), + /// Corresponds to [`Client::write_screen_resize`] + WriteScreenResize(u32, u32), /// Corresponds to [`Client::handle_tdp_sd_announce`] HandleTdpSdAnnounce(tdp::SharedDirectoryAnnounce), /// Corresponds to [`Client::handle_tdp_sd_info_response`] @@ -996,6 +1004,15 @@ impl ClientHandle { self.send(ClientFunction::WriteRdpdr(pdu)).await } + pub fn write_screen_resize(&self, width: u32, height: u32) -> ClientResult<()> { + self.blocking_send(ClientFunction::WriteScreenResize(width, height)) + } + + pub async fn write_screen_resize_async(&self, width: u32, height: u32) -> ClientResult<()> { + self.send(ClientFunction::WriteScreenResize(width, height)) + .await + } + pub fn handle_tdp_sd_announce(&self, sda: tdp::SharedDirectoryAnnounce) -> ClientResult<()> { self.blocking_send(ClientFunction::HandleTdpSdAnnounce(sda)) } @@ -1234,6 +1251,7 @@ pub enum ClientError { ErrorStack(ErrorStack), #[cfg(feature = "fips")] HandshakeError(HandshakeError), + DisplayPipelineError(DisplayPipelineError), } impl std::error::Error for ClientError {} @@ -1259,6 +1277,7 @@ impl Display for ClientError { ClientError::ErrorStack(e) => Display::fmt(e, f), #[cfg(feature = "fips")] ClientError::HandshakeError(e) => Display::fmt(e, f), + ClientError::DisplayPipelineError(e) => Display::fmt(e, f), } } } @@ -1331,6 +1350,12 @@ impl From> for ClientError { } } +impl From for ClientError { + fn from(e: DisplayPipelineError) -> Self { + ClientError::DisplayPipelineError(e) + } +} + pub type ClientResult = Result; impl From for ClientResult<()> { diff --git a/lib/srv/desktop/rdp/rdpclient/src/lib.rs b/lib/srv/desktop/rdp/rdpclient/src/lib.rs index 8203f03150c2..662801d013dd 100644 --- a/lib/srv/desktop/rdp/rdpclient/src/lib.rs +++ b/lib/srv/desktop/rdp/rdpclient/src/lib.rs @@ -415,6 +415,22 @@ pub unsafe extern "C" fn client_write_rdp_sync_keys( ) } +/// # Safety +/// +/// `cgo_handle` must be a valid handle. +#[no_mangle] +pub unsafe extern "C" fn client_write_screen_resize( + cgo_handle: CgoHandle, + width: u32, + height: u32, +) -> CGOErrCode { + handle_operation( + cgo_handle, + "client_write_screen_resize", + move |client_handle| client_handle.write_screen_resize(width, height), + ) +} + #[repr(C)] pub struct CGOConnectParams { go_addr: *const c_char, From ce2ffa7b4e7879ef038db43784244213303153df Mon Sep 17 00:00:00 2001 From: Isaiah Becker-Mayer Date: Tue, 12 Mar 2024 15:03:23 -0700 Subject: [PATCH 09/24] Renames tdp Connection Initialized to Connection Activated This message is now used both after the connection is first established and after the connection executes a Deactivation-Reactivation Sequence. This fits snugly in to our existing message flow and ensures that the fast path processor is updated appropriately whenever a Deactivation-Reactivation Sequence is executed due to a resize event. --- lib/srv/desktop/rdp/rdpclient/client.go | 10 ++-- lib/srv/desktop/rdp/rdpclient/src/client.rs | 60 ++++++++++++++----- lib/srv/desktop/rdp/rdpclient/src/lib.rs | 2 +- lib/srv/desktop/tdp/proto.go | 18 +++--- rfd/0037-desktop-access-protocol.md | 7 ++- .../src/DesktopSession/useTdpClientCanvas.tsx | 2 +- web/packages/teleport/src/lib/tdp/client.ts | 13 ++-- web/packages/teleport/src/lib/tdp/codec.ts | 6 +- 8 files changed, 75 insertions(+), 43 deletions(-) diff --git a/lib/srv/desktop/rdp/rdpclient/client.go b/lib/srv/desktop/rdp/rdpclient/client.go index 0b44a0d5a0ca..64cff451eb57 100644 --- a/lib/srv/desktop/rdp/rdpclient/client.go +++ b/lib/srv/desktop/rdp/rdpclient/client.go @@ -693,8 +693,8 @@ func (c *Client) handleRDPFastPathPDU(data []byte) C.CGOErrCode { return C.ErrCodeSuccess } -//export cgo_handle_rdp_connection_initialized -func cgo_handle_rdp_connection_initialized( +//export cgo_handle_rdp_connection_activated +func cgo_handle_rdp_connection_activated( handle C.uintptr_t, io_channel_id C.uint16_t, user_channel_id C.uint16_t, @@ -705,17 +705,17 @@ func cgo_handle_rdp_connection_initialized( if err != nil { return C.ErrCodeFailure } - return client.handleRDPConnectionInitialized(io_channel_id, user_channel_id, screen_width, screen_height) + return client.handleRDPConnectionActivated(io_channel_id, user_channel_id, screen_width, screen_height) } -func (c *Client) handleRDPConnectionInitialized(ioChannelID, userChannelID, screenWidth, screenHeight C.uint16_t) C.CGOErrCode { +func (c *Client) handleRDPConnectionActivated(ioChannelID, userChannelID, screenWidth, screenHeight C.uint16_t) C.CGOErrCode { c.cfg.Log.Debugf("Received RDP channel IDs: io_channel_id=%d, user_channel_id=%d", ioChannelID, userChannelID) // Note: RDP doesn't always use the resolution we asked for. // This is especially true when we request dimensions that are not a multiple of 4. c.cfg.Log.Debugf("RDP server provided resolution of %dx%d", screenWidth, screenHeight) - if err := c.cfg.Conn.WriteMessage(tdp.ConnectionInitialized{ + if err := c.cfg.Conn.WriteMessage(tdp.ConnectionActivated{ IOChannelID: uint16(ioChannelID), UserChannelID: uint16(userChannelID), ScreenWidth: uint16(screenWidth), diff --git a/lib/srv/desktop/rdp/rdpclient/src/client.rs b/lib/srv/desktop/rdp/rdpclient/src/client.rs index 2e81a81cc1cf..7d96bf063703 100644 --- a/lib/srv/desktop/rdp/rdpclient/src/client.rs +++ b/lib/srv/desktop/rdp/rdpclient/src/client.rs @@ -16,7 +16,7 @@ pub mod global; use crate::rdpdr::tdp; use crate::{ - cgo_handle_fastpath_pdu, cgo_handle_rdp_connection_initialized, cgo_handle_remote_copy, ssl, + cgo_handle_fastpath_pdu, cgo_handle_rdp_connection_activated, cgo_handle_remote_copy, ssl, CGOErrCode, CGOKeyboardEvent, CGOMousePointerEvent, CGOPointerButton, CGOPointerWheel, CGOSyncKeys, CgoHandle, }; @@ -25,7 +25,7 @@ use boring::error::ErrorStack; use bytes::BytesMut; use ironrdp_cliprdr::{Cliprdr, CliprdrClient, CliprdrSvcMessages}; use ironrdp_connector::connection_activation::ConnectionActivationState; -use ironrdp_connector::{Config, ConnectorError, Credentials}; +use ironrdp_connector::{Config, ConnectorError, Credentials, DesktopSize}; use ironrdp_dvc::DrdynvcClient; use ironrdp_pdu::dvc::display::{ ClientPdu, DisplayPipelineError, Monitor, MonitorFlags, MonitorLayoutPdu, Orientation, @@ -194,15 +194,12 @@ impl Client { debug!("connection_result: {:?}", connection_result); // Register the RDP channels with the browser client. - unsafe { - ClientResult::from(cgo_handle_rdp_connection_initialized( - cgo_handle, - connection_result.io_channel_id, - connection_result.user_channel_id, - connection_result.desktop_size.width, - connection_result.desktop_size.height, - )) - }?; + Self::send_connection_activated( + cgo_handle, + connection_result.io_channel_id, + connection_result.user_channel_id, + connection_result.desktop_size, + )?; // Take the stream back out of the framed object for splitting. let rdp_stream = rdp_stream.into_inner_no_leftover(); @@ -330,6 +327,9 @@ impl Client { return Ok(Some(reason)); } ProcessorOutput::DeactivateAll(mut sequence) => { + // Execute the Deactivation-Reactivation Sequence: + // https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/dfc234ce-481a-4674-9a5d-2a7bafb14432 + debug!("Received Server Deactivate All PDU, executing Deactivation-Reactivation Sequence"); let mut buf = WriteBuf::new(); loop { let written = single_connect_step_read( @@ -338,14 +338,28 @@ impl Client { &mut buf, ) .await?; - if let Some(_) = written.size() { + + if written.size().is_some() { write_requester .write_raw_pdu_async(buf.filled().to_vec()) .await?; } - if let ConnectionActivationState::Finalized { .. } = - sequence.state + + if let ConnectionActivationState::Finalized { + io_channel_id, + user_channel_id, + desktop_size, + } = sequence.state { + // Upon completing the activation sequence, register the io/user channels + // and desktop size with the client, just like we do upon receiving the + // connection result in [`Self::connect`]. + Self::send_connection_activated( + cgo_handle, + io_channel_id, + user_channel_id, + desktop_size, + )?; break; } } @@ -452,6 +466,23 @@ impl Client { }) } + fn send_connection_activated( + cgo_handle: CgoHandle, + io_channel_id: u16, + user_channel_id: u16, + desktop_size: DesktopSize, + ) -> ClientResult<()> { + unsafe { + ClientResult::from(cgo_handle_rdp_connection_activated( + cgo_handle, + io_channel_id, + user_channel_id, + desktop_size.width, + desktop_size.height, + )) + } + } + async fn update_clipboard( x224_processor: Arc>, data: String, @@ -649,7 +680,6 @@ impl Client { Ok::<_, ClientError>(full_dvc_buf) }) .await??; - write_stream.write_all(full_dvc_buf.filled()).await?; Ok(()) } diff --git a/lib/srv/desktop/rdp/rdpclient/src/lib.rs b/lib/srv/desktop/rdp/rdpclient/src/lib.rs index 662801d013dd..9c777365924e 100644 --- a/lib/srv/desktop/rdp/rdpclient/src/lib.rs +++ b/lib/srv/desktop/rdp/rdpclient/src/lib.rs @@ -672,7 +672,7 @@ pub struct CGOSharedDirectoryListRequest { extern "C" { fn cgo_handle_remote_copy(cgo_handle: CgoHandle, data: *mut u8, len: u32) -> CGOErrCode; fn cgo_handle_fastpath_pdu(cgo_handle: CgoHandle, data: *mut u8, len: u32) -> CGOErrCode; - fn cgo_handle_rdp_connection_initialized( + fn cgo_handle_rdp_connection_activated( cgo_handle: CgoHandle, io_channel_id: u16, user_channel_id: u16, diff --git a/lib/srv/desktop/tdp/proto.go b/lib/srv/desktop/tdp/proto.go index 85091f1150d9..780144f9a882 100644 --- a/lib/srv/desktop/tdp/proto.go +++ b/lib/srv/desktop/tdp/proto.go @@ -123,7 +123,7 @@ func decodeMessage(firstByte byte, in byteReader) (Message, error) { case TypeRDPResponsePDU: return decodeRDPResponsePDU(in) case TypeRDPConnectionInitialized: - return decodeConnectionInitialized(in) + return decodeConnectionActivated(in) case TypeMouseMove: return decodeMouseMove(in) case TypeMouseButton: @@ -360,20 +360,24 @@ func (r RDPResponsePDU) Encode() ([]byte, error) { return buf.Bytes(), nil } -// ConnectionInitialized is sent to the browser when an RDP session is fully initialized. +// ConnectionActivated is sent to the browser when an RDP session is fully activated. +// This includes after the RDP connection is first initialized, or after executing a +// Deactivation-Reactivation Sequence. +// // It contains data that the browser needs in order to correctly handle the session. // // See "3. Channel Connection" at https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/023f1e69-cfe8-4ee6-9ee0-7e759fb4e4ee +// Also see 1.3.1.3 Deactivation-Reactivation Sequence: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/dfc234ce-481a-4674-9a5d-2a7bafb14432 // -// | message type (31) | io_channel_id uint16 | user_channel_id uint16 | -type ConnectionInitialized struct { +// | message type (31) | io_channel_id uint16 | user_channel_id uint16 | screen_width uint16 | screen_height uint16 | +type ConnectionActivated struct { IOChannelID uint16 UserChannelID uint16 ScreenWidth uint16 ScreenHeight uint16 } -func (c ConnectionInitialized) Encode() ([]byte, error) { +func (c ConnectionActivated) Encode() ([]byte, error) { buf := new(bytes.Buffer) buf.WriteByte(byte(TypeRDPConnectionInitialized)) writeUint16(buf, c.IOChannelID) @@ -383,8 +387,8 @@ func (c ConnectionInitialized) Encode() ([]byte, error) { return buf.Bytes(), nil } -func decodeConnectionInitialized(in byteReader) (ConnectionInitialized, error) { - var ids ConnectionInitialized +func decodeConnectionActivated(in byteReader) (ConnectionActivated, error) { + var ids ConnectionActivated err := binary.Read(in, binary.BigEndian, &ids) return ids, trace.Wrap(err) } diff --git a/rfd/0037-desktop-access-protocol.md b/rfd/0037-desktop-access-protocol.md index 0c9fe18caf60..0ce8ad184d58 100644 --- a/rfd/0037-desktop-access-protocol.md +++ b/rfd/0037-desktop-access-protocol.md @@ -283,11 +283,12 @@ Some messages passed to the TDP client via a FastPath Frame warrant a response, At the time of writing this message is used to send responses to RemoteFX frames, which occasionaly demand such, but in theory it can be used to carry any raw RDP response message intended to be written directly into the TDP server-side's RDP connection. -#### 31 - RDP Connection Initialized +#### 31 - RDP Connection Activated This message is sent from the server to the browser when a connection -is initialized. It contains data that the browser needs in order to -correctly handle the session. +is initialized, or after executing a [Deactivation-Reactivation Sequence](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/dfc234ce-481a-4674-9a5d-2a7bafb14432). +It contains data that the browser needs in order to correctly handle the +session. ``` | message type (31) | io_channel_id uint16 | user_channel_id uint16 | screen_width uint16 | screen_height uint16 | diff --git a/web/packages/teleport/src/DesktopSession/useTdpClientCanvas.tsx b/web/packages/teleport/src/DesktopSession/useTdpClientCanvas.tsx index 05654b13c645..64f1b14e8da0 100644 --- a/web/packages/teleport/src/DesktopSession/useTdpClientCanvas.tsx +++ b/web/packages/teleport/src/DesktopSession/useTdpClientCanvas.tsx @@ -277,7 +277,7 @@ export default function useTdpClientCanvas(props: Props) { // TODO: probably need to clear the canvas const spec = getDisplaySize(); syncCanvas(canvas, spec); - cli.sendClientScreenSpec(spec); + cli.resize(spec); }, 250 ); diff --git a/web/packages/teleport/src/lib/tdp/client.ts b/web/packages/teleport/src/lib/tdp/client.ts index c7745f7873dd..cc7c749634fe 100644 --- a/web/packages/teleport/src/lib/tdp/client.ts +++ b/web/packages/teleport/src/lib/tdp/client.ts @@ -195,8 +195,8 @@ export default class Client extends EventEmitterWebAuthnSender { case MessageType.PNG2_FRAME: this.handlePng2Frame(buffer); break; - case MessageType.RDP_CONNECTION_INITIALIZED: - this.handleRDPConnectionInitialized(buffer); + case MessageType.RDP_CONNECTION_ACTIVATED: + this.handleRDPConnectionActivated(buffer); break; case MessageType.RDP_FASTPATH_PDU: this.handleRDPFastPathPDU(buffer); @@ -258,7 +258,6 @@ export default class Client extends EventEmitterWebAuthnSender { this.logger.warn(`received unsupported message type ${messageType}`); } } catch (err) { - console.error('Error in processMessage', err); this.handleError(err, TdpClientEvent.CLIENT_ERROR); } } @@ -322,9 +321,9 @@ export default class Client extends EventEmitterWebAuthnSender { ); } - handleRDPConnectionInitialized(buffer: ArrayBuffer) { + handleRDPConnectionActivated(buffer: ArrayBuffer) { const { ioChannelId, userChannelId, screenWidth, screenHeight } = - this.codec.decodeRDPConnectionInitialied(buffer); + this.codec.decodeRDPConnectionActivated(buffer); const spec = { width: screenWidth, height: screenHeight }; this.logger.info( `setting screen spec received from server ${spec.width} x ${spec.height}` @@ -365,7 +364,6 @@ export default class Client extends EventEmitterWebAuthnSender { } ); } catch (e) { - console.error('Error in handleRDPFastPathPDU', e); this.handleError(e, TdpClientEvent.CLIENT_ERROR); } } @@ -582,7 +580,6 @@ export default class Client extends EventEmitterWebAuthnSender { try { this.socket.send(data); } catch (e) { - console.error('Error in send', e); this.handleError(e, TdpClientEvent.CLIENT_ERROR); } return; @@ -688,7 +685,7 @@ export default class Client extends EventEmitterWebAuthnSender { } resize(spec: ClientScreenSpec) { - this.send(this.codec.encodeClientScreenSpec(spec)); + this.sendClientScreenSpec(spec); } sendRDPResponsePDU(responseFrame: ArrayBuffer) { diff --git a/web/packages/teleport/src/lib/tdp/codec.ts b/web/packages/teleport/src/lib/tdp/codec.ts index bfca1ed008c5..c213785f429b 100644 --- a/web/packages/teleport/src/lib/tdp/codec.ts +++ b/web/packages/teleport/src/lib/tdp/codec.ts @@ -51,7 +51,7 @@ export enum MessageType { NOTIFICATION = 28, RDP_FASTPATH_PDU = 29, RDP_RESPONSE_PDU = 30, - RDP_CONNECTION_INITIALIZED = 31, + RDP_CONNECTION_ACTIVATED = 31, SYNC_KEYS = 32, __LAST, // utility value } @@ -106,7 +106,7 @@ export type ClipboardData = { }; // | message type (31) | io_channel_id uint16 | user_channel_id uint16 | screen_width uint16 | screen_height uint16 | -export type RDPConnectionInitialized = { +export type RDPConnectionActivated = { ioChannelId: number; userChannelId: number; screenWidth: number; @@ -846,7 +846,7 @@ export default class Codec { } // | message type (31) | io_channel_id uint16 | user_channel_id uint16 | screen_width uint16 | screen_height uint16 | - decodeRDPConnectionInitialied(buffer: ArrayBuffer): RDPConnectionInitialized { + decodeRDPConnectionActivated(buffer: ArrayBuffer): RDPConnectionActivated { const dv = new DataView(buffer); let offset = 0; offset += BYTE_LEN; // eat message type From 983d7cfaf19ce9263171ab8e63b4225a4a1c0c27 Mon Sep 17 00:00:00 2001 From: Isaiah Becker-Mayer Date: Tue, 12 Mar 2024 15:15:15 -0700 Subject: [PATCH 10/24] Switch monitor orientation based on width/height --- lib/srv/desktop/rdp/rdpclient/src/client.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/srv/desktop/rdp/rdpclient/src/client.rs b/lib/srv/desktop/rdp/rdpclient/src/client.rs index 7d96bf063703..adc08aefe9bc 100644 --- a/lib/srv/desktop/rdp/rdpclient/src/client.rs +++ b/lib/srv/desktop/rdp/rdpclient/src/client.rs @@ -648,7 +648,12 @@ impl Client { height: u32, ) -> ClientResult<()> { let monitor_layout_buf = { - let mut monitor_layout_buf = WriteBuf::new(); + let mut monitor_layout_buf = WriteBuf::new(); // TODO(isaiah): re-use this? + let orientation = if width > height { + Orientation::Landscape + } else { + Orientation::Portrait + }; let monitor_layout_pdu = ClientPdu::DisplayControlMonitorLayout(MonitorLayoutPdu { monitors: vec![Monitor { flags: MonitorFlags::PRIMARY, @@ -658,7 +663,7 @@ impl Client { height, physical_width: 0, physical_height: 0, - orientation: Orientation::Landscape, + orientation, desktop_scale_factor: 100, // percent; todo: can this be zero? device_scale_factor: 100, // percent; todo: can this be zero? }], From 5737054a35df5674f318997801ca9eba010167ba Mon Sep 17 00:00:00 2001 From: Isaiah Becker-Mayer Date: Tue, 12 Mar 2024 21:06:29 -0700 Subject: [PATCH 11/24] remove superfluous canvas size sync --- .../src/DesktopSession/useTdpClientCanvas.tsx | 13 ++++--------- .../components/TdpClientCanvas/TdpClientCanvas.tsx | 7 ++----- web/packages/teleport/src/lib/tdp/client.ts | 4 ++-- 3 files changed, 8 insertions(+), 16 deletions(-) diff --git a/web/packages/teleport/src/DesktopSession/useTdpClientCanvas.tsx b/web/packages/teleport/src/DesktopSession/useTdpClientCanvas.tsx index 64f1b14e8da0..5f0a1666ab7c 100644 --- a/web/packages/teleport/src/DesktopSession/useTdpClientCanvas.tsx +++ b/web/packages/teleport/src/DesktopSession/useTdpClientCanvas.tsx @@ -272,15 +272,10 @@ export default function useTdpClientCanvas(props: Props) { // on the remote machine. const canvasOnContextMenu = () => false; - const windowOnResize = throttle( - (cli: TdpClient, canvas: HTMLCanvasElement) => { - // TODO: probably need to clear the canvas - const spec = getDisplaySize(); - syncCanvas(canvas, spec); - cli.resize(spec); - }, - 250 - ); + const windowOnResize = throttle((cli: TdpClient) => { + const spec = getDisplaySize(); + cli.resize(spec); + }, 250); const sendLocalClipboardToRemote = async (cli: TdpClient) => { if (await sysClipboardGuard(clipboardSharingState, 'read')) { diff --git a/web/packages/teleport/src/components/TdpClientCanvas/TdpClientCanvas.tsx b/web/packages/teleport/src/components/TdpClientCanvas/TdpClientCanvas.tsx index b4e12b6f9ee2..db5aa27ce13e 100644 --- a/web/packages/teleport/src/components/TdpClientCanvas/TdpClientCanvas.tsx +++ b/web/packages/teleport/src/components/TdpClientCanvas/TdpClientCanvas.tsx @@ -376,8 +376,7 @@ function TdpClientCanvas(props: Props) { useEffect(() => { if (client && windowOnResize) { - const canvas = canvasRef.current; - const _onresize = () => windowOnResize(client, canvas); + const _onresize = () => windowOnResize(client); window.addEventListener('resize', _onresize); return () => { windowOnResize.cancel(); @@ -453,9 +452,7 @@ export type Props = { canvasOnMouseUp?: (cli: TdpClient, e: MouseEvent) => void; canvasOnMouseWheelScroll?: (cli: TdpClient, e: WheelEvent) => void; canvasOnContextMenu?: () => boolean; - windowOnResize?: DebouncedFunc< - (cli: TdpClient, canvas: HTMLCanvasElement) => void - >; + windowOnResize?: DebouncedFunc<(cli: TdpClient) => void>; style?: CSSProperties; updatePointer?: boolean; }; diff --git a/web/packages/teleport/src/lib/tdp/client.ts b/web/packages/teleport/src/lib/tdp/client.ts index cc7c749634fe..da41080b4879 100644 --- a/web/packages/teleport/src/lib/tdp/client.ts +++ b/web/packages/teleport/src/lib/tdp/client.ts @@ -172,7 +172,7 @@ export default class Client extends EventEmitterWebAuthnSender { spec: ClientScreenSpec ) { this.logger.debug( - `initializing fast path processor with screen spec ${spec.width} x ${spec.height}` + `setting up fast path processor with screen spec ${spec.width} x ${spec.height}` ); this.fastPathProcessor = new FastPathProcessor( @@ -326,7 +326,7 @@ export default class Client extends EventEmitterWebAuthnSender { this.codec.decodeRDPConnectionActivated(buffer); const spec = { width: screenWidth, height: screenHeight }; this.logger.info( - `setting screen spec received from server ${spec.width} x ${spec.height}` + `screen spec received from server ${spec.width} x ${spec.height}` ); this.initFastPathProcessor(ioChannelId, userChannelId, { From f5ffe835748e37db53d19c3eb22b60804369ac69 Mon Sep 17 00:00:00 2001 From: Isaiah Becker-Mayer Date: Tue, 19 Mar 2024 20:50:03 -0700 Subject: [PATCH 12/24] Updates to the most up-to-date hash for IronRDP (not merged to master). Screen resize works in this commit, though its still the case that if you do so before the channel is announced by the rdp server, it will end the session --- Cargo.lock | 15 +++ Cargo.toml | 33 ++---- lib/srv/desktop/rdp/rdpclient/src/client.rs | 114 ++++++++++--------- web/packages/teleport/src/ironrdp/src/lib.rs | 4 +- 4 files changed, 90 insertions(+), 76 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 09e3bc2cdcc1..093affd0be3c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1225,6 +1225,7 @@ dependencies = [ [[package]] name = "ironrdp-async" version = "0.1.0" +source = "git+https://github.com/Devolutions/IronRDP?rev=4dccd6e21b70e79c0acb4c62de131acf2047bf0d#4dccd6e21b70e79c0acb4c62de131acf2047bf0d" dependencies = [ "bytes", "ironrdp-connector", @@ -1235,6 +1236,7 @@ dependencies = [ [[package]] name = "ironrdp-cliprdr" version = "0.1.0" +source = "git+https://github.com/Devolutions/IronRDP?rev=4dccd6e21b70e79c0acb4c62de131acf2047bf0d#4dccd6e21b70e79c0acb4c62de131acf2047bf0d" dependencies = [ "bitflags 2.4.2", "ironrdp-pdu", @@ -1246,6 +1248,7 @@ dependencies = [ [[package]] name = "ironrdp-connector" version = "0.1.0" +source = "git+https://github.com/Devolutions/IronRDP?rev=4dccd6e21b70e79c0acb4c62de131acf2047bf0d#4dccd6e21b70e79c0acb4c62de131acf2047bf0d" dependencies = [ "ironrdp-error", "ironrdp-pdu", @@ -1260,7 +1263,9 @@ dependencies = [ [[package]] name = "ironrdp-dvc" version = "0.1.0" +source = "git+https://github.com/Devolutions/IronRDP?rev=4dccd6e21b70e79c0acb4c62de131acf2047bf0d#4dccd6e21b70e79c0acb4c62de131acf2047bf0d" dependencies = [ + "bitflags 2.4.2", "ironrdp-pdu", "ironrdp-svc", "slab", @@ -1270,10 +1275,12 @@ dependencies = [ [[package]] name = "ironrdp-error" version = "0.1.0" +source = "git+https://github.com/Devolutions/IronRDP?rev=4dccd6e21b70e79c0acb4c62de131acf2047bf0d#4dccd6e21b70e79c0acb4c62de131acf2047bf0d" [[package]] name = "ironrdp-graphics" version = "0.1.0" +source = "git+https://github.com/Devolutions/IronRDP?rev=4dccd6e21b70e79c0acb4c62de131acf2047bf0d#4dccd6e21b70e79c0acb4c62de131acf2047bf0d" dependencies = [ "bit_field", "bitflags 2.4.2", @@ -1290,6 +1297,7 @@ dependencies = [ [[package]] name = "ironrdp-pdu" version = "0.1.0" +source = "git+https://github.com/Devolutions/IronRDP?rev=4dccd6e21b70e79c0acb4c62de131acf2047bf0d#4dccd6e21b70e79c0acb4c62de131acf2047bf0d" dependencies = [ "bit_field", "bitflags 2.4.2", @@ -1311,6 +1319,7 @@ dependencies = [ [[package]] name = "ironrdp-rdpdr" version = "0.1.0" +source = "git+https://github.com/Devolutions/IronRDP?rev=4dccd6e21b70e79c0acb4c62de131acf2047bf0d#4dccd6e21b70e79c0acb4c62de131acf2047bf0d" dependencies = [ "bitflags 2.4.2", "ironrdp-error", @@ -1322,6 +1331,7 @@ dependencies = [ [[package]] name = "ironrdp-rdpsnd" version = "0.1.0" +source = "git+https://github.com/Devolutions/IronRDP?rev=4dccd6e21b70e79c0acb4c62de131acf2047bf0d#4dccd6e21b70e79c0acb4c62de131acf2047bf0d" dependencies = [ "ironrdp-pdu", "ironrdp-svc", @@ -1330,9 +1340,11 @@ dependencies = [ [[package]] name = "ironrdp-session" version = "0.1.0" +source = "git+https://github.com/Devolutions/IronRDP?rev=4dccd6e21b70e79c0acb4c62de131acf2047bf0d#4dccd6e21b70e79c0acb4c62de131acf2047bf0d" dependencies = [ "bitflags 2.4.2", "ironrdp-connector", + "ironrdp-dvc", "ironrdp-error", "ironrdp-graphics", "ironrdp-pdu", @@ -1343,6 +1355,7 @@ dependencies = [ [[package]] name = "ironrdp-svc" version = "0.1.0" +source = "git+https://github.com/Devolutions/IronRDP?rev=4dccd6e21b70e79c0acb4c62de131acf2047bf0d#4dccd6e21b70e79c0acb4c62de131acf2047bf0d" dependencies = [ "bitflags 2.4.2", "ironrdp-pdu", @@ -1351,6 +1364,7 @@ dependencies = [ [[package]] name = "ironrdp-tls" version = "0.1.0" +source = "git+https://github.com/Devolutions/IronRDP?rev=4dccd6e21b70e79c0acb4c62de131acf2047bf0d#4dccd6e21b70e79c0acb4c62de131acf2047bf0d" dependencies = [ "tokio", "tokio-rustls", @@ -1360,6 +1374,7 @@ dependencies = [ [[package]] name = "ironrdp-tokio" version = "0.1.0" +source = "git+https://github.com/Devolutions/IronRDP?rev=4dccd6e21b70e79c0acb4c62de131acf2047bf0d#4dccd6e21b70e79c0acb4c62de131acf2047bf0d" dependencies = [ "bytes", "ironrdp-async", diff --git a/Cargo.toml b/Cargo.toml index f3d85216d13c..9c7354a0eb21 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,25 +23,14 @@ codegen-units = 1 [workspace.dependencies] # Note: To use a local IronRDP repository as a crate (for example, ironrdp-cliprdr), define the dependency as follows: # ironrdp-cliprdr = { path = "/path/to/local/IronRDP/crates/ironrdp-cliprdr" } -#ironrdp-cliprdr = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } -#ironrdp-connector = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } -#ironrdp-graphics = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } -#ironrdp-pdu = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } -#ironrdp-rdpdr = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } -#ironrdp-rdpsnd = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } -#ironrdp-session = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } -#ironrdp-svc = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } -#ironrdp-tls = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08", features = ["rustls"]} -#ironrdp-tokio = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" } - -ironrdp-cliprdr = { path = "/Users/ibeckermayer/Devolutions/IronRDP/crates/ironrdp-cliprdr" } -ironrdp-connector = { path = "/Users/ibeckermayer/Devolutions/IronRDP/crates/ironrdp-connector" } -ironrdp-graphics = { path = "/Users/ibeckermayer/Devolutions/IronRDP/crates/ironrdp-graphics" } -ironrdp-pdu = { path = "/Users/ibeckermayer/Devolutions/IronRDP/crates/ironrdp-pdu" } -ironrdp-rdpdr = { path = "/Users/ibeckermayer/Devolutions/IronRDP/crates/ironrdp-rdpdr" } -ironrdp-rdpsnd = { path = "/Users/ibeckermayer/Devolutions/IronRDP/crates/ironrdp-rdpsnd" } -ironrdp-session = { path = "/Users/ibeckermayer/Devolutions/IronRDP/crates/ironrdp-session" } -ironrdp-svc = { path = "/Users/ibeckermayer/Devolutions/IronRDP/crates/ironrdp-svc" } -ironrdp-dvc = { path = "/Users/ibeckermayer/Devolutions/IronRDP/crates/ironrdp-dvc" } -ironrdp-tls = { path = "/Users/ibeckermayer/Devolutions/IronRDP/crates/ironrdp-tls", features = ["rustls"]} -ironrdp-tokio = { path = "/Users/ibeckermayer/Devolutions/IronRDP/crates/ironrdp-tokio" } +ironrdp-cliprdr = { git = "https://github.com/Devolutions/IronRDP", rev = "4dccd6e21b70e79c0acb4c62de131acf2047bf0d" } +ironrdp-connector = { git = "https://github.com/Devolutions/IronRDP", rev = "4dccd6e21b70e79c0acb4c62de131acf2047bf0d" } +ironrdp-dvc = { git = "https://github.com/Devolutions/IronRDP", rev = "4dccd6e21b70e79c0acb4c62de131acf2047bf0d" } +ironrdp-graphics = { git = "https://github.com/Devolutions/IronRDP", rev = "4dccd6e21b70e79c0acb4c62de131acf2047bf0d" } +ironrdp-pdu = { git = "https://github.com/Devolutions/IronRDP", rev = "4dccd6e21b70e79c0acb4c62de131acf2047bf0d" } +ironrdp-rdpdr = { git = "https://github.com/Devolutions/IronRDP", rev = "4dccd6e21b70e79c0acb4c62de131acf2047bf0d" } +ironrdp-rdpsnd = { git = "https://github.com/Devolutions/IronRDP", rev = "4dccd6e21b70e79c0acb4c62de131acf2047bf0d" } +ironrdp-session = { git = "https://github.com/Devolutions/IronRDP", rev = "4dccd6e21b70e79c0acb4c62de131acf2047bf0d" } +ironrdp-svc = { git = "https://github.com/Devolutions/IronRDP", rev = "4dccd6e21b70e79c0acb4c62de131acf2047bf0d" } +ironrdp-tls = { git = "https://github.com/Devolutions/IronRDP", rev = "4dccd6e21b70e79c0acb4c62de131acf2047bf0d", features = ["rustls"]} +ironrdp-tokio = { git = "https://github.com/Devolutions/IronRDP", rev = "4dccd6e21b70e79c0acb4c62de131acf2047bf0d" } diff --git a/lib/srv/desktop/rdp/rdpclient/src/client.rs b/lib/srv/desktop/rdp/rdpclient/src/client.rs index adc08aefe9bc..6c4ee5f8bd90 100644 --- a/lib/srv/desktop/rdp/rdpclient/src/client.rs +++ b/lib/srv/desktop/rdp/rdpclient/src/client.rs @@ -26,10 +26,10 @@ use bytes::BytesMut; use ironrdp_cliprdr::{Cliprdr, CliprdrClient, CliprdrSvcMessages}; use ironrdp_connector::connection_activation::ConnectionActivationState; use ironrdp_connector::{Config, ConnectorError, Credentials, DesktopSize}; +use ironrdp_dvc::display::{Monitor, MonitorFlags, Orientation}; use ironrdp_dvc::DrdynvcClient; -use ironrdp_pdu::dvc::display::{ - ClientPdu, DisplayPipelineError, Monitor, MonitorFlags, MonitorLayoutPdu, Orientation, -}; +use ironrdp_dvc::DynamicChannelId; +use ironrdp_dvc::{display::DisplayControlClient, DvcProcessor}; use ironrdp_pdu::input::fast_path::{ FastPathInput, FastPathInputEvent, KeyboardFlags, SynchronizeFlags, }; @@ -39,7 +39,7 @@ use ironrdp_pdu::mcs::DisconnectReason; use ironrdp_pdu::rdp::capability_sets::MajorPlatformType; use ironrdp_pdu::rdp::RdpError; use ironrdp_pdu::write_buf::WriteBuf; -use ironrdp_pdu::{custom_err, dvc, function, PduError, PduParsing}; +use ironrdp_pdu::{custom_err, function, PduError, PduParsing}; use ironrdp_rdpdr::pdu::efs::ClientDeviceListAnnounce; use ironrdp_rdpdr::pdu::RdpdrPdu; use ironrdp_rdpdr::Rdpdr; @@ -157,7 +157,9 @@ impl Client { let mut connector = ironrdp_connector::ClientConnector::new(connector_config.clone()) .with_server_addr(server_socket_addr) - .with_static_channel(DrdynvcClient::new()) + .with_static_channel( + DrdynvcClient::new().with_dynamic_channel(DisplayControlClient::new()), + ) .with_static_channel(Rdpsnd::new()) // required for rdpdr to work .with_static_channel(rdpdr); @@ -211,8 +213,6 @@ impl Client { connection_result.static_channels, connection_result.user_channel_id, connection_result.io_channel_id, - None, - None, connection_result.connection_activation, ); @@ -647,45 +647,49 @@ impl Client { width: u32, height: u32, ) -> ClientResult<()> { - let monitor_layout_buf = { - let mut monitor_layout_buf = WriteBuf::new(); // TODO(isaiah): re-use this? - let orientation = if width > height { - Orientation::Landscape - } else { - Orientation::Portrait - }; - let monitor_layout_pdu = ClientPdu::DisplayControlMonitorLayout(MonitorLayoutPdu { - monitors: vec![Monitor { - flags: MonitorFlags::PRIMARY, - left: 0, - top: 0, - width, - height, - physical_width: 0, - physical_height: 0, - orientation, - desktop_scale_factor: 100, // percent; todo: can this be zero? - device_scale_factor: 100, // percent; todo: can this be zero? - }], - }); - monitor_layout_pdu.to_buffer(&mut monitor_layout_buf)?; - - Ok::<_, ClientError>(monitor_layout_buf) - }?; - - let full_dvc_buf = global::TOKIO_RT + let cloned = x224_processor.clone(); + let messages = global::TOKIO_RT .spawn_blocking(move || { - let mut full_dvc_buf = WriteBuf::new(); - let x224_processor = Self::x224_lock(&x224_processor)?; - x224_processor.encode_dynamic( - &mut full_dvc_buf, - dvc::display::CHANNEL_NAME, - monitor_layout_buf.filled(), - )?; - Ok::<_, ClientError>(full_dvc_buf) + let x224_processor = Self::x224_lock(&cloned)?; + let (disp_ctl_cli, channel_id): (&DisplayControlClient, Option) = + Self::get_dvc_processor::(&x224_processor)?; + + if channel_id.is_none() { + return Err(ClientError::InternalError( + "DisplayControlClient channel not found".to_string(), + )); + } + + Ok::<_, ClientError>(disp_ctl_cli.encode_monitors( + channel_id.unwrap(), + vec![Monitor { + flags: MonitorFlags::PRIMARY, + left: 0, + top: 0, + width, + height, + physical_width: 0, + physical_height: 0, + orientation: if width > height { + Orientation::Landscape + } else { + Orientation::Portrait + }, + desktop_scale_factor: 100, // percent; todo: can this be zero? + device_scale_factor: 100, // percent; todo: can this be zero? + }], + )) }) - .await??; - write_stream.write_all(full_dvc_buf.filled()).await?; + .await???; + + let encoded = Client::x224_process_svc_messages( + x224_processor, + SvcProcessorMessages::::new(messages), + ) + .await?; + + write_stream.write_all(&encoded).await?; + Ok(()) } @@ -912,6 +916,20 @@ impl Client { ))) } + fn get_dvc_processor<'a, S>( + x224_processor: &'a MutexGuard<'_, x224::Processor>, + ) -> Result<(&'a S, Option), ClientError> + where + S: DvcProcessor + 'static, + { + x224_processor + .get_dvc_processor::() + .ok_or(ClientError::InternalError(format!( + "get_dvc_processor::<{}>() returned None", + std::any::type_name::(), + ))) + } + /// Returns a mutable reference to the [`TeleportCliprdrBackend`] of the [`Cliprdr`] processor. fn cliprdr_backend( x224_processor: &mut x224::Processor, @@ -1286,7 +1304,6 @@ pub enum ClientError { ErrorStack(ErrorStack), #[cfg(feature = "fips")] HandshakeError(HandshakeError), - DisplayPipelineError(DisplayPipelineError), } impl std::error::Error for ClientError {} @@ -1312,7 +1329,6 @@ impl Display for ClientError { ClientError::ErrorStack(e) => Display::fmt(e, f), #[cfg(feature = "fips")] ClientError::HandshakeError(e) => Display::fmt(e, f), - ClientError::DisplayPipelineError(e) => Display::fmt(e, f), } } } @@ -1385,12 +1401,6 @@ impl From> for ClientError { } } -impl From for ClientError { - fn from(e: DisplayPipelineError) -> Self { - ClientError::DisplayPipelineError(e) - } -} - pub type ClientResult = Result; impl From for ClientResult<()> { diff --git a/web/packages/teleport/src/ironrdp/src/lib.rs b/web/packages/teleport/src/ironrdp/src/lib.rs index fc908431b336..233732d7ccb5 100644 --- a/web/packages/teleport/src/ironrdp/src/lib.rs +++ b/web/packages/teleport/src/ironrdp/src/lib.rs @@ -184,9 +184,9 @@ impl FastPathProcessor { /// /// `respond_cb: (responseFrame: ArrayBuffer) => void` /// + /// If `data` is `false` we hide the cursor (but remember its value), if `data` is `true` we restore + /// the last cursor value; otherwise we set the cursor to a bitmap from `ImageData`. /// `update_pointer_cb: (data: ImageData | boolean, hotspot_x: number, hotspot_y: number) => void` - /// if data is `false` we hide cursor but remember its value, if data is `true` we restore last - /// cursor value, otherwise we set cursor to bitmapt from `ImageData` pub fn process( &mut self, tdp_fast_path_frame: &[u8], From ad84d3703ba42f95013ae6bce81f458c749db59e Mon Sep 17 00:00:00 2001 From: Isaiah Becker-Mayer Date: Tue, 19 Mar 2024 21:42:18 -0700 Subject: [PATCH 13/24] Updates to the most recent hash for IronRDP feat/dynamic-resize --- Cargo.lock | 26 +++++++++++++------------- Cargo.toml | 22 +++++++++++----------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 093affd0be3c..066b36b14996 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1225,7 +1225,7 @@ dependencies = [ [[package]] name = "ironrdp-async" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=4dccd6e21b70e79c0acb4c62de131acf2047bf0d#4dccd6e21b70e79c0acb4c62de131acf2047bf0d" +source = "git+https://github.com/Devolutions/IronRDP?rev=ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9#ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" dependencies = [ "bytes", "ironrdp-connector", @@ -1236,7 +1236,7 @@ dependencies = [ [[package]] name = "ironrdp-cliprdr" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=4dccd6e21b70e79c0acb4c62de131acf2047bf0d#4dccd6e21b70e79c0acb4c62de131acf2047bf0d" +source = "git+https://github.com/Devolutions/IronRDP?rev=ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9#ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" dependencies = [ "bitflags 2.4.2", "ironrdp-pdu", @@ -1248,7 +1248,7 @@ dependencies = [ [[package]] name = "ironrdp-connector" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=4dccd6e21b70e79c0acb4c62de131acf2047bf0d#4dccd6e21b70e79c0acb4c62de131acf2047bf0d" +source = "git+https://github.com/Devolutions/IronRDP?rev=ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9#ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" dependencies = [ "ironrdp-error", "ironrdp-pdu", @@ -1263,7 +1263,7 @@ dependencies = [ [[package]] name = "ironrdp-dvc" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=4dccd6e21b70e79c0acb4c62de131acf2047bf0d#4dccd6e21b70e79c0acb4c62de131acf2047bf0d" +source = "git+https://github.com/Devolutions/IronRDP?rev=ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9#ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" dependencies = [ "bitflags 2.4.2", "ironrdp-pdu", @@ -1275,12 +1275,12 @@ dependencies = [ [[package]] name = "ironrdp-error" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=4dccd6e21b70e79c0acb4c62de131acf2047bf0d#4dccd6e21b70e79c0acb4c62de131acf2047bf0d" +source = "git+https://github.com/Devolutions/IronRDP?rev=ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9#ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" [[package]] name = "ironrdp-graphics" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=4dccd6e21b70e79c0acb4c62de131acf2047bf0d#4dccd6e21b70e79c0acb4c62de131acf2047bf0d" +source = "git+https://github.com/Devolutions/IronRDP?rev=ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9#ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" dependencies = [ "bit_field", "bitflags 2.4.2", @@ -1297,7 +1297,7 @@ dependencies = [ [[package]] name = "ironrdp-pdu" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=4dccd6e21b70e79c0acb4c62de131acf2047bf0d#4dccd6e21b70e79c0acb4c62de131acf2047bf0d" +source = "git+https://github.com/Devolutions/IronRDP?rev=ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9#ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" dependencies = [ "bit_field", "bitflags 2.4.2", @@ -1319,7 +1319,7 @@ dependencies = [ [[package]] name = "ironrdp-rdpdr" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=4dccd6e21b70e79c0acb4c62de131acf2047bf0d#4dccd6e21b70e79c0acb4c62de131acf2047bf0d" +source = "git+https://github.com/Devolutions/IronRDP?rev=ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9#ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" dependencies = [ "bitflags 2.4.2", "ironrdp-error", @@ -1331,7 +1331,7 @@ dependencies = [ [[package]] name = "ironrdp-rdpsnd" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=4dccd6e21b70e79c0acb4c62de131acf2047bf0d#4dccd6e21b70e79c0acb4c62de131acf2047bf0d" +source = "git+https://github.com/Devolutions/IronRDP?rev=ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9#ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" dependencies = [ "ironrdp-pdu", "ironrdp-svc", @@ -1340,7 +1340,7 @@ dependencies = [ [[package]] name = "ironrdp-session" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=4dccd6e21b70e79c0acb4c62de131acf2047bf0d#4dccd6e21b70e79c0acb4c62de131acf2047bf0d" +source = "git+https://github.com/Devolutions/IronRDP?rev=ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9#ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" dependencies = [ "bitflags 2.4.2", "ironrdp-connector", @@ -1355,7 +1355,7 @@ dependencies = [ [[package]] name = "ironrdp-svc" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=4dccd6e21b70e79c0acb4c62de131acf2047bf0d#4dccd6e21b70e79c0acb4c62de131acf2047bf0d" +source = "git+https://github.com/Devolutions/IronRDP?rev=ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9#ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" dependencies = [ "bitflags 2.4.2", "ironrdp-pdu", @@ -1364,7 +1364,7 @@ dependencies = [ [[package]] name = "ironrdp-tls" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=4dccd6e21b70e79c0acb4c62de131acf2047bf0d#4dccd6e21b70e79c0acb4c62de131acf2047bf0d" +source = "git+https://github.com/Devolutions/IronRDP?rev=ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9#ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" dependencies = [ "tokio", "tokio-rustls", @@ -1374,7 +1374,7 @@ dependencies = [ [[package]] name = "ironrdp-tokio" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=4dccd6e21b70e79c0acb4c62de131acf2047bf0d#4dccd6e21b70e79c0acb4c62de131acf2047bf0d" +source = "git+https://github.com/Devolutions/IronRDP?rev=ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9#ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" dependencies = [ "bytes", "ironrdp-async", diff --git a/Cargo.toml b/Cargo.toml index 9c7354a0eb21..bf8a46980194 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,14 +23,14 @@ codegen-units = 1 [workspace.dependencies] # Note: To use a local IronRDP repository as a crate (for example, ironrdp-cliprdr), define the dependency as follows: # ironrdp-cliprdr = { path = "/path/to/local/IronRDP/crates/ironrdp-cliprdr" } -ironrdp-cliprdr = { git = "https://github.com/Devolutions/IronRDP", rev = "4dccd6e21b70e79c0acb4c62de131acf2047bf0d" } -ironrdp-connector = { git = "https://github.com/Devolutions/IronRDP", rev = "4dccd6e21b70e79c0acb4c62de131acf2047bf0d" } -ironrdp-dvc = { git = "https://github.com/Devolutions/IronRDP", rev = "4dccd6e21b70e79c0acb4c62de131acf2047bf0d" } -ironrdp-graphics = { git = "https://github.com/Devolutions/IronRDP", rev = "4dccd6e21b70e79c0acb4c62de131acf2047bf0d" } -ironrdp-pdu = { git = "https://github.com/Devolutions/IronRDP", rev = "4dccd6e21b70e79c0acb4c62de131acf2047bf0d" } -ironrdp-rdpdr = { git = "https://github.com/Devolutions/IronRDP", rev = "4dccd6e21b70e79c0acb4c62de131acf2047bf0d" } -ironrdp-rdpsnd = { git = "https://github.com/Devolutions/IronRDP", rev = "4dccd6e21b70e79c0acb4c62de131acf2047bf0d" } -ironrdp-session = { git = "https://github.com/Devolutions/IronRDP", rev = "4dccd6e21b70e79c0acb4c62de131acf2047bf0d" } -ironrdp-svc = { git = "https://github.com/Devolutions/IronRDP", rev = "4dccd6e21b70e79c0acb4c62de131acf2047bf0d" } -ironrdp-tls = { git = "https://github.com/Devolutions/IronRDP", rev = "4dccd6e21b70e79c0acb4c62de131acf2047bf0d", features = ["rustls"]} -ironrdp-tokio = { git = "https://github.com/Devolutions/IronRDP", rev = "4dccd6e21b70e79c0acb4c62de131acf2047bf0d" } +ironrdp-cliprdr = { git = "https://github.com/Devolutions/IronRDP", rev = "ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" } +ironrdp-connector = { git = "https://github.com/Devolutions/IronRDP", rev = "ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" } +ironrdp-dvc = { git = "https://github.com/Devolutions/IronRDP", rev = "ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" } +ironrdp-graphics = { git = "https://github.com/Devolutions/IronRDP", rev = "ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" } +ironrdp-pdu = { git = "https://github.com/Devolutions/IronRDP", rev = "ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" } +ironrdp-rdpdr = { git = "https://github.com/Devolutions/IronRDP", rev = "ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" } +ironrdp-rdpsnd = { git = "https://github.com/Devolutions/IronRDP", rev = "ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" } +ironrdp-session = { git = "https://github.com/Devolutions/IronRDP", rev = "ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" } +ironrdp-svc = { git = "https://github.com/Devolutions/IronRDP", rev = "ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" } +ironrdp-tls = { git = "https://github.com/Devolutions/IronRDP", rev = "ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9", features = ["rustls"]} +ironrdp-tokio = { git = "https://github.com/Devolutions/IronRDP", rev = "ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" } From b21da761b7d915445347eab786cd62bdff54c563 Mon Sep 17 00:00:00 2001 From: Isaiah Becker-Mayer Date: Mon, 25 Mar 2024 20:19:14 -0500 Subject: [PATCH 14/24] Adds a mechanism to withhold sending resize requests to the RDP server until we're alerted by a new callback mechanism of the DisplayControlClient that the server has sent us its capabilities. This prevents an error where we send a resize before this event, which results either in an RDP error (if the channel is not opened) or a dropped event (if the server has not sent its capabilities yet). --- Cargo.lock | 40 ++++-- Cargo.toml | 24 ++-- lib/srv/desktop/rdp/rdpclient/Cargo.toml | 1 + lib/srv/desktop/rdp/rdpclient/src/client.rs | 149 ++++++++++++++------ 4 files changed, 144 insertions(+), 70 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 066b36b14996..1bd829d3c60a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1225,7 +1225,7 @@ dependencies = [ [[package]] name = "ironrdp-async" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9#ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" +source = "git+https://github.com/Devolutions/IronRDP?rev=94c176bf6a9bf0288c5943a607f1f8c6e35fc18c#94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" dependencies = [ "bytes", "ironrdp-connector", @@ -1236,7 +1236,7 @@ dependencies = [ [[package]] name = "ironrdp-cliprdr" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9#ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" +source = "git+https://github.com/Devolutions/IronRDP?rev=94c176bf6a9bf0288c5943a607f1f8c6e35fc18c#94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" dependencies = [ "bitflags 2.4.2", "ironrdp-pdu", @@ -1248,7 +1248,7 @@ dependencies = [ [[package]] name = "ironrdp-connector" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9#ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" +source = "git+https://github.com/Devolutions/IronRDP?rev=94c176bf6a9bf0288c5943a607f1f8c6e35fc18c#94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" dependencies = [ "ironrdp-error", "ironrdp-pdu", @@ -1260,12 +1260,22 @@ dependencies = [ "winapi", ] +[[package]] +name = "ironrdp-displaycontrol" +version = "0.1.0" +source = "git+https://github.com/Devolutions/IronRDP?rev=94c176bf6a9bf0288c5943a607f1f8c6e35fc18c#94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" +dependencies = [ + "ironrdp-dvc", + "ironrdp-pdu", + "ironrdp-svc", + "tracing", +] + [[package]] name = "ironrdp-dvc" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9#ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" +source = "git+https://github.com/Devolutions/IronRDP?rev=94c176bf6a9bf0288c5943a607f1f8c6e35fc18c#94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" dependencies = [ - "bitflags 2.4.2", "ironrdp-pdu", "ironrdp-svc", "slab", @@ -1275,12 +1285,12 @@ dependencies = [ [[package]] name = "ironrdp-error" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9#ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" +source = "git+https://github.com/Devolutions/IronRDP?rev=94c176bf6a9bf0288c5943a607f1f8c6e35fc18c#94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" [[package]] name = "ironrdp-graphics" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9#ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" +source = "git+https://github.com/Devolutions/IronRDP?rev=94c176bf6a9bf0288c5943a607f1f8c6e35fc18c#94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" dependencies = [ "bit_field", "bitflags 2.4.2", @@ -1297,7 +1307,7 @@ dependencies = [ [[package]] name = "ironrdp-pdu" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9#ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" +source = "git+https://github.com/Devolutions/IronRDP?rev=94c176bf6a9bf0288c5943a607f1f8c6e35fc18c#94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" dependencies = [ "bit_field", "bitflags 2.4.2", @@ -1319,7 +1329,7 @@ dependencies = [ [[package]] name = "ironrdp-rdpdr" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9#ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" +source = "git+https://github.com/Devolutions/IronRDP?rev=94c176bf6a9bf0288c5943a607f1f8c6e35fc18c#94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" dependencies = [ "bitflags 2.4.2", "ironrdp-error", @@ -1331,7 +1341,7 @@ dependencies = [ [[package]] name = "ironrdp-rdpsnd" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9#ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" +source = "git+https://github.com/Devolutions/IronRDP?rev=94c176bf6a9bf0288c5943a607f1f8c6e35fc18c#94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" dependencies = [ "ironrdp-pdu", "ironrdp-svc", @@ -1340,9 +1350,8 @@ dependencies = [ [[package]] name = "ironrdp-session" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9#ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" +source = "git+https://github.com/Devolutions/IronRDP?rev=94c176bf6a9bf0288c5943a607f1f8c6e35fc18c#94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" dependencies = [ - "bitflags 2.4.2", "ironrdp-connector", "ironrdp-dvc", "ironrdp-error", @@ -1355,7 +1364,7 @@ dependencies = [ [[package]] name = "ironrdp-svc" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9#ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" +source = "git+https://github.com/Devolutions/IronRDP?rev=94c176bf6a9bf0288c5943a607f1f8c6e35fc18c#94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" dependencies = [ "bitflags 2.4.2", "ironrdp-pdu", @@ -1364,7 +1373,7 @@ dependencies = [ [[package]] name = "ironrdp-tls" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9#ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" +source = "git+https://github.com/Devolutions/IronRDP?rev=94c176bf6a9bf0288c5943a607f1f8c6e35fc18c#94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" dependencies = [ "tokio", "tokio-rustls", @@ -1374,7 +1383,7 @@ dependencies = [ [[package]] name = "ironrdp-tokio" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9#ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" +source = "git+https://github.com/Devolutions/IronRDP?rev=94c176bf6a9bf0288c5943a607f1f8c6e35fc18c#94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" dependencies = [ "bytes", "ironrdp-async", @@ -2027,6 +2036,7 @@ dependencies = [ "env_logger", "ironrdp-cliprdr", "ironrdp-connector", + "ironrdp-displaycontrol", "ironrdp-dvc", "ironrdp-pdu", "ironrdp-rdpdr", diff --git a/Cargo.toml b/Cargo.toml index bf8a46980194..f7a7b336f4a8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,14 +23,16 @@ codegen-units = 1 [workspace.dependencies] # Note: To use a local IronRDP repository as a crate (for example, ironrdp-cliprdr), define the dependency as follows: # ironrdp-cliprdr = { path = "/path/to/local/IronRDP/crates/ironrdp-cliprdr" } -ironrdp-cliprdr = { git = "https://github.com/Devolutions/IronRDP", rev = "ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" } -ironrdp-connector = { git = "https://github.com/Devolutions/IronRDP", rev = "ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" } -ironrdp-dvc = { git = "https://github.com/Devolutions/IronRDP", rev = "ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" } -ironrdp-graphics = { git = "https://github.com/Devolutions/IronRDP", rev = "ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" } -ironrdp-pdu = { git = "https://github.com/Devolutions/IronRDP", rev = "ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" } -ironrdp-rdpdr = { git = "https://github.com/Devolutions/IronRDP", rev = "ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" } -ironrdp-rdpsnd = { git = "https://github.com/Devolutions/IronRDP", rev = "ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" } -ironrdp-session = { git = "https://github.com/Devolutions/IronRDP", rev = "ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" } -ironrdp-svc = { git = "https://github.com/Devolutions/IronRDP", rev = "ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" } -ironrdp-tls = { git = "https://github.com/Devolutions/IronRDP", rev = "ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9", features = ["rustls"]} -ironrdp-tokio = { git = "https://github.com/Devolutions/IronRDP", rev = "ead24a5f96bd9e8a402faf7fa227b0fdd406ddd9" } +# TODO: this rev hash is temporary, change once https://github.com/Devolutions/IronRDP/pull/424 is merged. +ironrdp-cliprdr = { git = "https://github.com/Devolutions/IronRDP", rev = "94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" } +ironrdp-connector = { git = "https://github.com/Devolutions/IronRDP", rev = "94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" } +ironrdp-displaycontrol = { git = "https://github.com/Devolutions/IronRDP", rev = "94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" } +ironrdp-dvc = { git = "https://github.com/Devolutions/IronRDP", rev = "94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" } +ironrdp-graphics = { git = "https://github.com/Devolutions/IronRDP", rev = "94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" } +ironrdp-pdu = { git = "https://github.com/Devolutions/IronRDP", rev = "94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" } +ironrdp-rdpdr = { git = "https://github.com/Devolutions/IronRDP", rev = "94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" } +ironrdp-rdpsnd = { git = "https://github.com/Devolutions/IronRDP", rev = "94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" } +ironrdp-session = { git = "https://github.com/Devolutions/IronRDP", rev = "94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" } +ironrdp-svc = { git = "https://github.com/Devolutions/IronRDP", rev = "94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" } +ironrdp-tls = { git = "https://github.com/Devolutions/IronRDP", rev = "94c176bf6a9bf0288c5943a607f1f8c6e35fc18c", features = ["rustls"]} +ironrdp-tokio = { git = "https://github.com/Devolutions/IronRDP", rev = "94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" } diff --git a/lib/srv/desktop/rdp/rdpclient/Cargo.toml b/lib/srv/desktop/rdp/rdpclient/Cargo.toml index a91173523f99..7a4115abbf30 100644 --- a/lib/srv/desktop/rdp/rdpclient/Cargo.toml +++ b/lib/srv/desktop/rdp/rdpclient/Cargo.toml @@ -22,6 +22,7 @@ ironrdp-rdpsnd.workspace = true ironrdp-session.workspace = true ironrdp-svc.workspace = true ironrdp-dvc.workspace = true +ironrdp-displaycontrol.workspace = true ironrdp-tls.workspace = true ironrdp-tokio.workspace = true iso7816 = "0.1.2" diff --git a/lib/srv/desktop/rdp/rdpclient/src/client.rs b/lib/srv/desktop/rdp/rdpclient/src/client.rs index 6c4ee5f8bd90..28201a9c5ca6 100644 --- a/lib/srv/desktop/rdp/rdpclient/src/client.rs +++ b/lib/srv/desktop/rdp/rdpclient/src/client.rs @@ -26,10 +26,12 @@ use bytes::BytesMut; use ironrdp_cliprdr::{Cliprdr, CliprdrClient, CliprdrSvcMessages}; use ironrdp_connector::connection_activation::ConnectionActivationState; use ironrdp_connector::{Config, ConnectorError, Credentials, DesktopSize}; -use ironrdp_dvc::display::{Monitor, MonitorFlags, Orientation}; -use ironrdp_dvc::DrdynvcClient; +use ironrdp_displaycontrol::client::DisplayControlClient; +use ironrdp_displaycontrol::pdu::DisplayControlPdu; +use ironrdp_dvc::DvcProcessor; use ironrdp_dvc::DynamicChannelId; -use ironrdp_dvc::{display::DisplayControlClient, DvcProcessor}; +use ironrdp_dvc::{DrdynvcClient, DvcMessage}; +use ironrdp_pdu::cursor::WriteCursor; use ironrdp_pdu::input::fast_path::{ FastPathInput, FastPathInputEvent, KeyboardFlags, SynchronizeFlags, }; @@ -39,7 +41,8 @@ use ironrdp_pdu::mcs::DisconnectReason; use ironrdp_pdu::rdp::capability_sets::MajorPlatformType; use ironrdp_pdu::rdp::RdpError; use ironrdp_pdu::write_buf::WriteBuf; -use ironrdp_pdu::{custom_err, function, PduError, PduParsing}; +use ironrdp_pdu::{custom_err, function, PduError}; +use ironrdp_pdu::{PduEncode, PduResult}; use ironrdp_rdpdr::pdu::efs::ClientDeviceListAnnounce; use ironrdp_rdpdr::pdu::RdpdrPdu; use ironrdp_rdpdr::Rdpdr; @@ -48,7 +51,7 @@ use ironrdp_session::x224::{self, ProcessorOutput}; use ironrdp_session::SessionErrorKind::Reason; use ironrdp_session::{reason_err, SessionError, SessionResult}; use ironrdp_svc::{SvcMessage, SvcProcessor, SvcProcessorMessages}; -use ironrdp_tokio::{single_connect_step_read, Framed, TokioStream}; +use ironrdp_tokio::{single_sequence_step_read, Framed, TokioStream}; use log::debug; use rand::{Rng, SeedableRng}; use std::fmt::{Debug, Display, Formatter}; @@ -70,6 +73,11 @@ use tokio_boring::{HandshakeError, SslStream}; const RDP_CONNECT_TIMEOUT: Duration = Duration::from_secs(5); +struct ResizeManager { + display_control_opened: bool, + withheld_resize: Option<(u32, u32)>, +} + /// The RDP client on the Rust side of things. Each `Client` /// corresponds with a Go `Client` specified by `cgo_handle`. pub struct Client { @@ -79,6 +87,7 @@ pub struct Client { write_stream: Option, function_receiver: Option, x224_processor: Arc>, + resize_manager: Arc>, } impl Client { @@ -134,6 +143,7 @@ impl Client { // Create a channel for sending/receiving function calls to/from the Client. let (client_handle, function_receiver) = ClientHandle::new(100); + let function_receiver = Some(function_receiver); let mut rdpdr = Rdpdr::new( Box::new(TeleportRdpdrBackend::new( @@ -155,11 +165,21 @@ impl Client { debug!("creating rdpdr client with directory sharing disabled") } + let resize_manager = Arc::new(Mutex::new(ResizeManager { + display_control_opened: false, + withheld_resize: None, + })); + + let resize_manager_clone = resize_manager.clone(); + let display_control = + DisplayControlClient::new().with_capabilities_received_callback(move |_| { + Self::on_display_ctl_capabilities_received(&resize_manager_clone) + }); + let drdynvc_client = DrdynvcClient::new().with_dynamic_channel(display_control); + let mut connector = ironrdp_connector::ClientConnector::new(connector_config.clone()) .with_server_addr(server_socket_addr) - .with_static_channel( - DrdynvcClient::new().with_dynamic_channel(DisplayControlClient::new()), - ) + .with_static_channel(drdynvc_client) .with_static_channel(Rdpsnd::new()) // required for rdpdr to work .with_static_channel(rdpdr); @@ -206,23 +226,24 @@ impl Client { // Take the stream back out of the framed object for splitting. let rdp_stream = rdp_stream.into_inner_no_leftover(); let (read_stream, write_stream) = split(rdp_stream); - let read_stream = ironrdp_tokio::TokioFramed::new(read_stream); - let write_stream = ironrdp_tokio::TokioFramed::new(write_stream); + let read_stream = Some(ironrdp_tokio::TokioFramed::new(read_stream)); + let write_stream = Some(ironrdp_tokio::TokioFramed::new(write_stream)); - let x224_processor = x224::Processor::new( + let x224_processor = Arc::new(Mutex::new(x224::Processor::new( connection_result.static_channels, connection_result.user_channel_id, connection_result.io_channel_id, connection_result.connection_activation, - ); + ))); Ok(Self { cgo_handle, client_handle, - read_stream: Some(read_stream), - write_stream: Some(write_stream), - function_receiver: Some(function_receiver), - x224_processor: Arc::new(Mutex::new(x224_processor)), + read_stream, + write_stream, + function_receiver, + x224_processor, + resize_manager, }) } @@ -272,15 +293,18 @@ impl Client { write_stream, function_receiver, self.x224_processor.clone(), + self.resize_manager.clone(), ); // Wait for either loop to finish. When one does, abort the other and return the result. tokio::select! { res = &mut read_loop_handle => { + // Read loop finished, abort the other tasks and return the result. write_loop_handle.abort(); res? }, res = &mut write_loop_handle => { + // Write loop finished, abort the other tasks and return the result. read_loop_handle.abort(); match res { Ok(Ok(())) => Ok(None), @@ -332,7 +356,7 @@ impl Client { debug!("Received Server Deactivate All PDU, executing Deactivation-Reactivation Sequence"); let mut buf = WriteBuf::new(); loop { - let written = single_connect_step_read( + let written = single_sequence_step_read( &mut read_stream, &mut sequence, &mut buf, @@ -377,6 +401,7 @@ impl Client { mut write_stream: RdpWriteStream, mut write_receiver: FunctionReceiver, x224_processor: Arc>, + resize_manager: Arc>, ) -> tokio::task::JoinHandle> { global::TOKIO_RT.spawn(async move { loop { @@ -399,13 +424,33 @@ impl Client { .await?; } ClientFunction::WriteScreenResize(width, height) => { - Client::write_screen_resize( - &mut write_stream, - x224_processor.clone(), - width, - height, - ) - .await?; + debug!("Received WriteScreenResize PDU"); + // Determine whether to withhold the resize or perform it immediately. + let action = { + let mut resize_manager = + Self::resize_manager_lock(&resize_manager)?; + if !resize_manager.display_control_opened { + debug!("DisplayControl channel not opened, withholding resize"); + // The client requested a resize but the DisplayControl channel has not been opened yet. + // Sending the resize now would cause an RDP error and end the session; instead we withhold + // it until the DisplayControl channel is opened. + resize_manager.withheld_resize = Some((width, height)); + None // No immediate action required. + } else { + Some((width, height)) // Perform the resize immediately. + } + }; // Drop the lock here to avoid holding it over the await below. + + if let Some((width, height)) = action { + debug!("Performing resize to [{:?}x{:?}]", width, height); + Client::write_screen_resize( + &mut write_stream, + x224_processor.clone(), + width, + height, + ) + .await?; + } } ClientFunction::HandleTdpSdAnnounce(sda) => { Client::handle_tdp_sd_announce( @@ -466,6 +511,29 @@ impl Client { }) } + fn on_display_ctl_capabilities_received( + resize_manager: &Arc>, + ) -> PduResult> { + debug!("DisplayControlClient channel opened"); + // We've been notified that the DisplayControl dvc channel has been opened: + let mut resize_manager = + Self::resize_manager_lock(resize_manager).map_err(|err| custom_err!(err))?; + resize_manager.display_control_opened = true; // Set the flag to true. + let withheld_resize = resize_manager.withheld_resize.take(); + if let Some((width, height)) = withheld_resize { + // If there was a resize withheld, perform it now. + debug!( + "Withheld resize for size [{:?}x{:?}] found, sending now", + width, height + ); + let pdu = DisplayControlPdu::create_monitor_layout_pdu(width, height)?; + return Ok(vec![Box::new(pdu)]); + } + + // No resize was withheld, nothing to do. + Ok(vec![]) + } + fn send_connection_activated( cgo_handle: CgoHandle, io_channel_id: u16, @@ -608,10 +676,9 @@ impl Client { write_stream: &mut RdpWriteStream, event: FastPathInputEvent, ) -> ClientResult<()> { - let mut data: Vec = Vec::new(); let input_pdu = FastPathInput(vec![event]); - input_pdu.to_buffer(&mut data)?; - + let mut data: Vec = vec![0; input_pdu.size()]; + input_pdu.encode(&mut WriteCursor::new(&mut data))?; write_stream.write_all(&data).await?; Ok(()) } @@ -660,24 +727,10 @@ impl Client { )); } - Ok::<_, ClientError>(disp_ctl_cli.encode_monitors( + Ok::<_, ClientError>(disp_ctl_cli.encode_monitor( channel_id.unwrap(), - vec![Monitor { - flags: MonitorFlags::PRIMARY, - left: 0, - top: 0, - width, - height, - physical_width: 0, - physical_height: 0, - orientation: if width > height { - Orientation::Landscape - } else { - Orientation::Portrait - }, - desktop_scale_factor: 100, // percent; todo: can this be zero? - device_scale_factor: 100, // percent; todo: can this be zero? - }], + width, + height, )) }) .await???; @@ -870,6 +923,14 @@ impl Client { .map_err(|err| reason_err!(function!(), "PoisonError: {:?}", err)) } + fn resize_manager_lock( + resize_manager: &Arc>, + ) -> Result, SessionError> { + resize_manager + .lock() + .map_err(|err| reason_err!(function!(), "PoisonError: {:?}", err)) + } + /// Returns an immutable reference to the [`SvcProcessor`] of type `S`. /// /// # Example From 6bde80b65bbd23fb94773075a659146eaf17891a Mon Sep 17 00:00:00 2001 From: Isaiah Becker-Mayer Date: Tue, 26 Mar 2024 14:13:23 -0500 Subject: [PATCH 15/24] Refactoring after update to the tip of https://github.com/Devolutions/IronRDP/pull/424 --- Cargo.lock | 28 ++--- Cargo.toml | 24 ++-- lib/srv/desktop/rdp/rdpclient/src/client.rs | 115 +++++++++++--------- 3 files changed, 92 insertions(+), 75 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1cbc5ad4264a..3bbe6ab7d443 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1225,7 +1225,7 @@ dependencies = [ [[package]] name = "ironrdp-async" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=94c176bf6a9bf0288c5943a607f1f8c6e35fc18c#94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" +source = "git+https://github.com/Devolutions/IronRDP?rev=10c2415348e0ddfc097d87099c61a33088e908b9#10c2415348e0ddfc097d87099c61a33088e908b9" dependencies = [ "bytes", "ironrdp-connector", @@ -1236,7 +1236,7 @@ dependencies = [ [[package]] name = "ironrdp-cliprdr" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=94c176bf6a9bf0288c5943a607f1f8c6e35fc18c#94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" +source = "git+https://github.com/Devolutions/IronRDP?rev=10c2415348e0ddfc097d87099c61a33088e908b9#10c2415348e0ddfc097d87099c61a33088e908b9" dependencies = [ "bitflags 2.5.0", "ironrdp-pdu", @@ -1248,7 +1248,7 @@ dependencies = [ [[package]] name = "ironrdp-connector" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=94c176bf6a9bf0288c5943a607f1f8c6e35fc18c#94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" +source = "git+https://github.com/Devolutions/IronRDP?rev=10c2415348e0ddfc097d87099c61a33088e908b9#10c2415348e0ddfc097d87099c61a33088e908b9" dependencies = [ "ironrdp-error", "ironrdp-pdu", @@ -1263,7 +1263,7 @@ dependencies = [ [[package]] name = "ironrdp-displaycontrol" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=94c176bf6a9bf0288c5943a607f1f8c6e35fc18c#94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" +source = "git+https://github.com/Devolutions/IronRDP?rev=10c2415348e0ddfc097d87099c61a33088e908b9#10c2415348e0ddfc097d87099c61a33088e908b9" dependencies = [ "ironrdp-dvc", "ironrdp-pdu", @@ -1274,7 +1274,7 @@ dependencies = [ [[package]] name = "ironrdp-dvc" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=94c176bf6a9bf0288c5943a607f1f8c6e35fc18c#94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" +source = "git+https://github.com/Devolutions/IronRDP?rev=10c2415348e0ddfc097d87099c61a33088e908b9#10c2415348e0ddfc097d87099c61a33088e908b9" dependencies = [ "ironrdp-pdu", "ironrdp-svc", @@ -1285,12 +1285,12 @@ dependencies = [ [[package]] name = "ironrdp-error" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=94c176bf6a9bf0288c5943a607f1f8c6e35fc18c#94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" +source = "git+https://github.com/Devolutions/IronRDP?rev=10c2415348e0ddfc097d87099c61a33088e908b9#10c2415348e0ddfc097d87099c61a33088e908b9" [[package]] name = "ironrdp-graphics" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=94c176bf6a9bf0288c5943a607f1f8c6e35fc18c#94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" +source = "git+https://github.com/Devolutions/IronRDP?rev=10c2415348e0ddfc097d87099c61a33088e908b9#10c2415348e0ddfc097d87099c61a33088e908b9" dependencies = [ "bit_field", "bitflags 2.5.0", @@ -1307,7 +1307,7 @@ dependencies = [ [[package]] name = "ironrdp-pdu" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=94c176bf6a9bf0288c5943a607f1f8c6e35fc18c#94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" +source = "git+https://github.com/Devolutions/IronRDP?rev=10c2415348e0ddfc097d87099c61a33088e908b9#10c2415348e0ddfc097d87099c61a33088e908b9" dependencies = [ "bit_field", "bitflags 2.5.0", @@ -1329,7 +1329,7 @@ dependencies = [ [[package]] name = "ironrdp-rdpdr" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=94c176bf6a9bf0288c5943a607f1f8c6e35fc18c#94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" +source = "git+https://github.com/Devolutions/IronRDP?rev=10c2415348e0ddfc097d87099c61a33088e908b9#10c2415348e0ddfc097d87099c61a33088e908b9" dependencies = [ "bitflags 2.5.0", "ironrdp-error", @@ -1341,7 +1341,7 @@ dependencies = [ [[package]] name = "ironrdp-rdpsnd" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=94c176bf6a9bf0288c5943a607f1f8c6e35fc18c#94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" +source = "git+https://github.com/Devolutions/IronRDP?rev=10c2415348e0ddfc097d87099c61a33088e908b9#10c2415348e0ddfc097d87099c61a33088e908b9" dependencies = [ "ironrdp-pdu", "ironrdp-svc", @@ -1350,7 +1350,7 @@ dependencies = [ [[package]] name = "ironrdp-session" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=94c176bf6a9bf0288c5943a607f1f8c6e35fc18c#94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" +source = "git+https://github.com/Devolutions/IronRDP?rev=10c2415348e0ddfc097d87099c61a33088e908b9#10c2415348e0ddfc097d87099c61a33088e908b9" dependencies = [ "ironrdp-connector", "ironrdp-dvc", @@ -1364,7 +1364,7 @@ dependencies = [ [[package]] name = "ironrdp-svc" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=94c176bf6a9bf0288c5943a607f1f8c6e35fc18c#94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" +source = "git+https://github.com/Devolutions/IronRDP?rev=10c2415348e0ddfc097d87099c61a33088e908b9#10c2415348e0ddfc097d87099c61a33088e908b9" dependencies = [ "bitflags 2.5.0", "ironrdp-pdu", @@ -1373,7 +1373,7 @@ dependencies = [ [[package]] name = "ironrdp-tls" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=94c176bf6a9bf0288c5943a607f1f8c6e35fc18c#94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" +source = "git+https://github.com/Devolutions/IronRDP?rev=10c2415348e0ddfc097d87099c61a33088e908b9#10c2415348e0ddfc097d87099c61a33088e908b9" dependencies = [ "tokio", "tokio-rustls", @@ -1383,7 +1383,7 @@ dependencies = [ [[package]] name = "ironrdp-tokio" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=94c176bf6a9bf0288c5943a607f1f8c6e35fc18c#94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" +source = "git+https://github.com/Devolutions/IronRDP?rev=10c2415348e0ddfc097d87099c61a33088e908b9#10c2415348e0ddfc097d87099c61a33088e908b9" dependencies = [ "bytes", "ironrdp-async", diff --git a/Cargo.toml b/Cargo.toml index f7a7b336f4a8..db83a2c6a03f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,15 +24,15 @@ codegen-units = 1 # Note: To use a local IronRDP repository as a crate (for example, ironrdp-cliprdr), define the dependency as follows: # ironrdp-cliprdr = { path = "/path/to/local/IronRDP/crates/ironrdp-cliprdr" } # TODO: this rev hash is temporary, change once https://github.com/Devolutions/IronRDP/pull/424 is merged. -ironrdp-cliprdr = { git = "https://github.com/Devolutions/IronRDP", rev = "94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" } -ironrdp-connector = { git = "https://github.com/Devolutions/IronRDP", rev = "94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" } -ironrdp-displaycontrol = { git = "https://github.com/Devolutions/IronRDP", rev = "94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" } -ironrdp-dvc = { git = "https://github.com/Devolutions/IronRDP", rev = "94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" } -ironrdp-graphics = { git = "https://github.com/Devolutions/IronRDP", rev = "94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" } -ironrdp-pdu = { git = "https://github.com/Devolutions/IronRDP", rev = "94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" } -ironrdp-rdpdr = { git = "https://github.com/Devolutions/IronRDP", rev = "94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" } -ironrdp-rdpsnd = { git = "https://github.com/Devolutions/IronRDP", rev = "94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" } -ironrdp-session = { git = "https://github.com/Devolutions/IronRDP", rev = "94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" } -ironrdp-svc = { git = "https://github.com/Devolutions/IronRDP", rev = "94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" } -ironrdp-tls = { git = "https://github.com/Devolutions/IronRDP", rev = "94c176bf6a9bf0288c5943a607f1f8c6e35fc18c", features = ["rustls"]} -ironrdp-tokio = { git = "https://github.com/Devolutions/IronRDP", rev = "94c176bf6a9bf0288c5943a607f1f8c6e35fc18c" } +ironrdp-cliprdr = { git = "https://github.com/Devolutions/IronRDP", rev = "10c2415348e0ddfc097d87099c61a33088e908b9" } +ironrdp-connector = { git = "https://github.com/Devolutions/IronRDP", rev = "10c2415348e0ddfc097d87099c61a33088e908b9" } +ironrdp-displaycontrol = { git = "https://github.com/Devolutions/IronRDP", rev = "10c2415348e0ddfc097d87099c61a33088e908b9" } +ironrdp-dvc = { git = "https://github.com/Devolutions/IronRDP", rev = "10c2415348e0ddfc097d87099c61a33088e908b9" } +ironrdp-graphics = { git = "https://github.com/Devolutions/IronRDP", rev = "10c2415348e0ddfc097d87099c61a33088e908b9" } +ironrdp-pdu = { git = "https://github.com/Devolutions/IronRDP", rev = "10c2415348e0ddfc097d87099c61a33088e908b9" } +ironrdp-rdpdr = { git = "https://github.com/Devolutions/IronRDP", rev = "10c2415348e0ddfc097d87099c61a33088e908b9" } +ironrdp-rdpsnd = { git = "https://github.com/Devolutions/IronRDP", rev = "10c2415348e0ddfc097d87099c61a33088e908b9" } +ironrdp-session = { git = "https://github.com/Devolutions/IronRDP", rev = "10c2415348e0ddfc097d87099c61a33088e908b9" } +ironrdp-svc = { git = "https://github.com/Devolutions/IronRDP", rev = "10c2415348e0ddfc097d87099c61a33088e908b9" } +ironrdp-tls = { git = "https://github.com/Devolutions/IronRDP", rev = "10c2415348e0ddfc097d87099c61a33088e908b9", features = ["rustls"]} +ironrdp-tokio = { git = "https://github.com/Devolutions/IronRDP", rev = "10c2415348e0ddfc097d87099c61a33088e908b9" } diff --git a/lib/srv/desktop/rdp/rdpclient/src/client.rs b/lib/srv/desktop/rdp/rdpclient/src/client.rs index 28201a9c5ca6..90da9295da74 100644 --- a/lib/srv/desktop/rdp/rdpclient/src/client.rs +++ b/lib/srv/desktop/rdp/rdpclient/src/client.rs @@ -73,8 +73,7 @@ use tokio_boring::{HandshakeError, SslStream}; const RDP_CONNECT_TIMEOUT: Duration = Duration::from_secs(5); -struct ResizeManager { - display_control_opened: bool, +struct ResizeWithholder { withheld_resize: Option<(u32, u32)>, } @@ -87,7 +86,7 @@ pub struct Client { write_stream: Option, function_receiver: Option, x224_processor: Arc>, - resize_manager: Arc>, + resize_withholder: Arc>, } impl Client { @@ -165,16 +164,14 @@ impl Client { debug!("creating rdpdr client with directory sharing disabled") } - let resize_manager = Arc::new(Mutex::new(ResizeManager { - display_control_opened: false, + let resize_withholder = Arc::new(Mutex::new(ResizeWithholder { withheld_resize: None, })); - let resize_manager_clone = resize_manager.clone(); - let display_control = - DisplayControlClient::new().with_capabilities_received_callback(move |_| { - Self::on_display_ctl_capabilities_received(&resize_manager_clone) - }); + let resize_manager_clone = resize_withholder.clone(); + let display_control = DisplayControlClient::new(move |_| { + Self::on_display_ctl_capabilities_received(&resize_manager_clone) + }); let drdynvc_client = DrdynvcClient::new().with_dynamic_channel(display_control); let mut connector = ironrdp_connector::ClientConnector::new(connector_config.clone()) @@ -243,7 +240,7 @@ impl Client { write_stream, function_receiver, x224_processor, - resize_manager, + resize_withholder, }) } @@ -293,7 +290,7 @@ impl Client { write_stream, function_receiver, self.x224_processor.clone(), - self.resize_manager.clone(), + self.resize_withholder.clone(), ); // Wait for either loop to finish. When one does, abort the other and return the result. @@ -401,7 +398,7 @@ impl Client { mut write_stream: RdpWriteStream, mut write_receiver: FunctionReceiver, x224_processor: Arc>, - resize_manager: Arc>, + resize_withholder: Arc>, ) -> tokio::task::JoinHandle> { global::TOKIO_RT.spawn(async move { loop { @@ -424,33 +421,14 @@ impl Client { .await?; } ClientFunction::WriteScreenResize(width, height) => { - debug!("Received WriteScreenResize PDU"); - // Determine whether to withhold the resize or perform it immediately. - let action = { - let mut resize_manager = - Self::resize_manager_lock(&resize_manager)?; - if !resize_manager.display_control_opened { - debug!("DisplayControl channel not opened, withholding resize"); - // The client requested a resize but the DisplayControl channel has not been opened yet. - // Sending the resize now would cause an RDP error and end the session; instead we withhold - // it until the DisplayControl channel is opened. - resize_manager.withheld_resize = Some((width, height)); - None // No immediate action required. - } else { - Some((width, height)) // Perform the resize immediately. - } - }; // Drop the lock here to avoid holding it over the await below. - - if let Some((width, height)) = action { - debug!("Performing resize to [{:?}x{:?}]", width, height); - Client::write_screen_resize( - &mut write_stream, - x224_processor.clone(), - width, - height, - ) - .await?; - } + Client::handle_screen_resize( + width, + height, + x224_processor.clone(), + &mut write_stream, + resize_withholder.clone(), + ) + .await?; } ClientFunction::HandleTdpSdAnnounce(sda) => { Client::handle_tdp_sd_announce( @@ -512,14 +490,13 @@ impl Client { } fn on_display_ctl_capabilities_received( - resize_manager: &Arc>, + resize_withholder: &Arc>, ) -> PduResult> { debug!("DisplayControlClient channel opened"); // We've been notified that the DisplayControl dvc channel has been opened: - let mut resize_manager = - Self::resize_manager_lock(resize_manager).map_err(|err| custom_err!(err))?; - resize_manager.display_control_opened = true; // Set the flag to true. - let withheld_resize = resize_manager.withheld_resize.take(); + let mut resize_withholder = + Self::resize_manager_lock(resize_withholder).map_err(|err| custom_err!(err))?; + let withheld_resize = resize_withholder.withheld_resize.take(); if let Some((width, height)) = withheld_resize { // If there was a resize withheld, perform it now. debug!( @@ -707,6 +684,46 @@ impl Client { Ok(()) } + async fn handle_screen_resize( + width: u32, + height: u32, + x224_processor: Arc>, + write_stream: &mut RdpWriteStream, + resize_withholder: Arc>, + ) -> ClientResult<()> { + debug!("Received WriteScreenResize PDU"); + // Determine whether to withhold the resize or perform it immediately. + let action = { + let x224_processor = Self::x224_lock(&x224_processor)?; + let (disp_ctl_cli, _) = + Self::get_dvc_processor::(&x224_processor)?; + if !disp_ctl_cli.ready() { + debug!("DisplayControl channel not ready, withholding resize"); + let mut resize_withholder = Self::resize_manager_lock(&resize_withholder)?; + // The client requested a resize but the DisplayControl channel has not been opened yet. + // Sending the resize now would cause an RDP error and end the session; instead we withhold + // it until the DisplayControl channel is ready. + resize_withholder.withheld_resize = Some((width, height)); + None // No immediate action required. + } else { + Some((width, height)) // Perform the resize immediately. + } + }; // Drop the lock here to avoid holding it over the await below. + + if let Some((width, height)) = action { + debug!("Performing resize to [{:?}x{:?}]", width, height); + return Client::write_screen_resize( + write_stream, + x224_processor.clone(), + width, + height, + ) + .await; + } + + Ok(()) + } + /// Sends a screen resize to the RDP server. async fn write_screen_resize( write_stream: &mut RdpWriteStream, @@ -718,7 +735,7 @@ impl Client { let messages = global::TOKIO_RT .spawn_blocking(move || { let x224_processor = Self::x224_lock(&cloned)?; - let (disp_ctl_cli, channel_id): (&DisplayControlClient, Option) = + let (disp_ctl_cli, channel_id) = Self::get_dvc_processor::(&x224_processor)?; if channel_id.is_none() { @@ -924,9 +941,9 @@ impl Client { } fn resize_manager_lock( - resize_manager: &Arc>, - ) -> Result, SessionError> { - resize_manager + resize_withholder: &Arc>, + ) -> Result, SessionError> { + resize_withholder .lock() .map_err(|err| reason_err!(function!(), "PoisonError: {:?}", err)) } From 6ce36b0847ed630bbbe2cfc314de3c8d39ea0846 Mon Sep 17 00:00:00 2001 From: Isaiah Becker-Mayer Date: Wed, 27 Mar 2024 14:45:02 -0500 Subject: [PATCH 16/24] Adds windowOnResize to story --- .../teleport/src/DesktopSession/DesktopSession.story.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/web/packages/teleport/src/DesktopSession/DesktopSession.story.tsx b/web/packages/teleport/src/DesktopSession/DesktopSession.story.tsx index f3980b70ce03..7be8f174c74a 100644 --- a/web/packages/teleport/src/DesktopSession/DesktopSession.story.tsx +++ b/web/packages/teleport/src/DesktopSession/DesktopSession.story.tsx @@ -19,6 +19,7 @@ import React, { useState } from 'react'; import { ButtonPrimary } from 'design/Button'; import { NotificationItem } from 'shared/components/Notification'; +import { throttle } from 'shared/utils/highbar'; import { TdpClient, TdpClientEvent } from 'teleport/lib/tdp'; @@ -90,6 +91,7 @@ const props: State = { setShowAnotherSessionActiveDialog: () => {}, warnings: [], onRemoveWarning: () => {}, + windowOnResize: throttle(() => {}, 1000), }; export const BothProcessing = () => ( From f6b65de97f5e4c1769ed635e86d664d5cded8ff8 Mon Sep 17 00:00:00 2001 From: Isaiah Becker-Mayer Date: Wed, 27 Mar 2024 14:45:37 -0500 Subject: [PATCH 17/24] adds Determine Toolchain Versions and cache paths and Print versions steps to os-compatibility-test.yaml --- .github/workflows/os-compatibility-test.yaml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.github/workflows/os-compatibility-test.yaml b/.github/workflows/os-compatibility-test.yaml index c67b3b38ad1f..eb0b43e32c7b 100644 --- a/.github/workflows/os-compatibility-test.yaml +++ b/.github/workflows/os-compatibility-test.yaml @@ -36,6 +36,22 @@ jobs: - name: Prepare workspace uses: ./.github/actions/prepare-workspace + - name: Determine Toolchain Versions and cache paths + run: | + echo NODE_VERSION=$(make -C build.assets print-node-version) >> $GITHUB_ENV + echo GOLANG_VERSION=$(make -C build.assets print-go-version | sed 's/^go//') >> $GITHUB_ENV + echo RUST_VERSION=$(make -C build.assets print-rust-version) >> $GITHUB_ENV + echo WASM_PACK_VERSION=$(make -C build.assets print-wasm-pack-version) >> $GITHUB_ENV + echo PKG_CONFIG_PATH="$(build.assets/build-fido2-macos.sh pkg_config_path)" >> $GITHUB_ENV + + - name: Print versions + run: | + echo "make: $(make --version)" + echo "node: ${NODE_VERSION}" + echo "go: ${GOLANG_VERSION}" + echo "rust: ${RUST_VERSION}" + echo "wasm-pack: ${WASM_PACK_VERSION}" + - name: Run make run: | make -j"$(nproc)" binaries From 42dc7203361c1a0ed01c7d89acd896607b7f1933 Mon Sep 17 00:00:00 2001 From: Isaiah Becker-Mayer Date: Mon, 1 Apr 2024 11:08:35 -0700 Subject: [PATCH 18/24] fixes debug log formatting --- lib/srv/desktop/rdp/rdpclient/client.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/srv/desktop/rdp/rdpclient/client.go b/lib/srv/desktop/rdp/rdpclient/client.go index 64cff451eb57..49568ba6aa3d 100644 --- a/lib/srv/desktop/rdp/rdpclient/client.go +++ b/lib/srv/desktop/rdp/rdpclient/client.go @@ -222,7 +222,7 @@ func (c *Client) readClientUsername() error { } u, ok := msg.(tdp.ClientUsername) if !ok { - c.cfg.Log.Debugf("Expected ClientUsername message, got %T ", msg) + c.cfg.Log.Debugf("Expected ClientUsername message, got %T", msg) continue } c.cfg.Log.Debugf("Got RDP username %q", u.Username) @@ -740,7 +740,7 @@ func cgo_handle_remote_copy(handle C.uintptr_t, data *C.uint8_t, length C.uint32 // handleRemoteCopy is called from Rust when data is copied // on the remote desktop func (c *Client) handleRemoteCopy(data []byte) C.CGOErrCode { - c.cfg.Log.Debugf("Received %d bytes of clipboard data from Windows desktop ", len(data)) + c.cfg.Log.Debugf("Received %d bytes of clipboard data from Windows desktop", len(data)) if err := c.cfg.Conn.WriteMessage(tdp.ClipboardData(data)); err != nil { c.cfg.Log.Errorf("failed handling remote copy: %v", err) From 90380c34ba621f880fe003957ba8d664b4e62bc8 Mon Sep 17 00:00:00 2001 From: Isaiah Becker-Mayer Date: Thu, 18 Apr 2024 20:28:52 -0700 Subject: [PATCH 19/24] Updates to local IronRDP and later IronRDP api --- Cargo.lock | 48 ++++++--------------- Cargo.toml | 37 ++++++++++------ lib/srv/desktop/rdp/rdpclient/src/client.rs | 19 +++++--- 3 files changed, 53 insertions(+), 51 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3bbe6ab7d443..fab7b3ba8f9c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -87,9 +87,9 @@ dependencies = [ [[package]] name = "asn1-rs" -version = "0.5.2" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6fd5ddaf0351dff5b8da21b2fb4ff8e08ddd02857f0bf69c47639106c0fff0" +checksum = "22ad1373757efa0f70ec53939aabc7152e1591cb485208052993070ac8d2429d" dependencies = [ "asn1-rs-derive", "asn1-rs-impl", @@ -102,25 +102,25 @@ dependencies = [ [[package]] name = "asn1-rs-derive" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c" +checksum = "7378575ff571966e99a744addeff0bff98b8ada0dedf1956d59e634db95eaac1" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.39", "synstructure", ] [[package]] name = "asn1-rs-impl" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed" +checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.39", ] [[package]] @@ -579,9 +579,9 @@ dependencies = [ [[package]] name = "der-parser" -version = "8.2.0" +version = "9.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbd676fbbab537128ef0278adb5576cf363cff6aa22a7b24effe97347cfab61e" +checksum = "5cd0a5c643689626bec213c4d8bd4d96acc8ffdb4ad4bb6bc16abf27d5f4b553" dependencies = [ "asn1-rs", "displaydoc", @@ -1225,7 +1225,6 @@ dependencies = [ [[package]] name = "ironrdp-async" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=10c2415348e0ddfc097d87099c61a33088e908b9#10c2415348e0ddfc097d87099c61a33088e908b9" dependencies = [ "bytes", "ironrdp-connector", @@ -1236,7 +1235,6 @@ dependencies = [ [[package]] name = "ironrdp-cliprdr" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=10c2415348e0ddfc097d87099c61a33088e908b9#10c2415348e0ddfc097d87099c61a33088e908b9" dependencies = [ "bitflags 2.5.0", "ironrdp-pdu", @@ -1248,7 +1246,6 @@ dependencies = [ [[package]] name = "ironrdp-connector" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=10c2415348e0ddfc097d87099c61a33088e908b9#10c2415348e0ddfc097d87099c61a33088e908b9" dependencies = [ "ironrdp-error", "ironrdp-pdu", @@ -1263,7 +1260,6 @@ dependencies = [ [[package]] name = "ironrdp-displaycontrol" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=10c2415348e0ddfc097d87099c61a33088e908b9#10c2415348e0ddfc097d87099c61a33088e908b9" dependencies = [ "ironrdp-dvc", "ironrdp-pdu", @@ -1274,7 +1270,6 @@ dependencies = [ [[package]] name = "ironrdp-dvc" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=10c2415348e0ddfc097d87099c61a33088e908b9#10c2415348e0ddfc097d87099c61a33088e908b9" dependencies = [ "ironrdp-pdu", "ironrdp-svc", @@ -1285,12 +1280,10 @@ dependencies = [ [[package]] name = "ironrdp-error" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=10c2415348e0ddfc097d87099c61a33088e908b9#10c2415348e0ddfc097d87099c61a33088e908b9" [[package]] name = "ironrdp-graphics" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=10c2415348e0ddfc097d87099c61a33088e908b9#10c2415348e0ddfc097d87099c61a33088e908b9" dependencies = [ "bit_field", "bitflags 2.5.0", @@ -1307,7 +1300,6 @@ dependencies = [ [[package]] name = "ironrdp-pdu" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=10c2415348e0ddfc097d87099c61a33088e908b9#10c2415348e0ddfc097d87099c61a33088e908b9" dependencies = [ "bit_field", "bitflags 2.5.0", @@ -1329,7 +1321,6 @@ dependencies = [ [[package]] name = "ironrdp-rdpdr" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=10c2415348e0ddfc097d87099c61a33088e908b9#10c2415348e0ddfc097d87099c61a33088e908b9" dependencies = [ "bitflags 2.5.0", "ironrdp-error", @@ -1341,7 +1332,6 @@ dependencies = [ [[package]] name = "ironrdp-rdpsnd" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=10c2415348e0ddfc097d87099c61a33088e908b9#10c2415348e0ddfc097d87099c61a33088e908b9" dependencies = [ "ironrdp-pdu", "ironrdp-svc", @@ -1350,9 +1340,9 @@ dependencies = [ [[package]] name = "ironrdp-session" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=10c2415348e0ddfc097d87099c61a33088e908b9#10c2415348e0ddfc097d87099c61a33088e908b9" dependencies = [ "ironrdp-connector", + "ironrdp-displaycontrol", "ironrdp-dvc", "ironrdp-error", "ironrdp-graphics", @@ -1364,7 +1354,6 @@ dependencies = [ [[package]] name = "ironrdp-svc" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=10c2415348e0ddfc097d87099c61a33088e908b9#10c2415348e0ddfc097d87099c61a33088e908b9" dependencies = [ "bitflags 2.5.0", "ironrdp-pdu", @@ -1373,7 +1362,6 @@ dependencies = [ [[package]] name = "ironrdp-tls" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=10c2415348e0ddfc097d87099c61a33088e908b9#10c2415348e0ddfc097d87099c61a33088e908b9" dependencies = [ "tokio", "tokio-rustls", @@ -1383,7 +1371,6 @@ dependencies = [ [[package]] name = "ironrdp-tokio" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=10c2415348e0ddfc097d87099c61a33088e908b9#10c2415348e0ddfc097d87099c61a33088e908b9" dependencies = [ "bytes", "ironrdp-async", @@ -2690,14 +2677,13 @@ dependencies = [ [[package]] name = "synstructure" -version = "0.12.6" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", - "unicode-xid", + "syn 2.0.39", ] [[package]] @@ -3016,12 +3002,6 @@ dependencies = [ "tinyvec", ] -[[package]] -name = "unicode-xid" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" - [[package]] name = "untrusted" version = "0.9.0" diff --git a/Cargo.toml b/Cargo.toml index db83a2c6a03f..fdc33563a11d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,15 +24,28 @@ codegen-units = 1 # Note: To use a local IronRDP repository as a crate (for example, ironrdp-cliprdr), define the dependency as follows: # ironrdp-cliprdr = { path = "/path/to/local/IronRDP/crates/ironrdp-cliprdr" } # TODO: this rev hash is temporary, change once https://github.com/Devolutions/IronRDP/pull/424 is merged. -ironrdp-cliprdr = { git = "https://github.com/Devolutions/IronRDP", rev = "10c2415348e0ddfc097d87099c61a33088e908b9" } -ironrdp-connector = { git = "https://github.com/Devolutions/IronRDP", rev = "10c2415348e0ddfc097d87099c61a33088e908b9" } -ironrdp-displaycontrol = { git = "https://github.com/Devolutions/IronRDP", rev = "10c2415348e0ddfc097d87099c61a33088e908b9" } -ironrdp-dvc = { git = "https://github.com/Devolutions/IronRDP", rev = "10c2415348e0ddfc097d87099c61a33088e908b9" } -ironrdp-graphics = { git = "https://github.com/Devolutions/IronRDP", rev = "10c2415348e0ddfc097d87099c61a33088e908b9" } -ironrdp-pdu = { git = "https://github.com/Devolutions/IronRDP", rev = "10c2415348e0ddfc097d87099c61a33088e908b9" } -ironrdp-rdpdr = { git = "https://github.com/Devolutions/IronRDP", rev = "10c2415348e0ddfc097d87099c61a33088e908b9" } -ironrdp-rdpsnd = { git = "https://github.com/Devolutions/IronRDP", rev = "10c2415348e0ddfc097d87099c61a33088e908b9" } -ironrdp-session = { git = "https://github.com/Devolutions/IronRDP", rev = "10c2415348e0ddfc097d87099c61a33088e908b9" } -ironrdp-svc = { git = "https://github.com/Devolutions/IronRDP", rev = "10c2415348e0ddfc097d87099c61a33088e908b9" } -ironrdp-tls = { git = "https://github.com/Devolutions/IronRDP", rev = "10c2415348e0ddfc097d87099c61a33088e908b9", features = ["rustls"]} -ironrdp-tokio = { git = "https://github.com/Devolutions/IronRDP", rev = "10c2415348e0ddfc097d87099c61a33088e908b9" } +#ironrdp-cliprdr = { git = "https://github.com/Devolutions/IronRDP", rev = "10c2415348e0ddfc097d87099c61a33088e908b9" } +#ironrdp-connector = { git = "https://github.com/Devolutions/IronRDP", rev = "10c2415348e0ddfc097d87099c61a33088e908b9" } +#ironrdp-displaycontrol = { git = "https://github.com/Devolutions/IronRDP", rev = "10c2415348e0ddfc097d87099c61a33088e908b9" } +#ironrdp-dvc = { git = "https://github.com/Devolutions/IronRDP", rev = "10c2415348e0ddfc097d87099c61a33088e908b9" } +#ironrdp-graphics = { git = "https://github.com/Devolutions/IronRDP", rev = "10c2415348e0ddfc097d87099c61a33088e908b9" } +#ironrdp-pdu = { git = "https://github.com/Devolutions/IronRDP", rev = "10c2415348e0ddfc097d87099c61a33088e908b9" } +#ironrdp-rdpdr = { git = "https://github.com/Devolutions/IronRDP", rev = "10c2415348e0ddfc097d87099c61a33088e908b9" } +#ironrdp-rdpsnd = { git = "https://github.com/Devolutions/IronRDP", rev = "10c2415348e0ddfc097d87099c61a33088e908b9" } +#ironrdp-session = { git = "https://github.com/Devolutions/IronRDP", rev = "10c2415348e0ddfc097d87099c61a33088e908b9" } +#ironrdp-svc = { git = "https://github.com/Devolutions/IronRDP", rev = "10c2415348e0ddfc097d87099c61a33088e908b9" } +#ironrdp-tls = { git = "https://github.com/Devolutions/IronRDP", rev = "10c2415348e0ddfc097d87099c61a33088e908b9", features = ["rustls"]} +#ironrdp-tokio = { git = "https://github.com/Devolutions/IronRDP", rev = "10c2415348e0ddfc097d87099c61a33088e908b9" } + +ironrdp-cliprdr = { path = "/Users/ibeckermayer/Devolutions/IronRDP/crates/ironrdp-cliprdr" } +ironrdp-connector = { path = "/Users/ibeckermayer/Devolutions/IronRDP/crates/ironrdp-connector" } +ironrdp-displaycontrol = { path = "/Users/ibeckermayer/Devolutions/IronRDP/crates/ironrdp-displaycontrol" } +ironrdp-dvc = { path = "/Users/ibeckermayer/Devolutions/IronRDP/crates/ironrdp-dvc" } +ironrdp-graphics = { path = "/Users/ibeckermayer/Devolutions/IronRDP/crates/ironrdp-graphics" } +ironrdp-pdu = { path = "/Users/ibeckermayer/Devolutions/IronRDP/crates/ironrdp-pdu" } +ironrdp-rdpdr = { path = "/Users/ibeckermayer/Devolutions/IronRDP/crates/ironrdp-rdpdr" } +ironrdp-rdpsnd = { path = "/Users/ibeckermayer/Devolutions/IronRDP/crates/ironrdp-rdpsnd" } +ironrdp-session = { path = "/Users/ibeckermayer/Devolutions/IronRDP/crates/ironrdp-session" } +ironrdp-svc = { path = "/Users/ibeckermayer/Devolutions/IronRDP/crates/ironrdp-svc" } +ironrdp-tls = { path = "/Users/ibeckermayer/Devolutions/IronRDP/crates/ironrdp-tls", features = ["rustls"]} +ironrdp-tokio = { path = "/Users/ibeckermayer/Devolutions/IronRDP/crates/ironrdp-tokio" } diff --git a/lib/srv/desktop/rdp/rdpclient/src/client.rs b/lib/srv/desktop/rdp/rdpclient/src/client.rs index 90da9295da74..2bc620055cd2 100644 --- a/lib/srv/desktop/rdp/rdpclient/src/client.rs +++ b/lib/srv/desktop/rdp/rdpclient/src/client.rs @@ -27,7 +27,7 @@ use ironrdp_cliprdr::{Cliprdr, CliprdrClient, CliprdrSvcMessages}; use ironrdp_connector::connection_activation::ConnectionActivationState; use ironrdp_connector::{Config, ConnectorError, Credentials, DesktopSize}; use ironrdp_displaycontrol::client::DisplayControlClient; -use ironrdp_displaycontrol::pdu::DisplayControlPdu; +use ironrdp_displaycontrol::pdu::{DisplayControlMonitorLayout, DisplayControlPdu}; use ironrdp_dvc::DvcProcessor; use ironrdp_dvc::DynamicChannelId; use ironrdp_dvc::{DrdynvcClient, DvcMessage}; @@ -39,6 +39,7 @@ use ironrdp_pdu::input::mouse::PointerFlags; use ironrdp_pdu::input::{InputEventError, MousePdu}; use ironrdp_pdu::mcs::DisconnectReason; use ironrdp_pdu::rdp::capability_sets::MajorPlatformType; +use ironrdp_pdu::rdp::client_info::PerformanceFlags; use ironrdp_pdu::rdp::RdpError; use ironrdp_pdu::write_buf::WriteBuf; use ironrdp_pdu::{custom_err, function, PduError}; @@ -355,7 +356,7 @@ impl Client { loop { let written = single_sequence_step_read( &mut read_stream, - &mut sequence, + sequence.as_mut(), &mut buf, ) .await?; @@ -370,6 +371,7 @@ impl Client { io_channel_id, user_channel_id, desktop_size, + .. } = sequence.state { // Upon completing the activation sequence, register the io/user channels @@ -503,7 +505,10 @@ impl Client { "Withheld resize for size [{:?}x{:?}] found, sending now", width, height ); - let pdu = DisplayControlPdu::create_monitor_layout_pdu(width, height)?; + let pdu: DisplayControlPdu = DisplayControlMonitorLayout::new_single_primary_monitor( + width, height, 0, width, height, + )? + .into(); return Ok(vec![Box::new(pdu)]); } @@ -744,10 +749,13 @@ impl Client { )); } - Ok::<_, ClientError>(disp_ctl_cli.encode_monitor( + Ok::<_, ClientError>(disp_ctl_cli.encode_single_primary_monitor( channel_id.unwrap(), width, height, + 0, + 0, + 0, )) }) .await???; @@ -1337,7 +1345,6 @@ fn create_config(width: u16, height: u16, pin: String) -> Config { keyboard_subtype: 0, keyboard_functional_keys_count: 12, ime_file_name: "".to_string(), - graphics: None, bitmap: Some(ironrdp_connector::BitmapConfig { lossy_compression: true, color_depth: 32, // Changing this to 16 gets us uncompressed bitmaps on machines configured like https://github.com/Devolutions/IronRDP/blob/55d11a5000ebd474c2ddc294b8b3935554443112/README.md?plain=1#L17-L36 @@ -1350,6 +1357,8 @@ fn create_config(width: u16, height: u16, pin: String) -> Config { no_server_pointer: false, autologon: true, pointer_software_rendering: false, + desktop_scale_factor: 0, + performance_flags: PerformanceFlags::empty(), } } From d5c511289ad926cfde655af241a8b9f5367d7e76 Mon Sep 17 00:00:00 2001 From: Isaiah Becker-Mayer Date: Thu, 25 Apr 2024 14:04:44 -0700 Subject: [PATCH 20/24] updates to IronRDP latest rev on https://github.com/Devolutions/IronRDP/pull/430 --- Cargo.lock | 28 ++++++------- Cargo.toml | 24 +++++------ lib/srv/desktop/rdp/rdpclient/src/client.rs | 46 ++++++++++++++------- 3 files changed, 56 insertions(+), 42 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7dc68c6b0541..fac9bdeee5f6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1225,7 +1225,7 @@ dependencies = [ [[package]] name = "ironrdp-async" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=8793b165b4467062dd0df675054186316dcc6cce#8793b165b4467062dd0df675054186316dcc6cce" +source = "git+https://github.com/Devolutions/IronRDP?rev=a40adbbe542033e7561722067fc705704783e66b#a40adbbe542033e7561722067fc705704783e66b" dependencies = [ "bytes", "ironrdp-connector", @@ -1236,7 +1236,7 @@ dependencies = [ [[package]] name = "ironrdp-cliprdr" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=8793b165b4467062dd0df675054186316dcc6cce#8793b165b4467062dd0df675054186316dcc6cce" +source = "git+https://github.com/Devolutions/IronRDP?rev=a40adbbe542033e7561722067fc705704783e66b#a40adbbe542033e7561722067fc705704783e66b" dependencies = [ "bitflags 2.5.0", "ironrdp-pdu", @@ -1248,7 +1248,7 @@ dependencies = [ [[package]] name = "ironrdp-connector" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=8793b165b4467062dd0df675054186316dcc6cce#8793b165b4467062dd0df675054186316dcc6cce" +source = "git+https://github.com/Devolutions/IronRDP?rev=a40adbbe542033e7561722067fc705704783e66b#a40adbbe542033e7561722067fc705704783e66b" dependencies = [ "ironrdp-error", "ironrdp-pdu", @@ -1263,7 +1263,7 @@ dependencies = [ [[package]] name = "ironrdp-displaycontrol" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=8793b165b4467062dd0df675054186316dcc6cce#8793b165b4467062dd0df675054186316dcc6cce" +source = "git+https://github.com/Devolutions/IronRDP?rev=a40adbbe542033e7561722067fc705704783e66b#a40adbbe542033e7561722067fc705704783e66b" dependencies = [ "ironrdp-dvc", "ironrdp-pdu", @@ -1274,7 +1274,7 @@ dependencies = [ [[package]] name = "ironrdp-dvc" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=8793b165b4467062dd0df675054186316dcc6cce#8793b165b4467062dd0df675054186316dcc6cce" +source = "git+https://github.com/Devolutions/IronRDP?rev=a40adbbe542033e7561722067fc705704783e66b#a40adbbe542033e7561722067fc705704783e66b" dependencies = [ "ironrdp-pdu", "ironrdp-svc", @@ -1285,12 +1285,12 @@ dependencies = [ [[package]] name = "ironrdp-error" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=8793b165b4467062dd0df675054186316dcc6cce#8793b165b4467062dd0df675054186316dcc6cce" +source = "git+https://github.com/Devolutions/IronRDP?rev=a40adbbe542033e7561722067fc705704783e66b#a40adbbe542033e7561722067fc705704783e66b" [[package]] name = "ironrdp-graphics" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=8793b165b4467062dd0df675054186316dcc6cce#8793b165b4467062dd0df675054186316dcc6cce" +source = "git+https://github.com/Devolutions/IronRDP?rev=a40adbbe542033e7561722067fc705704783e66b#a40adbbe542033e7561722067fc705704783e66b" dependencies = [ "bit_field", "bitflags 2.5.0", @@ -1307,7 +1307,7 @@ dependencies = [ [[package]] name = "ironrdp-pdu" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=8793b165b4467062dd0df675054186316dcc6cce#8793b165b4467062dd0df675054186316dcc6cce" +source = "git+https://github.com/Devolutions/IronRDP?rev=a40adbbe542033e7561722067fc705704783e66b#a40adbbe542033e7561722067fc705704783e66b" dependencies = [ "bit_field", "bitflags 2.5.0", @@ -1329,7 +1329,7 @@ dependencies = [ [[package]] name = "ironrdp-rdpdr" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=8793b165b4467062dd0df675054186316dcc6cce#8793b165b4467062dd0df675054186316dcc6cce" +source = "git+https://github.com/Devolutions/IronRDP?rev=a40adbbe542033e7561722067fc705704783e66b#a40adbbe542033e7561722067fc705704783e66b" dependencies = [ "bitflags 2.5.0", "ironrdp-error", @@ -1341,7 +1341,7 @@ dependencies = [ [[package]] name = "ironrdp-rdpsnd" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=8793b165b4467062dd0df675054186316dcc6cce#8793b165b4467062dd0df675054186316dcc6cce" +source = "git+https://github.com/Devolutions/IronRDP?rev=a40adbbe542033e7561722067fc705704783e66b#a40adbbe542033e7561722067fc705704783e66b" dependencies = [ "ironrdp-pdu", "ironrdp-svc", @@ -1350,7 +1350,7 @@ dependencies = [ [[package]] name = "ironrdp-session" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=8793b165b4467062dd0df675054186316dcc6cce#8793b165b4467062dd0df675054186316dcc6cce" +source = "git+https://github.com/Devolutions/IronRDP?rev=a40adbbe542033e7561722067fc705704783e66b#a40adbbe542033e7561722067fc705704783e66b" dependencies = [ "ironrdp-connector", "ironrdp-displaycontrol", @@ -1365,7 +1365,7 @@ dependencies = [ [[package]] name = "ironrdp-svc" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=8793b165b4467062dd0df675054186316dcc6cce#8793b165b4467062dd0df675054186316dcc6cce" +source = "git+https://github.com/Devolutions/IronRDP?rev=a40adbbe542033e7561722067fc705704783e66b#a40adbbe542033e7561722067fc705704783e66b" dependencies = [ "bitflags 2.5.0", "ironrdp-pdu", @@ -1374,7 +1374,7 @@ dependencies = [ [[package]] name = "ironrdp-tls" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=8793b165b4467062dd0df675054186316dcc6cce#8793b165b4467062dd0df675054186316dcc6cce" +source = "git+https://github.com/Devolutions/IronRDP?rev=a40adbbe542033e7561722067fc705704783e66b#a40adbbe542033e7561722067fc705704783e66b" dependencies = [ "tokio", "tokio-rustls", @@ -1384,7 +1384,7 @@ dependencies = [ [[package]] name = "ironrdp-tokio" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=8793b165b4467062dd0df675054186316dcc6cce#8793b165b4467062dd0df675054186316dcc6cce" +source = "git+https://github.com/Devolutions/IronRDP?rev=a40adbbe542033e7561722067fc705704783e66b#a40adbbe542033e7561722067fc705704783e66b" dependencies = [ "bytes", "ironrdp-async", diff --git a/Cargo.toml b/Cargo.toml index c0cfb8692dc0..422fd62d926c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,15 +25,15 @@ codegen-units = 1 # ironrdp-cliprdr = { path = "/path/to/local/IronRDP/crates/ironrdp-cliprdr" } # This rev hash is for testing purposes only. It should NOT be merged, and should be updated to IronRDP master once # https://github.com/Devolutions/IronRDP/pull/430 and https://github.com/Devolutions/IronRDP/pull/436 are merged. -ironrdp-cliprdr = { git = "https://github.com/Devolutions/IronRDP", rev = "8793b165b4467062dd0df675054186316dcc6cce" } -ironrdp-connector = { git = "https://github.com/Devolutions/IronRDP", rev = "8793b165b4467062dd0df675054186316dcc6cce" } -ironrdp-displaycontrol = { git = "https://github.com/Devolutions/IronRDP", rev = "8793b165b4467062dd0df675054186316dcc6cce" } -ironrdp-dvc = { git = "https://github.com/Devolutions/IronRDP", rev = "8793b165b4467062dd0df675054186316dcc6cce" } -ironrdp-graphics = { git = "https://github.com/Devolutions/IronRDP", rev = "8793b165b4467062dd0df675054186316dcc6cce" } -ironrdp-pdu = { git = "https://github.com/Devolutions/IronRDP", rev = "8793b165b4467062dd0df675054186316dcc6cce" } -ironrdp-rdpdr = { git = "https://github.com/Devolutions/IronRDP", rev = "8793b165b4467062dd0df675054186316dcc6cce" } -ironrdp-rdpsnd = { git = "https://github.com/Devolutions/IronRDP", rev = "8793b165b4467062dd0df675054186316dcc6cce" } -ironrdp-session = { git = "https://github.com/Devolutions/IronRDP", rev = "8793b165b4467062dd0df675054186316dcc6cce" } -ironrdp-svc = { git = "https://github.com/Devolutions/IronRDP", rev = "8793b165b4467062dd0df675054186316dcc6cce" } -ironrdp-tls = { git = "https://github.com/Devolutions/IronRDP", rev = "8793b165b4467062dd0df675054186316dcc6cce", features = ["rustls"]} -ironrdp-tokio = { git = "https://github.com/Devolutions/IronRDP", rev = "8793b165b4467062dd0df675054186316dcc6cce" } +ironrdp-cliprdr = { git = "https://github.com/Devolutions/IronRDP", rev = "a40adbbe542033e7561722067fc705704783e66b" } +ironrdp-connector = { git = "https://github.com/Devolutions/IronRDP", rev = "a40adbbe542033e7561722067fc705704783e66b" } +ironrdp-displaycontrol = { git = "https://github.com/Devolutions/IronRDP", rev = "a40adbbe542033e7561722067fc705704783e66b" } +ironrdp-dvc = { git = "https://github.com/Devolutions/IronRDP", rev = "a40adbbe542033e7561722067fc705704783e66b" } +ironrdp-graphics = { git = "https://github.com/Devolutions/IronRDP", rev = "a40adbbe542033e7561722067fc705704783e66b" } +ironrdp-pdu = { git = "https://github.com/Devolutions/IronRDP", rev = "a40adbbe542033e7561722067fc705704783e66b" } +ironrdp-rdpdr = { git = "https://github.com/Devolutions/IronRDP", rev = "a40adbbe542033e7561722067fc705704783e66b" } +ironrdp-rdpsnd = { git = "https://github.com/Devolutions/IronRDP", rev = "a40adbbe542033e7561722067fc705704783e66b" } +ironrdp-session = { git = "https://github.com/Devolutions/IronRDP", rev = "a40adbbe542033e7561722067fc705704783e66b" } +ironrdp-svc = { git = "https://github.com/Devolutions/IronRDP", rev = "a40adbbe542033e7561722067fc705704783e66b" } +ironrdp-tls = { git = "https://github.com/Devolutions/IronRDP", rev = "a40adbbe542033e7561722067fc705704783e66b", features = ["rustls"]} +ironrdp-tokio = { git = "https://github.com/Devolutions/IronRDP", rev = "a40adbbe542033e7561722067fc705704783e66b" } diff --git a/lib/srv/desktop/rdp/rdpclient/src/client.rs b/lib/srv/desktop/rdp/rdpclient/src/client.rs index 6d72a3cae2dc..2f6503e9117d 100644 --- a/lib/srv/desktop/rdp/rdpclient/src/client.rs +++ b/lib/srv/desktop/rdp/rdpclient/src/client.rs @@ -27,11 +27,11 @@ use ironrdp_cliprdr::{Cliprdr, CliprdrClient, CliprdrSvcMessages}; use ironrdp_connector::connection_activation::ConnectionActivationState; use ironrdp_connector::{Config, ConnectorError, Credentials, DesktopSize}; use ironrdp_displaycontrol::client::DisplayControlClient; -use ironrdp_displaycontrol::pdu::{DisplayControlMonitorLayout, DisplayControlPdu}; -use ironrdp_dvc::DynamicChannelId; +use ironrdp_displaycontrol::pdu::{ + DisplayControlMonitorLayout, DisplayControlPdu, MonitorLayoutEntry, +}; use ironrdp_dvc::{DrdynvcClient, DvcMessage}; use ironrdp_dvc::{DvcProcessor, DynamicVirtualChannel}; -use ironrdp_pdu::cursor::WriteCursor; use ironrdp_pdu::input::fast_path::{ FastPathInput, FastPathInputEvent, KeyboardFlags, SynchronizeFlags, }; @@ -42,8 +42,8 @@ use ironrdp_pdu::rdp::capability_sets::MajorPlatformType; use ironrdp_pdu::rdp::client_info::PerformanceFlags; use ironrdp_pdu::rdp::RdpError; use ironrdp_pdu::write_buf::WriteBuf; +use ironrdp_pdu::PduResult; use ironrdp_pdu::{custom_err, function, PduError}; -use ironrdp_pdu::{PduEncode, PduResult}; use ironrdp_rdpdr::pdu::efs::ClientDeviceListAnnounce; use ironrdp_rdpdr::pdu::RdpdrPdu; use ironrdp_rdpdr::Rdpdr; @@ -701,7 +701,18 @@ impl Client { write_stream: &mut RdpWriteStream, resize_withholder: Arc>, ) -> ClientResult<()> { - debug!("Received WriteScreenResize PDU"); + // Adjust the screen size to the nearest supported resolution (per the RDP spec). + let init_width = width; + let init_height = height; + debug!( + "Received screen resize [{:?}x{:?}]", + init_width, init_height + ); + let (width, height) = MonitorLayoutEntry::adjust_display_size(init_width, init_height); + if width != init_width || height != init_height { + debug!("Adjusted screen resize to [{:?}x{:?}]", width, height); + } + // Determine whether to withhold the resize or perform it immediately. let action = { let x224_processor = Self::x224_lock(&x224_processor)?; @@ -724,7 +735,6 @@ impl Client { }; // Drop the x224 lock here to avoid holding it over the await below. if let Some((width, height)) = action { - debug!("Performing resize to [{:?}x{:?}]", width, height); return Client::write_screen_resize( write_stream, x224_processor.clone(), @@ -748,11 +758,15 @@ impl Client { let messages = global::TOKIO_RT .spawn_blocking(move || { let x224_processor = Self::x224_lock(&cloned)?; - let dvc = x224_processor.get_dvc::().ok_or( - ClientError::InternalError("DisplayControlClient not found".to_string()), - )?; - let disp_ctl_cli = dvc.channel_processor_downcast_ref()?; - let channel_id = dvc.channel_id()?; + let dvc = Self::get_dvc::(&x224_processor)?; + let channel_id = dvc.channel_id().ok_or(ClientError::InternalError( + "DisplayControlClient channel_id not found".to_string(), + ))?; + let disp_ctl_cli = dvc + .channel_processor_downcast_ref::() + .ok_or(ClientError::InternalError( + "DisplayControlClient not found".to_string(), + ))?; Ok::<_, ClientError>(disp_ctl_cli.encode_single_primary_monitor( channel_id, @@ -769,7 +783,7 @@ impl Client { SvcProcessorMessages::::new(messages), ) .await?; - + debug!("Writing resize to [{:?}x{:?}]", width, height); write_stream.write_all(&encoded).await?; Ok(()) @@ -799,7 +813,7 @@ impl Client { .spawn_blocking(move || { debug!("received tdp: {:?}", res); let mut x224_processor = Self::x224_lock(&x224_processor)?; - let rdpdr = Self::rdpdr_backend(&mut x224_processor)?; + let rdpdr: &mut TeleportRdpdrBackend = Self::rdpdr_backend(&mut x224_processor)?; rdpdr.handle_tdp_sd_info_response(res)?; Ok(()) }) @@ -844,7 +858,7 @@ impl Client { .spawn_blocking(move || { debug!("received tdp: {:?}", res); let mut x224_processor = Self::x224_lock(&x224_processor)?; - let rdpdr = Self::rdpdr_backend(&mut x224_processor)?; + let rdpdr: &mut TeleportRdpdrBackend = Self::rdpdr_backend(&mut x224_processor)?; rdpdr.handle_tdp_sd_list_response(res)?; Ok(()) }) @@ -889,7 +903,7 @@ impl Client { .spawn_blocking(move || { debug!("received tdp: {:?}", res); let mut x224_processor = Self::x224_lock(&x224_processor)?; - let rdpdr = Self::rdpdr_backend(&mut x224_processor)?; + let rdpdr: &mut TeleportRdpdrBackend = Self::rdpdr_backend(&mut x224_processor)?; rdpdr.handle_tdp_sd_move_response(res)?; Ok(()) }) @@ -1023,7 +1037,7 @@ impl Client { fn get_dvc<'a, S>( x224_processor: &'a MutexGuard<'_, x224::Processor>, - ) -> Result, ClientError> + ) -> Result<&'a DynamicVirtualChannel, ClientError> where S: DvcProcessor + 'static, { From 638b6117fbcb539b3491a113eec4cd58c0ff3085 Mon Sep 17 00:00:00 2001 From: Isaiah Becker-Mayer Date: Thu, 25 Apr 2024 14:08:53 -0700 Subject: [PATCH 21/24] reverting mistaken changes --- .github/workflows/os-compatibility-test.yaml | 16 ---------------- e | 2 +- 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/.github/workflows/os-compatibility-test.yaml b/.github/workflows/os-compatibility-test.yaml index 477930e3eb36..9d2e6e782d8d 100644 --- a/.github/workflows/os-compatibility-test.yaml +++ b/.github/workflows/os-compatibility-test.yaml @@ -48,22 +48,6 @@ jobs: - name: Prepare workspace uses: ./.github/actions/prepare-workspace - - name: Determine Toolchain Versions and cache paths - run: | - echo NODE_VERSION=$(make -C build.assets print-node-version) >> $GITHUB_ENV - echo GOLANG_VERSION=$(make -C build.assets print-go-version | sed 's/^go//') >> $GITHUB_ENV - echo RUST_VERSION=$(make -C build.assets print-rust-version) >> $GITHUB_ENV - echo WASM_PACK_VERSION=$(make -C build.assets print-wasm-pack-version) >> $GITHUB_ENV - echo PKG_CONFIG_PATH="$(build.assets/build-fido2-macos.sh pkg_config_path)" >> $GITHUB_ENV - - - name: Print versions - run: | - echo "make: $(make --version)" - echo "node: ${NODE_VERSION}" - echo "go: ${GOLANG_VERSION}" - echo "rust: ${RUST_VERSION}" - echo "wasm-pack: ${WASM_PACK_VERSION}" - - name: Run make run: | make -j"$(nproc)" binaries diff --git a/e b/e index 62fb227d1ec4..c21f30dd7040 160000 --- a/e +++ b/e @@ -1 +1 @@ -Subproject commit 62fb227d1ec4b03e226c5ce9cdf63f588e9156b6 +Subproject commit c21f30dd70401c9ff53a728d4d69f35eb36ce400 From 88cdb8498f41b352cc14004ff047e40d011d32a3 Mon Sep 17 00:00:00 2001 From: Isaiah Becker-Mayer Date: Thu, 25 Apr 2024 14:39:42 -0700 Subject: [PATCH 22/24] throttle -> debounce and naming changes --- lib/srv/desktop/rdp/rdpclient/src/client.rs | 57 ++++++++++--------- .../src/DesktopSession/useTdpClientCanvas.tsx | 14 +++-- web/packages/teleport/src/lib/tdp/client.ts | 8 +-- 3 files changed, 43 insertions(+), 36 deletions(-) diff --git a/lib/srv/desktop/rdp/rdpclient/src/client.rs b/lib/srv/desktop/rdp/rdpclient/src/client.rs index 2f6503e9117d..611deca70a47 100644 --- a/lib/srv/desktop/rdp/rdpclient/src/client.rs +++ b/lib/srv/desktop/rdp/rdpclient/src/client.rs @@ -74,8 +74,11 @@ use tokio_boring::{HandshakeError, SslStream}; const RDP_CONNECT_TIMEOUT: Duration = Duration::from_secs(5); -struct ResizeWithholder { - withheld_resize: Option<(u32, u32)>, +/// The "Microsoft::Windows::RDS::DisplayControl" DVC is opened +/// by the server. Until it does so, we withhold the latest screen +/// resize, and only send it once we're notified that the DVC is open. +struct PendingResize { + pending_resize: Option<(u32, u32)>, } /// The RDP client on the Rust side of things. Each `Client` @@ -87,7 +90,7 @@ pub struct Client { write_stream: Option, function_receiver: Option, x224_processor: Arc>, - resize_withholder: Arc>, + pending_resize: Arc>, } impl Client { @@ -164,21 +167,21 @@ impl Client { debug!("creating rdpdr client with directory sharing disabled") } - let resize_withholder = Arc::new(Mutex::new(ResizeWithholder { - withheld_resize: None, + let pending_resize = Arc::new(Mutex::new(PendingResize { + pending_resize: None, })); - let resize_manager_clone = resize_withholder.clone(); + let pending_resize_clone = pending_resize.clone(); let display_control = DisplayControlClient::new(move |_| { - Self::on_display_ctl_capabilities_received(&resize_manager_clone) + Self::on_display_ctl_capabilities_received(&pending_resize_clone) }); let drdynvc_client = DrdynvcClient::new().with_dynamic_channel(display_control); let mut connector = ironrdp_connector::ClientConnector::new(connector_config.clone()) .with_server_addr(server_socket_addr) - .with_static_channel(drdynvc_client) + .with_static_channel(drdynvc_client) // require for resizing .with_static_channel(Rdpsnd::new()) // required for rdpdr to work - .with_static_channel(rdpdr); + .with_static_channel(rdpdr); // required for smart card + directory sharing if params.allow_clipboard { connector = connector.with_static_channel(Cliprdr::new(Box::new( @@ -240,7 +243,7 @@ impl Client { write_stream, function_receiver, x224_processor, - resize_withholder, + pending_resize, }) } @@ -290,7 +293,7 @@ impl Client { write_stream, function_receiver, self.x224_processor.clone(), - self.resize_withholder.clone(), + self.pending_resize.clone(), ); // Wait for either loop to finish. When one does, abort the other and return the result. @@ -399,7 +402,7 @@ impl Client { mut write_stream: RdpWriteStream, mut write_receiver: FunctionReceiver, x224_processor: Arc>, - resize_withholder: Arc>, + pending_resize: Arc>, ) -> tokio::task::JoinHandle> { global::TOKIO_RT.spawn(async move { loop { @@ -427,7 +430,7 @@ impl Client { height, x224_processor.clone(), &mut write_stream, - resize_withholder.clone(), + pending_resize.clone(), ) .await?; } @@ -495,17 +498,17 @@ impl Client { } fn on_display_ctl_capabilities_received( - resize_withholder: &Arc>, + pending_resize: &Arc>, ) -> PduResult> { debug!("DisplayControlClient channel opened"); // We've been notified that the DisplayControl dvc channel has been opened: - let mut resize_withholder = - Self::resize_manager_lock(resize_withholder).map_err(|err| custom_err!(err))?; - let withheld_resize = resize_withholder.withheld_resize.take(); - if let Some((width, height)) = withheld_resize { - // If there was a resize withheld, perform it now. + let mut pending_resize = + Self::resize_manager_lock(pending_resize).map_err(|err| custom_err!(err))?; + let pending_resize = pending_resize.pending_resize.take(); + if let Some((width, height)) = pending_resize { + // If there was a resize pending, perform it now. debug!( - "Withheld resize for size [{:?}x{:?}] found, sending now", + "Pending resize for size [{:?}x{:?}] found, sending now", width, height ); let pdu: DisplayControlPdu = DisplayControlMonitorLayout::new_single_primary_monitor( @@ -518,7 +521,7 @@ impl Client { return Ok(vec![Box::new(pdu)]); } - // No resize was withheld, nothing to do. + // No resize was pending, nothing to do. Ok(vec![]) } @@ -699,7 +702,7 @@ impl Client { height: u32, x224_processor: Arc>, write_stream: &mut RdpWriteStream, - resize_withholder: Arc>, + pending_resize: Arc>, ) -> ClientResult<()> { // Adjust the screen size to the nearest supported resolution (per the RDP spec). let init_width = width; @@ -728,8 +731,8 @@ impl Client { // Sending the resize now would cause an RDP error and end the session; instead we withhold // it until the DisplayControl channel is ready. debug!("DisplayControl channel not ready, withholding resize"); - let mut resize_withholder = Self::resize_manager_lock(&resize_withholder)?; - resize_withholder.withheld_resize = Some((width, height)); + let mut pending_resize = Self::resize_manager_lock(&pending_resize)?; + pending_resize.pending_resize = Some((width, height)); None // No immediate action required. } }; // Drop the x224 lock here to avoid holding it over the await below. @@ -982,9 +985,9 @@ impl Client { } fn resize_manager_lock( - resize_withholder: &Arc>, - ) -> Result, SessionError> { - resize_withholder + pending_resize: &Arc>, + ) -> Result, SessionError> { + pending_resize .lock() .map_err(|err| reason_err!(function!(), "PoisonError: {:?}", err)) } diff --git a/web/packages/teleport/src/DesktopSession/useTdpClientCanvas.tsx b/web/packages/teleport/src/DesktopSession/useTdpClientCanvas.tsx index 5f0a1666ab7c..3373c2f420b4 100644 --- a/web/packages/teleport/src/DesktopSession/useTdpClientCanvas.tsx +++ b/web/packages/teleport/src/DesktopSession/useTdpClientCanvas.tsx @@ -20,7 +20,7 @@ import { useState, useEffect, useRef } from 'react'; import { Attempt } from 'shared/hooks/useAttemptNext'; import { NotificationItem } from 'shared/components/Notification'; -import { throttle } from 'shared/utils/highbar'; +import { debounce } from 'shared/utils/highbar'; import { TdpClient, ButtonState, ScrollAxis } from 'teleport/lib/tdp'; import { @@ -272,10 +272,14 @@ export default function useTdpClientCanvas(props: Props) { // on the remote machine. const canvasOnContextMenu = () => false; - const windowOnResize = throttle((cli: TdpClient) => { - const spec = getDisplaySize(); - cli.resize(spec); - }, 250); + const windowOnResize = debounce( + (cli: TdpClient) => { + const spec = getDisplaySize(); + cli.resize(spec); + }, + 250, + { trailing: true } + ); const sendLocalClipboardToRemote = async (cli: TdpClient) => { if (await sysClipboardGuard(clipboardSharingState, 'read')) { diff --git a/web/packages/teleport/src/lib/tdp/client.ts b/web/packages/teleport/src/lib/tdp/client.ts index 1dc45174afe4..8985999baa97 100644 --- a/web/packages/teleport/src/lib/tdp/client.ts +++ b/web/packages/teleport/src/lib/tdp/client.ts @@ -197,10 +197,10 @@ export default class Client extends EventEmitterWebAuthnSender { this.handlePng2Frame(buffer); break; case MessageType.RDP_CONNECTION_ACTIVATED: - this.handleRDPConnectionActivated(buffer); + this.handleRdpConnectionActivated(buffer); break; case MessageType.RDP_FASTPATH_PDU: - this.handleRDPFastPathPDU(buffer); + this.handleRdpFastPathPDU(buffer); break; case MessageType.CLIENT_SCREEN_SPEC: this.handleClientScreenSpec(buffer); @@ -325,7 +325,7 @@ export default class Client extends EventEmitterWebAuthnSender { ); } - handleRDPConnectionActivated(buffer: ArrayBuffer) { + handleRdpConnectionActivated(buffer: ArrayBuffer) { const { ioChannelId, userChannelId, screenWidth, screenHeight } = this.codec.decodeRDPConnectionActivated(buffer); const spec = { width: screenWidth, height: screenHeight }; @@ -343,7 +343,7 @@ export default class Client extends EventEmitterWebAuthnSender { this.emit(TdpClientEvent.TDP_CLIENT_SCREEN_SPEC, spec); } - handleRDPFastPathPDU(buffer: ArrayBuffer) { + handleRdpFastPathPDU(buffer: ArrayBuffer) { let rdpFastPathPDU = this.codec.decodeRDPFastPathPDU(buffer); // This should never happen but let's catch it with an error in case it does. From 0ecbf48233b3f7f54f240e61cb2e673c03cf7609 Mon Sep 17 00:00:00 2001 From: Isaiah Becker-Mayer Date: Thu, 25 Apr 2024 17:52:36 -0700 Subject: [PATCH 23/24] js renamings --- web/packages/teleport/src/lib/tdp/client.ts | 10 +++++----- web/packages/teleport/src/lib/tdp/codec.ts | 8 ++++---- web/packages/teleport/src/lib/tdp/playerClient.ts | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/web/packages/teleport/src/lib/tdp/client.ts b/web/packages/teleport/src/lib/tdp/client.ts index 8985999baa97..da2c9a16e7e3 100644 --- a/web/packages/teleport/src/lib/tdp/client.ts +++ b/web/packages/teleport/src/lib/tdp/client.ts @@ -327,7 +327,7 @@ export default class Client extends EventEmitterWebAuthnSender { handleRdpConnectionActivated(buffer: ArrayBuffer) { const { ioChannelId, userChannelId, screenWidth, screenHeight } = - this.codec.decodeRDPConnectionActivated(buffer); + this.codec.decodeRdpConnectionActivated(buffer); const spec = { width: screenWidth, height: screenHeight }; this.logger.info( `screen spec received from server ${spec.width} x ${spec.height}` @@ -344,7 +344,7 @@ export default class Client extends EventEmitterWebAuthnSender { } handleRdpFastPathPDU(buffer: ArrayBuffer) { - let rdpFastPathPDU = this.codec.decodeRDPFastPathPDU(buffer); + let rdpFastPathPDU = this.codec.decodeRdpFastPathPDU(buffer); // This should never happen but let's catch it with an error in case it does. if (!this.fastPathProcessor) @@ -361,7 +361,7 @@ export default class Client extends EventEmitterWebAuthnSender { this.emit(TdpClientEvent.TDP_BMP_FRAME, bmpFrame); }, (responseFrame: ArrayBuffer) => { - this.sendRDPResponsePDU(responseFrame); + this.sendRdpResponsePDU(responseFrame); }, (data: ImageData | boolean, hotspot_x?: number, hotspot_y?: number) => { this.emit(TdpClientEvent.POINTER, { data, hotspot_x, hotspot_y }); @@ -711,8 +711,8 @@ export default class Client extends EventEmitterWebAuthnSender { this.sendClientScreenSpec(spec); } - sendRDPResponsePDU(responseFrame: ArrayBuffer) { - this.send(this.codec.encodeRDPResponsePDU(responseFrame)); + sendRdpResponsePDU(responseFrame: ArrayBuffer) { + this.send(this.codec.encodeRdpResponsePDU(responseFrame)); } // Emits an errType event, closing the socket if the error was fatal. diff --git a/web/packages/teleport/src/lib/tdp/codec.ts b/web/packages/teleport/src/lib/tdp/codec.ts index 4fb502eac915..b670e8d03dd6 100644 --- a/web/packages/teleport/src/lib/tdp/codec.ts +++ b/web/packages/teleport/src/lib/tdp/codec.ts @@ -108,7 +108,7 @@ export type ClipboardData = { }; // | message type (31) | io_channel_id uint16 | user_channel_id uint16 | screen_width uint16 | screen_height uint16 | -export type RDPConnectionActivated = { +export type RdpConnectionActivated = { ioChannelId: number; userChannelId: number; screenWidth: number; @@ -716,7 +716,7 @@ export default class Codec { } // | message type (30) | data_length uint32 | data []byte | - encodeRDPResponsePDU(responseFrame: ArrayBuffer): Message { + encodeRdpResponsePDU(responseFrame: ArrayBuffer): Message { const bufLen = BYTE_LEN + UINT_32_LEN + responseFrame.byteLength; const buffer = new ArrayBuffer(bufLen); const view = new DataView(buffer); @@ -865,7 +865,7 @@ export default class Codec { } // | message type (29) | data_length uint32 | data []byte | - decodeRDPFastPathPDU(buffer: ArrayBuffer): RdpFastPathPdu { + decodeRdpFastPathPDU(buffer: ArrayBuffer): RdpFastPathPdu { const dv = new DataView(buffer); let offset = 0; offset += BYTE_LEN; // eat message type @@ -875,7 +875,7 @@ export default class Codec { } // | message type (31) | io_channel_id uint16 | user_channel_id uint16 | screen_width uint16 | screen_height uint16 | - decodeRDPConnectionActivated(buffer: ArrayBuffer): RDPConnectionActivated { + decodeRdpConnectionActivated(buffer: ArrayBuffer): RdpConnectionActivated { const dv = new DataView(buffer); let offset = 0; offset += BYTE_LEN; // eat message type diff --git a/web/packages/teleport/src/lib/tdp/playerClient.ts b/web/packages/teleport/src/lib/tdp/playerClient.ts index 1b8473d03b0c..dd32996b5bd7 100644 --- a/web/packages/teleport/src/lib/tdp/playerClient.ts +++ b/web/packages/teleport/src/lib/tdp/playerClient.ts @@ -206,7 +206,7 @@ export class PlayerClient extends Client { // RDP response PDUs to the server during playback, which is unnecessary // and breaks the playback system. // eslint-disable-next-line @typescript-eslint/no-unused-vars - sendRDPResponsePDU(responseFrame: ArrayBuffer) { + sendRdpResponsePDU(responseFrame: ArrayBuffer) { return; } From e5efaeb52f708c2ea27042dedbaf1d3c36595b95 Mon Sep 17 00:00:00 2001 From: Isaiah Becker-Mayer Date: Mon, 29 Apr 2024 12:26:02 -0700 Subject: [PATCH 24/24] updates to IronRDP master --- Cargo.lock | 28 ++++++++++++++-------------- Cargo.toml | 26 ++++++++++++-------------- 2 files changed, 26 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1d3fc8574cbb..993fcebe49e9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1225,7 +1225,7 @@ dependencies = [ [[package]] name = "ironrdp-async" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=a40adbbe542033e7561722067fc705704783e66b#a40adbbe542033e7561722067fc705704783e66b" +source = "git+https://github.com/Devolutions/IronRDP?rev=fd105e4b56647ab2f54aa23954aec4aaeef118e2#fd105e4b56647ab2f54aa23954aec4aaeef118e2" dependencies = [ "bytes", "ironrdp-connector", @@ -1236,7 +1236,7 @@ dependencies = [ [[package]] name = "ironrdp-cliprdr" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=a40adbbe542033e7561722067fc705704783e66b#a40adbbe542033e7561722067fc705704783e66b" +source = "git+https://github.com/Devolutions/IronRDP?rev=fd105e4b56647ab2f54aa23954aec4aaeef118e2#fd105e4b56647ab2f54aa23954aec4aaeef118e2" dependencies = [ "bitflags 2.5.0", "ironrdp-pdu", @@ -1248,7 +1248,7 @@ dependencies = [ [[package]] name = "ironrdp-connector" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=a40adbbe542033e7561722067fc705704783e66b#a40adbbe542033e7561722067fc705704783e66b" +source = "git+https://github.com/Devolutions/IronRDP?rev=fd105e4b56647ab2f54aa23954aec4aaeef118e2#fd105e4b56647ab2f54aa23954aec4aaeef118e2" dependencies = [ "ironrdp-error", "ironrdp-pdu", @@ -1263,7 +1263,7 @@ dependencies = [ [[package]] name = "ironrdp-displaycontrol" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=a40adbbe542033e7561722067fc705704783e66b#a40adbbe542033e7561722067fc705704783e66b" +source = "git+https://github.com/Devolutions/IronRDP?rev=fd105e4b56647ab2f54aa23954aec4aaeef118e2#fd105e4b56647ab2f54aa23954aec4aaeef118e2" dependencies = [ "ironrdp-dvc", "ironrdp-pdu", @@ -1274,7 +1274,7 @@ dependencies = [ [[package]] name = "ironrdp-dvc" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=a40adbbe542033e7561722067fc705704783e66b#a40adbbe542033e7561722067fc705704783e66b" +source = "git+https://github.com/Devolutions/IronRDP?rev=fd105e4b56647ab2f54aa23954aec4aaeef118e2#fd105e4b56647ab2f54aa23954aec4aaeef118e2" dependencies = [ "ironrdp-pdu", "ironrdp-svc", @@ -1285,12 +1285,12 @@ dependencies = [ [[package]] name = "ironrdp-error" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=a40adbbe542033e7561722067fc705704783e66b#a40adbbe542033e7561722067fc705704783e66b" +source = "git+https://github.com/Devolutions/IronRDP?rev=fd105e4b56647ab2f54aa23954aec4aaeef118e2#fd105e4b56647ab2f54aa23954aec4aaeef118e2" [[package]] name = "ironrdp-graphics" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=a40adbbe542033e7561722067fc705704783e66b#a40adbbe542033e7561722067fc705704783e66b" +source = "git+https://github.com/Devolutions/IronRDP?rev=fd105e4b56647ab2f54aa23954aec4aaeef118e2#fd105e4b56647ab2f54aa23954aec4aaeef118e2" dependencies = [ "bit_field", "bitflags 2.5.0", @@ -1307,7 +1307,7 @@ dependencies = [ [[package]] name = "ironrdp-pdu" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=a40adbbe542033e7561722067fc705704783e66b#a40adbbe542033e7561722067fc705704783e66b" +source = "git+https://github.com/Devolutions/IronRDP?rev=fd105e4b56647ab2f54aa23954aec4aaeef118e2#fd105e4b56647ab2f54aa23954aec4aaeef118e2" dependencies = [ "bit_field", "bitflags 2.5.0", @@ -1329,7 +1329,7 @@ dependencies = [ [[package]] name = "ironrdp-rdpdr" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=a40adbbe542033e7561722067fc705704783e66b#a40adbbe542033e7561722067fc705704783e66b" +source = "git+https://github.com/Devolutions/IronRDP?rev=fd105e4b56647ab2f54aa23954aec4aaeef118e2#fd105e4b56647ab2f54aa23954aec4aaeef118e2" dependencies = [ "bitflags 2.5.0", "ironrdp-error", @@ -1341,7 +1341,7 @@ dependencies = [ [[package]] name = "ironrdp-rdpsnd" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=a40adbbe542033e7561722067fc705704783e66b#a40adbbe542033e7561722067fc705704783e66b" +source = "git+https://github.com/Devolutions/IronRDP?rev=fd105e4b56647ab2f54aa23954aec4aaeef118e2#fd105e4b56647ab2f54aa23954aec4aaeef118e2" dependencies = [ "ironrdp-pdu", "ironrdp-svc", @@ -1350,7 +1350,7 @@ dependencies = [ [[package]] name = "ironrdp-session" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=a40adbbe542033e7561722067fc705704783e66b#a40adbbe542033e7561722067fc705704783e66b" +source = "git+https://github.com/Devolutions/IronRDP?rev=fd105e4b56647ab2f54aa23954aec4aaeef118e2#fd105e4b56647ab2f54aa23954aec4aaeef118e2" dependencies = [ "ironrdp-connector", "ironrdp-displaycontrol", @@ -1365,7 +1365,7 @@ dependencies = [ [[package]] name = "ironrdp-svc" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=a40adbbe542033e7561722067fc705704783e66b#a40adbbe542033e7561722067fc705704783e66b" +source = "git+https://github.com/Devolutions/IronRDP?rev=fd105e4b56647ab2f54aa23954aec4aaeef118e2#fd105e4b56647ab2f54aa23954aec4aaeef118e2" dependencies = [ "bitflags 2.5.0", "ironrdp-pdu", @@ -1374,7 +1374,7 @@ dependencies = [ [[package]] name = "ironrdp-tls" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=a40adbbe542033e7561722067fc705704783e66b#a40adbbe542033e7561722067fc705704783e66b" +source = "git+https://github.com/Devolutions/IronRDP?rev=fd105e4b56647ab2f54aa23954aec4aaeef118e2#fd105e4b56647ab2f54aa23954aec4aaeef118e2" dependencies = [ "tokio", "tokio-rustls", @@ -1384,7 +1384,7 @@ dependencies = [ [[package]] name = "ironrdp-tokio" version = "0.1.0" -source = "git+https://github.com/Devolutions/IronRDP?rev=a40adbbe542033e7561722067fc705704783e66b#a40adbbe542033e7561722067fc705704783e66b" +source = "git+https://github.com/Devolutions/IronRDP?rev=fd105e4b56647ab2f54aa23954aec4aaeef118e2#fd105e4b56647ab2f54aa23954aec4aaeef118e2" dependencies = [ "bytes", "ironrdp-async", diff --git a/Cargo.toml b/Cargo.toml index 422fd62d926c..9577b8bfd872 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,17 +23,15 @@ codegen-units = 1 [workspace.dependencies] # Note: To use a local IronRDP repository as a crate (for example, ironrdp-cliprdr), define the dependency as follows: # ironrdp-cliprdr = { path = "/path/to/local/IronRDP/crates/ironrdp-cliprdr" } -# This rev hash is for testing purposes only. It should NOT be merged, and should be updated to IronRDP master once -# https://github.com/Devolutions/IronRDP/pull/430 and https://github.com/Devolutions/IronRDP/pull/436 are merged. -ironrdp-cliprdr = { git = "https://github.com/Devolutions/IronRDP", rev = "a40adbbe542033e7561722067fc705704783e66b" } -ironrdp-connector = { git = "https://github.com/Devolutions/IronRDP", rev = "a40adbbe542033e7561722067fc705704783e66b" } -ironrdp-displaycontrol = { git = "https://github.com/Devolutions/IronRDP", rev = "a40adbbe542033e7561722067fc705704783e66b" } -ironrdp-dvc = { git = "https://github.com/Devolutions/IronRDP", rev = "a40adbbe542033e7561722067fc705704783e66b" } -ironrdp-graphics = { git = "https://github.com/Devolutions/IronRDP", rev = "a40adbbe542033e7561722067fc705704783e66b" } -ironrdp-pdu = { git = "https://github.com/Devolutions/IronRDP", rev = "a40adbbe542033e7561722067fc705704783e66b" } -ironrdp-rdpdr = { git = "https://github.com/Devolutions/IronRDP", rev = "a40adbbe542033e7561722067fc705704783e66b" } -ironrdp-rdpsnd = { git = "https://github.com/Devolutions/IronRDP", rev = "a40adbbe542033e7561722067fc705704783e66b" } -ironrdp-session = { git = "https://github.com/Devolutions/IronRDP", rev = "a40adbbe542033e7561722067fc705704783e66b" } -ironrdp-svc = { git = "https://github.com/Devolutions/IronRDP", rev = "a40adbbe542033e7561722067fc705704783e66b" } -ironrdp-tls = { git = "https://github.com/Devolutions/IronRDP", rev = "a40adbbe542033e7561722067fc705704783e66b", features = ["rustls"]} -ironrdp-tokio = { git = "https://github.com/Devolutions/IronRDP", rev = "a40adbbe542033e7561722067fc705704783e66b" } +ironrdp-cliprdr = { git = "https://github.com/Devolutions/IronRDP", rev = "fd105e4b56647ab2f54aa23954aec4aaeef118e2" } +ironrdp-connector = { git = "https://github.com/Devolutions/IronRDP", rev = "fd105e4b56647ab2f54aa23954aec4aaeef118e2" } +ironrdp-displaycontrol = { git = "https://github.com/Devolutions/IronRDP", rev = "fd105e4b56647ab2f54aa23954aec4aaeef118e2" } +ironrdp-dvc = { git = "https://github.com/Devolutions/IronRDP", rev = "fd105e4b56647ab2f54aa23954aec4aaeef118e2" } +ironrdp-graphics = { git = "https://github.com/Devolutions/IronRDP", rev = "fd105e4b56647ab2f54aa23954aec4aaeef118e2" } +ironrdp-pdu = { git = "https://github.com/Devolutions/IronRDP", rev = "fd105e4b56647ab2f54aa23954aec4aaeef118e2" } +ironrdp-rdpdr = { git = "https://github.com/Devolutions/IronRDP", rev = "fd105e4b56647ab2f54aa23954aec4aaeef118e2" } +ironrdp-rdpsnd = { git = "https://github.com/Devolutions/IronRDP", rev = "fd105e4b56647ab2f54aa23954aec4aaeef118e2" } +ironrdp-session = { git = "https://github.com/Devolutions/IronRDP", rev = "fd105e4b56647ab2f54aa23954aec4aaeef118e2" } +ironrdp-svc = { git = "https://github.com/Devolutions/IronRDP", rev = "fd105e4b56647ab2f54aa23954aec4aaeef118e2" } +ironrdp-tls = { git = "https://github.com/Devolutions/IronRDP", rev = "fd105e4b56647ab2f54aa23954aec4aaeef118e2", features = ["rustls"]} +ironrdp-tokio = { git = "https://github.com/Devolutions/IronRDP", rev = "fd105e4b56647ab2f54aa23954aec4aaeef118e2" }