174 lines
5.2 KiB
C++
174 lines
5.2 KiB
C++
#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"));
|
||
} |