fix(connector): stay in CapabilitiesExchange when activation handles DeactivateAll#1371
Conversation
…DeactivateAll PR Devolutions#1254 taught the inner ConnectionActivationSequence to skip a Server Deactivate All PDU received before Server Demand Active (sent by e.g. Windows Server and gnome-remote-desktop during a Deactivation-Reactivation Sequence, MS-RDPBCGR 1.3.1.3): it returns Written::Nothing and stays in CapabilitiesExchange. However, the outer ClientConnector::step() only accepted ConnectionFinalization as the resulting inner state, so the same scenario still failed with "invalid state (this is a bug)" during the initial connection sequence. Mirror the inner behavior in the outer state machine and keep waiting for the Demand Active PDU. Fixes Devolutions#1362 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Rocco De Angelis (@rdeangel) thank you for looking into this! I've tried compiling again from your branch and it does get past the |
|
Thanks for testing again, good to see it's getting past ServerDeactivateAll now. From the error location, the connection is getting quite far: it's past NLA and licensing, into capabilities exchange. It handles the ServerDeactivateAll and waits for a ServerDemandActive, but the server sends a disconnectProviderUltimatum and drops instead. So I don't think this PR is causing the disconnect, it just lets the connection get far enough to reach it, where before it stopped at the "invalid state" error, but I'd rather not guess at why the server is dropping without more to go on. A couple of things that would really help narrow it down:
One small note: the UserRequested name is a little misleading, it's just the generic MCS code for a deliberate close, not necessarily anything a user did. Separately, this did make me wonder if it'd be worth surfacing DisconnectProviderUltimatum as a typed error instead of a string, so it's easier to handle distinctly but that's independent of this PR. |
|
That makes sense, to help narrow it down:
|
Fixes #1362
Problem
#1254 taught the inner
ConnectionActivationSequenceto skip a Server Deactivate All PDU received before Server Demand Active (sent by e.g. Windows Server and gnome-remote-desktop as part of a Deactivation-Reactivation Sequence, MS-RDPBCGR 1.3.1.3): it returnsWritten::Nothingand remains inCapabilitiesExchange.However, the outer
ClientConnector::step()only acceptsConnectionFinalizationas the resulting inner state after callingconnection_activation.step(), so the same scenario still fails withinvalid state (this is a bug)when it happens during the initial connection sequence — exactly the symptom reported in #1362.Changes
ClientConnector::step(): when the inner sequence stays inCapabilitiesExchange, the outer connector stays inCapabilitiesExchangetoo and waits for the next input.ClientConnectorinstead of the inner sequence (fails withinvalid statebefore the fix).🤖 Generated with Claude Code