feat(rdpeai): add RdpeaiServer orchestration for AUDIO_INPUT - #1945
Conversation
ironrdp-rdpeai only had a client processor (PR Devolutions#1645); the PDU layer (pdu.rs) was already bidirectional, but nothing drove the server side of the MS-RDPEAI state machine. RdpeaiServer fills that gap, mirroring RdpeaiClient's structure and the RdpdrServer precedent (PR Devolutions#1783): sends Version on channel start and Formats once the client replies, automatically; exposes open()/change_format() for the consuming application to call once it wants to record; and delivers decoded audio to an injected RdpeaiServerBackend. Out-of-sequence, unrecognized, and mismatched PDUs are logged and ignored rather than treated as errors, per MS-RDPEAI 3.1.5's explicit MUST-ignore requirement. change_format() honors 3.3.5.3.1's SHOULD NOT for AAC formats when the client only advertised protocol version 1. 14 new tests in ironrdp-testsuite-core cover the full handshake, open failure/retry, format-change round trip and the AAC/V1 skip rule, out-of-sequence handling, and channel close. ironrdp-server integration (a factory trait plus attach_channels wiring, matching RdpeiServerFactory's shape) is a separate follow-up, same split RdpdrServer took.
There was a problem hiding this comment.
The PR adds RdpeaiServer, filling the server half of AUDIO_INPUT and mirroring RdpeaiClient and the RdpdrServer precedent; handshake sequencing, format-negotiation filtering, open/retry handling, and the AAC/version-1 guard are sound. Two real defects remain: process() propagates decode errors for malformed/unrecognized PDUs, contradicting MS-RDPEAI 3.1.5's MUST-ignore rule and the module's own doc, with the error aborting DRDYNVC SVC processing; and client FormatChange confirmations are applied without range or parity validation, allowing mislabeled or silently dropped audio. Remaining items are minor maintainability nits and one unverified spec interpretation.
process() propagated a decode failure as an Err through the shared DRDYNVC SVC processor instead of ignoring it, contradicting the module's own MS-RDPEAI 3.1.5 MUST-ignore documentation and risking the whole dynamic-channel loop on a single malformed AUDIO_INPUT PDU. It now warns and returns an empty message list, matching every other ignore case in the same function. handle_format_change also trusted the client's echoed format index even when it did not match what the server requested, warning but still applying it. A non-conformant confirm now keeps the server-requested index instead, since an out-of-range echo silently drops all subsequent Data PDUs and an in-range-but-wrong one mislabels the format. Also drops a channel_id field that was set but never read (integrators recover the id via DrdynvcServer::get_channel_id_by_type, as the stacked wiring PR already does), folds the start()/close() reset sequence into a shared helper, and trims three constant-valued parameters plus a stale doc comment from the negotiate_and_open test helper.
|
Potential duplicate detected: #1946. PR Maintainer review is required. |
a1bd456
into
Devolutions:master
ironrdp-rdpeai only had a client processor (#1645). The PDU layer already decodes and encodes every message in both directions, but nothing drove the server side of the state machine.
RdpeaiServer fills that gap. It mirrors RdpeaiClient's structure and the RdpdrServer precedent (#1783): it sends Version on channel start and Formats once the client replies, automatically, exposes open() and change_format() for the embedding application to call once it wants to record or switch formats, and delivers decoded audio to an injected RdpeaiServerBackend.
Out-of-sequence, unrecognized, and mismatched PDUs are logged and ignored rather than treated as errors, per MS-RDPEAI 3.1.5's explicit MUST-ignore requirement. change_format() honors 3.3.5.3.1's SHOULD NOT for AAC formats when the client only advertised protocol version 1.
14 tests in ironrdp-testsuite-core cover the full handshake, open failure and retry, the format-change round trip and the AAC/version-1 skip rule, out-of-sequence handling, and channel close.
ironrdp-server integration is a separate follow-up, the same split RdpdrServer's PR took.
One PR is stacked on this
#1946 wires this into ironrdp-server (RdpeaiServerFactory, attach_channels, ServerEvent::Rdpeai). It only makes sense once this PR lands.