249 lines
6.0 KiB
C++
249 lines
6.0 KiB
C++
![]() |
#include "portcullis.h"
|
||
|
|
||
|
#if PORTCULLIS_ENABLE
|
||
|
|
||
|
#if __WIN32PC
|
||
|
#include <tchar.h> // for strcmp
|
||
|
#pragma warning(disable:4668)
|
||
|
#include <windows.h>
|
||
|
#pragma warning(error:4668)
|
||
|
#endif // __WIN32PC
|
||
|
|
||
|
#include "heartbeat/heartbeat.h"
|
||
|
|
||
|
#include "system/timer.h"
|
||
|
|
||
|
#if __WIN32PC
|
||
|
#if RSG_CPU_X64
|
||
|
#pragma comment (lib,"curl-7.28.0_x64.lib")
|
||
|
#else
|
||
|
#pragma comment (lib,"curl-7.28.0.lib")
|
||
|
#endif
|
||
|
#endif // __WIN32PC
|
||
|
|
||
|
namespace rage
|
||
|
{
|
||
|
extern sysThreadPool netThreadPool;
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////
|
||
|
void portcullisWorkItem::DoWork()
|
||
|
{
|
||
|
m_result = true;
|
||
|
#if __WIN32PC
|
||
|
//@@: range PORTCULLISWORKITEM_DOWORK_COMPARE_RESULT {
|
||
|
static const char* gameName = "Paradise";
|
||
|
|
||
|
char* hbResult = Portcullis::SendHeartbeat(gameName);
|
||
|
|
||
|
if(!hbResult ||
|
||
|
hbResult[0] != 0x66 ||
|
||
|
hbResult[1] != 0x75 ||
|
||
|
hbResult[2] != 0x74 ||
|
||
|
hbResult[3] != 0x75 ||
|
||
|
hbResult[4] != 0x72 ||
|
||
|
hbResult[5] != 0x65 ||
|
||
|
hbResult[6] != 0x74 ||
|
||
|
hbResult[7] != 0x61 ||
|
||
|
hbResult[8] != 0x6b ||
|
||
|
hbResult[9] != 0x65 ||
|
||
|
hbResult[10] != 0x37 ||
|
||
|
hbResult[11] != 0x35) // "futuretake75"
|
||
|
{
|
||
|
// crash game now or ideally a little bit later
|
||
|
m_result = false;
|
||
|
}
|
||
|
//@@: } PORTCULLISWORKITEM_DOWORK_COMPARE_RESULT
|
||
|
#endif // __WIN32
|
||
|
|
||
|
//@@: location PORTCULLISWORKITEM_DOWORK_EXIT
|
||
|
m_checkDone = true;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
bool portcullis::m_initialised = false;
|
||
|
|
||
|
#if SINGLE_THREAD_PORTCULLIS
|
||
|
bool portcullis::m_closeThread = false;
|
||
|
sysIpcThreadId portcullis::m_threadID = sysIpcThreadIdInvalid;
|
||
|
sysIpcSema portcullis::m_triggerCheck = sysIpcCreateSema(0);
|
||
|
sysIpcSema portcullis::m_threadClosed = sysIpcCreateSema(0);
|
||
|
#endif // SINGLE_THREAD_PORTCULLIS
|
||
|
|
||
|
bool portcullis::m_checkInProgress = false;
|
||
|
bool portcullis::m_checkSuccess = true;
|
||
|
|
||
|
int portcullis::m_failTolerance = 0;
|
||
|
netRandom portcullis::m_random;
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////
|
||
|
void portcullis::Initialise()
|
||
|
{
|
||
|
//@@: location PORTCULLIS_INITIALISE_ENTRY
|
||
|
m_random.Reset(sysTimer::GetSystemMsTime());
|
||
|
|
||
|
#if 0 && !__FINAL
|
||
|
MessageBoxA(NULL, "Portcullis is enabled on this build\n If your PC has not been authorised then the game will crash randomly.\nNote: this message should NOT appear on a build sent out to a 3rd party (Final)", "Portcullis", MB_OK|MB_SETFOREGROUND|MB_TASKMODAL);
|
||
|
#endif // !__FINAL
|
||
|
|
||
|
// Get a random number of times the check is allowed to fail before it forces a crash
|
||
|
m_failTolerance = m_random.GetRanged(2, 3);
|
||
|
#if __WIN32PC
|
||
|
Portcullis::Initialize(NULL, true, NULL);
|
||
|
m_initialised = true;
|
||
|
#elif RSG_DURANGO
|
||
|
|
||
|
#endif
|
||
|
|
||
|
#if SINGLE_THREAD_PORTCULLIS
|
||
|
if(m_threadID == sysIpcThreadIdInvalid)
|
||
|
m_threadID = sysIpcCreateThread(&ThreadFunc, NULL, sysIpcMinThreadStackSize, PRIO_NORMAL, "");
|
||
|
#endif // SINGLE_THREAD_PORTCULLIS
|
||
|
}
|
||
|
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////
|
||
|
void portcullis::DoHeartbeat()
|
||
|
{
|
||
|
#if SINGLE_THREAD_PORTCULLIS
|
||
|
static const char* gameName = "Paradise";
|
||
|
|
||
|
char* hbResult = Portcullis::SendHeartbeat(gameName);
|
||
|
|
||
|
if(!hbResult ||
|
||
|
hbResult[0] != 0x66 ||
|
||
|
hbResult[1] != 0x75 ||
|
||
|
hbResult[2] != 0x74 ||
|
||
|
hbResult[3] != 0x75 ||
|
||
|
hbResult[4] != 0x72 ||
|
||
|
hbResult[5] != 0x65 ||
|
||
|
hbResult[6] != 0x74 ||
|
||
|
hbResult[7] != 0x61 ||
|
||
|
hbResult[8] != 0x6b ||
|
||
|
hbResult[9] != 0x65 ||
|
||
|
hbResult[10] != 0x37 ||
|
||
|
hbResult[11] != 0x35) // "futuretake75"
|
||
|
{
|
||
|
// crash game now or ideally a little bit later
|
||
|
m_checkSuccess = false;
|
||
|
}
|
||
|
#endif // SINGLE_THREAD_PORTCULLIS
|
||
|
}
|
||
|
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////
|
||
|
void portcullis::ThreadFunc(void*)
|
||
|
{
|
||
|
#if SINGLE_THREAD_PORTCULLIS
|
||
|
m_closeThread = false;
|
||
|
while(!m_closeThread)
|
||
|
{
|
||
|
sysIpcWaitSema(m_triggerCheck);
|
||
|
m_checkInProgress = true;
|
||
|
|
||
|
DoHeartbeat();
|
||
|
|
||
|
m_checkInProgress = false;
|
||
|
}
|
||
|
|
||
|
sysIpcSignalSema(m_threadClosed);
|
||
|
#endif // SINGLE_THREAD_PORTCULLIS
|
||
|
}
|
||
|
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////
|
||
|
bool portcullis::DoCheck()
|
||
|
{
|
||
|
if(m_initialised == false)
|
||
|
{
|
||
|
//@@: location PORTCULLIS_DOCHECK_CALL_INITIALISE
|
||
|
Initialise();
|
||
|
}
|
||
|
|
||
|
int checkChance = m_random.GetRanged(0, 10000);
|
||
|
if(checkChance > 200) // Increase this to increase the chance of a check
|
||
|
return true; // No checking done
|
||
|
|
||
|
static portcullisWorkItem checkItem;
|
||
|
static int failCounter = 0;
|
||
|
|
||
|
// If a check has been done then see whether it has been successful
|
||
|
if(checkItem.CheckDone())
|
||
|
{
|
||
|
//@@: range PORTCULLIS_DOCHECK_CHECK_SUCCESSFUL {
|
||
|
if(!checkItem.CheckSuccessful())
|
||
|
{
|
||
|
++failCounter;
|
||
|
//@@: location PORTCULLIS_DOCHECK_CHECK_FAIL_COUNTER
|
||
|
if(failCounter > m_failTolerance)
|
||
|
return false; // Had a number of failures so return false
|
||
|
else
|
||
|
{
|
||
|
//MessageBoxA(NULL, "Portcullis check failed...", "Portcullis", MB_OK|MB_SETFOREGROUND|MB_TASKMODAL);
|
||
|
return true; // Pass for now...
|
||
|
}
|
||
|
}
|
||
|
|
||
|
failCounter = 0;
|
||
|
return true; // Check was successful so return true
|
||
|
//@@: } PORTCULLIS_DOCHECK_CHECK_SUCCESSFUL
|
||
|
}
|
||
|
|
||
|
|
||
|
// No check has been done recently so kick off a new one
|
||
|
if(!checkItem.CheckStarted())
|
||
|
{
|
||
|
//@@: range PORTCULLIS_DOCHECK_CHECK_2 {
|
||
|
checkChance = m_random.GetRanged(0, 10000);
|
||
|
if(checkChance > 9975) // Decrease this to increase the chance of a check
|
||
|
{
|
||
|
//@@: location PORTCULLIS_DOCHECK_QUEUE_WORK
|
||
|
checkItem.Started();
|
||
|
netThreadPool.QueueWork(&checkItem);
|
||
|
}
|
||
|
//@@: } PORTCULLIS_DOCHECK_CHECK_2
|
||
|
}
|
||
|
|
||
|
return true; // Nothing to report...
|
||
|
}
|
||
|
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////
|
||
|
void portcullis::Shutdown()
|
||
|
{
|
||
|
//@@: location PORTCULLIS_SHUTDOWN_ENTRY
|
||
|
if(!m_initialised)
|
||
|
return;
|
||
|
|
||
|
#if SINGLE_THREAD_PORTCULLIS
|
||
|
// Signal to close the thread and kick off the thread for a final spin
|
||
|
if(m_threadID != sysIpcThreadIdInvalid)
|
||
|
{
|
||
|
m_closeThread = true;
|
||
|
sysIpcSignalSema(m_triggerCheck);
|
||
|
|
||
|
sysIpcWaitSema(m_threadClosed);
|
||
|
|
||
|
sysIpcWaitThreadExit(m_threadID);
|
||
|
}
|
||
|
#endif // SINGLE_THREAD_PORTCULLIS
|
||
|
|
||
|
#if __WIN32PC
|
||
|
Portcullis::Shutdown();
|
||
|
#endif // __WIN32PC
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
#endif // PORTCULLIS_ENABLE
|