2022-05-20 11:52:19 +02:00
|
|
|
//=============================================================================//
|
|
|
|
//
|
|
|
|
// Purpose:
|
|
|
|
//
|
|
|
|
// $NoKeywords: $
|
|
|
|
//
|
|
|
|
//=============================================================================//
|
|
|
|
// server.cpp: implementation of the CServer class.
|
|
|
|
//
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "core/stdafx.h"
|
|
|
|
#include "common/protocol.h"
|
|
|
|
#include "tier1/cvar.h"
|
|
|
|
#include "engine/server/sv_main.h"
|
|
|
|
#include "engine/server/server.h"
|
2022-07-01 10:29:27 +02:00
|
|
|
#include "networksystem/pylon.h"
|
2022-08-09 17:34:10 +02:00
|
|
|
#include "networksystem/bansystem.h"
|
2023-03-31 22:37:53 +02:00
|
|
|
#include "ebisusdk/EbisuSDK.h"
|
2022-08-09 17:18:07 +02:00
|
|
|
#include "public/edict.h"
|
2022-05-20 11:52:19 +02:00
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
// Purpose: Gets the number of human players on the server
|
|
|
|
// Output : int
|
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
int CServer::GetNumHumanPlayers(void) const
|
|
|
|
{
|
|
|
|
int nHumans = 0;
|
|
|
|
for (int i = 0; i < g_ServerGlobalVariables->m_nMaxClients; i++)
|
|
|
|
{
|
|
|
|
CClient* pClient = g_pClient->GetClient(i);
|
|
|
|
if (!pClient)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (pClient->IsHumanPlayer())
|
|
|
|
nHumans++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nHumans;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
// Purpose: Gets the number of fake clients on the server
|
|
|
|
// Output : int
|
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
int CServer::GetNumFakeClients(void) const
|
|
|
|
{
|
|
|
|
int nBots = 0;
|
|
|
|
for (int i = 0; i < g_ServerGlobalVariables->m_nMaxClients; i++)
|
|
|
|
{
|
|
|
|
CClient* pClient = g_pClient->GetClient(i);
|
|
|
|
if (!pClient)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (pClient->IsConnected() && pClient->IsFakeClient())
|
|
|
|
nBots++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nBots;
|
2023-02-12 15:20:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
// Purpose: Gets the number of clients on the server
|
|
|
|
// Output : int
|
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
int CServer::GetNumClients(void) const
|
|
|
|
{
|
|
|
|
int nClients = 0;
|
|
|
|
for (int i = 0; i < g_ServerGlobalVariables->m_nMaxClients; i++)
|
|
|
|
{
|
|
|
|
CClient* pClient = g_pClient->GetClient(i);
|
|
|
|
if (!pClient)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (pClient->IsConnected())
|
|
|
|
nClients++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nClients;
|
2022-05-20 11:52:19 +02:00
|
|
|
}
|
|
|
|
|
2022-05-20 20:14:39 +02:00
|
|
|
//---------------------------------------------------------------------------------
|
2022-05-20 11:52:19 +02:00
|
|
|
// Purpose: client to server authentication
|
2022-08-30 12:07:09 +02:00
|
|
|
// Input : *pChallenge -
|
|
|
|
// Output : true if user isn't banned, false otherwise
|
2022-05-20 20:14:39 +02:00
|
|
|
//---------------------------------------------------------------------------------
|
2022-08-30 12:07:09 +02:00
|
|
|
bool CServer::AuthClient(user_creds_s* pChallenge)
|
2022-05-20 11:52:19 +02:00
|
|
|
{
|
2022-11-03 02:38:49 +01:00
|
|
|
char* pUserID = pChallenge->m_pUserID;
|
|
|
|
uint64_t nNucleusID = pChallenge->m_nNucleusID;
|
|
|
|
|
2022-11-03 02:30:57 +01:00
|
|
|
char pszAddresBuffer[INET6_ADDRSTRLEN]; // Render the client's address.
|
2023-01-29 15:12:27 +01:00
|
|
|
pChallenge->m_nAddr.ToString(pszAddresBuffer, sizeof(pszAddresBuffer));
|
2022-11-03 02:30:57 +01:00
|
|
|
|
|
|
|
const bool bEnableLogging = sv_showconnecting->GetBool();
|
|
|
|
if (bEnableLogging)
|
2022-11-03 02:38:49 +01:00
|
|
|
DevMsg(eDLL_T::SERVER, "Processing connectionless challenge for '%s' ('%llu')\n", pszAddresBuffer, nNucleusID);
|
2022-11-03 02:30:57 +01:00
|
|
|
|
2023-03-31 22:37:53 +02:00
|
|
|
// Only proceed connection if the client's name is valid and UTF-8 encoded.
|
|
|
|
if (!pUserID || !pUserID[0] || !IsValidUTF8(pUserID) || !IsValidPersonaName(pUserID))
|
2022-11-03 02:30:57 +01:00
|
|
|
{
|
|
|
|
RejectConnection(m_Socket, &pChallenge->m_nAddr, "#Valve_Reject_Invalid_Name");
|
|
|
|
if (bEnableLogging)
|
2022-11-03 02:38:49 +01:00
|
|
|
Warning(eDLL_T::SERVER, "Connection rejected for '%s' ('%llu' has an invalid name!)\n", pszAddresBuffer, nNucleusID);
|
2022-11-03 02:30:57 +01:00
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2022-05-20 11:52:19 +02:00
|
|
|
|
2023-03-31 22:37:53 +02:00
|
|
|
if (g_pBanSystem->IsBanListValid())
|
2022-05-20 11:52:19 +02:00
|
|
|
{
|
2023-03-31 22:37:53 +02:00
|
|
|
if (g_pBanSystem->IsBanned(pszAddresBuffer, nNucleusID))
|
2022-05-20 11:52:19 +02:00
|
|
|
{
|
2023-03-31 22:37:53 +02:00
|
|
|
RejectConnection(m_Socket, &pChallenge->m_nAddr, "#Valve_Reject_Banned");
|
2022-11-03 02:30:57 +01:00
|
|
|
if (bEnableLogging)
|
2022-11-03 02:38:49 +01:00
|
|
|
Warning(eDLL_T::SERVER, "Connection rejected for '%s' ('%llu' is banned from this server!)\n", pszAddresBuffer, nNucleusID);
|
2022-06-15 11:59:37 +02:00
|
|
|
|
2022-08-30 12:07:09 +02:00
|
|
|
return false;
|
2022-05-20 11:52:19 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-26 21:20:11 +01:00
|
|
|
if (sv_globalBanlist->GetBool())
|
2022-05-20 11:52:19 +02:00
|
|
|
{
|
2022-11-03 02:38:49 +01:00
|
|
|
std::thread th(SV_IsClientBanned, string(pszAddresBuffer), nNucleusID);
|
2022-08-29 14:00:54 +02:00
|
|
|
th.detach();
|
2022-05-20 11:52:19 +02:00
|
|
|
}
|
|
|
|
|
2022-08-30 12:07:09 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------
|
2022-10-07 22:32:08 +02:00
|
|
|
// Purpose: Initializes a CSVClient for a new net connection. This will only be called
|
2022-08-30 12:07:09 +02:00
|
|
|
// once for a player each game, not once for each level change.
|
|
|
|
// Input : *pServer -
|
|
|
|
// *pInpacket -
|
|
|
|
// Output : pointer to client instance on success, nullptr on failure
|
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
CClient* CServer::ConnectClient(CServer* pServer, user_creds_s* pChallenge)
|
|
|
|
{
|
2022-11-03 02:30:57 +01:00
|
|
|
if (pServer->m_State < server_state_t::ss_active || !pServer->AuthClient(pChallenge))
|
|
|
|
return nullptr;
|
2022-08-30 12:07:09 +02:00
|
|
|
|
2022-11-03 02:30:57 +01:00
|
|
|
CClient* pClient = v_CServer_ConnectClient(pServer, pChallenge);
|
|
|
|
return pClient;
|
2022-08-30 12:07:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
// Purpose: Rejects connection request and sends back a message
|
2022-11-05 00:12:45 +01:00
|
|
|
// Input : iSocket -
|
2022-08-30 12:07:09 +02:00
|
|
|
// *pChallenge -
|
|
|
|
// *szMessage -
|
|
|
|
//---------------------------------------------------------------------------------
|
2023-01-29 15:12:27 +01:00
|
|
|
void CServer::RejectConnection(int iSocket, netadr_t* pNetAdr, const char* szMessage)
|
2022-08-30 12:07:09 +02:00
|
|
|
{
|
2022-11-03 02:30:57 +01:00
|
|
|
v_CServer_RejectConnection(this, iSocket, pNetAdr, szMessage);
|
2022-05-20 11:52:19 +02:00
|
|
|
}
|
|
|
|
|
2022-11-05 00:12:45 +01:00
|
|
|
//---------------------------------------------------------------------------------
|
2023-02-18 11:42:36 +01:00
|
|
|
// Purpose: Runs the server frame job
|
2022-11-05 00:12:45 +01:00
|
|
|
// Input : flFrameTime -
|
|
|
|
// bRunOverlays -
|
|
|
|
// bUniformSnapshotInterval -
|
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
void CServer::FrameJob(double flFrameTime, bool bRunOverlays, bool bUniformSnapshotInterval)
|
|
|
|
{
|
|
|
|
v_CServer_FrameJob(flFrameTime, bRunOverlays, bUniformSnapshotInterval);
|
|
|
|
}
|
|
|
|
|
2023-02-18 11:42:36 +01:00
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
// Purpose: Runs the server frame
|
|
|
|
// Input : *pServer -
|
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
void CServer::RunFrame(CServer* pServer)
|
|
|
|
{
|
|
|
|
v_CServer_RunFrame(pServer);
|
|
|
|
}
|
|
|
|
|
2022-05-20 11:52:19 +02:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2023-01-25 02:26:52 +01:00
|
|
|
void VServer::Attach() const
|
2022-05-20 11:52:19 +02:00
|
|
|
{
|
2023-02-18 11:42:36 +01:00
|
|
|
DetourAttach(&v_CServer_RunFrame, &CServer::RunFrame);
|
2023-01-25 02:26:52 +01:00
|
|
|
#if defined(GAMEDLL_S3)
|
2022-08-30 12:07:09 +02:00
|
|
|
DetourAttach((LPVOID*)&v_CServer_ConnectClient, &CServer::ConnectClient);
|
2022-11-05 00:12:45 +01:00
|
|
|
DetourAttach((LPVOID*)&v_CServer_FrameJob, &CServer::FrameJob);
|
2023-01-25 02:26:52 +01:00
|
|
|
#endif // !TODO: S1 and S2 CServer functions require work.
|
2022-05-20 11:52:19 +02:00
|
|
|
}
|
|
|
|
|
2023-01-25 02:26:52 +01:00
|
|
|
void VServer::Detach() const
|
2022-05-20 11:52:19 +02:00
|
|
|
{
|
2023-02-18 11:42:36 +01:00
|
|
|
DetourDetach(&v_CServer_RunFrame, &CServer::RunFrame);
|
2023-01-25 02:26:52 +01:00
|
|
|
#if defined(GAMEDLL_S3)
|
2022-08-30 12:07:09 +02:00
|
|
|
DetourDetach((LPVOID*)&v_CServer_ConnectClient, &CServer::ConnectClient);
|
2022-11-05 00:12:45 +01:00
|
|
|
DetourDetach((LPVOID*)&v_CServer_FrameJob, &CServer::FrameJob);
|
2023-01-25 02:26:52 +01:00
|
|
|
#endif // !TODO: S1 and S2 CServer functions require work.
|
2022-05-20 11:52:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2022-05-20 20:14:39 +02:00
|
|
|
CServer* g_pServer = nullptr;
|