Skip to content

Commit

Permalink
Add public HTTP API endpoints for centralized app (#22)
Browse files Browse the repository at this point in the history
  • Loading branch information
NotBlue-Dev committed Nov 14, 2023
1 parent a9f4d5d commit 692c71c
Show file tree
Hide file tree
Showing 15 changed files with 509 additions and 14 deletions.
14 changes: 13 additions & 1 deletion EchoRelay.App/Forms/Controls/ServerInfoControl.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
using EchoRelay.Core.Server;
using EchoRelay.Core.Monitoring;
using EchoRelay.Core.Utils;
using Newtonsoft.Json;
using Server = EchoRelay.Core.Server.Server;

namespace EchoRelay.App.Forms.Controls
{
public partial class ServerInfoControl : UserControl
{
ApiManager _apiManager = ApiManager.Instance;
public ServerInfoControl()
{
InitializeComponent();
Expand Down Expand Up @@ -36,6 +38,16 @@ public void UpdateServerInfo(Server? server, bool updateServiceConfig)
rtbGeneratedServiceConfig.Text = "";
}
}


_apiManager.peerStatsObject.ServerIp = server?.PublicIPAddress?.ToString() ?? "localhost";
_apiManager.peerStatsObject.Login = server?.LoginService.Peers.Count ?? 0;
_apiManager.peerStatsObject.Matching = server?.MatchingService.Peers.Count ?? 0;
_apiManager.peerStatsObject.Config = server?.ConfigService.Peers.Count ?? 0;
_apiManager.peerStatsObject.Transaction = server?.TransactionService.Peers.Count ?? 0;
_apiManager.peerStatsObject.ServerDb = server?.ServerDBService.Peers.Count ?? 0;
Task.Run(() => _apiManager.PeerStats.EditPeerStats(_apiManager.peerStatsObject, server?.PublicIPAddress?.ToString() ?? "localhost"));

}

private void btnCopyServiceConfig_Click(object sender, EventArgs e)
Expand Down
9 changes: 9 additions & 0 deletions EchoRelay.App/Forms/MainWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
using System.Net.Sockets;
using System.Reflection;
using System.Runtime.CompilerServices;
using EchoRelay.Core.Monitoring;
using Server = EchoRelay.Core.Server.Server;

namespace EchoRelay
{
Expand All @@ -36,6 +38,8 @@ public partial class MainWindow : Form
/// The websocket server used to power central game services.
/// </summary>
public Server Server { get; set; }

public ApiManager apiManager { get; set; }

/// <summary>
/// The UI editors for different storage resources.
Expand Down Expand Up @@ -130,6 +134,8 @@ public MainWindow()
Server.ServerDBService.Registry.OnGameServerRegistered += Registry_OnGameServerRegistered;
Server.ServerDBService.Registry.OnGameServerUnregistered += Registry_OnGameServerUnregistered;
Server.ServerDBService.OnGameServerRegistrationFailure += ServerDBService_OnGameServerRegistrationFailure; ;

apiManager = ApiManager.Instance;
}
#endregion

Expand Down Expand Up @@ -360,6 +366,9 @@ private void Registry_OnGameServerRegistered(EchoRelay.Core.Server.Services.Serv
// Update server count on the game server tab.
tabGameServers.Text = $"Game Servers ({gameServersControl.GameServerCount})";
apiManager.peerStatsObject.GameServers = gameServersControl.GameServerCount;
Task.Run(() => apiManager.PeerStats.EditPeerStats(apiManager.peerStatsObject, Server.PublicIPAddress?.ToString() ?? "localhost"));
AppendLogText($"[{gameServer.Peer.Service.Name}] client({gameServer.Peer.Address}:{gameServer.Peer.Port}) registered game server (server_id={gameServer.ServerId}, region_symbol={gameServer.RegionSymbol}, version_lock={gameServer.VersionLock}, endpoint=<{gameServer.ExternalAddress}:{gameServer.Port}>)\n");
});
}
Expand Down
78 changes: 69 additions & 9 deletions EchoRelay.Cli/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
using Microsoft.AspNetCore.Components.Web;
using Newtonsoft.Json;
using System.Reflection;
using System.Runtime.InteropServices;
using EchoRelay.Core.Monitoring;
using Server = EchoRelay.Core.Server.Server;

namespace EchoRelay.Cli
{
Expand All @@ -20,11 +23,13 @@ class Program
/// <summary>
/// The instance of the server hosting central services.
/// </summary>
private static Server Server;
private static Server? Server;
/// <summary>
/// The update timer used to trigger a peer stats update on a given interval.
/// </summary>
private static System.Timers.Timer? peerStatsUpdateTimer;

private static ApiManager? apiManager;
/// <summary>
/// The time that the server was started.
/// </summary>
Expand All @@ -33,6 +38,22 @@ class Program
/// A mutex lock object to be used when printing to console, to avoid color collisions.
/// </summary>
private static object _printLock = new object();

[DllImport("Kernel32")]
private static extern bool SetConsoleCtrlHandler(EventHandler handler, bool add);

private delegate bool EventHandler(CtrlType sig);
private static EventHandler? consoleCloseHandler;

// Enum to represent different CtrlTypes
private enum CtrlType
{
CTRL_C_EVENT = 0,
CTRL_BREAK_EVENT = 1,
CTRL_CLOSE_EVENT = 2,
CTRL_LOGOFF_EVENT = 5,
CTRL_SHUTDOWN_EVENT = 6
}

/// <summary>
/// The CLI argument options for the application.
Expand Down Expand Up @@ -139,6 +160,8 @@ static void Main(string[] args)
)
);
apiManager = ApiManager.Instance;
// Set up all event handlers.
Server.OnServerStarted += Server_OnServerStarted;
Server.OnServerStopped += Server_OnServerStopped;
Expand All @@ -149,6 +172,10 @@ static void Main(string[] args)
Server.ServerDBService.Registry.OnGameServerRegistered += Registry_OnGameServerRegistered;
Server.ServerDBService.Registry.OnGameServerUnregistered += Registry_OnGameServerUnregistered;
Server.ServerDBService.OnGameServerRegistrationFailure += ServerDBService_OnGameServerRegistrationFailure;
// Set up the event handler for the console close event
consoleCloseHandler += new EventHandler(ConsoleCloseHandler);
SetConsoleCtrlHandler(consoleCloseHandler, true);
// Set up all verbose event handlers.
if (options.Verbose)
Expand Down Expand Up @@ -187,6 +214,8 @@ private static void Server_OnServerStarted(Server server)
}
}

updateServerInfo();

// Start the peer stats update timer
startedTime = DateTime.UtcNow;
peerStatsUpdateTimer = new System.Timers.Timer(Options!.StatsUpdateInterval);
Expand All @@ -197,14 +226,14 @@ private static void Server_OnServerStarted(Server server)
private static void PeerStatsUpdateTimer_Elapsed(object? sender, System.Timers.ElapsedEventArgs e)
{
Info($"[PEERSTATS] " +
$"elapsed: {(DateTime.UtcNow - startedTime)}, " +
$"gameservers: {Server.ServerDBService.Registry.RegisteredGameServers.Count}, " +
$"login: {Server.LoginService.Peers.Count}, " +
$"config: {Server.ConfigService.Peers.Count}, " +
$"matching: {Server.MatchingService.Peers.Count}, " +
$"serverdb: {Server.ServerDBService.Peers.Count}, " +
$"transaction: {Server.TransactionService.Peers.Count}"
);
$"elapsed: {(DateTime.UtcNow - startedTime)}, " +
$"gameservers: {Server.ServerDBService.Registry.RegisteredGameServers.Count}, " +
$"login: {Server.LoginService.Peers.Count}, " +
$"config: {Server.ConfigService.Peers.Count}, " +
$"matching: {Server.MatchingService.Peers.Count}, " +
$"serverdb: {Server.ServerDBService.Peers.Count}, " +
$"transaction: {Server.TransactionService.Peers.Count}"
);
}

private static void Server_OnServerStopped(Server server)
Expand All @@ -214,20 +243,36 @@ private static void Server_OnServerStopped(Server server)

// Print our server stopped message
Info("[SERVER] Server stopped");

updateServerInfo();
}

private static void Server_OnAuthorizationResult(Server server, System.Net.IPEndPoint client, bool authorized)
{
if(!authorized)
Error($"[SERVER] client({client.Address}:{client.Port}) failed authorization");
}

private static void updateServerInfo()
{
apiManager.peerStatsObject.ServerIp = Server?.PublicIPAddress?.ToString() ?? "localhost";
apiManager.peerStatsObject.Login = Server?.LoginService.Peers.Count;
apiManager.peerStatsObject.Matching = Server?.MatchingService.Peers.Count;
apiManager.peerStatsObject.Config = Server?.ConfigService.Peers.Count;
apiManager.peerStatsObject.Transaction = Server?.TransactionService.Peers.Count;
apiManager.peerStatsObject.ServerDb = Server?.ServerDBService.Peers.Count;
apiManager.peerStatsObject.GameServers = Server?.ServerDBService.Registry.RegisteredGameServers.Count;
Task.Run(() => apiManager.PeerStats.EditPeerStats(apiManager.peerStatsObject, apiManager.peerStatsObject.ServerIp));
}
private static void Server_OnServicePeerConnected(Core.Server.Services.Service service, Core.Server.Services.Peer peer)
{
Info($"[{service.Name}] client({peer.Address}:{peer.Port}) connected");
updateServerInfo();
}
private static void Server_OnServicePeerDisconnected(Core.Server.Services.Service service, Core.Server.Services.Peer peer)
{
Info($"[{service.Name}] client({peer.Address}:{peer.Port}) disconnected");
updateServerInfo();
}
private static void Server_OnServicePeerAuthenticated(Core.Server.Services.Service service, Core.Server.Services.Peer peer, Core.Game.XPlatformId userId)
{
Expand All @@ -237,11 +282,14 @@ private static void Server_OnServicePeerAuthenticated(Core.Server.Services.Servi
private static void Registry_OnGameServerRegistered(Core.Server.Services.ServerDB.RegisteredGameServer gameServer)
{
Info($"[{gameServer.Peer.Service.Name}] client({gameServer.Peer.Address}:{gameServer.Peer.Port}) registered game server (server_id={gameServer.ServerId}, region_symbol={gameServer.RegionSymbol}, version_lock={gameServer.VersionLock}, endpoint=<{gameServer.ExternalAddress}:{gameServer.Port}>)");
updateServerInfo();
}

private static void Registry_OnGameServerUnregistered(Core.Server.Services.ServerDB.RegisteredGameServer gameServer)
{
Info($"[{gameServer.Peer.Service.Name}] client({gameServer.Peer.Address}:{gameServer.Peer.Port}) unregistered game server (server_id={gameServer.ServerId}, region_symbol={gameServer.RegionSymbol}, version_lock={gameServer.VersionLock}, endpoint=<{gameServer.ExternalAddress}:{gameServer.Port}>)");
updateServerInfo();

}
private static void ServerDBService_OnGameServerRegistrationFailure(Peer peer, Core.Server.Messages.ServerDB.ERGameServerRegistrationRequest registrationRequest, string failureMessage)
{
Expand Down Expand Up @@ -310,5 +358,17 @@ private static void Debug(string msg)
Console.ResetColor();
}
}

// Handler for the console close event
private static bool ConsoleCloseHandler(CtrlType sig)
{
Console.WriteLine("Console is closing. Performing cleanup...");
Server?.Stop();

Thread.Sleep(1500);

// Allow the program to exit
return true;
}
}
}
42 changes: 42 additions & 0 deletions EchoRelay.Core/Monitoring/ApiClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System.Security.Cryptography;
using System.Text;

namespace EchoRelay.Core.Monitoring;

//TO DO : Encrypt data
public class ApiClient
{
private readonly HttpClient _httpClient;

public ApiClient(string baseUrl)
{
_httpClient = new HttpClient
{
BaseAddress = new Uri(baseUrl)
};
}

//TODO encrypt data to avoid people to send fake data
public async Task<string> PostMonitoringData(string endpoint, string data)
{
HttpContent content = new StringContent(data, Encoding.UTF8, "application/json");
HttpResponseMessage response = await _httpClient.PostAsync(endpoint, content);

if (response.IsSuccessStatusCode)
{
return await response.Content.ReadAsStringAsync();
}
throw new Exception($"API request failed with status code: {response.StatusCode}");
}

public async Task DeleteMonitoringData(string endpoint)
{
HttpResponseMessage response = await _httpClient.DeleteAsync(endpoint);

if (!response.IsSuccessStatusCode)
{
throw new Exception($"DELETE request failed with status code: {response.StatusCode}");
}
}

}
41 changes: 41 additions & 0 deletions EchoRelay.Core/Monitoring/ApiManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System.Security.Cryptography;

namespace EchoRelay.Core.Monitoring;

public class ApiManager
{

/// <summary>
/// Uri to the monitoring API
/// </summary>
public string URI { get; } = "http://localhost:3000/api/";
//public string URI { get; } = "http://51.75.140.182:3000/api/";

public PeerStatsObject peerStatsObject;
/// <summary>
/// Public key to encrypt data
/// </summary>
public ApiClient Monitoring { get; }

public Server Server { get; }

public GameServer GameServer { get; }
public PeerStats PeerStats { get; }

private static ApiManager instance = new ApiManager();

private ApiManager()
{
Monitoring = new ApiClient(URI);
GameServer = new GameServer(Monitoring);
PeerStats = new PeerStats(Monitoring);
Server = new Server(Monitoring);
peerStatsObject = new PeerStatsObject();
}

// Method to get the singleton instance
public static ApiManager Instance
{
get { return instance; }
}
}
63 changes: 63 additions & 0 deletions EchoRelay.Core/Monitoring/GameServer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using Newtonsoft.Json;

namespace EchoRelay.Core.Monitoring;

public class GameServer
{
private readonly ApiClient _apiClient;

public GameServer(ApiClient apiClient)
{
_apiClient = apiClient;
}

public async Task DeleteGameServerAsync(string sessionId)
{
// Define the endpoint for deleting a game server with the sessionID
string endpoint = $"deleteGameServer/{sessionId}";

try
{
await _apiClient.DeleteMonitoringData(endpoint);
Console.WriteLine($"Game server with session ID {sessionId} deleted successfully from monitoring.");
}
catch (Exception ex)
{
Console.WriteLine($"Error deleting the game server from monitoring: {ex.Message}");
}
}

public async Task AddGameServerAsync(GameServerObject jsonObject)
{
// Create a StringContent with the JSON data and set the content type
string jsonData = JsonConvert.SerializeObject(jsonObject);
string endpoint = "addGameServer/";

try
{
await _apiClient.PostMonitoringData(endpoint, jsonData);
Console.WriteLine($"Game server successfully added to monitoring.");
}
catch (Exception ex)
{
Console.WriteLine($"Error adding the game server from monitoring: {ex.Message}");
}
}

public async Task EditGameServer(GameServerObject jsonObject, string gameServerID)
{
// Create a StringContent with the JSON data and set the content type
string jsonData = JsonConvert.SerializeObject(jsonObject);
string endpoint = $"updateGameServer/{gameServerID}";

try
{
await _apiClient.PostMonitoringData(endpoint, jsonData);
Console.WriteLine($"Game server successfully edited in monitoring.");
}
catch (Exception ex)
{
Console.WriteLine($"Error editing the game server in monitoring: {ex.Message}");
}
}
}
Loading

0 comments on commit 692c71c

Please sign in to comment.