Implemented API

This commit is contained in:
s1lentq 2016-06-07 05:08:49 +07:00
parent 8d1c5e1bbb
commit 3958b33336
19 changed files with 641 additions and 56 deletions

View File

@ -71,6 +71,9 @@
#define FL_KILLME (1<<30) // This entity is marked for death -- This allows the engine to kill ents at the appropriate time
#define FL_DORMANT (1<<31) // Entity is dormant, no updates to client
// SV_EmitSound2 flags
#define SND_EMIT2_NOPAS (1<<0) // never to do check PAS
#define SND_EMIT2_INVOKER (1<<1) // do not send to the client invoker
// Engine edict->spawnflags
#define SF_NOTINDEATHMATCH 0x0800 // Do not spawn when deathmatch and loading entities from a file

View File

@ -35,7 +35,7 @@
#include "model.h"
#define REHLDS_API_VERSION_MAJOR 2
#define REHLDS_API_VERSION_MINOR 7
#define REHLDS_API_VERSION_MINOR 12
//Steam_NotifyClientConnect hook
typedef IHookChain<qboolean, IGameClient*, const void*, unsigned int> IRehldsHook_Steam_NotifyClientConnect;
@ -169,6 +169,26 @@ typedef IHookChainRegistry<int> IRehldsHookRegistry_SV_TransferConsistencyInfo;
typedef IHookChain<bool, uint64, const char *, uint32> IRehldsHook_Steam_GSBUpdateUserData;
typedef IHookChainRegistry<bool, uint64, const char *, uint32> IRehldsHookRegistry_Steam_GSBUpdateUserData;
//Cvar_DirectSet hook
typedef IVoidHookChain<struct cvar_s *, const char *> IRehldsHook_Cvar_DirectSet;
typedef IVoidHookChainRegistry<struct cvar_s *, const char *> IRehldsHookRegistry_Cvar_DirectSet;
//SV_EstablishTimeBase hook
typedef IVoidHookChain<IGameClient *, struct usercmd_s *, int, int, int> IRehldsHook_SV_EstablishTimeBase;
typedef IVoidHookChainRegistry<IGameClient *, struct usercmd_s *, int, int, int> IRehldsHookRegistry_SV_EstablishTimeBase;
//SV_Spawn_f hook
typedef IVoidHookChain<> IRehldsHook_SV_Spawn_f;
typedef IVoidHookChainRegistry<> IRehldsHookRegistry_SV_Spawn_f;
//SV_CreatePacketEntities hook
typedef IHookChain<int, enum sv_delta_s, IGameClient *, struct packet_entities_s *, struct sizebuf_s *> IRehldsHook_SV_CreatePacketEntities;
typedef IHookChainRegistry<int, enum sv_delta_s, IGameClient *, struct packet_entities_s *, struct sizebuf_s *> IRehldsHookRegistry_SV_CreatePacketEntities;
//SV_EmitSound2 hook
typedef IHookChain<bool, edict_t *, IGameClient *, int, const char*, float, float, int, int, int, const float*> IRehldsHook_SV_EmitSound2;
typedef IHookChainRegistry<bool, edict_t *, IGameClient *, int, const char*, float, float, int, int, int, const float*> IRehldsHookRegistry_SV_EmitSound2;
class IRehldsHookchains {
public:
virtual ~IRehldsHookchains() { }
@ -206,6 +226,11 @@ public:
virtual IRehldsHookRegistry_Steam_GSGetSteamID* Steam_GSGetSteamID() = 0;
virtual IRehldsHookRegistry_SV_TransferConsistencyInfo* SV_TransferConsistencyInfo() = 0;
virtual IRehldsHookRegistry_Steam_GSBUpdateUserData* Steam_GSBUpdateUserData() = 0;
virtual IRehldsHookRegistry_Cvar_DirectSet* Cvar_DirectSet() = 0;
virtual IRehldsHookRegistry_SV_EstablishTimeBase* SV_EstablishTimeBase() = 0;
virtual IRehldsHookRegistry_SV_Spawn_f* SV_Spawn_f() = 0;
virtual IRehldsHookRegistry_SV_CreatePacketEntities* SV_CreatePacketEntities() = 0;
virtual IRehldsHookRegistry_SV_EmitSound2* SV_EmitSound2() = 0;
};
struct RehldsFuncs_t {
@ -251,6 +276,10 @@ struct RehldsFuncs_t {
void*(*GetPluginApi)(const char *name);
void(*RegisterPluginApi)(const char *name, void *impl);
qboolean(*SV_FileInConsistencyList)(const char *filename, struct consistency_s **ppconsist);
qboolean(*Steam_NotifyClientConnect)(IGameClient *cl, const void *pvSteam2Key, unsigned int ucbSteam2Key);
void(*Steam_NotifyClientDisconnect)(IGameClient* cl);
void(*SV_StartSound)(int recipients, edict_t *entity, int channel, const char *sample, int volume, float attenuation, int flags, int pitch);
bool(*SV_EmitSound2)(edict_t *entity, IGameClient *receiver, int channel, const char *sample, float volume, float attenuation, int flags, int pitch, int emitFlags, const float *pOrigin);
};
class IRehldsApi {
@ -266,4 +295,4 @@ public:
virtual IRehldsFlightRecorder* GetFlightRecorder() = 0;
};
#define VREHLDS_HLDS_API_VERSION "VREHLDS_HLDS_API_VERSION001"
#define VREHLDS_HLDS_API_VERSION "VREHLDS_HLDS_API_VERSION001"

View File

@ -71,6 +71,7 @@ public:
virtual void SetLastVoiceTime(double time) = 0;
virtual double GetLastVoiceTime() = 0;
virtual bool GetLoopback() = 0;
virtual struct usercmd_s *GetLastCmd() = 0;
// this must be the last virtual function in class
#ifdef REHLDS_SELF
@ -125,4 +126,7 @@ public:
virtual double GetTime() = 0;
virtual void SetResourcesNum(int num) = 0;
virtual struct resource_s *GetResource(int index) = 0;
virtual void SetName(const char* name) = 0;
virtual class ISteamGameServer *GetSteamGameServer() = 0;
virtual struct netadr_s *GetNetFrom() = 0;
};

View File

@ -35,6 +35,7 @@
#define SSSE3_FLAG (1<<9)
#define SSE4_1_FLAG (1<<19)
#define SSE4_2_FLAG (1<<20)
#define POPCNT_FLAG (1<<23)
#define AVX_FLAG (1<<28)
#define AVX2_FLAG (1<<5)
@ -56,6 +57,7 @@ void Sys_CheckCpuInstructionsSupport(void)
cpuinfo.ssse3 = (cpuid_data[2] & SSSE3_FLAG) ? 1 : 0;
cpuinfo.sse4_1 = (cpuid_data[2] & SSE4_1_FLAG) ? 1 : 0;
cpuinfo.sse4_2 = (cpuid_data[2] & SSE4_2_FLAG) ? 1 : 0;
cpuinfo.popcnt = (cpuid_data[2] & POPCNT_FLAG) ? 1 : 0;
cpuinfo.avx = (cpuid_data[2] & AVX_FLAG) ? 1 : 0;
#if defined ASMLIB_H

View File

@ -31,7 +31,7 @@
typedef struct cpuinfo_s
{
uint8 sse3, ssse3, sse4_1, sse4_2, avx, avx2;
uint8 sse3, ssse3, sse4_1, sse4_2, avx, avx2, popcnt;
} cpuinfo_t;
extern cpuinfo_t cpuinfo;

View File

@ -163,7 +163,11 @@
<ClInclude Include="..\pm_shared\pm_shared.h" />
<ClInclude Include="..\public\FileSystem.h" />
<ClInclude Include="..\public\interface.h" />
<ClInclude Include="..\public\rechecker_api.h" />
<ClInclude Include="..\public\rechecker_interfaces.h" />
<ClInclude Include="..\src\cmdexec.h" />
<ClInclude Include="..\src\hookchains_impl.h" />
<ClInclude Include="..\src\rechecker_api_impl.h" />
<ClInclude Include="..\src\resource.h" />
<ClInclude Include="..\src\engine_rehlds.h" />
<ClInclude Include="..\src\main.h" />
@ -176,6 +180,8 @@
</ClCompile>
<ClCompile Include="..\public\interface.cpp" />
<ClCompile Include="..\src\cmdexec.cpp" />
<ClCompile Include="..\src\hookchains_impl.cpp" />
<ClCompile Include="..\src\rechecker_api_impl.cpp" />
<ClCompile Include="..\src\resource.cpp" />
<ClCompile Include="..\src\dllapi.cpp" />
<ClCompile Include="..\src\engine_api.cpp">

View File

@ -462,6 +462,14 @@
<ClInclude Include="..\src\engine_rehlds.h" />
<ClInclude Include="..\src\cmdexec.h" />
<ClInclude Include="..\src\resource.h" />
<ClInclude Include="..\src\hookchains_impl.h" />
<ClInclude Include="..\src\rechecker_api_impl.h" />
<ClInclude Include="..\public\rechecker_api.h">
<Filter>public</Filter>
</ClInclude>
<ClInclude Include="..\public\rechecker_interfaces.h">
<Filter>public</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\common\parsemsg.cpp">
@ -480,6 +488,8 @@
<ClCompile Include="..\src\sdk_util.cpp" />
<ClCompile Include="..\src\cmdexec.cpp" />
<ClCompile Include="..\src\resource.cpp" />
<ClCompile Include="..\src\hookchains_impl.cpp" />
<ClCompile Include="..\src\rechecker_api_impl.cpp" />
</ItemGroup>
<ItemGroup>
<Filter Include="sdk">
@ -506,6 +516,9 @@
<Filter Include="dist">
<UniqueIdentifier>{d8dea905-0ad8-4f5e-973c-fc9917c49e68}</UniqueIdentifier>
</Filter>
<Filter Include="public">
<UniqueIdentifier>{ec8144a1-347d-47dc-9f5f-ffe4670ac29d}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<None Include="..\dist\resources.ini">

102
public/rechecker_api.h Normal file
View File

@ -0,0 +1,102 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#pragma once
#include "hookchains.h"
#include "interface.h"
#define RECHECKER_API_VERSION_MAJOR 1
#define RECHECKER_API_VERSION_MINOR 0
enum flag_type_resources
{
FLAG_TYPE_NONE = 0,
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_HASH_ANY, // any file with any the hash value
};
class IResourceBuffer;
// FileConsistencyProcess hook
typedef IHookChain<bool, IGameClient *, IResourceBuffer *, flag_type_resources , uint32> IRecheckerHook_FileConsistencyProcess;
typedef IHookChainRegistry<bool, IGameClient *, IResourceBuffer *, flag_type_resources , uint32> IRecheckerHookRegistry_FileConsistencyProcess;
// CmdExec hook
typedef IVoidHookChain<IGameClient *, IResourceBuffer *, char *, uint32> IRecheckerHook_CmdExec;
typedef IVoidHookChainRegistry<IGameClient *, IResourceBuffer *, char *, uint32> IRecheckerHookRegistry_CmdExec;
class IRecheckerHookchains {
public:
virtual ~IRecheckerHookchains() { }
virtual IRecheckerHookRegistry_FileConsistencyProcess* FileConsistencyProcess() = 0;
virtual IRecheckerHookRegistry_CmdExec* CmdExec() = 0;
};
class IResourceBuffer {
public:
virtual ~IResourceBuffer() {}
virtual uint32 GetFileHash() const = 0;
virtual flag_type_resources GetFileFlag() const = 0;
virtual const char *GetFileName() const = 0;
virtual const char *GetCmdExec() const = 0;
virtual int GetLine() const = 0;
virtual bool IsBreak() const = 0;
virtual bool IsDuplicate() const = 0;
virtual void SetDuplicate() = 0;
};
class IResourceFile {
public:
virtual ~IResourceFile() {}
virtual const char *FindFilenameOfHash(uint32 hash) = 0;
virtual int GetConsistencyNum() const = 0;
virtual uint32 GetPrevHash() const = 0;
};
struct RecheckerFuncs_t {
void(*AddElement)(char *filename, char *cmdExec, flag_type_resources flag, uint32 hash, bool bBreak);
IResourceBuffer*(*FindElement)(char *filename);
IResourceFile*(*GetResourceFile)();
};
class IRecheckerApi {
public:
virtual ~IRecheckerApi() { }
virtual int GetMajorVersion() = 0;
virtual int GetMinorVersion() = 0;
virtual const RecheckerFuncs_t* GetFuncs() = 0;
virtual IRecheckerHookchains* GetHookchains() = 0;
};

View File

@ -68,7 +68,7 @@ char *GetExecCmdPrepare(IGameClient *pClient, CResourceBuffer *pResource, uint32
if (string[0] != '\0')
{
Resource.Log(LOG_NORMAL, " -> ExecuteCMD: (%s), for (#%u)(%s)", string, nUserID, pClient->GetName());
g_pResource->Log(LOG_NORMAL, " -> ExecuteCMD: (%s), for (#%u)(%s)", string, nUserID, pClient->GetName());
}
len = strlen(string);
@ -81,6 +81,11 @@ char *GetExecCmdPrepare(IGameClient *pClient, CResourceBuffer *pResource, uint32
return string;
}
void EXT_FUNC CmdExec_hook(IGameClient *pClient, IResourceBuffer *pRes, char *cmdExec, uint32 responseHash) {
// execute cmdexec
SERVER_COMMAND(cmdExec);
}
void CExecMngr::CommandExecute(IGameClient *pClient)
{
bool bBreak = false;
@ -113,8 +118,7 @@ void CExecMngr::CommandExecute(IGameClient *pClient)
if (cmdExec != NULL && cmdExec[0] != '\0')
{
// execute cmdexec
SERVER_COMMAND(cmdExec);
g_RecheckerHookchains.m_CmdExec.callChain(CmdExec_hook, pClient, pRes, cmdExec, _byteswap_ulong(pExec->GetClientHash()));
}
bBreak = pRes->IsBreak();

View File

@ -10,6 +10,8 @@ enum rehlds_ret
};
extern IRehldsApi *g_RehldsApi;
extern const RehldsFuncs_t *g_RehldsFuncs;
extern IRehldsHookchains *g_RehldsHookchains;
extern IRehldsServerStatic *g_RehldsSvs;
extern IRehldsServerData *g_RehldsServerData;

52
src/hookchains_impl.cpp Normal file
View File

@ -0,0 +1,52 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "precompiled.h"
#include "hookchains_impl.h"
AbstractHookChainRegistry::AbstractHookChainRegistry()
{
memset(m_Hooks, 0, sizeof(m_Hooks));
m_NumHooks = 0;
}
void AbstractHookChainRegistry::addHook(void* hookFunc) {
if (m_NumHooks >= MAX_HOOKS_IN_CHAIN) {
Sys_Error("MAX_HOOKS_IN_CHAIN limit hit");
}
m_Hooks[m_NumHooks++] = hookFunc;
}
void AbstractHookChainRegistry::removeHook(void* hookFunc) {
// erase hook
for (int i = 0; i < m_NumHooks; i++) {
if (hookFunc == m_Hooks[i]) {
if (--m_NumHooks != i)
{
memmove(&m_Hooks[i], &m_Hooks[i + 1], (m_NumHooks - i) * sizeof(m_Hooks[0]));
m_Hooks[m_NumHooks] = NULL;
}
else
m_Hooks[i] = NULL;
return;
}
}
}

160
src/hookchains_impl.h Normal file
View File

@ -0,0 +1,160 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#pragma once
#include "hookchains.h"
#define MAX_HOOKS_IN_CHAIN 10
extern void __declspec(noreturn) Sys_Error(const char* fmt, ...);
// Implementation for chains in modules
template<typename t_ret, typename ...t_args>
class IHookChainImpl : public IHookChain<t_ret, t_args...> {
public:
typedef t_ret(*hookfunc_t)(IHookChain<t_ret, t_args...>*, t_args...);
typedef t_ret(*origfunc_t)(t_args...);
IHookChainImpl(void** hooks, origfunc_t orig) : m_Hooks(hooks), m_OriginalFunc(orig)
{
if (orig == NULL)
Sys_Error("Non-void HookChain without original function.");
}
virtual ~IHookChainImpl() {}
virtual t_ret callNext(t_args... args) {
hookfunc_t nexthook = (hookfunc_t)m_Hooks[0];
if (nexthook)
{
IHookChainImpl nextChain(m_Hooks + 1, m_OriginalFunc);
return nexthook(&nextChain, args...);
}
return m_OriginalFunc(args...);
}
virtual t_ret callOriginal(t_args... args) {
return m_OriginalFunc(args...);
}
private:
void** m_Hooks;
origfunc_t m_OriginalFunc;
};
// Implementation for void chains in modules
template<typename ...t_args>
class IVoidHookChainImpl : public IVoidHookChain<t_args...> {
public:
typedef void(*hookfunc_t)(IVoidHookChain<t_args...>*, t_args...);
typedef void(*origfunc_t)(t_args...);
IVoidHookChainImpl(void** hooks, origfunc_t orig) : m_Hooks(hooks), m_OriginalFunc(orig) {}
virtual ~IVoidHookChainImpl() {}
virtual void callNext(t_args... args) {
hookfunc_t nexthook = (hookfunc_t)m_Hooks[0];
if (nexthook)
{
IVoidHookChainImpl nextChain(m_Hooks + 1, m_OriginalFunc);
nexthook(&nextChain, args...);
}
else
{
if (m_OriginalFunc)
m_OriginalFunc(args...);
}
}
virtual void callOriginal(t_args... args) {
origfunc_t origfunc = (origfunc_t)m_OriginalFunc;
origfunc(args...);
}
private:
void** m_Hooks;
origfunc_t m_OriginalFunc;
};
class AbstractHookChainRegistry {
protected:
void* m_Hooks[MAX_HOOKS_IN_CHAIN + 1]; // +1 for null
int m_NumHooks;
protected:
void addHook(void* hookFunc);
void removeHook(void* hookFunc);
public:
AbstractHookChainRegistry();
};
template<typename t_ret, typename ...t_args>
class IHookChainRegistryImpl : public IHookChainRegistry < t_ret, t_args...>, public AbstractHookChainRegistry {
public:
typedef t_ret(*hookfunc_t)(IHookChain<t_ret, t_args...>*, t_args...);
typedef t_ret(*origfunc_t)(t_args...);
virtual ~IHookChainRegistryImpl() { }
t_ret callChain(origfunc_t origFunc, t_args... args) {
IHookChainImpl<t_ret, t_args...> chain(m_Hooks, origFunc);
return chain.callNext(args...);
}
virtual void registerHook(hookfunc_t hook) {
addHook((void*)hook);
}
virtual void unregisterHook(hookfunc_t hook) {
removeHook((void*)hook);
}
};
template<typename ...t_args>
class IVoidHookChainRegistryImpl : public IVoidHookChainRegistry <t_args...>, public AbstractHookChainRegistry {
public:
typedef void(*hookfunc_t)(IVoidHookChain<t_args...>*, t_args...);
typedef void(*origfunc_t)(t_args...);
virtual ~IVoidHookChainRegistryImpl() { }
void callChain(origfunc_t origFunc, t_args... args) {
IVoidHookChainImpl<t_args...> chain(m_Hooks, origFunc);
chain.callNext(args...);
}
virtual void registerHook(hookfunc_t hook) {
addHook((void*)hook);
}
virtual void unregisterHook(hookfunc_t hook) {
removeHook((void*)hook);
}
};

View File

@ -11,8 +11,11 @@ bool OnMetaAttach()
if (RehldsApi_Init() != RETURN_LOAD)
return false;
g_pResource = new CResourceFile();
// initialize resource config
Resource.Init();
g_pResource->Init();
Rechecker_Api_Init();
// if have already registered take it
cvar_t *pcv_consistency_prev = g_engfuncs.pfnCVarGetPointer("mp_consistency_");
@ -48,7 +51,7 @@ bool OnMetaAttach()
g_engfuncs.pfnCvar_DirectSet(pcv_consistency_old, "1");
// to remove the old cvar of cvars list
cvar_t *cvar_vars = g_RehldsApi->GetFuncs()->GetCvarVars();
cvar_t *cvar_vars = g_RehldsFuncs->GetCvarVars();
for (cvar_t *var = cvar_vars, *prev = NULL; var != NULL; prev = var, var = var->next)
{
if (var == pcv_consistency_old)
@ -62,12 +65,12 @@ bool OnMetaAttach()
}
// register function from ReHLDS API
g_RehldsApi->GetHookchains()->SV_DropClient()->registerHook(&SV_DropClient);
g_RehldsApi->GetHookchains()->SV_CheckConsistencyResponse()->registerHook(&SV_CheckConsistencyResponse);
g_RehldsApi->GetHookchains()->SV_TransferConsistencyInfo()->registerHook(&SV_TransferConsistencyInfo);
g_RehldsHookchains->SV_DropClient()->registerHook(&SV_DropClient);
g_RehldsHookchains->SV_CheckConsistencyResponse()->registerHook(&SV_CheckConsistencyResponse);
g_RehldsHookchains->SV_TransferConsistencyInfo()->registerHook(&SV_TransferConsistencyInfo);
SV_AddResource = g_RehldsApi->GetFuncs()->SV_AddResource;
SV_FileInConsistencyList = g_RehldsApi->GetFuncs()->SV_FileInConsistencyList;
SV_AddResource = g_RehldsFuncs->SV_AddResource;
SV_FileInConsistencyList = g_RehldsFuncs->SV_FileInConsistencyList;
// go to attach
return true;
@ -84,7 +87,7 @@ void OnMetaDetach()
pcv_mp_consistency->name = tempName;
// restore old cvar mp_consistency
cvar_t *cvar_vars = g_RehldsApi->GetFuncs()->GetCvarVars();
cvar_t *cvar_vars = g_RehldsFuncs->GetCvarVars();
for (cvar_t *var = cvar_vars, *prev = NULL; var != NULL; prev = var, var = var->next)
{
if (var == pcv_mp_consistency)
@ -99,18 +102,18 @@ void OnMetaDetach()
// clear
Exec.Clear();
Resource.Clear();
delete g_pResource;
g_RehldsApi->GetHookchains()->SV_DropClient()->unregisterHook(&SV_DropClient);
g_RehldsApi->GetHookchains()->SV_CheckConsistencyResponse()->unregisterHook(&SV_CheckConsistencyResponse);
g_RehldsApi->GetHookchains()->SV_TransferConsistencyInfo()->unregisterHook(&SV_TransferConsistencyInfo);
g_RehldsHookchains->SV_DropClient()->unregisterHook(&SV_DropClient);
g_RehldsHookchains->SV_CheckConsistencyResponse()->unregisterHook(&SV_CheckConsistencyResponse);
g_RehldsHookchains->SV_TransferConsistencyInfo()->unregisterHook(&SV_TransferConsistencyInfo);
}
void ServerDeactivate_Post()
{
// clear
Exec.Clear();
Resource.Clear();
g_pResource->Clear();
SET_META_RESULT(MRES_IGNORED);
}
@ -121,7 +124,7 @@ void SV_DropClient(IRehldsHook_SV_DropClient *chain, IGameClient *pClient, bool
Exec.Clear(pClient);
// clear temporary files of response
Resource.Clear(pClient);
g_pResource->Clear(pClient);
// call next hook
chain->callNext(pClient, crash, string);
@ -129,10 +132,10 @@ void SV_DropClient(IRehldsHook_SV_DropClient *chain, IGameClient *pClient, bool
int SV_TransferConsistencyInfo(IRehldsHook_SV_TransferConsistencyInfo *chain)
{
Resource.LoadResources();
g_pResource->LoadResources();
// add to the resource
int nConsistency = Resource.CreateResourceList();
int nConsistency = g_pResource->CreateResourceList();
// returns the total number of consistency files
return chain->callNext() + nConsistency;
@ -151,14 +154,14 @@ void ClientPutInServer_Post(edict_t *pEntity)
Exec.CommandExecute(pClient);
// clear temporary files of response
Resource.Clear(pClient);
g_pResource->Clear(pClient);
SET_META_RESULT(MRES_IGNORED);
}
bool SV_CheckConsistencyResponse(IRehldsHook_SV_CheckConsistencyResponse *chain, IGameClient *pSenderClient, resource_t *resource, uint32 hash)
{
if (!Resource.FileConsistencyResponse(pSenderClient, resource, hash))
if (!g_pResource->FileConsistencyResponse(pSenderClient, resource, hash))
return false;
// call next hook and take return of values from original func

View File

@ -2,6 +2,7 @@
#ifdef _WIN32 // WINDOWS
#pragma warning(disable : 4005)
#define EXT_FUNC /**/
#else
#define _stricmp strcasecmp
#define _mkdir mkdir
@ -9,6 +10,7 @@
#undef __FUNCTION__
#endif
#define __FUNCTION__ __func__
#define EXT_FUNC __attribute__((force_align_arg_pointer))
#endif // _WIN32
#define MAX_PATH_LENGTH 260
@ -29,6 +31,10 @@
#include "engine_rehlds.h"
#include "consistency.h"
#include "hookchains_impl.h"
#include "rechecker_api.h"
#include "rechecker_api_impl.h"
#include "main.h"
#include "task.h"
//#include "config.h"
@ -49,4 +55,4 @@
extern void UTIL_Printf(const char *fmt, ...);
extern void UTIL_LogPrintf(const char *fmt, ...);
extern char *UTIL_VarArgs(const char *format, ...);
extern void __declspec(noreturn) Sys_Error(const char* fmt, ...);

View File

@ -0,0 +1,95 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#include "precompiled.h"
CRecheckerApi g_RecheckerApi;
CRecheckerHookchains g_RecheckerHookchains;
RecheckerFuncs_t g_RecheckerApiFuncs =
{
&AddElement_api,
&FindElement_api,
&GetResourceFile_api
};
void EXT_FUNC AddElement_api(char *filename, char *cmdExec, flag_type_resources flag, uint32 hash, bool bBreak)
{
g_pResource->AddElement(filename, cmdExec, flag, hash, 0, bBreak);
}
IResourceBuffer *EXT_FUNC FindElement_api(char *filename)
{
// to mark files which are not required to add to the resource again
for (auto res : (*g_pResource->GetResourceList()))
{
if (_stricmp(res->GetFileName(), filename) == 0)
{
// resource name already have, return its;
return res;
}
}
return nullptr;
}
IResourceFile *EXT_FUNC GetResourceFile_api()
{
return g_pResource;
}
IRecheckerHookRegistry_FileConsistencyProcess* CRecheckerHookchains::FileConsistencyProcess() {
return &m_FileConsistencyProcess;
}
IRecheckerHookRegistry_CmdExec* CRecheckerHookchains::CmdExec() {
return &m_CmdExec;
}
int EXT_FUNC CRecheckerApi::GetMajorVersion()
{
return RECHECKER_API_VERSION_MAJOR;
}
int EXT_FUNC CRecheckerApi::GetMinorVersion()
{
return RECHECKER_API_VERSION_MINOR;
}
const RecheckerFuncs_t* EXT_FUNC CRecheckerApi::GetFuncs()
{
return &g_RecheckerApiFuncs;
}
IRecheckerHookchains* EXT_FUNC CRecheckerApi::GetHookchains()
{
return &g_RecheckerHookchains;
}
void Rechecker_Api_Init()
{
g_RehldsFuncs->RegisterPluginApi("rechecker", &g_RecheckerApi);
}

63
src/rechecker_api_impl.h Normal file
View File

@ -0,0 +1,63 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#pragma once
// FileConsistencyProcess hook
typedef IHookChainImpl<bool, IGameClient *, IResourceBuffer *, flag_type_resources , uint32> CRecheckerHook_FileConsistencyProcess;
typedef IHookChainRegistryImpl<bool, IGameClient *, IResourceBuffer *, flag_type_resources , uint32> CRecheckerHookRegistry_FileConsistencyProcess;
// CmdExec hook
typedef IVoidHookChainImpl<IGameClient *, IResourceBuffer *, char *, uint32> CRecheckerHook_CmdExec;
typedef IVoidHookChainRegistryImpl<IGameClient *, IResourceBuffer *, char *, uint32> CRecheckerHookRegistry_CmdExec;
class CRecheckerHookchains: public IRecheckerHookchains {
public:
CRecheckerHookRegistry_FileConsistencyProcess m_FileConsistencyProcess;
CRecheckerHookRegistry_CmdExec m_CmdExec;
public:
virtual IRecheckerHookRegistry_FileConsistencyProcess *FileConsistencyProcess();
virtual IRecheckerHookRegistry_CmdExec *CmdExec();
};
extern CRecheckerHookchains g_RecheckerHookchains;
extern RecheckerFuncs_t g_RecheckerApiFuncs;
class CRecheckerApi: public IRecheckerApi {
public:
virtual int GetMajorVersion();
virtual int GetMinorVersion();
virtual const RecheckerFuncs_t* GetFuncs();
virtual IRecheckerHookchains* GetHookchains();
};
void Rechecker_Api_Init();
void AddElement_api(char *filename, char *cmdExec, flag_type_resources flag, uint32 hash, bool bBreak);
IResourceBuffer *FindElement_api(char *filename);
IResourceFile *GetResourceFile_api();

View File

@ -1,6 +1,6 @@
#include "precompiled.h"
CResourceFile Resource;
CResourceFile *g_pResource = nullptr;
std::vector<const char *> StringsCache;
cvar_t cv_rch_log = { "rch_log", "0", 0, 0.0f, NULL };
@ -8,6 +8,21 @@ cvar_t *pcv_rch_log = NULL;
const char *szTypeNames[] = { "none", "exists", "missing", "ignore", "hash_any" };
CResourceFile::CResourceFile() :
m_resourceList(),
m_responseList(),
m_ConsistencyNum(0),
m_PrevHash(0)
{
m_PathDir[0] = '\0';
m_LogFilePath[0] = '\0';
}
CResourceFile::~CResourceFile()
{
Clear();
}
int CResourceFile::CreateResourceList()
{
int startIndex = 4095;
@ -15,7 +30,7 @@ int CResourceFile::CreateResourceList()
ComputeConsistencyFiles();
for (auto& res : m_resourceList)
for (auto res : m_resourceList)
{
// prevent duplicate of filenames
// check if filename is been marked so do not add the resource again
@ -66,7 +81,7 @@ int CResourceFile::CreateResourceList()
return a.nIndex < b.nIndex;
});
for (auto& res : sortList)
for (auto res : sortList)
{
// Add new resource in the own order
SV_AddResource(res.type, res.szFileName, res.nDownloadSize, res.ucFlags, res.nIndex);
@ -519,7 +534,7 @@ void CResourceFile::AddElement(char *filename, char *cmdExec, flag_type_resource
auto nRes = new CResourceBuffer(filename, cmdExec, flag, hash, line, bBreak);
// to mark files which are not required to add to the resource again
for (auto& res : m_resourceList)
for (auto res : m_resourceList)
{
if (_stricmp(res->GetFileName(), filename) == 0)
{
@ -537,6 +552,10 @@ void CResourceFile::AddFileResponse(IGameClient *pSenderClient, char *filename,
m_responseList.push_back(new CResponseBuffer(pSenderClient, filename, hash));
}
bool EXT_FUNC FileConsistencyProcess_hook(IGameClient *pSenderClient, IResourceBuffer *res, flag_type_resources typeFind, uint32 hash) {
return true;
}
bool CResourceFile::FileConsistencyResponse(IGameClient *pSenderClient, resource_t *resource, uint32 hash)
{
bool bHandled = false;
@ -559,7 +578,7 @@ bool CResourceFile::FileConsistencyResponse(IGameClient *pSenderClient, resource
return true;
}
for (auto& res : m_resourceList)
for (auto res : m_resourceList)
{
if (strcmp(resource->szFileName, res->GetFileName()) != 0)
continue;
@ -581,7 +600,7 @@ bool CResourceFile::FileConsistencyResponse(IGameClient *pSenderClient, resource
}
break;
case FLAG_TYPE_HASH_ANY:
for (auto& temp : tempResourceList)
for (auto temp : tempResourceList)
{
if (_stricmp(temp->GetFileName(), res->GetFileName()) != 0)
continue;
@ -604,15 +623,19 @@ bool CResourceFile::FileConsistencyResponse(IGameClient *pSenderClient, resource
break;
}
if (typeFind != FLAG_TYPE_NONE)
if (g_RecheckerHookchains.m_FileConsistencyProcess.callChain(FileConsistencyProcess_hook, pSenderClient, res, typeFind, hash))
{
// push exec cmd
Exec.AddElement(pSenderClient, res, hash);
//FileConsistencyProcess
if (typeFind != FLAG_TYPE_NONE)
{
// push exec cmd
Exec.AddElement(pSenderClient, res, hash);
flag_type_log type = (typeFind == FLAG_TYPE_IGNORE) ? LOG_DETAILED : LOG_NORMAL;
Log(type, " -> file: (%s), exphash: (%x), got: (%x), typeFind: (%s), prevhash: (%x), (#%u)(%s), prevfile: (%s), findathash: (%s), md5hex: (%x)",
res->GetFileName(), res->GetFileHash(), hash, szTypeNames[ typeFind ], m_PrevHash, g_engfuncs.pfnGetPlayerUserId(pSenderClient->GetEdict()),
pSenderClient->GetName(), FindFilenameOfHash(m_PrevHash), FindFilenameOfHash(hash), _byteswap_ulong(hash));
flag_type_log type = (typeFind == FLAG_TYPE_IGNORE) ? LOG_DETAILED : LOG_NORMAL;
Log(type, " -> file: (%s), exphash: (%x), got: (%x), typeFind: (%s), prevhash: (%x), (#%u)(%s), prevfile: (%s), findathash: (%s), md5hex: (%x)",
res->GetFileName(), res->GetFileHash(), hash, szTypeNames[ typeFind ], m_PrevHash, g_engfuncs.pfnGetPlayerUserId(pSenderClient->GetEdict()),
pSenderClient->GetName(), FindFilenameOfHash(m_PrevHash), FindFilenameOfHash(hash), _byteswap_ulong(hash));
}
}
bHandled = true;
@ -625,7 +648,7 @@ bool CResourceFile::FileConsistencyResponse(IGameClient *pSenderClient, resource
const char *DuplicateString(const char *str)
{
for (auto& string : StringsCache)
for (auto string : StringsCache)
{
if (!strcmp(string, str))
return string;
@ -638,7 +661,7 @@ const char *DuplicateString(const char *str)
void ClearStringsCache()
{
for (auto& string : StringsCache)
for (auto string : StringsCache)
delete [] string;
StringsCache.clear();
@ -667,7 +690,7 @@ CResourceFile::CResponseBuffer::CResponseBuffer(IGameClient *pSenderClient, char
const char *CResourceFile::FindFilenameOfHash(uint32 hash)
{
for (auto& res : m_responseList)
for (auto res : m_responseList)
{
if (res->GetClientHash() == hash)
return res->GetFileName();

View File

@ -14,15 +14,6 @@ enum flag_type_log
LOG_DETAILED
};
enum flag_type_resources
{
FLAG_TYPE_NONE = 0,
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_HASH_ANY, // any file with any the hash value
};
enum arg_type_e
{
ARG_TYPE_FILE_NAME = 0,
@ -34,7 +25,7 @@ enum arg_type_e
};
// buffer for checker list
class CResourceBuffer
class CResourceBuffer: public IResourceBuffer
{
public:
CResourceBuffer(char *filename, char *cmdExec, flag_type_resources flag, uint32 hash, int line, bool bBreak);
@ -63,9 +54,12 @@ private:
bool m_Break; // do not check a next files
};
class CResourceFile
class CResourceFile: public IResourceFile
{
public:
CResourceFile();
~CResourceFile();
void Init();
void Clear(IGameClient *pClient = NULL);
void LoadResources();
@ -73,7 +67,6 @@ public:
void Log(flag_type_log type, const char *fmt, ...);
bool FileConsistencyResponse(IGameClient *pSenderClient, resource_t *resource, uint32 hash);
private:
// buffer for response list
class CResponseBuffer
@ -95,9 +88,7 @@ private:
private:
// for temporary files of responses
void AddElement(char *filename, char *cmdExec, flag_type_resources flag, uint32 hash, int line, bool bBreak);
void AddFileResponse(IGameClient *pSenderClient, char *filename, uint32 hash);
const char *FindFilenameOfHash(uint32 hash);
void LogPrepare();
// compute the total number of consistency files.
@ -118,9 +109,16 @@ private:
char m_PathDir[MAX_PATH_LENGTH];
char m_LogFilePath[MAX_PATH_LENGTH]; // log data
public:
const char *FindFilenameOfHash(uint32 hash);
int GetConsistencyNum() const { return m_ConsistencyNum; }
uint32 GetPrevHash() const { return m_PrevHash; }
void AddElement(char *filename, char *cmdExec, flag_type_resources flag, uint32 hash, int line, bool bBreak);
const ResourceList *GetResourceList() const { return &m_resourceList; }
};
extern CResourceFile Resource;
extern CResourceFile *g_pResource;
extern cvar_t *pcv_rch_log;
void ClearStringsCache();

View File

@ -37,3 +37,23 @@ char *UTIL_VarArgs(const char *format, ...)
return string;
}
void __declspec(noreturn) Sys_Error(const char* fmt, ...)
{
va_list argptr;
static char string[8192];
va_start(argptr, fmt);
vsnprintf(string, sizeof(string), fmt, argptr);
va_end(argptr);
printf("%s\n", string);
FILE *fl = fopen("rehlds_error.txt", "w");
fprintf(fl, "%s\n", string);
fclose(fl);
//TerminateProcess(GetCurrentProcess(), 1);
*((int*)NULL) = 0;
while (true);
}