mirror of
https://github.com/electronicarts/CnC_Renegade.git
synced 2025-12-16 07:31:40 -05:00
Initial commit of Command & Conquer Renegade source code.
This commit is contained in:
317
Code/Commando/FirewallWait.cpp
Normal file
317
Code/Commando/FirewallWait.cpp
Normal file
@@ -0,0 +1,317 @@
|
||||
/*
|
||||
** 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);
|
||||
}
|
||||
Reference in New Issue
Block a user