#pragma once #include "squirrel.h" #include "sqstdaux.h" #include "sqstdblob.h" #include "sqstdio.h" #include "sqstdmath.h" #include "sqstdstring.h" #include "sqstdsystem.h" #include #include #include #include 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(request_buf.data()); // 调用回调函数(需处理 Squirrel VM 上下文) std::cout << request_data << std::endl; std::lock_guard 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")); }