Skip to content

Enhance RDP features and expose additional WASM options - #1764

Open
Tô Nguyễn Đức Mạnh (tonguyenducmanh) wants to merge 16 commits into
Devolutions:masterfrom
tonguyenducmanh:master
Open

Tô Nguyễn Đức Mạnh (tonguyenducmanh) wants to merge 16 commits into
Devolutions:masterfrom
tonguyenducmanh:master

Conversation

@tonguyenducmanh

No description provided.

@github-actions github-actions Bot added needs-review A human reviewer is the current next actor risk/unknown Risk could not be determined automatically; needs maintainer-level scrutiny scope/web Affects the web/WASM ecosystem size/S Size: up to 199 counted lines and 5 files; exceeds XS in either measure labels Aug 22, 2026
Comment thread crates/iron-remote-desktop/src/lib.rs Outdated
@github-actions github-actions Bot added breaking-change Includes a breaking change, and requires special scrutiny at the boundaries kind/protocol Affects RDP or related protocol behavior kind/technical-debt Internal cleanup work risk/medium Behavioral change that does not substantially alter a core public API scope/cross-cutting Spans multiple architectural boundaries and removed risk/unknown Risk could not be determined automatically; needs maintainer-level scrutiny labels Sep 10, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Automated review will not run because this contributor is not yet eligible under the automation policy.

Contributors become eligible after one qualifying IronRDP pull request is merged into master. Maintainer review is required.

@CBenoit Benoît Cortier (CBenoit) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you for the PR.

As per the design principle documented here, I think these should be provided as extensions instead of be part of the common abstraction.

@github-actions github-actions Bot removed scope/cross-cutting Spans multiple architectural boundaries breaking-change Includes a breaking change, and requires special scrutiny at the boundaries needs-review A human reviewer is the current next actor labels Sep 26, 2026
@github-actions github-actions Bot added the needs-review A human reviewer is the current next actor label Sep 26, 2026
@github-actions github-actions Bot added size/S Size: up to 199 counted lines and 5 files; exceeds XS in either measure needs-review A human reviewer is the current next actor and removed size/XS Size: up to 49 counted lines and 2 files needs-review A human reviewer is the current next actor labels Sep 26, 2026
@github-actions github-actions Bot removed the needs-review A human reviewer is the current next actor label Oct 8, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The PR adds four browser-facing session builder options (pointer_software_rendering, desktop_scale_factor, performance_flags, timezone_info) via the extension mechanism, as the maintainer requested, and wires them into connector::Config. The design and protocol framing are sound: DST-date-zeroed TimezoneInfo is a valid 'no DST' encoding and the bias sign convention comment matches MS-RDPBCGR. Independent verification confirmed three concrete defects: timezone name truncation counts Unicode scalars instead of UTF-16 code units, so astral characters overflow the fixed 64-byte PDU name fields and shift subsequent Client Info PDU fields (the encoder pads but never truncates); the invalid performance_flags fallback stores an empty flag set while logging and previously shipping a non-empty default; and desktop_scale_factor silently floors fractional values and forwards values the connector itself treats as out of range. Remaining candidates are low severity: an inaccurate doc-comment premis…

Comment thread crates/ironrdp-web/src/session.rs
Comment thread crates/ironrdp-web/src/session.rs
Comment thread crates/ironrdp-web/src/session.rs
Comment thread crates/ironrdp-web/src/session.rs Outdated
Comment thread crates/ironrdp-web/src/session.rs Outdated
Comment thread crates/ironrdp-web/src/session.rs
Comment thread crates/ironrdp-web/src/session.rs Outdated
Comment thread crates/ironrdp-web/src/session.rs
@github-actions github-actions Bot added ai-reviewed/1 One automated review completed needs-author-action The pull request author is the current next actor labels Oct 8, 2026
@github-actions github-actions Bot removed needs-author-action The pull request author is the current next actor triage/overlap Possible overlap with another pull request; advisory only labels Oct 11, 2026
The desktop_scale_factor, performance_flags and timezone_info extensions
accepted any JS number and truncated it on the way to the wire.

- desktop_scale_factor now honours the MS-RDPBCGR 2.2.1.13.1.2 window of
  100% to 500%, keeps 0 as the "server picks" default, and rejects a
  fractional devicePixelRatio instead of flooring 1.5 to the out-of-range
  value 1.
- performance_flags falls back to PerformanceFlags::default() rather than
  an empty set, so a type-invalid value keeps the behaviour the client
  advertised before the extension existed.
- Timezone names are truncated on UTF-16 code units, not char scalars.
  StandardName and DaylightName are fixed at 64 bytes and the encoder only
  pads them, so an astral-plane name overflowed the field and shifted the
  rest of the Client Info PDU.

build_config keeps its original signature and the four values are assigned
on the returned config, which drops the too_many_arguments suppression and
unbreaks the test helper that was still calling the old signature.

Also states the DST trade-off accurately and covers the new pure helpers
with tests.
@github-actions github-actions Bot added size/M Size: up to 449 counted lines and 10 files; exceeds S in either measure and removed size/S Size: up to 199 counted lines and 5 files; exceeds XS in either measure labels Oct 11, 2026
@tonguyenducmanh

Copy link
Copy Markdown
Author

Benoît Cortier (@CBenoit) hi, i'm changed the code follow your review.

@github-actions github-actions Bot added the automation-failed Exact-head automated classification or review failed or was unavailable label Oct 19, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The PR wires four existing connector Config options (pointer_software_rendering, desktop_scale_factor, performance_flags, timezone_info) through the WASM extension mechanism in ironrdp-web session.rs, matching the maintainer-requested extension design. Independent verification: all new SessionBuilderInner defaults equal the build_config defaults they override, so existing sessions keep identical behaviour; the connector already consumes all four fields; the new parsers match MS-RDPBCGR constraints (100-500 integer percentages with 0 as the server default, whole-number bitmask in 0..=u32::MAX, bias within plus/minus 1440 with zeroed transition dates and biases); and truncate_timezone_name is genuinely required because TimezoneInfo::encode only pads the 64-byte name field. The get_property/get_str refactor is a small same-file dedup used by the new code. Two valid low-severity issues remain: the performance_flags extension leaks the internal bitflag layout to JS with no exported constan…

Reduced coverage: optional reviewer code-compressor was unavailable.

Push a commit after addressing these findings. If no code change is needed, you may resolve inline threads and comment @github-actions review-ready to request human review.

Comment on lines +1437 to +1459
/// Reads the `performance_flags` extension value as a `PerformanceFlags` bitmask.
///
/// JS numbers are doubles, so a value that is not a whole number in
/// `0..=u32::MAX` (a ratio, a negative number, or something past `u32::MAX`)
/// cannot be a bitmask, and casting it would silently truncate it. Such a value
/// falls back to `PerformanceFlags::default()` rather than to an empty set, so
/// a type-invalid value keeps advertising the behaviour the client had before
/// this extension existed.
///
/// Bits outside the known set are dropped rather than rejected, matching how
/// the connector treats the flags it forwards.
fn parse_performance_flags(value: f64) -> PerformanceFlags {
let is_bitmask = value.is_finite() && value >= 0.0 && value.fract() == 0.0 && value <= f64::from(u32::MAX);

if !is_bitmask {
warn!(value, "Invalid performance flags; using default");
return PerformanceFlags::default();
}

#[expect(clippy::as_conversions, clippy::cast_possible_truncation, clippy::cast_sign_loss)]
let bits = value as u32;

PerformanceFlags::from_bits_truncate(bits)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[skeptical] performance_flags extension exposes a raw bitflag layout with silently dropped unknown bits — low 🟡 — The extension hands the internal PerformanceFlags bit layout to JS as a bare f64 with no named constants exported anywhere in the repository, so consumers must hardcode magic numbers. parse_performance_flags uses PerformanceFlags::from_bits_truncate without logging dropped bits; the warn path only fires for type-invalid values. A transposed or guessed bit (e.g. 0x0200 instead of 0x0100) is silently discarded, so a browser client can believe it disabled wallpaper and theming while silently advertising them - the bandwidth-sensitive scenario the doc comment motivates. A warn on dropped bits or named flag arguments would make the failure observable; as written the misconfiguration is undetectable from the JS side.

Comment on lines +301 to +308
|timezone_info: JsValue| {
match parse_timezone_info(timezone_info) {
Ok(info) => self.0.borrow_mut().timezone_info = info,
Err(error) => {
let reason = iron_remote_desktop::IronError::backtrace(&error);
warn!(%reason, "Invalid timezone_info; falling back to default");
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[skeptical] timezone_info error path logs 'falling back to default' but keeps the previously set value — low 🟡 — On parse failure the Err arm only warns; self.0.borrow_mut().timezone_info is not assigned, so if the timezone_info extension was called earlier with a valid payload the session keeps that stale value, contradicting the 'falling back to default' log line. The sibling parsers match their logs: parse_desktop_scale_factor returns 0 and parse_performance_flags returns PerformanceFlags::default(). The inconsistency is diagnostic-level (a misleading warn during failed setup) plus a behavioural divergence between the three new extensions that maintainers must reason about for every future fallback. Applying the same fall-back-to-default semantics, or rewording the log, resolves it.

@github-actions github-actions Bot added ai-reviewed/2 Two automated reviews completed and removed ai-reviewed/1 One automated review completed labels Oct 21, 2026

This branch was previously deployed

1 inactive deployment
llm-providers — dcad2c5f Deployed Oct 19, 2026 by tonguyenducmanh via Classify pull request #3255
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-reviewed/2 Two automated reviews completed automation-failed Exact-head automated classification or review failed or was unavailable kind/protocol Affects RDP or related protocol behavior risk/medium Behavioral change that does not substantially alter a core public API scope/web Affects the web/WASM ecosystem size/M Size: up to 449 counted lines and 10 files; exceeds S in either measure

Development

Successfully merging this pull request may close these issues.

3 participants