Skip to content

refactor(network): Remove legacy Send Delay - #3007

Open
githubawn wants to merge 3 commits into
TheSuperHackers:mainfrom
githubawn:refactor/remove-send-delay
Open

refactor(network): Remove legacy Send Delay#3007
githubawn wants to merge 3 commits into
TheSuperHackers:mainfrom
githubawn:refactor/remove-send-delay

Conversation

@githubawn

Copy link
Copy Markdown

What this code did:

The SendDelay setting (m_firewallSendDelay) enabled a specialized NAT traversal mode (FIREWALL_TYPE_NETGEAR_BUG) in FirewallHelper.cpp and NAT.cpp:

  1. During pre-game connection setup, it inserted artificial delays (m_timeTillNextSend = -1) on outbound UDP STUN/probe packets sent to peer players.
  2. In NAT::establishConnectionPaths(), it rearranged player connection slots into special pairs for nodes identified as having the Netgear NAT bug.
  3. In NAT::probed() and NAT::gotMangledPort(), it blocked local clients from sending reciprocal NAT probes until the remote peer probed them first.
  4. Exposed a "Send Delay" checkbox in the in-game Options Menu GUI and saved/loaded SendDelay = yes/no in Options.ini.

Background & Reason for Removal:

  • Historical Workaround: Added in 2003 specifically for early consumer routers (e.g., Netgear WGR614 v1/v2, WGT624) that violated UDP Binding Stability and Endpoint-Independent Mapping per RFC 4787 (their stateful NAT tables prematurely flushed active socket bindings if rapid UDP packets were sent to multiple STUN mangler destinations).
  • Hardware Extinction: Global IPv4 Shodan/Censys scans confirm these 20-year-old 802.11b/g routers are extinct.
  • Community Confusion: Over the last 20 years, players frequently confused "Send Delay" in the Options GUI with in-game input lag or network ping delays, leading to endless forum troubleshooting guides instructing users to manually set SendDelay = no in Options.ini. In reality, it had zero effect on in-game performance.
  • Code Cleanliness: Removing this eliminates non-standard probe delays in NAT.cpp, removes dead code across FirewallHelper, OptionPreferences, and GlobalData, and hides the obsolete setting from the Options GUI.

@githubawn githubawn changed the title refactor(network): Remove legacy Send Delay and Netgear NAT workaround refactor(network): Remove legacy Send Delay Jul 23, 2026
@greptile-apps

greptile-apps Bot commented Jul 23, 2026

Copy link
Copy Markdown

Greptile Summary

This PR removes the legacy SendDelay / FIREWALL_TYPE_NETGEAR_BUG NAT-traversal workaround that was originally written in 2003 for early Netgear routers whose NAT tables would flush under rapid UDP traffic. The workaround is extinct-hardware-specific and had been causing user confusion for years because the Options-menu checkbox was mistaken for a general lag setting.

  • Core removal (FirewallHelper, NAT, OptionPreferences, GlobalData): All detection, pairing, and probe-delay logic tied to FIREWALL_TYPE_NETGEAR_BUG and m_firewallSendDelay is deleted from both the Generals and Zero Hour code paths, with the #if defined(DEBUG_LOGGING) guard in NAT::doThisConnectionRound correctly extended to cover variables that are now log-only.
  • GUI cleanup (OptionsMenu.cpp × 2): Save/load references for the Send Delay checkbox are removed unconditionally, and the checkbox widget is hidden inside an #if ENABLE_GUI_HACKS block — leaving the widget visible and interactable (but silently non-functional) in builds where that macro is not defined.

Confidence Score: 4/5

Safe to merge for builds where ENABLE_GUI_HACKS is always defined; needs attention if non-ENABLE_GUI_HACKS builds ship to players.

The network logic removal is thorough and the NAT connection flow remains correct for all non-Netgear cases. The only real concern is that the Options-menu Send Delay checkbox hiding is conditional on ENABLE_GUI_HACKS, while all its save/load wiring was removed unconditionally — so in any build where the macro is absent the widget is live but does nothing, which could confuse players and would contradict one of the PR stated goals.

Files Needing Attention: Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp and its GeneralsMD counterpart — the conditional vs. unconditional removal asymmetry for the Send Delay checkbox.

Important Files Changed

Filename Overview
Core/GameEngine/Include/GameNetwork/FirewallHelper.h Removes the FIREWALL_TYPE_NETGEAR_BUG enum value and both isNetgear() overloads; straightforward dead-code removal.
Core/GameEngine/Source/GameNetwork/FirewallHelper.cpp Removes all m_firewallSendDelay / FIREWALL_TYPE_NETGEAR_BUG references and dead #if (0) block; clean removal with no behavioral gaps.
Core/GameEngine/Source/GameNetwork/NAT.cpp Removes Netgear pairing loop and probe-delay logic; the connectionAssigned[i] == TRUE guard at the top of the remaining assignment loop is now dead code (always false), but harmless.
Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp GUI hiding of Send Delay checkbox is guarded by #if ENABLE_GUI_HACKS, but all save/load logic was removed unconditionally — leaving the checkbox visible and enabled but non-functional in builds without that macro.
GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp Same ENABLE_GUI_HACKS asymmetry as the Generals variant — checkbox remains visible and enabled but non-functional in builds without the macro.

Sequence Diagram

sequenceDiagram
    participant UI as Options Menu
    participant GP as GlobalData
    participant FH as FirewallHelper
    participant NAT as NAT

    note over UI,NAT: Before (with SendDelay / Netgear path)
    UI->>GP: "m_firewallSendDelay = getSendDelay()"
    GP->>FH: detectionBeginUpdate sets FIREWALL_TYPE_NETGEAR_BUG
    FH->>NAT: establishConnectionPaths (Netgear pairing loop)
    NAT->>NAT: "doThisConnectionRound sets m_timeTillNextSend = -1"
    NAT->>NAT: gotMangledPort waits for m_beenProbed before probing

    note over UI,NAT: After (this PR)
    UI-->>GP: (no SendDelay read)
    GP->>FH: detectionBeginUpdate (no Netgear branch)
    FH->>NAT: establishConnectionPaths (simple slot to node assignment)
    NAT->>NAT: doThisConnectionRound probes immediately
    NAT->>NAT: gotMangledPort always calls sendAProbe()
Loading
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp:955-960
**Checkbox hidden only under `ENABLE_GUI_HACKS`, but save/load removed unconditionally**

The "Send Delay" checkbox is hidden inside `#if ENABLE_GUI_HACKS`, but every save (`saveOptions`) and load (`OptionsMenuInit``GadgetCheckBoxSetChecked`) reference was removed unconditionally. In any build where `ENABLE_GUI_HACKS` is not defined, the checkbox remains visible and enabled in the Options GUI — users can toggle it freely — but the state is never persisted and has no effect. The same asymmetry is present in `GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp`.

Reviews (3): Last reviewed commit: "refactor(network): Put Send Delay check ..." | Re-trigger Greptile

@bobtista

Copy link
Copy Markdown

Left one question, otherwise this looks good

@githubawn githubawn added GUI For graphical user interface Minor Severity: Minor < Major < Critical < Blocker Network Anything related to network, servers Gen Relates to Generals ZH Relates to Zero Hour labels Jul 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Gen Relates to Generals GUI For graphical user interface Minor Severity: Minor < Major < Critical < Blocker Network Anything related to network, servers ZH Relates to Zero Hour

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants