From 480c78c9f24dfb9e42758c662662d323f86fc27a Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Sat, 30 Jan 2021 01:11:33 +0100 Subject: [PATCH] Working boost::beast POST request --- src/Init/Heartbeat.cpp | 39 +++++++++++++++++---------------------- src/Network/Http.cpp | 29 +++++++++++++++++++---------- 2 files changed, 36 insertions(+), 32 deletions(-) diff --git a/src/Init/Heartbeat.cpp b/src/Init/Heartbeat.cpp index 080b7c8..536b0e4 100644 --- a/src/Init/Heartbeat.cpp +++ b/src/Init/Heartbeat.cpp @@ -25,25 +25,20 @@ std::string GetPlayers() { } return Return; } -std::unordered_map GenerateCall() { - return { { "uuid", Key }, - { "players", std::to_string(CI->Size()) }, - { "maxplayers", std::to_string(MaxPlayers) }, - { "port", std::to_string(Port) }, - { "map", MapName }, - { "private", (Private ? "true" : "false") }, - { "version", GetSVer() }, - { "clientversion", GetCVer() }, - { "name", ServerName }, - { "pps", StatReport }, - { "modlist", FileList }, - { "modstotalsize", std::to_string(MaxModSize) }, - { "modstotal", std::to_string(ModsLoaded) }, - { "playerslist", GetPlayers() }, - { "desc", ServerDesc } }; +std::string GenerateCall() { + std::stringstream Ret; + Ret << "uuid=" << Key << "&players=" << CI->Size() + << "&maxplayers=" << MaxPlayers << "&port=" << Port + << "&map=" << MapName << "&private=" << (Private ? "true" : "false") + << "&version=" << GetSVer() << "&clientversion=" << GetCVer() + << "&name=" << ServerName << "&pps=" << StatReport + << "&modlist=" << FileList << "&modstotalsize=" << MaxModSize + << "&modstotal=" << ModsLoaded << "&playerslist=" << GetPlayers() + << "&desc=" << ServerDesc; + return Ret.str(); } -std::string RunPromise(const std::string& host, const std::string& target, const std::unordered_map& R) { - std::packaged_task task([&] { return PostHTTP(host, target, R, "", false); }); +std::string RunPromise(const std::string& host, const std::string& target, const std::unordered_map& R, const std::string& body) { + std::packaged_task task([&] { DebugPrintTIDInternal("Heartbeat_POST"); return PostHTTP(host, target, R, body, false); }); std::future f1 = task.get_future(); std::thread t(std::move(task)); t.detach(); @@ -56,19 +51,19 @@ std::string RunPromise(const std::string& host, const std::string& target, const [[noreturn]] void Heartbeat() { DebugPrintTID(); - std::unordered_map R; + std::string R; std::string T; bool isAuth = false; while (true) { R = GenerateCall(); if (!CustomIP.empty()) - R.insert({ "ip", CustomIP }); - T = RunPromise("beammp.com", "/heartbeatv2", R); + R += "&ip=" + CustomIP; + T = RunPromise("beammp.com", "/heartbeatv2", {}, R); if (T.substr(0, 2) != "20") { //Backend system refused server startup! std::this_thread::sleep_for(std::chrono::seconds(10)); - T = RunPromise("backup1.beammp.com", "/heartbeatv2", R); + T = RunPromise("backup1.beammp.com", "/heartbeatv2", {}, R); if (T.substr(0, 2) != "20") { warn("Backend system refused server! Server might not show in the public list"); } diff --git a/src/Network/Http.cpp b/src/Network/Http.cpp index 6fea3b1..7e16011 100644 --- a/src/Network/Http.cpp +++ b/src/Network/Http.cpp @@ -31,6 +31,8 @@ using tcp = net::ip::tcp; // from // UNUSED?! std::string HttpRequest(const std::string& host, int port, const std::string& target) { + // FIXME: this is likely not very well written. + // if it causes issues, yell at me and I'll fix it asap. - Lion try { net::io_context io; tcp::resolver resolver(io); @@ -73,41 +75,45 @@ std::string PostHTTP(const std::string& host, const std::string& target, const s net::io_context io; // The SSL context is required, and holds certificates - ssl::context ctx(ssl::context::tlsv13_client); + ssl::context ctx(ssl::context::tlsv13); ctx.set_verify_mode(ssl::verify_none); tcp::resolver resolver(io); beast::ssl_stream stream(io, ctx); - auto const results = resolver.resolve(host, std::to_string(443)); + auto const results = resolver.resolve(tcp::v6(), host, std::to_string(443)); 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() }; - throw boost::system::system_error { ec }; + // FIXME: we could throw and crash, if we like + // throw boost::system::system_error { ec }; + debug("POST " + host + target + " failed."); + return "-1"; } beast::get_lowest_layer(stream).connect(results); stream.handshake(ssl::stream_base::client); - http::request req { http::verb::post, target, 11 /* http 1.1 */ }; req.set(http::field::host, host); req.set("X-Forwarded-For", HttpRequest("api.ipify.org", 80, "/")); if (!body.empty()) { if (json) { + // FIXME: json is untested. req.set(http::field::content_type, "application/json"); + } else { + req.set(http::field::content_type, "application/x-www-form-urlencoded"); } req.set(http::field::content_length, boost::lexical_cast(body.size())); - req.set(http::field::body, body); + req.body() = body; + // info("body is " + body + " (" + req.body() + ")"); + // info("content size is " + std::to_string(body.size()) + " (" + boost::lexical_cast(body.size()) + ")"); } for (const auto& pair : fields) { - info("setting " + pair.first + " to " + pair.second); + // info("setting " + pair.first + " to " + pair.second); req.set(pair.first, pair.second); } - // tell the server what we are (boost beast) - req.prepare_payload(); std::stringstream oss; oss << req; - warn(oss.str()); beast::get_lowest_layer(stream).expires_after(std::chrono::seconds(5)); @@ -126,7 +132,10 @@ std::string PostHTTP(const std::string& host, const std::string& target, const s stream.shutdown(ec); // IGNORING ec - info(result.str()); + // info(result.str()); + std::string debug_response_str; + std::getline(result, debug_response_str); + debug("POST " + host + target + ": " + debug_response_str); return result.str(); /*} catch (const std::exception& e) {