Skip to content

fix(network): Synchronize disconnect removal and quit handling - #662

Open
tintinhamans wants to merge 12 commits into
GeneralsOnlineDevelopmentTeam:mainfrom
tintinhamans:arctic/go/stack2/07-disconnect-quit
Open

tintinhamans wants to merge 12 commits into
GeneralsOnlineDevelopmentTeam:mainfrom
tintinhamans:arctic/go/stack2/07-disconnect-quit

Conversation

@tintinhamans

@tintinhamans tintinhamans commented Oct 25, 2026 •

Copy link
Copy Markdown

Merge after #661.

A leaving player could be removed on different frames on different machines, a graceful quit waited out the whole timeout like a dead connection, a leave notice about any slot was trusted from any peer, and the log lines of a dead connection were not limited.

The first three commits are cherry-picks of TheSuperHackers#3612 (merged) and TheSuperHackers#3631 (open). A player that quits from the disconnect screen sends its leave at once. Everyone that got the leave tells the others with a notice, a DISCONNECTPLAYER with frame 0xFFFFFFFF, so all pick the same next router. The acting packet router removes the player on one frame for everyone, and DISCONNECTPLAYER is applied only from the acting router. A notice without the leaver's own leave counts after 3 s of quiet.

The last commit keeps the GO handling on top of that:

  • A notice that carries the leaver's match key signature counts at once, the 3 s quiet time is only the fallback for an unsigned one.
  • A player silent for 2 s on the disconnect screen does not count as a voter, and one vote alone never removes a player from a game with more than two.
  • The countdowns run from the start of the stall instead of from when the screen came up, and a stall right after the screen went off brings it back without a new wait. The screen shows after at most 1 s.
  • Frames of the removed player that others still miss can be asked for again.
  • A peer that closes its connection on purpose during a match is treated as left and removed without waiting for the timeout. That is read from the GNS end debug string, which is fragile if its wording changes.
  • Slots outside 0 <= slot < MAX_SLOTS are rejected.

Two keys are new: disconnect.freeze_before_screen_ms (5000) is how long a player is stuck before the disconnect screen comes up, disconnect.remove_after_ms (60000) how long a silent player stays on it. [DISC] Recv Failed and "connection is invalid" are limited to once per 5 s per connection, send failures to once per second, and a packet is dropped after 3 failed retries.

A leaver without a match key yet sends an unsigned notice, so the others wait the quiet time. The signature does not cover the frame, so a captured notice can be replayed in the same match. No new message type, the signature field comes from the identity PR.

Tested: builds x86 Release z_generals. GO rig with the full stack, 3 runs of 7 cases: a menu quit by a player or the host is removed in 0 to 3 s, also behind a link with 100% loss, a killed player or host after the 60 s countdown since the rig does not vote. All survivors removed on the same logic frame in 20 of 21 runs, 0 CRC mismatches. A lagging player plus a crash still fails 2 of 3 runs, the removal takes 120 s there. Not covered: a leave lost to one player, a quit from the disconnect screen itself.

@tintinhamans
tintinhamans force-pushed the arctic/go/stack2/07-disconnect-quit branch 4 times, most recently from bba753e to 05afd00 Compare October 26, 2026 15:39
@tintinhamans
tintinhamans force-pushed the arctic/go/stack2/07-disconnect-quit branch from 05afd00 to fbb383a Compare October 28, 2026 01:47
@tintinhamans
tintinhamans force-pushed the arctic/go/stack2/07-disconnect-quit branch from fbb383a to d879bb7 Compare November 4, 2026 21:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant