use boost beast instead of curl

This commit is contained in:
Lion Kortlepel 2021-01-13 22:39:45 +01:00
parent 4e1d2a7ddd
commit d394d7b5a6
5 changed files with 99 additions and 69 deletions

View File

@ -25,7 +25,7 @@ endif ()
file(GLOB source_files "src/*.cpp" "include/*.h" "include/*/*.h" "include/*/*/*.h" "include/*.hpp" "include/*/*.hpp" "src/*/*.cpp")
add_executable(BeamMP-Server ${source_files})
target_include_directories(BeamMP-Server PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
target_include_directories(BeamMP-Server PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> cpp-httplib)
find_package(Lua REQUIRED)
target_include_directories(BeamMP-Server PUBLIC ${LUA_INCLUDE_DIR})

View File

@ -7,5 +7,5 @@
///
#pragma once
#include <string>
std::string HttpRequest(const std::string& IP, int port);
std::string PostHTTP(const std::string& IP, const std::string& Fields, bool json);
std::string HttpRequest(const std::string& host, int port, const std::string& target);
std::string PostHTTP(const std::string& host, int port, const std::string& target, const std::string& Fields, bool json);

View File

@ -36,8 +36,8 @@ std::string GenerateCall() {
<< "&desc=" << ServerDesc;
return Ret.str();
}
std::string RunPromise(const std::string& IP, const std::string& R) {
std::packaged_task<std::string()> task([&] { return PostHTTP(IP, R, false); });
std::string RunPromise(const std::string& host, const std::string& target, const std::string& R) {
std::packaged_task<std::string()> task([&] { return PostHTTP(host, 443, target, R, false); });
std::future<std::string> f1 = task.get_future();
std::thread t(std::move(task));
t.detach();
@ -56,14 +56,12 @@ std::string RunPromise(const std::string& IP, const std::string& R) {
R = GenerateCall();
if (!CustomIP.empty())
R += "&ip=" + CustomIP;
std::string link = "https://beammp.com/heartbeatv2";
T = RunPromise(link, R);
T = RunPromise("https://beammp.com", "/heartbeatv2", R);
if (T.substr(0, 2) != "20") {
//Backend system refused server startup!
std::this_thread::sleep_for(std::chrono::seconds(10));
std::string Backup = "https://backup1.beammp.com/heartbeatv2";
T = RunPromise(Backup, R);
T = RunPromise("https://backup1.beammp.com", "/heartbeatv2", R);
if (T.substr(0, 2) != "20") {
warn("Backend system refused server! Server might not show in the public list");
}

View File

@ -20,8 +20,7 @@
std::string GetClientInfo(const std::string& PK) {
if (!PK.empty()) {
return PostHTTP("https://auth.beammp.com/pkToUser", R"({"key":")" + PK + "\"}", true);
;
return PostHTTP("https://auth.beammp.com", 443, "/pkToUser", R"({"key":")" + PK + "\"}", true);
}
return "";
}

View File

@ -7,71 +7,104 @@
///
#include "CustomAssert.h"
#include <curl/curl.h>
#include <iostream>
class CurlManager {
public:
CurlManager() {
curl = curl_easy_init();
}
~CurlManager() {
curl_easy_cleanup(curl);
}
inline CURL* Get() {
return curl;
#include <boost/asio/connect.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
#include <boost/beast/version.hpp>
#include <boost/lexical_cast.hpp>
#include <cstdlib>
#include <iostream>
#include <string>
namespace beast = boost::beast; // from <boost/beast.hpp>
namespace http = beast::http; // from <boost/beast/http.hpp>
namespace net = boost::asio; // from <boost/asio.hpp>
using tcp = net::ip::tcp; // from <boost/asio/ip/tcp.hpp>
// UNUSED?!
std::string HttpRequest(const std::string& host, int port, const std::string& target) {
try {
net::io_context io;
tcp::resolver resolver(io);
beast::tcp_stream stream(io);
auto const results = resolver.resolve(host, std::to_string(port));
stream.connect(results);
http::request<http::string_body> req { http::verb::get, target, 11 /* http 1.1 */ };
req.set(http::field::host, host);
// tell the server what we are (boost beast)
req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
http::write(stream, req);
// used for reading
beast::flat_buffer buffer;
http::response<http::string_body> response;
http::read(stream, buffer, response);
std::string result(response.body());
beast::error_code ec;
stream.socket().shutdown(tcp::socket::shutdown_both, ec);
if (ec && ec != beast::errc::not_connected) {
throw beast::system_error { ec }; // goes down to `return "-1"` anyways
}
private:
CURL* curl;
};
return result;
static size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp) {
std::string((char*)userp).append((char*)contents, size * nmemb);
return size * nmemb;
}
std::string HttpRequest(const std::string& IP, int port) {
CurlManager M;
std::string readBuffer;
CURL* curl = M.Get();
CURLcode res;
Assert(curl);
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, IP.c_str());
curl_easy_setopt(curl, CURLOPT_PORT, port);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
res = curl_easy_perform(curl);
if (res != CURLE_OK)
} catch (const std::exception& e) {
error(e.what());
return "-1";
}
return readBuffer;
}
std::string PostHTTP(const std::string& IP, const std::string& Fields, bool json) {
auto header = curl_slist { (char*)"Content-Type: application/json", nullptr };
static std::mutex Lock;
std::scoped_lock Guard(Lock);
CurlManager M;
CURL* curl = M.Get();
CURLcode res;
char readBuffer[5000];
std::string PostHTTP(const std::string& host, int port, const std::string& target, const std::string& Fields, bool json) {
try {
net::io_context io;
tcp::resolver resolver(io);
beast::tcp_stream stream(io);
auto const results = resolver.resolve(host, std::to_string(port));
stream.connect(results);
Assert(curl);
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, IP.c_str());
if (json)
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header);
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, Fields.size());
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, Fields.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 5);
res = curl_easy_perform(curl);
if (res != CURLE_OK)
http::request<http::string_body> req { http::verb::post, target, 11 /* http 1.1 */ };
req.set(http::field::host, host);
if (json) {
req.set(http::field::content_type, "application/json");
}
req.set(http::field::content_length, boost::lexical_cast<std::string>(Fields.size()));
req.set(http::field::body, Fields.c_str());
// tell the server what we are (boost beast)
req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
req.prepare_payload();
stream.expires_after(std::chrono::seconds(5));
http::write(stream, req);
// used for reading
beast::flat_buffer buffer;
http::response<http::string_body> response;
http::read(stream, buffer, response);
std::string result(response.body());
beast::error_code ec;
stream.socket().shutdown(tcp::socket::shutdown_both, ec);
if (ec && ec != beast::errc::not_connected) {
throw beast::system_error { ec }; // goes down to `return "-1"` anyways
}
return result;
} catch (const std::exception& e) {
error(e.what());
return "-1";
}
return readBuffer;
}