diff --git a/Core/GameEngine/Include/Common/OptionPreferences.h b/Core/GameEngine/Include/Common/OptionPreferences.h index 1f45873191a..037b0375f43 100644 --- a/Core/GameEngine/Include/Common/OptionPreferences.h +++ b/Core/GameEngine/Include/Common/OptionPreferences.h @@ -85,10 +85,7 @@ class OptionPreferences : public UserPreferences Bool getScreenEdgeScrollEnabledInFullscreenApp() const; ScreenEdgeScrollMode getScreenEdgeScrollMode() const; Bool getSendDelay(); - Int getFirewallBehavior(); - Short getFirewallPortAllocationDelta(); UnsignedShort getFirewallPortOverride(); - Bool getFirewallNeedToRefresh(); Bool usesSystemMapDir(); AsciiString getPreferred3DProvider(); AsciiString getSpeakerType(); @@ -132,4 +129,8 @@ class OptionPreferences : public UserPreferences Bool getShowMoneyPerMinute() const; Real getGameWindowTransitionSpeedMultiplier() const; + +private: + + void setIPAddress(AsciiString key, AsciiString IP); }; diff --git a/Core/GameEngine/Include/GameNetwork/FirewallHelper.h b/Core/GameEngine/Include/GameNetwork/FirewallHelper.h index 352b1a040bc..23e707b5043 100644 --- a/Core/GameEngine/Include/GameNetwork/FirewallHelper.h +++ b/Core/GameEngine/Include/GameNetwork/FirewallHelper.h @@ -175,21 +175,24 @@ class FirewallHelperClass { FirewallHelperClass(); virtual ~FirewallHelperClass(); Bool detectFirewall(); + void detectFirewallBehavior(); UnsignedShort getRawFirewallBehavior() {return((UnsignedShort)m_behavior);} Short getSourcePortAllocationDelta(); Int getFirewallHardness(FirewallBehaviorType behavior); Int getFirewallRetries(FirewallBehaviorType behavior); void setSourcePortPoolStart(Int port) {m_sourcePortPool = port;}; Int getSourcePortPool() {return(m_sourcePortPool);}; - void readFirewallBehavior(); void reset(); Bool behaviorDetectionUpdate(); FirewallBehaviorType getFirewallBehavior(); - void writeFirewallBehavior(); void flagNeedToRefresh(Bool flag); + Bool isBehaviorDetectionComplete() {return(m_currentState == DETECTIONSTATE_DONE);} + FirewallBehaviorType getLastFirewallBehavior() {return(m_lastBehavior);} + Short getLastSourcePortAllocationDelta() {return((Short)m_lastSourcePortAllocationDelta);} + static void getManglerName(Int manglerIndex, Char *nameBuf); Bool sendToManglerFromPort(UnsignedInt address, UnsignedShort port, UnsignedShort packetID, Bool blitzme = FALSE); UnsignedShort getManglerResponse(UnsignedShort packetID, Int time = 0); @@ -239,12 +242,9 @@ class FirewallHelperClass { return(FALSE); }; - - private: Int getNATPortAllocationScheme(Int numPorts, UnsignedShort *originalPorts, UnsignedShort *mangledPorts, Bool &relativeDelta, Bool &looksGood); - void detectFirewallBehavior(/*Bool &canRecord*/); Bool getReferencePort(); SpareSocketStruct * findSpareSocketByPort(UnsignedShort port); @@ -305,3 +305,6 @@ class FirewallHelperClass { extern FirewallHelperClass *TheFirewallHelper; FirewallHelperClass * createFirewallHelper(); + +FirewallHelperClass::FirewallBehaviorType getBestKnownFirewallBehavior(); +Short getBestKnownSourcePortAllocationDelta(); diff --git a/Core/GameEngine/Source/Common/OptionPreferences.cpp b/Core/GameEngine/Source/Common/OptionPreferences.cpp index af61c4c84fe..8d26448aa4e 100644 --- a/Core/GameEngine/Source/Common/OptionPreferences.cpp +++ b/Core/GameEngine/Source/Common/OptionPreferences.cpp @@ -45,6 +45,7 @@ #include "GameLogic/ScriptEngine.h" #include "GameNetwork/IPEnumeration.h" +#include "GameNetwork/FirewallHelper.h" OptionPreferences::OptionPreferences() { @@ -140,16 +141,27 @@ UnsignedInt OptionPreferences::getLANIPAddress() return TheGlobalData->m_defaultIP; } +void OptionPreferences::setIPAddress(AsciiString key, AsciiString IP) +{ + if ((*this)[key].compareNoCase(IP) == 0) + return; + + (*this)[key] = IP; + + if (TheFirewallHelper != nullptr) + TheFirewallHelper->flagNeedToRefresh(TRUE); +} + void OptionPreferences::setLANIPAddress(AsciiString IP) { - (*this)["IPAddress"] = IP; + setIPAddress("IPAddress", IP); } void OptionPreferences::setLANIPAddress(UnsignedInt IP) { - AsciiString tmp; - tmp.format("%d.%d.%d.%d", PRINTF_IP_AS_4_INTS(IP)); - (*this)["IPAddress"] = tmp; + AsciiString ipString; + ipString.format("%d.%d.%d.%d", PRINTF_IP_AS_4_INTS(IP)); + setLANIPAddress(ipString); } UnsignedInt OptionPreferences::getOnlineIPAddress() @@ -170,14 +182,14 @@ UnsignedInt OptionPreferences::getOnlineIPAddress() void OptionPreferences::setOnlineIPAddress(AsciiString IP) { - (*this)["GameSpyIPAddress"] = IP; + setIPAddress("GameSpyIPAddress", IP); } void OptionPreferences::setOnlineIPAddress(UnsignedInt IP) { - AsciiString tmp; - tmp.format("%d.%d.%d.%d", PRINTF_IP_AS_4_INTS(IP)); - (*this)["GameSpyIPAddress"] = tmp; + AsciiString ipString; + ipString.format("%d.%d.%d.%d", PRINTF_IP_AS_4_INTS(IP)); + setOnlineIPAddress(ipString); } Bool OptionPreferences::getArchiveReplaysEnabled() const @@ -463,31 +475,6 @@ Bool OptionPreferences::getSendDelay() return FALSE; } -Int OptionPreferences::getFirewallBehavior() -{ - OptionPreferences::const_iterator it = find("FirewallBehavior"); - if (it == end()) - return TheGlobalData->m_firewallBehavior; - - Int behavior = atoi(it->second.str()); - if (behavior < 0) - { - behavior = 0; - } - return behavior; -} - -Short OptionPreferences::getFirewallPortAllocationDelta() -{ - OptionPreferences::const_iterator it = find("FirewallPortAllocationDelta"); - if (it == end()) { - return TheGlobalData->m_firewallPortAllocationDelta; - } - - Short delta = atoi(it->second.str()); - return delta; -} - UnsignedShort OptionPreferences::getFirewallPortOverride() { OptionPreferences::const_iterator it = find("FirewallPortOverride"); @@ -501,21 +488,6 @@ UnsignedShort OptionPreferences::getFirewallPortOverride() return portOverride; } -Bool OptionPreferences::getFirewallNeedToRefresh() -{ - OptionPreferences::const_iterator it = find("FirewallNeedToRefresh"); - if (it == end()) { - return FALSE; - } - - Bool retval = FALSE; - AsciiString str = it->second; - if (str.compareNoCase("TRUE") == 0) { - retval = TRUE; - } - return retval; -} - AsciiString OptionPreferences::getPreferred3DProvider() { OptionPreferences::const_iterator it = find("3DAudioProvider"); diff --git a/Core/GameEngine/Source/GameNetwork/FirewallHelper.cpp b/Core/GameEngine/Source/GameNetwork/FirewallHelper.cpp index 04e5f7166b0..1bd56307921 100644 --- a/Core/GameEngine/Source/GameNetwork/FirewallHelper.cpp +++ b/Core/GameEngine/Source/GameNetwork/FirewallHelper.cpp @@ -54,6 +54,7 @@ #include "GameNetwork/NAT.h" #include "GameNetwork/udp.h" #include "GameNetwork/NetworkDefs.h" +#include "GameNetwork/IPEnumeration.h" #include "GameNetwork/GameSpy/GSConfig.h" @@ -61,7 +62,47 @@ FirewallHelperClass *TheFirewallHelper = nullptr; FirewallHelperClass * createFirewallHelper() { - return NEW FirewallHelperClass(); + FirewallHelperClass *helper = NEW FirewallHelperClass(); + helper->detectFirewallBehavior(); + return helper; +} + +FirewallHelperClass::FirewallBehaviorType getBestKnownFirewallBehavior() +{ + if (TheFirewallHelper != nullptr) + { + if (TheFirewallHelper->isBehaviorDetectionComplete() + && TheFirewallHelper->getFirewallBehavior() != FirewallHelperClass::FIREWALL_TYPE_UNKNOWN) + { + return TheFirewallHelper->getFirewallBehavior(); + } + + if (TheFirewallHelper->getLastFirewallBehavior() != FirewallHelperClass::FIREWALL_TYPE_UNKNOWN) + { + return TheFirewallHelper->getLastFirewallBehavior(); + } + } + + return FirewallHelperClass::FIREWALL_TYPE_UNKNOWN; +} + +Short getBestKnownSourcePortAllocationDelta() +{ + if (TheFirewallHelper != nullptr) + { + if (TheFirewallHelper->isBehaviorDetectionComplete() + && TheFirewallHelper->getFirewallBehavior() != FirewallHelperClass::FIREWALL_TYPE_UNKNOWN) + { + return TheFirewallHelper->getSourcePortAllocationDelta(); + } + + if (TheFirewallHelper->getLastFirewallBehavior() != FirewallHelperClass::FIREWALL_TYPE_UNKNOWN) + { + return TheFirewallHelper->getLastSourcePortAllocationDelta(); + } + } + + return 0; } @@ -176,22 +217,12 @@ void FirewallHelperClass::reset() *=============================================================================================*/ Bool FirewallHelperClass::detectFirewall() { - OptionPreferences pref; - - OptionPreferences::const_iterator it = pref.find("FirewallNeedToRefresh"); - if (it != pref.end()) { - AsciiString str = it->second; - if (str.compareNoCase("TRUE") == 0) { - TheWritableGlobalData->m_firewallBehavior = FIREWALL_TYPE_UNKNOWN; - } - } - - if (TheWritableGlobalData->m_firewallBehavior == FIREWALL_TYPE_UNKNOWN) { + if (m_behavior == FIREWALL_TYPE_UNKNOWN) { detectFirewallBehavior(); return FALSE; } else { - DEBUG_LOG(("FirewallHelperClass::detectFirewall - firewall behavior already specified as %d, port allocation delta is %d, skipping detection.", TheWritableGlobalData->m_firewallBehavior, TheWritableGlobalData->m_firewallPortAllocationDelta)); + DEBUG_LOG(("FirewallHelperClass::detectFirewall - firewall behavior already specified as %d, port allocation delta is %d, skipping detection.", m_behavior, m_sourcePortAllocationDelta)); } return TRUE; @@ -480,44 +511,6 @@ UnsignedShort FirewallHelperClass::getManglerResponse(UnsignedShort packetID, In return mangled_port; } - - - -/*********************************************************************************************** - * FirewallHelperClass::Write_Firewall_Settings -- Save out firewall settings. * - * * - * * - * * - * INPUT: Nothing * - * * - * OUTPUT: Nothing * - * * - * WARNINGS: None * - * * - * HISTORY: * - * 3/22/01 10:23PM ST : Created * - *=============================================================================================*/ -void FirewallHelperClass::writeFirewallBehavior() -{ - OptionPreferences pref; - - char num[16]; - num[0] = 0; - itoa(TheGlobalData->m_firewallBehavior, num, 10); - AsciiString numstr; - numstr = num; - (pref)["FirewallBehavior"] = numstr; - - TheWritableGlobalData->m_firewallPortAllocationDelta = getSourcePortAllocationDelta(); - num[0] = 0; - itoa(TheGlobalData->m_firewallPortAllocationDelta, num, 10); - numstr = num; - (pref)["FirewallPortAllocationDelta"] = numstr; - - pref.write(); -} - - /*********************************************************************************************** * FirewallHelperClass::flagNeedToRefresh -- Flag that the next time we log in we need to * * refresh our firewall settings. * @@ -535,38 +528,11 @@ void FirewallHelperClass::writeFirewallBehavior() *=============================================================================================*/ void FirewallHelperClass::flagNeedToRefresh(Bool flag) { - OptionPreferences pref; - - (pref)["FirewallNeedToRefresh"] = flag ? "TRUE" : "FALSE"; - - pref.write(); -} - - -/*********************************************************************************************** - * FirewallHelperClass::Read_Firewall_Behavior -- Read in old firewall settings * - * * - * * - * * - * INPUT: Nothing * - * * - * OUTPUT: Nothing * - * * - * WARNINGS: None * - * * - * HISTORY: * - * 3/22/01 10:25PM ST : Created * - *=============================================================================================*/ -void FirewallHelperClass::readFirewallBehavior() -{ -#if (0) - m_lastBehavior = (FirewallBehaviorType) ConfigINI.Get_Int("MultiPlayer", "FirewallSettings", FIREWALL_UNKNOWN); - m_lastSourcePortAllocationDelta = ConfigINI.Get_Int("MultiPlayer", "FirewallDelta", 1); -#endif //(0) + if (flag) { + detectFirewallBehavior(); + } } - - /*********************************************************************************************** * FHC::detectFirewallBehavior -- What is that wacky firewall doing to our packet headers? * * * @@ -581,15 +547,28 @@ void FirewallHelperClass::readFirewallBehavior() * HISTORY: * * 3/15/01 12:30PM ST : Created * *=============================================================================================*/ -void FirewallHelperClass::detectFirewallBehavior(/*Bool &canRecord*/) +void FirewallHelperClass::detectFirewallBehavior() { - m_behavior = FIREWALL_TYPE_SIMPLE; + reset(); + m_currentTry = 0; + m_numManglers = 0; + m_numResponses = 0; + m_packetID = 0; + m_timeoutLength = 0; + m_timeoutStart = 0; + if (m_behavior != FIREWALL_TYPE_UNKNOWN) + { + m_lastBehavior = m_behavior; + m_lastSourcePortAllocationDelta = m_sourcePortAllocationDelta; + } + + m_sourcePortAllocationDelta = 0; + m_behavior = FIREWALL_TYPE_UNKNOWN; m_currentState = DETECTIONSTATE_BEGIN; } FirewallHelperClass::FirewallBehaviorType FirewallHelperClass::getFirewallBehavior() { - m_currentState = DETECTIONSTATE_IDLE; return m_behavior; } @@ -608,6 +587,12 @@ Short FirewallHelperClass::getSourcePortAllocationDelta() { Bool FirewallHelperClass::detectionBeginUpdate() { // UnsignedShort mangler_port = MANGLER_PORT; m_packetID = 0x7f00; + + if (TheGameSpyConfig == nullptr) { + DEBUG_LOG(("FirewallHelperClass::detectionBeginUpdate - no GameSpy config, skipping detection.")); + m_currentState = DETECTIONSTATE_DONE; + return TRUE; + } //int current_mangler = 0; /* diff --git a/Core/GameEngine/Source/GameNetwork/GameSpy/PeerDefs.cpp b/Core/GameEngine/Source/GameNetwork/GameSpy/PeerDefs.cpp index 60d4be33148..28609a79681 100644 --- a/Core/GameEngine/Source/GameNetwork/GameSpy/PeerDefs.cpp +++ b/Core/GameEngine/Source/GameNetwork/GameSpy/PeerDefs.cpp @@ -43,6 +43,7 @@ #include "GameNetwork/GameSpy/PersistentStorageThread.h" #include "GameNetwork/GameSpy/GSConfig.h" #include "GameNetwork/GameSpyOverlay.h" +#include "GameNetwork/FirewallHelper.h" #include "GameNetwork/RankPointValue.h" #include "GameLogic/GameLogic.h" @@ -633,6 +634,11 @@ void SetUpGameSpy( const char *motdBuffer, const char *configBuffer ) TheGameSpyConfig = GameSpyConfigInterface::create(configBuffer); + if (TheFirewallHelper == nullptr) + { + TheFirewallHelper = createFirewallHelper(); + } + TheLadderList = NEW LadderList; ThePinger = PingerInterface::createNewPingerInterface(); @@ -697,6 +703,9 @@ void TearDownGameSpy() delete TheLadderList; TheLadderList = nullptr; + delete TheFirewallHelper; + TheFirewallHelper = nullptr; + delete TheGameSpyConfig; TheGameSpyConfig = nullptr; diff --git a/Core/GameEngine/Source/GameNetwork/NAT.cpp b/Core/GameEngine/Source/GameNetwork/NAT.cpp index 159d8532cfa..279051444dc 100644 --- a/Core/GameEngine/Source/GameNetwork/NAT.cpp +++ b/Core/GameEngine/Source/GameNetwork/NAT.cpp @@ -210,9 +210,6 @@ NATStateType NAT::update() { { m_NATState = NATSTATE_DONE; TheEstablishConnectionsMenu->endMenu(); - - delete TheFirewallHelper; - TheFirewallHelper = nullptr; } } else if (m_NATState == NATSTATE_DOCONNECTIONPATHS) { if (allConnectionsDoneThisRound() == TRUE) { @@ -257,18 +254,7 @@ NATStateType NAT::update() { m_NATState = NATSTATE_FAILED; TheEstablishConnectionsMenu->endMenu(); if (TheFirewallHelper != nullptr) { - // we failed NAT negotiation, perhaps we need to redetect our firewall settings. - // We don't trust the user to do it for themselves so we force them to do it next time - // the log in. - // 2/19/03 - ok, we don't want to do this right away, if the user tries to play in another game - // before they log out and log back in the game won't have a chance at working. - // so we need to simply flag it so that when they log out the firewall behavior gets blown away. TheFirewallHelper->flagNeedToRefresh(TRUE); -// TheWritableGlobalData->m_firewallBehavior = FirewallHelperClass::FIREWALL_TYPE_UNKNOWN; -// TheFirewallHelper->writeFirewallBehavior(); - - delete TheFirewallHelper; - TheFirewallHelper = nullptr; } // we failed to connect, so we don't have to pass on the transport to the network. delete m_transport; @@ -845,7 +831,7 @@ void NAT::processManglerResponse(UnsignedShort mangledPort) { return; } - Short delta = TheGlobalData->m_firewallPortAllocationDelta; + Short delta = getBestKnownSourcePortAllocationDelta(); UnsignedShort sourcePort = getSlotPort(m_connectionNodes[m_localNodeNumber].m_slotIndex); UnsignedShort returnPort = 0; diff --git a/Generals/Code/GameEngine/Include/Common/GlobalData.h b/Generals/Code/GameEngine/Include/Common/GlobalData.h index 26023c229db..ee8b029142e 100644 --- a/Generals/Code/GameEngine/Include/Common/GlobalData.h +++ b/Generals/Code/GameEngine/Include/Common/GlobalData.h @@ -323,10 +323,8 @@ class GlobalData : public SubsystemInterface Int m_netMinPlayers; ///< Min players needed to start a net game UnsignedInt m_defaultIP; ///< preferred IP address for LAN - UnsignedInt m_firewallBehavior; ///< Last detected firewall behavior Bool m_firewallSendDelay; ///< Use send delay for firewall connection negotiations UnsignedInt m_firewallPortOverride; ///< User-specified port to be used - Short m_firewallPortAllocationDelta; ///< the port allocation delta last detected. Int m_baseValuePerSupplyBox; Real m_BuildSpeed; diff --git a/Generals/Code/GameEngine/Source/Common/GlobalData.cpp b/Generals/Code/GameEngine/Source/Common/GlobalData.cpp index 25d5432c51f..cd57f922ade 100644 --- a/Generals/Code/GameEngine/Source/Common/GlobalData.cpp +++ b/Generals/Code/GameEngine/Source/Common/GlobalData.cpp @@ -434,9 +434,7 @@ GlobalData* GlobalData::m_theOriginal = nullptr; { "ShellMapOn", INI::parseBool, nullptr, offsetof( GlobalData, m_shellMapOn ) }, { "PlayIntro", INI::parseBool, nullptr, offsetof( GlobalData, m_playIntro ) }, - { "FirewallBehavior", INI::parseInt, nullptr, offsetof( GlobalData, m_firewallBehavior ) }, { "FirewallPortOverride", INI::parseInt, nullptr, offsetof( GlobalData, m_firewallPortOverride ) }, - { "FirewallPortAllocationDelta",INI::parseInt, nullptr, offsetof( GlobalData, m_firewallPortAllocationDelta) }, { "GroupSelectMinSelectSize", INI::parseInt, nullptr, offsetof( GlobalData, m_groupSelectMinSelectSize ) }, { "GroupSelectVolumeBase", INI::parseReal, nullptr, offsetof( GlobalData, m_groupSelectVolumeBase ) }, @@ -938,10 +936,8 @@ GlobalData::GlobalData() // m_languageFilterPref = false; m_languageFilterPref = true; - m_firewallBehavior = FirewallHelperClass::FIREWALL_TYPE_UNKNOWN; m_firewallSendDelay = FALSE; m_firewallPortOverride = 0; - m_firewallPortAllocationDelta = 0; m_loadScreenDemo = FALSE; m_disableRender = false; @@ -1206,8 +1202,6 @@ void GlobalData::parseGameDataDefinition( INI* ini ) TheWritableGlobalData->m_moveScrollAnchor = optionPref.getMoveScrollAnchor(); TheWritableGlobalData->m_defaultIP = optionPref.getLANIPAddress(); TheWritableGlobalData->m_firewallSendDelay = optionPref.getSendDelay(); - TheWritableGlobalData->m_firewallBehavior = optionPref.getFirewallBehavior(); - TheWritableGlobalData->m_firewallPortAllocationDelta = optionPref.getFirewallPortAllocationDelta(); TheWritableGlobalData->m_firewallPortOverride = optionPref.getFirewallPortOverride(); TheWritableGlobalData->m_saveCameraInReplay = optionPref.saveCameraInReplays(); diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp index 91b7f80af92..cdeb55d983e 100644 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp +++ b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp @@ -121,8 +121,6 @@ static GameWindow * checkDrawAnchor = nullptr; static NameKeyType checkMoveAnchorID = NAMEKEY_INVALID; static GameWindow * checkMoveAnchor = nullptr; -static NameKeyType buttonFirewallRefreshID = NAMEKEY_INVALID; -static GameWindow * buttonFirewallRefresh = nullptr; // //static NameKeyType checkAudioHardwareID = NAMEKEY_INVALID; //static GameWindow * checkAudioHardware = nullptr; @@ -970,8 +968,12 @@ void OptionsMenuInit( WindowLayout *layout, void *userData ) checkLanguageFilter = TheWindowManager->winGetWindowFromId( nullptr, checkLanguageFilterID ); checkSendDelayID = TheNameKeyGenerator->nameToKey( "OptionsMenu.wnd:CheckSendDelay" ); checkSendDelay = TheWindowManager->winGetWindowFromId( nullptr, checkSendDelayID); - buttonFirewallRefreshID = TheNameKeyGenerator->nameToKey( "OptionsMenu.wnd:ButtonFirewallRefresh" ); - buttonFirewallRefresh = TheWindowManager->winGetWindowFromId( nullptr, buttonFirewallRefreshID); +#if ENABLE_GUI_HACKS + // TheSuperHackers @tweak 25/07/2026 Hide the obsolete Refresh NAT button, because NAT detection is now self-healing + GameWindow *buttonFirewallRefresh = TheWindowManager->winGetWindowFromId(nullptr, NAMEKEY("OptionsMenu.wnd:ButtonFirewallRefresh")); + if (buttonFirewallRefresh) + buttonFirewallRefresh->winHide(TRUE); +#endif checkDrawAnchorID = TheNameKeyGenerator->nameToKey( "OptionsMenu.wnd:CheckBoxDrawAnchor" ); checkDrawAnchor = TheWindowManager->winGetWindowFromId( nullptr, checkDrawAnchorID); checkMoveAnchorID = TheNameKeyGenerator->nameToKey( "OptionsMenu.wnd:CheckBoxMoveAnchor" ); @@ -1391,8 +1393,6 @@ void OptionsMenuInit( WindowLayout *layout, void *userData ) checkSendDelay->winEnable(FALSE); - buttonFirewallRefresh->winEnable(FALSE); - if (comboBoxDetail) comboBoxDetail->winEnable(FALSE); @@ -1696,18 +1696,6 @@ WindowMsgHandledType OptionsMenuSystem( GameWindow *window, UnsignedInt msg, (*pref)["UseCameraInReplays"] = "no"; } } - else if (controlID == buttonFirewallRefreshID) - { - // setting the behavior to unknown will force the firewall helper to detect the firewall behavior - // the next time we log into gamespy/WOL/whatever. - char num[16]; - num[0] = 0; - TheWritableGlobalData->m_firewallBehavior = FirewallHelperClass::FIREWALL_TYPE_UNKNOWN; - itoa(TheGlobalData->m_firewallBehavior, num, 10); - AsciiString numstr; - numstr = num; - (*pref)["FirewallBehavior"] = numstr; - } break; } diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLGameSetupMenu.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLGameSetupMenu.cpp index f0f4b8df4a5..992de08732b 100644 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLGameSetupMenu.cpp +++ b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLGameSetupMenu.cpp @@ -1208,11 +1208,10 @@ void WOLGameSetupMenuInit( WindowLayout *layout, void *userData ) hostSlot->setAccept(); if (TheGameSpyInfo->amIHost()) { - OptionPreferences natPref; CustomMatchPreferences customPref; hostSlot->setColor( customPref.getPreferredColor() ); hostSlot->setPlayerTemplate( customPref.getPreferredFaction() ); - hostSlot->setNATBehavior((FirewallHelperClass::FirewallBehaviorType)natPref.getFirewallBehavior()); + hostSlot->setNATBehavior(getBestKnownFirewallBehavior()); hostSlot->setPingString(TheGameSpyInfo->getPingString()); game->setMap(customPref.getPreferredMap()); @@ -1243,7 +1242,6 @@ void WOLGameSetupMenuInit( WindowLayout *layout, void *userData ) } else { - OptionPreferences natPref; CustomMatchPreferences customPref; AsciiString options; PeerRequest req; @@ -1260,7 +1258,7 @@ void WOLGameSetupMenuInit( WindowLayout *layout, void *userData ) options.format("Color=%d", customPref.getPreferredColor()); req.options = options.str(); TheGameSpyPeerMessageQueue->addRequest(req); - options.format("NAT=%d", natPref.getFirewallBehavior()); + options.format("NAT=%d", getBestKnownFirewallBehavior()); req.options = options.str(); TheGameSpyPeerMessageQueue->addRequest(req); options.format("Ping=%s", TheGameSpyInfo->getPingString().str()); diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLoginMenu.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLoginMenu.cpp index 6edaba07101..5fc6c8a4029 100644 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLoginMenu.cpp +++ b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLoginMenu.cpp @@ -66,6 +66,7 @@ #include "GameNetwork/GameSpy/PersistentStorageThread.h" #include "GameNetwork/GameSpyOverlay.h" +#include "GameNetwork/FirewallHelper.h" #include "GameNetwork/WOLBrowser/WebBrowser.h" @@ -811,6 +812,11 @@ void WOLLoginMenuUpdate( WindowLayout * layout, void *userData) if(isShuttingDown && TheShell->isAnimFinished() && TheTransitionHandler->isFinished()) shutdownComplete(layout); + if (TheFirewallHelper != nullptr) + { + TheFirewallHelper->behaviorDetectionUpdate(); + } + if (TheShell->isAnimFinished() && !buttonPushed && TheGameSpyPeerMessageQueue) { PingResponse pingResp; diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQuickMatchMenu.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQuickMatchMenu.cpp index 1f8cbb310d5..5283bc2ec02 100644 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQuickMatchMenu.cpp +++ b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQuickMatchMenu.cpp @@ -1691,8 +1691,7 @@ WindowMsgHandledType WOLQuickMatchMenuSystem( GameWindow *window, UnsignedInt ms index = (Int)GadgetComboBoxGetItemData( comboBoxColor, selected ); req.QM.color = index; - OptionPreferences natPref; - req.QM.NAT = natPref.getFirewallBehavior(); + req.QM.NAT = getBestKnownFirewallBehavior(); if (ladderIndex) { diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLWelcomeMenu.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLWelcomeMenu.cpp index 403d17c9bea..8b950d2382a 100644 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLWelcomeMenu.cpp +++ b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLWelcomeMenu.cpp @@ -489,11 +489,6 @@ void WOLWelcomeMenuInit( WindowLayout *layout, void *userData ) if (TheFirewallHelper == nullptr) { TheFirewallHelper = createFirewallHelper(); } - if (TheFirewallHelper->detectFirewall() == TRUE) { - // don't need to detect firewall, already been done. - delete TheFirewallHelper; - TheFirewallHelper = nullptr; - } /* if (TheGameSpyChat && TheGameSpyChat->isConnected()) @@ -550,9 +545,6 @@ void WOLWelcomeMenuShutdown( WindowLayout *layout, void *userData ) { listboxInfo = nullptr; - delete TheFirewallHelper; - TheFirewallHelper = nullptr; - isShuttingDown = TRUE; // if we are shutting down for an immediate pop, skip the animations @@ -590,18 +582,7 @@ void WOLWelcomeMenuUpdate( WindowLayout * layout, void *userData) if (TheFirewallHelper != nullptr) { - if (TheFirewallHelper->behaviorDetectionUpdate()) - { - TheWritableGlobalData->m_firewallBehavior = TheFirewallHelper->getFirewallBehavior(); - - TheFirewallHelper->writeFirewallBehavior(); - - TheFirewallHelper->flagNeedToRefresh(FALSE); // 2/19/03 BGC, we're done, so we don't need to refresh the NAT anymore. - - // we are now done with the firewall helper - delete TheFirewallHelper; - TheFirewallHelper = nullptr; - } + TheFirewallHelper->behaviorDetectionUpdate(); } if (TheShell->isAnimFinished() && !buttonPushed && TheGameSpyPeerMessageQueue) diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameSpy.cpp index 8fd4ed5c6b4..5b3f780e386 100644 --- a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy.cpp +++ b/Generals/Code/GameEngine/Source/GameNetwork/GameSpy.cpp @@ -283,21 +283,7 @@ void GameSpyChat::update() } if (TheFirewallHelper != nullptr) { - if (TheFirewallHelper->behaviorDetectionUpdate()) { - TheGlobalData->m_firewallBehavior = TheFirewallHelper->getFirewallBehavior(); - OptionPreferences *pref = NEW OptionPreferences; - char num[16]; - num[0] = 0; - itoa(TheGlobalData->m_firewallBehavior, num, 10); - AsciiString numstr; - numstr = num; - (*pref)["FirewallBehavior"] = numstr; - pref->write(); - - // we are now done with the firewall helper - delete TheFirewallHelper; - TheFirewallHelper = nullptr; - } + TheFirewallHelper->behaviorDetectionUpdate(); } UnsignedInt now = timeGetTime(); @@ -965,7 +951,7 @@ void JoinRoomCallback(PEER peer, PEERBool success, PEERJoinResult result, RoomTy localIP = ntohl(localIP); // The IP returned from GetLocalChatConnectionAddress is in network byte order. options.format("IP=%d", localIP); peerUTMPlayer(TheGameSpyChat->getPeer(), hostName.str(), "REQ/", options.str(), PEERFalse); - options.format("NAT=%d", TheFirewallHelper->getFirewallBehavior()); + options.format("NAT=%d", getBestKnownFirewallBehavior()); peerUTMPlayer(TheGameSpyChat->getPeer(), hostName.str(), "REQ/", options.str(), PEERFalse); // refresh the map cache diff --git a/GeneralsMD/Code/GameEngine/Include/Common/GlobalData.h b/GeneralsMD/Code/GameEngine/Include/Common/GlobalData.h index 5235b763fd1..2ed3d340cc0 100644 --- a/GeneralsMD/Code/GameEngine/Include/Common/GlobalData.h +++ b/GeneralsMD/Code/GameEngine/Include/Common/GlobalData.h @@ -324,10 +324,8 @@ class GlobalData : public SubsystemInterface Int m_netMinPlayers; ///< Min players needed to start a net game UnsignedInt m_defaultIP; ///< preferred IP address for LAN - UnsignedInt m_firewallBehavior; ///< Last detected firewall behavior Bool m_firewallSendDelay; ///< Use send delay for firewall connection negotiations UnsignedInt m_firewallPortOverride; ///< User-specified port to be used - Short m_firewallPortAllocationDelta; ///< the port allocation delta last detected. Int m_baseValuePerSupplyBox; Real m_BuildSpeed; diff --git a/GeneralsMD/Code/GameEngine/Source/Common/GlobalData.cpp b/GeneralsMD/Code/GameEngine/Source/Common/GlobalData.cpp index 131d20513ff..e63611447f0 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/GlobalData.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/GlobalData.cpp @@ -434,9 +434,7 @@ GlobalData* GlobalData::m_theOriginal = nullptr; { "ShellMapOn", INI::parseBool, nullptr, offsetof( GlobalData, m_shellMapOn ) }, { "PlayIntro", INI::parseBool, nullptr, offsetof( GlobalData, m_playIntro ) }, - { "FirewallBehavior", INI::parseInt, nullptr, offsetof( GlobalData, m_firewallBehavior ) }, { "FirewallPortOverride", INI::parseInt, nullptr, offsetof( GlobalData, m_firewallPortOverride ) }, - { "FirewallPortAllocationDelta",INI::parseInt, nullptr, offsetof( GlobalData, m_firewallPortAllocationDelta) }, { "GroupSelectMinSelectSize", INI::parseInt, nullptr, offsetof( GlobalData, m_groupSelectMinSelectSize ) }, { "GroupSelectVolumeBase", INI::parseReal, nullptr, offsetof( GlobalData, m_groupSelectVolumeBase ) }, @@ -945,10 +943,8 @@ GlobalData::GlobalData() // m_languageFilterPref = false; m_languageFilterPref = true; - m_firewallBehavior = FirewallHelperClass::FIREWALL_TYPE_UNKNOWN; m_firewallSendDelay = FALSE; m_firewallPortOverride = 0; - m_firewallPortAllocationDelta = 0; m_loadScreenDemo = FALSE; m_disableRender = false; @@ -1213,8 +1209,6 @@ void GlobalData::parseGameDataDefinition( INI* ini ) TheWritableGlobalData->m_moveScrollAnchor = optionPref.getMoveScrollAnchor(); TheWritableGlobalData->m_defaultIP = optionPref.getLANIPAddress(); TheWritableGlobalData->m_firewallSendDelay = optionPref.getSendDelay(); - TheWritableGlobalData->m_firewallBehavior = optionPref.getFirewallBehavior(); - TheWritableGlobalData->m_firewallPortAllocationDelta = optionPref.getFirewallPortAllocationDelta(); TheWritableGlobalData->m_firewallPortOverride = optionPref.getFirewallPortOverride(); TheWritableGlobalData->m_saveCameraInReplay = optionPref.saveCameraInReplays(); diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp index ee99e20c452..7baad300dac 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp @@ -127,8 +127,6 @@ static GameWindow * checkDrawAnchor = nullptr; static NameKeyType checkMoveAnchorID = NAMEKEY_INVALID; static GameWindow * checkMoveAnchor = nullptr; -static NameKeyType buttonFirewallRefreshID = NAMEKEY_INVALID; -static GameWindow * buttonFirewallRefresh = nullptr; // //static NameKeyType checkAudioHardwareID = NAMEKEY_INVALID; //static GameWindow * checkAudioHardware = nullptr; @@ -999,8 +997,12 @@ void OptionsMenuInit( WindowLayout *layout, void *userData ) checkLanguageFilter = TheWindowManager->winGetWindowFromId( nullptr, checkLanguageFilterID ); checkSendDelayID = TheNameKeyGenerator->nameToKey( "OptionsMenu.wnd:CheckSendDelay" ); checkSendDelay = TheWindowManager->winGetWindowFromId( nullptr, checkSendDelayID); - buttonFirewallRefreshID = TheNameKeyGenerator->nameToKey( "OptionsMenu.wnd:ButtonFirewallRefresh" ); - buttonFirewallRefresh = TheWindowManager->winGetWindowFromId( nullptr, buttonFirewallRefreshID); +#if ENABLE_GUI_HACKS + // TheSuperHackers @tweak 25/07/2026 Hide the obsolete Refresh NAT button, because NAT detection is now self-healing + GameWindow *buttonFirewallRefresh = TheWindowManager->winGetWindowFromId(nullptr, NAMEKEY("OptionsMenu.wnd:ButtonFirewallRefresh")); + if (buttonFirewallRefresh) + buttonFirewallRefresh->winHide(TRUE); +#endif checkDrawAnchorID = TheNameKeyGenerator->nameToKey( "OptionsMenu.wnd:CheckBoxDrawAnchor" ); checkDrawAnchor = TheWindowManager->winGetWindowFromId( nullptr, checkDrawAnchorID); checkMoveAnchorID = TheNameKeyGenerator->nameToKey( "OptionsMenu.wnd:CheckBoxMoveAnchor" ); @@ -1427,8 +1429,6 @@ void OptionsMenuInit( WindowLayout *layout, void *userData ) checkSendDelay->winEnable(FALSE); - buttonFirewallRefresh->winEnable(FALSE); - if (comboBoxDetail) comboBoxDetail->winEnable(FALSE); @@ -1732,18 +1732,6 @@ WindowMsgHandledType OptionsMenuSystem( GameWindow *window, UnsignedInt msg, (*pref)["UseCameraInReplays"] = "no"; } } - else if (controlID == buttonFirewallRefreshID) - { - // setting the behavior to unknown will force the firewall helper to detect the firewall behavior - // the next time we log into gamespy/WOL/whatever. - char num[16]; - num[0] = 0; - TheWritableGlobalData->m_firewallBehavior = FirewallHelperClass::FIREWALL_TYPE_UNKNOWN; - itoa(TheGlobalData->m_firewallBehavior, num, 10); - AsciiString numstr; - numstr = num; - (*pref)["FirewallBehavior"] = numstr; - } break; } diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLGameSetupMenu.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLGameSetupMenu.cpp index f360ba9423b..46aa6479b92 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLGameSetupMenu.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLGameSetupMenu.cpp @@ -1365,11 +1365,10 @@ void WOLGameSetupMenuInit( WindowLayout *layout, void *userData ) hostSlot->setAccept(); if (TheGameSpyInfo->amIHost()) { - OptionPreferences natPref; CustomMatchPreferences customPref; hostSlot->setColor( customPref.getPreferredColor() ); hostSlot->setPlayerTemplate( customPref.getPreferredFaction() ); - hostSlot->setNATBehavior((FirewallHelperClass::FirewallBehaviorType)natPref.getFirewallBehavior()); + hostSlot->setNATBehavior(getBestKnownFirewallBehavior()); hostSlot->setPingString(TheGameSpyInfo->getPingString()); game->setMap(customPref.getPreferredMap()); @@ -1420,7 +1419,6 @@ void WOLGameSetupMenuInit( WindowLayout *layout, void *userData ) } else { - OptionPreferences natPref; CustomMatchPreferences customPref; AsciiString options; PeerRequest req; @@ -1437,7 +1435,7 @@ void WOLGameSetupMenuInit( WindowLayout *layout, void *userData ) options.format("Color=%d", customPref.getPreferredColor()); req.options = options.str(); TheGameSpyPeerMessageQueue->addRequest(req); - options.format("NAT=%d", natPref.getFirewallBehavior()); + options.format("NAT=%d", getBestKnownFirewallBehavior()); req.options = options.str(); TheGameSpyPeerMessageQueue->addRequest(req); options.format("Ping=%s", TheGameSpyInfo->getPingString().str()); diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLoginMenu.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLoginMenu.cpp index 25d49d2daa2..0cf9d06be13 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLoginMenu.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLoginMenu.cpp @@ -66,6 +66,7 @@ #include "GameNetwork/GameSpy/PersistentStorageThread.h" #include "GameNetwork/GameSpyOverlay.h" +#include "GameNetwork/FirewallHelper.h" #include "GameNetwork/WOLBrowser/WebBrowser.h" @@ -811,6 +812,11 @@ void WOLLoginMenuUpdate( WindowLayout * layout, void *userData) if(isShuttingDown && TheShell->isAnimFinished() && TheTransitionHandler->isFinished()) shutdownComplete(layout); + if (TheFirewallHelper != nullptr) + { + TheFirewallHelper->behaviorDetectionUpdate(); + } + if (TheShell->isAnimFinished() && !buttonPushed && TheGameSpyPeerMessageQueue) { PingResponse pingResp; diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQuickMatchMenu.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQuickMatchMenu.cpp index 977f72e5a87..c57936351cc 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQuickMatchMenu.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQuickMatchMenu.cpp @@ -1756,8 +1756,7 @@ WindowMsgHandledType WOLQuickMatchMenuSystem( GameWindow *window, UnsignedInt ms index = (Int)GadgetComboBoxGetItemData( comboBoxColor, selected ); req.QM.color = index; - OptionPreferences natPref; - req.QM.NAT = natPref.getFirewallBehavior(); + req.QM.NAT = getBestKnownFirewallBehavior(); if (ladderIndex) { diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLWelcomeMenu.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLWelcomeMenu.cpp index c84a8fd559e..ed18907163b 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLWelcomeMenu.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLWelcomeMenu.cpp @@ -506,11 +506,6 @@ void WOLWelcomeMenuInit( WindowLayout *layout, void *userData ) if (TheFirewallHelper == nullptr) { TheFirewallHelper = createFirewallHelper(); } - if (TheFirewallHelper->detectFirewall() == TRUE) { - // don't need to detect firewall, already been done. - delete TheFirewallHelper; - TheFirewallHelper = nullptr; - } /* if (TheGameSpyChat && TheGameSpyChat->isConnected()) @@ -567,9 +562,6 @@ void WOLWelcomeMenuShutdown( WindowLayout *layout, void *userData ) { listboxInfo = nullptr; - delete TheFirewallHelper; - TheFirewallHelper = nullptr; - isShuttingDown = TRUE; // if we are shutting down for an immediate pop, skip the animations @@ -607,18 +599,7 @@ void WOLWelcomeMenuUpdate( WindowLayout * layout, void *userData) if (TheFirewallHelper != nullptr) { - if (TheFirewallHelper->behaviorDetectionUpdate()) - { - TheWritableGlobalData->m_firewallBehavior = TheFirewallHelper->getFirewallBehavior(); - - TheFirewallHelper->writeFirewallBehavior(); - - TheFirewallHelper->flagNeedToRefresh(FALSE); // 2/19/03 BGC, we're done, so we don't need to refresh the NAT anymore. - - // we are now done with the firewall helper - delete TheFirewallHelper; - TheFirewallHelper = nullptr; - } + TheFirewallHelper->behaviorDetectionUpdate(); } if (TheShell->isAnimFinished() && !buttonPushed && TheGameSpyPeerMessageQueue)