2023-04-25 00:46:45 +02:00
|
|
|
//===========================================================================//
|
|
|
|
//
|
|
|
|
// Purpose:
|
|
|
|
//
|
|
|
|
//===========================================================================//
|
2022-05-20 11:52:19 +02:00
|
|
|
#include "core/stdafx.h"
|
2022-08-27 23:45:58 +02:00
|
|
|
#include "tier0/threadtools.h"
|
|
|
|
#include "tier0/frametask.h"
|
2023-04-25 00:46:45 +02:00
|
|
|
#include "tier1/cvar.h"
|
2022-05-20 11:52:19 +02:00
|
|
|
#include "engine/server/sv_main.h"
|
2023-04-28 23:47:58 +02:00
|
|
|
#include "engine/client/client.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-04-29 11:11:10 +01:00
|
|
|
#include "engine/client/client.h"
|
|
|
|
#include "server.h"
|
2022-05-20 11:52:19 +02:00
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Purpose: checks if particular client is banned on the comp server
|
|
|
|
//-----------------------------------------------------------------------------
|
2024-03-10 02:13:15 +01:00
|
|
|
void SV_CheckForBanAndDisconnect(CClient* const pClient, const string& svIPAddr,
|
2023-08-31 00:16:25 +02:00
|
|
|
const NucleusID_t nNucleusID, const string& svPersonaName, const int nPort)
|
2022-05-20 11:52:19 +02:00
|
|
|
{
|
2023-04-29 20:36:29 +02:00
|
|
|
Assert(pClient != nullptr);
|
|
|
|
|
2022-08-27 23:45:58 +02:00
|
|
|
string svError;
|
2024-03-10 02:13:15 +01:00
|
|
|
const bool bCompBanned = g_MasterServer.CheckForBan(svIPAddr, nNucleusID, svPersonaName, svError);
|
2022-06-14 20:56:55 +02:00
|
|
|
|
2022-05-20 11:52:19 +02:00
|
|
|
if (bCompBanned)
|
|
|
|
{
|
2024-03-10 02:13:15 +01:00
|
|
|
g_TaskQueue.Dispatch([pClient, svError, svIPAddr, nNucleusID, nPort]
|
|
|
|
{
|
|
|
|
// Make sure client isn't already disconnected,
|
|
|
|
// and that if there is a valid netchannel, that
|
|
|
|
// it hasn't been taken by a different client by
|
|
|
|
// the time this task is getting executed.
|
|
|
|
const CNetChan* const pChan = pClient->GetNetChan();
|
|
|
|
if (pChan && pClient->GetNucleusID() == nNucleusID)
|
2022-08-27 23:45:58 +02:00
|
|
|
{
|
2024-03-10 02:13:15 +01:00
|
|
|
const int nUserID = pClient->GetUserID();
|
|
|
|
|
|
|
|
pClient->Disconnect(Reputation_t::REP_MARK_BAD, svError.c_str());
|
|
|
|
Warning(eDLL_T::SERVER, "Removed client '[%s]:%i' from slot #%i ('%llu' is banned globally!)\n",
|
|
|
|
svIPAddr.c_str(), nPort, nUserID, nNucleusID);
|
|
|
|
}
|
|
|
|
}, 0);
|
2022-05-20 11:52:19 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-29 12:15:51 +02:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Purpose: checks if particular client is banned on the master server
|
|
|
|
//-----------------------------------------------------------------------------
|
2024-03-10 02:13:15 +01:00
|
|
|
void SV_ProcessBulkCheck(const CBanSystem::BannedList_t* const pBannedVec)
|
2023-04-28 23:47:58 +02:00
|
|
|
{
|
2024-03-10 02:13:15 +01:00
|
|
|
CBanSystem::BannedList_t* const outBannedVec = new CBanSystem::BannedList_t();
|
2024-01-21 21:29:23 +01:00
|
|
|
g_MasterServer.GetBannedList(*pBannedVec, *outBannedVec);
|
2023-08-31 00:16:25 +02:00
|
|
|
|
2024-03-10 02:13:15 +01:00
|
|
|
g_TaskQueue.Dispatch([outBannedVec]
|
|
|
|
{
|
|
|
|
SV_CheckClientsForBan(outBannedVec);
|
|
|
|
delete outBannedVec;
|
|
|
|
}, 0);
|
2023-04-28 23:47:58 +02:00
|
|
|
}
|
|
|
|
|
2023-04-29 12:15:51 +02:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Purpose: creates a snapshot of the currently connected clients
|
|
|
|
// Input : *pBannedVec - if passed, will check for bans and kick the clients
|
|
|
|
//-----------------------------------------------------------------------------
|
2024-03-10 02:13:15 +01:00
|
|
|
void SV_CheckClientsForBan(const CBanSystem::BannedList_t* const pBannedVec /*= nullptr*/)
|
2023-04-28 23:47:58 +02:00
|
|
|
{
|
2023-04-29 00:05:47 +02:00
|
|
|
Assert(ThreadInMainThread());
|
2024-03-10 02:13:15 +01:00
|
|
|
|
|
|
|
CBanSystem::BannedList_t* bannedVec = !pBannedVec
|
|
|
|
? new CBanSystem::BannedList_t
|
|
|
|
: nullptr;
|
2023-04-28 23:47:58 +02:00
|
|
|
|
2023-04-30 01:50:38 +02:00
|
|
|
for (int c = 0; c < g_ServerGlobalVariables->m_nMaxClients; c++) // Loop through all possible client instances.
|
2023-04-28 23:47:58 +02:00
|
|
|
{
|
2024-03-10 02:13:15 +01:00
|
|
|
CClient* const pClient = g_pServer->GetClient(c);
|
|
|
|
|
2023-04-28 23:47:58 +02:00
|
|
|
if (!pClient)
|
|
|
|
continue;
|
|
|
|
|
2024-03-10 02:13:15 +01:00
|
|
|
const CNetChan* const pNetChan = pClient->GetNetChan();
|
|
|
|
|
2023-04-28 23:47:58 +02:00
|
|
|
if (!pNetChan)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!pClient->IsConnected())
|
|
|
|
continue;
|
|
|
|
|
2023-04-30 11:31:05 +02:00
|
|
|
if (pNetChan->GetRemoteAddress().IsLoopback())
|
|
|
|
continue;
|
|
|
|
|
2024-03-10 02:13:15 +01:00
|
|
|
const char* const szIPAddr = pNetChan->GetAddress(true);
|
2023-08-31 00:16:25 +02:00
|
|
|
const NucleusID_t nNucleusID = pClient->GetNucleusID();
|
2023-04-28 23:47:58 +02:00
|
|
|
|
2023-06-18 17:08:05 +02:00
|
|
|
// If no banned list was provided, build one with all clients
|
|
|
|
// on the server. This will be used for bulk checking so live
|
|
|
|
// bans could be performed, as this function is called periodically.
|
2024-03-10 02:13:15 +01:00
|
|
|
if (bannedVec)
|
2023-08-31 00:16:25 +02:00
|
|
|
bannedVec->AddToTail(CBanSystem::Banned_t(szIPAddr, nNucleusID));
|
2023-04-28 23:47:58 +02:00
|
|
|
else
|
|
|
|
{
|
2023-06-18 17:08:05 +02:00
|
|
|
// Check if current client is within provided banned list, and
|
|
|
|
// prune if so...
|
2023-08-31 00:16:25 +02:00
|
|
|
FOR_EACH_VEC(*pBannedVec, i)
|
2023-04-28 23:47:58 +02:00
|
|
|
{
|
2023-08-31 00:16:25 +02:00
|
|
|
const CBanSystem::Banned_t& banned = (*pBannedVec)[i];
|
|
|
|
|
|
|
|
if (banned.m_NucleusID == pClient->GetNucleusID())
|
2023-04-28 23:47:58 +02:00
|
|
|
{
|
2023-04-30 01:29:54 +02:00
|
|
|
const int nUserID = pClient->GetUserID();
|
|
|
|
const int nPort = pNetChan->GetPort();
|
|
|
|
|
2023-08-31 00:16:25 +02:00
|
|
|
pClient->Disconnect(Reputation_t::REP_MARK_BAD, "%s", banned.m_Address.String());
|
2023-04-30 01:29:54 +02:00
|
|
|
Warning(eDLL_T::SERVER, "Removed client '[%s]:%i' from slot #%i ('%llu' is banned globally!)\n",
|
|
|
|
szIPAddr, nPort, nUserID, nNucleusID);
|
2023-04-28 23:47:58 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-10 02:13:15 +01:00
|
|
|
if (bannedVec && !bannedVec->IsEmpty())
|
2023-08-31 00:16:25 +02:00
|
|
|
{
|
2024-03-10 02:13:15 +01:00
|
|
|
std::thread bulkCheck([bannedVec]()
|
|
|
|
{
|
|
|
|
SV_ProcessBulkCheck(bannedVec);
|
|
|
|
delete bannedVec;
|
|
|
|
});
|
2023-08-31 00:16:25 +02:00
|
|
|
|
2024-03-10 02:13:15 +01:00
|
|
|
bulkCheck.detach();
|
2023-08-31 00:16:25 +02:00
|
|
|
}
|
2024-03-10 02:13:15 +01:00
|
|
|
else if (bannedVec)
|
2023-04-28 23:47:58 +02:00
|
|
|
{
|
2023-08-31 00:16:25 +02:00
|
|
|
delete bannedVec;
|
2024-03-10 02:13:15 +01:00
|
|
|
bannedVec = nullptr;
|
2022-05-20 11:52:19 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-25 00:46:45 +02:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Purpose: loads the game .dll
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void SV_InitGameDLL()
|
|
|
|
{
|
|
|
|
v_SV_InitGameDLL();
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Purpose: release resources associated with extension DLLs.
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void SV_ShutdownGameDLL()
|
|
|
|
{
|
|
|
|
v_SV_ShutdownGameDLL();
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Purpose: activates the server
|
|
|
|
// Output : true on success, false on failure
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool SV_ActivateServer()
|
|
|
|
{
|
|
|
|
return v_SV_ActivateServer();
|
|
|
|
}
|
|
|
|
|
2024-03-10 02:13:15 +01:00
|
|
|
void SV_BroadcastVoiceData(CClient* const cl, const int nBytes, char* const data)
|
2023-04-29 11:11:10 +01:00
|
|
|
{
|
|
|
|
if (!sv_voiceenable->GetBool())
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (g_ServerGlobalVariables->m_nMaxClients <= 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
SVC_VoiceData voiceData(cl->GetUserID(), nBytes, data);
|
|
|
|
|
|
|
|
for (int i = 0; i < g_ServerGlobalVariables->m_nMaxClients; i++)
|
|
|
|
{
|
2023-07-12 08:56:17 +02:00
|
|
|
CClient* pClient = g_pServer->GetClient(i);
|
2023-04-29 11:11:10 +01:00
|
|
|
|
|
|
|
if (!pClient)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// is this client fully connected
|
|
|
|
if (pClient->GetSignonState() != SIGNONSTATE::SIGNONSTATE_FULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// is this client the sender
|
|
|
|
if (pClient == cl && !sv_voiceEcho->GetBool())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// is this client on the sender's team
|
|
|
|
if (pClient->GetTeamNum() != cl->GetTeamNum() && !sv_alltalk->GetBool())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// there's also supposed to be some xplat checks here
|
|
|
|
// but since r5r is only on PC, there's no point in implementing them here
|
|
|
|
|
|
|
|
CNetChan* pNetChan = pClient->GetNetChan();
|
|
|
|
|
|
|
|
if (!pNetChan)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// if voice stream has enough space for new data
|
|
|
|
if (pNetChan->GetStreamVoice().GetNumBitsLeft() >= 8 * nBytes + 96)
|
2023-05-30 23:01:46 +02:00
|
|
|
pClient->SendNetMsgEx(&voiceData, false, false, true);
|
2023-04-29 11:11:10 +01:00
|
|
|
}
|
|
|
|
}
|