Refactoring

Added Makefile
Added some flags to like "BREAK", "IGNORE"
This commit is contained in:
s1lentq 2015-11-11 23:29:54 +06:00
parent 6e4dbe9da7
commit 9f148eab97
14 changed files with 441 additions and 285 deletions

48
Makefile Normal file
View File

@ -0,0 +1,48 @@
NAME = rechecker
COMPILER = /opt/intel/bin/icpc
OBJECTS = src/main.cpp src/meta_api.cpp src/dllapi.cpp\
src/cmdexec.cpp src/engine_rehlds.cpp src/h_export.cpp\
src/resource.cpp src/sdk_util.cpp public/interface.cpp
LINK = -lm -ldl -static-intel -static-libgcc -no-intel-extensions
OPT_FLAGS = -O3 -msse3 -ipo -no-prec-div -fp-model fast=2 -funroll-loops -fomit-frame-pointer -fno-stack-protector
INCLUDE = -I. -Isrc -Icommon -Idlls -Iengine -Ipm_shared -Ipublic -Imetamod
BIN_DIR = Release
CFLAGS = $(OPT_FLAGS)
CFLAGS += -g0 -fvisibility=hidden -DNOMINMAX -fvisibility-inlines-hidden\
-DNDEBUG -Dlinux -D__linux__ -std=c++11 -shared -wd147,274 -fasm-blocks\
-Qoption,cpp,--treat_func_as_string_literal_cpp -fno-rtti
OBJ_LINUX := $(OBJECTS:%.c=$(BIN_DIR)/%.o)
$(BIN_DIR)/%.o: %.c
$(COMPILER) $(INCLUDE) $(CFLAGS) -o $@ -c $<
all:
mkdir -p $(BIN_DIR)
mkdir -p $(BIN_DIR)/sdk
$(MAKE) $(NAME) && strip -x $(BIN_DIR)/$(NAME)_mm_i386.so
$(NAME): $(OBJ_LINUX)
$(COMPILER) $(INCLUDE) $(CFLAGS) $(OBJ_LINUX) $(LINK) -o$(BIN_DIR)/$(NAME)_mm_i386.so
check:
cppcheck $(INCLUDE) --quiet --max-configs=100 -D__linux__ -DNDEBUG -DHAVE_STDINT_H .
debug:
$(MAKE) all DEBUG=false
default: all
clean:
rm -rf Release/sdk/*.o
rm -rf Release/*.o
rm -rf Release/$(NAME)_mm_i386.so

View File

@ -145,6 +145,10 @@ typedef IVoidHookChainRegistry<IGameClient *, char *, size_t, sizebuf_t *, IGame
typedef IHookChain<bool, IGameClient *, resource_t *, uint32> IRehldsHook_SV_CheckConsistencyResponce; typedef IHookChain<bool, IGameClient *, resource_t *, uint32> IRehldsHook_SV_CheckConsistencyResponce;
typedef IHookChainRegistry<bool, IGameClient *, resource_t *, uint32> IRehldsHookRegistry_SV_CheckConsistencyResponce; typedef IHookChainRegistry<bool, IGameClient *, resource_t *, uint32> IRehldsHookRegistry_SV_CheckConsistencyResponce;
//SV_DropClient hook
typedef IVoidHookChain<IGameClient*, bool, const char*> IRehldsHook_SV_DropClient;
typedef IVoidHookChainRegistry<IGameClient*, bool, const char*> IRehldsHookRegistry_SV_DropClient;
class IRehldsHookchains { class IRehldsHookchains {
public: public:
virtual ~IRehldsHookchains() { } virtual ~IRehldsHookchains() { }
@ -176,6 +180,7 @@ public:
virtual IRehldsHookRegistry_PF_BuildSoundMsg_I* PF_BuildSoundMsg_I() = 0; virtual IRehldsHookRegistry_PF_BuildSoundMsg_I* PF_BuildSoundMsg_I() = 0;
virtual IRehldsHookRegistry_SV_WriteFullClientUpdate* SV_WriteFullClientUpdate() = 0; virtual IRehldsHookRegistry_SV_WriteFullClientUpdate* SV_WriteFullClientUpdate() = 0;
virtual IRehldsHookRegistry_SV_CheckConsistencyResponce* SV_CheckConsistencyResponce() = 0; virtual IRehldsHookRegistry_SV_CheckConsistencyResponce* SV_CheckConsistencyResponce() = 0;
virtual IRehldsHookRegistry_SV_DropClient* SV_DropClient() = 0;
}; };
struct RehldsFuncs_t { struct RehldsFuncs_t {

View File

@ -164,7 +164,7 @@
<ClInclude Include="..\public\FileSystem.h" /> <ClInclude Include="..\public\FileSystem.h" />
<ClInclude Include="..\public\interface.h" /> <ClInclude Include="..\public\interface.h" />
<ClInclude Include="..\src\cmdexec.h" /> <ClInclude Include="..\src\cmdexec.h" />
<ClInclude Include="..\src\config.h" /> <ClInclude Include="..\src\resource.h" />
<ClInclude Include="..\src\engine_rehlds.h" /> <ClInclude Include="..\src\engine_rehlds.h" />
<ClInclude Include="..\src\main.h" /> <ClInclude Include="..\src\main.h" />
<ClInclude Include="..\src\precompiled.h" /> <ClInclude Include="..\src\precompiled.h" />
@ -175,9 +175,11 @@
</ClCompile> </ClCompile>
<ClCompile Include="..\public\interface.cpp" /> <ClCompile Include="..\public\interface.cpp" />
<ClCompile Include="..\src\cmdexec.cpp" /> <ClCompile Include="..\src\cmdexec.cpp" />
<ClCompile Include="..\src\config.cpp" /> <ClCompile Include="..\src\resource.cpp" />
<ClCompile Include="..\src\dllapi.cpp" /> <ClCompile Include="..\src\dllapi.cpp" />
<ClCompile Include="..\src\engine_api.cpp" /> <ClCompile Include="..\src\engine_api.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\src\engine_rehlds.cpp" /> <ClCompile Include="..\src\engine_rehlds.cpp" />
<ClCompile Include="..\src\h_export.cpp" /> <ClCompile Include="..\src\h_export.cpp" />
<ClCompile Include="..\src\main.cpp" /> <ClCompile Include="..\src\main.cpp" />

View File

@ -460,8 +460,8 @@
<ClInclude Include="..\src\main.h" /> <ClInclude Include="..\src\main.h" />
<ClInclude Include="..\src\precompiled.h" /> <ClInclude Include="..\src\precompiled.h" />
<ClInclude Include="..\src\engine_rehlds.h" /> <ClInclude Include="..\src\engine_rehlds.h" />
<ClInclude Include="..\src\config.h" />
<ClInclude Include="..\src\cmdexec.h" /> <ClInclude Include="..\src\cmdexec.h" />
<ClInclude Include="..\src\resource.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="..\common\parsemsg.cpp"> <ClCompile Include="..\common\parsemsg.cpp">
@ -478,8 +478,8 @@
<ClCompile Include="..\src\meta_api.cpp" /> <ClCompile Include="..\src\meta_api.cpp" />
<ClCompile Include="..\src\precompiled.cpp" /> <ClCompile Include="..\src\precompiled.cpp" />
<ClCompile Include="..\src\sdk_util.cpp" /> <ClCompile Include="..\src\sdk_util.cpp" />
<ClCompile Include="..\src\config.cpp" />
<ClCompile Include="..\src\cmdexec.cpp" /> <ClCompile Include="..\src\cmdexec.cpp" />
<ClCompile Include="..\src\resource.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Filter Include="sdk"> <Filter Include="sdk">

View File

@ -1,21 +1,22 @@
#include "precompiled.h" #include "precompiled.h"
CBufExec CmdExec; CExecManager Exec;
CBufExecNew::CBufExecNew(IGameClient *pClient, CResourceCheckerNew *pResource) CBufExec::CBufExec(IGameClient *pClient, CResourceBuffer *pResource, uint32 responseHash)
{ {
m_pClient = pClient; m_pClient = pClient;
m_pResource = pResource; m_pResource = pResource;
m_Hash = responseHash;
} }
CBufExecNew::~CBufExecNew() CBufExec::~CBufExec()
{ {
; ;
} }
void CBufExec::AddElement(IGameClient *pClient, CResourceCheckerNew *pResource) void CExecManager::AddElement(IGameClient *pClient, CResourceBuffer *pResource, uint32 responseHash)
{ {
m_vector.push_back(new CBufExecNew(pClient, pResource)); m_execList.push_back(new CBufExec(pClient, pResource, responseHash));
} }
void StringReplace(char *src, const char *strold, const char *strnew) void StringReplace(char *src, const char *strold, const char *strnew)
@ -37,7 +38,7 @@ void StringReplace(char *src, const char *strold, const char *strnew)
} }
} }
char *GetExecCmdPrepare(IGameClient *pClient, CResourceCheckerNew *pResource) char *GetExecCmdPrepare(IGameClient *pClient, CResourceBuffer *pResource, uint32 responseHash)
{ {
int len; int len;
const netadr_t *net; const netadr_t *net;
@ -48,15 +49,15 @@ char *GetExecCmdPrepare(IGameClient *pClient, CResourceCheckerNew *pResource)
net = pClient->GetNetChan()->GetRemoteAdr(); net = pClient->GetNetChan()->GetRemoteAdr();
// replace key values
StringReplace(string, "[file_name]", pResource->GetFileName());
StringReplace(string, "[file_hash]", UTIL_VarArgs("%x", responseHash));
// replace of templates for identification // replace of templates for identification
StringReplace(string, "[name]", pClient->GetName());
StringReplace(string, "[userid]", UTIL_VarArgs("#%u", g_engfuncs.pfnGetPlayerUserId(pClient->GetEdict()))); StringReplace(string, "[userid]", UTIL_VarArgs("#%u", g_engfuncs.pfnGetPlayerUserId(pClient->GetEdict())));
StringReplace(string, "[steamid]", UTIL_VarArgs("%s", g_engfuncs.pfnGetPlayerAuthId(pClient->GetEdict()))); StringReplace(string, "[steamid]", UTIL_VarArgs("%s", g_engfuncs.pfnGetPlayerAuthId(pClient->GetEdict())));
StringReplace(string, "[ip]", UTIL_VarArgs("%i.%i.%i.%i", net->ip[0], net->ip[1], net->ip[2], net->ip[3])); StringReplace(string, "[ip]", UTIL_VarArgs("%i.%i.%i.%i", net->ip[0], net->ip[1], net->ip[2], net->ip[3]));
StringReplace(string, "[name]", pClient->GetName());
// replace key values
StringReplace(string, "[file_name]", pResource->GetFileName());
StringReplace(string, "[file_hash]", UTIL_VarArgs("%x", pResource->GetHashFile()));
len = strlen(string); len = strlen(string);
@ -69,42 +70,71 @@ char *GetExecCmdPrepare(IGameClient *pClient, CResourceCheckerNew *pResource)
return string; return string;
} }
void CBufExec::Exec(IGameClient *pClient) void CExecManager::CommandExecute(IGameClient *pClient)
{ {
CBufExecVectorIt it = m_vector.begin(); bool bBreak = false;
auto iter = m_execList.begin();
while (it != m_vector.end()) while (iter != m_execList.end())
{ {
CBufExecNew *exc = (*it); CBufExec *pExec = (*iter);
if (exc->GetGameClient() != pClient) { if (pExec->GetGameClient() != pClient) {
it++; iter++;
continue; continue;
} }
CResourceBuffer *pRes = pExec->GetResource();
// exit the loop if the client is out of the game // exit the loop if the client is out of the game
// TODO: Check me! // TODO: Check me!
if (!pClient->IsConnected()) { if (!pClient->IsConnected()) {
break; break;
} }
char *cmdExec = GetExecCmdPrepare(pClient, exc->GetResource()); char *cmdExec = GetExecCmdPrepare(pClient, pRes, pExec->GetHash());
// 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 (cmdExec != NULL && cmdExec[0] != '\0') {
// execute cmd // execute cmdexec
SERVER_COMMAND(cmdExec); SERVER_COMMAND(cmdExec);
// erase cmdexec // erase cmdexec
delete exc; delete pExec;
it = m_vector.erase(it); iter = m_execList.erase(iter);
} }
else else
it++; iter++;
bBreak = (pRes->GetFlagsFile() & FLAG_TYPE_BREAK) == FLAG_TYPE_BREAK;
} }
} }
void CBufExec::Clear() void CExecManager::Clear(IGameClient *pClient)
{ {
m_vector.clear(); if (pClient == NULL) {
m_execList.clear();
return;
}
auto iter = m_execList.begin();
while (iter != m_execList.end())
{
CBufExec *pExec = (*iter);
// erase cmdexec
if (pExec->GetGameClient() == pClient) {
delete pExec;
iter = m_execList.erase(iter);
}
else
iter++;
}
} }

View File

@ -1,35 +1,33 @@
#pragma once #pragma once
#include <vector>
class CBufExecNew
{
public:
CBufExecNew(IGameClient *pClient, CResourceCheckerNew *pResource);
~CBufExecNew();
IGameClient *GetGameClient() { return m_pClient; };
CResourceCheckerNew *GetResource() { return m_pResource; };
private:
IGameClient *m_pClient;
CResourceCheckerNew *m_pResource;
};
typedef std::vector<CBufExecNew *> CBufExecVector;
typedef CBufExecVector::iterator CBufExecVectorIt;
class CBufExec class CBufExec
{ {
public: public:
void AddElement(IGameClient *pClient, CResourceCheckerNew *pResource); CBufExec(IGameClient *pClient, CResourceBuffer *pResource, uint32 responseHash);
~CBufExec();
void Exec(IGameClient *pClient); IGameClient *GetGameClient() const { return m_pClient; };
void Clear(); CResourceBuffer *GetResource() const { return m_pResource; };
uint32 GetHash() const { return m_Hash; };
private: private:
CBufExecVector m_vector; IGameClient *m_pClient;
CResourceBuffer *m_pResource;
uint32 m_Hash;
}; };
extern CBufExec CmdExec; class CExecManager
{
public:
void AddElement(IGameClient *pClient, CResourceBuffer *pResource, uint32 responseHash);
void CommandExecute(IGameClient *pClient);
void Clear(IGameClient *pClient = NULL);
private:
typedef std::vector<CBufExec *> CBufExecList;
CBufExecList m_execList;
};
extern CExecManager Exec;
extern void StringReplace(char *src, const char *strold, const char *strnew); extern void StringReplace(char *src, const char *strold, const char *strnew);

View File

@ -1,97 +0,0 @@
#pragma once
#include <vector>
#define FILE_INI_CONFIG "config.ini"
#define FILE_INI_RESOURCES "resources.ini"
//#ifdef MAX_PATH
//#define MAX_PATH 260
//#endif // MAX_PATH
#define MAX_CLIENTS 32
#define MAX_CMD_LENGTH 128
#define MAX_PATH_LENGTH 260
enum find_type_e
{
FIND_TYPE_NONE = 0,
FIND_TYPE_ON_HASH,
FIND_TYPE_ANY_HASH,
FIND_TYPE_MISSING
};
enum arg_type_e
{
ARG_TYPE_FILE_NAME = 0,
ARG_TYPE_FILE_HASH,
ARG_TYPE_CMD_EXEC,
MAX_PARSE_ARGUMENT,
};
enum flag_type_resources
{
FLAG_TYPE_NONE = 0,
FLAG_TYPE_EXISTS,
FLAG_TYPE_MISSGIN,
FLAG_TYPE_HASH_ANY,
};
class CResourceCheckerNew
{
public:
CResourceCheckerNew(char *filename, char *cmdExec, flag_type_resources flag, uint32 hash);
~CResourceCheckerNew();
uint32 GetHashFile() { return m_HashFile; };
flag_type_resources GetFlagFile() { return m_Flag; };
char *GetFileName() { return m_FileName; };
char *GetCmdExec() { return m_CmdExec; };
bool GetMark() { return m_Mark; };
void SetMark() { m_Mark = true; };
private:
uint32 m_HashFile;
flag_type_resources m_Flag;
char *m_FileName;
char *m_CmdExec;
bool m_Mark;
};
typedef std::vector<CResourceCheckerNew *> ResourceCheckerVector;
typedef ResourceCheckerVector::iterator ResourceCheckerVectorIt;
class CConfig
{
public:
void Init();
void Load();
void AddResource();
void ClearResources();
bool FileConsistencyResponce(IGameClient *pSenderClient, resource_t *resource, uint32 hash);
bool IsConfigLoaded() { return !m_ConfigFailed; };
private:
void ParseConfig();
void ParseResources();
void AddElement(char *filename, char *cmdExec, flag_type_resources flag, uint32 hash);
// parse
const char *GetNextToken(char **pbuf);
private:
ResourceCheckerVector m_vector;
uint32 m_PreHash;
bool m_ConfigFailed;
char m_szPathConfirDir[MAX_PATH_LENGTH];
char m_szPathResourcesDir[MAX_PATH_LENGTH];
};
extern CConfig Config;
extern void UTIL_Printf(char *fmt, ...);

View File

@ -3,6 +3,7 @@
DLL_FUNCTIONS *g_pFunctionTable; DLL_FUNCTIONS *g_pFunctionTable;
extern qboolean ClientConnect_Post(edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[128]); extern qboolean ClientConnect_Post(edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[128]);
extern void ServerDeactivate_Post(); extern void ServerDeactivate_Post();
extern void ServerActivate_Post(edict_t *pEdictList, int edictCount, int clientMax); extern void ServerActivate_Post(edict_t *pEdictList, int edictCount, int clientMax);
extern void ClientPutInServer_Post(edict_t *pEntity); extern void ClientPutInServer_Post(edict_t *pEntity);

View File

@ -1,10 +1,12 @@
#include "precompiled.h" #include "precompiled.h"
bool g_bInitialized = false; bool g_bInitialized = false;
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); 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); void (*SV_AddResource)(resourcetype_t type, const char *name, int size, unsigned char flags, int index);
bool OnMetaAttach(void) bool OnMetaAttach()
{ {
if (RehldsApi_Init() != RETURN_LOAD) { if (RehldsApi_Init() != RETURN_LOAD) {
return false; return false;
@ -12,30 +14,49 @@ bool OnMetaAttach(void)
// register function from ReHLDS API // register function from ReHLDS API
g_RehldsApi->GetHookchains()->SV_CheckConsistencyResponce()->registerHook(&SV_CheckConsistencyResponce); g_RehldsApi->GetHookchains()->SV_CheckConsistencyResponce()->registerHook(&SV_CheckConsistencyResponce);
g_RehldsApi->GetHookchains()->SV_DropClient()->registerHook(&SV_DropClient);
SV_AddResource = reinterpret_cast<void (*)(resourcetype_t, const char *, int, unsigned char, int)>(g_RehldsApi->GetFuncs()->SV_AddResource); SV_AddResource = reinterpret_cast<void (*)(resourcetype_t, const char *, int, unsigned char, int)>(g_RehldsApi->GetFuncs()->SV_AddResource);
// initialize config // initialize resource config
Config.Init(); Resource.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_old->name = "mp_consistency_orig";
g_engfuncs.pfnCVarRegister(&mp_consistency);
g_engfuncs.pfnCvar_DirectSet(mp_consistency_old, "1");
// if is OK go to attach // if is OK go to attach
return Config.IsConfigLoaded(); return Resource.IsConfigLoaded();
} }
void OnMetaDetach(void) void OnMetaDetach()
{ {
g_RehldsApi->GetHookchains()->SV_CheckConsistencyResponce()->unregisterHook(&SV_CheckConsistencyResponce); g_RehldsApi->GetHookchains()->SV_CheckConsistencyResponce()->unregisterHook(&SV_CheckConsistencyResponce);
// clear // clear
CmdExec.Clear(); Exec.Clear();
Config.ClearResources(); Resource.Clear();
} }
void ServerDeactivate_Post() void ServerDeactivate_Post()
{ {
if (g_bInitialized) { if (g_bInitialized) {
// clear // clear
CmdExec.Clear(); Exec.Clear();
Config.ClearResources(); Resource.Clear();
g_bInitialized = false; g_bInitialized = false;
} }
@ -44,10 +65,22 @@ void ServerDeactivate_Post()
void ServerActivate_Post(edict_t *pEdictList, int edictCount, int clientMax) void ServerActivate_Post(edict_t *pEdictList, int edictCount, int clientMax)
{ {
Config.Load(); Resource.Load();
SET_META_RESULT(MRES_IGNORED); 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);
}
// call next hook
chain->callNext(pClient, crash, string);
}
void ClientPutInServer_Post(edict_t *pEntity) void ClientPutInServer_Post(edict_t *pEntity)
{ {
int nIndex = ENTINDEX(pEntity) - 1; int nIndex = ENTINDEX(pEntity) - 1;
@ -60,7 +93,7 @@ void ClientPutInServer_Post(edict_t *pEntity)
if (pClient != NULL) { if (pClient != NULL) {
// client is connected to putinserver, go execute cmd out buffer // client is connected to putinserver, go execute cmd out buffer
CmdExec.Exec(pClient); Exec.CommandExecute(pClient);
} }
SET_META_RESULT(MRES_IGNORED); SET_META_RESULT(MRES_IGNORED);
@ -69,7 +102,7 @@ void ClientPutInServer_Post(edict_t *pEntity)
qboolean ClientConnect_Post(edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[128]) qboolean ClientConnect_Post(edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[128])
{ {
if (!g_bInitialized) { if (!g_bInitialized) {
Config.AddResource(); Resource.Add();
g_bInitialized = true; g_bInitialized = true;
} }
@ -80,9 +113,10 @@ qboolean ClientConnect_Post(edict_t *pEntity, const char *pszName, const char *p
bool SV_CheckConsistencyResponce(IRehldsHook_SV_CheckConsistencyResponce *chain, IGameClient *pSenderClient, resource_t *resource, uint32 hash) bool SV_CheckConsistencyResponce(IRehldsHook_SV_CheckConsistencyResponce *chain, IGameClient *pSenderClient, resource_t *resource, uint32 hash)
{ {
if (resource->type == t_decal) { if (resource->type == t_decal) {
if (!Config.FileConsistencyResponce(pSenderClient, resource, hash)) if (!Resource.FileConsistencyResponce(pSenderClient, resource, hash))
return false; return false;
} }
return chain->callNext(pSenderClient, resource, hash);; // call next hook and take return of values from original func
return chain->callNext(pSenderClient, resource, hash);
} }

View File

@ -3,8 +3,8 @@
plugin_info_t Plugin_info = plugin_info_t Plugin_info =
{ {
META_INTERFACE_VERSION, META_INTERFACE_VERSION,
"ReChecker", "Rechecker",
"1.0", "1.1",
__DATE__, __DATE__,
"s1lent", "s1lent",
"http://www.dedicated-server.ru/", "http://www.dedicated-server.ru/",

View File

@ -2,8 +2,13 @@
#ifdef _WIN32 // WINDOWS #ifdef _WIN32 // WINDOWS
#pragma warning(disable : 4005) #pragma warning(disable : 4005)
#else
#define _stricmp strcasecmp
// Deail with stupid macro in kernel.h
#undef __FUNCTION__
#endif // _WIN32 #endif // _WIN32
#include <vector>
#include <cstring> // strrchr #include <cstring> // strrchr
#include <extdll.h> #include <extdll.h>
@ -16,19 +21,21 @@
#include "engine_rehlds.h" #include "engine_rehlds.h"
#include "main.h" #include "main.h"
#include "config.h" #include "resource.h"
#include "cmdexec.h" #include "cmdexec.h"
#include "sdk_util.h" // UTIL_LogPrintf, etc //#include "sdk_util.h" // UTIL_LogPrintf, etc
/* <7508> ../engine/consistency.h:9 */ #undef DLLEXPORT
typedef struct consistency_s #ifdef _WIN32
{ #define DLLEXPORT __declspec(dllexport)
char * filename; #define NOINLINE __declspec(noinline)
int issound; #else
int orig_index; #define DLLEXPORT __attribute__((visibility("default")))
int value; #define NOINLINE __attribute__((noinline))
int check_type; #define WINAPI /* */
float mins[3]; #endif // _WIN32
float maxs[3];
} consistency_t; extern void UTIL_Printf(const char *fmt, ...);
extern void UTIL_LogPrintf(const char *fmt, ...);
extern char *UTIL_VarArgs(const char *format, ...);

View File

@ -1,40 +1,40 @@
#include "precompiled.h" #include "precompiled.h"
CConfig Config; CResourceFile Resource;
void CConfig::AddResource() void CResourceFile::Add()
{ {
ResourceCheckerVectorIt it = m_vector.begin();
int nConsistency = g_RehldsServerData->GetConsistencyNum(); int nConsistency = g_RehldsServerData->GetConsistencyNum();
while (it != m_vector.end()) for (auto iter = m_resourceList.cbegin(); iter != m_resourceList.cend(); ++iter)
{ {
CResourceCheckerNew *pRes = (*it); CResourceBuffer *pRes = (*iter);
// prevent duplicate of filenames // prevent duplicate of filenames
// check if filename is been marked so do not add the resource again // check if filename is been marked so do not add the resource again
if (pRes->GetMark() != true) { if (pRes->GetMark() != true) {
#ifdef _DEBUG //#ifdef _DEBUG
printf(__FUNCTION__ " :: (%s)(%s)\n", pRes->GetFileName(), pRes->GetCmdExec()); if (CVAR_GET_FLOAT("developer") == 1.0f) {
#endif // _DEBUG UTIL_Printf(__FUNCTION__ " :: (%s)(%s)(%x)\n", pRes->GetFileName(), pRes->GetCmdExec(), pRes->GetHashFile());
}
//#endif // _DEBUG
SV_AddResource(t_decal, pRes->GetFileName(), 0, RES_CHECKFILE, 4095); SV_AddResource(t_decal, pRes->GetFileName(), 0, RES_CHECKFILE, 4095);
nConsistency++; nConsistency++;
} }
it++;
} }
g_RehldsServerData->SetConsistencyNum(nConsistency); g_RehldsServerData->SetConsistencyNum(nConsistency);
} }
void CConfig::ClearResources() void CResourceFile::Clear()
{ {
m_PreHash = 0; m_PrevHash = 0;
// clear resources // clear resources
m_vector.clear(); m_resourceList.clear();
} }
void CConfig::Init() void CResourceFile::Init()
{ {
char *pos; char *pos;
char path[MAX_PATH_LENGTH]; char path[MAX_PATH_LENGTH];
@ -49,32 +49,8 @@ void CConfig::Init()
*(pos + 1) = '\0'; *(pos + 1) = '\0';
// config.ini
snprintf(m_szPathConfirDir, sizeof(m_szPathConfirDir) - 1, "%s" FILE_INI_CONFIG, path);
// resources.ini // resources.ini
snprintf(m_szPathResourcesDir, sizeof(m_szPathResourcesDir) - 1, "%s" FILE_INI_RESOURCES, path); snprintf(m_PathDir, sizeof(m_PathDir) - 1, "%s" FILE_INI_RESOURCES, path);
}
void CConfig::Load()
{
//ParseConfig();
ParseResources();
}
void CConfig::ParseConfig()
{
FILE *fp = fopen(m_szPathResourcesDir, "r");
if (fp == NULL)
{
UTIL_Printf(__FUNCTION__ ": can't find path to " FILE_INI_CONFIG "\n");
return;
}
// soon coming..
fclose(fp);
} }
inline uint8 hexbyte(uint8 *hex) inline uint8 hexbyte(uint8 *hex)
@ -92,7 +68,7 @@ inline bool invalidchar(const char c)
|| c == '>' || c == '|') != 0; || c == '>' || c == '|') != 0;
} }
bool FileIsValidChar(char *psrc, char &pchar) { bool IsValidFilename(char *psrc, char &pchar) {
char *pch = strrchr(psrc, '/'); char *pch = strrchr(psrc, '/');
@ -127,7 +103,7 @@ bool FileIsExtension(char *psrc) {
return strchr(pch, '/') == NULL; return strchr(pch, '/') == NULL;
} }
void CConfig::ParseResources() void CResourceFile::Load()
{ {
char *pos; char *pos;
char buffer[4096]; char buffer[4096];
@ -135,12 +111,12 @@ void CConfig::ParseResources()
FILE *fp; FILE *fp;
int argc; int argc;
int len; int len;
flag_type_resources flag = FLAG_TYPE_NONE; int flags;
char filename[MAX_PATH_LENGTH]; char filename[MAX_PATH_LENGTH];
char cmdBufExec[MAX_PATH_LENGTH]; char cmdBufExec[MAX_PATH_LENGTH];
int cline = 0; int cline = 0;
fp = fopen(m_szPathResourcesDir, "r"); fp = fopen(m_PathDir, "r");
if (fp == NULL) if (fp == NULL)
{ {
@ -161,8 +137,9 @@ void CConfig::ParseResources()
const char *pToken = GetNextToken(&pos); const char *pToken = GetNextToken(&pos);
argc = 0; argc = 0;
hash[0] = '\0'; flags = FLAG_TYPE_NONE;
flag = FLAG_TYPE_NONE;
memset(hash, 0, sizeof(hash));
while (pToken != NULL && argc <= MAX_PARSE_ARGUMENT) while (pToken != NULL && argc <= MAX_PARSE_ARGUMENT)
{ {
@ -184,14 +161,14 @@ void CConfig::ParseResources()
pbuf[len] = '\0'; pbuf[len] = '\0';
if (_stricmp((const char *)pbuf, "UNKNOWN") == 0) { if (_stricmp((const char *)pbuf, "UNKNOWN") == 0) {
flag = FLAG_TYPE_HASH_ANY; flags = FLAG_TYPE_HASH_ANY;
} }
else else
{ {
for (int i = 0; i < sizeof(pbuf) / 2; i++) for (int i = 0; i < sizeof(pbuf) / 2; i++)
hash[i] = hexbyte(&pbuf[i * 2]); hash[i] = hexbyte(&pbuf[i * 2]);
flag = (*(uint32 *)&hash[0] != 0x00000000) ? FLAG_TYPE_EXISTS : FLAG_TYPE_MISSGIN; flags = (*(uint32 *)&hash[0] != 0x00000000) ? FLAG_TYPE_EXISTS : FLAG_TYPE_MISSGIN;
} }
break; break;
@ -201,8 +178,27 @@ void CConfig::ParseResources()
strncpy(cmdBufExec, pToken, len + 1); strncpy(cmdBufExec, pToken, len + 1);
cmdBufExec[len + 1] = '\0'; cmdBufExec[len + 1] = '\0';
if (_stricmp(cmdBufExec, "IGNORE") == 0) {
flags = FLAG_TYPE_IGNORE;
cmdBufExec[0] = '\0';
}
else if (_stricmp(cmdBufExec, "BREAK") == 0) {
flags |= FLAG_TYPE_BREAK;
cmdBufExec[0] = '\0';
}
else {
// replface \' to " // replface \' to "
StringReplace(cmdBufExec, "'", "\""); StringReplace(cmdBufExec, "'", "\"");
}
}
case ARG_TYPE_FLAG:
{
if (_stricmp(pToken, "IGNORE") == 0) {
flags = FLAG_TYPE_IGNORE;
}
else if (_stricmp(pToken, "BREAK") == 0) {
flags |= FLAG_TYPE_BREAK;
}
break; break;
} }
default: default:
@ -211,6 +207,11 @@ void CConfig::ParseResources()
argc++; argc++;
pToken = GetNextToken(&pos); pToken = GetNextToken(&pos);
if (pToken == NULL && argc == ARG_TYPE_FLAG) {
// go to next argument
argc++;
}
} }
if (argc >= MAX_PARSE_ARGUMENT) { if (argc >= MAX_PARSE_ARGUMENT) {
@ -226,29 +227,33 @@ void CConfig::ParseResources()
continue; continue;
} }
else if (!FileIsValidChar(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); UTIL_Printf(__FUNCTION__ ": Failed to load \"" FILE_INI_RESOURCES "\"; filename has invalid character '%c' on line %d\n", pchar, cline);
continue; continue;
} }
else if (flag == FLAG_TYPE_NONE) { else if (flags == FLAG_TYPE_NONE) {
UTIL_Printf(__FUNCTION__ ": Failed to load \"" FILE_INI_RESOURCES "\"; parsing hash failed on line %d\n", cline); UTIL_Printf(__FUNCTION__ ": Failed to load \"" FILE_INI_RESOURCES "\"; parsing hash failed on line %d\n", cline);
continue; continue;
} }
else if (strlen(cmdBufExec) <= 0) { // TODO: is there a need to flag FLAG_TYPE_BREAK without cmdexec?
UTIL_Printf(__FUNCTION__ ": Failed to load \"" FILE_INI_RESOURCES "\"; command line is empty on line %d\n", cline); else if (strlen(cmdBufExec) <= 0 && !(flags & (FLAG_TYPE_IGNORE | FLAG_TYPE_BREAK))) {
UTIL_Printf(__FUNCTION__ ": Failed to load \"" FILE_INI_RESOURCES "\"; parsing command line is empty on line %d\n", cline);
continue; continue;
} }
AddElement(filename, cmdBufExec, flag, *(uint32 *)&hash[0]); AddElement(filename, cmdBufExec, flags, *(uint32 *)&hash[0]);
}
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);
} }
} }
fclose(fp); fclose(fp);
} }
const char *CConfig::GetNextToken(char **pbuf) const char *CResourceFile::GetNextToken(char **pbuf)
{ {
char *rpos = *pbuf; char *rpos = *pbuf;
if (*rpos == '\0') if (*rpos == '\0')
@ -340,17 +345,17 @@ void TrimSpace(char *pbuf)
*pend = '\0'; *pend = '\0';
} }
void CConfig::AddElement(char *filename, char *cmdExec, flag_type_resources flag, uint32 hash) void CResourceFile::AddElement(char *filename, char *cmdExec, int flags, uint32 hash)
{ {
m_vector.push_back(new CResourceCheckerNew(filename, cmdExec, flag, hash)); m_resourceList.push_back(new CResourceBuffer(filename, cmdExec, flags, hash));
// to mark files which are not required to add to the resource again // to mark files which are not required to add to the resource again
for (ResourceCheckerVectorIt it = m_vector.begin(); it != m_vector.end(); ++it) for (auto iter = m_resourceList.cbegin(); iter != m_resourceList.cend(); ++iter)
{ {
CResourceCheckerNew *pRes = (*it); CResourceBuffer *pRes = (*iter);
// do not check the last element // do not check the last element
if (pRes == m_vector.back()) if (pRes == m_resourceList.back())
continue; continue;
if (_stricmp(pRes->GetFileName(), filename) == 0) { if (_stricmp(pRes->GetFileName(), filename) == 0) {
@ -360,75 +365,103 @@ void CConfig::AddElement(char *filename, char *cmdExec, flag_type_resources flag
} }
} }
bool CConfig::FileConsistencyResponce(IGameClient *pSenderClient, resource_t *resource, uint32 hash) bool CResourceFile::FileConsistencyResponce(IGameClient *pSenderClient, resource_t *resource, uint32 hash)
{ {
bool bCheckeFiles = false; bool bCheckeFiles = false;
find_type_e typeFind = FIND_TYPE_NONE; find_type_e typeFind = FIND_TYPE_NONE;
std::vector<CResourceBuffer *> tempResourceList;
for (ResourceCheckerVectorIt it = m_vector.begin(); it != m_vector.end(); ++it) for (auto iter = m_resourceList.begin(); iter != m_resourceList.end(); ++iter)
{ {
CResourceCheckerNew *pRes = (*it); CResourceBuffer *pRes = (*iter);
if (strcmp(resource->szFileName, pRes->GetFileName()) != 0) if (strcmp(resource->szFileName, pRes->GetFileName()) != 0)
continue; continue;
bCheckeFiles = true; bCheckeFiles = true;
switch (pRes->GetFlagFile()) int flags = pRes->GetFlagsFile();
if (flags & FLAG_TYPE_IGNORE)
{ {
case FLAG_TYPE_EXISTS: if (m_PrevHash != hash) {
if (m_PreHash != hash && pRes->GetHashFile() == hash) { tempResourceList.push_back(pRes);
typeFind = FIND_TYPE_IGNORE;
}
}
else if (flags & FLAG_TYPE_EXISTS)
{
if (m_PrevHash != hash && pRes->GetHashFile() == hash) {
typeFind = FIND_TYPE_ON_HASH; typeFind = FIND_TYPE_ON_HASH;
} }
break; }
case FLAG_TYPE_MISSGIN: else if (flags & FLAG_TYPE_MISSGIN)
if (m_PreHash == hash) { {
if (m_PrevHash == hash) {
typeFind = FIND_TYPE_MISSING; typeFind = FIND_TYPE_MISSING;
} }
break;
case FLAG_TYPE_HASH_ANY:
if (m_PreHash != hash) {
typeFind = FIND_TYPE_ANY_HASH;
} }
break; else if (flags & FLAG_TYPE_HASH_ANY)
default: {
if (m_PrevHash != hash)
{
typeFind = FIND_TYPE_ANY_HASH;
for (size_t i = 0; i < tempResourceList.size(); i++) {
CResourceBuffer *pTemp = tempResourceList[i];
if (_stricmp(pTemp->GetFileName(), pRes->GetFileName()) != 0) {
continue;
}
if (pTemp->GetHashFile() == hash) {
typeFind = FIND_TYPE_NONE; typeFind = FIND_TYPE_NONE;
break; break;
} }
}
}
}
else
typeFind = FIND_TYPE_NONE;
if (typeFind != FIND_TYPE_NONE) { if (typeFind != FIND_TYPE_NONE) {
// push exec cmd // push exec cmd
CmdExec.AddElement(pSenderClient, pRes); Exec.AddElement(pSenderClient, pRes, hash);
#ifdef _DEBUG
printf("* (%s)(%s)(%x)\n", pRes->GetFileName(), pRes->GetCmdExec(), pRes->GetHashFile()); //#ifdef _DEBUG
#endif // _DEBUG if (CVAR_GET_FLOAT("developer") == 1.0f) {
UTIL_Printf(" -> filename: (%s), cmdexec: (%s), hash: (%x)\n", pRes->GetFileName(), pRes->GetCmdExec(), pRes->GetHashFile());
}
//#endif // _DEBUG
} }
} }
m_PreHash = hash; m_PrevHash = hash;
return !bCheckeFiles; return !bCheckeFiles;
} }
CResourceCheckerNew::CResourceCheckerNew(char *filename, char *cmdExec, flag_type_resources flag, uint32 hash) CResourceBuffer::CResourceBuffer(char *filename, char *cmdExec, int flags, uint32 hash)
{ {
int iLenFile = strlen(filename); int lenFile = strlen(filename);
int iLenExec = strlen(cmdExec); int lenExec = strlen(cmdExec);
m_FileName = new char[iLenFile + 1]; m_FileName = new char[lenFile + 1];
m_CmdExec = new char[iLenExec + 1]; m_CmdExec = new char[lenExec + 1];
strncpy(m_FileName, filename, iLenFile); strncpy(m_FileName, filename, lenFile);
strncpy(m_CmdExec, cmdExec, iLenExec); strncpy(m_CmdExec, cmdExec, lenExec);
m_FileName[lenFile] = '\0';
m_CmdExec[lenExec] = '\0';
m_FileName[iLenFile] = '\0';
m_CmdExec[iLenExec] = '\0';
m_Mark = false; m_Mark = false;
m_Flag = flag; m_Flags = flags;
m_HashFile = hash; m_HashFile = hash;
} }
CResourceCheckerNew::~CResourceCheckerNew() CResourceBuffer::~CResourceBuffer()
{ {
// free me // free me
delete[] m_FileName, delete[] m_FileName,

95
src/resource.h Normal file
View File

@ -0,0 +1,95 @@
#pragma once
#define FILE_INI_RESOURCES "resources.ini"
#define MAX_CLIENTS 32
#define MAX_CMD_LENGTH 128
#define MAX_PATH_LENGTH 260
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,
};
enum arg_type_e
{
ARG_TYPE_FILE_NAME = 0,
ARG_TYPE_FILE_HASH,
ARG_TYPE_CMD_EXEC,
ARG_TYPE_FLAG,
MAX_PARSE_ARGUMENT,
};
class CResourceBuffer
{
public:
CResourceBuffer(char *filename, char *cmdExec, int flags, uint32 hash);
~CResourceBuffer();
uint32 GetHashFile() const { return m_HashFile; };
int GetFlagsFile() const { return m_Flags; };
char *GetFileName() const { return m_FileName; };
char *GetCmdExec() const { return m_CmdExec; };
bool GetBreak() const { return m_Break; };
void SetBreak() { m_Break = true; };
bool GetMark() const { return m_Mark; };
void SetMark() { m_Mark = true; };
private:
uint32 m_HashFile;
int m_Flags;
char *m_FileName;
char *m_CmdExec;
bool m_Mark;
bool m_Break;
};
class CResourceFile
{
public:
void Init();
void Load();
void Add();
void Clear();
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);
// parse
const char *GetNextToken(char **pbuf);
private:
typedef std::vector<CResourceBuffer *> ResourceList;
ResourceList m_resourceList;
uint32 m_PrevHash;
bool m_ConfigFailed;
char m_PathDir[MAX_PATH_LENGTH];
};
extern CResourceFile Resource;

View File

@ -1,6 +1,6 @@
#include "precompiled.h" #include "precompiled.h"
void UTIL_Printf(char *fmt, ...) void UTIL_Printf(const char *fmt, ...)
{ {
va_list argptr; va_list argptr;
static char string[1024]; static char string[1024];
@ -13,7 +13,7 @@ void UTIL_Printf(char *fmt, ...)
SERVER_PRINT(string); SERVER_PRINT(string);
} }
void UTIL_LogPrintf(char *fmt, ...) void UTIL_LogPrintf(const char *fmt, ...)
{ {
va_list argptr; va_list argptr;
static char string[1024]; static char string[1024];
@ -26,7 +26,7 @@ void UTIL_LogPrintf(char *fmt, ...)
ALERT(at_logged, "%s", string); ALERT(at_logged, "%s", string);
} }
char *UTIL_VarArgs(char *format, ...) char *UTIL_VarArgs(const char *format, ...)
{ {
va_list argptr; va_list argptr;
static char string[1024]; static char string[1024];