111
This commit is contained in:
171
include/IO_Ex.hpp
Normal file
171
include/IO_Ex.hpp
Normal file
@@ -0,0 +1,171 @@
|
||||
#pragma once
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <cctype>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
using namespace std;
|
||||
|
||||
// 定义宏用于注册获取不同类型值的函数
|
||||
#define REGISTER_GET_FUNCTION(Type, FunctionName) \
|
||||
Type Get##FunctionName() \
|
||||
{ \
|
||||
char buffer[sizeof(Type)]; \
|
||||
read(buffer, sizeof(Type)); \
|
||||
Type result; \
|
||||
memcpy(&result, buffer, sizeof(Type)); \
|
||||
return result; \
|
||||
}
|
||||
class IO_Ex
|
||||
{
|
||||
|
||||
public:
|
||||
// 原始数据
|
||||
char *_Data;
|
||||
// 最大长度
|
||||
int _MaxLen = 0;
|
||||
// 当前位置
|
||||
int _CurPos = 0;
|
||||
// 上一次读取的实际大小
|
||||
int _LastReadSize = 0;
|
||||
|
||||
public:
|
||||
IO_Ex(const char *filename)
|
||||
{
|
||||
fstream file(filename, std::ios::binary | std::ios::in);
|
||||
if (file.is_open())
|
||||
{
|
||||
file.seekg(0, std::ios::end);
|
||||
std::streampos length = file.tellg();
|
||||
file.seekg(0, std::ios::beg);
|
||||
_MaxLen = length;
|
||||
_Data = new char[static_cast<size_t>(length)];
|
||||
file.read(_Data, length);
|
||||
file.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "无法打开文件。" << std::endl;
|
||||
}
|
||||
}
|
||||
~IO_Ex();
|
||||
|
||||
public:
|
||||
int tellg()
|
||||
{
|
||||
return _CurPos;
|
||||
}
|
||||
void read(char *ptr, int size)
|
||||
{
|
||||
if ((size + _CurPos) > _MaxLen)
|
||||
{
|
||||
size = _MaxLen - _CurPos;
|
||||
}
|
||||
memcpy(ptr, _Data + _CurPos, size);
|
||||
_CurPos += size;
|
||||
_LastReadSize = size;
|
||||
}
|
||||
int gcount()
|
||||
{
|
||||
return _LastReadSize;
|
||||
}
|
||||
void seek(int _jidx)
|
||||
{
|
||||
_CurPos = _jidx;
|
||||
}
|
||||
|
||||
public:
|
||||
unsigned int charPtrToInt(const char *bytes)
|
||||
{
|
||||
unsigned int result;
|
||||
std::memcpy(&result, bytes, sizeof(int));
|
||||
return result;
|
||||
}
|
||||
|
||||
void CrcDecode(const int Length, const int crc32)
|
||||
{
|
||||
int num = 0x81A79011;
|
||||
for (int i = 0; i < Length; i += 4)
|
||||
{
|
||||
int Pos = tellg();
|
||||
char buffer[4];
|
||||
read(buffer, 4);
|
||||
unsigned int anInt = charPtrToInt(buffer);
|
||||
unsigned int val = (anInt ^ num ^ crc32);
|
||||
unsigned int jiemi = (val >> 6) | ((val << (32 - 6)) & 0xFFFFFFFF);
|
||||
_Data[Pos] = ((jiemi >> 0) & 0xFF);
|
||||
;
|
||||
_Data[Pos + 1] = ((jiemi >> 8) & 0xFF);
|
||||
_Data[Pos + 2] = ((jiemi >> 16) & 0xFF);
|
||||
_Data[Pos + 3] = ((jiemi >> 24) & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
std::string tolower(std::string str)
|
||||
{
|
||||
for (size_t i = 0; i < str.length(); ++i)
|
||||
{
|
||||
str[i] = std::tolower(str[i]);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
std::vector<std::string> split(const std::string &str, const std::string &delimiter)
|
||||
{
|
||||
std::vector<std::string> tokens;
|
||||
size_t pos = 0;
|
||||
size_t found;
|
||||
while ((found = str.find(delimiter, pos)) != std::string::npos)
|
||||
{
|
||||
tokens.push_back(str.substr(pos, found - pos));
|
||||
pos = found + delimiter.length();
|
||||
}
|
||||
tokens.push_back(str.substr(pos));
|
||||
return tokens;
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
REGISTER_GET_FUNCTION(int, Int);
|
||||
REGISTER_GET_FUNCTION(short, Short);
|
||||
REGISTER_GET_FUNCTION(unsigned short, UShort);
|
||||
|
||||
std::string GetString(const int size)
|
||||
{
|
||||
char *buffer = new char[size + 1];
|
||||
read(buffer, size);
|
||||
buffer[size] = '\0';
|
||||
if (gcount() != size)
|
||||
{
|
||||
std::cerr << "未能成功读取指定字节数的数据!" << std::endl;
|
||||
delete[] buffer;
|
||||
return "";
|
||||
}
|
||||
std::string result = buffer;
|
||||
delete[] buffer;
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string GetStringNormal(const int size)
|
||||
{
|
||||
char *buffer = new char[size + 1];
|
||||
read(buffer, size);
|
||||
buffer[size] = '\0';
|
||||
if (gcount() != size)
|
||||
{
|
||||
std::cerr << "未能成功读取指定字节数的数据!" << std::endl;
|
||||
delete[] buffer;
|
||||
return "";
|
||||
}
|
||||
std::string result(buffer);
|
||||
delete[] buffer;
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
IO_Ex::~IO_Ex()
|
||||
{
|
||||
}
|
||||
226
include/PVF_IO.hpp
Normal file
226
include/PVF_IO.hpp
Normal file
@@ -0,0 +1,226 @@
|
||||
#pragma once
|
||||
#include "IO_Ex.hpp"
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <cstdint>
|
||||
#include "squirrel.h"
|
||||
#include "sqstdaux.h"
|
||||
#include "sqstdblob.h"
|
||||
#include "sqstdio.h"
|
||||
#include "sqstdmath.h"
|
||||
#include "sqstdstring.h"
|
||||
#include "sqstdsystem.h"
|
||||
|
||||
class PVF_IO : public IO_Ex
|
||||
{
|
||||
struct PvfFileInfo
|
||||
{
|
||||
int ROffset;
|
||||
int Cr32;
|
||||
int Length;
|
||||
bool DecodeFlag = false;
|
||||
};
|
||||
|
||||
private:
|
||||
int StartPos = 0;
|
||||
std::map<std::string, PvfFileInfo> FileInfo;
|
||||
std::map<int, std::string> BinStringM;
|
||||
std::map<std::string, std::map<std::string, std::string>> LoadStringM;
|
||||
|
||||
public:
|
||||
// 构造函数
|
||||
PVF_IO(const char *defaultFilename = "Script.pvf") : IO_Ex(defaultFilename) {}
|
||||
|
||||
// 析构函数,在对象销毁时,基类(fstream)的析构函数会自动被调用,一般不需要额外特殊处理
|
||||
~PVF_IO() {}
|
||||
|
||||
// 显式删除拷贝构造函数,禁止拷贝操作
|
||||
PVF_IO(const PVF_IO &) = delete;
|
||||
|
||||
// 也可以考虑同时删除拷贝赋值运算符,保持一致的语义,避免误用
|
||||
PVF_IO &operator=(const PVF_IO &) = delete;
|
||||
|
||||
public:
|
||||
void Init()
|
||||
{
|
||||
// 读取头建立树
|
||||
InitHeader();
|
||||
|
||||
// 读取bin文件
|
||||
InitBin();
|
||||
|
||||
// 读取LoadString
|
||||
InitLoadString();
|
||||
}
|
||||
|
||||
void InitHeader()
|
||||
{
|
||||
// 读取UUID的长度
|
||||
int UUID_LENGTH = GetInt();
|
||||
// UUID 读 1 - 36位 构造 UTF8 string
|
||||
std::string UUID = GetString(UUID_LENGTH);
|
||||
// 版本号
|
||||
int Version = GetInt();
|
||||
// 文件路径数据的大小
|
||||
int AlignedIndexHeaderSize = GetInt();
|
||||
// 解密密钥
|
||||
int IndexHeaderCrc = GetInt();
|
||||
// 文件数量
|
||||
int IndexSize = GetInt();
|
||||
|
||||
// 文件起始位置
|
||||
int FristPos = tellg();
|
||||
|
||||
CrcDecode(AlignedIndexHeaderSize, IndexHeaderCrc);
|
||||
|
||||
int CurrPos = 0;
|
||||
StartPos = AlignedIndexHeaderSize + 56;
|
||||
|
||||
// 建立pvf文件索引表
|
||||
for (size_t i = 0; i < IndexSize; i++)
|
||||
{
|
||||
seek(FristPos + CurrPos);
|
||||
int FileNumber = GetInt();
|
||||
int FilePathLength = GetInt();
|
||||
std::string FileName = tolower(GetString(FilePathLength));
|
||||
int FileLength = GetInt();
|
||||
int Cre32 = GetInt();
|
||||
int RelativeOffset = GetInt();
|
||||
if (FileLength > 0)
|
||||
{
|
||||
int RealFileLength = (FileLength + 3) & 4294967292;
|
||||
PvfFileInfo Info;
|
||||
Info.ROffset = RelativeOffset;
|
||||
Info.Cr32 = Cre32;
|
||||
Info.Length = RealFileLength;
|
||||
Info.DecodeFlag = false;
|
||||
FileInfo[FileName] = Info;
|
||||
}
|
||||
CurrPos += 20;
|
||||
CurrPos += FilePathLength;
|
||||
}
|
||||
}
|
||||
|
||||
void InitBin()
|
||||
{
|
||||
if (FileInfo.count("stringtable.bin") == 0)
|
||||
{
|
||||
std::cout << "bin文件不存在" << std::endl;
|
||||
return;
|
||||
}
|
||||
PvfFileInfo BinInfo = FileInfo["stringtable.bin"];
|
||||
seek(StartPos + BinInfo.ROffset);
|
||||
CrcDecode(BinInfo.Length, BinInfo.Cr32);
|
||||
seek(StartPos + BinInfo.ROffset);
|
||||
|
||||
int FileHPos = tellg();
|
||||
int Count = GetInt();
|
||||
int CurrentIndex = 0;
|
||||
|
||||
for (int i = 0; i < Count; i++)
|
||||
{
|
||||
seek(FileHPos + CurrentIndex * 4 + 4);
|
||||
int StartPos = GetInt();
|
||||
int EndPos = GetInt();
|
||||
int Len = EndPos - StartPos;
|
||||
seek(FileHPos + StartPos + 4);
|
||||
std::string Str = GetString(Len);
|
||||
BinStringM[CurrentIndex] = Str;
|
||||
CurrentIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
void InitLoadString()
|
||||
{
|
||||
if (FileInfo.count("n_string.lst") == 0)
|
||||
{
|
||||
std::cout << "LoadString文件不存在" << std::endl;
|
||||
return;
|
||||
}
|
||||
PvfFileInfo Info = FileInfo["n_string.lst"];
|
||||
seek(StartPos + Info.ROffset);
|
||||
CrcDecode(Info.Length, Info.Cr32);
|
||||
seek(StartPos + Info.ROffset);
|
||||
|
||||
int FileHPos = tellg();
|
||||
int Flag = GetShort();
|
||||
int i = 2;
|
||||
while (i < Info.Length)
|
||||
{
|
||||
if ((Info.Length - i) >= 10)
|
||||
{
|
||||
seek(FileHPos + i + 6);
|
||||
int FindKey = GetInt();
|
||||
std::string Key = GetBinString(FindKey);
|
||||
std::string Type = tolower(Key.substr(0, Key.find("/")));
|
||||
if (Key.length() > 0)
|
||||
{
|
||||
PvfFileInfo *FileInfo = GetFileInfo(Key);
|
||||
if (FileInfo == nullptr)
|
||||
continue;
|
||||
|
||||
seek(StartPos + FileInfo->ROffset);
|
||||
CrcDecode(FileInfo->Length, FileInfo->Cr32);
|
||||
seek(StartPos + FileInfo->ROffset);
|
||||
|
||||
std::string Str = GetStringNormal(FileInfo->Length);
|
||||
std::vector<std::string> StrArr = split(Str, "\n");
|
||||
for (auto it = StrArr.begin(); it != StrArr.end(); ++it)
|
||||
{
|
||||
std::string strobj = *it;
|
||||
if (strobj.find(">") != std::string::npos)
|
||||
{
|
||||
std::vector<std::string> strobjarr = split(strobj, ">");
|
||||
if (strobjarr.size() > 1)
|
||||
{
|
||||
LoadStringM[Type][strobjarr[0]] = strobjarr[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
i += 10;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
std::string GetBinString(int Key)
|
||||
{
|
||||
if (BinStringM.count(Key))
|
||||
return BinStringM[Key];
|
||||
return "";
|
||||
}
|
||||
std::string GetLoadString(std::string Type, std::string Key)
|
||||
{
|
||||
if (LoadStringM.count(Type) && LoadStringM[Type].count(Key))
|
||||
return LoadStringM[Type][Key];
|
||||
return "";
|
||||
}
|
||||
PvfFileInfo *GetFileInfo(std::string path)
|
||||
{
|
||||
path = tolower(path);
|
||||
if (FileInfo.count(path))
|
||||
return &FileInfo[path];
|
||||
return nullptr;
|
||||
}
|
||||
void LoadFileToBlob(HSQUIRRELVM v, std::string path, SQUserPointer blobp)
|
||||
{
|
||||
path = tolower(path);
|
||||
if (FileInfo.count(path))
|
||||
{
|
||||
seek(StartPos + FileInfo[path].ROffset);
|
||||
if (FileInfo[path].DecodeFlag == false)
|
||||
{
|
||||
CrcDecode(FileInfo[path].Length, FileInfo[path].Cr32);
|
||||
seek(StartPos + FileInfo[path].ROffset);
|
||||
FileInfo[path].DecodeFlag = true;
|
||||
}
|
||||
read((char *)blobp, FileInfo[path].Length);
|
||||
return;
|
||||
}
|
||||
sq_pushnull(v);
|
||||
return;
|
||||
}
|
||||
};
|
||||
@@ -111,11 +111,24 @@ static SQInteger L_DeHookFunc(HSQUIRRELVM v)
|
||||
|
||||
static void example_listener_on_enter(GumInvocationListener *listener, GumInvocationContext *ic)
|
||||
{
|
||||
gpointer ReturnAddress = gum_invocation_context_get_return_address(ic);
|
||||
|
||||
ExampleListener *self = EXAMPLE_LISTENER(listener);
|
||||
|
||||
std::lock_guard<std::recursive_mutex> lock(SqMtx);
|
||||
// 执行虚拟机Main函数
|
||||
SQInteger top = sq_gettop(v); // saves the stack size before the call
|
||||
|
||||
sq_pushroottable(v);
|
||||
sq_pushstring(v, _SC("_Haker_SetNextReturnAddress"), -1);
|
||||
if (SQ_SUCCEEDED(sq_get(v, -2)))
|
||||
{
|
||||
sq_pushroottable(v);
|
||||
sq_pushuserpointer(v, ReturnAddress);
|
||||
sq_call(v, 2, SQFalse, SQTrue);
|
||||
}
|
||||
sq_settop(v, top);
|
||||
|
||||
sq_pushobject(v, self->CallBackOnEnter);
|
||||
sq_pushroottable(v);
|
||||
sq_newarray(v, 0);
|
||||
|
||||
102
include/SqrReg_Asset.hpp
Normal file
102
include/SqrReg_Asset.hpp
Normal file
@@ -0,0 +1,102 @@
|
||||
#pragma once
|
||||
#include "PVF_IO.hpp"
|
||||
|
||||
static SQInteger Asset_LoadScript(HSQUIRRELVM v)
|
||||
{
|
||||
// 获得路径
|
||||
const SQChar *Path;
|
||||
sq_getstring(v, 2, &Path);
|
||||
|
||||
PVF_IO *pvf = new PVF_IO(Path);
|
||||
pvf->Init();
|
||||
sq_pushuserpointer(v, pvf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static SQInteger Asset_GetPvfFileSize(HSQUIRRELVM v)
|
||||
{
|
||||
// 获取PVF指针
|
||||
SQUserPointer Pvfbuf;
|
||||
// 获得路径
|
||||
const SQChar *Path;
|
||||
sq_getuserpointer(v, 2, &Pvfbuf);
|
||||
sq_getstring(v, 3, &Path);
|
||||
|
||||
PVF_IO *Pvf = (PVF_IO *)Pvfbuf;
|
||||
auto Info = Pvf->GetFileInfo(Path);
|
||||
if (Info)
|
||||
sq_pushinteger(v, Info->Length);
|
||||
else
|
||||
sq_pushnull(v);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static SQInteger Asset_GetPvfFile(HSQUIRRELVM v)
|
||||
{
|
||||
// 获取PVF指针
|
||||
SQUserPointer Pvfbuf, blobp;
|
||||
// 获得路径
|
||||
const SQChar *Path;
|
||||
sq_getuserpointer(v, 2, &Pvfbuf);
|
||||
sq_getstring(v, 3, &Path);
|
||||
sqstd_getblob(v, 4, &blobp);
|
||||
|
||||
PVF_IO *Pvf = (PVF_IO *)Pvfbuf;
|
||||
Pvf->LoadFileToBlob(v, Path, blobp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SQInteger Asset_GetPvfBinString(HSQUIRRELVM v)
|
||||
{
|
||||
// 获取PVF指针
|
||||
SQUserPointer Pvfbuf;
|
||||
// 获得Key
|
||||
SQInteger Key;
|
||||
sq_getuserpointer(v, 2, &Pvfbuf);
|
||||
sq_getinteger(v, 3, &Key);
|
||||
|
||||
PVF_IO *Pvf = (PVF_IO *)Pvfbuf;
|
||||
std::string value = Pvf->GetBinString(Key);
|
||||
|
||||
sq_pushstring(v, value.c_str(), value.length());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static SQInteger Asset_GetPvfLoadString(HSQUIRRELVM v)
|
||||
{
|
||||
// 获取PVF指针
|
||||
SQUserPointer Pvfbuf;
|
||||
// 获取类型
|
||||
const SQChar *Type;
|
||||
// 获得Key
|
||||
const SQChar *Key;
|
||||
sq_getuserpointer(v, 2, &Pvfbuf);
|
||||
sq_getstring(v, 3, &Type);
|
||||
sq_getstring(v, 4, &Key);
|
||||
|
||||
PVF_IO *Pvf = (PVF_IO *)Pvfbuf;
|
||||
|
||||
std::string value = Pvf->GetLoadString(Type, Key);
|
||||
value = value.c_str();
|
||||
|
||||
sq_pushstring(v, value.c_str(), value.length());
|
||||
return 1;
|
||||
}
|
||||
|
||||
void RegisterAssetNutApi(const SQChar *funcName, SQFUNCTION funcAddr, HSQUIRRELVM v)
|
||||
{
|
||||
sq_pushroottable(v);
|
||||
sq_pushstring(v, funcName, -1);
|
||||
sq_newclosure(v, funcAddr, 0);
|
||||
sq_newslot(v, -3, false);
|
||||
sq_poptop(v);
|
||||
}
|
||||
|
||||
void RegisterAsset(HSQUIRRELVM v)
|
||||
{
|
||||
RegisterAssetNutApi(_SC("Asset_LoadScript"), Asset_LoadScript, v);
|
||||
RegisterAssetNutApi(_SC("Asset_GetPvfFileSize"), Asset_GetPvfFileSize, v);
|
||||
RegisterAssetNutApi(_SC("Asset_GetPvfFile"), Asset_GetPvfFile, v);
|
||||
RegisterAssetNutApi(_SC("Asset_GetPvfBinString"), Asset_GetPvfBinString, v);
|
||||
RegisterAssetNutApi(_SC("Asset_GetPvfLoadString"), Asset_GetPvfLoadString, v);
|
||||
}
|
||||
@@ -11,42 +11,149 @@
|
||||
#include <asio/basic_socket_streambuf.hpp>
|
||||
#include <iostream>
|
||||
|
||||
extern HSQUIRRELVM v;
|
||||
extern std::recursive_mutex SqMtx;
|
||||
|
||||
static SQInteger CreateHttp(HSQUIRRELVM v)
|
||||
{
|
||||
const SQChar *Host;
|
||||
sq_getstring(v, 2, &Host);
|
||||
const SQChar *Sevice;
|
||||
sq_getstring(v, 3, &Sevice);
|
||||
const SQChar *Service;
|
||||
sq_getstring(v, 3, &Service);
|
||||
const SQChar *Content;
|
||||
sq_getstring(v, 4, &Content);
|
||||
|
||||
asio::io_context ioContext;
|
||||
asio::ip::tcp::resolver resolver(ioContext);
|
||||
asio::ip::tcp::resolver::results_type endpoints = resolver.resolve(Host, Sevice);
|
||||
|
||||
asio::ip::tcp::socket socket(ioContext);
|
||||
asio::connect(socket, endpoints);
|
||||
|
||||
std::string request = std::string(Content);
|
||||
asio::write(socket, asio::buffer(request));
|
||||
|
||||
asio::streambuf response;
|
||||
asio::error_code error;
|
||||
asio::read(socket, response, error);
|
||||
|
||||
if (error != asio::error::eof)
|
||||
try
|
||||
{
|
||||
throw asio::system_error(error);
|
||||
sq_pushnull(v);
|
||||
}
|
||||
asio::io_context ioContext;
|
||||
asio::ip::tcp::resolver resolver(ioContext);
|
||||
auto endpoints = resolver.resolve(Host, Service);
|
||||
asio::ip::tcp::socket socket(ioContext);
|
||||
asio::connect(socket, endpoints);
|
||||
// 发送HTTP请求(假设Content包含完整请求)
|
||||
std::string request = Content;
|
||||
asio::write(socket, asio::buffer(request));
|
||||
// 读取响应(改进建议:解析Content-Length或分块传输)
|
||||
asio::streambuf response;
|
||||
asio::error_code error;
|
||||
while (asio::read(socket, response, asio::transfer_at_least(1), error))
|
||||
{
|
||||
}
|
||||
|
||||
std::istream responseStream(&response);
|
||||
std::ostringstream oss;
|
||||
oss << responseStream.rdbuf();
|
||||
sq_pushstring(v, oss.str().c_str(), -1);
|
||||
if (error && error != asio::error::eof)
|
||||
{
|
||||
throw asio::system_error(error);
|
||||
}
|
||||
// 将响应内容返回
|
||||
std::istream responseStream(&response);
|
||||
std::ostringstream oss;
|
||||
oss << responseStream.rdbuf();
|
||||
sq_pushstring(v, oss.str().c_str(), -1);
|
||||
return 1;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
return sq_throwerror(v, e.what()); // 返回错误信息
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return sq_throwerror(v, _SC("Unknown error occurred"));
|
||||
}
|
||||
}
|
||||
|
||||
void handle_client(tcp::socket *socket, HSQOBJECT HttpServerObject)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 读取请求
|
||||
asio::streambuf request_buf;
|
||||
asio::read_until(*socket, request_buf, "\r\n\r\n");
|
||||
// 提取请求内容
|
||||
std::string request_data = asio::buffer_cast<const char *>(request_buf.data());
|
||||
|
||||
// 调用回调函数(需处理 Squirrel VM 上下文)
|
||||
std::cout << request_data << std::endl;
|
||||
std::lock_guard<std::recursive_mutex> lock(SqMtx);
|
||||
// 执行虚拟机Main函数
|
||||
SQInteger top = sq_gettop(v); // saves the stack size before the call
|
||||
sq_pushobject(v, HttpServerObject);
|
||||
sq_pushstring(v, _SC("Event"), -1);
|
||||
if (SQ_SUCCEEDED(sq_get(v, -2)))
|
||||
{
|
||||
sq_pushobject(v, HttpServerObject);
|
||||
sq_pushuserpointer(v, socket);
|
||||
sq_pushstring(v, request_data.c_str(), -1);
|
||||
sq_call(v, 3, SQFalse, SQTrue); // calls the function
|
||||
}
|
||||
sq_settop(v, top); // restores the original stack size
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
std::cerr << "Error: " << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// 启动 HTTP 服务
|
||||
void start_server(const std::string &host, const std::string &port, HSQOBJECT HttpServerObject)
|
||||
{
|
||||
asio::io_context io_context;
|
||||
tcp::acceptor acceptor(io_context, tcp::endpoint(asio::ip::make_address(host), std::stoi(port)));
|
||||
std::cout << "Server listening on " << host << ":" << port << std::endl;
|
||||
while (true)
|
||||
{
|
||||
tcp::socket *socket = new tcp::socket(io_context);
|
||||
acceptor.accept(*socket);
|
||||
std::cout << "收到信息" << std::endl;
|
||||
// 传递 HttpServerObject 到 handle_client
|
||||
std::thread(handle_client, std::move(socket), HttpServerObject).detach();
|
||||
}
|
||||
}
|
||||
|
||||
static SQInteger CreateHttpServer(HSQUIRRELVM v)
|
||||
{
|
||||
const SQChar *host, *port;
|
||||
sq_getstring(v, 2, &host);
|
||||
sq_getstring(v, 3, &port);
|
||||
HSQOBJECT HttpServerObject;
|
||||
sq_getstackobj(v, 4, &HttpServerObject);
|
||||
// 必须增加一次引用一会记得删除 不然这个函数会被释放
|
||||
sq_addref(v, &HttpServerObject);
|
||||
try
|
||||
{
|
||||
std::thread server_thread(start_server, host, port, HttpServerObject);
|
||||
server_thread.detach();
|
||||
sq_pushbool(v, true);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
sq_pushbool(v, false);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static SQInteger HttpServerResponse_Write(HSQUIRRELVM v)
|
||||
{
|
||||
SQUserPointer P;
|
||||
sq_getuserpointer(v, 2, &P);
|
||||
tcp::socket *socket = (tcp::socket *)P;
|
||||
const SQChar *Content;
|
||||
sq_getstring(v, 3, &Content);
|
||||
try
|
||||
{
|
||||
std::string response = Content;
|
||||
asio::write(*socket, asio::buffer(response));
|
||||
socket->close();
|
||||
delete socket;
|
||||
return 0;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
socket->close();
|
||||
delete socket;
|
||||
return sq_throwerror(v, _SC("Unknown error occurred"));
|
||||
}
|
||||
}
|
||||
|
||||
static SQInteger register_Dio_func(HSQUIRRELVM v, SQFUNCTION f, const char *fname)
|
||||
{
|
||||
sq_pushroottable(v);
|
||||
@@ -60,4 +167,8 @@ static void RegisterDio(HSQUIRRELVM v)
|
||||
{
|
||||
// 创建Http
|
||||
register_Dio_func(v, CreateHttp, _SC("Sq_CreateHttp"));
|
||||
// 创建HttpServer
|
||||
register_Dio_func(v, CreateHttpServer, _SC("Sq_CreateHttpServer"));
|
||||
// 回应HttpServer响应体
|
||||
register_Dio_func(v, HttpServerResponse_Write, _SC("Sq_HttpServerResponse_Write"));
|
||||
}
|
||||
@@ -803,19 +803,6 @@ void processDirectory(const std::string &directoryPath, std::unordered_map<std::
|
||||
sq_call(v, 2, SQFalse, SQTrue); // calls the function
|
||||
}
|
||||
sq_settop(v, top); // restores the original stack size
|
||||
|
||||
// // 文件有变动,写入文件路径
|
||||
// std::ofstream outputFile("/dp_s/auto_reload.dat", std::ios_base::app);
|
||||
// if (outputFile.is_open())
|
||||
// {
|
||||
// std::string ins = "dofile(\"" + filePath + "\");";
|
||||
// outputFile << ins << std::endl;
|
||||
// outputFile.close();
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// std::cerr << "无法创建输出文件。" << std::endl;
|
||||
// }
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1001,6 +988,68 @@ static SQInteger L_HookEquimentUseJewel(HSQUIRRELVM v)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SQInteger LongLongOperation(HSQUIRRELVM v)
|
||||
{
|
||||
const SQChar *valuebuf1;
|
||||
sq_getstring(v, 2, &valuebuf1);
|
||||
long long value1 = std::atoll(valuebuf1);
|
||||
|
||||
const SQChar *valuebuf2;
|
||||
sq_getstring(v, 3, &valuebuf2);
|
||||
long long value2 = std::atoll(valuebuf2);
|
||||
|
||||
const SQChar *TypeBuf;
|
||||
sq_getstring(v, 4, &TypeBuf);
|
||||
std::string Type(TypeBuf);
|
||||
|
||||
std::string RetString = "";
|
||||
if (Type == "+")
|
||||
{
|
||||
RetString = std::to_string(value1 + value2);
|
||||
}
|
||||
else if (Type == "-")
|
||||
{
|
||||
RetString = std::to_string(value1 - value2);
|
||||
}
|
||||
else if (Type == "*")
|
||||
{
|
||||
RetString = std::to_string((static_cast<double>(value1) * static_cast<double>(value2)));
|
||||
}
|
||||
else if (Type == "/")
|
||||
{
|
||||
RetString = std::to_string((static_cast<double>(value1) / static_cast<double>(value2)));
|
||||
}
|
||||
else if (Type == "%")
|
||||
{
|
||||
RetString = std::to_string(value1 % value2);
|
||||
}
|
||||
else if (Type == "format")
|
||||
{
|
||||
if (value1 < 1000)
|
||||
{
|
||||
RetString = std::to_string(value1);
|
||||
}
|
||||
else if (value1 < 1000000)
|
||||
{
|
||||
RetString = std::to_string(value1 / 1000.0) + "k";
|
||||
}
|
||||
else if (value1 < 1000000000)
|
||||
{
|
||||
RetString = std::to_string(value1 / 1000000.0) + "M";
|
||||
}
|
||||
else if (value1 < 1000000000000LL)
|
||||
{
|
||||
RetString = std::to_string(value1 / 1000000000.0) + "G";
|
||||
}
|
||||
else
|
||||
{
|
||||
RetString = std::to_string(value1 / 1000000000000.0) + "T";
|
||||
}
|
||||
}
|
||||
sq_pushstring(v, RetString.c_str(), -1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void RegisterGame(HSQUIRRELVM v)
|
||||
{
|
||||
getConfigPath(szGamePath, sizeof(szGamePath));
|
||||
@@ -1071,4 +1120,6 @@ static void RegisterGame(HSQUIRRELVM v)
|
||||
register_World_func(v, AutoReload, _SC("Sq_AutoReload"));
|
||||
// Hook装备镶嵌
|
||||
register_World_func(v, L_HookEquimentUseJewel, _SC("L_HookEquimentUseJewel"));
|
||||
//大数字计算
|
||||
register_World_func(v, LongLongOperation, _SC("Sq_LongLongOperation"));
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <functional>
|
||||
#include <list>
|
||||
#include <ffi.h>
|
||||
#include <keystone/keystone.h>
|
||||
|
||||
static SQInteger _file_releasehook(SQUserPointer p, SQInteger SQ_UNUSED_ARG(size))
|
||||
{
|
||||
@@ -54,6 +55,29 @@ static SQInteger PointerOperation(HSQUIRRELVM v)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static SQInteger PointerOperationPointer(HSQUIRRELVM v)
|
||||
{
|
||||
SQUserPointer Address;
|
||||
sq_getuserpointer(v, 2, &Address);
|
||||
SQUserPointer Address2;
|
||||
sq_getuserpointer(v, 3, &Address2);
|
||||
|
||||
const SQChar *TypecharBuf;
|
||||
sq_getstring(v, 4, &TypecharBuf);
|
||||
std::string Type(TypecharBuf);
|
||||
|
||||
if (Type == "+")
|
||||
{
|
||||
sq_pushuserpointer(v, (void *)((int)Address + (int)Address2));
|
||||
}
|
||||
else if (Type == "-")
|
||||
{
|
||||
sq_pushuserpointer(v, (void *)((int)Address - (int)Address2));
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 写字节数组
|
||||
static SQInteger Memory_WriteByteArr(HSQUIRRELVM v)
|
||||
{
|
||||
@@ -97,6 +121,53 @@ static SQInteger Memory_ReadString(HSQUIRRELVM v)
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 将汇编代码字符串转为字节码
|
||||
static SQInteger Asmjit_Compile(HSQUIRRELVM v)
|
||||
{
|
||||
const SQChar *CharBuf;
|
||||
sq_getstring(v, 2, &CharBuf);
|
||||
std::string AsmCode(CharBuf);
|
||||
SQUserPointer Address = 0;
|
||||
if (sq_gettop(v) == 3)
|
||||
{
|
||||
sq_getuserpointer(v, 3, &Address);
|
||||
}
|
||||
|
||||
ks_engine *ks;
|
||||
ks_err err;
|
||||
size_t count;
|
||||
unsigned char *encode;
|
||||
size_t size;
|
||||
// 打开Keystone引擎,使用x86-64架构和Intel语法
|
||||
if (ks_open(KS_ARCH_X86, KS_MODE_32, &ks) != KS_ERR_OK)
|
||||
{
|
||||
// fprintf(stderr, "Failed to open Keystone\n");
|
||||
return -1;
|
||||
}
|
||||
// 可选:设置语法为Intel(默认已经是Intel,可省略)
|
||||
ks_option(ks, KS_OPT_SYNTAX, KS_OPT_SYNTAX_INTEL);
|
||||
// 汇编指令
|
||||
if (ks_asm(ks, AsmCode.c_str(), (uint64_t)Address, &encode, &size, &count) != KS_ERR_OK)
|
||||
{
|
||||
// fprintf(stderr, "Assembly error: %s\n", ks_strerror(ks_errno(ks)));
|
||||
ks_close(ks);
|
||||
return -1;
|
||||
}
|
||||
// 创建Squirrel数组
|
||||
sq_newarray(v, 0);
|
||||
// 将每个字节压入数组
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
{
|
||||
sq_pushinteger(v, encode[i]); // 压入字节值
|
||||
sq_arrayappend(v, -2); // 添加到数组(-2是数组位置)
|
||||
}
|
||||
// 释放资源
|
||||
ks_free(encode);
|
||||
ks_close(ks);
|
||||
|
||||
return 1; // 返回1表示有返回值
|
||||
}
|
||||
|
||||
static SQInteger register_Memory_func(HSQUIRRELVM v, SQFUNCTION f, const char *fname)
|
||||
{
|
||||
sq_pushroottable(v);
|
||||
@@ -112,8 +183,11 @@ static void RegisterMemory(HSQUIRRELVM v)
|
||||
register_Memory_func(v, Register_Destruction, "Register_Destruction");
|
||||
// 运算
|
||||
register_Memory_func(v, PointerOperation, "Sq_PointerOperation");
|
||||
register_Memory_func(v, PointerOperationPointer, "Sq_PointerOperationPointer");
|
||||
// 写字节
|
||||
register_Memory_func(v, Memory_WriteByteArr, "Sq_Memory_WriteByteArr");
|
||||
// 读字符串
|
||||
register_Memory_func(v, Memory_ReadString, "Sq_Memory_ReadString");
|
||||
// 将汇编代码字符串转为字节码
|
||||
register_Memory_func(v, Asmjit_Compile, "Sq_Asmjit_Compile");
|
||||
}
|
||||
5726
include/httplib.h
Normal file
5726
include/httplib.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -67,7 +67,7 @@ public:
|
||||
sq_settop(v, top); // restores the original stack size
|
||||
io_context.poll(); // 处理一次事件循环,避免主线程阻塞
|
||||
} else {
|
||||
std::cerr << "Error connecting to server: " << error.message() << std::endl;
|
||||
// std::cerr << "Error connecting to server: " << error.message() << std::endl;
|
||||
start();
|
||||
} });
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "SqrReg_Memory.hpp" //内存类
|
||||
#include "SqrReg_ActiveHook.hpp" //动态HOOK
|
||||
#include "SqrReg_Dio.hpp" //网络类
|
||||
#include "SqrReg_Asset.hpp" //资源类
|
||||
#include <iostream>
|
||||
#include <stdarg.h>
|
||||
|
||||
@@ -35,4 +36,5 @@ static void GlobaRegisterSquirrel(HSQUIRRELVM v)
|
||||
RegisterMemory(v); // 内存类
|
||||
RegisterActiveHook(v); // 动态HOOK
|
||||
RegisterDio(v); // 网络类
|
||||
RegisterAsset(v); // 资源类
|
||||
}
|
||||
Reference in New Issue
Block a user