From 853b078124cbe1e4c2926c59b40d3183c89fbbf5 Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Thu, 1 Jul 2021 00:33:28 +0200 Subject: [PATCH] add MP.HttpsGET, MP.HttpsPOST --- src/Http.cpp | 23 +++++++--- src/TLuaFile.cpp | 112 ++++++++++++++++++++++++++++++++++++++++++++--- src/TNetwork.cpp | 2 +- 3 files changed, 125 insertions(+), 12 deletions(-) diff --git a/src/Http.cpp b/src/Http.cpp index a02e323..f69ff5a 100644 --- a/src/Http.cpp +++ b/src/Http.cpp @@ -17,11 +17,14 @@ using tcp = net::ip::tcp; // from std::string Http::GET(const std::string& host, int port, const std::string& target, unsigned int* status) { + try { // Check command line arguments. int version = 11; + + // The io_context is required for all I/O net::io_context ioc; @@ -67,6 +70,8 @@ std::string Http::GET(const std::string& host, int port, const std::string& targ beast::flat_buffer buffer; + + // Declare a container to hold the response http::response res; @@ -86,17 +91,18 @@ std::string Http::GET(const std::string& host, int port, const std::string& targ *status = res.base().result_int(); } - // ignore ec + if (ec) + throw beast::system_error { ec }; // If we get here then the connection is closed gracefully return std::string(res.body()); } catch (std::exception const& e) { Application::Console().Write(__func__ + std::string(": ") + e.what()); - return "-1"; + return ErrorString; } } -std::string Http::POST(const std::string& host, const std::string& target, const std::unordered_map& fields, const std::string& body, bool json, int* status) { +std::string Http::POST(const std::string& host, int port, const std::string& target, const std::unordered_map& fields, const std::string& body, const std::string& ContentType, unsigned int* status) { try { net::io_context io; @@ -110,7 +116,7 @@ std::string Http::POST(const std::string& host, const std::string& target, const decltype(resolver)::results_type results; auto try_connect_with_protocol = [&](tcp protocol) { try { - results = resolver.resolve(protocol, host, std::to_string(443)); + results = resolver.resolve(protocol, host, std::to_string(port)); if (!SSL_set_tlsext_host_name(stream.native_handle(), host.c_str())) { boost::system::error_code ec { static_cast(::ERR_get_error()), boost::asio::error::get_ssl_category() }; // FIXME: we could throw and crash, if we like @@ -189,6 +195,10 @@ std::string Http::POST(const std::string& host, const std::string& target, const } Sentry.SetContext("https-post-response-data", response_data); + if (status) { + *status = response.base().result_int(); + } + std::stringstream result; result << response; @@ -199,12 +209,13 @@ std::string Http::POST(const std::string& host, const std::string& target, const // info(result.str()); std::string debug_response_str; std::getline(result, debug_response_str); + //debug("POST " + host + target + ": " + debug_response_str); return std::string(response.body()); } catch (const std::exception& e) { - Application::Console().Write(e.what()); - return "-1"; + Application::Console().Write(__func__ + std::string(": ") + e.what()); + return ErrorString; } } diff --git a/src/TLuaFile.cpp b/src/TLuaFile.cpp index c5bad80..403a671 100644 --- a/src/TLuaFile.cpp +++ b/src/TLuaFile.cpp @@ -676,7 +676,7 @@ int lua_Registered(lua_State* L) { lua_getstack(L, 0, &info); lua_getinfo(L, "n", &info); - if(auto it = TLuaEngine::mGlobals.find(info.name); it != TLuaEngine::mGlobals.end()){ + if (auto it = TLuaEngine::mGlobals.find(info.name); it != TLuaEngine::mGlobals.end()) { lua_getglobal(it->second, info.name); if (lua_isfunction(it->second, -1)) { lua_pcall(it->second, 0, 0, 0); //TODO revisit to allow arguments and return also we need to mutex this @@ -689,13 +689,13 @@ int lua_Registered(lua_State* L) { } int lua_Register(lua_State* L) { - if(lua_isstring(L, 1)){ + if (lua_isstring(L, 1)) { std::string Name(lua_tolstring(L, 1, nullptr)); lua_getglobal(L, Name.c_str()); if (lua_isfunction(L, -1)) { TLuaEngine::mGlobals.emplace(Name, L); for (auto& Script : Engine().LuaFiles()) { - if(Script->GetState() != L){ + if (Script->GetState() != L) { lua_register(Script->GetState(), Name.c_str(), lua_Registered); } } @@ -705,7 +705,7 @@ int lua_Register(lua_State* L) { ClearStack(L); } } else { - SendError(Engine(), L, "Register wrong arguments expected string"); + SendError(Engine(), L, "Wrong arguments to `Register`, expected string"); } return 0; } @@ -799,6 +799,106 @@ int lua_GetOSName(lua_State* L) { return 1; } +// status, body = HttpGET(host, port, target) +// example usage: +// send a GET https://example.com:443/index.html: +// status, body = MP.HttpGET("example.com", 443, "/index.html") +int lua_HttpsGET(lua_State* L) { + if (!lua_isstring(L, 1)) { + SendError(Engine(), L, "`HttpsGET` expects host (type string) as first argument."); + ClearStack(L); + return 0; + } + if (!lua_isnumber(L, 2)) { + SendError(Engine(), L, "`HttpsGET` expects port (type number) as second argument."); + ClearStack(L); + return 0; + } + if (!lua_isstring(L, 3)) { + SendError(Engine(), L, "`HttpsGET` expects target (type string) as third argument."); + ClearStack(L); + return 0; + } + + auto Host = lua_tostring(L, 1); + auto Port = int(lua_tointeger(L, 2)); + auto Target = lua_tostring(L, 3); + + ClearStack(L); + + unsigned int Status; + auto Body = Http::GET(Host, Port, Target, &Status); + lua_pushinteger(L, Status); + + auto PrettyRemote = "https://" + std::string(Host) + ":" + std::to_string(Port) + std::string(Target); + if (Body == Http::ErrorString) { + SendError(Engine(), L, "HTTPS GET " + PrettyRemote + " failed status " + std::to_string(Status) + ". Check the console or log for more info."); + return 1; + } else { + debug("GET " + PrettyRemote + " completed status " + std::to_string(Status)); + } + + lua_pushstring(L, Body.c_str()); + + return 2; +} + +// status, body = HttpsPOST(host, port, target, body, content_type) +int lua_HttpsPOST(lua_State* L) { + if (!lua_isstring(L, 1)) { + SendError(Engine(), L, "`HttpsPOST` expects host (type string) as 1. argument."); + ClearStack(L); + return 0; + } + if (!lua_isnumber(L, 2)) { + SendError(Engine(), L, "`HttpsPOST` expects port (type number) as 2. argument."); + ClearStack(L); + return 0; + } + if (!lua_isstring(L, 3)) { + SendError(Engine(), L, "`HttpsPOST` expects target (type string) as 3. argument."); + ClearStack(L); + return 0; + } + if (!lua_isstring(L, 4)) { + SendError(Engine(), L, "`HttpsPOST` expects body (type string) as 4. argument."); + ClearStack(L); + return 0; + } + if (!lua_isstring(L, 5)) { + SendError(Engine(), L, "`HttpsPOST` expects content_type (type string) as 5. argument."); + ClearStack(L); + return 0; + } + + auto Host = lua_tostring(L, 1); + auto Port = int(lua_tointeger(L, 2)); + auto Target = lua_tostring(L, 3); + auto RequestBody = lua_tostring(L, 4); + auto ContentType = lua_tostring(L, 5); + + ClearStack(L); + + // build fields + std::unordered_map Fields; + + unsigned int Status; + auto ResponseBody = Http::POST(Host, Port, Target, {}, RequestBody, ContentType, &Status); + + lua_pushinteger(L, Status); + + auto PrettyRemote = "https://" + std::string(Host) + ":" + std::to_string(Port) + std::string(Target); + if (ResponseBody == Http::ErrorString) { + SendError(Engine(), L, "HTTPS POST " + PrettyRemote + " failed status " + std::to_string(Status) + ". Check the console or log for more info."); + return 1; + } else { + debug("POST " + PrettyRemote + " completed status " + std::to_string(Status)); + } + + lua_pushstring(L, ResponseBody.c_str()); + return 2; +} + void TLuaFile::Load() { Assert(mLuaState); luaL_openlibs(mLuaState); @@ -826,6 +926,8 @@ void TLuaFile::Load() { LuaTable::InsertFunction(mLuaState, "Sleep", lua_Sleep); LuaTable::InsertFunction(mLuaState, "Set", lua_Set); LuaTable::InsertFunction(mLuaState, "GetOSName", lua_GetOSName); + LuaTable::InsertFunction(mLuaState, "HttpsGET", lua_HttpsGET); + LuaTable::InsertFunction(mLuaState, "HttpsPOST", lua_HttpsPOST); LuaTable::End(mLuaState, "MP"); lua_register(mLuaState, "print", lua_Print); @@ -901,7 +1003,7 @@ void SendError(TLuaEngine& Engine, lua_State* L, const std::string& msg) { TLuaFile& S = MaybeS.value(); a = fs::path(S.GetFileName()).filename().string(); } - warn(a + (" | Incorrect Call of ") + msg); + warn(a + (" | Error in MP Lua call: ") + msg); } void TLuaArg::PushArgs(lua_State* State) { diff --git a/src/TNetwork.cpp b/src/TNetwork.cpp index f8722fc..3f6511f 100644 --- a/src/TNetwork.cpp +++ b/src/TNetwork.cpp @@ -290,7 +290,7 @@ void TNetwork::Authentication(SOCKET TCPSock) { json::Document AuthResponse; AuthResponse.Parse(Rc.c_str()); - if (Rc == "-1" || AuthResponse.HasParseError()) { + if (Rc == Http::ErrorString || AuthResponse.HasParseError()) { ClientKick(*Client, "Invalid key! Please restart your game."); return; }