| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317 |
- /*
- ** Command & Conquer Renegade(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /******************************************************************************
- *
- * FILE
- * $Archive: /Commando/Code/Commando/FirewallWait.cpp $
- *
- * DESCRIPTION
- * Firewall negotiation wait condition.
- *
- * PROGRAMMER
- * $Author: Tom_s $
- *
- * VERSION INFO
- * $Revision: 16 $
- * $Modtime: 3/04/02 11:45a $
- *
- ******************************************************************************/
- #include "always.h"
- #include "FirewallWait.h"
- #include "nat.h"
- #include "string_ids.h"
- #include "translatedb.h"
- #include "natter.h"
- #include <WWOnline\WOLSession.h>
- #include <WWDebug\WWDebug.h>
- #ifdef _MSC_VER
- #pragma warning (push,3)
- #endif
- #include "systimer.h"
- #ifdef _MSC_VER
- #pragma warning (pop)
- #endif
- /*
- ** Wait code for firewall/NAT detection.
- **
- **
- **
- */
- RefPtr<FirewallDetectWait> FirewallDetectWait::Create(void)
- {
- return new FirewallDetectWait();
- }
- FirewallDetectWait::FirewallDetectWait(void) :
- SingleWait(TRANSLATION(IDS_FIREWALL_NEGOTIATING_FIREWALL), 60000),
- mEvent(NULL),
- mPingsRemaining(UINT_MAX)
- {
- mWOLSession = WWOnline::Session::GetInstance(false);
- assert(mWOLSession.IsValid());
- }
- FirewallDetectWait::~FirewallDetectWait()
- {
- WWDEBUG_SAY(("FirewallDetectWait: End - %S\n", mEndText));
- mWOLSession->EnablePinging(true);
- if (mEvent)
- {
- CloseHandle(mEvent);
- }
- }
- void FirewallDetectWait::WaitBeginning(void)
- {
- WWDEBUG_SAY(("FirewallDetectWait: Beginning\n"));
- mEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- if (mEvent == NULL)
- {
- WWDEBUG_SAY(("FirewallDetectWait: Can't create event\n"));
- EndWait(Error, TRANSLATION(IDS_FIREWALL_CREATE_EVENT_FAILED));
- }
- else
- {
- mWOLSession->EnablePinging(false);
- mTimeout = 15000;
- }
- }
- WaitCondition::WaitResult FirewallDetectWait::GetResult(void)
- {
- if (mEndResult == Waiting)
- {
- // Wait for pending pings to finish first
- unsigned int pingsWaiting = mWOLSession->GetPendingPingCount();
- if (mPingsRemaining != pingsWaiting)
- {
- mPingsRemaining = pingsWaiting;
- mTimeout = 60000;
- FirewallHelper.Detect_Firewall(mEvent);
- }
- if (mPingsRemaining == 0)
- {
- DWORD result = WaitForSingleObject(mEvent, 0);
- if (result == WAIT_OBJECT_0)
- {
- WWDEBUG_SAY(("FirewallDetectWait: ConditionMet\n"));
- WOLNATInterface.Save_Firewall_Info_To_Registry();
- EndWait(ConditionMet, TRANSLATION(IDS_FIREWALL_NEGOTIATION_COMPLETE));
- }
- else if (result == WAIT_FAILED)
- {
- WWDEBUG_SAY(("FirewallDetectWait: WAIT_FAILED\n"));
- EndWait(Error, TRANSLATION(IDS_FIREWALL_NEGOTIATION_FAILED));
- }
- }
- }
- if (mEndResult != Waiting)
- {
- mWOLSession->EnablePinging(true);
- }
- return mEndResult;
- }
- /*
- ** Wait code for clients when trying to open up a firewall for a server connection.
- **
- */
- RefPtr<FirewallConnectWait> FirewallConnectWait::Create(void)
- {
- return new FirewallConnectWait;
- }
- FirewallConnectWait::FirewallConnectWait(void) :
- SingleWait(TRANSLATION(IDS_FIREWALL_NEGOTIATING_WITH_SERVER)),
- mEvent(NULL),
- mCancelEvent(NULL),
- mSuccessFlag(FirewallHelperClass::FW_RESULT_UNKNOWN),
- mQueueCount(0),
- mLastQueueCount(0),
- mPingsRemaining(UINT_MAX)
- {
- mWOLSession = WWOnline::Session::GetInstance(false);
- assert(mWOLSession.IsValid());
- }
- FirewallConnectWait::~FirewallConnectWait()
- {
- WWDEBUG_SAY(("FirewallConnectWait: End - %S\n", mEndText));
- mWOLSession->EnablePinging(true);
- if (mEvent)
- {
- CloseHandle(mEvent);
- }
- if (mCancelEvent)
- {
- CloseHandle(mCancelEvent);
- }
- }
- void FirewallConnectWait::WaitBeginning(void)
- {
- WWDEBUG_SAY(("FirewallConnectWait: Beginning\n"));
- mEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- mCancelEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- if (mEvent == NULL)
- {
- WWDEBUG_SAY(("FirewallConnectWait: Can't create event\n"));
- EndWait(Error, TRANSLATION(IDS_FIREWALL_CREATE_EVENT_FAILED));
- }
- else
- {
- mWOLSession->EnablePinging(false);
- WOLNATInterface.Tell_Server_That_Client_Is_In_Channel();
- mTimeout = 15000;
- mStartTime = TIMEGETTIME();
- }
- }
- WaitCondition::WaitResult FirewallConnectWait::GetResult(void)
- {
- if (mEndResult == Waiting)
- {
- // Wait for pending pings to finish first
- unsigned int pingsWaiting = mWOLSession->GetPendingPingCount();
- if (mPingsRemaining != pingsWaiting)
- {
- mPingsRemaining = pingsWaiting;
- if (mPingsRemaining == 0)
- {
- FirewallHelper.Set_Client_Connect_Event(mEvent, mCancelEvent, &mSuccessFlag, (int*)&mQueueCount);
- mTimeout = 32000;
- mStartTime = TIMEGETTIME();
- }
- }
- if (mPingsRemaining == 0)
- {
- if ((TIMEGETTIME() - mStartTime) > mTimeout)
- {
- EndWait(TimeOut, TRANSLATION(IDS_FIREWALL_PORT_NEGOTIATION_TIMEOUT));
- }
- else
- {
- // Maybe change the wait text if there are players queued in front of us.
- if (mQueueCount != mLastQueueCount)
- {
- wchar_t temp[256];
- swprintf(temp, TRANSLATION(IDS_FIREWALL_QUEUE_NOTIFICATION), mQueueCount);
- WideStringClass text(temp, true);
- SetWaitText(text);
- mLastQueueCount = mQueueCount;
- mTimeout = max((unsigned)32000, ((mQueueCount * 32000) + 32000));
- mStartTime = TIMEGETTIME();
- }
- DWORD result = WaitForSingleObject(mEvent, 0);
- if (result == WAIT_OBJECT_0)
- {
- if (mSuccessFlag == FirewallHelperClass::FW_RESULT_SUCCEEDED)
- {
- WWDEBUG_SAY(("FirewallConnectWait: ConditionMet\n"));
- EndWait(ConditionMet, TRANSLATION(IDS_FIREWALL_PORT_NEGOTIATION_COMPLETE));
- }
- else
- {
- assert(mSuccessFlag == FirewallHelperClass::FW_RESULT_FAILED);
- WWDEBUG_SAY(("FirewallConnectWait: ConditionMet\n"));
- EndWait(Error, TRANSLATION(IDS_FIREWALL_PORT_NEGOTIATION_FAILED));
- }
- }
- else if (result == WAIT_FAILED)
- {
- WWDEBUG_SAY(("FirewallConnectWait: WAIT_FAILED\n"));
- EndWait(Error, TRANSLATION(IDS_FIREWALL_PORT_NEGOTIATION_FAILED));
- }
- }
- }
- }
- if (mEndResult != Waiting)
- {
- mWOLSession->EnablePinging(true);
- }
- return mEndResult;
- }
- //
- // Override base class end wait to check for cancel being pressed.
- //
- void FirewallConnectWait::EndWait(WaitResult result, const wchar_t* endText)
- {
- WWDEBUG_SAY(("FirewallConnectWait: EndWait\n"));
- if (result == UserCancel || result == TimeOut)
- {
- // Tell the firewall negotiation code to give up.
- SetEvent(mCancelEvent);
- }
- // Give the firewall code a little time to respond then remove it's cancel event anyway. It'll figure it out.
- for (int i=0 ; i<100 ; i++)
- {
- if (mSuccessFlag == FirewallHelperClass::FW_RESULT_CANCELLED)
- {
- break;
- }
- Sleep(1);
- }
- FirewallHelper.Set_Client_Connect_Event(NULL, NULL, NULL, NULL);
- SingleWait::EndWait(result, endText);
- }
|