Repository navigation
fix(client): answer auto-detect requests on the UDP tunnel #2009
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
Open
AKolenda
wants to merge
12
commits into
Devolutions:master
Choose a base branch
from
AKolenda:fix/rdpeudp-tunnel-autodetect
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+1,130
−79
Open
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
9da61ef
feat(session): answer bandwidth measurements during the session
8d73039
refactor(session): answer auto-detect requests through one responder
9523d05
refactor(session): tidy the bandwidth responder
9ce7fda
fix(client): answer auto-detect requests on the UDP tunnel
5e7c60e
test(client): run the tunnel auto-detect tests in CI
6e47326
fix(client): handle tunnel auto-detect failures and byte accounting
6d92e89
fix(session): count complete bandwidth frames and reject untimed esti…
acd23df
test(client): verify tunnel fallback and complete frame accounting
a073ac1
feat(rdpeudp-tokio): stamp tunnel reads and decode auto-detect sub-he…
3d70762
fix(session): share one bandwidth measurement across the tunnel and TCP
d5ae7c7
fix(session): report the open bandwidth window on a Stop of the other…
4630f9b
fix(session): keep a bandwidth window across a mismatched Stop
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,3 +16,6 @@ pub mod rdp; | |
| mod clipboard; | ||
|
|
||
| mod ws; | ||
|
|
||
| #[cfg(feature = "udp")] | ||
| mod udp; | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| //! Internal client handling for a reliable UDP tunnel. | ||
|
|
||
| use ironrdp_rdpeudp_tokio::UdpTransport; | ||
| use ironrdp_session::{ActiveStage, SessionError, SessionResult}; | ||
| use tracing::warn; | ||
|
|
||
| /// Drops a failed sideband and withdraws it from future Soft-Sync negotiation. | ||
| /// A channel already moved to the tunnel cannot resume over TCP without reconnecting. | ||
| /// Both receive closure and auto-detect send failures use this policy. | ||
| pub(crate) fn disable_failed_tunnel( | ||
| stage: &mut ActiveStage, | ||
| transport: &mut Option<UdpTransport>, | ||
| error: SessionError, | ||
| ) -> SessionResult<()> { | ||
| if stage.reliable_udp_dvc_tunnel_in_use() { | ||
| return Err(error); | ||
| } | ||
| *transport = None; | ||
| stage.disable_reliable_udp_dvc_tunnel()?; | ||
| warn!(%error, "Reliable UDP tunnel failed before channel migration; continuing with TCP"); | ||
| Ok(()) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| //! Auto-detect messages carried in tunnel sub-headers. | ||
| //! | ||
| //! On a sideband channel in use, the server sends its auto-detect requests in the sub-headers of | ||
| //! Tunnel Data PDUs, and the client answers there ([MS-RDPBCGR] 3.2.5.14). Each sub-header is the | ||
| //! auto-detect structure itself: SubHeaderLength and SubHeaderType are its headerLength and | ||
| //! headerTypeId ([MS-RDPEMT] 2.2.1.1.1). | ||
| //! | ||
| //! [MS-RDPBCGR]: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/16ffa852-8aa7-481c-99a0-36c1a9a198f6 | ||
| //! [MS-RDPEMT]: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpemt/4f538fd7-3aca-4e7d-a213-13eb5f95c1ad | ||
|
|
||
| use ironrdp_core::{Decode, Encode}; | ||
| use ironrdp_pdu::rdp::autodetect::{AutoDetectRequest, AutoDetectResponse}; | ||
| use ironrdp_rdpemt::{SubHeaderType, TunnelSubHeader}; | ||
| use tracing::debug; | ||
|
|
||
| use crate::transport::TunnelMessage; | ||
|
|
||
| impl TunnelMessage { | ||
| /// Decodes the auto-detect requests among this message's sub-headers. | ||
| /// | ||
| /// Sub-headers of other types and requests that do not decode are skipped. RTT requests | ||
| /// are returned along with the bandwidth requests MS-RDPEMT lists, because Windows sends | ||
| /// them on the tunnel too, although MS-RDPEMT does not specify that encapsulation. | ||
| pub fn auto_detect_requests(&self) -> Vec<AutoDetectRequest> { | ||
| self.sub_headers | ||
| .iter() | ||
| .filter(|sub_header| sub_header.sub_header_type == SubHeaderType::AutoDetectRequest) | ||
| .filter_map(|sub_header| match redecode(sub_header) { | ||
| Ok(request) => Some(request), | ||
| Err(error) => { | ||
| debug!(%error, data = ?sub_header.data, "Ignoring an undecodable auto-detect request on the tunnel"); | ||
| None | ||
| } | ||
| }) | ||
| .collect() | ||
| } | ||
|
|
||
| /// Builds a message with no higher-layer data that carries `responses` as sub-headers. | ||
| /// | ||
| /// A response that cannot be encoded is skipped. Returns `None` when nothing is left to | ||
| /// send. | ||
| pub fn from_auto_detect_responses(responses: &[AutoDetectResponse]) -> Option<Self> { | ||
| let sub_headers: Vec<TunnelSubHeader> = responses | ||
| .iter() | ||
| .filter_map(|response| match redecode(response) { | ||
| Ok(sub_header) => Some(sub_header), | ||
| Err(error) => { | ||
| debug!(%error, ?response, "Could not encode an auto-detect response for the tunnel"); | ||
| None | ||
| } | ||
| }) | ||
| .collect(); | ||
| (!sub_headers.is_empty()).then_some(Self { | ||
| sub_headers, | ||
| data: Vec::new(), | ||
| }) | ||
| } | ||
| } | ||
|
|
||
| /// Re-reads one wire structure as another with the same bytes. | ||
| fn redecode<T: for<'de> Decode<'de>>(value: &dyn Encode) -> Result<T, String> { | ||
| let bytes = ironrdp_core::encode_vec(value).map_err(|error| error.to_string())?; | ||
| ironrdp_core::decode(&bytes).map_err(|error| error.to_string()) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.