Refactoring

Fix first prevhash
For the future implemented config and task
This commit is contained in:
s1lentq 2015-11-13 05:01:02 +06:00
parent 92c1719982
commit d025e0edd4
19 changed files with 617 additions and 284 deletions

5
dist/config.ini vendored Normal file
View File

@ -0,0 +1,5 @@
#
# delay_exec 0|60 Delay before executing the all cmdexec
#
delay_exec = 3.5

31
dist/resources.ini vendored Normal file
View File

@ -0,0 +1,31 @@
#
# Resource checker
# -> Template keys from CMD exec
# [name] - nickname client
# [ip] - IP address client
# [userid] - userid client
# [steamid] - SteamID client
#
# [file_name] - the path of the file
# [file_hash] - hash the file of responce client
#
# -> Format
# path to file hash (exec cmd)
# "../opengl32.dll" c8005c526355d8015d462dc7f4ddb159 "kick [userid]"
#
# NOTE: Hash enough 4 bytes (or 8 characters)
# -> Example
# full md5 hash: c8005c526355d8015d462dc7f4ddb159
# 4 bytes from the hash: c8005c52
#
# -> Flags
# BREAK - when detected, do not check a next files
# IGNORE - no detect on specifed hash values
#
# -> Template keys from Hash
# UNKNOWN - check for any other hash
# 00000000 - check for the missing file
# c8005c52 - check for matching on hash
#
"../opengl32.dll" UNKNOWN "kick [userid]"

View File

@ -149,6 +149,10 @@ typedef IHookChainRegistry<bool, IGameClient *, resource_t *, uint32> IRehldsHoo
typedef IVoidHookChain<IGameClient*, bool, const char*> IRehldsHook_SV_DropClient;
typedef IVoidHookChainRegistry<IGameClient*, bool, const char*> IRehldsHookRegistry_SV_DropClient;
//SV_ActivateServer hook
typedef IVoidHookChain<int> IRehldsHook_SV_ActivateServer;
typedef IVoidHookChainRegistry<int> IRehldsHookRegistry_SV_ActivateServer;
class IRehldsHookchains {
public:
virtual ~IRehldsHookchains() { }
@ -181,6 +185,7 @@ public:
virtual IRehldsHookRegistry_SV_WriteFullClientUpdate* SV_WriteFullClientUpdate() = 0;
virtual IRehldsHookRegistry_SV_CheckConsistencyResponce* SV_CheckConsistencyResponce() = 0;
virtual IRehldsHookRegistry_SV_DropClient* SV_DropClient() = 0;
virtual IRehldsHookRegistry_SV_ActivateServer* SV_ActivateServer() = 0;
};
struct RehldsFuncs_t {

View File

@ -115,4 +115,6 @@ public:
virtual void SetModelName(const char* modelname) = 0;
virtual void SetConsistencyNum(int num) = 0;
virtual int GetConsistencyNum() = 0;
virtual int GetResourcesNum() = 0;
virtual int GetDecalNameNum() = 0;
};

View File

@ -164,21 +164,35 @@
<ClInclude Include="..\public\FileSystem.h" />
<ClInclude Include="..\public\interface.h" />
<ClInclude Include="..\src\cmdexec.h" />
<ClInclude Include="..\src\config.h">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClInclude>
<ClInclude Include="..\src\resource.h" />
<ClInclude Include="..\src\engine_rehlds.h" />
<ClInclude Include="..\src\main.h" />
<ClInclude Include="..\src\precompiled.h" />
<ClInclude Include="..\src\task.h">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\common\parsemsg.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\public\interface.cpp" />
<ClCompile Include="..\src\cmdexec.cpp" />
<ClCompile Include="..\src\config.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\src\resource.cpp" />
<ClCompile Include="..\src\dllapi.cpp" />
<ClCompile Include="..\src\engine_api.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\src\engine_rehlds.cpp" />
<ClCompile Include="..\src\h_export.cpp" />
@ -186,8 +200,17 @@
<ClCompile Include="..\src\meta_api.cpp" />
<ClCompile Include="..\src\precompiled.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\src\sdk_util.cpp" />
<ClCompile Include="..\src\task.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\dist\config.ini" />
<None Include="..\dist\resources.ini" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{9A72E8DC-7667-46C1-899D-1E8B939564D2}</ProjectGuid>
@ -266,14 +289,14 @@ REM IF EXIST "$(ProjectDir)ServerStart_cs_6153.bat" (CALL "$(ProjectDir)ServerSt
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)../src/;$(SolutionDir)../src/sdk;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)../src/;$(SolutionDir)../common/;$(SolutionDir)../dlls/;$(SolutionDir)../engine/;$(SolutionDir)../pm_shared/;$(SolutionDir)../public/;$(SolutionDir)../metamod/;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeaderFile>precompiled.h</PrecompiledHeaderFile>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<OmitFramePointers>true</OmitFramePointers>
<StringPooling>true</StringPooling>
<ExceptionHandling>false</ExceptionHandling>
<ExceptionHandling>Sync</ExceptionHandling>
<BufferSecurityCheck>false</BufferSecurityCheck>
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
<DisableSpecificWarnings>

View File

@ -462,6 +462,8 @@
<ClInclude Include="..\src\engine_rehlds.h" />
<ClInclude Include="..\src\cmdexec.h" />
<ClInclude Include="..\src\resource.h" />
<ClInclude Include="..\src\config.h" />
<ClInclude Include="..\src\task.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\common\parsemsg.cpp">
@ -480,6 +482,8 @@
<ClCompile Include="..\src\sdk_util.cpp" />
<ClCompile Include="..\src\cmdexec.cpp" />
<ClCompile Include="..\src\resource.cpp" />
<ClCompile Include="..\src\config.cpp" />
<ClCompile Include="..\src\task.cpp" />
</ItemGroup>
<ItemGroup>
<Filter Include="sdk">
@ -503,5 +507,16 @@
<Filter Include="sdk\engine">
<UniqueIdentifier>{1bb5b890-a282-419e-912a-26d9d8fccf5b}</UniqueIdentifier>
</Filter>
<Filter Include="dist">
<UniqueIdentifier>{d8dea905-0ad8-4f5e-973c-fc9917c49e68}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<None Include="..\dist\resources.ini">
<Filter>dist</Filter>
</None>
<None Include="..\dist\config.ini">
<Filter>dist</Filter>
</None>
</ItemGroup>
</Project>

View File

@ -1,29 +1,28 @@
#include "precompiled.h"
CExecManager Exec;
CExecMngr Exec;
CBufExec::CBufExec(IGameClient *pClient, CResourceBuffer *pResource, uint32 responseHash)
CExecMngr::CBufExec::CBufExec(IGameClient *pClient, CResourceBuffer *pResource, uint32 responseHash)
{
m_pClient = pClient;
m_pResource = pResource;
m_ClientHash = responseHash;
}
CBufExec::~CBufExec()
CExecMngr::CBufExec::~CBufExec()
{
;
}
void CExecManager::AddElement(IGameClient *pClient, CResourceBuffer *pResource, uint32 responseHash)
void CExecMngr::AddElement(IGameClient *pClient, CResourceBuffer *pResource, uint32 responseHash)
{
m_execList.push_back(new CBufExec(pClient, pResource, responseHash));
}
void StringReplace(char *src, const char *strold, const char *strnew)
{
if (strnew == NULL) {
if (strnew == NULL)
return;
}
char *p = src;
int oldLen = strlen(strold), newLen = strlen(strnew);
@ -44,6 +43,10 @@ char *GetExecCmdPrepare(IGameClient *pClient, CResourceBuffer *pResource, uint32
const netadr_t *net;
static char string[256];
// check cmdexec is empty
if (pResource->GetCmdExec() == NULL)
return NULL;
strncpy(string, pResource->GetCmdExec(), sizeof(string) - 1);
string[sizeof(string) - 1] = '\0';
@ -61,16 +64,15 @@ char *GetExecCmdPrepare(IGameClient *pClient, CResourceBuffer *pResource, uint32
len = strlen(string);
if (len < sizeof(string) - 2) {
if (len < sizeof(string) - 2)
strcat(string, "\n");
}
else
string[len - 1] = '\n';
return string;
}
void CExecManager::CommandExecute(IGameClient *pClient)
void CExecMngr::CommandExecute(IGameClient *pClient)
{
bool bBreak = false;
auto iter = m_execList.begin();
@ -79,7 +81,8 @@ void CExecManager::CommandExecute(IGameClient *pClient)
{
CBufExec *pExec = (*iter);
if (pExec->GetGameClient() != pClient) {
if (pExec->GetGameClient() != pClient)
{
iter++;
continue;
}
@ -88,38 +91,31 @@ void CExecManager::CommandExecute(IGameClient *pClient)
// exit the loop if the client is out of the game
// TODO: Check me!
if (!pClient->IsConnected()) {
if (!pClient->IsConnected())
{
break;
}
char *cmdExec = GetExecCmdPrepare(pClient, pRes, pExec->GetClientHash());
// erase all cmdexec because have flag is break
if (bBreak) {
// erase cmd exec
delete pExec;
iter = m_execList.erase(iter);
continue;
}
if (cmdExec != NULL && cmdExec[0] != '\0') {
if (!bBreak // erase all cmdexec because have flag is break
&& cmdExec != NULL && cmdExec[0] != '\0')
{
// execute cmdexec
SERVER_COMMAND(cmdExec);
// erase cmdexec
delete pExec;
iter = m_execList.erase(iter);
}
else
iter++;
bBreak = (pRes->GetFileFlags() & FLAG_TYPE_BREAK) == FLAG_TYPE_BREAK;
// erase cmdexec
delete pExec;
iter = m_execList.erase(iter);
bBreak = (pRes->GetFileFlag() == FLAG_TYPE_BREAK);
}
}
void CExecManager::Clear(IGameClient *pClient)
void CExecMngr::Clear(IGameClient *pClient)
{
if (pClient == NULL) {
if (pClient == NULL)
{
m_execList.clear();
return;
}
@ -130,7 +126,8 @@ void CExecManager::Clear(IGameClient *pClient)
CBufExec *pExec = (*iter);
// erase cmdexec
if (pExec->GetGameClient() == pClient) {
if (pExec->GetGameClient() == pClient)
{
delete pExec;
iter = m_execList.erase(iter);
}

View File

@ -1,22 +1,6 @@
#pragma once
class CBufExec
{
public:
CBufExec(IGameClient *pClient, CResourceBuffer *pResource, uint32 responseHash);
~CBufExec();
IGameClient *GetGameClient() const { return m_pClient; };
CResourceBuffer *GetResource() const { return m_pResource; };
uint32 GetClientHash() const { return m_ClientHash; };
private:
IGameClient *m_pClient;
CResourceBuffer *m_pResource;
uint32 m_ClientHash;
};
class CExecManager
class CExecMngr
{
public:
void AddElement(IGameClient *pClient, CResourceBuffer *pResource, uint32 responseHash);
@ -24,10 +8,26 @@ public:
void Clear(IGameClient *pClient = NULL);
private:
class CBufExec
{
public:
CBufExec(IGameClient *pClient, CResourceBuffer *pResource, uint32 responseHash);
~CBufExec();
IGameClient *GetGameClient() const { return m_pClient; };
CResourceBuffer *GetResource() const { return m_pResource; };
uint32 GetClientHash() const { return m_ClientHash; };
private:
IGameClient *m_pClient;
CResourceBuffer *m_pResource;
uint32 m_ClientHash;
};
typedef std::list<CBufExec *> CBufExecList;
CBufExecList m_execList;
};
extern CExecManager Exec;
extern CExecMngr Exec;
extern void StringReplace(char *src, const char *strold, const char *strnew);

101
src/config.cpp Normal file
View File

@ -0,0 +1,101 @@
#include "precompiled.h"
#define TRY_READ_INT(a,b,min,max) if (_stricmp(argv[0], ##a) == 0) b = clamp(atoi(argv[1]), min, max);
#define TRY_READ_FLOAT(a,b,min,max) if (_stricmp(argv[0], ##a) == 0) b = clamp(atof(argv[1]), min, max);
#define TRY_READ_STRING(a,b) if (_stricmp(argv[0], ##a) == 0) strncpy(b, argv[1], sizeof(b) - 1); b[sizeof(b) - 1] = '\0';
CConfig Config;
void CConfig::Init()
{
char *pos;
char path[MAX_PATH_LENGTH];
strncpy(path, GET_PLUGIN_PATH(PLID), sizeof(path) - 1);
path[sizeof(path) - 1] = '\0';
pos = strrchr(path, '/');
if (*pos == '\0')
return;
*(pos + 1) = '\0';
// config.ini
snprintf(m_PathDir, sizeof(m_PathDir), "%s" FILE_INI_CONFIG, path);
}
int parse(char *line, char **argv, int max_args)
{
int count = 0;
while (*line)
{
// null whitespaces
while (*line == ' ' || *line == '\t' || *line == '\n' || *line == '\r' || *line == '=' || *line == '"')
*line++ = '\0';
if (*line)
{
// save arg address
argv[count++] = line;
if (count == max_args)
break;
// skip arg
while (*line != '\0' && *line != ' ' && *line != '\t' && *line != '\n' && *line != '\r' && *line != '=' && *line != '"')
line++;
}
}
return count;
}
void CConfig::ResetValues()
{
m_DelayExec = 2.5f;
// [..]
}
void CConfig::Load()
{
FILE *fp;
char line[1024];
char *argv[3];
int argc;
char *pos;
// reset config
ResetValues();
fp = fopen(m_PathDir, "rt");
if (fp == NULL)
{
m_ConfigFailed = true;
UTIL_Printf(__FUNCTION__ ": can't find path to " FILE_INI_CONFIG "\n");
return;
}
while (!feof(fp) && fgets(line, sizeof(line), fp))
{
pos = line;
if (*pos == '\0' || *pos == ';' || *pos == '\\' || *pos == '/' || *pos == '#')
continue;
if ((pos = strchr(line, ';')) != NULL || (pos = strstr(line, "//")) != NULL)
*pos = '\0';
argc = parse(line, argv, ARRAYSIZE(argv));
if (argc != 2)
continue;
else TRY_READ_FLOAT("delay_exec", m_DelayExec, 0.0, 60.0)
}
fclose(fp);
m_ConfigFailed = false;
}

28
src/config.h Normal file
View File

@ -0,0 +1,28 @@
#pragma once
#define FILE_INI_CONFIG "config.ini"
class CConfig
{
public:
void Init();
void Load();
float GetDelay() const { return m_DelayExec; };
bool IsConfigLoaded() const { return !m_ConfigFailed; };
private:
void ResetValues();
private:
bool m_ConfigFailed;
char m_PathDir[MAX_PATH_LENGTH];
// settings
float m_DelayExec;
};
template <typename T>
T clamp(T a, T min, T max) { return (a > max) ? max : (a < min) ? min : a; }
extern CConfig Config;

View File

@ -2,10 +2,7 @@
DLL_FUNCTIONS *g_pFunctionTable;
extern qboolean ClientConnect_Post(edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[128]);
extern void ServerDeactivate_Post();
extern void ServerActivate_Post(edict_t *pEdictList, int edictCount, int clientMax);
extern void ClientPutInServer_Post(edict_t *pEntity);
static DLL_FUNCTIONS gFunctionTable =
@ -92,13 +89,13 @@ static DLL_FUNCTIONS gFunctionTable_Post =
NULL, // pfnRestoreGlobalState
NULL, // pfnResetGlobalState
&ClientConnect_Post, // pfnClientConnect
NULL, // pfnClientConnect
NULL, // pfnClientDisconnect
NULL, // pfnClientKill
&ClientPutInServer_Post, // pfnClientPutInServer
NULL, // pfnClientCommand
NULL, // pfnClientUserInfoChanged
&ServerActivate_Post, // pfnServerActivate
NULL, // pfnServerActivate
&ServerDeactivate_Post, // pfnServerDeactivate
NULL, // pfnPlayerPreThink

View File

@ -1,45 +1,44 @@
#include "precompiled.h"
bool g_bInitialized = false;
cvar_t mp_consistency = { "mp_consistency", "0", 0, 0.0f, NULL };
void SV_DropClient(IRehldsHook_SV_DropClient *chain, IGameClient *pClient, bool crash, const char *string);
bool SV_CheckConsistencyResponce(IRehldsHook_SV_CheckConsistencyResponce *chain, IGameClient *pSenderClient, resource_t *resource, uint32 hash);
void (*SV_AddResource)(resourcetype_t type, const char *name, int size, unsigned char flags, int index);
bool OnMetaAttach()
{
if (RehldsApi_Init() != RETURN_LOAD) {
if (RehldsApi_Init() != RETURN_LOAD)
return false;
}
// register function from ReHLDS API
g_RehldsApi->GetHookchains()->SV_CheckConsistencyResponce()->registerHook(&SV_CheckConsistencyResponce);
g_RehldsApi->GetHookchains()->SV_DropClient()->registerHook(&SV_DropClient);
g_RehldsApi->GetHookchains()->SV_ActivateServer()->registerHook(&SV_ActivateServer);
g_RehldsApi->GetHookchains()->SV_CheckConsistencyResponce()->registerHook(&SV_CheckConsistencyResponce);
SV_AddResource = g_RehldsApi->GetFuncs()->SV_AddResource;
// initialize resource config
Resource.Init();
/*
// initialize config
Config.Init();
*/
// set force cvar on own value and replacement of original
// NOTE: in gamedll used this cvar not through a pointer thus we create own cvar for gamedll with default values
// so for engine set it the cvar values is 1.
cvar_t *mp_consistency_old = g_engfuncs.pfnCVarGetPointer("mp_consistency");
cvar_t mp_consistency = {
mp_consistency_old->name,
mp_consistency_old->string,
mp_consistency_old->flags,
mp_consistency_old->value,
NULL
};
mp_consistency.value = mp_consistency_old->value;
mp_consistency.string = mp_consistency_old->string;
mp_consistency.flags = mp_consistency_old->flags;
mp_consistency_old->name = "mp_consistency_orig";
g_engfuncs.pfnCVarRegister(&mp_consistency);
g_engfuncs.pfnCvar_DirectSet(mp_consistency_old, "1");
// if is OK go to attach
return Resource.IsConfigLoaded();
// if all config's is OK go to attach
return (Resource.IsConfigLoaded()/* && Config.IsConfigLoaded()*/);
}
void OnMetaDetach()
@ -48,74 +47,87 @@ void OnMetaDetach()
// clear
Exec.Clear();
/*Task.Clear();*/
Resource.Clear();
}
void ServerDeactivate_Post()
{
if (g_bInitialized) {
// clear
Exec.Clear();
Resource.Clear();
g_bInitialized = false;
}
// clear
Exec.Clear();
/*Task.Clear();*/
Resource.Clear();
SET_META_RESULT(MRES_IGNORED);
}
void ServerActivate_Post(edict_t *pEdictList, int edictCount, int clientMax)
{
Resource.Load();
SET_META_RESULT(MRES_IGNORED);
}
void SV_DropClient(IRehldsHook_SV_DropClient *chain, IGameClient *pClient, bool crash, const char *string)
{
if (pClient != NULL) { // TODO: sure?
// clear buffer cmdexec the client when was disconnected up to perform cmdexec
Exec.Clear(pClient);
}
// clear buffer cmdexec the client when was disconnected up to perform cmdexec
Exec.Clear(pClient);
/*Task.Clear(pClient);*/
// call next hook
chain->callNext(pClient, crash, string);
}
/*
void StartFrame()
{
Task.StartFrame();
SET_META_RESULT(MRES_IGNORED);
}
*/
void SV_ActivateServer(IRehldsHook_SV_ActivateServer *chain, int runPhysics)
{
/*Config.Load();*/
Resource.LoadResources();
chain->callNext(runPhysics);
// add to the resource
Resource.CreateResourceList();
}
/*
void TaskHandler(IGameClient *pClient)
{
if (!pClient->IsConnected())
return;
// client is connected to putinserver, go execute cmd out buffer
Exec.CommandExecute(pClient);
}
*/
void ClientPutInServer_Post(edict_t *pEntity)
{
int nIndex = ENTINDEX(pEntity) - 1;
if (nIndex < 0 || nIndex >= gpGlobals->maxClients) {
if (nIndex < 0 || nIndex >= gpGlobals->maxClients)
RETURN_META(MRES_IGNORED);
}
IGameClient *pClient = g_RehldsApi->GetServerStatic()->GetClient(nIndex);
if (pClient != NULL) {
/*
float time = Config.GetDelay();
if (time <= 0.0f)
*/
// client is connected to putinserver, go execute cmd out buffer
Exec.CommandExecute(pClient);
}
/*
else
Task.AddTask(pClient, time, (xtask_t)TaskHandler);
*/
SET_META_RESULT(MRES_IGNORED);
}
qboolean ClientConnect_Post(edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[128])
{
if (!g_bInitialized) {
Resource.Add();
g_bInitialized = true;
}
SET_META_RESULT(MRES_IGNORED);
return META_RESULT_ORIG_RET(qboolean);
}
bool SV_CheckConsistencyResponce(IRehldsHook_SV_CheckConsistencyResponce *chain, IGameClient *pSenderClient, resource_t *resource, uint32 hash)
{
if (resource->type == t_decal) {
if (!Resource.FileConsistencyResponce(pSenderClient, resource, hash))
return false;
}
if (!Resource.FileConsistencyResponce(pSenderClient, resource, hash))
return false;
// call next hook and take return of values from original func
return chain->callNext(pSenderClient, resource, hash);

View File

@ -1,3 +1,11 @@
#pragma once
void StartFrame();
void SV_ActivateServer(IRehldsHook_SV_ActivateServer *chain, int runPhysics);
void SV_DropClient(IRehldsHook_SV_DropClient *chain, IGameClient *pClient, bool crash, const char *string);
bool SV_CheckConsistencyResponce(IRehldsHook_SV_CheckConsistencyResponce *chain, IGameClient *pSenderClient, resource_t *resource, uint32 hash);
/*
extern DLL_FUNCTIONS *g_pFunctionTable;
*/
extern void (*SV_AddResource)(resourcetype_t type, const char *name, int size, unsigned char flags, int index);

View File

@ -8,7 +8,7 @@ plugin_info_t Plugin_info =
__DATE__,
"s1lent",
"http://www.dedicated-server.ru/",
"ReChecker",
"Rechecker",
PT_STARTUP,
PT_NEVER,
};

View File

@ -8,6 +8,8 @@
#undef __FUNCTION__
#endif // _WIN32
#define MAX_PATH_LENGTH 260
#include <list>
#include <vector>
#include <cstring> // strrchr
@ -21,7 +23,10 @@
#include "rehlds_api.h"
#include "engine_rehlds.h"
#include "main.h"
//#include "main.h"
//#include "task.h"
#include "config.h"
#include "resource.h"
#include "cmdexec.h"
//#include "sdk_util.h" // UTIL_LogPrintf, etc

View File

@ -3,27 +3,35 @@
CResourceFile Resource;
std::vector<const char *> StringsCache;
void CResourceFile::Add()
void CResourceFile::CreateResourceList()
{
int nConsistency = g_RehldsServerData->GetConsistencyNum();
m_DecalsNum = g_RehldsServerData->GetDecalNameNum();
for (auto iter = m_resourceList.cbegin(); iter != m_resourceList.cend(); ++iter)
for (auto iter = m_resourceList.cbegin(), end = m_resourceList.cend(); iter != end; ++iter)
{
CResourceBuffer *pRes = (*iter);
// prevent duplicate of filenames
// check if filename is been marked so do not add the resource again
if (!pRes->IsDuplicate()) {
//#ifdef _DEBUG
if (CVAR_GET_FLOAT("developer") == 1.0f) {
UTIL_Printf(__FUNCTION__ " :: (%s)(%s)(%x)\n", pRes->GetFileName(), pRes->GetCmdExec(), pRes->GetFileHash());
if (!pRes->IsDuplicate())
{
// check limit resource
if (g_RehldsServerData->GetResourcesNum() >= MAX_RESOURCE_LIST)
{
UTIL_Printf(__FUNCTION__ ": can't add resource \"%s\" on line %d; exceeded the limit of resources max '%d'\n", pRes->GetFileName(), pRes->GetLine(), MAX_RESOURCE_LIST);
break;
}
//#endif // _DEBUG
SV_AddResource(t_decal, pRes->GetFileName(), 0, RES_CHECKFILE, 4095);
#ifdef _DEBUG
UTIL_Printf(__FUNCTION__ " :: (%s)(%s)(%x)\n", pRes->GetFileName(), pRes->GetCmdExec(), pRes->GetFileHash());
#endif // _DEBUG
SV_AddResource(t_decal, pRes->GetFileName(), 0, RES_CHECKFILE, m_DecalsNum++);
nConsistency++;
}
}
m_DecalsNum = g_RehldsServerData->GetDecalNameNum();
g_RehldsServerData->SetConsistencyNum(nConsistency);
}
@ -71,16 +79,17 @@ inline bool invalidchar(const char c)
|| c == '>' || c == '|') != 0;
}
bool IsValidFilename(char *psrc, char &pchar) {
bool IsValidFilename(char *psrc, char &pchar)
{
char *pch = strrchr(psrc, '/');
if (pch == NULL) {
if (pch == NULL)
pch = psrc;
}
while (*pch++) {
if (invalidchar(*pch)) {
while (*pch++)
{
if (invalidchar(*pch))
{
pchar = *pch;
return false;
}
@ -89,32 +98,30 @@ bool IsValidFilename(char *psrc, char &pchar) {
return true;
}
bool IsFileHasExtension(char *psrc) {
bool IsFileHasExtension(char *psrc)
{
// find the extension filename
char *pch = strrchr(psrc, '.');
if (pch == NULL) {
if (pch == NULL)
return false;
}
// the size extension
if (strlen(&pch[1]) <= 0) {
if (strlen(&pch[1]) <= 0)
return false;
}
return strchr(pch, '/') == NULL;
}
void CResourceFile::Load()
void CResourceFile::LoadResources()
{
char *pos;
char buffer[4096];
char line[4096];
uint8 hash[16];
FILE *fp;
int argc;
int len;
int flags;
flag_type_resources flag;
char filename[MAX_PATH_LENGTH];
char cmdBufExec[MAX_PATH_LENGTH];
int cline = 0;
@ -128,9 +135,9 @@ void CResourceFile::Load()
return;
}
while (!feof(fp) && fgets(buffer, sizeof(buffer), fp))
while (!feof(fp) && fgets(line, sizeof(line), fp))
{
pos = buffer;
pos = line;
cline++;
@ -140,7 +147,7 @@ void CResourceFile::Load()
const char *pToken = GetNextToken(&pos);
argc = 0;
flags = FLAG_TYPE_NONE;
flag = FLAG_TYPE_NONE;
memset(hash, 0, sizeof(hash));
@ -152,8 +159,8 @@ void CResourceFile::Load()
{
case ARG_TYPE_FILE_NAME:
{
strncpy(filename, pToken, len + 1);
filename[len + 1] = '\0';
strncpy(filename, pToken, len);
filename[len] = '\0';
break;
}
case ARG_TYPE_FILE_HASH:
@ -163,44 +170,50 @@ void CResourceFile::Load()
strncpy((char *)pbuf, pToken, len);
pbuf[len] = '\0';
if (_stricmp((const char *)pbuf, "UNKNOWN") == 0) {
flags = FLAG_TYPE_HASH_ANY;
if (_stricmp((const char *)pbuf, "UNKNOWN") == 0)
{
flag = FLAG_TYPE_HASH_ANY;
}
else
{
for (int i = 0; i < sizeof(pbuf) / 2; i++)
hash[i] = hexbyte(&pbuf[i * 2]);
flags = (*(uint32 *)&hash[0] != 0x00000000) ? FLAG_TYPE_EXISTS : FLAG_TYPE_MISSGIN;
flag = (*(uint32 *)&hash[0] != 0x00000000) ? FLAG_TYPE_EXISTS : FLAG_TYPE_MISSING;
}
break;
}
case ARG_TYPE_CMD_EXEC:
{
strncpy(cmdBufExec, pToken, len + 1);
cmdBufExec[len + 1] = '\0';
strncpy(cmdBufExec, pToken, len);
cmdBufExec[len] = '\0';
if (_stricmp(cmdBufExec, "IGNORE") == 0) {
flags = FLAG_TYPE_IGNORE;
if (_stricmp(cmdBufExec, "IGNORE") == 0)
{
flag = FLAG_TYPE_IGNORE;
cmdBufExec[0] = '\0';
}
else if (_stricmp(cmdBufExec, "BREAK") == 0) {
flags |= FLAG_TYPE_BREAK;
else if (_stricmp(cmdBufExec, "BREAK") == 0)
{
flag = FLAG_TYPE_BREAK;
cmdBufExec[0] = '\0';
}
else {
else
{
// replface \' to "
StringReplace(cmdBufExec, "'", "\"");
}
break;
}
case ARG_TYPE_FLAG:
{
if (_stricmp(pToken, "IGNORE") == 0) {
flags = FLAG_TYPE_IGNORE;
if (_stricmp(pToken, "IGNORE") == 0)
{
flag = FLAG_TYPE_IGNORE;
}
else if (_stricmp(pToken, "BREAK") == 0) {
flags |= FLAG_TYPE_BREAK;
else if (_stricmp(pToken, "BREAK") == 0)
{
flag = FLAG_TYPE_BREAK;
}
break;
}
@ -211,44 +224,47 @@ void CResourceFile::Load()
argc++;
pToken = GetNextToken(&pos);
if (pToken == NULL && argc == ARG_TYPE_FLAG) {
if (pToken == NULL && argc == ARG_TYPE_FLAG)
{
// go to next argument
argc++;
}
}
if (argc >= MAX_PARSE_ARGUMENT) {
if (argc >= MAX_PARSE_ARGUMENT)
{
char pchar;
if (strlen(filename) <= 0) {
if (strlen(filename) <= 0)
{
UTIL_Printf(__FUNCTION__ ": Failed to load \"" FILE_INI_RESOURCES "\"; path to filename is empty on line %d\n", cline);
continue;
}
else if (!IsFileHasExtension(filename)) {
else if (!IsFileHasExtension(filename))
{
UTIL_Printf(__FUNCTION__ ": Failed to load \"" FILE_INI_RESOURCES "\"; filename has no extension on line %d\n", cline);
continue;
}
else if (!IsValidFilename(filename, pchar)) {
else if (!IsValidFilename(filename, pchar))
{
UTIL_Printf(__FUNCTION__ ": Failed to load \"" FILE_INI_RESOURCES "\"; filename has invalid character '%c' on line %d\n", pchar, cline);
continue;
}
else if (flags == FLAG_TYPE_NONE) {
else if (flag == FLAG_TYPE_NONE)
{
UTIL_Printf(__FUNCTION__ ": Failed to load \"" FILE_INI_RESOURCES "\"; parsing hash failed on line %d\n", cline);
continue;
}
// TODO: is there a need to flag FLAG_TYPE_BREAK without cmdexec?
else if (strlen(cmdBufExec) <= 0 && !(flags & (FLAG_TYPE_IGNORE | FLAG_TYPE_BREAK))) {
else if (strlen(cmdBufExec) <= 0 && (flag != FLAG_TYPE_IGNORE && flag != FLAG_TYPE_BREAK))
{
UTIL_Printf(__FUNCTION__ ": Failed to load \"" FILE_INI_RESOURCES "\"; parsing command line is empty on line %d\n", cline);
continue;
}
AddElement(filename, cmdBufExec, flags, *(uint32 *)&hash[0]);
AddElement(filename, cmdBufExec, flag, *(uint32 *)&hash[0], cline);
}
else if (pToken != NULL || argc > ARG_TYPE_FILE_NAME) {
else if (pToken != NULL || argc > ARG_TYPE_FILE_NAME)
{
UTIL_Printf(__FUNCTION__ ": Failed to load \"" FILE_INI_RESOURCES "\"; parsing not enough arguments on line %d (got '%d', expected '%d')\n", cline, argc, MAX_PARSE_ARGUMENT);
}
}
@ -267,7 +283,8 @@ const char *CResourceFile::GetNextToken(char **pbuf)
while (*rpos != 0 && isspace(*rpos))
rpos++;
if (*rpos == '\0') {
if (*rpos == '\0')
{
*pbuf = rpos;
return NULL;
}
@ -320,45 +337,17 @@ const char *CResourceFile::GetNextToken(char **pbuf)
return res;
}
void TrimSpace(char *pbuf)
void CResourceFile::AddElement(char *filename, char *cmdExec, flag_type_resources flag, uint32 hash, int line)
{
char *pend = pbuf;
char *pstart = pbuf;
while ((*pstart == ' '
|| *pstart == '"'
|| *pstart == '\''
|| *pstart == '\t'
|| *pstart == '\r'
|| *pstart == '\n'))
++pstart;
while (*pstart)
*pend++ = *pstart++;
*pend = '\0';
while (pend > pbuf && *--pend &&
(*pend == ' '
|| *pend == '"'
|| *pend == '\''
|| *pend == '\t'
|| *pend == '\r'
|| *pend == '\n'
|| *pend == ';'))
*pend = '\0';
}
void CResourceFile::AddElement(char *filename, char *cmdExec, int flags, uint32 hash)
{
auto nRes = new CResourceBuffer(filename, cmdExec, flags, hash);
auto nRes = new CResourceBuffer(filename, cmdExec, flag, hash, line);
// to mark files which are not required to add to the resource again
for (auto iter = m_resourceList.cbegin(); iter != m_resourceList.cend(); ++iter)
for (auto iter = m_resourceList.cbegin(), end = m_resourceList.cend(); iter != end; ++iter)
{
CResourceBuffer *pRes = (*iter);
if (_stricmp(pRes->GetFileName(), filename) == 0) {
if (_stricmp(pRes->GetFileName(), filename) == 0)
{
// resource name already registered
nRes->SetDuplicate();
break;
@ -370,106 +359,123 @@ void CResourceFile::AddElement(char *filename, char *cmdExec, int flags, uint32
bool CResourceFile::FileConsistencyResponce(IGameClient *pSenderClient, resource_t *resource, uint32 hash)
{
if (resource->type != t_decal
|| resource->nIndex < m_DecalsNum) // if by some miracle the decals will have the flag RES_CHECKFILE
// to be sure not bypass the decals
{
m_PrevHash = hash;
return true;
}
// strange thing
// if this happened when missing all the files from client
if (!m_PrevHash)
{
return true;
}
bool bHandled = false;
find_type_e typeFind = FIND_TYPE_NONE;
flag_type_resources typeFind;
std::vector<CResourceBuffer *> tempResourceList;
for (auto iter = m_resourceList.begin(); iter != m_resourceList.end(); ++iter)
for (auto iter = m_resourceList.cbegin(), end = m_resourceList.cend(); iter != end; ++iter)
{
CResourceBuffer *pRes = (*iter);
if (strcmp(resource->szFileName, pRes->GetFileName()) != 0)
continue;
bHandled = true;
typeFind = pRes->GetFileFlag();
int flags = pRes->GetFileFlags();
if (m_PrevHash == hash && typeFind != FLAG_TYPE_MISSING)
typeFind = FLAG_TYPE_NONE;
if (flags & FLAG_TYPE_IGNORE)
switch (typeFind)
{
if (m_PrevHash != hash) {
tempResourceList.push_back(pRes);
typeFind = FIND_TYPE_IGNORE;
}
}
else if (flags & FLAG_TYPE_EXISTS)
{
if (m_PrevHash != hash && pRes->GetFileHash() == hash) {
typeFind = FIND_TYPE_ON_HASH;
}
}
else if (flags & FLAG_TYPE_MISSGIN)
{
if (m_PrevHash == hash) {
typeFind = FIND_TYPE_MISSING;
}
}
else if (flags & FLAG_TYPE_HASH_ANY)
{
if (m_PrevHash != hash)
case FLAG_TYPE_BREAK:
/* empty */
break;
case FLAG_TYPE_IGNORE:
tempResourceList.push_back(pRes);
break;
case FLAG_TYPE_EXISTS:
if (pRes->GetFileHash() == hash)
{
typeFind = FIND_TYPE_ANY_HASH;
typeFind = FLAG_TYPE_EXISTS;
}
break;
case FLAG_TYPE_HASH_ANY:
for (auto it = tempResourceList.cbegin(); it != tempResourceList.cend(); ++it)
{
CResourceBuffer *pTemp = (*it);
for (size_t i = 0; i < tempResourceList.size(); i++) {
CResourceBuffer *pTemp = tempResourceList[i];
if (_stricmp(pTemp->GetFileName(), pRes->GetFileName()) != 0)
continue;
if (_stricmp(pTemp->GetFileName(), pRes->GetFileName()) != 0) {
continue;
}
if (pTemp->GetFileHash() == hash) {
typeFind = FIND_TYPE_NONE;
break;
}
if (pTemp->GetFileHash() == hash)
{
typeFind = FLAG_TYPE_NONE;
break;
}
}
break;
case FLAG_TYPE_MISSING:
if (m_PrevHash != hash)
{
typeFind = FLAG_TYPE_NONE;
}
break;
default:
typeFind = FLAG_TYPE_NONE;
break;
}
else
typeFind = FIND_TYPE_NONE;
if (typeFind != FIND_TYPE_NONE) {
if (typeFind != FLAG_TYPE_NONE)
{
// push exec cmd
Exec.AddElement(pSenderClient, pRes, hash);
//#ifdef _DEBUG
if (CVAR_GET_FLOAT("developer") == 1.0f) {
UTIL_Printf(" -> filename: (%s), cmdexec: (%s), hash: (%x)\n", pRes->GetFileName(), pRes->GetCmdExec(), pRes->GetFileHash());
}
//#endif // _DEBUG
#ifdef _DEBUG
UTIL_Printf(" -> filename: (%s), cmdexec: (%s), hash: (%x), typeFind: (%d)\n", pRes->GetFileName(), pRes->GetCmdExec(), pRes->GetFileHash(), typeFind);
#endif // _DEBUG
}
bHandled = true;
}
m_PrevHash = hash;
return !bHandled;
}
const char* DuplicateString(const char* str)
const char *DuplicateString(const char *str)
{
for (auto it = StringsCache.begin(), end = StringsCache.end(); it != end; ++it)
for (auto iter = StringsCache.cbegin(), end = StringsCache.cend(); iter != end; ++iter)
{
if (!strcmp(*it, str))
return *it;
if (!strcmp(*iter, str))
return *iter;
}
const char* s = strcpy(new char[strlen(str) + 1], str);
const char *s = strcpy(new char[strlen(str) + 1], str);
StringsCache.push_back(s);
return s;
}
void ClearStringsCache()
{
for (auto it = StringsCache.begin(), end = StringsCache.end(); it != end; ++it)
delete *it;
for (auto iter = StringsCache.begin(), end = StringsCache.end(); iter != end; ++iter)
delete [] *iter;
StringsCache.clear();
}
CResourceBuffer::CResourceBuffer(char *filename, char *cmdExec, int flags, uint32 hash)
CResourceBuffer::CResourceBuffer(char *filename, char *cmdExec, flag_type_resources flag, uint32 hash, int line)
{
m_FileName = DuplicateString(filename);
m_CmdExec = DuplicateString(cmdExec);
m_CmdExec = (cmdExec[0] != '\0') ? DuplicateString(cmdExec) : NULL;
m_Duplicate = false;
m_Flags = flags;
m_Flag = flag;
m_FileHash = hash;
m_Line = line;
}

View File

@ -2,27 +2,17 @@
#define FILE_INI_RESOURCES "resources.ini"
#define MAX_CLIENTS 32
#define MAX_CMD_LENGTH 128
#define MAX_PATH_LENGTH 260
#define MAX_RESOURCE_LIST 1280
enum flag_type_resources
{
FLAG_TYPE_NONE = 0,
FLAG_TYPE_EXISTS = (1 << 0), // to comparison with the specified hash value
FLAG_TYPE_MISSGIN = (1 << 1), // check it missing file on client
FLAG_TYPE_IGNORE = (1 << 2), // ignore the specified hash value
FLAG_TYPE_BREAK = (1 << 3), // do not check a next files
FLAG_TYPE_HASH_ANY = (1 << 4), // any file with any the hash value
};
enum find_type_e
{
FIND_TYPE_NONE = 0,
FIND_TYPE_ON_HASH,
FIND_TYPE_MISSING,
FIND_TYPE_IGNORE,
FIND_TYPE_ANY_HASH,
FLAG_TYPE_EXISTS, // to comparison with the specified hash value
FLAG_TYPE_MISSING, // check it missing file on client
FLAG_TYPE_IGNORE, // ignore the specified hash value
FLAG_TYPE_BREAK, // do not check a next files
FLAG_TYPE_HASH_ANY, // any file with any the hash value
};
enum arg_type_e
@ -38,16 +28,14 @@ enum arg_type_e
class CResourceBuffer
{
public:
CResourceBuffer(char *filename, char *cmdExec, int flags, uint32 hash);
CResourceBuffer(char *filename, char *cmdExec, flag_type_resources flag, uint32 hash, int line);
uint32 GetFileHash() const { return m_FileHash; };
int GetFileFlags() const { return m_Flags; };
flag_type_resources GetFileFlag() const { return m_Flag; };
const char *GetFileName() const { return m_FileName; };
const char *GetCmdExec() const { return m_CmdExec; };
bool GetBreak() const { return m_Break; };
void SetBreak() { m_Break = true; };
int GetLine() const { return m_Line; };
bool IsDuplicate() const { return m_Duplicate; };
void SetDuplicate() { m_Duplicate = true; };
@ -55,28 +43,27 @@ public:
private:
uint32 m_FileHash;
int m_Flags;
flag_type_resources m_Flag;
int m_Line;
const char *m_FileName;
const char *m_CmdExec;
bool m_Duplicate;
bool m_Break;
};
class CResourceFile
{
public:
void Init();
void Load();
void Add();
void Clear();
void LoadResources();
void CreateResourceList();
bool FileConsistencyResponce(IGameClient *pSenderClient, resource_t *resource, uint32 hash);
bool IsConfigLoaded() const { return !m_ConfigFailed; };
private:
void AddElement(char *filename, char *cmdExec, int flags, uint32 hash);
void AddElement(char *filename, char *cmdExec, flag_type_resources flag, uint32 hash, int line);
// parse
const char *GetNextToken(char **pbuf);
@ -85,6 +72,7 @@ private:
typedef std::vector<CResourceBuffer *> ResourceList;
ResourceList m_resourceList;
int m_DecalsNum;
uint32 m_PrevHash;
bool m_ConfigFailed;
char m_PathDir[MAX_PATH_LENGTH];

74
src/task.cpp Normal file
View File

@ -0,0 +1,74 @@
#include "precompiled.h"
CTaskMngr Task;
CTaskMngr::CBufTask::CBufTask(IGameClient *pClient, float time, xtask_t handler)
{
m_pClient = pClient;
m_Handler = handler;
m_EndTime = gpGlobals->time + time;
}
void CTaskMngr::AddTask(IGameClient *pClient, float time, xtask_t handler)
{
g_pFunctionTable->pfnStartFrame = ::StartFrame;
m_taskList.push_back(new CBufTask(pClient, time, handler));
}
void CTaskMngr::StartFrame()
{
if (m_taskList.empty())
{
// more not to call
g_pFunctionTable->pfnStartFrame = NULL;
return;
}
if (m_nextFrame > gpGlobals->time)
return;
auto iter = m_taskList.begin();
while (iter != m_taskList.end())
{
CBufTask *pTask = (*iter);
if (pTask->GetEndTime() >= gpGlobals->time)
{
iter++;
continue;
}
pTask->Handler();
// erase task
delete pTask;
iter = m_taskList.erase(iter);
}
m_nextFrame = gpGlobals->time + TASK_FREQUENCY_TIME;
}
void CTaskMngr::Clear(IGameClient *pClient)
{
if (pClient == NULL)
{
// reset next frame
m_nextFrame = 0;
}
auto iter = m_taskList.begin();
while (iter != m_taskList.end())
{
CBufTask *pTask = (*iter);
if (pClient != NULL && pTask->GetClient() != pClient)
{
iter++;
continue;
}
// erase task
delete pTask;
iter = m_taskList.erase(iter);
}
}

36
src/task.h Normal file
View File

@ -0,0 +1,36 @@
#pragma once
#define TASK_FREQUENCY_TIME 1.0f // check frequency current tasks
typedef void (*xtask_t)(IGameClient *);
class CTaskMngr
{
public:
void AddTask(IGameClient *pClient, float time, xtask_t handler);
void StartFrame();
void Clear(IGameClient *pClient = NULL);
private:
class CBufTask
{
public:
CBufTask(IGameClient *pClient, float time, xtask_t handler);
IGameClient *GetClient() const { return m_pClient; };
float GetEndTime() const { return m_EndTime; };
void Handler() const { m_Handler(m_pClient); };
private:
IGameClient *m_pClient;
xtask_t m_Handler;
float m_EndTime;
};
typedef std::vector<CBufTask *> CBufTaskList;
CBufTaskList m_taskList;
float m_nextFrame;
};
extern CTaskMngr Task;