Files
ReSkate/Server/global_bans.cpp
T
AyeZeeBB 101e1af6e4 Official, staff and friends in the server browser; server tokens; Linux self-update
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
2026-10-07 00:19:56 -05:00

75 lines
2.8 KiB
C++

#include "global_bans.h"
#include "Extension/Multiplayer/developer_identity.h"
#ifdef _WIN32
#include "Engine/Vfs/https_download.h"
#else
#include <cstdio>
#endif
#include <algorithm>
#include <optional>
#include <stdexcept>
#include <vector>
namespace dingosdk::server {
namespace {
constexpr std::size_t max_bytes = 256 * 1024;
#ifdef _WIN32
std::string download() {
const auto url = multiplayer::identity_lists_url;
https::Download result;
auto answer = https::get_text(std::wstring(url.begin(), url.end()), max_bytes, 15, L"ReSkateServer/1", &result);
if (!answer) throw std::runtime_error("HTTP " + std::to_string(result.http_status) + ", error " + std::to_string(result.error));
return std::move(*answer);
}
#else
// curl does the TLS: the Linux server has no HTTPS client of its own (server_update.cpp).
// The command is fixed text, with nothing from a player or the config in it.
std::string download() {
const auto command = "curl --silent --show-error --fail --max-time 15 --max-filesize " + std::to_string(max_bytes) +
" --proto =https --user-agent ReSkateServer/1 " + std::string(multiplayer::identity_lists_url) + " 2>&1";
auto *pipe = popen(command.c_str(), "r");
if (!pipe) throw std::runtime_error("curl could not be started");
std::string output;
char buffer[4096];
for (std::size_t count; (count = fread(buffer, 1, sizeof(buffer), pipe)) > 0;)
if (output.size() < max_bytes) output.append(buffer, count);
if (pclose(pipe) != 0) {
// curl's own words (or the shell's, when curl is not installed), on one line.
while (!output.empty() && (output.back() == '\n' || output.back() == '\r')) output.pop_back();
std::replace(output.begin(), output.end(), '\n', ' ');
throw std::runtime_error(output.empty() ? "curl failed" : output);
}
return output;
}
#endif
} // namespace
BanListCheck use_ban_list(std::string_view answer) {
static std::optional<std::vector<std::uint64_t>> last;
BanListCheck check;
try {
auto lists = multiplayer::parse_identity_lists(answer);
multiplayer::server_tokens_rule = multiplayer::parse_server_tokens_required(answer);
const auto &bans = lists[static_cast<std::size_t>(multiplayer::IdentityList::banned)];
check.banned = bans.size();
check.changed = last != bans;
last = bans;
multiplayer::publish_identity_lists(std::move(lists));
check.ok = true;
} catch (const std::exception &e) {
check.problem = std::string("the answer was not the lists: ") + e.what();
}
return check;
}
BanListCheck read_global_bans() {
try {
return use_ban_list(download());
} catch (const std::exception &e) {
BanListCheck check;
check.problem = e.what();
return check;
}
}
} // namespace dingosdk::server