251 lines
No EOL
5.5 KiB
C++
251 lines
No EOL
5.5 KiB
C++
#define GAME_DLL
|
|
#include "cbase.h"
|
|
#include "bitbuf.h"
|
|
#include "plugin.h"
|
|
#include "glua.h"
|
|
#include "chook.h"
|
|
|
|
typedef struct {
|
|
uint16 family;
|
|
uint16 port;
|
|
uint32 addr;
|
|
} ws2_addr;
|
|
|
|
#define LUA_CALLBACK "onServerQuery"
|
|
#define LUA_CALLBACK2 "onClientResponse"
|
|
|
|
typedef int (__stdcall* SendTo_t)(int,const char*,int,int,void*,int);
|
|
|
|
DECLARE_PLUGIN(CA2SFix)
|
|
public:
|
|
virtual bool Load(CreateInterfaceFn,
|
|
CreateInterfaceFn);
|
|
virtual void Unload();
|
|
virtual bool LuaInit(lua_State*);
|
|
bool IsResponseAllowed(uint32 naddr,unsigned char req);
|
|
bool ProcessResponse(bf_read&,bf_write&,uint32);
|
|
bool ProcessLua(bf_read&,bf_write&,uint32);
|
|
|
|
bool m_bLua;
|
|
lua_State* L;
|
|
static CHook* s_pSendHook;
|
|
static SendTo_t s_SendTo;
|
|
END_PLUGIN(CA2SFix,"A2S Fix");
|
|
|
|
CHook* CA2SFix::s_pSendHook = NULL;
|
|
SendTo_t CA2SFix::s_SendTo = NULL;
|
|
|
|
static int __stdcall SendTo_Hook(int s,const char* buf,
|
|
int len,int flags,void* addr,int tolen)
|
|
{
|
|
static char s_szBuf[1024];
|
|
uint32 naddr = ((ws2_addr*)addr)->addr;
|
|
if(*(uint32*)buf == 0xFFFFFFFF)
|
|
{
|
|
if(!s_CA2SFix.IsResponseAllowed(naddr,(unsigned char)buf[4]))
|
|
return len;
|
|
}
|
|
if(*(uint32*)buf == 0xFFFFFFFF && buf[4] == 0x49)
|
|
{
|
|
memset(s_szBuf,'\0',1024);
|
|
bf_read br(buf,len);
|
|
bf_write bf(s_szBuf,1024);
|
|
if(!s_CA2SFix.ProcessResponse(br,bf,naddr))
|
|
return len;
|
|
return CA2SFix::s_SendTo(s,(const char*)bf.GetData(),
|
|
bf.GetNumBytesWritten(),flags,addr,tolen);
|
|
}
|
|
return CA2SFix::s_SendTo(s,buf,len,flags,addr,tolen);
|
|
}
|
|
|
|
bool CA2SFix::Load(CreateInterfaceFn engineFn,CreateInterfaceFn)
|
|
{
|
|
s_pSendHook = new CHook((DWORD)GetProcAddress(
|
|
GetModuleHandle("WS2_32.dll"),"sendto"),5);
|
|
s_SendTo = (SendTo_t)s_pSendHook
|
|
->HookFunction((DWORD)&SendTo_Hook);
|
|
m_bLua = (GetModuleHandle("lua502.dll") != NULL);
|
|
return true;
|
|
}
|
|
|
|
void CA2SFix::Unload()
|
|
{
|
|
delete s_pSendHook;
|
|
}
|
|
|
|
bool CA2SFix::LuaInit(lua_State* _L)
|
|
{
|
|
L = _L;
|
|
return true;
|
|
}
|
|
|
|
bool CA2SFix::ProcessResponse(bf_read& br,bf_write& bf,uint32 naddr)
|
|
{
|
|
bf.WriteLong(br.ReadLong());
|
|
bf.WriteByte(br.ReadByte());
|
|
br.ReadByte();
|
|
bf.WriteByte(7); //Protocol version
|
|
if(m_bLua)
|
|
{
|
|
if(!ProcessLua(br,bf,naddr))
|
|
return false;
|
|
}
|
|
else bf.WriteBitsFromBuffer(&br,br.GetNumBitsLeft());
|
|
return true;
|
|
}
|
|
|
|
#define lua_setstring(L,name,s) \
|
|
lua_pushstring(L,name); \
|
|
lua_pushstring(L,s); \
|
|
lua_settable(L,-3)
|
|
|
|
#define lua_setnumber(L,name,d) \
|
|
lua_pushstring(L,name); \
|
|
lua_pushnumber(L,(double)d); \
|
|
lua_settable(L,-3)
|
|
|
|
inline const char* lua_getstring(lua_State* L,
|
|
const char* name)
|
|
{
|
|
lua_pushstring(L,name);
|
|
lua_gettable(L,-2);
|
|
const char* pStr = lua_tostring(L,-1);
|
|
lua_pop(L,1);
|
|
return pStr;
|
|
}
|
|
|
|
inline int lua_getnumber(lua_State* L,
|
|
const char* name)
|
|
{
|
|
lua_pushstring(L,name);
|
|
lua_gettable(L,-2);
|
|
int pNum = lua_tonumber(L,-1);
|
|
lua_pop(L,1);
|
|
return pNum;
|
|
}
|
|
|
|
int _aterror(lua_State* L)
|
|
{
|
|
return g_pLua502->GetLuaCallbacks()->OnLuaError(L);
|
|
}
|
|
|
|
inline char* addr2str(uint32 naddr)
|
|
{
|
|
static char szBuf[32] = {0};
|
|
unsigned char* ip = (unsigned char*)&naddr;
|
|
sprintf(szBuf,"%d.%d.%d.%d",ip[0],
|
|
ip[1],ip[2],ip[3]);
|
|
return szBuf;
|
|
}
|
|
|
|
bool CA2SFix::IsResponseAllowed(uint32 naddr,unsigned char req)
|
|
{
|
|
lua_pushcfunction(L,_aterror);
|
|
int iHandler = lua_gettop(L);
|
|
|
|
lua_getglobal(L,LUA_CALLBACK2);
|
|
if(lua_isnil(L,-1))
|
|
{
|
|
lua_pop(L,2);
|
|
return true;
|
|
}
|
|
|
|
lua_pushstring(L,addr2str(naddr));
|
|
lua_pushnumber(L,req);
|
|
lua_pcall(L,2,1,iHandler);
|
|
bool bRet = lua_toboolean(L,-1);
|
|
lua_pop(L,2);
|
|
return bRet;
|
|
}
|
|
|
|
bool CA2SFix::ProcessLua(bf_read& br,bf_write& bf,uint32 naddr)
|
|
{
|
|
lua_pushcfunction(L,_aterror);
|
|
int iHandler = lua_gettop(L);
|
|
|
|
lua_getglobal(L,LUA_CALLBACK);
|
|
if(lua_isnil(L,-1))
|
|
{
|
|
lua_pop(L,2);
|
|
bf.WriteBitsFromBuffer(&br,br.GetNumBitsLeft());
|
|
return true;
|
|
}
|
|
|
|
static char szServer[256] = {0};
|
|
static char szMapName[128] = {0};
|
|
static char szFolder[128];
|
|
static char szGame[64] = {0};
|
|
static char szVersion[32] = {0};
|
|
int iAppId,iPlayers,iMaxPlayers,iBots;
|
|
char szSvType[2] = {0,0};
|
|
char szSvEnv[2] = {0,0};
|
|
bool bVisibility,bVac;
|
|
|
|
br.ReadString(szServer,256);
|
|
br.ReadString(szMapName,128);
|
|
br.ReadString(szFolder,128);
|
|
br.ReadString(szGame,64);
|
|
|
|
iAppId = br.ReadWord();
|
|
iPlayers = br.ReadByte();
|
|
iMaxPlayers = br.ReadByte();
|
|
iBots = br.ReadByte();
|
|
|
|
szSvType[0] = br.ReadByte();
|
|
szSvEnv[0] = br.ReadByte();
|
|
|
|
bVisibility = br.ReadByte();
|
|
bVac = br.ReadByte();
|
|
br.ReadString(szVersion,32);
|
|
|
|
lua_newtable(L);
|
|
|
|
lua_setstring(L,"name",szServer);
|
|
lua_setstring(L,"map",szMapName);
|
|
lua_setstring(L,"folder",szFolder);
|
|
lua_setstring(L,"game",szGame);
|
|
|
|
lua_setnumber(L,"appid",iAppId);
|
|
lua_setnumber(L,"players",iPlayers);
|
|
lua_setnumber(L,"maxplayers",iMaxPlayers);
|
|
lua_setnumber(L,"bots",iBots);
|
|
|
|
lua_setstring(L,"type",szSvType);
|
|
lua_setstring(L,"env",szSvEnv);
|
|
|
|
lua_setnumber(L,"visibility",bVisibility);
|
|
lua_setnumber(L,"vac",bVac);
|
|
|
|
lua_setstring(L,"version",szVersion);
|
|
|
|
lua_pushstring(L,addr2str(naddr));
|
|
lua_pcall(L,2,1,iHandler);
|
|
if(lua_isnil(L,-1))
|
|
{
|
|
lua_pop(L,2);
|
|
bf.WriteBitsFromBuffer(&br,br.GetNumBitsLeft());
|
|
return true;
|
|
}
|
|
|
|
bf.WriteString(lua_getstring(L,"name"));
|
|
bf.WriteString(lua_getstring(L,"map"));
|
|
bf.WriteString(lua_getstring(L,"folder"));
|
|
bf.WriteString(lua_getstring(L,"game"));
|
|
|
|
bf.WriteWord(lua_getnumber(L,"appid"));
|
|
bf.WriteByte(lua_getnumber(L,"players"));
|
|
bf.WriteByte(lua_getnumber(L,"maxplayers"));
|
|
bf.WriteByte(lua_getnumber(L,"bots"));
|
|
|
|
bf.WriteByte(lua_getstring(L,"type")[0]);
|
|
bf.WriteByte(lua_getstring(L,"env")[0]);
|
|
|
|
bf.WriteByte(lua_getnumber(L,"visibility"));
|
|
bf.WriteByte(lua_getnumber(L,"vac"));
|
|
|
|
bf.WriteString(lua_getstring(L,"version"));
|
|
bf.WriteBitsFromBuffer(&br,br.GetNumBitsLeft());
|
|
|
|
lua_pop(L,2);
|
|
return true;
|
|
} |