Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: hook up resize for ironrdp-client crate #430

Merged
merged 93 commits into from
Apr 29, 2024

Conversation

ibeckermayer
Copy link
Collaborator

This commit adds the ability to resize the RDP session window on the fly using the DisplayControl channel.

It includes some known issues:

  1. After a resize, session performance degrades.
  2. Too large a resize can cause an InvalidChannelWidth or InvalidChannelHeight error.

See: https://www.loom.com/share/7cbfc5b0e02d4aff998939f54816d14b?sid=8e69fec2-aaa7-4a0a-ae67-d277a5000972

Isaiah Becker-Mayer added 30 commits March 19, 2024 20:51
…receiving a ServerDeactivateAll on the I/O channel
sequences into a separate connection_activation module. This allows us
to reuse them when we receive a Server Deactivate All.
`single_connect_step_read` and `single_connect_step_write`.

Also adds a `ConnectionActivationSequence::reset_clone` method to aid
in reusing the sequence for Deactivate All PDU handling.

Passes `ConnectionActivationSequence` to `x224::Processor` to hand back
upon receiving a Deactivate All PDU.
…:Windows::RDS::DisplayControl DVC to work.
…to us from the server via the BlockType in the BlockHeader, so it needn't be rigidly tracked explicitly in DecodingContext. This makes the RFX pipeline more flexible, which in turn allows us to seamlessly use it when we get another sync sequence mid-stream due to having fielded a Server Deactivate PDU.
client codebase. This uses `encode_dvc_data` to encode the DVC data
responses.

Currently no dynamic channels are added so the code is untested (WIP).
in the form of `DisplayControlClient`
I attempted to transfer everything in ironrdp_pdu::dvc::display
into it, but it required more refactoring that I'd expected to get it to
play nicely with the no_std possibility.

This also removes the requirement of keeping track of the channel_id
in each `DynamicVirtualChannel`, and instead lets the `DynamicChannelSet`
take care of returning that as needed.
`DvcPduEncode` trait simply inherits `PduEncode`. It is a marker trait
to indicate that the implementor, when encoded, is ready to be wrapped
in DataFirst and/or Data PDU(s).

`MonitorLayoutPdu` is a copy of the pdu by the same name in the
`ironrdp-pdu` crate. It is moved (well, copied for now) to the `ironrdp-dvc`
crate and implements `DvcPduEncode`.
added previously. Also creates a `DrdynvcPdu` enum that implements
`SvcPduEncode`, and begins migrating `DataFirstPdu` and `DataPdu` to
the new `PduEncode` paradigm.

In the process, also:
- Moved `DynamicVirtualChannel` and `DynamicChannelSet` from `client.rs`
to `lib.rs` since they can ultimately be used by both client and server.
… This has been tested to work for screen resize. The refactored server side code has not been tested.
…bles testing in ironrdp-dvc by eliminating the test = false line in Cargo.toml
- Abstracts the CapabilitiesExchange and ConnectionFinalization
sequences into a separate connection_activation module. This allows us
to reuse them when we receive a Server Deactivate All.
- Creates IoChannelPdu enum to be used to account for the potential of
receiving a ServerDeactivateAll on the I/O channel
`single_connect_step_read` and `single_connect_step_write`.

Also adds a `ConnectionActivationSequence::reset_clone` method to aid
in reusing the sequence for Deactivate All PDU handling.

Passes `ConnectionActivationSequence` to `x224::Processor` to hand back
upon receiving a Deactivate All PDU.
…:Windows::RDS::DisplayControl DVC to work.
…to us from the server via the BlockType in the BlockHeader, so it needn't be rigidly tracked explicitly in DecodingContext. This makes the RFX pipeline more flexible, which in turn allows us to seamlessly use it when we get another sync sequence mid-stream due to having fielded a Server Deactivate PDU.
ibeckermayer pushed a commit to gravitational/teleport that referenced this pull request Apr 25, 2024
Comment on lines +67 to +70
// TODO: it should be possible to get the physical size here, however winit doesn't make it straightforward.
// FreeRDP does it based on DPI reading grabbed via [`SDL_GetDisplayDPI`](https://wiki.libsdl.org/SDL2/SDL_GetDisplayDPI):
// https://github.com/FreeRDP/FreeRDP/blob/ba8cf8cf2158018fb7abbedb51ab245f369be813/client/SDL/sdl_monitor.cpp#L250-L262
let (physical_width, physical_height) = (0, 0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: Can’t you use this? https://docs.rs/winit/latest/winit/window/struct.Window.html#method.inner_size
Is it really fine to feed in 0s?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inner_size gives you a PhysicalSize, but that only gives you a "size represented in physical pixels." However without knowing the DPI (or other relation to a unit of length), we can't calculate the "physical size" that RDP wants, which is the width/height in millimeters.

If we hand back 0s here, they're simply ignored per the spec:

image

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ibeckermayer
I think passing in client (0, 0) is not optimal (it is not obvious that they will be ignored), maybe it would be great to change RdpInputEvent::Resize fields to have physical_dimensions: Option<(u32, u32)> instead of separate u32 fields? This will keep this implementation detail as close to PDU encode/decode code as possible

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be fixed in follow-up PR, merging PR to unblock @ibeckermayer

crates/ironrdp-connector/src/connection_activation.rs Outdated Show resolved Hide resolved
@CBenoit CBenoit changed the title Hooks up resize for ironrdp-client crate. feat: hook up resize for ironrdp-client crate Apr 26, 2024
@ibeckermayer ibeckermayer requested a review from CBenoit April 26, 2024 21:30
Copy link
Contributor

@pacmancoder pacmancoder left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me!

@pacmancoder pacmancoder merged commit fd105e4 into master Apr 29, 2024
7 checks passed
@pacmancoder pacmancoder deleted the isaiah/hook-up-resize-ironrdp-client branch April 29, 2024 19:20
github-merge-queue bot pushed a commit to gravitational/teleport that referenced this pull request Apr 29, 2024
* Resize

* ???

* ???

* Fixes to compile

* Updates to latest IronRDP with dvc fix, cleans up some of the debug code

* Hooks up resize listener on the client and sends changes as ClientScreenSpecs to the backend. Currently just gets logged in the WDS

* Handles the new DeactivateAll ProcessorOutput

* hooks up client_write_screen_resize

* 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.

* Switch monitor orientation based on width/height

* remove superfluous canvas size sync

* 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

* Updates to the most recent hash for IronRDP feat/dynamic-resize

* 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).

* Refactoring after update to the tip of Devolutions/IronRDP#424

* Adds windowOnResize to story

* adds Determine Toolchain Versions and cache paths and Print versions steps to os-compatibility-test.yaml

* fixes debug log formatting

* Updates to local IronRDP and later IronRDP api

* updates to IronRDP latest rev on Devolutions/IronRDP#430

* reverting mistaken changes

* throttle -> debounce and naming changes

* js renamings

* updates to IronRDP master

---------

Co-authored-by: Przemko Robakowski <[email protected]>
ibeckermayer pushed a commit to gravitational/teleport that referenced this pull request Apr 29, 2024
* Resize

* ???

* ???

* Fixes to compile

* Updates to latest IronRDP with dvc fix, cleans up some of the debug code

* Hooks up resize listener on the client and sends changes as ClientScreenSpecs to the backend. Currently just gets logged in the WDS

* Handles the new DeactivateAll ProcessorOutput

* hooks up client_write_screen_resize

* 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.

* Switch monitor orientation based on width/height

* remove superfluous canvas size sync

* 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

* Updates to the most recent hash for IronRDP feat/dynamic-resize

* 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).

* Refactoring after update to the tip of Devolutions/IronRDP#424

* Adds windowOnResize to story

* adds Determine Toolchain Versions and cache paths and Print versions steps to os-compatibility-test.yaml

* fixes debug log formatting

* Updates to local IronRDP and later IronRDP api

* updates to IronRDP latest rev on Devolutions/IronRDP#430

* reverting mistaken changes

* throttle -> debounce and naming changes

* js renamings

* updates to IronRDP master

---------

Co-authored-by: Przemko Robakowski <[email protected]>
github-merge-queue bot pushed a commit to gravitational/teleport that referenced this pull request Apr 30, 2024
* Resize

* ???

* ???

* Fixes to compile

* Updates to latest IronRDP with dvc fix, cleans up some of the debug code

* Hooks up resize listener on the client and sends changes as ClientScreenSpecs to the backend. Currently just gets logged in the WDS

* Handles the new DeactivateAll ProcessorOutput

* hooks up client_write_screen_resize

* 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.

* Switch monitor orientation based on width/height

* remove superfluous canvas size sync

* 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

* Updates to the most recent hash for IronRDP feat/dynamic-resize

* 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).

* Refactoring after update to the tip of Devolutions/IronRDP#424

* Adds windowOnResize to story

* adds Determine Toolchain Versions and cache paths and Print versions steps to os-compatibility-test.yaml

* fixes debug log formatting

* Updates to local IronRDP and later IronRDP api

* updates to IronRDP latest rev on Devolutions/IronRDP#430

* reverting mistaken changes

* throttle -> debounce and naming changes

* js renamings

* updates to IronRDP master

---------

Co-authored-by: Przemko Robakowski <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants