mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2025-08-16 16:26:26 +00:00
implement mod hashing + new download
This commit is contained in:
parent
7f69e336a9
commit
a4b62d013c
@ -19,6 +19,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
class TResourceManager {
|
class TResourceManager {
|
||||||
public:
|
public:
|
||||||
@ -30,10 +31,17 @@ public:
|
|||||||
[[nodiscard]] std::string FileSizes() const { return mFileSizes; }
|
[[nodiscard]] std::string FileSizes() const { return mFileSizes; }
|
||||||
[[nodiscard]] int ModsLoaded() const { return mModsLoaded; }
|
[[nodiscard]] int ModsLoaded() const { return mModsLoaded; }
|
||||||
|
|
||||||
|
[[nodiscard]] std::string NewFileList() const;
|
||||||
|
|
||||||
|
void RefreshFiles();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_t mMaxModSize = 0;
|
size_t mMaxModSize = 0;
|
||||||
std::string mFileSizes;
|
std::string mFileSizes;
|
||||||
std::string mFileList;
|
std::string mFileList;
|
||||||
std::string mTrimmedList;
|
std::string mTrimmedList;
|
||||||
int mModsLoaded = 0;
|
int mModsLoaded = 0;
|
||||||
|
|
||||||
|
std::mutex mModsMutex;
|
||||||
|
nlohmann::json mMods;
|
||||||
};
|
};
|
||||||
|
@ -758,11 +758,11 @@ void TNetwork::Parse(TClient& c, const std::vector<uint8_t>& Packet) {
|
|||||||
case 'S':
|
case 'S':
|
||||||
if (SubCode == 'R') {
|
if (SubCode == 'R') {
|
||||||
beammp_debug("Sending Mod Info");
|
beammp_debug("Sending Mod Info");
|
||||||
std::string ToSend = mResourceManager.FileList() + mResourceManager.FileSizes();
|
std::string ToSend = mResourceManager.NewFileList();
|
||||||
if (ToSend.empty())
|
beammp_debugf("Mod Info: {}", ToSend);
|
||||||
ToSend = "-";
|
|
||||||
if (!TCPSend(c, StringToVector(ToSend))) {
|
if (!TCPSend(c, StringToVector(ToSend))) {
|
||||||
// TODO: error
|
ClientKick(c, "TCP Send 'SY' failed");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -17,9 +17,14 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#include "TResourceManager.h"
|
#include "TResourceManager.h"
|
||||||
|
#include "Common.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <fmt/core.h>
|
||||||
|
#include <ios>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
@ -52,3 +57,83 @@ TResourceManager::TResourceManager() {
|
|||||||
|
|
||||||
Application::SetSubsystemStatus("ResourceManager", Application::Status::Good);
|
Application::SetSubsystemStatus("ResourceManager", Application::Status::Good);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string TResourceManager::NewFileList() const {
|
||||||
|
return mMods.dump();
|
||||||
|
}
|
||||||
|
void TResourceManager::RefreshFiles() {
|
||||||
|
mMods.clear();
|
||||||
|
std::unique_lock Lock(mModsMutex);
|
||||||
|
|
||||||
|
std::string Path = Application::Settings.getAsString(Settings::Key::General_ResourceFolder) + "/Client";
|
||||||
|
for (const auto& entry : fs::directory_iterator(Path)) {
|
||||||
|
std::string File(entry.path().string());
|
||||||
|
|
||||||
|
if (entry.path().extension() != ".zip" || std::filesystem::is_directory(entry.path())) {
|
||||||
|
beammp_warnf("'{}' is not a ZIP file and will be ignored", File);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
EVP_MD_CTX* mdctx;
|
||||||
|
const EVP_MD* md;
|
||||||
|
uint8_t sha256_value[EVP_MAX_MD_SIZE];
|
||||||
|
md = EVP_sha256();
|
||||||
|
if (md == nullptr) {
|
||||||
|
throw std::runtime_error("EVP_sha256() failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
mdctx = EVP_MD_CTX_new();
|
||||||
|
if (mdctx == nullptr) {
|
||||||
|
throw std::runtime_error("EVP_MD_CTX_new() failed");
|
||||||
|
}
|
||||||
|
if (!EVP_DigestInit_ex2(mdctx, md, NULL)) {
|
||||||
|
EVP_MD_CTX_free(mdctx);
|
||||||
|
throw std::runtime_error("EVP_DigestInit_ex2() failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ifstream stream(File, std::ios::binary);
|
||||||
|
|
||||||
|
const size_t FileSize = std::filesystem::file_size(File);
|
||||||
|
size_t Read = 0;
|
||||||
|
std::vector<char> Data;
|
||||||
|
while (Read < FileSize) {
|
||||||
|
Data.resize(size_t(std::min<size_t>(FileSize - Read, 4096)));
|
||||||
|
size_t RealDataSize = Data.size();
|
||||||
|
stream.read(Data.data(), std::streamsize(Data.size()));
|
||||||
|
if (stream.eof() || stream.fail()) {
|
||||||
|
RealDataSize = size_t(stream.gcount());
|
||||||
|
}
|
||||||
|
Data.resize(RealDataSize);
|
||||||
|
if (RealDataSize == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (RealDataSize > 0 && !EVP_DigestUpdate(mdctx, Data.data(), Data.size())) {
|
||||||
|
EVP_MD_CTX_free(mdctx);
|
||||||
|
throw std::runtime_error("EVP_DigestUpdate() failed");
|
||||||
|
}
|
||||||
|
Read += RealDataSize;
|
||||||
|
}
|
||||||
|
unsigned int sha256_len = 0;
|
||||||
|
if (!EVP_DigestFinal_ex(mdctx, sha256_value, &sha256_len)) {
|
||||||
|
EVP_MD_CTX_free(mdctx);
|
||||||
|
throw std::runtime_error("EVP_DigestFinal_ex() failed");
|
||||||
|
}
|
||||||
|
EVP_MD_CTX_free(mdctx);
|
||||||
|
|
||||||
|
std::string result;
|
||||||
|
for (size_t i = 0; i < sha256_len; i++) {
|
||||||
|
result += fmt::format("{:02x}", sha256_value[i]);
|
||||||
|
}
|
||||||
|
beammp_debugf("sha256('{}'): {}", File, result);
|
||||||
|
mMods.push_back(nlohmann::json {
|
||||||
|
{ "file_name", File },
|
||||||
|
{ "file_size", Read },
|
||||||
|
{ "hash_algorithm", "sha256" },
|
||||||
|
{ "hash", result },
|
||||||
|
});
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
beammp_errorf("Sha256 hashing of '{}' failed: {}", File, e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -190,6 +190,7 @@ int BeamMPServerMain(MainArguments Arguments) {
|
|||||||
|
|
||||||
beammp_trace("Running in debug mode on a debug build");
|
beammp_trace("Running in debug mode on a debug build");
|
||||||
TResourceManager ResourceManager;
|
TResourceManager ResourceManager;
|
||||||
|
ResourceManager.RefreshFiles();
|
||||||
TPPSMonitor PPSMonitor(Server);
|
TPPSMonitor PPSMonitor(Server);
|
||||||
THeartbeatThread Heartbeat(ResourceManager, Server);
|
THeartbeatThread Heartbeat(ResourceManager, Server);
|
||||||
TNetwork Network(Server, PPSMonitor, ResourceManager);
|
TNetwork Network(Server, PPSMonitor, ResourceManager);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user