Update server url + motd/updater cleanup
This commit is contained in:
parent
a3df8a3e22
commit
9a9bb2e196
@ -5,6 +5,7 @@
|
|||||||
#include "console.hpp"
|
#include "console.hpp"
|
||||||
#include "images.hpp"
|
#include "images.hpp"
|
||||||
#include "command.hpp"
|
#include "command.hpp"
|
||||||
|
#include "updater.hpp"
|
||||||
|
|
||||||
#include <utils/string.hpp>
|
#include <utils/string.hpp>
|
||||||
#include <utils/http.hpp>
|
#include <utils/http.hpp>
|
||||||
@ -13,15 +14,14 @@
|
|||||||
#include <utils/io.hpp>
|
#include <utils/io.hpp>
|
||||||
#include <utils/cryptography.hpp>
|
#include <utils/cryptography.hpp>
|
||||||
|
|
||||||
#define MAX_FEATURED_TABS 8
|
|
||||||
|
|
||||||
#define CACHE_MAX_AGE 24h * 5
|
|
||||||
#define CACHE_FILE_SIGNATURE 'CM2H' // H2MC (H2-MOD Cache)
|
|
||||||
|
|
||||||
namespace motd
|
namespace motd
|
||||||
{
|
{
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
constexpr auto max_featured_tabs = 8;
|
||||||
|
constexpr auto cache_max_age = 24h * 5; // 5 days
|
||||||
|
constexpr auto cache_file_signature = 'CM2H'; // H2MC (H2-MOD Cache);
|
||||||
|
|
||||||
utils::concurrency::container<links_map_t> links;
|
utils::concurrency::container<links_map_t> links;
|
||||||
utils::concurrency::container<nlohmann::json, std::recursive_mutex> marketing;
|
utils::concurrency::container<nlohmann::json, std::recursive_mutex> marketing;
|
||||||
|
|
||||||
@ -31,6 +31,12 @@ namespace motd
|
|||||||
time_t date_created;
|
time_t date_created;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct parsed_cache_file
|
||||||
|
{
|
||||||
|
cached_file_header header{};
|
||||||
|
std::string data;
|
||||||
|
};
|
||||||
|
|
||||||
std::filesystem::path get_cache_folder()
|
std::filesystem::path get_cache_folder()
|
||||||
{
|
{
|
||||||
return utils::properties::get_appdata_path() / "cache";
|
return utils::properties::get_appdata_path() / "cache";
|
||||||
@ -45,10 +51,10 @@ namespace motd
|
|||||||
void cache_file(const std::string& name, const std::string& data)
|
void cache_file(const std::string& name, const std::string& data)
|
||||||
{
|
{
|
||||||
std::string buffer;
|
std::string buffer;
|
||||||
auto now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
|
const auto now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
|
||||||
|
|
||||||
cached_file_header header{};
|
cached_file_header header{};
|
||||||
header.signature = CACHE_FILE_SIGNATURE;
|
header.signature = cache_file_signature;
|
||||||
header.date_created = now;
|
header.date_created = now;
|
||||||
|
|
||||||
buffer.append(reinterpret_cast<char*>(&header), sizeof(header));
|
buffer.append(reinterpret_cast<char*>(&header), sizeof(header));
|
||||||
@ -58,6 +64,42 @@ namespace motd
|
|||||||
utils::io::write_file(path, buffer, false);
|
utils::io::write_file(path, buffer, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<cached_file_header> parse_cached_file_header(std::string& data)
|
||||||
|
{
|
||||||
|
if (data.size() < sizeof(cached_file_header))
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto buffer = data.data();
|
||||||
|
const auto header = reinterpret_cast<cached_file_header*>(buffer);
|
||||||
|
return {*header};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<parsed_cache_file> parse_cached_file(const std::string& path)
|
||||||
|
{
|
||||||
|
parsed_cache_file parsed{};
|
||||||
|
|
||||||
|
auto data = utils::io::read_file(path);
|
||||||
|
const auto header = parse_cached_file_header(data);
|
||||||
|
|
||||||
|
if (!header.has_value())
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (header->signature != cache_file_signature)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto file_data = data.data() + sizeof(cached_file_header);
|
||||||
|
parsed.header = *header;
|
||||||
|
parsed.data = std::string{file_data, data.size() - sizeof(cached_file_header)};
|
||||||
|
|
||||||
|
return {parsed};
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<std::string> read_cached_file(const std::string& name)
|
std::optional<std::string> read_cached_file(const std::string& name)
|
||||||
{
|
{
|
||||||
const auto path = get_cached_file_name(name);
|
const auto path = get_cached_file_name(name);
|
||||||
@ -66,29 +108,41 @@ namespace motd
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto now = std::chrono::system_clock::now();
|
const auto parsed = parse_cached_file(path);
|
||||||
auto data = utils::io::read_file(path);
|
if (!parsed.has_value())
|
||||||
if (data.size() < sizeof(cached_file_header))
|
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto buffer = data.data();
|
return {parsed->data};
|
||||||
const auto header = reinterpret_cast<cached_file_header*>(buffer);
|
|
||||||
if (header->signature != CACHE_FILE_SIGNATURE)
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void delete_old_files()
|
||||||
|
{
|
||||||
|
const auto path = get_cache_folder().generic_string();
|
||||||
|
if (!utils::io::directory_exists(path))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto now = std::chrono::system_clock::now();
|
||||||
|
const auto files = utils::io::list_files(path);
|
||||||
|
|
||||||
|
for (const auto& file : files)
|
||||||
|
{
|
||||||
|
std::string data{};
|
||||||
|
if (!utils::io::read_file(file, &data))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto header = parse_cached_file_header(data);
|
||||||
const auto date = std::chrono::system_clock::from_time_t(header->date_created);
|
const auto date = std::chrono::system_clock::from_time_t(header->date_created);
|
||||||
if (now - date >= CACHE_MAX_AGE)
|
if (now - date >= cache_max_age)
|
||||||
{
|
{
|
||||||
utils::io::remove_file(path);
|
utils::io::remove_file(file);
|
||||||
return {};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto file_data = buffer + sizeof(cached_file_header);
|
|
||||||
return std::string{file_data, data.size() - sizeof(cached_file_header)};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::string> download_image(const std::string& url)
|
std::optional<std::string> download_image(const std::string& url)
|
||||||
@ -99,6 +153,8 @@ namespace motd
|
|||||||
return {cached.value()};
|
return {cached.value()};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console::debug("[HTTP] GET File \"%s\"\n", url.data());
|
||||||
|
|
||||||
const auto res = utils::http::get_data(url);
|
const auto res = utils::http::get_data(url);
|
||||||
if (res.has_value())
|
if (res.has_value())
|
||||||
{
|
{
|
||||||
@ -120,7 +176,6 @@ namespace motd
|
|||||||
if (image_data.has_value())
|
if (image_data.has_value())
|
||||||
{
|
{
|
||||||
const auto& image = image_data.value();
|
const auto& image = image_data.value();
|
||||||
console::debug("Downloaded motd image\n");
|
|
||||||
images::override_texture("motd_image", image);
|
images::override_texture("motd_image", image);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -136,7 +191,7 @@ namespace motd
|
|||||||
for (const auto& [key, tab] : data["featured"].items())
|
for (const auto& [key, tab] : data["featured"].items())
|
||||||
{
|
{
|
||||||
index++;
|
index++;
|
||||||
if (index >= MAX_FEATURED_TABS + 1)
|
if (index >= max_featured_tabs + 1)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -153,7 +208,6 @@ namespace motd
|
|||||||
if (image_data.has_value())
|
if (image_data.has_value())
|
||||||
{
|
{
|
||||||
const auto& image = image_data.value();
|
const auto& image = image_data.value();
|
||||||
console::debug("Downloaded featured tab image %i\n", index);
|
|
||||||
images::override_texture(std::format("{}_{}", image_name, index), image);
|
images::override_texture(std::format("{}_{}", image_name, index), image);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -216,6 +270,8 @@ namespace motd
|
|||||||
|
|
||||||
void init(bool load_images = true)
|
void init(bool load_images = true)
|
||||||
{
|
{
|
||||||
|
delete_old_files();
|
||||||
|
|
||||||
links.access([](links_map_t& map)
|
links.access([](links_map_t& map)
|
||||||
{
|
{
|
||||||
init_links(map);
|
init_links(map);
|
||||||
@ -225,7 +281,7 @@ namespace motd
|
|||||||
{
|
{
|
||||||
data.clear();
|
data.clear();
|
||||||
|
|
||||||
const auto marketing_data = utils::http::get_data("https://master.fed0001.xyz/h2-mod/marketing.json");
|
const auto marketing_data = updater::get_server_file("h2-mod/marketing.json");
|
||||||
if (marketing_data.has_value())
|
if (marketing_data.has_value())
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -266,7 +322,7 @@ namespace motd
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::min(MAX_FEATURED_TABS, static_cast<int>(data["featured"].size()));
|
return std::min(max_featured_tabs, static_cast<int>(data["featured"].size()));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,12 +70,6 @@ namespace updater
|
|||||||
std::vector<std::string> garbage_files{};
|
std::vector<std::string> garbage_files{};
|
||||||
};
|
};
|
||||||
|
|
||||||
// remove this at some point
|
|
||||||
std::vector<std::string> old_data_files =
|
|
||||||
{
|
|
||||||
{"./cdata"},
|
|
||||||
};
|
|
||||||
|
|
||||||
utils::concurrency::container<update_data_t> update_data;
|
utils::concurrency::container<update_data_t> update_data;
|
||||||
|
|
||||||
std::string select(const std::string& main, const std::string& develop)
|
std::string select(const std::string& main, const std::string& develop)
|
||||||
@ -165,31 +159,16 @@ namespace updater
|
|||||||
return utils::string::va("%i", uint32_t(time(nullptr)));
|
return utils::string::va("%i", uint32_t(time(nullptr)));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::string> download_file(const std::string& name)
|
std::optional<std::string> download_data_file(const std::string& name)
|
||||||
{
|
{
|
||||||
return utils::http::get_data(MASTER + select(DATA_PATH, DATA_PATH_DEV) + name + "?" + get_time_str());
|
const auto file = std::format("{}{}?{}", select(DATA_PATH, DATA_PATH_DEV), name, get_time_str());
|
||||||
|
return updater::get_server_file(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool has_old_data_files()
|
std::optional<std::string> download_file_list()
|
||||||
{
|
{
|
||||||
bool has = false;
|
const auto file = std::format("{}?{}", select(FILES_PATH, FILES_PATH_DEV), get_time_str());
|
||||||
for (const auto& file : old_data_files)
|
return updater::get_server_file(file);
|
||||||
{
|
|
||||||
if (utils::io::directory_exists(file))
|
|
||||||
{
|
|
||||||
has = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return has;
|
|
||||||
}
|
|
||||||
|
|
||||||
void delete_old_data_files()
|
|
||||||
{
|
|
||||||
for (const auto& file : old_data_files)
|
|
||||||
{
|
|
||||||
std::filesystem::remove_all(file);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_update_cancelled()
|
bool is_update_cancelled()
|
||||||
@ -285,6 +264,34 @@ namespace updater
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<std::string> get_server_file(const std::string& endpoint)
|
||||||
|
{
|
||||||
|
static std::vector<std::string> server_urls =
|
||||||
|
{
|
||||||
|
{"https://h2-mod.fed.cat/"},
|
||||||
|
{"https://master.fed0001.xyz/"}, // remove this at some point
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto try_url = [&](const std::string& base_url)
|
||||||
|
{
|
||||||
|
const auto url = base_url + endpoint;
|
||||||
|
console::debug("[HTTP] GET file \"%s\"\n", url.data());
|
||||||
|
const auto result = utils::http::get_data(url);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const auto& url : server_urls)
|
||||||
|
{
|
||||||
|
const auto result = try_url(url);
|
||||||
|
if (result.has_value())
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
void relaunch()
|
void relaunch()
|
||||||
{
|
{
|
||||||
utils::nt::relaunch_self("-singleplayer");
|
utils::nt::relaunch_self("-singleplayer");
|
||||||
@ -342,7 +349,7 @@ namespace updater
|
|||||||
{
|
{
|
||||||
return update_data.access<bool>([](update_data_t& data_)
|
return update_data.access<bool>([](update_data_t& data_)
|
||||||
{
|
{
|
||||||
return data_.required_files.size() > 0 || data_.garbage_files.size() > 0 || has_old_data_files();
|
return data_.required_files.size() > 0 || data_.garbage_files.size() > 0;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -393,7 +400,7 @@ namespace updater
|
|||||||
|
|
||||||
scheduler::once([]()
|
scheduler::once([]()
|
||||||
{
|
{
|
||||||
const auto files_data = utils::http::get_data(MASTER + select(FILES_PATH, FILES_PATH_DEV) + "?" + get_time_str());
|
const auto files_data = download_file_list();
|
||||||
|
|
||||||
if (is_update_cancelled())
|
if (is_update_cancelled())
|
||||||
{
|
{
|
||||||
@ -484,8 +491,6 @@ namespace updater
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete_old_data_files();
|
|
||||||
|
|
||||||
const auto garbage_files = update_data.access<std::vector<std::string>>([](update_data_t& data_)
|
const auto garbage_files = update_data.access<std::vector<std::string>>([](update_data_t& data_)
|
||||||
{
|
{
|
||||||
return data_.garbage_files;
|
return data_.garbage_files;
|
||||||
@ -531,7 +536,7 @@ namespace updater
|
|||||||
console::info("[Updater] downloading file %s\n", file.name.data());
|
console::info("[Updater] downloading file %s\n", file.name.data());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const auto data = download_file(file.name);
|
const auto data = download_data_file(file.name);
|
||||||
|
|
||||||
if (is_update_cancelled())
|
if (is_update_cancelled())
|
||||||
{
|
{
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
namespace updater
|
namespace updater
|
||||||
{
|
{
|
||||||
|
std::optional<std::string> get_server_file(const std::string& endpoint);
|
||||||
|
|
||||||
void relaunch();
|
void relaunch();
|
||||||
|
|
||||||
void set_has_tried_update(bool tried);
|
void set_has_tried_update(bool tried);
|
||||||
|
@ -125,10 +125,10 @@ FARPROC load_binary(const launcher::mode mode)
|
|||||||
return loader.load(self, data);
|
return loader.load(self, data);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove_crash_file()
|
void remove_crash_file()
|
||||||
{
|
{
|
||||||
utils::io::remove_file("__h2Exe");
|
utils::io::remove_file("__h2Exe");
|
||||||
utils::io::remove_file("h2_sp_patched.exe"); // remove this at some point
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void verify_version()
|
void verify_version()
|
||||||
|
Loading…
Reference in New Issue
Block a user