feat(network): Self-healing NAT state - #3010
Conversation
|
| Filename | Overview |
|---|---|
| Core/GameEngine/Source/GameNetwork/FirewallHelper.cpp | Moves firewall classification into resettable in-memory state with asynchronous detection and retry throttling. |
| Core/GameEngine/Source/GameNetwork/GameSpy/PeerDefs.cpp | Establishes GameSpy-session ownership for the firewall helper. |
| Core/GameEngine/Source/GameNetwork/NAT.cpp | Reuses live firewall state during traversal and restarts detection after negotiation failure. |
| Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLGameSetupMenu.cpp | Republishes completed NAT classifications through host-mediated staging-room slot broadcasts. |
| GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLGameSetupMenu.cpp | Mirrors the staging-room NAT republication flow for Zero Hour. |
| Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQuickMatchMenu.cpp | Prevents Quick Match submission until NAT detection completes successfully. |
| GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQuickMatchMenu.cpp | Mirrors the successful-classification guard for Zero Hour Quick Match. |
Sequence Diagram
sequenceDiagram
participant Menu as Multiplayer Menu
participant Helper as FirewallHelper
participant Mangler as STUN/Mangler Service
participant Host as Staging Host
participant Peers as Room Peers
Menu->>Helper: behaviorDetectionUpdate()
Helper->>Mangler: asynchronous NAT probes
Mangler-->>Helper: mapped-port responses
Helper->>Helper: classify NAT behavior
alt Local player is host
Menu->>Host: update local slot
Host->>Peers: broadcast SL/ slot list
else Local player is client
Menu->>Host: "send REQ/ NAT=value"
Host->>Peers: broadcast corrected SL/ slot list
end
Reviews (29): Last reviewed commit: "another grepfile round" | Re-trigger Greptile
79e5c8e to
8113c09
Compare
xezon
left a comment
There was a problem hiding this comment.
How can this change be tested? Did you test it? Does it work?
Tested this with a Gamespy emulator and it does follow the intended changes. |
e2d7f2a to
0ec4675
Compare
|
The bot sure had a lot to say here |
xezon
left a comment
There was a problem hiding this comment.
This change is a bit complicated. Needs more Networking eyes 👀
| m_packetID++; | ||
| m_timeoutStart = timeGetTime(); | ||
| m_timeoutLength = 4000; | ||
| m_timeoutLength = 3000; |
| static const Int MAX_NUM_MANGLERS = 4; | ||
| static const UnsignedShort MANGLER_PORT = 4321; | ||
|
|
||
| static const UnsignedInt BEHAVIOR_DETECTION_WAIT_TIME = 6000; |
|
|
||
| static const UnsignedInt BEHAVIOR_DETECTION_WAIT_TIME = 6000; | ||
|
|
||
| class FirewallHelperClass { |
There was a problem hiding this comment.
I suggest add a comment above this class explaining the new things it does now.
| TheFirewallHelper->behaviorDetectionUpdate(); | ||
| republishNATBehaviorIfChanged(); | ||
|
|
||
| if (TheFirewallHelper->isBehaviorDetectionComplete() && TheFirewallHelper->getFirewallBehavior() == FirewallHelperClass::FIREWALL_TYPE_UNKNOWN) |
There was a problem hiding this comment.
So if detection is complete it will detect firewall behavior again?
| else if (key == "NAT") | ||
| { | ||
| if ((val >= FirewallHelperClass::FIREWALL_TYPE_SIMPLE) && | ||
| if ((val >= FirewallHelperClass::FIREWALL_TYPE_UNKNOWN) && |
| slReq.UTM.isStagingRoom = TRUE; | ||
| slReq.id = "SL/"; | ||
| slReq.options = GameInfoToAsciiString(game).str(); | ||
| TheGameSpyPeerMessageQueue->addRequest(slReq); |
There was a problem hiding this comment.
This block exists twice in this file. Consolidate?
| m_timeoutLength = 0; | ||
| m_timeoutStart = 0; | ||
|
|
||
|
|
| req.nick = aName.str(); | ||
| options.format("NAT=%d", behavior); | ||
| req.options = options.str(); | ||
| TheGameSpyPeerMessageQueue->addRequest(req); |
There was a problem hiding this comment.
Can you explain why these publishing events and requests are needed after firewall behavior detection?
What this code did:
The
ButtonFirewallRefreshbutton inOptionsMenu.cppandFirewallNeedToRefreshinFirewallHelper.cpp/OptionPreferences.cpp:FirewallNeedToRefreshandLastFirewallIPboolean flags to/fromOptions.ini.GlobalData(TheWritableGlobalData->m_firewallBehavior) with disk-persisted firewall state across process restarts.How the new system works:
republishNATBehaviorIfChanged()to dynamically monitor the background thread. The instant the probe successfully classifies the network, it broadcasts the true NAT behavior over the network via UTM/SL/packets, updating peer clients seamlessly.UNKNOWNstate.detectFirewallBehavior()retry in the background to ensure the session isn't permanently bricked.Background & Reason for Removal:
FirewallNeedToRefreshandLastFirewallIPfromOptions.ini, preventing stale or corrupted flags from persisting across game crashes or process restarts.FirewallHelperClassin memory, removing direct mutations toTheWritableGlobalData->m_firewallBehavior.