2022-05-20 11:52:19 +02:00
|
|
|
//=============================================================================//
|
2021-12-25 22:36:38 +01:00
|
|
|
//
|
2022-05-20 11:52:19 +02:00
|
|
|
// Purpose:
|
2021-12-25 22:36:38 +01:00
|
|
|
//
|
2022-05-20 11:52:19 +02:00
|
|
|
// $NoKeywords: $
|
|
|
|
//
|
|
|
|
//=============================================================================//
|
|
|
|
// clientstate.cpp: implementation of the CClientState class.
|
|
|
|
//
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////
|
2021-12-25 22:36:38 +01:00
|
|
|
#include "core/stdafx.h"
|
2024-05-07 14:44:12 +02:00
|
|
|
#include "mathlib/bitvec.h"
|
2023-06-18 17:10:57 +02:00
|
|
|
#include "tier0/frametask.h"
|
2023-10-22 17:00:56 +02:00
|
|
|
#include "engine/common.h"
|
2022-08-18 02:15:23 +02:00
|
|
|
#include "engine/host.h"
|
2024-02-19 20:43:22 +01:00
|
|
|
#include "engine/host_cmd.h"
|
2023-11-25 17:41:08 +01:00
|
|
|
#ifndef CLIENT_DLL
|
|
|
|
#include "engine/server/server.h"
|
|
|
|
#endif // !CLIENT_DLL
|
2023-05-10 00:05:38 +02:00
|
|
|
#include "clientstate.h"
|
2023-06-18 17:10:57 +02:00
|
|
|
#include "common/callback.h"
|
2023-05-10 00:05:38 +02:00
|
|
|
#include "cdll_engine_int.h"
|
2023-06-03 18:06:35 +02:00
|
|
|
#include "vgui/vgui_baseui_interface.h"
|
2024-04-05 17:42:05 +02:00
|
|
|
#include "rtech/playlists/playlists.h"
|
2023-10-15 10:40:46 +02:00
|
|
|
#include <ebisusdk/EbisuSDK.h>
|
2023-11-25 17:41:08 +01:00
|
|
|
#include <engine/cmd.h>
|
2022-01-04 11:53:54 +01:00
|
|
|
|
2024-05-17 11:12:57 +02:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// Purpose: console command callbacks
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
static void SetName_f(const CCommand& args)
|
|
|
|
{
|
|
|
|
if (args.ArgC() < 2)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!IsOriginDisabled())
|
|
|
|
return;
|
|
|
|
|
|
|
|
const char* pszName = args.Arg(1);
|
|
|
|
|
|
|
|
if (!pszName[0])
|
|
|
|
pszName = "unnamed";
|
|
|
|
|
|
|
|
const size_t nLen = strlen(pszName);
|
|
|
|
|
|
|
|
if (nLen > MAX_PERSONA_NAME_LEN)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Update nucleus name.
|
|
|
|
memset(g_PersonaName, '\0', MAX_PERSONA_NAME_LEN);
|
|
|
|
strncpy(g_PersonaName, pszName, nLen);
|
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// Purpose: console commands
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
static ConCommand cl_setname("cl_setname", SetName_f, "Sets the client's persona name", FCVAR_RELEASE);
|
2022-01-04 11:53:54 +01:00
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// Purpose: returns true if client simulation is paused
|
|
|
|
//------------------------------------------------------------------------------
|
2022-10-29 00:01:10 +02:00
|
|
|
bool CClientState::IsPaused() const
|
2022-01-04 11:53:54 +01:00
|
|
|
{
|
2023-06-03 18:06:35 +02:00
|
|
|
return m_bPaused || !*host_initialized || g_pEngineVGui->ShouldPause();
|
2022-01-04 11:53:54 +01:00
|
|
|
}
|
|
|
|
|
2022-11-10 11:47:02 +01:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// Purpose: returns true if client is fully connected and active
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
bool CClientState::IsActive(void) const
|
|
|
|
{
|
|
|
|
return m_nSignonState == SIGNONSTATE::SIGNONSTATE_FULL;
|
|
|
|
};
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// Purpose: returns true if client connected but not active
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
bool CClientState::IsConnected(void) const
|
|
|
|
{
|
|
|
|
return m_nSignonState >= SIGNONSTATE::SIGNONSTATE_CONNECTED;
|
|
|
|
};
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// Purpose: returns true if client is still connecting
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
bool CClientState::IsConnecting(void) const
|
|
|
|
{
|
|
|
|
return m_nSignonState >= SIGNONSTATE::SIGNONSTATE_NONE;
|
|
|
|
}
|
|
|
|
|
2022-01-04 11:53:54 +01:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// Purpose: gets the client time
|
2022-02-19 02:31:16 +01:00
|
|
|
// Technically doesn't belong here
|
2022-01-04 11:53:54 +01:00
|
|
|
//------------------------------------------------------------------------------
|
2022-10-29 00:01:10 +02:00
|
|
|
float CClientState::GetClientTime() const
|
2022-01-04 11:53:54 +01:00
|
|
|
{
|
2022-08-18 02:15:23 +02:00
|
|
|
if (m_bClockCorrectionEnabled)
|
2022-01-04 11:53:54 +01:00
|
|
|
{
|
2023-09-17 16:44:18 +02:00
|
|
|
return (float)m_ClockDriftMgr.m_nSimulationTick * g_pCommonHostState->interval_per_tick;
|
2022-01-04 11:53:54 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-08-18 11:35:32 +02:00
|
|
|
return m_flClockDriftFrameTime;
|
2022-01-04 11:53:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
2022-07-03 11:03:25 +02:00
|
|
|
// Purpose: gets the simulation tick count
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
int CClientState::GetTick() const
|
|
|
|
{
|
|
|
|
return m_ClockDriftMgr.m_nSimulationTick;
|
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// Purpose: gets the last-received server tick count
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
int CClientState::GetServerTickCount() const
|
|
|
|
{
|
|
|
|
return m_ClockDriftMgr.m_nServerTick;
|
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// Purpose: sets the server tick count
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
void CClientState::SetServerTickCount(int tick)
|
|
|
|
{
|
|
|
|
m_ClockDriftMgr.m_nServerTick = tick;
|
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// Purpose: gets the client tick count
|
2022-01-04 11:53:54 +01:00
|
|
|
//------------------------------------------------------------------------------
|
2022-05-20 11:52:19 +02:00
|
|
|
int CClientState::GetClientTickCount() const
|
2022-01-04 11:53:54 +01:00
|
|
|
{
|
2022-05-20 20:14:39 +02:00
|
|
|
return m_ClockDriftMgr.m_nClientTick;
|
2022-01-04 11:53:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
2022-07-03 11:03:25 +02:00
|
|
|
// Purpose: sets the client tick count
|
2022-01-04 11:53:54 +01:00
|
|
|
//------------------------------------------------------------------------------
|
2022-05-20 11:52:19 +02:00
|
|
|
void CClientState::SetClientTickCount(int tick)
|
2022-01-04 11:53:54 +01:00
|
|
|
{
|
2022-05-20 20:14:39 +02:00
|
|
|
m_ClockDriftMgr.m_nClientTick = tick;
|
2022-01-04 11:53:54 +01:00
|
|
|
}
|
|
|
|
|
2023-06-03 18:06:35 +02:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// Purpose: gets the client frame time
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
float CClientState::GetFrameTime() const
|
|
|
|
{
|
|
|
|
if (IsPaused())
|
|
|
|
{
|
|
|
|
return 0.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
return m_flFrameTime;
|
|
|
|
}
|
|
|
|
|
2023-02-18 00:31:57 +01:00
|
|
|
//------------------------------------------------------------------------------
|
2023-06-18 17:10:57 +02:00
|
|
|
// Purpose: called when connection to the server has been closed
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
void CClientState::VConnectionClosing(CClientState* thisptr, const char* szReason)
|
|
|
|
{
|
|
|
|
CClientState__ConnectionClosing(thisptr, szReason);
|
|
|
|
|
|
|
|
// Delay execution to the next frame; this is required to avoid a rare crash.
|
|
|
|
// Cannot reload playlists while still disconnecting.
|
2024-02-28 00:43:57 +01:00
|
|
|
g_TaskQueue.Dispatch([]()
|
2023-06-18 17:10:57 +02:00
|
|
|
{
|
|
|
|
// Reload the local playlist to override the cached
|
|
|
|
// one from the server we got disconnected from.
|
2024-02-23 00:12:06 +01:00
|
|
|
v_Playlists_Download_f();
|
2024-04-05 17:42:05 +02:00
|
|
|
Playlists_SDKInit();
|
2023-06-18 17:10:57 +02:00
|
|
|
}, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// Purpose: called when a SVC_ServerTick messages comes in.
|
|
|
|
// This function has an additional check for the command tick against '-1',
|
|
|
|
// if it is '-1', we process statistics only. This is required as the game
|
|
|
|
// no longer can process server ticks every frame unlike previous games.
|
|
|
|
// Without this, the server CPU and frame time don't get updated to the client.
|
2023-02-18 00:31:57 +01:00
|
|
|
//------------------------------------------------------------------------------
|
2023-11-25 17:41:08 +01:00
|
|
|
bool CClientState::VProcessServerTick(CClientState* thisptr, SVC_ServerTick* msg)
|
2023-02-18 00:31:57 +01:00
|
|
|
{
|
2023-11-25 17:41:08 +01:00
|
|
|
if (msg->m_NetTick.m_nCommandTick != -1)
|
2023-02-18 00:31:57 +01:00
|
|
|
{
|
2024-02-06 14:42:36 +01:00
|
|
|
// Updates statistics and updates clockdrift.
|
2023-11-25 17:41:08 +01:00
|
|
|
return CClientState__ProcessServerTick(thisptr, msg);
|
2023-02-18 00:31:57 +01:00
|
|
|
}
|
|
|
|
else // Statistics only.
|
|
|
|
{
|
2023-11-25 17:41:08 +01:00
|
|
|
CClientState* const thisptr_ADJ = thisptr->GetShiftedBasePointer();
|
2023-02-18 00:31:57 +01:00
|
|
|
|
2024-02-06 14:42:36 +01:00
|
|
|
if (thisptr_ADJ->IsConnected())
|
|
|
|
{
|
|
|
|
CNetChan* const pChan = thisptr_ADJ->m_NetChannel;
|
|
|
|
|
|
|
|
pChan->SetRemoteFramerate(msg->m_NetTick.m_flHostFrameTime, msg->m_NetTick.m_flHostFrameTimeStdDeviation);
|
|
|
|
pChan->SetRemoteCPUStatistics(msg->m_NetTick.m_nServerCPU);
|
|
|
|
}
|
2023-02-18 00:31:57 +01:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-19 20:43:22 +01:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// Purpose: processes string commands sent from server
|
|
|
|
// Input : *thisptr -
|
|
|
|
// *msg -
|
|
|
|
// Output : true on success, false otherwise
|
|
|
|
//------------------------------------------------------------------------------
|
2023-11-25 17:41:08 +01:00
|
|
|
bool CClientState::_ProcessStringCmd(CClientState* thisptr, NET_StringCmd* msg)
|
|
|
|
{
|
|
|
|
CClientState* const thisptr_ADJ = thisptr->GetShiftedBasePointer();
|
|
|
|
|
|
|
|
if (thisptr_ADJ->m_bRestrictServerCommands
|
2023-11-26 13:21:20 +01:00
|
|
|
#ifndef CLIENT_DLL
|
2023-11-25 17:41:08 +01:00
|
|
|
&& !g_pServer->IsActive()
|
|
|
|
#endif // !CLIENT_DLL
|
|
|
|
)
|
|
|
|
{
|
|
|
|
CCommand args;
|
|
|
|
args.Tokenize(msg->cmd, cmd_source_t::kCommandSrcInvalid);
|
|
|
|
|
|
|
|
if (args.ArgC() > 0)
|
|
|
|
{
|
|
|
|
if (!Cbuf_AddTextWithMarkers(msg->cmd,
|
|
|
|
eCmdExecutionMarker_Enable_FCVAR_SERVER_CAN_EXECUTE,
|
|
|
|
eCmdExecutionMarker_Disable_FCVAR_SERVER_CAN_EXECUTE))
|
|
|
|
{
|
|
|
|
DevWarning(eDLL_T::CLIENT, "%s: No room for %i execution markers; command \"%s\" ignored\n",
|
|
|
|
__FUNCTION__, 2, msg->cmd);
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Cbuf_AddText(Cbuf_GetCurrentPlayer(), msg->cmd, cmd_source_t::kCommandSrcCode);
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2024-02-19 20:43:22 +01:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// Purpose: create's string tables from string table data sent from server
|
|
|
|
// Input : *thisptr -
|
|
|
|
// *msg -
|
|
|
|
// Output : true on success, false otherwise
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
bool CClientState::_ProcessCreateStringTable(CClientState* thisptr, SVC_CreateStringTable* msg)
|
|
|
|
{
|
|
|
|
CClientState* const cl = thisptr->GetShiftedBasePointer();
|
|
|
|
|
|
|
|
if (!cl->IsConnected())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
CNetworkStringTableContainer* const container = cl->m_StringTableContainer;
|
|
|
|
|
|
|
|
// Must have a string table container at this point!
|
|
|
|
if (!container)
|
|
|
|
{
|
|
|
|
Assert(0);
|
|
|
|
|
|
|
|
COM_ExplainDisconnection(true, "String table container missing.\n");
|
|
|
|
v_Host_Disconnect(true);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
container->AllowCreation(true);
|
|
|
|
const ssize_t startbit = msg->m_DataIn.GetNumBitsRead();
|
|
|
|
|
|
|
|
CNetworkStringTable* const table = (CNetworkStringTable*)container->CreateStringTable(false, msg->m_szTableName,
|
|
|
|
msg->m_nMaxEntries, msg->m_nUserDataSize, msg->m_nUserDataSizeBits, msg->m_nDictFlags);
|
|
|
|
|
|
|
|
table->SetTick(cl->GetServerTickCount());
|
|
|
|
CClientState__HookClientStringTable(cl, msg->m_szTableName);
|
|
|
|
|
|
|
|
if (msg->m_bDataCompressed)
|
|
|
|
{
|
|
|
|
// TODO[ AMOS ]: check sizes before proceeding to decode
|
|
|
|
// the string tables
|
|
|
|
unsigned int msgUncompressedSize = msg->m_DataIn.ReadLong();
|
|
|
|
unsigned int msgCompressedSize = msg->m_DataIn.ReadLong();
|
|
|
|
|
|
|
|
size_t uncompressedSize = msgUncompressedSize;
|
|
|
|
size_t compressedSize = msgCompressedSize;
|
|
|
|
|
|
|
|
bool bSuccess = false;
|
|
|
|
|
|
|
|
// TODO[ AMOS ]: this could do better. The engine does UINT_MAX-3
|
|
|
|
// which doesn't look very great. Clamp to more reasonable values
|
|
|
|
// than UINT_MAX-3 or UINT_MAX/2? The largest string tables sent
|
|
|
|
// are settings layout string tables which are roughly 256KiB
|
|
|
|
// compressed with LZSS. perhaps clamp this to something like 16MiB?
|
|
|
|
if (msg->m_DataIn.TotalBytesAvailable() > 0 &&
|
|
|
|
msgCompressedSize <= (unsigned int)msg->m_DataIn.TotalBytesAvailable() &&
|
|
|
|
msgCompressedSize < UINT_MAX / 2 && msgUncompressedSize < UINT_MAX / 2)
|
|
|
|
{
|
|
|
|
// allocate buffer for uncompressed data, align to 4 bytes boundary
|
|
|
|
uint8_t* const uncompressedBuffer = new uint8_t[PAD_NUMBER(msgUncompressedSize, 4)];
|
|
|
|
uint8_t* const compressedBuffer = new uint8_t[PAD_NUMBER(msgCompressedSize, 4)];
|
|
|
|
|
|
|
|
msg->m_DataIn.ReadBytes(compressedBuffer, msgCompressedSize);
|
|
|
|
|
|
|
|
// uncompress data
|
|
|
|
bSuccess = NET_BufferToBufferDecompress(compressedBuffer, compressedSize, uncompressedBuffer, uncompressedSize);
|
|
|
|
bSuccess &= (uncompressedSize == msgUncompressedSize);
|
|
|
|
|
|
|
|
if (bSuccess)
|
|
|
|
{
|
|
|
|
bf_read data(uncompressedBuffer, (int)uncompressedSize);
|
|
|
|
table->ParseUpdate(data, msg->m_nNumEntries);
|
|
|
|
}
|
|
|
|
|
|
|
|
delete[] uncompressedBuffer;
|
|
|
|
delete[] compressedBuffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!bSuccess)
|
|
|
|
{
|
|
|
|
Assert(false);
|
|
|
|
DevWarning(eDLL_T::CLIENT, "%s: Received malformed string table message!\n", __FUNCTION__);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
table->ParseUpdate(msg->m_DataIn, msg->m_nNumEntries);
|
|
|
|
}
|
|
|
|
|
|
|
|
container->AllowCreation(false);
|
|
|
|
const ssize_t endbit = msg->m_DataIn.GetNumBitsRead();
|
|
|
|
|
|
|
|
return (endbit - startbit) == msg->m_nLength;
|
|
|
|
}
|
|
|
|
|
2024-05-07 14:44:12 +02:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// Purpose: processes user message data
|
|
|
|
// Input : *thisptr -
|
|
|
|
// *msg -
|
|
|
|
// Output : true on success, false otherwise
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
bool CClientState::_ProcessUserMessage(CClientState* thisptr, SVC_UserMessage* msg)
|
|
|
|
{
|
|
|
|
CClientState* const cl = thisptr->GetShiftedBasePointer();
|
|
|
|
|
|
|
|
if (!cl->IsConnected())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// buffer for incoming user message
|
|
|
|
ALIGN4 byte userdata[MAX_USER_MSG_DATA] ALIGN4_POST = { 0 };
|
|
|
|
bf_read userMsg("UserMessage(read)", userdata, sizeof(userdata));
|
|
|
|
|
|
|
|
int bitsRead = msg->m_DataIn.ReadBitsClamped(userdata, msg->m_nLength);
|
|
|
|
userMsg.StartReading(userdata, Bits2Bytes(bitsRead));
|
|
|
|
|
|
|
|
// dispatch message to client.dll
|
|
|
|
if (!g_pHLClient->DispatchUserMessage(msg->m_nMsgType, &userMsg))
|
|
|
|
{
|
|
|
|
Warning(eDLL_T::CLIENT, "Couldn't dispatch user message (%i)\n", msg->m_nMsgType);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2024-02-24 02:15:09 +01:00
|
|
|
static ConVar cl_onlineAuthEnable("cl_onlineAuthEnable", "1", FCVAR_RELEASE, "Enables the client-side online authentication system");
|
|
|
|
|
|
|
|
static ConVar cl_onlineAuthToken("cl_onlineAuthToken", "", FCVAR_HIDDEN | FCVAR_USERINFO | FCVAR_DONTRECORD | FCVAR_SERVER_CANNOT_QUERY | FCVAR_PLATFORM_SYSTEM, "The client's online authentication token");
|
|
|
|
static ConVar cl_onlineAuthTokenSignature1("cl_onlineAuthTokenSignature1", "", FCVAR_HIDDEN | FCVAR_USERINFO | FCVAR_DONTRECORD | FCVAR_SERVER_CANNOT_QUERY | FCVAR_PLATFORM_SYSTEM, "The client's online authentication token signature", false, 0.f, false, 0.f, "Primary");
|
|
|
|
static ConVar cl_onlineAuthTokenSignature2("cl_onlineAuthTokenSignature2", "", FCVAR_HIDDEN | FCVAR_USERINFO | FCVAR_DONTRECORD | FCVAR_SERVER_CANNOT_QUERY | FCVAR_PLATFORM_SYSTEM, "The client's online authentication token signature", false, 0.f, false, 0.f, "Secondary");
|
|
|
|
|
2023-10-20 19:30:07 +02:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// Purpose: get authentication token for current connection context
|
|
|
|
// Input : *connectParams -
|
2023-10-22 17:00:56 +02:00
|
|
|
// *reasonBuf -
|
|
|
|
// reasonBufLen -
|
2023-10-20 19:30:07 +02:00
|
|
|
// Output : true on success, false otherwise
|
|
|
|
//------------------------------------------------------------------------------
|
2023-10-22 17:00:56 +02:00
|
|
|
bool CClientState::Authenticate(connectparams_t* connectParams, char* const reasonBuf, const size_t reasonBufLen) const
|
2023-10-15 10:40:46 +02:00
|
|
|
{
|
2023-10-22 17:00:56 +02:00
|
|
|
#define FORMAT_ERROR_REASON(fmt, ...) V_snprintf(reasonBuf, reasonBufLen, fmt, ##__VA_ARGS__);
|
|
|
|
|
2023-10-15 10:40:46 +02:00
|
|
|
string msToken; // token returned by the masterserver authorising the client to play online
|
|
|
|
string message; // message returned by the masterserver about the result of the auth
|
|
|
|
|
|
|
|
// verify that the client is not lying about their account identity
|
|
|
|
// code is immediately discarded upon verification
|
|
|
|
|
2024-01-21 21:29:23 +01:00
|
|
|
const bool ret = g_MasterServer.AuthForConnection(*g_NucleusID, connectParams->netAdr, g_OriginAuthCode, msToken, message);
|
2023-10-15 10:40:46 +02:00
|
|
|
if (!ret)
|
|
|
|
{
|
2023-10-22 17:00:56 +02:00
|
|
|
FORMAT_ERROR_REASON("%s", message.c_str());
|
2023-10-15 10:40:46 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// get full token
|
|
|
|
const char* token = msToken.c_str();
|
|
|
|
|
|
|
|
// get a pointer to the delimiter that begins the token's signature
|
|
|
|
const char* tokenSignatureDelim = strrchr(token, '.');
|
|
|
|
|
|
|
|
if (!tokenSignatureDelim)
|
|
|
|
{
|
2023-10-22 17:00:56 +02:00
|
|
|
FORMAT_ERROR_REASON("Invalid token returned by MS");
|
2023-10-15 10:40:46 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// replace the delimiter with a null char so the first cvar only takes the header and payload data
|
|
|
|
*(char*)tokenSignatureDelim = '\0';
|
|
|
|
const size_t sigLength = strlen(tokenSignatureDelim) - 1;
|
|
|
|
|
2024-02-24 02:15:09 +01:00
|
|
|
cl_onlineAuthToken.SetValue(token);
|
2023-10-15 10:40:46 +02:00
|
|
|
|
|
|
|
if (sigLength > 0)
|
|
|
|
{
|
|
|
|
// get a pointer to the first part of the token signature to store in cl_onlineAuthTokenSignature1
|
|
|
|
const char* tokenSignaturePart1 = tokenSignatureDelim + 1;
|
|
|
|
|
2024-02-24 02:15:09 +01:00
|
|
|
cl_onlineAuthTokenSignature1.SetValue(tokenSignaturePart1);
|
2023-10-15 10:40:46 +02:00
|
|
|
|
|
|
|
if (sigLength > 255)
|
|
|
|
{
|
|
|
|
// get a pointer to the rest of the token signature to store in cl_onlineAuthTokenSignature2
|
|
|
|
const char* tokenSignaturePart2 = tokenSignaturePart1 + 255;
|
|
|
|
|
2024-02-24 02:15:09 +01:00
|
|
|
cl_onlineAuthTokenSignature2.SetValue(tokenSignaturePart2);
|
2023-10-15 10:40:46 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2023-10-22 17:00:56 +02:00
|
|
|
#undef REJECT_CONNECTION
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsLocalHost(connectparams_t* connectParams)
|
|
|
|
{
|
|
|
|
return (strstr(connectParams->netAdr, "localhost") || strstr(connectParams->netAdr, "127.0.0.1"));
|
2023-10-15 10:40:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void CClientState::VConnect(CClientState* thisptr, connectparams_t* connectParams)
|
|
|
|
{
|
2024-02-24 02:15:09 +01:00
|
|
|
if (cl_onlineAuthEnable.GetBool() && !IsLocalHost(connectParams))
|
2023-10-22 17:00:56 +02:00
|
|
|
{
|
|
|
|
char authFailReason[512];
|
|
|
|
|
|
|
|
if (!thisptr->Authenticate(connectParams, authFailReason, sizeof(authFailReason)))
|
|
|
|
{
|
|
|
|
COM_ExplainDisconnection(true, "Failed to authenticate for online play: %s", authFailReason);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2023-10-20 19:12:42 +02:00
|
|
|
|
2023-10-15 10:40:46 +02:00
|
|
|
CClientState__Connect(thisptr, connectParams);
|
|
|
|
}
|
|
|
|
|
2023-11-26 13:21:20 +01:00
|
|
|
void VClientState::Detour(const bool bAttach) const
|
2023-02-18 00:31:57 +01:00
|
|
|
{
|
2023-11-26 13:21:20 +01:00
|
|
|
DetourSetup(&CClientState__ConnectionClosing, &CClientState::VConnectionClosing, bAttach);
|
|
|
|
DetourSetup(&CClientState__ProcessStringCmd, &CClientState::_ProcessStringCmd, bAttach);
|
|
|
|
DetourSetup(&CClientState__ProcessServerTick, &CClientState::VProcessServerTick, bAttach);
|
2024-02-19 20:43:22 +01:00
|
|
|
DetourSetup(&CClientState__ProcessCreateStringTable, &CClientState::_ProcessCreateStringTable, bAttach);
|
2024-05-07 14:44:12 +02:00
|
|
|
DetourSetup(&CClientState__ProcessUserMessage, &CClientState::_ProcessUserMessage, bAttach);
|
2023-11-26 13:21:20 +01:00
|
|
|
DetourSetup(&CClientState__Connect, &CClientState::VConnect, bAttach);
|
2023-02-18 00:31:57 +01:00
|
|
|
}
|
|
|
|
|
2022-05-20 20:14:39 +02:00
|
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
|
|
CClientState* g_pClientState = nullptr;
|
2022-08-18 02:15:23 +02:00
|
|
|
CClientState** g_pClientState_Shifted = nullptr;
|