mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2025-07-04 00:36:14 +00:00
implement SSL POST
This commit is contained in:
parent
c75acbff76
commit
f6121704df
@ -25,13 +25,13 @@ endif ()
|
|||||||
file(GLOB source_files "src/*.cpp" "include/*.h" "include/*/*.h" "include/*/*/*.h" "include/*.hpp" "include/*/*.hpp" "src/*/*.cpp")
|
file(GLOB source_files "src/*.cpp" "include/*.h" "include/*/*.h" "include/*/*/*.h" "include/*.hpp" "include/*/*.hpp" "src/*/*.cpp")
|
||||||
add_executable(BeamMP-Server ${source_files})
|
add_executable(BeamMP-Server ${source_files})
|
||||||
|
|
||||||
target_include_directories(BeamMP-Server PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> cpp-httplib)
|
target_include_directories(BeamMP-Server PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
|
||||||
|
|
||||||
find_package(Lua REQUIRED)
|
find_package(Lua REQUIRED)
|
||||||
target_include_directories(BeamMP-Server PUBLIC ${LUA_INCLUDE_DIR})
|
target_include_directories(BeamMP-Server PUBLIC ${LUA_INCLUDE_DIR})
|
||||||
|
|
||||||
if (UNIX)
|
if (UNIX)
|
||||||
target_link_libraries(BeamMP-Server z pthread stdc++fs ${Boost_LINK_DIRS} ${LUA_LIBRARIES} curl dl)
|
target_link_libraries(BeamMP-Server z pthread stdc++fs ${Boost_LINK_DIRS} ${LUA_LIBRARIES} curl dl crypto ssl)
|
||||||
elseif (WIN32)
|
elseif (WIN32)
|
||||||
include(FindLua)
|
include(FindLua)
|
||||||
find_package(ZLIB REQUIRED)
|
find_package(ZLIB REQUIRED)
|
||||||
|
@ -7,5 +7,6 @@
|
|||||||
///
|
///
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
std::string HttpRequest(const std::string& host, int port, const std::string& target);
|
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);
|
std::string PostHTTP(const std::string& host, const std::string& target, const std::unordered_map<std::string, std::string>& fields, const std::string& body, bool json);
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include <future>
|
#include <future>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
void WebsocketInit();
|
void WebsocketInit();
|
||||||
std::string GetPlayers() {
|
std::string GetPlayers() {
|
||||||
@ -24,20 +25,25 @@ std::string GetPlayers() {
|
|||||||
}
|
}
|
||||||
return Return;
|
return Return;
|
||||||
}
|
}
|
||||||
std::string GenerateCall() {
|
std::unordered_map<std::string, std::string> GenerateCall() {
|
||||||
std::stringstream Ret;
|
return { { "uuid", Key },
|
||||||
Ret << "uuid=" << Key << "&players=" << CI->Size()
|
{ "players", std::to_string(CI->Size()) },
|
||||||
<< "&maxplayers=" << MaxPlayers << "&port=" << Port
|
{ "maxplayers", std::to_string(MaxPlayers) },
|
||||||
<< "&map=" << MapName << "&private=" << (Private ? "true" : "false")
|
{ "port", std::to_string(Port) },
|
||||||
<< "&version=" << GetSVer() << "&clientversion=" << GetCVer()
|
{ "map", MapName },
|
||||||
<< "&name=" << ServerName << "&pps=" << StatReport
|
{ "private", (Private ? "true" : "false") },
|
||||||
<< "&modlist=" << FileList << "&modstotalsize=" << MaxModSize
|
{ "version", GetSVer() },
|
||||||
<< "&modstotal=" << ModsLoaded << "&playerslist=" << GetPlayers()
|
{ "clientversion", GetCVer() },
|
||||||
<< "&desc=" << ServerDesc;
|
{ "name", ServerName },
|
||||||
return Ret.str();
|
{ "pps", StatReport },
|
||||||
|
{ "modlist", FileList },
|
||||||
|
{ "modstotalsize", std::to_string(MaxModSize) },
|
||||||
|
{ "modstotal", std::to_string(ModsLoaded) },
|
||||||
|
{ "playerslist", GetPlayers() },
|
||||||
|
{ "desc", ServerDesc } };
|
||||||
}
|
}
|
||||||
std::string RunPromise(const std::string& host, const std::string& target, const std::string& R) {
|
std::string RunPromise(const std::string& host, const std::string& target, const std::unordered_map<std::string, std::string>& R) {
|
||||||
std::packaged_task<std::string()> task([&] { return PostHTTP(host, 443, target, R, false); });
|
std::packaged_task<std::string()> task([&] { return PostHTTP(host, target, R, "", false); });
|
||||||
std::future<std::string> f1 = task.get_future();
|
std::future<std::string> f1 = task.get_future();
|
||||||
std::thread t(std::move(task));
|
std::thread t(std::move(task));
|
||||||
t.detach();
|
t.detach();
|
||||||
@ -50,12 +56,13 @@ std::string RunPromise(const std::string& host, const std::string& target, const
|
|||||||
|
|
||||||
[[noreturn]] void Heartbeat() {
|
[[noreturn]] void Heartbeat() {
|
||||||
DebugPrintTID();
|
DebugPrintTID();
|
||||||
std::string R, T;
|
std::unordered_map<std::string, std::string> R;
|
||||||
|
std::string T;
|
||||||
bool isAuth = false;
|
bool isAuth = false;
|
||||||
while (true) {
|
while (true) {
|
||||||
R = GenerateCall();
|
R = GenerateCall();
|
||||||
if (!CustomIP.empty())
|
if (!CustomIP.empty())
|
||||||
R += "&ip=" + CustomIP;
|
R.insert({ "ip", CustomIP });
|
||||||
T = RunPromise("beammp.com", "/heartbeatv2", R);
|
T = RunPromise("beammp.com", "/heartbeatv2", R);
|
||||||
|
|
||||||
if (T.substr(0, 2) != "20") {
|
if (T.substr(0, 2) != "20") {
|
||||||
@ -69,8 +76,10 @@ std::string RunPromise(const std::string& host, const std::string& target, const
|
|||||||
//Server Authenticated
|
//Server Authenticated
|
||||||
if (!isAuth) {
|
if (!isAuth) {
|
||||||
WebsocketInit();
|
WebsocketInit();
|
||||||
if (T.length() == 4)info(("Authenticated!"));
|
if (T.length() == 4)
|
||||||
else info(("Resumed authenticated session!"));
|
info(("Authenticated!"));
|
||||||
|
else
|
||||||
|
info(("Resumed authenticated session!"));
|
||||||
isAuth = true;
|
isAuth = true;
|
||||||
}
|
}
|
||||||
//std::this_thread::sleep_for(std::chrono::seconds(5));
|
//std::this_thread::sleep_for(std::chrono::seconds(5));
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
std::string GetClientInfo(const std::string& PK) {
|
std::string GetClientInfo(const std::string& PK) {
|
||||||
if (!PK.empty()) {
|
if (!PK.empty()) {
|
||||||
return PostHTTP("auth.beammp.com", 443, "/pkToUser", R"({"key":")" + PK + "\"}", true);
|
return PostHTTP("auth.beammp.com", "/pkToUser", {}, R"({"key":")" + PK + "\"}", true);
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
@ -11,17 +11,22 @@
|
|||||||
|
|
||||||
#include <boost/asio/connect.hpp>
|
#include <boost/asio/connect.hpp>
|
||||||
#include <boost/asio/ip/tcp.hpp>
|
#include <boost/asio/ip/tcp.hpp>
|
||||||
|
#include <boost/asio/ssl/error.hpp>
|
||||||
|
#include <boost/asio/ssl/stream.hpp>
|
||||||
#include <boost/beast/core.hpp>
|
#include <boost/beast/core.hpp>
|
||||||
#include <boost/beast/http.hpp>
|
#include <boost/beast/http.hpp>
|
||||||
|
#include <boost/beast/ssl.hpp>
|
||||||
#include <boost/beast/version.hpp>
|
#include <boost/beast/version.hpp>
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace beast = boost::beast; // from <boost/beast.hpp>
|
namespace beast = boost::beast; // from <boost/beast.hpp>
|
||||||
namespace http = beast::http; // from <boost/beast/http.hpp>
|
namespace http = beast::http; // from <boost/beast/http.hpp>
|
||||||
namespace net = boost::asio; // from <boost/asio.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>
|
using tcp = net::ip::tcp; // from <boost/asio/ip/tcp.hpp>
|
||||||
|
|
||||||
// UNUSED?!
|
// UNUSED?!
|
||||||
@ -63,48 +68,69 @@ std::string HttpRequest(const std::string& host, int port, const std::string& ta
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PostHTTP(const std::string& host, int port, const std::string& target, const std::string& Fields, bool json) {
|
std::string PostHTTP(const std::string& host, const std::string& target, const std::unordered_map<std::string, std::string>& fields, const std::string& body, bool json) {
|
||||||
try {
|
//try {
|
||||||
net::io_context io;
|
net::io_context io;
|
||||||
|
|
||||||
|
// The SSL context is required, and holds certificates
|
||||||
|
ssl::context ctx(ssl::context::tlsv13_client);
|
||||||
|
|
||||||
|
ctx.set_verify_mode(ssl::verify_none);
|
||||||
|
|
||||||
tcp::resolver resolver(io);
|
tcp::resolver resolver(io);
|
||||||
beast::tcp_stream stream(io);
|
beast::ssl_stream<beast::tcp_stream> stream(io, ctx);
|
||||||
auto const results = resolver.resolve(host, std::to_string(port));
|
auto const results = resolver.resolve(host, std::to_string(443));
|
||||||
stream.connect(results);
|
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() };
|
||||||
|
throw boost::system::system_error { ec };
|
||||||
|
}
|
||||||
|
beast::get_lowest_layer(stream).connect(results);
|
||||||
|
stream.handshake(ssl::stream_base::client);
|
||||||
|
|
||||||
http::request<http::string_body> req { http::verb::post, target, 11 /* http 1.1 */ };
|
http::request<http::string_body> req { http::verb::post, target, 11 /* http 1.1 */ };
|
||||||
|
|
||||||
req.set(http::field::host, host);
|
req.set(http::field::host, host);
|
||||||
|
req.set("X-Forwarded-For", HttpRequest("api.ipify.org", 80, "/"));
|
||||||
|
if (!body.empty()) {
|
||||||
if (json) {
|
if (json) {
|
||||||
req.set(http::field::content_type, "application/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::content_length, boost::lexical_cast<std::string>(body.size()));
|
||||||
req.set(http::field::body, Fields.c_str());
|
req.set(http::field::body, body);
|
||||||
|
}
|
||||||
|
for (const auto& pair : fields) {
|
||||||
|
info("setting " + pair.first + " to " + pair.second);
|
||||||
|
req.set(pair.first, pair.second);
|
||||||
|
}
|
||||||
// tell the server what we are (boost beast)
|
// tell the server what we are (boost beast)
|
||||||
req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
|
|
||||||
req.prepare_payload();
|
req.prepare_payload();
|
||||||
|
|
||||||
stream.expires_after(std::chrono::seconds(5));
|
std::stringstream oss;
|
||||||
|
oss << req;
|
||||||
|
warn(oss.str());
|
||||||
|
|
||||||
|
beast::get_lowest_layer(stream).expires_after(std::chrono::seconds(5));
|
||||||
|
|
||||||
http::write(stream, req);
|
http::write(stream, req);
|
||||||
|
|
||||||
// used for reading
|
// used for reading
|
||||||
beast::flat_buffer buffer;
|
beast::flat_buffer buffer;
|
||||||
http::response<http::string_body> response;
|
http::response<http::dynamic_body> response;
|
||||||
|
|
||||||
http::read(stream, buffer, response);
|
http::read(stream, buffer, response);
|
||||||
|
|
||||||
std::string result(response.body());
|
std::stringstream result;
|
||||||
|
result << response;
|
||||||
|
|
||||||
beast::error_code ec;
|
beast::error_code ec;
|
||||||
stream.socket().shutdown(tcp::socket::shutdown_both, ec);
|
stream.shutdown(ec);
|
||||||
if (ec && ec != beast::errc::not_connected) {
|
// IGNORING ec
|
||||||
throw beast::system_error { ec }; // goes down to `return "-1"` anyways
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
info(result.str());
|
||||||
|
return result.str();
|
||||||
|
|
||||||
} catch (const std::exception& e) {
|
/*} catch (const std::exception& e) {
|
||||||
error(e.what());
|
error(e.what());
|
||||||
return "-1";
|
return "-1";
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user