#include "api_lua.hpp" #include "engine/Engine.hpp" #include "network/Network.hpp" #include "coders/json.hpp" using namespace scripting; static int l_get(lua::State* L, network::Network& network) { std::string url(lua::require_lstring(L, 1)); lua::pushvalue(L, 2); auto onResponse = lua::create_lambda_nothrow(L); network::OnReject onReject = nullptr; if (lua::gettop(L) >= 3) { lua::pushvalue(L, 3); auto callback = lua::create_lambda_nothrow(L); onReject = [callback](int code) { callback({code}); }; } network.get(url, [onResponse](std::vector bytes) { engine->postRunnable([=]() { onResponse({std::string(bytes.data(), bytes.size())}); }); }, std::move(onReject)); return 0; } static int l_get_binary(lua::State* L, network::Network& network) { std::string url(lua::require_lstring(L, 1)); lua::pushvalue(L, 2); auto onResponse = lua::create_lambda_nothrow(L); network::OnReject onReject = nullptr; if (lua::gettop(L) >= 3) { lua::pushvalue(L, 3); auto callback = lua::create_lambda_nothrow(L); onReject = [callback](int code) { callback({code}); }; } network.get(url, [onResponse](std::vector bytes) { auto buffer = std::make_shared>( reinterpret_cast(bytes.data()), bytes.size() ); engine->postRunnable([=]() { onResponse({buffer}); }); }, std::move(onReject)); return 0; } static int l_post(lua::State* L, network::Network& network) { std::string url(lua::require_lstring(L, 1)); auto data = lua::tovalue(L, 2); lua::pushvalue(L, 3); auto onResponse = lua::create_lambda_nothrow(L); network::OnReject onReject = nullptr; if (lua::gettop(L) >= 4) { lua::pushvalue(L, 4); auto callback = lua::create_lambda_nothrow(L); onReject = [callback](int code) { callback({code}); }; } std::string string; if (data.isString()) { string = data.asString(); } else { string = json::stringify(data, false); } engine->getNetwork().post(url, string, [onResponse](std::vector bytes) { auto buffer = std::make_shared>( reinterpret_cast(bytes.data()), bytes.size() ); engine->postRunnable([=]() { onResponse({std::string(bytes.data(), bytes.size())}); }); }, std::move(onReject)); return 0; } static int l_connect(lua::State* L, network::Network& network) { std::string address = lua::require_string(L, 1); int port = lua::tointeger(L, 2); lua::pushvalue(L, 3); auto callback = lua::create_lambda_nothrow(L); u64id_t id = network.connect(address, port, [callback](u64id_t id) { engine->postRunnable([=]() { callback({id}); }); }); return lua::pushinteger(L, id); } static int l_close(lua::State* L, network::Network& network) { u64id_t id = lua::tointeger(L, 1); if (auto connection = network.getConnection(id)) { connection->close(true); } return 0; } static int l_closeserver(lua::State* L, network::Network& network) { u64id_t id = lua::tointeger(L, 1); if (auto server = network.getServer(id)) { server->close(); } return 0; } static int l_send(lua::State* L, network::Network& network) { u64id_t id = lua::tointeger(L, 1); auto connection = network.getConnection(id); if (connection == nullptr || connection->getState() == network::ConnectionState::CLOSED) { return 0; } if (lua::istable(L, 2)) { lua::pushvalue(L, 2); size_t size = lua::objlen(L, 2); util::Buffer buffer(size); for (size_t i = 0; i < size; i++) { lua::rawgeti(L, i + 1); buffer[i] = lua::tointeger(L, -1); lua::pop(L); } lua::pop(L); connection->send(buffer.data(), size); } else if (lua::isstring(L, 2)) { auto string = lua::tolstring(L, 2); connection->send(string.data(), string.length()); } else { auto string = lua::bytearray_as_string(L, 2); connection->send(string.data(), string.length()); lua::pop(L); } return 0; } static int l_recv(lua::State* L, network::Network& network) { u64id_t id = lua::tointeger(L, 1); int length = lua::tointeger(L, 2); auto connection = engine->getNetwork().getConnection(id); if (connection == nullptr) { return 0; } length = glm::min(length, connection->available()); util::Buffer buffer(length); int size = connection->recv(buffer.data(), length); if (size == -1) { return 0; } if (lua::toboolean(L, 3)) { lua::createtable(L, size, 0); for (size_t i = 0; i < size; i++) { lua::pushinteger(L, buffer[i] & 0xFF); lua::rawseti(L, i+1); } return 1; } else { return lua::create_bytearray(L, buffer.data(), size); } } static int l_available(lua::State* L, network::Network& network) { u64id_t id = lua::tointeger(L, 1); if (auto connection = network.getConnection(id)) { return lua::pushinteger(L, connection->available()); } return 0; } static int l_open(lua::State* L, network::Network& network) { int port = lua::tointeger(L, 1); lua::pushvalue(L, 2); auto callback = lua::create_lambda_nothrow(L); u64id_t id = network.openServer(port, [callback](u64id_t id) { engine->postRunnable([=]() { callback({id}); }); }); return lua::pushinteger(L, id); } static int l_is_alive(lua::State* L, network::Network& network) { u64id_t id = lua::tointeger(L, 1); if (auto connection = network.getConnection(id)) { return lua::pushboolean( L, connection->getState() != network::ConnectionState::CLOSED || connection->available() > 0 ); } return lua::pushboolean(L, false); } static int l_is_connected(lua::State* L, network::Network& network) { u64id_t id = lua::tointeger(L, 1); if (auto connection = network.getConnection(id)) { return lua::pushboolean( L, connection->getState() == network::ConnectionState::CONNECTED ); } return lua::pushboolean(L, false); } static int l_get_address(lua::State* L, network::Network& network) { u64id_t id = lua::tointeger(L, 1); if (auto connection = network.getConnection(id)) { lua::pushstring(L, connection->getAddress()); lua::pushinteger(L, connection->getPort()); return 2; } return 0; } static int l_is_serveropen(lua::State* L, network::Network& network) { u64id_t id = lua::tointeger(L, 1); if (auto server = network.getServer(id)) { return lua::pushboolean(L, server->isOpen()); } return lua::pushboolean(L, false); } static int l_get_serverport(lua::State* L, network::Network& network) { u64id_t id = lua::tointeger(L, 1); if (auto server = network.getServer(id)) { return lua::pushinteger(L, server->getPort()); } return 0; } static int l_get_total_upload(lua::State* L, network::Network& network) { return lua::pushinteger(L, network.getTotalUpload()); } static int l_get_total_download(lua::State* L, network::Network& network) { return lua::pushinteger(L, network.getTotalDownload()); } template int wrap(lua_State* L) { int result = 0; try { result = func(L, engine->getNetwork()); } // transform exception with description into lua_error catch (std::exception& e) { luaL_error(L, e.what()); } // Rethrow any other exception (lua error for example) catch (...) { throw; } return result; } const luaL_Reg networklib[] = { {"get", wrap}, {"get_binary", wrap}, {"post", wrap}, {"get_total_upload", wrap}, {"get_total_download", wrap}, {"__open", wrap}, {"__closeserver", wrap}, {"__connect", wrap}, {"__close", wrap}, {"__send", wrap}, {"__recv", wrap}, {"__available", wrap}, {"__is_alive", wrap}, {"__is_connected", wrap}, {"__get_address", wrap}, {"__is_serveropen", wrap}, {"__get_serverport", wrap}, {NULL, NULL} };