Skip to content

refactor(network): Remove legacy Send Delay#3007

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

refactor(network): Remove legacy Send Delay#3007
githubawn wants to merge 2 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 workaround that was introduced in 2003 for consumer routers that violated UDP binding stability rules. The dead code is cleanly excised across 14 files spanning the network, preferences, global-data, and GUI layers for both the base game and Zero Hour.

  • NAT traversal simplified: establishConnectionPaths() no longer shuffles nodes into Netgear-first pairs; gotMangledPort() now unconditionally sends the probe instead of gating on whether the remote was a Netgear node; probed() still correctly sets m_beenProbed (used by connectionUpdate() to stop re-sending the mangled port number).
  • GUI cleanup: The CheckSendDelay checkbox is hidden at init via a local variable with a null guard (also fixes a pre-existing potential null dereference on winEnable(FALSE)); the save/load path is removed so the setting is silently ignored in any existing Options.ini.
  • Header hygiene: FIREWALL_TYPE_NETGEAR_BUG = 8, isNetgear(), getSendDelay(), and m_firewallSendDelay are all removed from their respective headers, and the previously-commented-out NATCONNECTIONSTATE_NETGEARDELAY enum value is finally deleted.

Confidence Score: 5/5

Safe to merge — the removal is surgical and complete, with no orphaned references to deleted symbols

All call sites for the removed field, enum value, and methods are accounted for in the diff, and a repository-wide grep confirms no remaining references outside the changed files. The simplified NAT probe flow is logically correct: m_beenProbed is still set in probed() and is still read in connectionUpdate() to stop re-sending the mangled port, so removing the Netgear-gated branch does not disturb the non-Netgear connection handshake. The GUI change replaces a global static widget pointer with a local lookup plus a null guard, which also fixes a latent null-dereference in the old winEnable call.

No files require special attention

Important Files Changed

Filename Overview
Core/GameEngine/Source/GameNetwork/NAT.cpp Removes Netgear-specific connection-pairing, probe-delay, and gotMangledPort gating logic; expands #if DEBUG_LOGGING guard correctly around variables now only used for logging
Core/GameEngine/Source/GameNetwork/FirewallHelper.cpp Removes all FIREWALL_TYPE_NETGEAR_BUG detection branches, hardness/retry adjustments, and dead #if(0) block; remaining code paths are unaffected
Core/GameEngine/Include/GameNetwork/FirewallHelper.h Removes FIREWALL_TYPE_NETGEAR_BUG = 8 enum value and both isNetgear() method overloads; no downstream bitmask arithmetic is broken since all call sites are also removed
Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp Removes static checkSendDelay global, hides the widget via a local lookup with a null guard, and drops all save/load/enable logic; also fixes a pre-existing potential null dereference on winEnable(FALSE)
GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp Mirrors the Generals OptionsMenu.cpp changes; same pattern of hiding the widget via a local variable with null guard
Generals/Code/GameEngine/Include/Common/GlobalData.h Removes m_firewallSendDelay Bool field; paired correctly with removal of initialization and ini-loading in GlobalData.cpp
GeneralsMD/Code/GameEngine/Include/Common/GlobalData.h Mirrors Generals GlobalData.h; removes m_firewallSendDelay field
Core/GameEngine/Source/Common/OptionPreferences.cpp Removes getSendDelay() implementation; existing Options.ini files with SendDelay key will have the entry silently ignored, which is correct backward-compatible behavior
Core/GameEngine/Include/Common/OptionPreferences.h Removes getSendDelay() declaration; straightforward header cleanup
Core/GameEngine/Include/GameNetwork/NAT.h Removes already-commented-out NATCONNECTIONSTATE_NETGEARDELAY enum value

Sequence Diagram

sequenceDiagram
    participant A as Client A (local)
    participant M as Mangler Server
    participant B as Client B (remote)

    Note over A,B: After this PR - unified path for all NAT types

    A->>M: sendMangledSourcePort()
    M-->>A: mangledPort response
    A->>A: processManglerResponse(mangledPort)
    A->>B: gotMangledPort - sendAProbe() + notifyTargetOfProbe()
    A->>A: "state = WAITINGFORRESPONSE"

    B->>M: sendMangledSourcePort()
    M-->>B: mangledPort response
    B->>B: processManglerResponse(mangledPort)
    B->>A: gotMangledPort - sendAProbe() + notifyTargetOfProbe()
    B->>B: "state = WAITINGFORRESPONSE"

    A-->>B: "PROBE received - probed() - m_beenProbed = TRUE"
    B-->>A: "PROBE received - probed() - m_beenProbed = TRUE"

    A->>A: "state = DONE"
    B->>B: "state = DONE"
Loading

Reviews (2): Last reviewed commit: "refactor(network): Use NAMEKEY macro for..." | Re-trigger Greptile

@bobtista

Copy link
Copy Markdown

Left one question, otherwise this looks good

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.

2 participants