mirror of
https://github.com/Dingo-Shenanigans/ReSkate.git
synced 2026-10-17 23:17:06 +02:00
Server browser - Official servers (the backend's "official_servers") sort first and are drawn in ReSkate blue - Servers Steam friends are skating in sort next, drawn in green with the friends' names; searching a friend's name finds their server - A player in a session they joined can join another server straight from the list; hosts still end their session first, and a Steam friend's join offer never replaces a session - Joining a dedicated server from the list records it as the player's public session, so friends see it and the row shows HERE - Blocked servers (the backend's "blocked_servers") are hidden and cannot be joined, by code either - When the backend sets "server_tokens_required", dedicated servers that signed in without a login token are hidden, except on the player's own network - A search that gets no internet list from Steam keeps the last list for two minutes, and waits six seconds before treating it as empty Roles - New Staff tag from the backend's "staff" list: green name, badge and item animation, ranked after Dev - Staff can pick a rainbow for their items on the Special page; it is sent as a solid colour older builds can show, so the protocol is unchanged Dedicated server - steam_token: sign in with a Steam game server login token and keep the same Steam ID every start; empty signs in anonymously as before - A listed server without a token says so at startup, and when the token rule starts or stops hiding it - Linux servers update themselves from the release's "server_linux" tarball, with the machine's curl and tar, pinned by SHA-256, and carry on in the same process Launcher - Only create the MiniDumpWriteDump API-set shim under Wine/Proton
71 lines
4.6 KiB
C++
71 lines
4.6 KiB
C++
// What the Linux server's self-update accepts from a release: launcher.json's "server_linux"
|
|
// entry, and the list of files in the tarball.
|
|
#include "Server/server_release.h"
|
|
#include <iostream>
|
|
#include <stdexcept>
|
|
|
|
namespace {
|
|
int failures{};
|
|
void check(bool ok, const char *what) {
|
|
if (!ok) {
|
|
std::cerr << "FAIL: " << what << '\n';
|
|
++failures;
|
|
}
|
|
}
|
|
template <class Call> bool throws(Call &&call) {
|
|
try {
|
|
call();
|
|
} catch (const std::exception &) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
} // namespace
|
|
|
|
int main() {
|
|
using namespace dingosdk::server;
|
|
const std::string sha(64, 'a'), exe(64, 'b');
|
|
const auto assets = release_assets(
|
|
R"({"tag_name":"v1.2.0","assets":[{"name":"launcher.json","browser_download_url":"https://github.com/o/r/releases/download/v1.2.0/launcher.json"},)"
|
|
R"({"name":"ReSkateServer-Linux-1.2.0.tar.gz","browser_download_url":"https://github.com/o/r/releases/download/v1.2.0/ReSkateServer-Linux-1.2.0.tar.gz"}]})");
|
|
check(assets.size() == 2 && assets.contains("launcher.json"), "A release's assets were not read");
|
|
check(throws([] { release_assets(R"({"message":"API rate limit exceeded"})"); }), "An answer that is not a release was accepted");
|
|
|
|
const auto entry = [&](std::string url, std::string hash, std::string exe_hash, std::string size, std::string version = "1.2.0") {
|
|
return R"({"schema":1,"server":{"url":"asset:ReSkateServer-1.2.0.zip"},"server_linux":{"version":")" + version + R"(","url":")" + url +
|
|
R"(","sha256":")" + hash + R"(","size":)" + size + R"(,"exe_sha256":")" + exe_hash + R"("}})";
|
|
};
|
|
const auto good = parse_linux_release(entry("asset:ReSkateServer-Linux-1.2.0.tar.gz", sha, exe, "31000000"), assets);
|
|
check(good && good->version == "1.2.0" && good->size == 31000000 && good->sha256 == sha && good->exe_sha256 == exe &&
|
|
good->url == "https://github.com/o/r/releases/download/v1.2.0/ReSkateServer-Linux-1.2.0.tar.gz",
|
|
"A Linux release was not read, or its asset was not resolved");
|
|
const auto direct = parse_linux_release(entry("https://example.com/server.tar.gz", sha, exe, "1"), {});
|
|
check(direct && direct->url == "https://example.com/server.tar.gz", "A direct HTTPS link was not kept");
|
|
// A release from before Linux servers updated themselves has no entry: nothing to do.
|
|
check(!parse_linux_release(R"({"schema":1,"server":{"url":"asset:ReSkateServer-1.1.3.zip"}})", assets), "A release with no Linux server gave one");
|
|
for (const auto &wrong : {entry("asset:missing.tar.gz", sha, exe, "1"), entry("http://example.com/s.tar.gz", sha, exe, "1"),
|
|
entry("https://example.com/s.tar.gz --output /etc/passwd", sha, exe, "1"),
|
|
entry("https://example.com/s.tar.gz", std::string(64, 'A'), exe, "1"),
|
|
entry("https://example.com/s.tar.gz", sha, "abc", "1"), entry("https://example.com/s.tar.gz", sha, exe, "0"),
|
|
entry("https://example.com/s.tar.gz", sha, exe, "999999999999"),
|
|
entry("https://example.com/s.tar.gz", sha, exe, "-5"), entry("https://example.com/s.tar.gz", sha, exe, "1", "1.2; rm"),
|
|
std::string(R"({"server_linux":"yes"})"), std::string("[]")})
|
|
check(throws([&] { parse_linux_release(wrong, assets); }), ("A wrong Linux release was accepted: " + wrong).c_str());
|
|
|
|
check(https_url("https://github.com/o/r/releases/download/v1/a.tar.gz?x=1&y=%20") && !https_url("https://") &&
|
|
!https_url("file:///etc/passwd") && !https_url("https://a b") && !https_url("https://a\nb") && !https_url("-o x"),
|
|
"Only plain HTTPS links may be handed to curl");
|
|
|
|
check(checked_archive_listing("ReSkateServer-Linux-1.2.0/\nReSkateServer-Linux-1.2.0/ReSkateServer\n"
|
|
"ReSkateServer-Linux-1.2.0/licenses/\nReSkateServer-Linux-1.2.0/licenses/zstd-LICENSE.txt\n") ==
|
|
"ReSkateServer-Linux-1.2.0",
|
|
"A release tarball's listing was refused");
|
|
check(checked_archive_listing("./pkg/\r\n./pkg/ReSkateServer\r\n") == "pkg", "A listing written with ./ was refused");
|
|
for (const char *wrong : {"", "pkg/\n", "pkg/ReSkateServer\nother/file\n", "pkg/a\n/etc/passwd\n", "pkg/a\npkg/../../etc/passwd\n",
|
|
"pkg/a\npkg//b\n", "pkg/a\npkg\\b\n", "../a\n../b\n", "pkg/a\n./\n"})
|
|
check(throws([&] { checked_archive_listing(wrong); }), "A tarball that is not one plain folder was accepted");
|
|
|
|
if (!failures) std::cout << "server release: ok\n";
|
|
return failures ? 1 : 0;
|
|
}
|