mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
Merge branch 'bulk_check' into indev
This commit is contained in:
commit
55aa254e6b
@ -250,6 +250,7 @@ void Winsock_Shutdown()
|
||||
}
|
||||
void QuerySystemInfo()
|
||||
{
|
||||
#ifndef DEDICATED
|
||||
for (int i = 0; ; i++)
|
||||
{
|
||||
DISPLAY_DEVICE dd = { sizeof(dd), {0} };
|
||||
@ -266,6 +267,7 @@ void QuerySystemInfo()
|
||||
spdlog::info("{:25s}: '{:s}'\n", "GPU model identifier", szDeviceName);
|
||||
}
|
||||
}
|
||||
#endif // !DEDICATED
|
||||
|
||||
const CPUInformation& pi = GetCPUInformation();
|
||||
|
||||
|
@ -10,7 +10,7 @@ void HEbisuSDK_Init()
|
||||
#ifdef DEDICATED
|
||||
*g_EbisuSDKInit = true; // <- 1st EbisuSDK
|
||||
*g_EbisuProfileInit = true; // <- 2nd EbisuSDK
|
||||
*g_NucleusID = true; // <- 3rd EbisuSDK
|
||||
*g_NucleusID = 9990000; // <- 3rd EbisuSDK
|
||||
#endif // DEDICATED
|
||||
}
|
||||
|
||||
|
@ -268,9 +268,10 @@ void CHostState::Think(void) const
|
||||
|
||||
statsTimer.Start();
|
||||
}
|
||||
if (banListTimer.GetDurationInProgress().GetSeconds() > sv_banlistRefreshRate->GetDouble())
|
||||
if (sv_globalBanlist->GetBool() &&
|
||||
banListTimer.GetDurationInProgress().GetSeconds() > sv_banlistRefreshRate->GetDouble())
|
||||
{
|
||||
g_pBanSystem->BanListCheck();
|
||||
SV_CheckForBan();
|
||||
banListTimer.Start();
|
||||
}
|
||||
#ifdef DEDICATED
|
||||
|
@ -80,12 +80,17 @@ int CServer::GetNumClients(void) const
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
// Purpose: client to server authentication
|
||||
// Input : *pChallenge -
|
||||
// Output : true if user isn't banned, false otherwise
|
||||
// Purpose: Initializes a CSVClient for a new net connection. This will only be called
|
||||
// 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
|
||||
//---------------------------------------------------------------------------------
|
||||
bool CServer::AuthClient(user_creds_s* pChallenge)
|
||||
CClient* CServer::ConnectClient(CServer* pServer, user_creds_s* pChallenge)
|
||||
{
|
||||
if (pServer->m_State < server_state_t::ss_active)
|
||||
return nullptr;
|
||||
|
||||
char* pszPersonaName = pChallenge->personaName;
|
||||
uint64_t nNucleusID = pChallenge->personaId;
|
||||
|
||||
@ -99,46 +104,25 @@ bool CServer::AuthClient(user_creds_s* pChallenge)
|
||||
// Only proceed connection if the client's name is valid and UTF-8 encoded.
|
||||
if (!VALID_CHARSTAR(pszPersonaName) || !IsValidUTF8(pszPersonaName) || !IsValidPersonaName(pszPersonaName))
|
||||
{
|
||||
RejectConnection(m_Socket, &pChallenge->netAdr, "#Valve_Reject_Invalid_Name");
|
||||
pServer->RejectConnection(pServer->m_Socket, &pChallenge->netAdr, "#Valve_Reject_Invalid_Name");
|
||||
if (bEnableLogging)
|
||||
Warning(eDLL_T::SERVER, "Connection rejected for '%s' ('%llu' has an invalid name!)\n", pszAddresBuffer, nNucleusID);
|
||||
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (g_pBanSystem->IsBanListValid())
|
||||
{
|
||||
if (g_pBanSystem->IsBanned(pszAddresBuffer, nNucleusID))
|
||||
{
|
||||
RejectConnection(m_Socket, &pChallenge->netAdr, "#Valve_Reject_Banned");
|
||||
pServer->RejectConnection(pServer->m_Socket, &pChallenge->netAdr, "#Valve_Reject_Banned");
|
||||
if (bEnableLogging)
|
||||
Warning(eDLL_T::SERVER, "Connection rejected for '%s' ('%llu' is banned from this server!)\n", pszAddresBuffer, nNucleusID);
|
||||
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (sv_globalBanlist->GetBool())
|
||||
{
|
||||
std::thread th(SV_IsClientBanned, string(pszAddresBuffer), nNucleusID);
|
||||
th.detach();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
// Purpose: Initializes a CSVClient for a new net connection. This will only be called
|
||||
// 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)
|
||||
{
|
||||
if (pServer->m_State < server_state_t::ss_active || !pServer->AuthClient(pChallenge))
|
||||
return nullptr;
|
||||
|
||||
CClient* pClient = v_CServer_ConnectClient(pServer, pChallenge);
|
||||
|
||||
for (auto& callback : !g_pPluginSystem->GetConnectClientCallbacks())
|
||||
@ -147,6 +131,12 @@ CClient* CServer::ConnectClient(CServer* pServer, user_creds_s* pChallenge)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (pClient && sv_globalBanlist->GetBool())
|
||||
{
|
||||
std::thread th(SV_IsClientBanned, pClient, string(pszAddresBuffer), nNucleusID, string(pszPersonaName));
|
||||
th.detach();
|
||||
}
|
||||
|
||||
return pClient;
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,6 @@ public:
|
||||
bool IsActive(void) const { return m_State >= server_state_t::ss_active; }
|
||||
bool IsLoading(void) const { return m_State == server_state_t::ss_loading; }
|
||||
bool IsDedicated(void) const { return m_bIsDedicated; }
|
||||
bool AuthClient(user_creds_s* pChallenge);
|
||||
void RejectConnection(int iSocket, netadr_t* pNetAdr, const char* szMessage);
|
||||
static CClient* ConnectClient(CServer* pServer, user_creds_s* pChallenge);
|
||||
static void RunFrame(CServer* pServer);
|
||||
|
@ -1,7 +1,14 @@
|
||||
//===========================================================================//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//===========================================================================//
|
||||
#include "core/stdafx.h"
|
||||
#include "tier0/threadtools.h"
|
||||
#include "tier0/frametask.h"
|
||||
#include "tier1/cvar.h"
|
||||
#include "engine/server/sv_main.h"
|
||||
#include "engine/client/client.h"
|
||||
#include "networksystem/pylon.h"
|
||||
#include "networksystem/bansystem.h"
|
||||
#include "engine/client/client.h"
|
||||
@ -11,24 +18,124 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: checks if particular client is banned on the comp server
|
||||
//-----------------------------------------------------------------------------
|
||||
void SV_IsClientBanned(const string& svIPAddr, const uint64_t nNucleusID)
|
||||
void SV_IsClientBanned(CClient* pClient, const string& svIPAddr, const uint64_t nNucleusID, const string& svPersonaName)
|
||||
{
|
||||
string svError;
|
||||
Assert(pClient != nullptr);
|
||||
|
||||
string svError;
|
||||
bool bCompBanned = g_pMasterServer->CheckForBan(svIPAddr, nNucleusID, svPersonaName, svError);
|
||||
|
||||
bool bCompBanned = g_pMasterServer->CheckForBan(svIPAddr, nNucleusID, svError);
|
||||
if (bCompBanned)
|
||||
{
|
||||
if (!ThreadInMainThread())
|
||||
{
|
||||
g_TaskScheduler->Dispatch([svError, nNucleusID]
|
||||
g_TaskScheduler->Dispatch([pClient, svError, svIPAddr, nNucleusID]
|
||||
{
|
||||
g_pBanSystem->AddConnectionRefuse(svError, nNucleusID); // Add to the vector.
|
||||
// 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.
|
||||
CNetChan* pChan = pClient->GetNetChan();
|
||||
if (pChan && pClient->GetNucleusID() == nNucleusID)
|
||||
{
|
||||
pClient->Disconnect(Reputation_t::REP_MARK_BAD, svError.c_str());
|
||||
Warning(eDLL_T::SERVER, "Removed client '%s' ('%llu' is banned globally!)\n",
|
||||
svIPAddr.c_str(), nNucleusID);
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
Warning(eDLL_T::SERVER, "Added '%s' to refused list ('%llu' is banned from the master server!)\n", svIPAddr.c_str(), nNucleusID);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: checks if particular client is banned on the master server
|
||||
//-----------------------------------------------------------------------------
|
||||
void SV_ProcessBulkCheck(const BannedVec_t& bannedVec)
|
||||
{
|
||||
BannedVec_t outBannedVec;
|
||||
g_pMasterServer->GetBannedList(bannedVec, outBannedVec);
|
||||
|
||||
if (!ThreadInMainThread())
|
||||
{
|
||||
g_TaskScheduler->Dispatch([outBannedVec]
|
||||
{
|
||||
SV_CheckForBan(&outBannedVec);
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: creates a snapshot of the currently connected clients
|
||||
// Input : *pBannedVec - if passed, will check for bans and kick the clients
|
||||
//-----------------------------------------------------------------------------
|
||||
void SV_CheckForBan(const BannedVec_t* pBannedVec /*= nullptr*/)
|
||||
{
|
||||
Assert(ThreadInMainThread());
|
||||
BannedVec_t bannedVec;
|
||||
|
||||
for (int c = 0; c < MAX_PLAYERS; c++) // Loop through all possible client instances.
|
||||
{
|
||||
CClient* pClient = g_pClient->GetClient(c);
|
||||
if (!pClient)
|
||||
continue;
|
||||
|
||||
CNetChan* pNetChan = pClient->GetNetChan();
|
||||
if (!pNetChan)
|
||||
continue;
|
||||
|
||||
if (!pClient->IsConnected())
|
||||
continue;
|
||||
|
||||
const char* szIPAddr = pNetChan->GetAddress();
|
||||
const uint64_t nNucleusID = pClient->GetNucleusID();
|
||||
|
||||
if (!pBannedVec)
|
||||
bannedVec.push_back(std::make_pair(string(szIPAddr), nNucleusID));
|
||||
else
|
||||
{
|
||||
for (auto& it : *pBannedVec)
|
||||
{
|
||||
if (it.second == pClient->GetNucleusID())
|
||||
{
|
||||
pClient->Disconnect(Reputation_t::REP_MARK_BAD, "%s", it.first.c_str());
|
||||
Warning(eDLL_T::SERVER, "Removed client '%s' from slot '%i' ('%llu' is banned globally!)\n",
|
||||
szIPAddr, c, nNucleusID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!pBannedVec && !bannedVec.empty())
|
||||
{
|
||||
std::thread(&SV_ProcessBulkCheck, bannedVec).detach();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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();
|
||||
}
|
||||
|
||||
void SV_BroadcastVoiceData(CClient* cl, int nBytes, char* data)
|
||||
{
|
||||
if (!sv_voiceenable->GetBool())
|
||||
@ -73,15 +180,18 @@ void SV_BroadcastVoiceData(CClient* cl, int nBytes, char* data)
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void HSV_Main::Attach(void) const
|
||||
{
|
||||
//DetourAttach(&v_SV_InitGameDLL, SV_InitGameDLL);
|
||||
//DetourAttach(&v_SV_ShutdownGameDLL, SV_ShutdownGameDLL);
|
||||
//DetourAttach(&v_SV_ActivateServer, SV_ActivateServer);
|
||||
DetourAttach(&v_SV_BroadcastVoiceData, SV_BroadcastVoiceData);
|
||||
}
|
||||
|
||||
void HSV_Main::Detach(void) const
|
||||
{
|
||||
//DetourDetach(&v_SV_InitGameDLL, SV_InitGameDLL);
|
||||
//DetourDetach(&v_SV_ShutdownGameDLL, SV_ShutdownGameDLL);
|
||||
//DetourDetach(&v_SV_ActivateServer, SV_ActivateServer);
|
||||
DetourDetach(&v_SV_BroadcastVoiceData, SV_BroadcastVoiceData);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
@ -3,18 +3,22 @@
|
||||
#include "networksystem/bansystem.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class CClient;
|
||||
|
||||
class CClient;
|
||||
|
||||
/* ==== SV_MAIN ======================================================================================================================================================= */
|
||||
inline CMemory p_SV_InitGameDLL;
|
||||
inline auto SV_InitGameDLL = p_SV_InitGameDLL.RCast<void(*)(void)>();
|
||||
inline auto v_SV_InitGameDLL = p_SV_InitGameDLL.RCast<void(*)(void)>();
|
||||
|
||||
inline CMemory p_SV_ShutdownGameDLL;
|
||||
inline auto SV_ShutdownGameDLL = p_SV_ShutdownGameDLL.RCast<void(*)(void)>();
|
||||
inline auto v_SV_ShutdownGameDLL = p_SV_ShutdownGameDLL.RCast<void(*)(void)>();
|
||||
|
||||
inline CMemory p_SV_ActivateServer;
|
||||
inline auto v_SV_ActivateServer = p_SV_ActivateServer.RCast<bool(*)(void)>();
|
||||
|
||||
inline CMemory p_SV_CreateBaseline;
|
||||
inline auto SV_CreateBaseline = p_SV_CreateBaseline.RCast<bool(*)(void)>();
|
||||
inline auto v_SV_CreateBaseline = p_SV_CreateBaseline.RCast<bool(*)(void)>();
|
||||
|
||||
inline CMemory p_CGameServer__SpawnServer;
|
||||
inline auto CGameServer__SpawnServer = p_CGameServer__SpawnServer.RCast<bool(*)(void* thisptr, const char* pszMapName, const char* pszMapGroupName)>();
|
||||
@ -26,7 +30,11 @@ inline bool* s_bIsDedicated = nullptr;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void SV_IsClientBanned(const string& svIPAddr, const uint64_t nNucleusID);
|
||||
void SV_InitGameDLL();
|
||||
void SV_ShutdownGameDLL();
|
||||
bool SV_ActivateServer();
|
||||
void SV_IsClientBanned(CClient* pClient, const string& svIPAddr, const uint64_t nNucleusID, const string& svPersonaName);
|
||||
void SV_CheckForBan(const BannedVec_t* pBannedVec = nullptr);
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -37,6 +45,7 @@ class HSV_Main : public IDetour
|
||||
LogFunAdr("CGameServer::SpawnServer", p_CGameServer__SpawnServer.GetPtr());
|
||||
LogFunAdr("SV_InitGameDLL", p_SV_InitGameDLL.GetPtr());
|
||||
LogFunAdr("SV_ShutdownGameDLL", p_SV_ShutdownGameDLL.GetPtr());
|
||||
LogFunAdr("SV_ActivateServer", p_SV_ActivateServer.GetPtr());
|
||||
LogFunAdr("SV_CreateBaseline", p_SV_CreateBaseline.GetPtr());
|
||||
LogVarAdr("s_bIsDedicated", reinterpret_cast<uintptr_t>(s_bIsDedicated));
|
||||
}
|
||||
@ -44,6 +53,7 @@ class HSV_Main : public IDetour
|
||||
{
|
||||
p_SV_InitGameDLL = g_GameDll.FindPatternSIMD("48 81 EC ?? ?? ?? ?? E8 ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ?? 0F 85 ?? ?? ?? ??");
|
||||
p_SV_ShutdownGameDLL = g_GameDll.FindPatternSIMD("48 83 EC 28 80 3D ?? ?? ?? ?? ?? 0F 84 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? 48");
|
||||
p_SV_ActivateServer = g_GameDll.FindPatternSIMD("48 8B C4 56 48 81 EC ?? ?? ?? ?? 48 89 ?? ?? 48 8D");
|
||||
p_SV_CreateBaseline = g_GameDll.FindPatternSIMD("48 83 EC 28 48 8B 0D ?? ?? ?? ?? 48 85 C9 75 07");
|
||||
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1)
|
||||
p_CGameServer__SpawnServer = g_GameDll.FindPatternSIMD("40 53 55 56 57 41 55 41 56 41 57 48 81 EC ?? ?? ?? ??");
|
||||
@ -53,11 +63,13 @@ class HSV_Main : public IDetour
|
||||
#endif
|
||||
p_SV_BroadcastVoiceData = g_GameDll.FindPatternSIMD("4C 8B DC 56 48 81 EC ? ? ? ? 80 3D ? ? ? ? ? ");
|
||||
|
||||
SV_InitGameDLL = p_SV_InitGameDLL.RCast<void(*)(void)>();
|
||||
SV_ShutdownGameDLL = p_SV_ShutdownGameDLL.RCast<void(*)(void)>();
|
||||
SV_CreateBaseline = p_SV_CreateBaseline.RCast<bool(*)(void)>();
|
||||
CGameServer__SpawnServer = p_CGameServer__SpawnServer.RCast<bool(*)(void*, const char*, const char*)>();
|
||||
v_SV_InitGameDLL = p_SV_InitGameDLL.RCast<void(*)(void)>();
|
||||
v_SV_ShutdownGameDLL = p_SV_ShutdownGameDLL.RCast<void(*)(void)>();
|
||||
v_SV_ActivateServer = p_SV_ActivateServer.RCast<bool(*)(void)>();
|
||||
v_SV_CreateBaseline = p_SV_CreateBaseline.RCast<bool(*)(void)>();
|
||||
v_SV_BroadcastVoiceData = p_SV_BroadcastVoiceData.RCast<void(__fastcall*)(CClient* cl, int nBytes, char* data)>();
|
||||
|
||||
CGameServer__SpawnServer = p_CGameServer__SpawnServer.RCast<bool(*)(void*, const char*, const char*)>();
|
||||
}
|
||||
virtual void GetVar(void) const
|
||||
{
|
||||
|
@ -98,25 +98,27 @@ void CBanSystem::Save(void) const
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: adds a banned player entry to the banned list
|
||||
// Input : &svIpAddress -
|
||||
// nNucleusID -
|
||||
// Input : *ipAddress -
|
||||
// nucleusId -
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBanSystem::AddEntry(const string& svIpAddress, const uint64_t nNucleusID)
|
||||
bool CBanSystem::AddEntry(const char* ipAddress, const uint64_t nucleusId)
|
||||
{
|
||||
Assert(!svIpAddress.empty());
|
||||
Assert(VALID_CHARSTAR(ipAddress));
|
||||
const auto idPair = std::make_pair(string(ipAddress), nucleusId);
|
||||
|
||||
if (IsBanListValid())
|
||||
{
|
||||
auto it = std::find(m_vBanList.begin(), m_vBanList.end(), std::make_pair(svIpAddress, nNucleusID));
|
||||
auto it = std::find(m_vBanList.begin(), m_vBanList.end(), idPair);
|
||||
|
||||
if (it == m_vBanList.end())
|
||||
{
|
||||
m_vBanList.push_back(std::make_pair(svIpAddress, nNucleusID));
|
||||
m_vBanList.push_back(idPair);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_vBanList.push_back(std::make_pair(svIpAddress, nNucleusID));
|
||||
m_vBanList.push_back(idPair);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -125,24 +127,25 @@ bool CBanSystem::AddEntry(const string& svIpAddress, const uint64_t nNucleusID)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: deletes an entry in the banned list
|
||||
// Input : &svIpAddress -
|
||||
// nNucleusID -
|
||||
// Input : *ipAddress -
|
||||
// nucleusId -
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBanSystem::DeleteEntry(const string& svIpAddress, const uint64_t nNucleusID)
|
||||
bool CBanSystem::DeleteEntry(const char* ipAddress, const uint64_t nucleusId)
|
||||
{
|
||||
Assert(!svIpAddress.empty());
|
||||
Assert(VALID_CHARSTAR(ipAddress));
|
||||
|
||||
if (IsBanListValid())
|
||||
{
|
||||
auto it = std::find_if(m_vBanList.begin(), m_vBanList.end(),
|
||||
[&](const pair<const string, const uint64_t>& element)
|
||||
{ return (svIpAddress.compare(element.first) == NULL || element.second == nNucleusID); });
|
||||
{
|
||||
return (strcmp(ipAddress, element.first.c_str()) == NULL
|
||||
|| element.second == nucleusId);
|
||||
});
|
||||
|
||||
if (it != m_vBanList.end())
|
||||
{
|
||||
DeleteConnectionRefuse(it->second);
|
||||
m_vBanList.erase(it);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -150,109 +153,27 @@ bool CBanSystem::DeleteEntry(const string& svIpAddress, const uint64_t nNucleusI
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: adds a connect refuse entry to the refused list
|
||||
// Input : &svError -
|
||||
// nNucleusID -
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBanSystem::AddConnectionRefuse(const string& svError, const uint64_t nNucleusID)
|
||||
{
|
||||
if (IsRefuseListValid())
|
||||
{
|
||||
auto it = std::find_if(m_vRefuseList.begin(), m_vRefuseList.end(),
|
||||
[&](const pair<const string, const uint64_t>& element) { return element.second == nNucleusID; });
|
||||
|
||||
if (it == m_vRefuseList.end())
|
||||
{
|
||||
m_vRefuseList.push_back(std::make_pair(svError, nNucleusID));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_vRefuseList.push_back(std::make_pair(svError, nNucleusID));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: deletes an entry in the refused list
|
||||
// Input : nNucleusID -
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBanSystem::DeleteConnectionRefuse(const uint64_t nNucleusID)
|
||||
{
|
||||
if (IsRefuseListValid())
|
||||
{
|
||||
auto it = std::find_if(m_vRefuseList.begin(), m_vRefuseList.end(),
|
||||
[&](const pair<const string, const uint64_t>& element) { return element.second == nNucleusID; });
|
||||
|
||||
if (it != m_vRefuseList.end())
|
||||
{
|
||||
m_vRefuseList.erase(it);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Check refuse list and kill netchan connection.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBanSystem::BanListCheck(void)
|
||||
{
|
||||
if (!IsRefuseListValid())
|
||||
return;
|
||||
|
||||
for (size_t i = 0; i < m_vRefuseList.size(); i++)
|
||||
{
|
||||
for (int c = 0; c < MAX_PLAYERS; c++) // Loop through all possible client instances.
|
||||
{
|
||||
CClient* pClient = g_pClient->GetClient(c);
|
||||
if (!pClient)
|
||||
continue;
|
||||
|
||||
CNetChan* pNetChan = pClient->GetNetChan();
|
||||
if (!pNetChan)
|
||||
continue;
|
||||
|
||||
if (!pClient->IsConnected())
|
||||
continue;
|
||||
|
||||
if (pClient->GetNucleusID() != m_vRefuseList[i].second)
|
||||
continue;
|
||||
|
||||
string svIpAddress = pNetChan->GetAddress();
|
||||
|
||||
Warning(eDLL_T::SERVER, "Removing client '%s' from slot '%i' ('%llu' is banned from this server!)\n", svIpAddress.c_str(), c, pClient->GetNucleusID());
|
||||
pClient->Disconnect(Reputation_t::REP_MARK_BAD, "%s", m_vRefuseList[i].first.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: checks if specified ip address or nucleus id is banned
|
||||
// Input : &svIpAddress -
|
||||
// nNucleusID -
|
||||
// Input : *ipAddress -
|
||||
// nucleusId -
|
||||
// Output : true if banned, false if not banned
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBanSystem::IsBanned(const string& svIpAddress, const uint64_t nNucleusID) const
|
||||
bool CBanSystem::IsBanned(const char* ipAddress, const uint64_t nucleusId) const
|
||||
{
|
||||
for (size_t i = 0; i < m_vBanList.size(); i++)
|
||||
{
|
||||
const string& ipAddress = m_vBanList[i].first;
|
||||
const uint64_t nucleusID = m_vBanList[i].second;
|
||||
const string& bannedIpAddress = m_vBanList[i].first;
|
||||
const uint64_t bannedNucleusID = m_vBanList[i].second;
|
||||
|
||||
if (ipAddress.empty() ||
|
||||
!nucleusID) // Cannot be null.
|
||||
if (bannedIpAddress.empty()
|
||||
|| !bannedNucleusID) // Cannot be null.
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ipAddress.compare(svIpAddress) == NULL ||
|
||||
nNucleusID == nucleusID)
|
||||
if (bannedIpAddress.compare(ipAddress) == NULL
|
||||
|| nucleusId == bannedNucleusID)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -261,14 +182,6 @@ bool CBanSystem::IsBanned(const string& svIpAddress, const uint64_t nNucleusID)
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: checks if refused list is valid
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBanSystem::IsRefuseListValid(void) const
|
||||
{
|
||||
return !m_vRefuseList.empty();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: checks if banned list is valid
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -279,71 +192,75 @@ bool CBanSystem::IsBanListValid(void) const
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: kicks a player by given name
|
||||
// Input : &svPlayerName -
|
||||
// Input : *playerName -
|
||||
// *reason -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBanSystem::KickPlayerByName(const string& svPlayerName)
|
||||
void CBanSystem::KickPlayerByName(const char* playerName, const char* reason)
|
||||
{
|
||||
if (svPlayerName.empty())
|
||||
if (!VALID_CHARSTAR(playerName))
|
||||
return;
|
||||
|
||||
AuthorPlayerByName(svPlayerName, false);
|
||||
AuthorPlayerByName(playerName, false);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: kicks a player by given handle or id
|
||||
// Input : &svHandle -
|
||||
// Input : *playerHandle -
|
||||
// *reason -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBanSystem::KickPlayerById(const string& svHandle)
|
||||
void CBanSystem::KickPlayerById(const char* playerHandle, const char* reason)
|
||||
{
|
||||
if (svHandle.empty())
|
||||
if (!VALID_CHARSTAR(playerHandle))
|
||||
return;
|
||||
|
||||
AuthorPlayerById(svHandle, false);
|
||||
AuthorPlayerById(playerHandle, false);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: bans a player by given name
|
||||
// Input : &svPlayerName -
|
||||
// Input : *playerName -
|
||||
// *reason -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBanSystem::BanPlayerByName(const string& svPlayerName)
|
||||
void CBanSystem::BanPlayerByName(const char* playerName, const char* reason)
|
||||
{
|
||||
if (svPlayerName.empty())
|
||||
if (!VALID_CHARSTAR(playerName))
|
||||
return;
|
||||
|
||||
AuthorPlayerByName(svPlayerName, true);
|
||||
AuthorPlayerByName(playerName, true);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: bans a player by given handle or id
|
||||
// Input : &svHandle -
|
||||
// Input : *playerHandle -
|
||||
// *reason -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBanSystem::BanPlayerById(const string& svHandle)
|
||||
void CBanSystem::BanPlayerById(const char* playerHandle, const char* reason)
|
||||
{
|
||||
if (svHandle.empty())
|
||||
if (!VALID_CHARSTAR(playerHandle))
|
||||
return;
|
||||
|
||||
AuthorPlayerById(svHandle, true);
|
||||
AuthorPlayerById(playerHandle, true);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: unbans a player by given nucleus id or ip address
|
||||
// Input : &svCriteria -
|
||||
// Input : *criteria -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBanSystem::UnbanPlayer(const string& svCriteria)
|
||||
void CBanSystem::UnbanPlayer(const char* criteria)
|
||||
{
|
||||
try
|
||||
{
|
||||
bool bSave = false;
|
||||
if (StringIsDigit(svCriteria)) // Check if we have an ip address or nucleus id.
|
||||
if (StringIsDigit(criteria)) // Check if we have an ip address or nucleus id.
|
||||
{
|
||||
if (DeleteEntry("<<invalid>>", std::stoll(svCriteria))) // Delete ban entry.
|
||||
if (DeleteEntry("<<invalid>>", std::stoll(criteria))) // Delete ban entry.
|
||||
{
|
||||
bSave = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (DeleteEntry(svCriteria, 0)) // Delete ban entry.
|
||||
if (DeleteEntry(criteria, 0)) // Delete ban entry.
|
||||
{
|
||||
bSave = true;
|
||||
}
|
||||
@ -352,7 +269,7 @@ void CBanSystem::UnbanPlayer(const string& svCriteria)
|
||||
if (bSave)
|
||||
{
|
||||
Save(); // Save modified vector to file.
|
||||
DevMsg(eDLL_T::SERVER, "Removed '%s' from banned list\n", svCriteria.c_str());
|
||||
DevMsg(eDLL_T::SERVER, "Removed '%s' from banned list\n", criteria);
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
@ -364,15 +281,19 @@ void CBanSystem::UnbanPlayer(const string& svCriteria)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: authors player by given name
|
||||
// Input : &svPlayerName -
|
||||
// bBan - (only kicks if false)
|
||||
// Input : *playerName -
|
||||
// shouldBan - (only kicks if false)
|
||||
// *reason -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBanSystem::AuthorPlayerByName(const string& svPlayerName, const bool bBan)
|
||||
void CBanSystem::AuthorPlayerByName(const char* playerName, const bool shouldBan, const char* reason)
|
||||
{
|
||||
Assert(!svPlayerName.empty());
|
||||
Assert(VALID_CHARSTAR(playerName));
|
||||
bool bDisconnect = false;
|
||||
bool bSave = false;
|
||||
|
||||
if (!reason)
|
||||
reason = shouldBan ? "Banned from server" : "Kicked from server";
|
||||
|
||||
for (int i = 0; i < MAX_PLAYERS; i++)
|
||||
{
|
||||
CClient* pClient = g_pClient->GetClient(i);
|
||||
@ -385,12 +306,12 @@ void CBanSystem::AuthorPlayerByName(const string& svPlayerName, const bool bBan)
|
||||
|
||||
if (strlen(pNetChan->GetName()) > 0)
|
||||
{
|
||||
if (svPlayerName.compare(pNetChan->GetName()) == NULL) // Our wanted name?
|
||||
if (strcmp(playerName, pNetChan->GetName()) == NULL) // Our wanted name?
|
||||
{
|
||||
if (bBan && AddEntry(pNetChan->GetAddress(), pClient->GetNucleusID()) && !bSave)
|
||||
if (shouldBan && AddEntry(pNetChan->GetAddress(), pClient->GetNucleusID()) && !bSave)
|
||||
bSave = true;
|
||||
|
||||
pClient->Disconnect(REP_MARK_BAD, bBan ? "Banned from server" : "Kicked from server");
|
||||
pClient->Disconnect(REP_MARK_BAD, reason);
|
||||
bDisconnect = true;
|
||||
}
|
||||
}
|
||||
@ -399,29 +320,33 @@ void CBanSystem::AuthorPlayerByName(const string& svPlayerName, const bool bBan)
|
||||
if (bSave)
|
||||
{
|
||||
Save();
|
||||
DevMsg(eDLL_T::SERVER, "Added '%s' to banned list\n", svPlayerName.c_str());
|
||||
DevMsg(eDLL_T::SERVER, "Added '%s' to banned list\n", playerName);
|
||||
}
|
||||
else if (bDisconnect)
|
||||
{
|
||||
DevMsg(eDLL_T::SERVER, "Kicked '%s' from server\n", svPlayerName.c_str());
|
||||
DevMsg(eDLL_T::SERVER, "Kicked '%s' from server\n", playerName);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: authors player by given nucleus id or ip address
|
||||
// Input : &svHandle -
|
||||
// bBan - (only kicks if false)
|
||||
// Input : *playerHandle -
|
||||
// shouldBan - (only kicks if false)
|
||||
// *reason -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBanSystem::AuthorPlayerById(const string& svHandle, const bool bBan)
|
||||
void CBanSystem::AuthorPlayerById(const char* playerHandle, const bool shouldBan, const char* reason)
|
||||
{
|
||||
Assert(!svHandle.empty());
|
||||
Assert(VALID_CHARSTAR(playerHandle));
|
||||
|
||||
try
|
||||
{
|
||||
bool bOnlyDigits = StringIsDigit(svHandle);
|
||||
bool bOnlyDigits = StringIsDigit(playerHandle);
|
||||
bool bDisconnect = false;
|
||||
bool bSave = false;
|
||||
|
||||
if (!reason)
|
||||
reason = shouldBan ? "Banned from server" : "Kicked from server";
|
||||
|
||||
for (int i = 0; i < MAX_PLAYERS; i++)
|
||||
{
|
||||
CClient* pClient = g_pClient->GetClient(i);
|
||||
@ -434,7 +359,7 @@ void CBanSystem::AuthorPlayerById(const string& svHandle, const bool bBan)
|
||||
|
||||
if (bOnlyDigits)
|
||||
{
|
||||
uint64_t nTargetID = static_cast<uint64_t>(std::stoll(svHandle));
|
||||
uint64_t nTargetID = static_cast<uint64_t>(std::stoll(playerHandle));
|
||||
if (nTargetID > static_cast<uint64_t>(MAX_PLAYERS)) // Is it a possible nucleusID?
|
||||
{
|
||||
uint64_t nNucleusID = pClient->GetNucleusID();
|
||||
@ -448,21 +373,21 @@ void CBanSystem::AuthorPlayerById(const string& svHandle, const bool bBan)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bBan && AddEntry(pNetChan->GetAddress(), pClient->GetNucleusID()) && !bSave)
|
||||
if (shouldBan && AddEntry(pNetChan->GetAddress(), pClient->GetNucleusID()) && !bSave)
|
||||
bSave = true;
|
||||
|
||||
pClient->Disconnect(REP_MARK_BAD, bBan ? "Banned from server" : "Kicked from server");
|
||||
pClient->Disconnect(REP_MARK_BAD, reason);
|
||||
bDisconnect = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (svHandle.compare(pNetChan->GetAddress()) != NULL)
|
||||
if (strcmp(playerHandle, pNetChan->GetAddress()) != NULL)
|
||||
continue;
|
||||
|
||||
if (bBan && AddEntry(pNetChan->GetAddress(), pClient->GetNucleusID()) && !bSave)
|
||||
if (shouldBan && AddEntry(pNetChan->GetAddress(), pClient->GetNucleusID()) && !bSave)
|
||||
bSave = true;
|
||||
|
||||
pClient->Disconnect(REP_MARK_BAD, bBan ? "Banned from server" : "Kicked from server");
|
||||
pClient->Disconnect(REP_MARK_BAD, reason);
|
||||
bDisconnect = true;
|
||||
}
|
||||
}
|
||||
@ -470,11 +395,11 @@ void CBanSystem::AuthorPlayerById(const string& svHandle, const bool bBan)
|
||||
if (bSave)
|
||||
{
|
||||
Save();
|
||||
DevMsg(eDLL_T::SERVER, "Added '%s' to banned list\n", svHandle.c_str());
|
||||
DevMsg(eDLL_T::SERVER, "Added '%s' to banned list\n", playerHandle);
|
||||
}
|
||||
else if (bDisconnect)
|
||||
{
|
||||
DevMsg(eDLL_T::SERVER, "Kicked '%s' from server\n", svHandle.c_str());
|
||||
DevMsg(eDLL_T::SERVER, "Kicked '%s' from server\n", playerHandle);
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
|
@ -1,37 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
typedef vector<std::pair<string, uint64_t>> BannedVec_t;
|
||||
|
||||
class CBanSystem
|
||||
{
|
||||
public:
|
||||
void Load(void);
|
||||
void Save(void) const;
|
||||
|
||||
bool AddEntry(const string& svIpAddress, const uint64_t nNucleusID);
|
||||
bool DeleteEntry(const string& svIpAddress, const uint64_t nNucleusID);
|
||||
bool AddEntry(const char* ipAddress, const uint64_t nucleusId);
|
||||
bool DeleteEntry(const char* ipAddress, const uint64_t nucleusId);
|
||||
|
||||
bool AddConnectionRefuse(const string& svError, const uint64_t nNucleusID);
|
||||
bool DeleteConnectionRefuse(const uint64_t nNucleusID);
|
||||
|
||||
void BanListCheck(void);
|
||||
|
||||
bool IsBanned(const string& svIpAddress, const uint64_t nNucleusID) const;
|
||||
bool IsRefuseListValid(void) const;
|
||||
bool IsBanned(const char* ipAddress, const uint64_t nucleusId) const;
|
||||
bool IsBanListValid(void) const;
|
||||
|
||||
void KickPlayerByName(const string& svPlayerName);
|
||||
void KickPlayerById(const string& svHandle);
|
||||
void KickPlayerByName(const char* playerName, const char* reason = nullptr);
|
||||
void KickPlayerById(const char* playerHandle, const char* reason = nullptr);
|
||||
|
||||
void BanPlayerByName(const string& svPlayerName);
|
||||
void BanPlayerById(const string& svHandle);
|
||||
void BanPlayerByName(const char* playerName, const char* reason = nullptr);
|
||||
void BanPlayerById(const char* playerHandle, const char* reason = nullptr);
|
||||
|
||||
void UnbanPlayer(const string& svCriteria);
|
||||
void UnbanPlayer(const char* criteria);
|
||||
|
||||
private:
|
||||
void AuthorPlayerByName(const string& svPlayerName, const bool bBan);
|
||||
void AuthorPlayerById(const string& svHandle, const bool bBan);
|
||||
void AuthorPlayerByName(const char* playerName, const bool bBan, const char* reason = nullptr);
|
||||
void AuthorPlayerById(const char* playerHandle, const bool bBan, const char* reason = nullptr);
|
||||
|
||||
vector<std::pair<string, uint64_t>> m_vRefuseList;
|
||||
vector<std::pair<string, uint64_t>> m_vBanList;
|
||||
BannedVec_t m_vBanList;
|
||||
};
|
||||
|
||||
extern CBanSystem* g_pBanSystem;
|
||||
|
@ -14,222 +14,122 @@
|
||||
#endif // !CLIENT_DLL
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: returns a vector of hosted servers.
|
||||
// Input : &svOutMessage -
|
||||
// Purpose: gets a vector of hosted servers.
|
||||
// Input : &outMessage -
|
||||
// Output : vector<NetGameServer_t>
|
||||
//-----------------------------------------------------------------------------
|
||||
vector<NetGameServer_t> CPylon::GetServerList(string& svOutMessage) const
|
||||
vector<NetGameServer_t> CPylon::GetServerList(string& outMessage) const
|
||||
{
|
||||
vector<NetGameServer_t> vslList;
|
||||
vector<NetGameServer_t> vecServers;
|
||||
|
||||
nlohmann::json jsRequestBody = nlohmann::json::object();
|
||||
jsRequestBody["version"] = SDK_VERSION;
|
||||
nlohmann::json requestJson = nlohmann::json::object();
|
||||
requestJson["version"] = SDK_VERSION;
|
||||
|
||||
string svRequestBody = jsRequestBody.dump(4);
|
||||
string svResponse;
|
||||
nlohmann::json responseJson;
|
||||
CURLINFO status;
|
||||
|
||||
if (pylon_showdebuginfo->GetBool())
|
||||
if (!SendRequest("/servers", requestJson, responseJson,
|
||||
outMessage, status, "server list error"))
|
||||
{
|
||||
DevMsg(eDLL_T::ENGINE, "%s - Sending server list request to comp-server:\n%s\n", __FUNCTION__, svRequestBody.c_str());
|
||||
return vecServers;
|
||||
}
|
||||
|
||||
CURLINFO status;
|
||||
if (!QueryMasterServer(pylon_matchmaking_hostname->GetString(), "/servers", svRequestBody, svResponse, svOutMessage, status))
|
||||
if (!responseJson.contains("servers"))
|
||||
{
|
||||
return vslList;
|
||||
outMessage = Format("Invalid response with status: %d", int(status));
|
||||
return vecServers;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (status == 200) // STATUS_OK
|
||||
for (auto& obj : responseJson["servers"])
|
||||
{
|
||||
nlohmann::json jsResultBody = nlohmann::json::parse(svResponse);
|
||||
if (jsResultBody["success"].is_boolean() && jsResultBody["success"].get<bool>())
|
||||
{
|
||||
for (auto& obj : jsResultBody["servers"])
|
||||
vecServers.push_back(
|
||||
NetGameServer_t
|
||||
{
|
||||
vslList.push_back(
|
||||
NetGameServer_t
|
||||
{
|
||||
obj.value("name",""),
|
||||
obj.value("description",""),
|
||||
obj.value("hidden","false") == "true",
|
||||
obj.value("map",""),
|
||||
obj.value("playlist",""),
|
||||
obj.value("ip",""),
|
||||
obj.value("port", ""),
|
||||
obj.value("key",""),
|
||||
obj.value("checksum",""),
|
||||
obj.value("version", SDK_VERSION),
|
||||
obj.value("playerCount", ""),
|
||||
obj.value("maxPlayers", ""),
|
||||
obj.value("timeStamp", 0),
|
||||
obj.value("publicRef", ""),
|
||||
obj.value("cachedId", ""),
|
||||
}
|
||||
);
|
||||
obj.value("name",""),
|
||||
obj.value("description",""),
|
||||
obj.value("hidden","false") == "true",
|
||||
obj.value("map",""),
|
||||
obj.value("playlist",""),
|
||||
obj.value("ip",""),
|
||||
obj.value("port", ""),
|
||||
obj.value("key",""),
|
||||
obj.value("checksum",""),
|
||||
obj.value("version", SDK_VERSION),
|
||||
obj.value("playerCount", ""),
|
||||
obj.value("maxPlayers", ""),
|
||||
obj.value("timeStamp", 0),
|
||||
obj.value("publicRef", ""),
|
||||
obj.value("cachedId", ""),
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (jsResultBody["error"].is_string())
|
||||
{
|
||||
svOutMessage = jsResultBody["error"].get<string>();
|
||||
}
|
||||
else
|
||||
{
|
||||
svOutMessage = Format("Unknown error with status: %d", static_cast<int>(status));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (status)
|
||||
{
|
||||
if (!svResponse.empty())
|
||||
{
|
||||
nlohmann::json jsResultBody = nlohmann::json::parse(svResponse);
|
||||
|
||||
if (jsResultBody["error"].is_string())
|
||||
{
|
||||
svOutMessage = jsResultBody["error"].get<string>();
|
||||
}
|
||||
else
|
||||
{
|
||||
svOutMessage = Format("Server list error: %d", static_cast<int>(status));
|
||||
}
|
||||
|
||||
return vslList;
|
||||
}
|
||||
|
||||
svOutMessage = Format("Failed comp-server query: %d", static_cast<int>(status));
|
||||
return vslList;
|
||||
}
|
||||
|
||||
svOutMessage = Format("Failed to reach comp-server: %s", "connection timed-out");
|
||||
return vslList;
|
||||
);
|
||||
}
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
Warning(eDLL_T::ENGINE, "%s - Exception while parsing comp-server response:\n%s\n", __FUNCTION__, ex.what());
|
||||
Warning(eDLL_T::ENGINE, "%s - %s\n", __FUNCTION__, ex.what());
|
||||
vecServers.clear(); // Clear as the vector may be partially filled.
|
||||
}
|
||||
|
||||
return vslList;
|
||||
return vecServers;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Gets the server by token string.
|
||||
// Input : &slOutServer -
|
||||
// &svOutMessage -
|
||||
// &svToken -
|
||||
// Input : &outGameServer -
|
||||
// &outMessage -
|
||||
// &token -
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CPylon::GetServerByToken(NetGameServer_t& slOutServer, string& svOutMessage, const string& svToken) const
|
||||
bool CPylon::GetServerByToken(NetGameServer_t& outGameServer,
|
||||
string& outMessage, const string& token) const
|
||||
{
|
||||
nlohmann::json jsRequestBody = nlohmann::json::object();
|
||||
jsRequestBody["token"] = svToken;
|
||||
|
||||
string svRequestBody = jsRequestBody.dump(4);
|
||||
string svResponseBuf;
|
||||
|
||||
const bool bDebugLog = pylon_showdebuginfo->GetBool();
|
||||
|
||||
if (bDebugLog)
|
||||
{
|
||||
DevMsg(eDLL_T::ENGINE, "%s - Sending token connect request to comp-server:\n%s\n", __FUNCTION__, svRequestBody.c_str());
|
||||
}
|
||||
nlohmann::json requestJson = nlohmann::json::object();
|
||||
requestJson["token"] = token;
|
||||
|
||||
nlohmann::json responseJson;
|
||||
CURLINFO status;
|
||||
if (!QueryMasterServer(pylon_matchmaking_hostname->GetString(), "/server/byToken", svRequestBody, svResponseBuf, svOutMessage, status))
|
||||
|
||||
if (!SendRequest("/server/byToken", requestJson, responseJson,
|
||||
outMessage, status, "server not found"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bDebugLog)
|
||||
if (!responseJson.contains("server"))
|
||||
{
|
||||
DevMsg(eDLL_T::ENGINE, "%s - Comp-server replied with status: '%d'\n", __FUNCTION__, status);
|
||||
outMessage = Format("Invalid response with status: %d", int(status));
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (status == 200) // STATUS_OK
|
||||
nlohmann::json& serverJson = responseJson["server"];
|
||||
outGameServer = NetGameServer_t
|
||||
{
|
||||
nlohmann::json jsResultBody = nlohmann::json::parse(svResponseBuf);
|
||||
serverJson.value("name",""),
|
||||
serverJson.value("description",""),
|
||||
serverJson.value("hidden","false") == "true",
|
||||
serverJson.value("map",""),
|
||||
serverJson.value("playlist",""),
|
||||
serverJson.value("ip",""),
|
||||
serverJson.value("port", ""),
|
||||
serverJson.value("key",""),
|
||||
serverJson.value("checksum",""),
|
||||
serverJson.value("version", SDK_VERSION),
|
||||
serverJson.value("playerCount", ""),
|
||||
serverJson.value("maxPlayers", ""),
|
||||
serverJson.value("timeStamp", 0),
|
||||
serverJson.value("publicRef", ""),
|
||||
serverJson.value("cachedId", ""),
|
||||
};
|
||||
|
||||
if (bDebugLog)
|
||||
{
|
||||
string svResultBody = jsResultBody.dump(4);
|
||||
DevMsg(eDLL_T::ENGINE, "%s - Comp-server response body:\n%s\n", __FUNCTION__, svResultBody.c_str());
|
||||
}
|
||||
|
||||
if (jsResultBody["success"].is_boolean() && jsResultBody["success"])
|
||||
{
|
||||
slOutServer = NetGameServer_t
|
||||
{
|
||||
jsResultBody["server"].value("name",""),
|
||||
jsResultBody["server"].value("description",""),
|
||||
jsResultBody["server"].value("hidden","false") == "true",
|
||||
jsResultBody["server"].value("map",""),
|
||||
jsResultBody["server"].value("playlist",""),
|
||||
jsResultBody["server"].value("ip",""),
|
||||
jsResultBody["server"].value("port", ""),
|
||||
jsResultBody["server"].value("key",""),
|
||||
jsResultBody["server"].value("checksum",""),
|
||||
jsResultBody["server"].value("version", SDK_VERSION),
|
||||
jsResultBody["server"].value("playerCount", ""),
|
||||
jsResultBody["server"].value("maxPlayers", ""),
|
||||
jsResultBody["server"].value("timeStamp", 0),
|
||||
jsResultBody["server"].value("publicRef", ""),
|
||||
jsResultBody["server"].value("cachedId", ""),
|
||||
};
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (jsResultBody["error"].is_string())
|
||||
{
|
||||
svOutMessage = jsResultBody["error"].get<string>();
|
||||
}
|
||||
else
|
||||
{
|
||||
svOutMessage = Format("Unknown error with status: %d", static_cast<int>(status));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (status)
|
||||
{
|
||||
if (!svResponseBuf.empty())
|
||||
{
|
||||
nlohmann::json jsResultBody = nlohmann::json::parse(svResponseBuf);
|
||||
|
||||
if (jsResultBody["error"].is_string())
|
||||
{
|
||||
svOutMessage = jsResultBody["error"].get<string>();
|
||||
}
|
||||
else
|
||||
{
|
||||
svOutMessage = Format("Server not found: %d", static_cast<int>(status));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
svOutMessage = Format("Failed comp-server query: %d", static_cast<int>(status));
|
||||
return false;
|
||||
}
|
||||
|
||||
svOutMessage = Format("Failed to reach comp-server: %s", "connection timed-out");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
Warning(eDLL_T::ENGINE, "%s - Exception while parsing comp-server response:\n%s\n", __FUNCTION__, ex.what());
|
||||
Warning(eDLL_T::ENGINE, "%s - %s\n", __FUNCTION__, ex.what());
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -237,126 +137,56 @@ bool CPylon::GetServerByToken(NetGameServer_t& slOutServer, string& svOutMessage
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Sends host server POST request.
|
||||
// Input : &svOutMessage -
|
||||
// &svOutToken -
|
||||
// Input : &outMessage -
|
||||
// &outToken -
|
||||
// &netGameServer -
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CPylon::PostServerHost(string& svOutMessage, string& svOutToken, const NetGameServer_t& netGameServer) const
|
||||
bool CPylon::PostServerHost(string& outMessage, string& outToken,
|
||||
const NetGameServer_t& netGameServer) const
|
||||
{
|
||||
nlohmann::json jsRequestBody = nlohmann::json::object();
|
||||
jsRequestBody["name"] = netGameServer.m_svHostName;
|
||||
jsRequestBody["description"] = netGameServer.m_svDescription;
|
||||
jsRequestBody["hidden"] = netGameServer.m_bHidden;
|
||||
jsRequestBody["map"] = netGameServer.m_svHostMap;
|
||||
jsRequestBody["playlist"] = netGameServer.m_svPlaylist;
|
||||
jsRequestBody["ip"] = netGameServer.m_svIpAddress;
|
||||
jsRequestBody["port"] = netGameServer.m_svGamePort;
|
||||
jsRequestBody["key"] = netGameServer.m_svEncryptionKey;
|
||||
jsRequestBody["checksum"] = netGameServer.m_svRemoteChecksum;
|
||||
jsRequestBody["version"] = netGameServer.m_svSDKVersion;
|
||||
jsRequestBody["playerCount"] = netGameServer.m_svPlayerCount;
|
||||
jsRequestBody["maxPlayers"] = netGameServer.m_svMaxPlayers;
|
||||
jsRequestBody["timeStamp"] = netGameServer.m_nTimeStamp;
|
||||
jsRequestBody["publicRef"] = netGameServer.m_svPublicRef;
|
||||
jsRequestBody["cachedId"] = netGameServer.m_svCachedId;
|
||||
|
||||
string svRequestBody = jsRequestBody.dump(4);
|
||||
string svResponseBuf;
|
||||
|
||||
const bool bDebugLog = pylon_showdebuginfo->GetBool();
|
||||
if (bDebugLog)
|
||||
{
|
||||
DevMsg(eDLL_T::ENGINE, "%s - Sending post host request to comp-server:\n%s\n", __FUNCTION__, svRequestBody.c_str());
|
||||
}
|
||||
nlohmann::json requestJson = nlohmann::json::object();
|
||||
requestJson["name"] = netGameServer.m_svHostName;
|
||||
requestJson["description"] = netGameServer.m_svDescription;
|
||||
requestJson["hidden"] = netGameServer.m_bHidden;
|
||||
requestJson["map"] = netGameServer.m_svHostMap;
|
||||
requestJson["playlist"] = netGameServer.m_svPlaylist;
|
||||
requestJson["ip"] = netGameServer.m_svIpAddress;
|
||||
requestJson["port"] = netGameServer.m_svGamePort;
|
||||
requestJson["key"] = netGameServer.m_svEncryptionKey;
|
||||
requestJson["checksum"] = netGameServer.m_svRemoteChecksum;
|
||||
requestJson["version"] = netGameServer.m_svSDKVersion;
|
||||
requestJson["playerCount"] = netGameServer.m_svPlayerCount;
|
||||
requestJson["maxPlayers"] = netGameServer.m_svMaxPlayers;
|
||||
requestJson["timeStamp"] = netGameServer.m_nTimeStamp;
|
||||
requestJson["publicRef"] = netGameServer.m_svPublicRef;
|
||||
requestJson["cachedId"] = netGameServer.m_svCachedId;
|
||||
|
||||
nlohmann::json responseJson;
|
||||
CURLINFO status;
|
||||
if (!QueryMasterServer(pylon_matchmaking_hostname->GetString(), "/servers/add", svRequestBody, svResponseBuf, svOutMessage, status))
|
||||
|
||||
if (!SendRequest("/servers/add", requestJson, responseJson,
|
||||
outMessage, status, "server host error"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bDebugLog)
|
||||
if (netGameServer.m_bHidden)
|
||||
{
|
||||
DevMsg(eDLL_T::ENGINE, "%s - Comp-server replied with status: '%d'\n", __FUNCTION__, status);
|
||||
}
|
||||
nlohmann::json& tokenJson = responseJson["token"];
|
||||
|
||||
try
|
||||
{
|
||||
if (status == 200) // STATUS_OK
|
||||
if (!tokenJson.is_string())
|
||||
{
|
||||
nlohmann::json jsResultBody = nlohmann::json::parse(svResponseBuf);
|
||||
outMessage = Format("Invalid response with status: %d", int(status));
|
||||
outToken.clear();
|
||||
|
||||
if (bDebugLog)
|
||||
{
|
||||
string svResultBody = jsResultBody.dump(4);
|
||||
DevMsg(eDLL_T::ENGINE, "%s - Comp-server response body:\n%s\n", __FUNCTION__, svResultBody.c_str());
|
||||
}
|
||||
|
||||
if (jsResultBody["success"].is_boolean() && jsResultBody["success"].get<bool>())
|
||||
{
|
||||
if (jsResultBody["token"].is_string())
|
||||
{
|
||||
svOutToken = jsResultBody["token"].get<string>();
|
||||
}
|
||||
else
|
||||
{
|
||||
svOutMessage = Format("Invalid response with status: %d", static_cast<int>(status));
|
||||
svOutToken.clear();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (jsResultBody["error"].is_string())
|
||||
{
|
||||
svOutMessage = jsResultBody["error"].get<string>();
|
||||
}
|
||||
else
|
||||
{
|
||||
svOutMessage = Format("Unknown error with status: %d", static_cast<int>(status));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (status)
|
||||
{
|
||||
if (!svResponseBuf.empty())
|
||||
{
|
||||
nlohmann::json jsResultBody = nlohmann::json::parse(svResponseBuf);
|
||||
|
||||
if (jsResultBody["error"].is_string())
|
||||
{
|
||||
svOutMessage = jsResultBody["error"].get<string>();
|
||||
}
|
||||
else
|
||||
{
|
||||
svOutMessage = Format("Server host error: %d", static_cast<int>(status));
|
||||
}
|
||||
|
||||
svOutToken.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
svOutMessage = Format("Failed comp-server query: %d", static_cast<int>(status));
|
||||
svOutToken.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
svOutMessage = Format("Failed to reach comp-server: %s", "connection timed-out");
|
||||
svOutToken.clear();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
Warning(eDLL_T::ENGINE, "%s - Exception while parsing comp-server response:\n%s\n", __FUNCTION__, ex.what());
|
||||
|
||||
outToken = tokenJson.get<string>();
|
||||
}
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef DEDICATED
|
||||
@ -372,26 +202,26 @@ bool CPylon::KeepAlive(const NetGameServer_t& netGameServer)
|
||||
return false;
|
||||
}
|
||||
|
||||
string svHostToken;
|
||||
string svErrorMsg;
|
||||
string errorMsg;
|
||||
string hostToken;
|
||||
|
||||
bool result = PostServerHost(svErrorMsg, svHostToken, netGameServer);
|
||||
const bool result = PostServerHost(errorMsg, hostToken, netGameServer);
|
||||
if (!result)
|
||||
{
|
||||
if (!svErrorMsg.empty() && m_ErrorMsg.compare(svErrorMsg) != NULL)
|
||||
if (!errorMsg.empty() && m_ErrorMsg.compare(errorMsg) != NULL)
|
||||
{
|
||||
m_ErrorMsg = svErrorMsg;
|
||||
Error(eDLL_T::SERVER, NO_ERROR, "%s\n", svErrorMsg.c_str());
|
||||
m_ErrorMsg = errorMsg;
|
||||
Error(eDLL_T::SERVER, NO_ERROR, "%s\n", errorMsg.c_str());
|
||||
}
|
||||
}
|
||||
else // Attempt to log the token, if there is one.
|
||||
{
|
||||
if (!svHostToken.empty() && m_Token.compare(svHostToken) != NULL)
|
||||
if (!hostToken.empty() && m_Token.compare(hostToken) != NULL)
|
||||
{
|
||||
m_Token = svHostToken;
|
||||
m_Token = hostToken;
|
||||
DevMsg(eDLL_T::SERVER, "Published server with token: %s'%s%s%s'\n",
|
||||
g_svReset.c_str(), g_svGreyB.c_str(),
|
||||
svHostToken.c_str(), g_svReset.c_str());
|
||||
hostToken.c_str(), g_svReset.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@ -400,105 +230,267 @@ bool CPylon::KeepAlive(const NetGameServer_t& netGameServer)
|
||||
#endif // DEDICATED
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Checks if client is banned on the comp server.
|
||||
// Input : &svIpAddress -
|
||||
// nNucleusID -
|
||||
// &svOutReason -
|
||||
// Output : Returns true if banned, false if not banned.
|
||||
// Purpose: Checks a list of clients for their banned status.
|
||||
// Input : &inBannedVec -
|
||||
// &outBannedVec -
|
||||
// Output : True on success, false otherwise.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CPylon::CheckForBan(const string& svIpAddress, const uint64_t nNucleusID, string& svOutReason) const
|
||||
bool CPylon::GetBannedList(const BannedVec_t& inBannedVec, BannedVec_t& outBannedVec) const
|
||||
{
|
||||
nlohmann::json jsRequestBody = nlohmann::json::object();
|
||||
jsRequestBody["id"] = nNucleusID;
|
||||
jsRequestBody["ip"] = svIpAddress;
|
||||
nlohmann::json arrayJson = nlohmann::json::array();
|
||||
|
||||
string svRequestBody = jsRequestBody.dump(4);
|
||||
string svResponseBuf;
|
||||
string svOutMessage;
|
||||
CURLINFO status;
|
||||
|
||||
const bool bDebugLog = pylon_showdebuginfo->GetBool();
|
||||
|
||||
if (bDebugLog)
|
||||
for (const auto& bannedPair : inBannedVec)
|
||||
{
|
||||
DevMsg(eDLL_T::ENGINE, "%s - Sending ban check request to comp-server:\n%s\n", __FUNCTION__, svRequestBody.c_str());
|
||||
nlohmann::json player;
|
||||
player["id"] = bannedPair.second;
|
||||
player["ip"] = bannedPair.first;
|
||||
arrayJson.push_back(player);
|
||||
}
|
||||
|
||||
if (!QueryMasterServer(pylon_matchmaking_hostname->GetString(), "/banlist/isBanned", svRequestBody, svResponseBuf, svOutMessage, status))
|
||||
nlohmann::json playerArray;
|
||||
playerArray["players"] = arrayJson;
|
||||
|
||||
string outMessage;
|
||||
CURLINFO status;
|
||||
|
||||
if (!SendRequest("/banlist/bulkCheck", playerArray,
|
||||
arrayJson, outMessage, status, "banned bulk check error"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bDebugLog)
|
||||
if (!arrayJson.contains("bannedPlayers"))
|
||||
{
|
||||
DevMsg(eDLL_T::ENGINE, "%s - Comp-server replied with status: '%d'\n", __FUNCTION__, status);
|
||||
}
|
||||
|
||||
if (status != 200)
|
||||
{
|
||||
Error(eDLL_T::ENGINE, NO_ERROR, "%s - Failed to query comp-server: status code = %d\n", __FUNCTION__, status);
|
||||
outMessage = Format("Invalid response with status: %d", int(status));
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
nlohmann::json jsResultBody = nlohmann::json::parse(svResponseBuf);
|
||||
|
||||
if (bDebugLog)
|
||||
for (auto& obj : arrayJson["bannedPlayers"])
|
||||
{
|
||||
string svResultBody = jsResultBody.dump(4);
|
||||
DevMsg(eDLL_T::ENGINE, "%s - Comp-server response body:\n%s\n", __FUNCTION__, svResultBody.c_str());
|
||||
outBannedVec.push_back(
|
||||
std::make_pair(
|
||||
obj.value("reason", "#DISCONNECT_BANNED"),
|
||||
obj.value("id", uint64_t(0))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (jsResultBody["success"].is_boolean() && jsResultBody["success"].get<bool>())
|
||||
{
|
||||
if (jsResultBody["banned"].is_boolean() && jsResultBody["banned"].get<bool>())
|
||||
{
|
||||
svOutReason = jsResultBody.value("reason", "#DISCONNECT_BANNED");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
Warning(eDLL_T::ENGINE, "%s - Exception while parsing comp-server response:\n%s\n", __FUNCTION__, ex.what());
|
||||
Warning(eDLL_T::ENGINE, "%s - %s\n", __FUNCTION__, ex.what());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Sends query to master server.
|
||||
// Input : &svHostName -
|
||||
// &svApi -
|
||||
// &svInRequest -
|
||||
// &svResponse -
|
||||
// &svOutMessage -
|
||||
// &outStatus -
|
||||
// Output : Returns true if successful, false otherwise.
|
||||
// Purpose: Checks if client is banned on the comp server.
|
||||
// Input : &ipAddress -
|
||||
// nucleusId -
|
||||
// &outReason - <- contains banned reason if any.
|
||||
// Output : True if banned, false if not banned.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CPylon::QueryMasterServer(const string& svHostName, const string& svApi, const string& svInRequest,
|
||||
string& svOutResponse, string& svOutMessage, CURLINFO& outStatus) const
|
||||
bool CPylon::CheckForBan(const string& ipAddress, const uint64_t nucleusId,
|
||||
const string& personaName, string& outReason) const
|
||||
{
|
||||
string svUrl;
|
||||
CURLFormatUrl(svUrl, svHostName, svApi);
|
||||
nlohmann::json requestJson = nlohmann::json::object();
|
||||
requestJson["name"] = personaName;
|
||||
requestJson["id"] = nucleusId;
|
||||
requestJson["ip"] = ipAddress;
|
||||
|
||||
nlohmann::json responseJson;
|
||||
string outMessage;
|
||||
CURLINFO status;
|
||||
|
||||
if (!SendRequest("/banlist/isBanned", requestJson,
|
||||
responseJson, outMessage, status, "banned check error"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (responseJson["banned"].is_boolean() &&
|
||||
responseJson["banned"].get<bool>())
|
||||
{
|
||||
outReason = responseJson.value("reason", "#DISCONNECT_BANNED");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
Warning(eDLL_T::ENGINE, "%s - %s\n", __FUNCTION__, ex.what());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Sends request to Pylon Master Server.
|
||||
// Input : *endpoint -
|
||||
// &requestJson -
|
||||
// &responseJson -
|
||||
// &outMessage -
|
||||
// &status -
|
||||
// Output : True on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CPylon::SendRequest(const char* endpoint, const nlohmann::json& requestJson,
|
||||
nlohmann::json& responseJson, string& outMessage, CURLINFO& status, const char* errorText) const
|
||||
{
|
||||
string responseBody;
|
||||
|
||||
if (!QueryServer(endpoint, requestJson.dump(4).c_str(), responseBody, outMessage, status))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (status == 200) // STATUS_OK
|
||||
{
|
||||
responseJson = nlohmann::json::parse(responseBody);
|
||||
LogBody(responseJson);
|
||||
|
||||
if (responseJson["success"].is_boolean() &&
|
||||
responseJson["success"].get<bool>())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ExtractError(responseJson, outMessage, status);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ExtractError(responseBody, outMessage, status, errorText);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
Warning(eDLL_T::ENGINE, "%s - Exception while parsing response:\n%s\n", __FUNCTION__, ex.what());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Sends query to master server.
|
||||
// Input : *endpoint -
|
||||
// *request -
|
||||
// &outResponse -
|
||||
// &outMessage - <- contains an error message on failure.
|
||||
// &outStatus -
|
||||
// Output : True on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CPylon::QueryServer(const char* endpoint, const char* request,
|
||||
string& outResponse, string& outMessage, CURLINFO& outStatus) const
|
||||
{
|
||||
const bool showDebug = pylon_showdebuginfo->GetBool();
|
||||
const char* hostName = pylon_matchmaking_hostname->GetString();
|
||||
|
||||
if (showDebug)
|
||||
{
|
||||
DevMsg(eDLL_T::ENGINE, "Sending request to '%s' with endpoint '%s':\n%s\n",
|
||||
hostName, endpoint, request);
|
||||
}
|
||||
|
||||
string finalUrl;
|
||||
CURLFormatUrl(finalUrl, hostName, endpoint);
|
||||
|
||||
curl_slist* sList = nullptr;
|
||||
CURL* curl = CURLInitRequest(svUrl, svInRequest, svOutResponse, sList);
|
||||
CURL* curl = CURLInitRequest(finalUrl.c_str(), request, outResponse, sList);
|
||||
if (!curl)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
CURLcode res = CURLSubmitRequest(curl, sList);
|
||||
if (!CURLHandleError(curl, res, svOutMessage))
|
||||
if (!CURLHandleError(curl, res, outMessage))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
outStatus = CURLRetrieveInfo(curl);
|
||||
|
||||
if (showDebug)
|
||||
{
|
||||
DevMsg(eDLL_T::ENGINE, "Host '%s' replied with status: '%d'\n",
|
||||
hostName, outStatus);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Extracts the error from the result json.
|
||||
// Input : &resultJson -
|
||||
// &outMessage -
|
||||
// status -
|
||||
// *errorText -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPylon::ExtractError(const nlohmann::json& resultJson, string& outMessage,
|
||||
CURLINFO status, const char* errorText) const
|
||||
{
|
||||
if (resultJson["error"].is_string())
|
||||
{
|
||||
outMessage = resultJson["error"].get<string>();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!errorText)
|
||||
{
|
||||
errorText = "unknown error";
|
||||
}
|
||||
|
||||
outMessage = Format("Failed with status: %d (%s)",
|
||||
int(status), errorText);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Extracts the error from the response buffer.
|
||||
// Input : &response -
|
||||
// &outMessage -
|
||||
// status -
|
||||
// *errorText -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPylon::ExtractError(const string& response, string& outMessage,
|
||||
CURLINFO status, const char* errorText) const
|
||||
{
|
||||
if (!response.empty())
|
||||
{
|
||||
nlohmann::json resultBody = nlohmann::json::parse(response);
|
||||
ExtractError(resultBody, outMessage, status, errorText);
|
||||
}
|
||||
else if (status)
|
||||
{
|
||||
outMessage = Format("Failed server query: %d", int(status));
|
||||
}
|
||||
else
|
||||
{
|
||||
outMessage = Format("Failed to reach server: %s",
|
||||
"connection timed out");
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Logs the response body if debug is enabled.
|
||||
// Input : &responseJson -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPylon::LogBody(const nlohmann::json& responseJson) const
|
||||
{
|
||||
if (pylon_showdebuginfo->GetBool())
|
||||
{
|
||||
const string responseBody = responseJson.dump(4);
|
||||
DevMsg(eDLL_T::ENGINE, "\n%s\n", responseBody.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
CPylon* g_pMasterServer(new CPylon());
|
||||
|
@ -1,15 +1,24 @@
|
||||
#pragma once
|
||||
#include "thirdparty/curl/include/curl/curl.h"
|
||||
#include "bansystem.h"
|
||||
#include "serverlisting.h"
|
||||
|
||||
class CPylon
|
||||
{
|
||||
public:
|
||||
vector<NetGameServer_t> GetServerList(string& svOutMessage) const;
|
||||
bool GetServerByToken(NetGameServer_t& slOutServer, string& svOutMessage, const string& svToken) const;
|
||||
bool PostServerHost(string& svOutMessage, string& svOutToken, const NetGameServer_t& netGameServer) const;
|
||||
bool CheckForBan(const string& svIpAddress, const uint64_t nNucleusID, string& svOutReason) const;
|
||||
bool QueryMasterServer(const string& svHostName, const string& svApi, const string& svRequest, string& svResponse, string& svOutMessage, CURLINFO& status) const;
|
||||
vector<NetGameServer_t> GetServerList(string& outMessage) const;
|
||||
bool GetServerByToken(NetGameServer_t& slOutServer, string& outMessage, const string& svToken) const;
|
||||
bool PostServerHost(string& outMessage, string& svOutToken, const NetGameServer_t& netGameServer) const;
|
||||
|
||||
bool GetBannedList(const BannedVec_t& inBannedVec, BannedVec_t& outBannedVec) const;
|
||||
bool CheckForBan(const string& ipAddress, const uint64_t nucleusId, const string& personaName, string& outReason) const;
|
||||
|
||||
void ExtractError(const nlohmann::json& resultBody, string& outMessage, CURLINFO status, const char* errorText = nullptr) const;
|
||||
void ExtractError(const string& response, string& outMessage, CURLINFO status, const char* messageText = nullptr) const;
|
||||
|
||||
void LogBody(const nlohmann::json& responseJson) const;
|
||||
bool SendRequest(const char* endpoint, const nlohmann::json& requestJson, nlohmann::json& responseJson, string& outMessage, CURLINFO& status, const char* errorText = nullptr) const;
|
||||
bool QueryServer(const char* endpoint, const char* request, string& outResponse, string& outMessage, CURLINFO& outStatus) const;
|
||||
|
||||
#ifdef DEDICATED
|
||||
bool KeepAlive(const NetGameServer_t& netGameServer);
|
||||
|
@ -1,13 +1,13 @@
|
||||
#ifndef TIER2_CURLUTILS_H
|
||||
#define TIER2_CURLUTILS_H
|
||||
|
||||
size_t CURLWriteStringCallback(char* contents, size_t size, size_t nmemb, void* userp);
|
||||
size_t CURLWriteStringCallback(char* contents, const size_t size, const size_t nmemb, void* userp);
|
||||
|
||||
CURL* CURLInitRequest(const string& remote, const string& request, string& response, curl_slist*& slist);
|
||||
CURL* CURLInitRequest(const char* remote, const char* request, string& outResponse, curl_slist*& slist);
|
||||
CURLcode CURLSubmitRequest(CURL* curl, curl_slist*& slist);
|
||||
CURLINFO CURLRetrieveInfo(CURL* curl);
|
||||
|
||||
bool CURLHandleError(CURL* curl, CURLcode res, string& outMessage);
|
||||
void CURLFormatUrl(string& url, const string& host, const string& api);
|
||||
void CURLFormatUrl(string& outUrl, const char* host, const char* api);
|
||||
|
||||
#endif // !TIER2_CURLUTILS_H
|
@ -347,13 +347,13 @@ void CSurface::Init()
|
||||
this->m_NetRandomKeyToggle->SetAnchor(Forms::AnchorStyles::Top | Forms::AnchorStyles::Left);
|
||||
this->m_EngineNetworkGroup->AddControl(this->m_NetRandomKeyToggle);
|
||||
|
||||
this->m_NoQueuedPacketThread = new UIX::UIXCheckBox();
|
||||
this->m_NoQueuedPacketThread->SetSize({ 125, 18 });
|
||||
this->m_NoQueuedPacketThread->SetLocation({ 15, 30 });
|
||||
this->m_NoQueuedPacketThread->SetTabIndex(2);
|
||||
this->m_NoQueuedPacketThread->SetText("No queued packets");
|
||||
this->m_NoQueuedPacketThread->SetAnchor(Forms::AnchorStyles::Top | Forms::AnchorStyles::Left);
|
||||
this->m_EngineNetworkGroup->AddControl(this->m_NoQueuedPacketThread);
|
||||
this->m_QueuedPacketThread = new UIX::UIXCheckBox();
|
||||
this->m_QueuedPacketThread->SetSize({ 125, 18 });
|
||||
this->m_QueuedPacketThread->SetLocation({ 15, 30 });
|
||||
this->m_QueuedPacketThread->SetTabIndex(2);
|
||||
this->m_QueuedPacketThread->SetText("Queued packets");
|
||||
this->m_QueuedPacketThread->SetAnchor(Forms::AnchorStyles::Top | Forms::AnchorStyles::Left);
|
||||
this->m_EngineNetworkGroup->AddControl(this->m_QueuedPacketThread);
|
||||
|
||||
this->m_NoTimeOutToggle = new UIX::UIXCheckBox();
|
||||
this->m_NoTimeOutToggle->SetSize({ 125, 18 });
|
||||
@ -566,7 +566,7 @@ void CSurface::LoadSettings()
|
||||
this->m_NetRandomKeyToggle->SetChecked(attributeView != "0");
|
||||
|
||||
attributeView = vRoot.attribs["noQueuedPackets"];
|
||||
this->m_NoQueuedPacketThread->SetChecked(attributeView != "0");
|
||||
this->m_QueuedPacketThread->SetChecked(attributeView != "0");
|
||||
|
||||
attributeView = vRoot.attribs["noTimeOut"];
|
||||
this->m_NoTimeOutToggle->SetChecked(attributeView != "0");
|
||||
@ -635,7 +635,7 @@ void CSurface::SaveSettings()
|
||||
// Network.
|
||||
vRoot.add_attribute("encryptionEnable", GetControlValue(this->m_NetEncryptionToggle));
|
||||
vRoot.add_attribute("randomNetKey", GetControlValue(this->m_NetRandomKeyToggle));
|
||||
vRoot.add_attribute("noQueuedPackets", GetControlValue(this->m_NoQueuedPacketThread));
|
||||
vRoot.add_attribute("noQueuedPackets", GetControlValue(this->m_QueuedPacketThread));
|
||||
vRoot.add_attribute("noTimeOut", GetControlValue(this->m_NoTimeOutToggle));
|
||||
|
||||
// Video.
|
||||
@ -1031,14 +1031,9 @@ void CSurface::AppendHostParameters(string& svParameters)
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSurface::AppendNetParameters(string& svParameters)
|
||||
{
|
||||
if (this->m_NetEncryptionToggle->Checked())
|
||||
AppendParameterInternal(svParameters, "+net_encryptionEnable", "1");
|
||||
|
||||
if (this->m_NetRandomKeyToggle->Checked())
|
||||
AppendParameterInternal(svParameters, "+net_useRandomKey", "1");
|
||||
|
||||
if (this->m_NoQueuedPacketThread->Checked())
|
||||
AppendParameterInternal(svParameters, "+net_queued_packet_thread", "0");
|
||||
AppendParameterInternal(svParameters, "+net_encryptionEnable", this->m_NetEncryptionToggle->Checked() ? "1" : "0");
|
||||
AppendParameterInternal(svParameters, "+net_useRandomKey", this->m_NetRandomKeyToggle->Checked() ? "1" : "0");
|
||||
AppendParameterInternal(svParameters, "+net_queued_packet_thread", this->m_QueuedPacketThread->Checked() ? "1" : "0");
|
||||
|
||||
if (this->m_NoTimeOutToggle->Checked())
|
||||
AppendParameterInternal(svParameters, "-notimeout");
|
||||
|
@ -106,7 +106,7 @@ private:
|
||||
UIX::UIXCheckBox* m_NoAsyncJobsToggle;
|
||||
UIX::UIXCheckBox* m_NetEncryptionToggle;
|
||||
UIX::UIXCheckBox* m_NetRandomKeyToggle;
|
||||
UIX::UIXCheckBox* m_NoQueuedPacketThread;
|
||||
UIX::UIXCheckBox* m_QueuedPacketThread;
|
||||
UIX::UIXCheckBox* m_NoTimeOutToggle;
|
||||
UIX::UIXCheckBox* m_WindowedToggle;
|
||||
UIX::UIXCheckBox* m_NoBorderToggle;
|
||||
|
@ -342,8 +342,8 @@ void ConVar::StaticInit(void)
|
||||
sv_showconnecting = ConVar::StaticCreate("sv_showconnecting" , "1", FCVAR_RELEASE, "Logs information about the connecting client to the console.", false, 0.f, false, 0.f, nullptr, nullptr);
|
||||
sv_globalBanlist = ConVar::StaticCreate("sv_globalBanlist" , "1", FCVAR_RELEASE, "Determines whether or not to use the global banned list.", false, 0.f, false, 0.f, nullptr, "0 = Disable, 1 = Enable.");
|
||||
sv_pylonVisibility = ConVar::StaticCreate("sv_pylonVisibility", "0", FCVAR_RELEASE, "Determines the visibility to the Pylon master server.", false, 0.f, false, 0.f, nullptr, "0 = Offline, 1 = Hidden, 2 = Public.");
|
||||
sv_pylonRefreshRate = ConVar::StaticCreate("sv_pylonRefreshRate" , "5.0", FCVAR_RELEASE, "Pylon host refresh rate (seconds).", true, 2.f, true, 8.f, nullptr, nullptr);
|
||||
sv_banlistRefreshRate = ConVar::StaticCreate("sv_banlistRefreshRate", "1.0", FCVAR_RELEASE, "Banned list refresh rate (seconds).", true, 1.f, false, 0.f, nullptr, nullptr);
|
||||
sv_pylonRefreshRate = ConVar::StaticCreate("sv_pylonRefreshRate" , "5.0" , FCVAR_DEVELOPMENTONLY, "Pylon host refresh rate (seconds).", true, 2.f, true, 8.f, nullptr, nullptr);
|
||||
sv_banlistRefreshRate = ConVar::StaticCreate("sv_banlistRefreshRate", "30.0", FCVAR_DEVELOPMENTONLY, "Banned list refresh rate (seconds).", true, 1.f, false, 0.f, nullptr, nullptr);
|
||||
sv_statusRefreshRate = ConVar::StaticCreate("sv_statusRefreshRate" , "0.5", FCVAR_RELEASE, "Server status refresh rate (seconds).", true, 0.f, false, 0.f, nullptr, nullptr);
|
||||
sv_autoReloadRate = ConVar::StaticCreate("sv_autoReloadRate" , "0" , FCVAR_RELEASE, "Time in seconds between each server auto-reload (disabled if null).", true, 0.f, false, 0.f, nullptr, nullptr);
|
||||
sv_simulateBots = ConVar::StaticCreate("sv_simulateBots", "1", FCVAR_RELEASE, "Simulate user commands for bots on the server.", true, 0.f, false, 0.f, nullptr, nullptr);
|
||||
@ -1245,13 +1245,13 @@ static void PrintCommand(const ConCommand* cmd, bool logging, FileHandle_t& f)
|
||||
Q_strncat(emptyflags, csvf, len);
|
||||
}
|
||||
// Names staring with +/- need to be wrapped in single quotes
|
||||
char name[256];
|
||||
Q_snprintf(name, sizeof(name), "%s", cmd->GetName());
|
||||
if (name[0] == '+' || name[0] == '-')
|
||||
char nameBuf[256];
|
||||
Q_snprintf(nameBuf, sizeof(nameBuf), "%s", cmd->GetName());
|
||||
if (nameBuf[0] == '+' || nameBuf[0] == '-')
|
||||
{
|
||||
Q_snprintf(name, sizeof(name), "'%s'", cmd->GetName());
|
||||
Q_snprintf(nameBuf, sizeof(nameBuf), "'%s'", cmd->GetName());
|
||||
}
|
||||
FileSystem()->FPrintf(f, "\"%s\",\"%s\",%s,\"%s\"\n", name, "cmd", emptyflags, StripQuotes(cmd->GetHelpText(), tempbuff, sizeof(tempbuff)));
|
||||
FileSystem()->FPrintf(f, "\"%s\",\"%s\",%s,\"%s\"\n", nameBuf, "cmd", emptyflags, StripQuotes(cmd->GetHelpText(), tempbuff, sizeof(tempbuff)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,13 +7,13 @@
|
||||
#include "tier1/cvar.h"
|
||||
#include "tier2/curlutils.h"
|
||||
|
||||
size_t CURLWriteStringCallback(char* contents, size_t size, size_t nmemb, void* userp)
|
||||
size_t CURLWriteStringCallback(char* contents, const size_t size, const size_t nmemb, void* userp)
|
||||
{
|
||||
reinterpret_cast<string*>(userp)->append(contents, size * nmemb);
|
||||
return size * nmemb;
|
||||
}
|
||||
|
||||
CURL* CURLInitRequest(const string& remote, const string& request, string& response, curl_slist*& slist)
|
||||
CURL* CURLInitRequest(const char* remote, const char* request, string& outResponse, curl_slist*& slist)
|
||||
{
|
||||
std::function<void(const char*)> fnError = [&](const char* errorMsg)
|
||||
{
|
||||
@ -36,14 +36,14 @@ CURL* CURLInitRequest(const string& remote, const string& request, string& respo
|
||||
}
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist);
|
||||
curl_easy_setopt(curl, CURLOPT_URL, remote.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, request.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_URL, remote);
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, request);
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, curl_timeout->GetInt());
|
||||
curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CURLWriteStringCallback);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &outResponse);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_VERBOSE, curl_debug->GetBool());
|
||||
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
|
||||
@ -89,7 +89,7 @@ bool CURLHandleError(CURL* curl, CURLcode res, string& outMessage)
|
||||
return false;
|
||||
}
|
||||
|
||||
void CURLFormatUrl(string& url, const string& host, const string& api)
|
||||
void CURLFormatUrl(string& outUrl, const char* host, const char* api)
|
||||
{
|
||||
url = Format("%s%s%s", "https://", host.c_str(), api.c_str());
|
||||
outUrl = Format("%s%s%s", "https://", host, api);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user