mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2025-07-01 15:26:59 +00:00
remove boost, add httplib, temporarily remove http* lua
This commit is contained in:
parent
1e305c3c90
commit
701a7feee3
2
.github/workflows/cmake-linux.yml
vendored
2
.github/workflows/cmake-linux.yml
vendored
@ -21,8 +21,6 @@ jobs:
|
||||
echo ${#beammp_sentry_url}
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libz-dev rapidjson-dev liblua5.3 libssl-dev libwebsocketpp-dev libcurl4-openssl-dev
|
||||
sudo add-apt-repository ppa:mhier/libboost-latest
|
||||
sudo apt-get install -y libboost1.70-dev libboost1.70
|
||||
|
||||
- name: Create Build Environment
|
||||
run: cmake -E make_directory ${{github.workspace}}/build-linux
|
||||
|
2
.github/workflows/cmake-windows.yml
vendored
2
.github/workflows/cmake-windows.yml
vendored
@ -18,7 +18,7 @@ jobs:
|
||||
uses: lukka/run-vcpkg@v7
|
||||
id: runvcpkg
|
||||
with:
|
||||
vcpkgArguments: 'lua zlib rapidjson boost-beast boost-asio openssl websocketpp curl'
|
||||
vcpkgArguments: 'lua zlib rapidjson openssl websocketpp curl'
|
||||
vcpkgDirectory: '${{ runner.workspace }}/b/vcpkg'
|
||||
vcpkgGitCommitId: '8dddc6c899ce6fdbeab38b525a31e7f23cb2d5bb'
|
||||
vcpkgTriplet: 'x64-windows-static'
|
||||
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -22,3 +22,6 @@
|
||||
[submodule "deps/libzip"]
|
||||
path = deps/libzip
|
||||
url = https://github.com/nih-at/libzip
|
||||
[submodule "deps/cpp-httplib"]
|
||||
path = deps/cpp-httplib
|
||||
url = https://github.com/yhirose/cpp-httplib
|
||||
|
@ -13,8 +13,11 @@ include_directories("${PROJECT_SOURCE_DIR}/deps/rapidjson/include")
|
||||
include_directories("${PROJECT_SOURCE_DIR}/deps/websocketpp")
|
||||
include_directories("${PROJECT_SOURCE_DIR}/deps/commandline")
|
||||
include_directories("${PROJECT_SOURCE_DIR}/deps/sol2/include")
|
||||
include_directories("${PROJECT_SOURCE_DIR}/deps/cpp-httplib")
|
||||
include_directories("${PROJECT_SOURCE_DIR}/deps")
|
||||
|
||||
add_compile_definitions(CPPHTTPLIB_OPENSSL_SUPPORT)
|
||||
|
||||
if (WIN32)
|
||||
# this has to happen before sentry, so that crashpad on windows links with these settings.
|
||||
message(STATUS "MSVC -> forcing use of statically-linked runtime.")
|
||||
@ -67,9 +70,6 @@ set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG")
|
||||
|
||||
message(STATUS "Looking for Boost")
|
||||
find_package(Boost REQUIRED COMPONENTS system thread)
|
||||
|
||||
add_executable(BeamMP-Server
|
||||
src/main.cpp
|
||||
include/TConsole.h src/TConsole.cpp
|
||||
@ -92,7 +92,7 @@ add_executable(BeamMP-Server
|
||||
include/SignalHandling.h src/SignalHandling.cpp)
|
||||
|
||||
target_compile_definitions(BeamMP-Server PRIVATE SECRET_SENTRY_URL="${BEAMMP_SECRET_SENTRY_URL}")
|
||||
include_directories(BeamMP-Server PUBLIC ${Boost_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
include_directories(BeamMP-Server PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
|
||||
target_include_directories(BeamMP-Server PUBLIC
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include"
|
||||
@ -101,7 +101,6 @@ target_include_directories(BeamMP-Server PUBLIC
|
||||
message(STATUS "Looking for Lua")
|
||||
find_package(Lua REQUIRED)
|
||||
target_include_directories(BeamMP-Server PUBLIC
|
||||
${Boost_INCLUDE_DIRS}
|
||||
${LUA_INCLUDE_DIR}
|
||||
${CURL_INCLUDE_DIRS}
|
||||
"include/tomlplusplus"
|
||||
@ -131,7 +130,7 @@ elseif (WIN32)
|
||||
find_package(ZLIB REQUIRED)
|
||||
message(STATUS "Looking for RapidJSON")
|
||||
find_package(RapidJSON CONFIG REQUIRED)
|
||||
target_include_directories(BeamMP-Server PRIVATE ${RAPIDJSON_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS})
|
||||
target_include_directories(BeamMP-Server PRIVATE ${RAPIDJSON_INCLUDE_DIRS})
|
||||
target_link_libraries(BeamMP-Server
|
||||
ws2_32
|
||||
ZLIB::ZLIB
|
||||
|
@ -51,7 +51,7 @@ Currently only linux and windows are supported (generally). See [Releases](https
|
||||
|
||||
Please use the prepackaged binaries in [Releases](https://github.com/BeamMP/BeamMP-Server/releases/).
|
||||
|
||||
Dependencies for windows can be installed with `vcpkg`, in which case the current dependencies are the `x64-windows-static` versions of `lua`, `zlib`, `rapidjson`, `boost-beast`, `boost-asio` and `openssl`.
|
||||
Dependencies for windows can be installed with `vcpkg`, in which case the current dependencies are the `x64-windows-static` versions of `lua`, `zlib`, `rapidjson`, and `openssl`.
|
||||
|
||||
#### Linux / \*nix
|
||||
|
||||
@ -72,19 +72,16 @@ These package names are in the debian / ubuntu style. Feel free to PR your own g
|
||||
- `rapidjson-dev`
|
||||
- `libopenssl-dev` or `libssl-dev`
|
||||
|
||||
**If** you're building it from source, you'll need `libboost1.70-all-dev` or `libboost1.71-all-dev` or higher as well.
|
||||
If you can't find this version of boost (only 1.6x, for example), you can either update to a newer version of your distro, build boost yourself, or use an unstable rolling release (like Debian `sid` aka `unstable`).
|
||||
|
||||
In the end you should end up with a command something like this:
|
||||
|
||||
```sh
|
||||
sudo apt install git make cmake g++-10 liblua5.3 libz-dev rapidjson-dev libopenssl-dev libboost1.71-all-dev
|
||||
sudo apt install git make cmake g++-10 liblua5.3 libz-dev rapidjson-dev libopenssl-dev
|
||||
```
|
||||
|
||||
In the end you should end up with a command something like this:
|
||||
|
||||
```sh
|
||||
sudo apt install git make cmake g++-10 liblua5.3 libz-dev rapidjson-dev libopenssl-dev libboost1.71-all-dev
|
||||
sudo apt install git make cmake g++-10 liblua5.3 libz-dev rapidjson-dev libopenssl-dev
|
||||
```
|
||||
|
||||
### How to build
|
||||
|
1
deps/cpp-httplib
vendored
Submodule
1
deps/cpp-httplib
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 301faa074c4a0fa1dbe470dfb4f77912caa1c57f
|
@ -5,7 +5,7 @@
|
||||
|
||||
namespace Http {
|
||||
std::string GET(const std::string& host, int port, const std::string& target, unsigned int* status = nullptr);
|
||||
std::string POST(const std::string& host, int port, const std::string& target, const std::unordered_map<std::string, std::string>& fields, const std::string& body, const std::string& ContentType, unsigned int* status = nullptr);
|
||||
std::string POST(const std::string& host, int port, const std::string& target, const std::string& body, const std::string& ContentType, unsigned int* status = nullptr);
|
||||
namespace Status {
|
||||
std::string ToString(int code);
|
||||
}
|
||||
|
139
src/Http.cpp
139
src/Http.cpp
@ -1,134 +1,39 @@
|
||||
#include "Http.h"
|
||||
|
||||
#include "Common.h"
|
||||
#undef error
|
||||
|
||||
#include <boost/asio/connect.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/beast.hpp>
|
||||
#include <boost/beast/ssl.hpp>
|
||||
#include <map>
|
||||
|
||||
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>
|
||||
namespace ssl = net::ssl; // from <boost/asio/ssl.hpp>
|
||||
using tcp = net::ip::tcp; // from <boost/asio/ip/tcp.hpp>
|
||||
#include <httplib.h>
|
||||
|
||||
std::string GenericRequest(http::verb verb, const std::string& host, int port, const std::string& target, const std::unordered_map<std::string, std::string>& fields, const std::string& body, const std::string& ContentType, unsigned int* status) {
|
||||
try {
|
||||
net::io_context io;
|
||||
// TODO: Add sentry error handling back
|
||||
|
||||
// The SSL context is required, and holds certificates
|
||||
ssl::context ctx(ssl::context::tlsv13);
|
||||
|
||||
ctx.set_verify_mode(ssl::verify_none);
|
||||
|
||||
tcp::resolver resolver(io);
|
||||
beast::ssl_stream<beast::tcp_stream> stream(io, ctx);
|
||||
decltype(resolver)::results_type results;
|
||||
auto try_connect_with_protocol = [&](tcp protocol) {
|
||||
try {
|
||||
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<int>(::ERR_get_error()), boost::asio::error::get_ssl_category() };
|
||||
return false;
|
||||
}
|
||||
beast::get_lowest_layer(stream).connect(results);
|
||||
} catch (const boost::system::system_error&) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
bool ok = try_connect_with_protocol(tcp::v4());
|
||||
if (!ok) {
|
||||
Application::Console().Write("[ERROR] failed to resolve or connect in POST " + host + target);
|
||||
Sentry.AddErrorBreadcrumb("failed to resolve or connect to " + host + target, __FILE__, std::to_string(__LINE__)); // FIXME: this is ugly.
|
||||
return "-1";
|
||||
}
|
||||
stream.handshake(ssl::stream_base::client);
|
||||
http::request<http::string_body> req { verb, target, 11 /* http 1.1 */ };
|
||||
|
||||
req.set(http::field::host, host);
|
||||
if (!body.empty()) {
|
||||
if (!ContentType.empty()) {
|
||||
req.set(http::field::content_type, ContentType); // "application/json"
|
||||
// "application/x-www-form-urlencoded"
|
||||
}
|
||||
|
||||
req.set(http::field::content_length, std::to_string(body.size()));
|
||||
req.body() = body;
|
||||
}
|
||||
for (const auto& pair : fields) {
|
||||
req.set(pair.first, pair.second);
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, std::string> request_data;
|
||||
for (const auto& header : req.base()) {
|
||||
// need to do explicit casts to convert string_view to string
|
||||
// since string_view may not be null-terminated (and in fact isn't, here)
|
||||
std::string KeyString(header.name_string());
|
||||
std::string ValueString(header.value());
|
||||
request_data[KeyString] = ValueString;
|
||||
}
|
||||
Sentry.SetContext("https-request-data", request_data);
|
||||
|
||||
std::stringstream oss;
|
||||
oss << req;
|
||||
|
||||
beast::get_lowest_layer(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::unordered_map<std::string, std::string> response_data;
|
||||
response_data["reponse-code"] = std::to_string(response.result_int());
|
||||
std::string Http::GET(const std::string& host, int port, const std::string& target, unsigned int* status) {
|
||||
httplib::SSLClient client(host, port);
|
||||
client.enable_server_certificate_verification(false);
|
||||
auto res = client.Get(target.c_str());
|
||||
if (res) {
|
||||
if (status) {
|
||||
*status = response.result_int();
|
||||
*status = res->status;
|
||||
}
|
||||
for (const auto& header : response.base()) {
|
||||
// need to do explicit casts to convert string_view to string
|
||||
// since string_view may not be null-terminated (and in fact isn't, here)
|
||||
std::string KeyString(header.name_string());
|
||||
std::string ValueString(header.value());
|
||||
response_data[KeyString] = ValueString;
|
||||
}
|
||||
Sentry.SetContext("https-response-data", response_data);
|
||||
|
||||
if (status) {
|
||||
*status = response.base().result_int();
|
||||
}
|
||||
|
||||
std::stringstream result;
|
||||
result << response;
|
||||
|
||||
beast::error_code ec;
|
||||
stream.shutdown(ec);
|
||||
// IGNORING ec
|
||||
|
||||
std::string debug_response_str;
|
||||
std::getline(result, debug_response_str);
|
||||
|
||||
return std::string(response.body());
|
||||
|
||||
} catch (const std::exception& e) {
|
||||
Application::Console().Write(__func__ + std::string(": ") + e.what());
|
||||
Sentry.AddErrorBreadcrumb(e.what(), __FILE__, std::to_string(__LINE__)); // FIXME: this is ugly.
|
||||
return res->body;
|
||||
} else {
|
||||
return Http::ErrorString;
|
||||
}
|
||||
}
|
||||
|
||||
std::string Http::GET(const std::string& host, int port, const std::string& target, unsigned int* status) {
|
||||
return GenericRequest(http::verb::get, host, port, target, {}, {}, "", status);
|
||||
}
|
||||
|
||||
std::string Http::POST(const std::string& host, int port, const std::string& target, const std::unordered_map<std::string, std::string>& fields, const std::string& body, const std::string& ContentType, unsigned int* status) {
|
||||
return GenericRequest(http::verb::post, host, port, target, fields, body, ContentType, status);
|
||||
std::string Http::POST(const std::string& host, int port, const std::string& target, const std::string& body, const std::string& ContentType, unsigned int* status) {
|
||||
httplib::SSLClient client(host, port);
|
||||
client.enable_server_certificate_verification(false);
|
||||
auto res = client.Post(target.c_str(), body.c_str(), body.size(), ContentType.c_str());
|
||||
if (res) {
|
||||
if (status) {
|
||||
*status = res->status;
|
||||
}
|
||||
return res->body;
|
||||
} else {
|
||||
return Http::ErrorString;
|
||||
}
|
||||
}
|
||||
|
||||
// RFC 2616, RFC 7231
|
||||
|
@ -48,17 +48,17 @@ void THeartbeatThread::operator()() {
|
||||
|
||||
auto Target = "/heartbeat";
|
||||
unsigned int ResponseCode = 0;
|
||||
T = Http::POST(Application::GetBackendHostname(), 443, Target, {}, Body, "application/x-www-form-urlencoded", &ResponseCode);
|
||||
T = Http::POST(Application::GetBackendHostname(), 443, Target, Body, "application/x-www-form-urlencoded", &ResponseCode);
|
||||
|
||||
if ((T.substr(0, 2) != "20" && ResponseCode != 200) || ResponseCode != 200) {
|
||||
beammp_trace("got " + T + " from backend");
|
||||
SentryReportError(Application::GetBackendHostname() + Target, ResponseCode);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
T = Http::POST(Application::GetBackup1Hostname(), 443, Target, {}, Body, "application/x-www-form-urlencoded", &ResponseCode);
|
||||
T = Http::POST(Application::GetBackup1Hostname(), 443, Target, Body, "application/x-www-form-urlencoded", &ResponseCode);
|
||||
if ((T.substr(0, 2) != "20" && ResponseCode != 200) || ResponseCode != 200) {
|
||||
SentryReportError(Application::GetBackup1Hostname() + Target, ResponseCode);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
T = Http::POST(Application::GetBackup2Hostname(), 443, Target, {}, Body, "application/x-www-form-urlencoded", &ResponseCode);
|
||||
T = Http::POST(Application::GetBackup2Hostname(), 443, Target, Body, "application/x-www-form-urlencoded", &ResponseCode);
|
||||
if ((T.substr(0, 2) != "20" && ResponseCode != 200) || ResponseCode != 200) {
|
||||
beammp_warn("Backend system refused server! Server will not show in the public server list.");
|
||||
|
||||
|
@ -446,16 +446,9 @@ TLuaEngine::StateThreadData::StateThreadData(const std::string& Name, std::atomi
|
||||
mEngine->CancelEventTimers(EventName, mStateId);
|
||||
});
|
||||
MPTable.set_function("Set", &LuaAPI::MP::Set);
|
||||
MPTable.set_function("HttpsGET", [&](const std::string& Host, int Port, const std::string& Target) -> std::tuple<int, std::string> {
|
||||
unsigned Status;
|
||||
auto Body = Http::GET(Host, Port, Target, &Status);
|
||||
return { Status, Body };
|
||||
});
|
||||
MPTable.set_function("HttpsPOST", [&](const std::string& Host, int Port, const std::string& Target, const std::string& Body, const std::string& ContentType) -> std::tuple<int, std::string> {
|
||||
unsigned Status;
|
||||
auto ResponseBody = Http::POST(Host, Port, Target, {}, Body, ContentType, &Status);
|
||||
return { Status, ResponseBody };
|
||||
});
|
||||
auto HttpTable = StateView.create_named_table("Http");
|
||||
//HttpTable.set_function("CreateConnection", &LuaAPI::Http::CreateConnection);
|
||||
|
||||
MPTable.create_named("Settings",
|
||||
"Debug", 0,
|
||||
"Private", 1,
|
||||
|
@ -241,7 +241,7 @@ void TNetwork::Authentication(const TConnection& ClientConnection) {
|
||||
auto Target = "/pkToUser";
|
||||
unsigned int ResponseCode = 0;
|
||||
if (!Rc.empty()) {
|
||||
Rc = Http::POST(Application::GetBackendUrlForAuth(), 443, Target, {}, RequestString, "application/json", &ResponseCode);
|
||||
Rc = Http::POST(Application::GetBackendUrlForAuth(), 443, Target, RequestString, "application/json", &ResponseCode);
|
||||
}
|
||||
|
||||
json::Document AuthResponse;
|
||||
|
Loading…
x
Reference in New Issue
Block a user