mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
Ban system and authentication improvements
* Fixed bug where multiple of the same entries get added to the global ban/refuse list. * Fixed bug where we still use the client instance after deleting it in 'CBanSystem::BanListCheck()'. * Load banlist at a later state (not at construction of class), this is needed for a future change of adapting the 'business' code to feature the game's FileSystem. * CServer cleanup. * More detailed ban messages (banned, added to refused list, removed from slot, etc..). * Use localization key for banned message ("#Valve_Reject_Banned"). * Add const qualifiers to all CPylon methods. Note: * This commit requires changes on the master server, these changes are already performed, however the new master server isn't live yet until we publish the new release.
This commit is contained in:
parent
8712f7db81
commit
1285d15623
@ -182,6 +182,7 @@ FORCEINLINE void CHostState::Init(void)
|
||||
FORCEINLINE void CHostState::Setup(void)
|
||||
{
|
||||
g_pHostState->LoadConfig();
|
||||
g_pBanSystem->Load();
|
||||
g_pConVar->PurgeHostNames();
|
||||
|
||||
net_usesocketsforloopback->SetValue(1);
|
||||
@ -242,7 +243,7 @@ FORCEINLINE void CHostState::Think(void) const
|
||||
).count()
|
||||
};
|
||||
|
||||
std::thread(KeepAliveToPylon, netGameServer).detach();
|
||||
std::thread(&CPylon::KeepAlive, g_pMasterServer, netGameServer).detach();
|
||||
pylonTimer.Start();
|
||||
}
|
||||
#endif // DEDICATED
|
||||
|
@ -59,50 +59,74 @@ int CServer::GetNumFakeClients(void) const
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
// Purpose: client to server authentication
|
||||
// Input : *this -
|
||||
// *pInpacket -
|
||||
// Output : pointer to client instance on success, nullptr on failure
|
||||
// Input : *pChallenge -
|
||||
// Output : true if user isn't banned, false otherwise
|
||||
//---------------------------------------------------------------------------------
|
||||
CClient* CServer::Authenticate(CServer* pServer, user_creds_s* pInpacket)
|
||||
bool CServer::AuthClient(user_creds_s* pChallenge)
|
||||
{
|
||||
string svIpAddress = pInpacket->m_nAddr.GetAddress();
|
||||
string svIpAddress = pChallenge->m_nAddr.GetAddress();
|
||||
if (sv_showconnecting->GetBool())
|
||||
{
|
||||
DevMsg(eDLL_T::SERVER, "Processing connectionless challenge from '%s' ('%llu')\n", svIpAddress.c_str(), pInpacket->m_nNucleusID);
|
||||
}
|
||||
DevMsg(eDLL_T::SERVER, "Processing connectionless challenge for '%s' ('%llu')\n", svIpAddress.c_str(), pChallenge->m_nNucleusID);
|
||||
|
||||
if (g_pBanSystem->IsBanListValid()) // Is the banlist vector valid?
|
||||
{
|
||||
if (g_pBanSystem->IsBanned(svIpAddress, pInpacket->m_nNucleusID)) // Is the client trying to connect banned?
|
||||
if (g_pBanSystem->IsBanned(svIpAddress, pChallenge->m_nNucleusID)) // Is the client trying to connect banned?
|
||||
{
|
||||
v_CServer_RejectConnection(pServer, pServer->m_Socket, pInpacket, "You have been banned from this server."); // RejectConnection for the client.
|
||||
RejectConnection(m_Socket, pChallenge, "#Valve_Reject_Banned"); // RejectConnection for the client.
|
||||
if (sv_showconnecting->GetBool())
|
||||
{
|
||||
Warning(eDLL_T::SERVER, "Connection rejected for '%s' ('%llu' is banned from this server!)\n", svIpAddress.c_str(), pInpacket->m_nNucleusID);
|
||||
}
|
||||
Warning(eDLL_T::SERVER, "Connection rejected for '%s' ('%llu' is banned from this server!)\n", svIpAddress.c_str(), pChallenge->m_nNucleusID);
|
||||
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_bCheckCompBanDB)
|
||||
{
|
||||
std::thread th(SV_IsClientBanned, g_pMasterServer, svIpAddress, pInpacket->m_nNucleusID);
|
||||
std::thread th(SV_IsClientBanned, svIpAddress, pChallenge->m_nNucleusID);
|
||||
th.detach();
|
||||
}
|
||||
|
||||
return v_CServer_Authenticate(pServer, pInpacket);
|
||||
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->AuthClient(pChallenge))
|
||||
{
|
||||
CClient* pClient = v_CServer_ConnectClient(pServer, pChallenge);
|
||||
return pClient;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
// Purpose: Rejects connection request and sends back a message
|
||||
// Input : *iSocket -
|
||||
// *pChallenge -
|
||||
// *szMessage -
|
||||
//---------------------------------------------------------------------------------
|
||||
void CServer::RejectConnection(int iSocket, user_creds_s* pChallenge, const char* szMessage)
|
||||
{
|
||||
v_CServer_RejectConnection(this, iSocket, pChallenge, szMessage);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
void CServer_Attach()
|
||||
{
|
||||
DetourAttach((LPVOID*)&v_CServer_Authenticate, &CServer::Authenticate);
|
||||
DetourAttach((LPVOID*)&v_CServer_ConnectClient, &CServer::ConnectClient);
|
||||
}
|
||||
|
||||
void CServer_Detach()
|
||||
{
|
||||
DetourDetach((LPVOID*)&v_CServer_Authenticate, &CServer::Authenticate);
|
||||
DetourDetach((LPVOID*)&v_CServer_ConnectClient, &CServer::ConnectClient);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -21,7 +21,7 @@ struct user_creds_s
|
||||
v_netadr_t m_nAddr;
|
||||
int32_t m_nProtocolVer;
|
||||
int32_t m_nchallenge;
|
||||
uint8_t gap2[8];
|
||||
uint32_t m_nReservation;
|
||||
uint64_t m_nNucleusID;
|
||||
uint8_t* m_pUserID;
|
||||
};
|
||||
@ -40,7 +40,9 @@ 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 g_bDedicated; }
|
||||
static CClient* Authenticate(CServer* pServer, user_creds_s* pInpacket);
|
||||
bool AuthClient(user_creds_s* pChallenge);
|
||||
void RejectConnection(int iSocket, user_creds_s* pCreds, const char* szMessage);
|
||||
static CClient* ConnectClient(CServer* pServer, user_creds_s* pChallenge);
|
||||
#endif // !CLIENT_DLL
|
||||
|
||||
private:
|
||||
@ -86,7 +88,7 @@ inline CMemory p_CServer_Think;
|
||||
inline auto v_CServer_Think = p_CServer_Think.RCast<void (*)(bool bCheckClockDrift, bool bIsSimulating)>();
|
||||
|
||||
inline CMemory p_CServer_Authenticate;
|
||||
inline auto v_CServer_Authenticate = p_CServer_Authenticate.RCast<CClient* (*)(CServer* pServer, user_creds_s* pCreds)>();
|
||||
inline auto v_CServer_ConnectClient = p_CServer_Authenticate.RCast<CClient* (*)(CServer* pServer, user_creds_s* pCreds)>();
|
||||
|
||||
inline CMemory p_CServer_RejectConnection;
|
||||
inline auto v_CServer_RejectConnection = p_CServer_RejectConnection.RCast<void* (*)(CServer* pServer, int iSocket, user_creds_s* pCreds, const char* szMessage)>();
|
||||
@ -102,7 +104,7 @@ class VServer : public IDetour
|
||||
virtual void GetAdr(void) const
|
||||
{
|
||||
spdlog::debug("| FUN: CServer::Think : {:#18x} |\n", p_CServer_Think.GetPtr());
|
||||
spdlog::debug("| FUN: CServer::Authenticate : {:#18x} |\n", p_CServer_Authenticate.GetPtr());
|
||||
spdlog::debug("| FUN: CServer::ConnectClient : {:#18x} |\n", p_CServer_Authenticate.GetPtr());
|
||||
spdlog::debug("| FUN: CServer::RejectConnection : {:#18x} |\n", p_CServer_RejectConnection.GetPtr());
|
||||
spdlog::debug("| VAR: g_pServer[128] : {:#18x} |\n", reinterpret_cast<uintptr_t>(g_pServer));
|
||||
spdlog::debug("+----------------------------------------------------------------+\n");
|
||||
@ -120,7 +122,7 @@ class VServer : public IDetour
|
||||
p_CServer_RejectConnection = g_GameDll.FindPatternSIMD(reinterpret_cast<rsig_t>("\x4C\x89\x4C\x24\x00\x53\x55\x56\x57\x48\x81\xEC\x00\x00\x00\x00\x49\x8B\xD9"), "xxxx?xxxxxxx????xxx");
|
||||
|
||||
v_CServer_Think = p_CServer_Think.RCast<void (*)(bool, bool)>(); /*48 89 5C 24 ?? 48 89 74 24 ?? 57 48 81 EC ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ??*/
|
||||
v_CServer_Authenticate = p_CServer_Authenticate.RCast<CClient* (*)(CServer*, user_creds_s*)>(); /*40 55 57 41 55 41 57 48 8D AC 24 ?? ?? ?? ??*/
|
||||
v_CServer_ConnectClient = p_CServer_Authenticate.RCast<CClient* (*)(CServer*, user_creds_s*)>(); /*40 55 57 41 55 41 57 48 8D AC 24 ?? ?? ?? ??*/
|
||||
v_CServer_RejectConnection = p_CServer_RejectConnection.RCast<void* (*)(CServer*, int, user_creds_s*, const char*)>(); /*4C 89 4C 24 ?? 53 55 56 57 48 81 EC ?? ?? ?? ?? 49 8B D9*/
|
||||
}
|
||||
virtual void GetVar(void) const
|
||||
|
@ -8,15 +8,13 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: checks if particular client is banned on the comp server
|
||||
//-----------------------------------------------------------------------------
|
||||
void SV_IsClientBanned(CPylon* pPylon, const string& svIPAddr, const uint64_t nNucleusID)
|
||||
void SV_IsClientBanned(const string& svIPAddr, const uint64_t nNucleusID)
|
||||
{
|
||||
string svError;
|
||||
|
||||
bool bCompBanned = pPylon->CheckForBan(svIPAddr, nNucleusID, svError);
|
||||
bool bCompBanned = g_pMasterServer->CheckForBan(svIPAddr, nNucleusID, svError);
|
||||
if (bCompBanned)
|
||||
{
|
||||
DevMsg(eDLL_T::SERVER, "Connection rejected for '%s' ('%llu' is banned from the master server!)\n", svIPAddr.c_str(), nNucleusID);
|
||||
|
||||
if (!ThreadInMainThread())
|
||||
{
|
||||
g_TaskScheduler->Dispatch([svError, nNucleusID]
|
||||
@ -24,6 +22,7 @@ void SV_IsClientBanned(CPylon* pPylon, const string& svIPAddr, const uint64_t nN
|
||||
g_pBanSystem->AddConnectionRefuse(svError, nNucleusID); // Add to the vector.
|
||||
}, 0);
|
||||
}
|
||||
Warning(eDLL_T::SERVER, "Added '%s' to refused list ('%llu' is banned from the master server!)\n", svIPAddr.c_str(), nNucleusID);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ inline bool* s_bDedicated = nullptr;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void SV_IsClientBanned(CPylon* pPylon, const string& svIPAddr, const uint64_t nNucleusID);
|
||||
void SV_IsClientBanned(const string& svIPAddr, const uint64_t nNucleusID);
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -10,23 +10,6 @@
|
||||
#include "engine/client/client.h"
|
||||
#include "networksystem/bansystem.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CBanSystem::CBanSystem(void)
|
||||
{
|
||||
Load();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : pair<const string&, const uint64_t> -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBanSystem::operator[](std::pair<const string&, const uint64_t> pair)
|
||||
{
|
||||
AddEntry(pair.first, pair.second);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: loads and parses the banlist
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -99,7 +82,9 @@ void CBanSystem::Save(void) const
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBanSystem::AddEntry(const string& svIpAddress, const uint64_t nNucleusID)
|
||||
{
|
||||
if (!svIpAddress.empty())
|
||||
Assert(!svIpAddress.empty());
|
||||
|
||||
if (IsBanListValid())
|
||||
{
|
||||
auto it = std::find(m_vBanList.begin(), m_vBanList.end(), std::make_pair(svIpAddress, nNucleusID));
|
||||
if (it == m_vBanList.end())
|
||||
@ -108,6 +93,12 @@ bool CBanSystem::AddEntry(const string& svIpAddress, const uint64_t nNucleusID)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_vBanList.push_back(std::make_pair(svIpAddress, nNucleusID));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -118,17 +109,24 @@ bool CBanSystem::AddEntry(const string& svIpAddress, const uint64_t nNucleusID)
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBanSystem::DeleteEntry(const string& svIpAddress, const uint64_t nNucleusID)
|
||||
{
|
||||
bool result = false;
|
||||
for (size_t i = 0; i < m_vBanList.size(); i++)
|
||||
Assert(!svIpAddress.empty());
|
||||
|
||||
if (IsBanListValid())
|
||||
{
|
||||
if (svIpAddress.compare(m_vBanList[i].first) == NULL || nNucleusID == m_vBanList[i].second)
|
||||
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); });
|
||||
|
||||
if (it != m_vBanList.end())
|
||||
{
|
||||
m_vBanList.erase(m_vBanList.begin() + i);
|
||||
result = true;
|
||||
DeleteConnectionRefuse(it->second);
|
||||
m_vBanList.erase(it);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -136,37 +134,47 @@ bool CBanSystem::DeleteEntry(const string& svIpAddress, const uint64_t nNucleusI
|
||||
// Input : &svError -
|
||||
// nNucleusID -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBanSystem::AddConnectionRefuse(const string& svError, const uint64_t nNucleusID)
|
||||
bool CBanSystem::AddConnectionRefuse(const string& svError, const uint64_t nNucleusID)
|
||||
{
|
||||
if (m_vRefuseList.empty())
|
||||
if (IsRefuseListValid())
|
||||
{
|
||||
m_vRefuseList.push_back(std::make_pair(svError, nNucleusID));
|
||||
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
|
||||
{
|
||||
for (size_t i = 0; i < m_vRefuseList.size(); i++)
|
||||
{
|
||||
if (m_vRefuseList[i].second != nNucleusID)
|
||||
{
|
||||
m_vRefuseList.push_back(std::make_pair(svError, nNucleusID));
|
||||
}
|
||||
}
|
||||
m_vRefuseList.push_back(std::make_pair(svError, nNucleusID));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: deletes an entry in the refuselist
|
||||
// Input : nNucleusID -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBanSystem::DeleteConnectionRefuse(const uint64_t nNucleusID)
|
||||
bool CBanSystem::DeleteConnectionRefuse(const uint64_t nNucleusID)
|
||||
{
|
||||
for (size_t i = 0; i < m_vRefuseList.size(); i++)
|
||||
if (IsRefuseListValid())
|
||||
{
|
||||
if (m_vRefuseList[i].second == nNucleusID)
|
||||
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(m_vRefuseList.begin() + i);
|
||||
m_vRefuseList.erase(it);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -194,11 +202,11 @@ void CBanSystem::BanListCheck(void)
|
||||
|
||||
string svIpAddress = pNetChan->GetAddress();
|
||||
|
||||
Warning(eDLL_T::SERVER, "Connection rejected for '%s' ('%llu' is banned from this server!)\n", svIpAddress.c_str(), pClient->GetNucleusID());
|
||||
NET_DisconnectClient(pClient, c, m_vRefuseList[i].first.c_str(), 0, true);
|
||||
|
||||
if (AddEntry(svIpAddress, pClient->GetNucleusID() && !bSave))
|
||||
Warning(eDLL_T::SERVER, "Removing client '%s' from slot '%hu' ('%llu' is banned from this server!)\n", svIpAddress.c_str(), pClient->GetHandle(), pClient->GetNucleusID());
|
||||
if (AddEntry(svIpAddress, pClient->GetNucleusID()) && !bSave)
|
||||
bSave = true;
|
||||
|
||||
NET_DisconnectClient(pClient, c, m_vRefuseList[i].first.c_str(), 0, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,17 +3,14 @@
|
||||
class CBanSystem
|
||||
{
|
||||
public:
|
||||
CBanSystem(void);
|
||||
void operator[](std::pair<const string&, const uint64_t> pair);
|
||||
|
||||
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);
|
||||
|
||||
void AddConnectionRefuse(const string& svError, const uint64_t nNucleusID);
|
||||
void DeleteConnectionRefuse(const uint64_t nNucleusID);
|
||||
bool AddConnectionRefuse(const string& svError, const uint64_t nNucleusID);
|
||||
bool DeleteConnectionRefuse(const uint64_t nNucleusID);
|
||||
|
||||
void BanListCheck(void);
|
||||
|
||||
|
@ -12,29 +12,10 @@
|
||||
#include <engine/server/server.h>
|
||||
#endif // !CLIENT_DLL
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Send keep alive request to Pylon Master Server.
|
||||
// NOTE: When Pylon update reaches indev remove this and implement properly.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool KeepAliveToPylon(const NetGameServer_t& netGameServer)
|
||||
{
|
||||
#ifndef CLIENT_DLL
|
||||
if (g_pServer->IsActive() && sv_pylonVisibility->GetBool()) // Check for active game.
|
||||
{
|
||||
string m_szHostToken;
|
||||
string m_szHostRequestMessage;
|
||||
|
||||
bool result = g_pMasterServer->PostServerHost(m_szHostRequestMessage, m_szHostToken, netGameServer);
|
||||
return result;
|
||||
}
|
||||
return false;
|
||||
#endif // !CLIENT_DLL
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: returns a vector of hosted servers.
|
||||
//-----------------------------------------------------------------------------
|
||||
vector<NetGameServer_t> CPylon::GetServerList(string& svOutMessage)
|
||||
vector<NetGameServer_t> CPylon::GetServerList(string& svOutMessage) const
|
||||
{
|
||||
vector<NetGameServer_t> vslList{};
|
||||
|
||||
@ -43,7 +24,7 @@ vector<NetGameServer_t> CPylon::GetServerList(string& svOutMessage)
|
||||
|
||||
string svRequestBody = jsRequestBody.dump(4);
|
||||
|
||||
if (pylon_showdebug->GetBool())
|
||||
if (pylon_showdebuginfo->GetBool())
|
||||
{
|
||||
DevMsg(eDLL_T::ENGINE, "%s - Sending server list request to comp-server:\n%s\n", __FUNCTION__, svRequestBody.c_str());
|
||||
}
|
||||
@ -51,7 +32,7 @@ vector<NetGameServer_t> CPylon::GetServerList(string& svOutMessage)
|
||||
httplib::Client htClient(pylon_matchmaking_hostname->GetString()); htClient.set_connection_timeout(10);
|
||||
httplib::Result htResult = htClient.Post("/servers", jsRequestBody.dump(4).c_str(), jsRequestBody.dump(4).length(), "application/json");
|
||||
|
||||
if (htResult && pylon_showdebug->GetBool())
|
||||
if (htResult && pylon_showdebuginfo->GetBool())
|
||||
{
|
||||
DevMsg(eDLL_T::ENGINE, "%s - Replied with '%d'.\n", __FUNCTION__, htResult->status);
|
||||
}
|
||||
@ -89,9 +70,9 @@ vector<NetGameServer_t> CPylon::GetServerList(string& svOutMessage)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (jsResultBody["err"].is_string())
|
||||
if (jsResultBody["error"].is_string())
|
||||
{
|
||||
svOutMessage = jsResultBody["err"].get<string>();
|
||||
svOutMessage = jsResultBody["error"].get<string>();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -107,9 +88,9 @@ vector<NetGameServer_t> CPylon::GetServerList(string& svOutMessage)
|
||||
{
|
||||
nlohmann::json jsResultBody = nlohmann::json::parse(htResult->body);
|
||||
|
||||
if (jsResultBody["err"].is_string())
|
||||
if (jsResultBody["error"].is_string())
|
||||
{
|
||||
svOutMessage = jsResultBody["err"].get<string>();
|
||||
svOutMessage = jsResultBody["error"].get<string>();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -135,116 +116,6 @@ vector<NetGameServer_t> CPylon::GetServerList(string& svOutMessage)
|
||||
return vslList;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Sends host server POST request.
|
||||
// Input : &svOutMessage -
|
||||
// &svOutToken -
|
||||
// &slServerListing -
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CPylon::PostServerHost(string& svOutMessage, string& svOutToken, const NetGameServer_t& slServerListing)
|
||||
{
|
||||
nlohmann::json jsRequestBody = nlohmann::json::object();
|
||||
jsRequestBody["name"] = slServerListing.m_svHostName;
|
||||
jsRequestBody["description"] = slServerListing.m_svDescription;
|
||||
jsRequestBody["hidden"] = slServerListing.m_bHidden;
|
||||
jsRequestBody["map"] = slServerListing.m_svHostMap;
|
||||
jsRequestBody["playlist"] = slServerListing.m_svPlaylist;
|
||||
jsRequestBody["ip"] = slServerListing.m_svIpAddress;
|
||||
jsRequestBody["port"] = slServerListing.m_svGamePort;
|
||||
jsRequestBody["key"] = slServerListing.m_svEncryptionKey;
|
||||
jsRequestBody["checksum"] = slServerListing.m_svRemoteChecksum;
|
||||
jsRequestBody["version"] = slServerListing.m_svSDKVersion;
|
||||
jsRequestBody["playerCount"] = slServerListing.m_svPlayerCount;
|
||||
jsRequestBody["maxPlayers"] = slServerListing.m_svMaxPlayers;
|
||||
jsRequestBody["timeStamp"] = slServerListing.m_nTimeStamp;
|
||||
jsRequestBody["publicRef"] = slServerListing.m_svPublicRef;
|
||||
jsRequestBody["cachedID"] = slServerListing.m_svCachedID;
|
||||
|
||||
string svRequestBody = jsRequestBody.dump(4);
|
||||
if (pylon_showdebug->GetBool())
|
||||
{
|
||||
DevMsg(eDLL_T::ENGINE, "%s - Sending post host request to comp-server:\n%s\n", __FUNCTION__, svRequestBody.c_str());
|
||||
}
|
||||
|
||||
httplib::Client htClient(pylon_matchmaking_hostname->GetString()); htClient.set_connection_timeout(10);
|
||||
httplib::Result htResult = htClient.Post("/servers/add", svRequestBody.c_str(), svRequestBody.length(), "application/json");
|
||||
|
||||
if (htResult && pylon_showdebug->GetBool())
|
||||
{
|
||||
DevMsg(eDLL_T::ENGINE, "%s - Comp-server replied with '%d'\n", __FUNCTION__, htResult->status);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (htResult && htResult->status == 200) // STATUS_OK
|
||||
{
|
||||
nlohmann::json jsResultBody = nlohmann::json::parse(htResult->body);
|
||||
if (jsResultBody["success"].is_boolean() && jsResultBody["success"].get<bool>())
|
||||
{
|
||||
if (jsResultBody["token"].is_string())
|
||||
{
|
||||
svOutToken = jsResultBody["token"].get<string>();
|
||||
}
|
||||
else
|
||||
{
|
||||
svOutToken = string();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (jsResultBody["err"].is_string())
|
||||
{
|
||||
svOutMessage = jsResultBody["err"].get<string>();
|
||||
}
|
||||
else
|
||||
{
|
||||
svOutMessage = "An unknown error occured!";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (htResult)
|
||||
{
|
||||
if (!htResult->body.empty())
|
||||
{
|
||||
nlohmann::json jsResultBody = nlohmann::json::parse(htResult->body);
|
||||
|
||||
if (jsResultBody["err"].is_string())
|
||||
{
|
||||
svOutMessage = jsResultBody["err"].get<string>();
|
||||
}
|
||||
else
|
||||
{
|
||||
svOutMessage = string("Failed to reach comp-server ") + std::to_string(htResult->status);
|
||||
}
|
||||
|
||||
svOutToken = string();
|
||||
return false;
|
||||
}
|
||||
|
||||
svOutToken = string();
|
||||
svOutMessage = string("Failed to reach comp-server: ") + std::to_string(htResult->status);
|
||||
return false;
|
||||
}
|
||||
|
||||
svOutToken = string();
|
||||
svOutMessage = "Failed to reach comp-server: connection timed-out";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
Warning(eDLL_T::ENGINE, "%s - Exception while parsing comp-server response:\n%s\n", __FUNCTION__, ex.what());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Gets the server by token string.
|
||||
// Input : &slOutServer -
|
||||
@ -252,14 +123,14 @@ bool CPylon::PostServerHost(string& svOutMessage, string& svOutToken, const NetG
|
||||
// svToken -
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CPylon::GetServerByToken(NetGameServer_t& slOutServer, string& svOutMessage, const string& svToken)
|
||||
bool CPylon::GetServerByToken(NetGameServer_t& slOutServer, string& svOutMessage, const string& svToken) const
|
||||
{
|
||||
nlohmann::json jsRequestBody = nlohmann::json::object();
|
||||
jsRequestBody["token"] = svToken;
|
||||
|
||||
string svRequestBody = jsRequestBody.dump(4);
|
||||
|
||||
if (pylon_showdebug->GetBool())
|
||||
if (pylon_showdebuginfo->GetBool())
|
||||
{
|
||||
DevMsg(eDLL_T::ENGINE, "%s - Sending token connect request to comp-server:\n%s\n", __FUNCTION__, svRequestBody.c_str());
|
||||
}
|
||||
@ -267,7 +138,7 @@ bool CPylon::GetServerByToken(NetGameServer_t& slOutServer, string& svOutMessage
|
||||
httplib::Client htClient(pylon_matchmaking_hostname->GetString()); htClient.set_connection_timeout(10);
|
||||
httplib::Result htResult = htClient.Post("/server/byToken", jsRequestBody.dump(4).c_str(), jsRequestBody.dump(4).length(), "application/json");
|
||||
|
||||
if (pylon_showdebug->GetBool())
|
||||
if (pylon_showdebuginfo->GetBool())
|
||||
{
|
||||
DevMsg(eDLL_T::ENGINE, "%s - Comp-server replied with '%d'\n", __FUNCTION__, htResult->status);
|
||||
}
|
||||
@ -304,9 +175,9 @@ bool CPylon::GetServerByToken(NetGameServer_t& slOutServer, string& svOutMessage
|
||||
}
|
||||
else
|
||||
{
|
||||
if (jsResultBody["err"].is_string())
|
||||
if (jsResultBody["error"].is_string())
|
||||
{
|
||||
svOutMessage = jsResultBody["err"].get<string>();
|
||||
svOutMessage = jsResultBody["error"].get<string>();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -326,9 +197,9 @@ bool CPylon::GetServerByToken(NetGameServer_t& slOutServer, string& svOutMessage
|
||||
{
|
||||
nlohmann::json jsResultBody = nlohmann::json::parse(htResult->body);
|
||||
|
||||
if (jsResultBody["err"].is_string())
|
||||
if (jsResultBody["error"].is_string())
|
||||
{
|
||||
svOutMessage = jsResultBody["err"].get<string>();
|
||||
svOutMessage = jsResultBody["error"].get<string>();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -355,14 +226,144 @@ bool CPylon::GetServerByToken(NetGameServer_t& slOutServer, string& svOutMessage
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Sends host server POST request.
|
||||
// Input : &svOutMessage -
|
||||
// &svOutToken -
|
||||
// &slServerListing -
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CPylon::PostServerHost(string& svOutMessage, string& svOutToken, const NetGameServer_t& slServerListing) const
|
||||
{
|
||||
nlohmann::json jsRequestBody = nlohmann::json::object();
|
||||
jsRequestBody["name"] = slServerListing.m_svHostName;
|
||||
jsRequestBody["description"] = slServerListing.m_svDescription;
|
||||
jsRequestBody["hidden"] = slServerListing.m_bHidden;
|
||||
jsRequestBody["map"] = slServerListing.m_svHostMap;
|
||||
jsRequestBody["playlist"] = slServerListing.m_svPlaylist;
|
||||
jsRequestBody["ip"] = slServerListing.m_svIpAddress;
|
||||
jsRequestBody["port"] = slServerListing.m_svGamePort;
|
||||
jsRequestBody["key"] = slServerListing.m_svEncryptionKey;
|
||||
jsRequestBody["checksum"] = slServerListing.m_svRemoteChecksum;
|
||||
jsRequestBody["version"] = slServerListing.m_svSDKVersion;
|
||||
jsRequestBody["playerCount"] = slServerListing.m_svPlayerCount;
|
||||
jsRequestBody["maxPlayers"] = slServerListing.m_svMaxPlayers;
|
||||
jsRequestBody["timeStamp"] = slServerListing.m_nTimeStamp;
|
||||
jsRequestBody["publicRef"] = slServerListing.m_svPublicRef;
|
||||
jsRequestBody["cachedID"] = slServerListing.m_svCachedID;
|
||||
|
||||
string svRequestBody = jsRequestBody.dump(4);
|
||||
if (pylon_showdebuginfo->GetBool())
|
||||
{
|
||||
DevMsg(eDLL_T::ENGINE, "%s - Sending post host request to comp-server:\n%s\n", __FUNCTION__, svRequestBody.c_str());
|
||||
}
|
||||
|
||||
httplib::Client htClient(pylon_matchmaking_hostname->GetString()); htClient.set_connection_timeout(10);
|
||||
httplib::Result htResult = htClient.Post("/servers/add", svRequestBody.c_str(), svRequestBody.length(), "application/json");
|
||||
|
||||
if (htResult && pylon_showdebuginfo->GetBool())
|
||||
{
|
||||
DevMsg(eDLL_T::ENGINE, "%s - Comp-server replied with '%d'\n", __FUNCTION__, htResult->status);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (htResult && htResult->status == 200) // STATUS_OK
|
||||
{
|
||||
nlohmann::json jsResultBody = nlohmann::json::parse(htResult->body);
|
||||
if (jsResultBody["success"].is_boolean() && jsResultBody["success"].get<bool>())
|
||||
{
|
||||
if (jsResultBody["token"].is_string())
|
||||
{
|
||||
svOutToken = jsResultBody["token"].get<string>();
|
||||
}
|
||||
else
|
||||
{
|
||||
svOutToken = string();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (jsResultBody["error"].is_string())
|
||||
{
|
||||
svOutMessage = jsResultBody["error"].get<string>();
|
||||
}
|
||||
else
|
||||
{
|
||||
svOutMessage = "An unknown error occured!";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (htResult)
|
||||
{
|
||||
if (!htResult->body.empty())
|
||||
{
|
||||
nlohmann::json jsResultBody = nlohmann::json::parse(htResult->body);
|
||||
|
||||
if (jsResultBody["error"].is_string())
|
||||
{
|
||||
svOutMessage = jsResultBody["error"].get<string>();
|
||||
}
|
||||
else
|
||||
{
|
||||
svOutMessage = string("Failed to reach comp-server ") + std::to_string(htResult->status);
|
||||
}
|
||||
|
||||
svOutToken = string();
|
||||
return false;
|
||||
}
|
||||
|
||||
svOutToken = string();
|
||||
svOutMessage = string("Failed to reach comp-server: ") + std::to_string(htResult->status);
|
||||
return false;
|
||||
}
|
||||
|
||||
svOutToken = string();
|
||||
svOutMessage = "Failed to reach comp-server: connection timed-out";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
Warning(eDLL_T::ENGINE, "%s - Exception while parsing comp-server response:\n%s\n", __FUNCTION__, ex.what());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Send keep alive request to Pylon Master Server.
|
||||
// Input : &netGameServer -
|
||||
// Output : Returns true on success, false otherwise.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CPylon::KeepAlive(const NetGameServer_t& netGameServer) const
|
||||
{
|
||||
#ifndef CLIENT_DLL
|
||||
if (g_pServer->IsActive() && sv_pylonVisibility->GetBool()) // Check for active game.
|
||||
{
|
||||
string m_szHostToken;
|
||||
string m_szHostRequestMessage;
|
||||
|
||||
bool result = g_pMasterServer->PostServerHost(m_szHostRequestMessage, m_szHostToken, netGameServer);
|
||||
return result;
|
||||
}
|
||||
return false;
|
||||
#endif // !CLIENT_DLL
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Checks if client is banned on the comp server.
|
||||
// Input : svIpAddress -
|
||||
// nNucleusID -
|
||||
// &svOutErrCl -
|
||||
// &svOutReason -
|
||||
// Output : Returns true if banned, false if not banned.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CPylon::CheckForBan(const string& svIpAddress, uint64_t nNucleusID, string& svOutErrCl)
|
||||
bool CPylon::CheckForBan(const string& svIpAddress, const uint64_t nNucleusID, string& svOutReason) const
|
||||
{
|
||||
nlohmann::json jsRequestBody = nlohmann::json::object();
|
||||
jsRequestBody["id"] = nNucleusID;
|
||||
@ -380,7 +381,7 @@ bool CPylon::CheckForBan(const string& svIpAddress, uint64_t nNucleusID, string&
|
||||
{
|
||||
if (jsResultBody["banned"].is_boolean() && jsResultBody["banned"].get<bool>())
|
||||
{
|
||||
svOutErrCl = jsResultBody.value("errCl", "#DISCONNECT_BANNED");
|
||||
svOutReason = jsResultBody.value("reason", "#DISCONNECT_BANNED");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -6,9 +6,10 @@ bool KeepAliveToPylon(const NetGameServer_t& netGameServer);
|
||||
class CPylon
|
||||
{
|
||||
public:
|
||||
vector<NetGameServer_t> GetServerList(string& svOutMessage);
|
||||
bool PostServerHost(string& svOutMessage, string& svOutToken, const NetGameServer_t& slServerListing);
|
||||
bool GetServerByToken(NetGameServer_t& slOutServer, string& svOutMessage, const string& svToken);
|
||||
bool CheckForBan(const string& svIpAddress, uint64_t nNucleusID, string& svOutErrCl);
|
||||
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& slServerListing) const;
|
||||
bool KeepAlive(const NetGameServer_t& netGameServer) const;
|
||||
bool CheckForBan(const string& svIpAddress, const uint64_t nNucleusID, string& svOutReason) const;
|
||||
};
|
||||
extern CPylon* g_pMasterServer;
|
||||
|
@ -1020,6 +1020,7 @@ playlists
|
||||
"PROMO_SDK_ERROR" "You should not see this."
|
||||
|
||||
"DISCONNECT_BANNED" "The client's game account has been banned: Banned"
|
||||
"VALVE_REJECT_BANNED" "You have been banned from this server."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -197,12 +197,12 @@ void ConVar::Init(void) const
|
||||
// NETCHANNEL |
|
||||
net_tracePayload = ConVar::Create("net_tracePayload" , "0", FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT , "Log the payload of the send/recv datagram to a file on the disk.", false, 0.f, false, 0.f, nullptr, nullptr);
|
||||
net_encryptionEnable = ConVar::Create("net_encryptionEnable" , "1", FCVAR_DEVELOPMENTONLY | FCVAR_REPLICATED , "Use AES encryption on game packets.", false, 0.f, false, 0.f, nullptr, nullptr);
|
||||
net_useRandomKey = ConVar::Create("net_useRandomKey" , "1" , FCVAR_RELEASE , "Use random base64 netkey for game packets.", false, 0.f, false, 0.f, nullptr, nullptr);
|
||||
net_useRandomKey = ConVar::Create("net_useRandomKey" , "1" , FCVAR_RELEASE , "Use random AES encryption key for game packets.", false, 0.f, false, 0.f, &NET_UseRandomKeyChanged_f, nullptr);
|
||||
//-------------------------------------------------------------------------
|
||||
// NETWORKSYSTEM |
|
||||
pylon_matchmaking_hostname = ConVar::Create("pylon_matchmaking_hostname", "r5a-comp-sv.herokuapp.com", FCVAR_RELEASE , "Holds the pylon matchmaking hostname.", false, 0.f, false, 0.f, &MP_HostName_Changed_f, nullptr);
|
||||
pylon_host_update_interval = ConVar::Create("pylon_host_update_interval", "5" , FCVAR_RELEASE , "Length of time in seconds between each status update interval to master server.", true, 5.f, false, 0.f, nullptr, nullptr);
|
||||
pylon_showdebug = ConVar::Create("pylon_showdebug" , "0" , FCVAR_DEVELOPMENTONLY, "Shows debug output for pylon.", false, 0.f, false, 0.f, nullptr, nullptr);
|
||||
pylon_showdebuginfo = ConVar::Create("pylon_showdebuginfo" , "0" , FCVAR_DEVELOPMENTONLY, "Shows debug output for pylon.", false, 0.f, false, 0.f, nullptr, nullptr);
|
||||
//-------------------------------------------------------------------------
|
||||
// RTECH API |
|
||||
rtech_debug = ConVar::Create("rtech_debug", "0", FCVAR_DEVELOPMENTONLY, "Shows debug output for the RTech system.", false, 0.f, false, 0.f, nullptr, nullptr);
|
||||
|
@ -168,7 +168,7 @@ ConVar* net_useRandomKey = nullptr;
|
||||
ConVar* net_usesocketsforloopback = nullptr;
|
||||
ConVar* pylon_matchmaking_hostname = nullptr;
|
||||
ConVar* pylon_host_update_interval = nullptr;
|
||||
ConVar* pylon_showdebug = nullptr;
|
||||
ConVar* pylon_showdebuginfo = nullptr;
|
||||
//-----------------------------------------------------------------------------
|
||||
// RTECH API |
|
||||
ConVar* rtech_debug = nullptr;
|
||||
|
@ -163,7 +163,7 @@ extern ConVar* net_useRandomKey;
|
||||
extern ConVar* net_usesocketsforloopback;
|
||||
extern ConVar* pylon_matchmaking_hostname;
|
||||
extern ConVar* pylon_host_update_interval;
|
||||
extern ConVar* pylon_showdebug;
|
||||
extern ConVar* pylon_showdebuginfo;
|
||||
//-------------------------------------------------------------------------
|
||||
// RTECH API |
|
||||
extern ConVar* rtech_debug;
|
||||
|
Loading…
x
Reference in New Issue
Block a user