From 92f0c7c9f4423a3442642333ff3111cd3bbccf8a Mon Sep 17 00:00:00 2001 From: cxxpxr <60411087+cxxpxr@users.noreply.github.com> Date: Sun, 11 Apr 2021 01:02:40 -0400 Subject: [PATCH] Cleanup switched to use static webclient and refactored existing code. --- .../LRM/Config.cs | 2 +- .../LRM/Program/Program.cs | 156 ++---------------- .../LRM/Program/ProgramConfigurator.cs | 150 +++++++++++++++++ .../LRM/Program/ProgramExtra.cs | 17 +- .../LRM/Program/ProgramVariables.cs | 12 +- .../LRM/RelayHandler/RelayHandler.cs | 9 +- 6 files changed, 191 insertions(+), 155 deletions(-) create mode 100644 ServerProject-DONT-IMPORT-INTO-UNITY/LRM/Program/ProgramConfigurator.cs diff --git a/ServerProject-DONT-IMPORT-INTO-UNITY/LRM/Config.cs b/ServerProject-DONT-IMPORT-INTO-UNITY/LRM/Config.cs index 8e5b6ae..7ef295a 100644 --- a/ServerProject-DONT-IMPORT-INTO-UNITY/LRM/Config.cs +++ b/ServerProject-DONT-IMPORT-INTO-UNITY/LRM/Config.cs @@ -4,7 +4,7 @@ using System.Text; namespace LightReflectiveMirror { - class Config + public class Config { //======================== // Required Settings diff --git a/ServerProject-DONT-IMPORT-INTO-UNITY/LRM/Program/Program.cs b/ServerProject-DONT-IMPORT-INTO-UNITY/LRM/Program/Program.cs index 9c53ced..b640ffe 100644 --- a/ServerProject-DONT-IMPORT-INTO-UNITY/LRM/Program/Program.cs +++ b/ServerProject-DONT-IMPORT-INTO-UNITY/LRM/Program/Program.cs @@ -16,24 +16,14 @@ namespace LightReflectiveMirror partial class Program { public static void Main(string[] args) => new Program().MainAsync().GetAwaiter().GetResult(); - public List GetRooms() => _relay.rooms; public async Task MainAsync() { WriteTitle(); instance = this; _startupTime = DateTime.Now; - using (WebClient wc = new WebClient()) - { - try - { - publicIP = wc.DownloadString("http://ipv4.icanhazip.com").Replace("\\r", "").Replace("\\n", "").Trim(); - } - catch { - WriteLogMessage("Failed to reach public IP endpoint! Using loopback address.", ConsoleColor.Yellow); - publicIP = "127.0.0.1"; - } - } + + GetPublicIP(); if (!File.Exists(CONFIG_PATH)) { @@ -46,22 +36,7 @@ namespace LightReflectiveMirror { conf = JsonConvert.DeserializeObject(File.ReadAllText(CONFIG_PATH)); - // Docker variables. - if (ushort.TryParse(Environment.GetEnvironmentVariable("LRM_ENDPOINT_PORT"), out ushort endpointPort)) - conf.EndpointPort = endpointPort; - - if (ushort.TryParse(Environment.GetEnvironmentVariable("LRM_TRANSPORT_PORT"), out ushort transportPort)) - conf.TransportPort = transportPort; - - if (ushort.TryParse(Environment.GetEnvironmentVariable("LRM_PUNCHER_PORT"), out ushort puncherPort)) - conf.NATPunchtroughPort = puncherPort; - - string LBAuthKey = Environment.GetEnvironmentVariable("LRM_LB_AUTHKEY"); - if (!string.IsNullOrWhiteSpace(LBAuthKey)) - { - conf.LoadBalancerAuthKey = LBAuthKey; - WriteLogMessage("\nLoaded LB auth key from environment variable\n", ConsoleColor.Green); - } + ConfigureDocker(); WriteLogMessage("Loading Assembly... ", ConsoleColor.White, true); try @@ -75,109 +50,13 @@ namespace LightReflectiveMirror if (transport != null) { - var transportClass = asm.GetType(conf.TransportClass); - WriteLogMessage("OK", ConsoleColor.Green); - - WriteLogMessage("\nLoading Transport Methods... ", ConsoleColor.White, true); - CheckMethods(transportClass); - WriteLogMessage("OK", ConsoleColor.Green); - - WriteLogMessage("\nInvoking Transport Methods..."); - - if (_awakeMethod != null) - _awakeMethod.Invoke(transport, null); - - if (_startMethod != null) - _startMethod.Invoke(transport, null); - - WriteLogMessage("\nStarting Transport... ", ConsoleColor.White, true); - - transport.OnServerError = (clientID, error) => - { - WriteLogMessage($"Transport Error, Client: {clientID}, Error: {error}", ConsoleColor.Red); - }; - - transport.OnServerConnected = (clientID) => - { - WriteLogMessage($"Transport Connected, Client: {clientID}", ConsoleColor.Cyan); - _currentConnections.Add(clientID); - _relay.ClientConnected(clientID); - - if (conf.EnableNATPunchtroughServer) - { - string natID = Guid.NewGuid().ToString(); - _pendingNATPunches.Add(clientID, natID); - _NATRequestPosition = 0; - _NATRequest.WriteByte(ref _NATRequestPosition, (byte)OpCodes.RequestNATConnection); - _NATRequest.WriteString(ref _NATRequestPosition, natID); - _NATRequest.WriteInt(ref _NATRequestPosition, conf.NATPunchtroughPort); - transport.ServerSend(clientID, 0, new ArraySegment(_NATRequest, 0, _NATRequestPosition)); - } - }; - - _relay = new RelayHandler(transport.GetMaxPacketSize(0)); - - transport.OnServerDataReceived = _relay.HandleMessage; - transport.OnServerDisconnected = (clientID) => - { - _currentConnections.Remove(clientID); - _relay.HandleDisconnect(clientID); - - if (NATConnections.ContainsKey(clientID)) - NATConnections.Remove(clientID); - - if (_pendingNATPunches.TryGetByFirst(clientID, out _)) - _pendingNATPunches.Remove(clientID); - }; - - transport.ServerStart(conf.TransportPort); - - WriteLogMessage("OK", ConsoleColor.Green); + ConfigureTransport(asm); if (conf.UseEndpoint) - { - WriteLogMessage("\nStarting Endpoint Service... ", ConsoleColor.White, true); - var endpointService = new EndpointServer(); - - if (endpointService.Start(conf.EndpointPort)) - { - WriteLogMessage("OK", ConsoleColor.Green); - Endpoint.RoomsModified(); - } - else - { - WriteLogMessage("FAILED\nPlease run as administrator or check if port is in use.", ConsoleColor.DarkRed); - } - } + ConfigureEndpoint(); if (conf.EnableNATPunchtroughServer) - { - WriteLogMessage("\nStarting NatPunchthrough Socket... ", ConsoleColor.White, true); - - try - { - _punchServer = new UdpClient(conf.NATPunchtroughPort); - - WriteLogMessage("OK\n", ConsoleColor.Green, true); - - WriteLogMessage("\nStarting NatPunchthrough Thread... ", ConsoleColor.White, true); - var natThread = new Thread(new ThreadStart(RunNATPunchLoop)); - - try - { - natThread.Start(); - } - catch (Exception e) - { - WriteLogMessage("FAILED\n" + e, ConsoleColor.DarkRed); - } - } - catch (Exception e) - { - WriteLogMessage("FAILED\nCheck if port is in use.", ConsoleColor.DarkRed, true); - Console.WriteLine(e); - } - } + ConfigurePunchthrough(); } else { @@ -197,6 +76,11 @@ namespace LightReflectiveMirror await RegisterSelfToLoadBalancer(); } + await HeartbeatLoop(); + } + + private async Task HeartbeatLoop() + { while (true) { try @@ -209,7 +93,6 @@ namespace LightReflectiveMirror WriteLogMessage("Error During Transport Update! " + e, ConsoleColor.Red); } - _currentHeartbeatTimer++; if (_currentHeartbeatTimer >= conf.UpdateHeartbeatInterval) @@ -224,7 +107,9 @@ namespace LightReflectiveMirror if (DateTime.Now > Endpoint.lastPing.AddSeconds(60)) { // Dont await that on main thread. It would cause a lag spike for clients. +#pragma warning disable CS4014 RegisterSelfToLoadBalancer(); +#pragma warning restore CS4014 } } @@ -239,11 +124,8 @@ namespace LightReflectiveMirror { try { - using (WebClient wc = new()) - { - wc.Headers.Add("Authorization", conf.LoadBalancerAuthKey); - await wc.DownloadStringTaskAsync($"http://{conf.LoadBalancerAddress}:{conf.LoadBalancerPort}/api/roomsupdated"); - } + webClient.Headers.Add("Authorization", conf.LoadBalancerAuthKey); + await webClient.DownloadStringTaskAsync($"http://{conf.LoadBalancerAddress}:{conf.LoadBalancerPort}/api/roomsupdated"); } catch { } // LLB might be down, ignore. } @@ -279,13 +161,5 @@ namespace LightReflectiveMirror return false; } } - - void CheckMethods(Type type) - { - _awakeMethod = type.GetMethod("Awake", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); - _startMethod = type.GetMethod("Start", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); - _updateMethod = type.GetMethod("Update", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); - _lateUpdateMethod = type.GetMethod("LateUpdate", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); - } } } diff --git a/ServerProject-DONT-IMPORT-INTO-UNITY/LRM/Program/ProgramConfigurator.cs b/ServerProject-DONT-IMPORT-INTO-UNITY/LRM/Program/ProgramConfigurator.cs new file mode 100644 index 0000000..2de3939 --- /dev/null +++ b/ServerProject-DONT-IMPORT-INTO-UNITY/LRM/Program/ProgramConfigurator.cs @@ -0,0 +1,150 @@ +using LightReflectiveMirror.Endpoints; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Sockets; +using System.Reflection; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace LightReflectiveMirror +{ + public partial class Program + { + private void ConfigureTransport(Assembly asm) + { + var transportClass = asm.GetType(conf.TransportClass); + WriteLogMessage("OK", ConsoleColor.Green); + + WriteLogMessage("\nLoading Transport Methods... ", ConsoleColor.White, true); + CheckMethods(transportClass); + WriteLogMessage("OK", ConsoleColor.Green); + + WriteLogMessage("\nInvoking Transport Methods..."); + + if (_awakeMethod != null) + _awakeMethod.Invoke(transport, null); + + if (_startMethod != null) + _startMethod.Invoke(transport, null); + + WriteLogMessage("\nStarting Transport... ", ConsoleColor.White, true); + + transport.OnServerError = (clientID, error) => + { + WriteLogMessage($"Transport Error, Client: {clientID}, Error: {error}", ConsoleColor.Red); + }; + + transport.OnServerConnected = (clientID) => + { + WriteLogMessage($"Transport Connected, Client: {clientID}", ConsoleColor.Cyan); + _currentConnections.Add(clientID); + _relay.ClientConnected(clientID); + + if (conf.EnableNATPunchtroughServer) + { + string natID = Guid.NewGuid().ToString(); + _pendingNATPunches.Add(clientID, natID); + _NATRequestPosition = 0; + _NATRequest.WriteByte(ref _NATRequestPosition, (byte)OpCodes.RequestNATConnection); + _NATRequest.WriteString(ref _NATRequestPosition, natID); + _NATRequest.WriteInt(ref _NATRequestPosition, conf.NATPunchtroughPort); + transport.ServerSend(clientID, 0, new ArraySegment(_NATRequest, 0, _NATRequestPosition)); + } + }; + + _relay = new RelayHandler(transport.GetMaxPacketSize(0)); + + transport.OnServerDataReceived = _relay.HandleMessage; + transport.OnServerDisconnected = (clientID) => + { + _currentConnections.Remove(clientID); + _relay.HandleDisconnect(clientID); + + if (NATConnections.ContainsKey(clientID)) + NATConnections.Remove(clientID); + + if (_pendingNATPunches.TryGetByFirst(clientID, out _)) + _pendingNATPunches.Remove(clientID); + }; + + transport.ServerStart(conf.TransportPort); + + WriteLogMessage("OK", ConsoleColor.Green); + } + + private static void ConfigureEndpoint() + { + WriteLogMessage("\nStarting Endpoint Service... ", ConsoleColor.White, true); + var endpointService = new EndpointServer(); + + if (endpointService.Start(conf.EndpointPort)) + { + WriteLogMessage("OK", ConsoleColor.Green); + Endpoint.RoomsModified(); + } + else + { + WriteLogMessage("FAILED\nPlease run as administrator or check if port is in use.", ConsoleColor.DarkRed); + } + } + + private void ConfigurePunchthrough() + { + WriteLogMessage("\nStarting NatPunchthrough Socket... ", ConsoleColor.White, true); + + try + { + _punchServer = new UdpClient(conf.NATPunchtroughPort); + + WriteLogMessage("OK\n", ConsoleColor.Green, true); + + WriteLogMessage("\nStarting NatPunchthrough Thread... ", ConsoleColor.White, true); + var natThread = new Thread(new ThreadStart(RunNATPunchLoop)); + + try + { + natThread.Start(); + } + catch (Exception e) + { + WriteLogMessage("FAILED\n" + e, ConsoleColor.DarkRed); + } + } + catch (Exception e) + { + WriteLogMessage("FAILED\nCheck if port is in use.", ConsoleColor.DarkRed, true); + Console.WriteLine(e); + } + } + + private static void ConfigureDocker() + { + // Docker variables. + if (ushort.TryParse(Environment.GetEnvironmentVariable("LRM_ENDPOINT_PORT"), out ushort endpointPort)) + conf.EndpointPort = endpointPort; + + if (ushort.TryParse(Environment.GetEnvironmentVariable("LRM_TRANSPORT_PORT"), out ushort transportPort)) + conf.TransportPort = transportPort; + + if (ushort.TryParse(Environment.GetEnvironmentVariable("LRM_PUNCHER_PORT"), out ushort puncherPort)) + conf.NATPunchtroughPort = puncherPort; + + string LBAuthKey = Environment.GetEnvironmentVariable("LRM_LB_AUTHKEY"); + if (!string.IsNullOrWhiteSpace(LBAuthKey)) + { + conf.LoadBalancerAuthKey = LBAuthKey; + WriteLogMessage("\nLoaded LB auth key from environment variable\n", ConsoleColor.Green); + } + } + + void CheckMethods(Type type) + { + _awakeMethod = type.GetMethod("Awake", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); + _startMethod = type.GetMethod("Start", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); + _updateMethod = type.GetMethod("Update", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); + _lateUpdateMethod = type.GetMethod("LateUpdate", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); + } + } +} diff --git a/ServerProject-DONT-IMPORT-INTO-UNITY/LRM/Program/ProgramExtra.cs b/ServerProject-DONT-IMPORT-INTO-UNITY/LRM/Program/ProgramExtra.cs index 347a850..471cffa 100644 --- a/ServerProject-DONT-IMPORT-INTO-UNITY/LRM/Program/ProgramExtra.cs +++ b/ServerProject-DONT-IMPORT-INTO-UNITY/LRM/Program/ProgramExtra.cs @@ -1,11 +1,12 @@ using System; +using System.Collections.Generic; using System.Linq; namespace LightReflectiveMirror { partial class Program { - + public List GetRooms() => _relay.rooms; public int GetConnections() => _currentConnections.Count; public TimeSpan GetUptime() => DateTime.Now - _startupTime; public int GetPublicRoomCount() => _relay.rooms.Where(x => x.isPublic).Count(); @@ -19,6 +20,20 @@ namespace LightReflectiveMirror Console.WriteLine(message); } + private static void GetPublicIP() + { + try + { + // easier to just ping an outside source to get our public ip + publicIP = webClient.DownloadString("http://ipv4.icanhazip.com").Replace("\\r", "").Replace("\\n", "").Trim(); + } + catch + { + WriteLogMessage("Failed to reach public IP endpoint! Using loopback address.", ConsoleColor.Yellow); + publicIP = "127.0.0.1"; + } + } + void WriteTitle() { string t = @" diff --git a/ServerProject-DONT-IMPORT-INTO-UNITY/LRM/Program/ProgramVariables.cs b/ServerProject-DONT-IMPORT-INTO-UNITY/LRM/Program/ProgramVariables.cs index 9addd44..6af02aa 100644 --- a/ServerProject-DONT-IMPORT-INTO-UNITY/LRM/Program/ProgramVariables.cs +++ b/ServerProject-DONT-IMPORT-INTO-UNITY/LRM/Program/ProgramVariables.cs @@ -1,5 +1,4 @@ -using LightReflectiveMirror.Endpoints; -using Mirror; +using Mirror; using System; using System.Collections.Generic; using System.Net; @@ -8,8 +7,9 @@ using System.Reflection; namespace LightReflectiveMirror { - partial class Program + public partial class Program { + public static WebClient webClient = new(); public static Transport transport; public static Program instance; public static Config conf; @@ -22,9 +22,9 @@ namespace LightReflectiveMirror private DateTime _startupTime; public static string publicIP; - private List _currentConnections = new List(); - public Dictionary NATConnections = new Dictionary(); - private BiDictionary _pendingNATPunches = new BiDictionary(); + private List _currentConnections = new(); + public Dictionary NATConnections = new(); + private BiDictionary _pendingNATPunches = new(); private int _currentHeartbeatTimer = 0; private byte[] _NATRequest = new byte[500]; diff --git a/ServerProject-DONT-IMPORT-INTO-UNITY/LRM/RelayHandler/RelayHandler.cs b/ServerProject-DONT-IMPORT-INTO-UNITY/LRM/RelayHandler/RelayHandler.cs index dd015a2..7b6f666 100644 --- a/ServerProject-DONT-IMPORT-INTO-UNITY/LRM/RelayHandler/RelayHandler.cs +++ b/ServerProject-DONT-IMPORT-INTO-UNITY/LRM/RelayHandler/RelayHandler.cs @@ -99,13 +99,10 @@ namespace LightReflectiveMirror else { // ping load balancer here - using (WebClient wc = new()) - { - var uri = new Uri($"http://{Program.conf.LoadBalancerAddress}:{Program.conf.LoadBalancerPort}/api/get/id"); - string randomID = wc.DownloadString(uri).Replace("\\r", "").Replace("\\n", "").Trim(); + var uri = new Uri($"http://{Program.conf.LoadBalancerAddress}:{Program.conf.LoadBalancerPort}/api/get/id"); + string randomID = Program.webClient.DownloadString(uri).Replace("\\r", "").Replace("\\n", "").Trim(); - return randomID; - } + return randomID; } }