DP_S/include/SqrReg_Dio.hpp

174 lines
5.2 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
#include "squirrel.h"
#include "sqstdaux.h"
#include "sqstdblob.h"
#include "sqstdio.h"
#include "sqstdmath.h"
#include "sqstdstring.h"
#include "sqstdsystem.h"
#include <asio.hpp>
#include <asio/ssl.hpp>
#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 *Service;
sq_getstring(v, 3, &Service);
const SQChar *Content;
sq_getstring(v, 4, &Content);
try
{
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))
{
}
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);
sq_pushstring(v, fname, -1);
sq_newclosure(v, f, 0); // create a new function
sq_newslot(v, -3, SQFalse);
sq_pop(v, 1); // pops the root table
}
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"));
}