From a3fcea242ae7d76397ffd26e38a242288e178ab3 Mon Sep 17 00:00:00 2001 From: Checkraze <71046427+Cheackraze@users.noreply.github.com> Date: Mon, 3 Jun 2024 17:32:14 -0400 Subject: [PATCH] cleanup --- Content.Server/Administration/ServerApi.cs | 2 +- .../Connection/ConnectionManager.cs | 3 ++ Content.Server/_NF/Auth/Auth.cs | 48 ++++++++++--------- 3 files changed, 29 insertions(+), 24 deletions(-) diff --git a/Content.Server/Administration/ServerApi.cs b/Content.Server/Administration/ServerApi.cs index ae9cf27d6b7..2f7bcbe48e2 100644 --- a/Content.Server/Administration/ServerApi.cs +++ b/Content.Server/Administration/ServerApi.cs @@ -666,7 +666,7 @@ private enum ErrorCode /// /// Record used to send the response for the info endpoint. /// - public sealed class InfoResponse //frontier - public to maybe reuse + private sealed class InfoResponse { public required int RoundId { get; init; } public required List Players { get; init; } diff --git a/Content.Server/Connection/ConnectionManager.cs b/Content.Server/Connection/ConnectionManager.cs index 05e32a7fa74..e14f5106512 100644 --- a/Content.Server/Connection/ConnectionManager.cs +++ b/Content.Server/Connection/ConnectionManager.cs @@ -234,6 +234,9 @@ private async Task NetMgrOnConnecting(NetConnectingArgs e) } //Frontier + //This is our little chunk that serves as a dAuth. It takes in a comma seperated list of IP:PORT, and chekcs + //the requesting player against the list of players logged in to other servers. It is intended to be failsafe. + //In the case of Admins, it shares the same bypass setting as the soft_max_player_limit if (!_cfg.GetCVar(CCVars.AllowMultiConnect) && !adminBypass) { var serverListString = _cfg.GetCVar(CCVars.ServerAuthList); diff --git a/Content.Server/_NF/Auth/Auth.cs b/Content.Server/_NF/Auth/Auth.cs index 21e04940160..6bb26df02bb 100644 --- a/Content.Server/_NF/Auth/Auth.cs +++ b/Content.Server/_NF/Auth/Auth.cs @@ -1,15 +1,12 @@ -using System.Collections.Immutable; using System.Net; using System.Threading; using System.Threading.Tasks; using System.Net.Http; using System.Net.Http.Json; -//using System.IO; using System.Net.Http.Headers; -using System.Text.Json; using Content.Shared.CCVar; -using JetBrains.Annotations; using Robust.Shared.Configuration; +using JetBrains.Annotations; namespace Content.Server._NF.Auth; @@ -19,20 +16,22 @@ public sealed class MiniAuthManager private readonly HttpClient _http = new(); private readonly ISawmill _sawmill = default!; + /// + /// Frontier function to ping a server and check to see if the given player is currently connected to the given server. + /// Servers using this function must share an admin_api token as defined in their respective server_config.toml + /// + /// The address of the server to ping. + /// the GUID of the player to check for connection. + /// True if the response from the server is successful and the player is connected. False in any case of error, timeout, or failure. public async Task IsPlayerConnected(string address, Guid player) { var connected = false; var statusAddress = "http://" + address + "/admin/info"; var cancel = new CancellationToken(); - var linkedToken = CancellationTokenSource.CreateLinkedTokenSource(cancel); linkedToken.CancelAfter(TimeSpan.FromSeconds(10)); - var actor = new Actor() - { - Guid = player, - Name = player.ToString() - }; + _http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("SS14Token", _cfg.GetCVar(CCVars.AdminApiToken)); using var response = await _http.GetAsync(statusAddress, linkedToken.Token); @@ -41,25 +40,35 @@ public async Task IsPlayerConnected(string address, Guid player) if (response.IsSuccessStatusCode) { - var status = await response.Content.ReadFromJsonAsync(linkedToken.Token); - foreach (var connectedPlayer in status!.Players) + //We need to do a try catch here because theres essentially no way to guarantee our json response is proper. + //Throughout all of this, we want it to fail to deny, not fail to allow, so if any step of our auth goes wrong, + //people can still connect. + try { - if (connectedPlayer.UserId == player) - connected = true; + var status = await response.Content.ReadFromJsonAsync(linkedToken.Token); + foreach (var connectedPlayer in status!.Players) + { + if (connectedPlayer.UserId == player) + connected = true; + } + } + catch (Exception) + { + _sawmill.Error("Bad data received from auth server", response.StatusCode); } } else { _sawmill.Error("Auth server returned bad response {StatusCode}!", response.StatusCode); } - //var status = await _http.GetFromJsonAsync(statusAddress, linkedToken.Token); return connected; } /// /// Record used to send the response for the info endpoint. + /// Frontier - This is a direct copy of ServerAPI.InfoResponse to match the json format. they kept it private so i just copied it /// [UsedImplicitly] - private sealed record InfoResponse //frontier - public to maybe reuse + private sealed record InfoResponse { public required int RoundId { get; init; } public required List Players { get; init; } @@ -83,11 +92,4 @@ public sealed class MapInfo public required string Name { get; init; } } } - - private sealed class Actor - { - public required Guid Guid { get; init; } - public required string Name { get; init; } - } - }