diff --git a/LoadBalancerProject-DONT-IMPORT-INTO-UNITY/Config.cs b/LoadBalancerProject-DONT-IMPORT-INTO-UNITY/Config.cs new file mode 100644 index 0000000..5a72803 --- /dev/null +++ b/LoadBalancerProject-DONT-IMPORT-INTO-UNITY/Config.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace LightReflectiveMirror.LoadBalancing +{ + class Config + { + public int ConnectedServerPingRate = 10000; + public string AuthKey = "AuthKey"; + public ushort EndpointPort = 8080; + } +} diff --git a/LoadBalancerProject-DONT-IMPORT-INTO-UNITY/Endpoint.cs b/LoadBalancerProject-DONT-IMPORT-INTO-UNITY/Endpoint.cs new file mode 100644 index 0000000..ce65f6f --- /dev/null +++ b/LoadBalancerProject-DONT-IMPORT-INTO-UNITY/Endpoint.cs @@ -0,0 +1,65 @@ +using Grapevine; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using System; +using System.Threading.Tasks; + +namespace LightReflectiveMirror.LoadBalancing +{ + [RestResource] + public class Endpoint + { + [RestRoute("Get", "/api/auth")] + public async Task ReceiveAuthKey(IHttpContext context) + { + var req = context.Request.Headers; + + // if server is authenticated + if (req[0] == Program.conf.AuthKey) + { + var address = context.Request.RemoteEndPoint.Address.ToString(); + await Program.instance.AddServer(address); + + Console.WriteLine("Server accepted: " + address); + + await context.Response.SendResponseAsync(HttpStatusCode.Ok); + } + else + await context.Response.SendResponseAsync(HttpStatusCode.Forbidden); + } + } + + public class EndpointServer + { + public bool Start(ushort port = 8080) + { + try + { + var config = new ConfigurationBuilder() + .SetBasePath(System.IO.Directory.GetCurrentDirectory()) + .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) + .Build(); + + var server = new RestServerBuilder(new ServiceCollection(), config, + (services) => + { + services.AddLogging(configure => configure.AddConsole()); + services.Configure(options => options.MinLevel = LogLevel.None); + }, (server) => + { + server.Prefixes.Add($"http://*:{port}/"); + }).Build(); + + server.Router.Options.SendExceptionMessages = false; + server.Start(); + + return true; + } + catch + { + return false; + } + } + } +} diff --git a/LoadBalancerProject-DONT-IMPORT-INTO-UNITY/Program.cs b/LoadBalancerProject-DONT-IMPORT-INTO-UNITY/Program.cs new file mode 100644 index 0000000..b94476c --- /dev/null +++ b/LoadBalancerProject-DONT-IMPORT-INTO-UNITY/Program.cs @@ -0,0 +1,158 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Threading; +using System.Threading.Tasks; + +namespace LightReflectiveMirror.LoadBalancing +{ + class Program + { + /// + /// Keeps track of all available relays. + /// Key is server address, value is CCU/Info. + /// + public Dictionary availableRelayServers = new(); + + private int _pingDelay = 10000; + const string API_PATH = "/api/stats"; + const string CONFIG_PATH = "config.json"; + + public static Config conf; + public static Program instance; + + public static void Main(string[] args) => new Program().MainAsync().GetAwaiter().GetResult(); + + public async Task MainAsync() + { + WriteTitle(); + instance = this; + + if (!File.Exists(CONFIG_PATH)) + { + File.WriteAllText(CONFIG_PATH, JsonConvert.SerializeObject(new Config(), Formatting.Indented)); + WriteLogMessage("A config.json file was generated. Please configure it to the proper settings and re-run!", ConsoleColor.Yellow); + Console.ReadKey(); + Environment.Exit(0); + } + else + { + conf = JsonConvert.DeserializeObject(File.ReadAllText(CONFIG_PATH)); + _pingDelay = conf.ConnectedServerPingRate; + + if (new EndpointServer().Start(conf.EndpointPort)) + WriteLogMessage("Endpoint server started successfully", ConsoleColor.Green); + else + WriteLogMessage("Endpoint server started unsuccessfully", ConsoleColor.Red); + } + + var pingThread = new Thread(new ThreadStart(() => PingServers())); + pingThread.Start(); + + // keep console alive + await Task.Delay(-1); + } + + + public async Task AddServer(string serverIP) + { + var stats = await InitialPingServer(serverIP); + + if(stats.PublicRoomCount != -1) + availableRelayServers.Add(serverIP, stats); + } + + async Task InitialPingServer(string serverIP) + { + string url = serverIP + API_PATH; + HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(url); + + try + { + WebResponse response = await myRequest.GetResponseAsync(); + var reader = new StreamReader(response.GetResponseStream()); + + return JsonConvert.DeserializeObject(reader.ReadToEnd()); + } + catch (Exception ex) + { + // server doesnt exist anymore probably + // do more shit here + + return new RelayStats { PublicRoomCount = -1 }; + } + } + + async Task PingServers() + { + while (true) + { + foreach (var server in availableRelayServers) + { + string url = server + API_PATH; + HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(url); + + try + { + WebResponse response = await myRequest.GetResponseAsync(); + + var reader = new StreamReader(response.GetResponseStream()); + + availableRelayServers.Remove(server.Key); + availableRelayServers.Add(server.Key, JsonConvert.DeserializeObject(reader.ReadToEnd())); + } + catch (Exception ex) + { + // server doesnt exist anymore probably + // do more shit here + + availableRelayServers.Remove(server.Key); + } + } + + await Task.Delay(_pingDelay); + } + } + + void WriteTitle() + { + string t = @" + w c(..)o ( + _ _____ __ __ \__(-) __) + | | | __ \ | \/ | /\ ( + | | | |__) || \ / | /(_)___) + | | | _ / | |\/| | w /| + | |____ | | \ \ | | | | | \ + |______||_| \_\|_| |_| m m copyright monkesoft 2021 +"; + + string load = $"Chimp Event Listener Initializing... OK" + + "\nHarambe Memorial Initializing... OK" + + "\nBananas Initializing... OK\n"; + + WriteLogMessage(t, ConsoleColor.Green); + WriteLogMessage(load, ConsoleColor.Cyan); + } + + static void WriteLogMessage(string message, ConsoleColor color = ConsoleColor.White, bool oneLine = false) + { + Console.ForegroundColor = color; + if (oneLine) + Console.Write(message); + else + Console.WriteLine(message); + } + + [Serializable] + public struct RelayStats + { + public int ConnectedClients; + public int RoomCount; + public int PublicRoomCount; + public TimeSpan Uptime; + } + + } +}