From b6a56d16c4b40bb463dafe124f2e48f7050df11f Mon Sep 17 00:00:00 2001 From: Chris Yeninas <844685+PhantomGamers@users.noreply.github.com> Date: Sat, 27 Apr 2024 23:35:40 -0400 Subject: [PATCH 1/8] Update NgrokManager.cs cleanup + error throwing --- NebulaNetwork/Ngrok/NgrokManager.cs | 68 +++++++++++++++++------------ 1 file changed, 39 insertions(+), 29 deletions(-) diff --git a/NebulaNetwork/Ngrok/NgrokManager.cs b/NebulaNetwork/Ngrok/NgrokManager.cs index fbfd13227..61b976d2f 100644 --- a/NebulaNetwork/Ngrok/NgrokManager.cs +++ b/NebulaNetwork/Ngrok/NgrokManager.cs @@ -21,11 +21,11 @@ namespace NebulaNetwork.Ngrok; public class NgrokManager { - private readonly string _authtoken; + private readonly string _authToken; private readonly TaskCompletionSource _ngrokAddressObtainedSource = new(); private readonly string _ngrokConfigPath; - private readonly string _ngrokPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), + private readonly string _ngrokPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? throw new InvalidOperationException("_ngrokPath null"), "ngrok-v3-stable-windows-amd64", "ngrok.exe"); private readonly int _port; @@ -39,11 +39,11 @@ public class NgrokManager public string NgrokLastErrorCode; private static readonly string[] contents = { "version: 2" }; - public NgrokManager(int port, string authtoken = null, string region = null) + public NgrokManager(int port, string authToken = null, string region = null) { - _ngrokConfigPath = Path.Combine(Path.GetDirectoryName(_ngrokPath), "ngrok.yml"); + _ngrokConfigPath = Path.Combine(Path.GetDirectoryName(_ngrokPath) ?? throw new InvalidOperationException("_ngrokConfigPath null"), "ngrok.yml"); _port = port; - _authtoken = authtoken ?? Config.Options.NgrokAuthtoken; + _authToken = authToken ?? Config.Options.NgrokAuthtoken; _region = region ?? Config.Options.NgrokRegion; if (!NgrokEnabled) @@ -51,7 +51,7 @@ public NgrokManager(int port, string authtoken = null, string region = null) return; } - if (string.IsNullOrEmpty(_authtoken)) + if (string.IsNullOrEmpty(_authToken)) { Log.WarnInform("Ngrok support was enabled, however no Authtoken was provided".Translate()); return; @@ -97,6 +97,10 @@ public NgrokManager(int port, string authtoken = null, string region = null) try { await DownloadAndInstallNgrok(); + if (!IsNgrokInstalled()) + { + throw new FileNotFoundException(); + } } catch { @@ -124,17 +128,13 @@ private async Task DownloadAndInstallNgrok() { using (var client = new HttpClient()) { - using (var s = client.GetStreamAsync("https://bin.equinox.io/c/bNyj1mQVY4c/ngrok-v3-stable-windows-amd64.zip")) + using var s = client.GetStreamAsync("https://bin.equinox.io/c/bNyj1mQVY4c/ngrok-v3-stable-windows-amd64.zip"); + using var zip = new ZipArchive(await s, ZipArchiveMode.Read); + if (File.Exists(_ngrokPath)) { - using (var zip = new ZipArchive(await s, ZipArchiveMode.Read)) - { - if (File.Exists(_ngrokPath)) - { - File.Delete(_ngrokPath); - } - zip.ExtractToDirectory(Path.GetDirectoryName(_ngrokPath)); - } + File.Delete(_ngrokPath); } + zip.ExtractToDirectory(Path.GetDirectoryName(_ngrokPath)); } File.WriteAllLines(_ngrokConfigPath, contents); @@ -151,36 +151,46 @@ private bool StartNgrok() { StopNgrok(); - _ngrokProcess = new Process(); - _ngrokProcess.StartInfo = new ProcessStartInfo + _ngrokProcess = new Process { - WindowStyle = ProcessWindowStyle.Hidden, - RedirectStandardOutput = true, - RedirectStandardError = true, - UseShellExecute = false, - CreateNoWindow = true, - FileName = _ngrokPath, - Arguments = - $"tcp {_port} --authtoken {_authtoken} --log stdout --log-format json --config \"{_ngrokConfigPath}\"" + + StartInfo = new ProcessStartInfo + { + WindowStyle = ProcessWindowStyle.Hidden, + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false, + CreateNoWindow = true, + FileName = _ngrokPath, + Arguments = + $"tcp {_port} --authtoken {_authToken} --log stdout --log-format json --config \"{_ngrokConfigPath}\"" + (!string.IsNullOrEmpty(_region) ? $" --region {_region}" : "") + } }; _ngrokProcess.OutputDataReceived += OutputDataReceivedEventHandler; _ngrokProcess.ErrorDataReceived += ErrorDataReceivedEventHandler; + _ngrokProcess.Exited += (_, _) => + { + _ngrokProcess = null; + }; var started = _ngrokProcess.Start(); if (IsNgrokActive()) { // This links the process as a child process by attaching a null debugger thus ensuring that the process is killed when its parent dies. - new ChildProcessLinker(_ngrokProcess, exception => + _ = new ChildProcessLinker(_ngrokProcess, _ => { Log.Warn( "Failed to link Ngrok process to DSP process as a child! (This might result in a left over ngrok process if the DSP process uncleanly killed)"); }); } + else + { + Log.Error("Failed to start Ngrok process!"); + } - _ngrokProcess.BeginOutputReadLine(); - _ngrokProcess.BeginErrorReadLine(); + _ngrokProcess?.BeginOutputReadLine(); + _ngrokProcess?.BeginErrorReadLine(); return started; } @@ -266,7 +276,7 @@ public bool IsNgrokActive() } _ngrokProcess.Refresh(); - return !_ngrokProcess.HasExited; + return !_ngrokProcess?.HasExited ?? false; } public Task GetNgrokAddressAsync() From 865b09b9a3ae6381cb8ae51d2162303416c9d74e Mon Sep 17 00:00:00 2001 From: Chris Yeninas <844685+PhantomGamers@users.noreply.github.com> Date: Sat, 27 Apr 2024 23:36:26 -0400 Subject: [PATCH 2/8] Update NgrokManager.cs error descriptions --- NebulaNetwork/Ngrok/NgrokManager.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/NebulaNetwork/Ngrok/NgrokManager.cs b/NebulaNetwork/Ngrok/NgrokManager.cs index 61b976d2f..bac380f58 100644 --- a/NebulaNetwork/Ngrok/NgrokManager.cs +++ b/NebulaNetwork/Ngrok/NgrokManager.cs @@ -37,6 +37,7 @@ public class NgrokManager public string NgrokAddress; public string NgrokLastErrorCode; + public string NgrokLastErrorCodeDesc; private static readonly string[] contents = { "version: 2" }; public NgrokManager(int port, string authToken = null, string region = null) @@ -250,7 +251,12 @@ private void ErrorDataReceivedEventHandler(object sender, DataReceivedEventArgs return; } NgrokLastErrorCode = errorCodeMatches[errorCodeMatches.Count - 1].Value; - Log.WarnInform(string.Format("Ngrok Error! Code: {0}".Translate(), NgrokLastErrorCode)); + NgrokLastErrorCodeDesc = NgrokLastErrorCode switch + { + "ERR_NGROK_105" => "Authtoken is invalid".Translate(), + _ => string.Empty + }; + Log.WarnInform(string.Format("Ngrok Error! Code: {0} ({1})".Translate(), NgrokLastErrorCode, NgrokLastErrorCodeDesc)); } public void StopNgrok() From 957cbf02121a26a911fa6d3c7d94284d892f8fec Mon Sep 17 00:00:00 2001 From: Chris Yeninas <844685+PhantomGamers@users.noreply.github.com> Date: Sat, 27 Apr 2024 23:55:57 -0400 Subject: [PATCH 3/8] Update NgrokManager.cs additional error protection, trying to avoid hardlocking the game client if this method throws somewhere --- NebulaNetwork/Ngrok/NgrokManager.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/NebulaNetwork/Ngrok/NgrokManager.cs b/NebulaNetwork/Ngrok/NgrokManager.cs index bac380f58..cb28ef149 100644 --- a/NebulaNetwork/Ngrok/NgrokManager.cs +++ b/NebulaNetwork/Ngrok/NgrokManager.cs @@ -276,13 +276,16 @@ public void StopNgrok() public bool IsNgrokActive() { - if (_ngrokProcess == null) + try + { + _ngrokProcess?.Refresh(); + return !_ngrokProcess?.HasExited ?? false; + } + catch (Exception e) { + Log.Error(e); return false; } - - _ngrokProcess.Refresh(); - return !_ngrokProcess?.HasExited ?? false; } public Task GetNgrokAddressAsync() From af4f3141e62029a33860dd79c4dcae549a027840 Mon Sep 17 00:00:00 2001 From: Chris Yeninas <844685+PhantomGamers@users.noreply.github.com> Date: Sun, 28 Apr 2024 00:03:01 -0400 Subject: [PATCH 4/8] Update ConstructionSystem_Transpiler.cs remove erroneous log statement --- .../Patches/Transpilers/ConstructionSystem_Transpiler.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/NebulaPatcher/Patches/Transpilers/ConstructionSystem_Transpiler.cs b/NebulaPatcher/Patches/Transpilers/ConstructionSystem_Transpiler.cs index 5d588f021..da8401041 100644 --- a/NebulaPatcher/Patches/Transpilers/ConstructionSystem_Transpiler.cs +++ b/NebulaPatcher/Patches/Transpilers/ConstructionSystem_Transpiler.cs @@ -34,7 +34,6 @@ public static IEnumerable AddBuildTargetToModules_Transpiler(IE new CodeMatch(OpCodes.Ldloc_0), new CodeMatch(OpCodes.Bgt_Un) ); - Log.Info(codeMatcher.IsValid); var sqrDist = codeMatcher.InstructionAt(-2).operand; var skipLabel = codeMatcher.Operand; codeMatcher.Advance(1) From 50482e76f04deb7ad447f53ad5270bdce4e38550 Mon Sep 17 00:00:00 2001 From: Chris Yeninas <844685+PhantomGamers@users.noreply.github.com> Date: Sun, 28 Apr 2024 22:08:45 -0400 Subject: [PATCH 5/8] more ngrok updates catch more errors, some cleanup, add ngrok error code desc to chat command --- NebulaModel/Networking/IServer.cs | 1 + NebulaNetwork/Ngrok/NgrokManager.cs | 32 +++++++++++++++---- NebulaNetwork/Server.cs | 1 + .../Chat/Commands/InfoCommandHandler.cs | 12 +++---- 4 files changed, 33 insertions(+), 13 deletions(-) diff --git a/NebulaModel/Networking/IServer.cs b/NebulaModel/Networking/IServer.cs index 1147ef83f..1de43bc96 100644 --- a/NebulaModel/Networking/IServer.cs +++ b/NebulaModel/Networking/IServer.cs @@ -14,6 +14,7 @@ public interface IServer : INetworkProvider bool NgrokActive { get; } bool NgrokEnabled { get; } string NgrokLastErrorCode { get; } + string NgrokLastErrorCodeDesc { get; } public event EventHandler Connected; public event EventHandler Disconnected; diff --git a/NebulaNetwork/Ngrok/NgrokManager.cs b/NebulaNetwork/Ngrok/NgrokManager.cs index cb28ef149..e00898d2d 100644 --- a/NebulaNetwork/Ngrok/NgrokManager.cs +++ b/NebulaNetwork/Ngrok/NgrokManager.cs @@ -140,7 +140,14 @@ private async Task DownloadAndInstallNgrok() File.WriteAllLines(_ngrokConfigPath, contents); - Log.WarnInform("Ngrok install completed in the plugin folder".Translate()); + if (File.Exists(_ngrokPath)) + { + Log.WarnInform("Ngrok install completed in the plugin folder".Translate()); + } + else + { + Log.Error("Ngrok installation failed".Translate()); + } } private bool IsNgrokInstalled() @@ -172,7 +179,7 @@ private bool StartNgrok() _ngrokProcess.ErrorDataReceived += ErrorDataReceivedEventHandler; _ngrokProcess.Exited += (_, _) => { - _ngrokProcess = null; + StopNgrok(); }; var started = _ngrokProcess.Start(); @@ -256,7 +263,11 @@ private void ErrorDataReceivedEventHandler(object sender, DataReceivedEventArgs "ERR_NGROK_105" => "Authtoken is invalid".Translate(), _ => string.Empty }; - Log.WarnInform(string.Format("Ngrok Error! Code: {0} ({1})".Translate(), NgrokLastErrorCode, NgrokLastErrorCodeDesc)); + if (!string.IsNullOrWhiteSpace(NgrokLastErrorCodeDesc)) + { + NgrokLastErrorCodeDesc = $"({NgrokLastErrorCodeDesc})"; + } + Log.WarnInform(string.Format("Ngrok Error! Code: {0} {1}".Translate(), NgrokLastErrorCode, NgrokLastErrorCodeDesc)); } public void StopNgrok() @@ -266,11 +277,18 @@ public void StopNgrok() return; } _ngrokProcess.Refresh(); - if (!_ngrokProcess.HasExited) + try { - _ngrokProcess.Kill(); - _ngrokProcess.Close(); + if (!_ngrokProcess.HasExited) + { + _ngrokProcess.Kill(); + } + } + catch (Exception e) + { + Log.Error(e); } + _ngrokProcess.Close(); _ngrokProcess = null; } @@ -301,7 +319,7 @@ public Task GetNgrokAddressAsync() if (!_ngrokAddressObtainedSource.Task.Wait(TimeSpan.FromSeconds(15))) { throw new TimeoutException( - $"Not able to get Ngrok tunnel address because 15s timeout was exceeded! LastErrorCode: {NgrokLastErrorCode}"); + $"Not able to get Ngrok tunnel address because 15s timeout was exceeded! LastErrorCode: {NgrokLastErrorCode} ({NgrokLastErrorCodeDesc})"); } return NgrokAddress; diff --git a/NebulaNetwork/Server.cs b/NebulaNetwork/Server.cs index 4b018736c..523162a4b 100644 --- a/NebulaNetwork/Server.cs +++ b/NebulaNetwork/Server.cs @@ -77,6 +77,7 @@ public Server(ushort port, bool loadSaveFile = false) public bool NgrokActive => ngrokManager.IsNgrokActive(); public bool NgrokEnabled => ngrokManager.NgrokEnabled; public string NgrokLastErrorCode => ngrokManager.NgrokLastErrorCode; + public string NgrokLastErrorCodeDesc => ngrokManager.NgrokLastErrorCodeDesc; public event EventHandler Connected; public event EventHandler Disconnected; diff --git a/NebulaWorld/Chat/Commands/InfoCommandHandler.cs b/NebulaWorld/Chat/Commands/InfoCommandHandler.cs index 397506200..ec9f9237e 100644 --- a/NebulaWorld/Chat/Commands/InfoCommandHandler.cs +++ b/NebulaWorld/Chat/Commands/InfoCommandHandler.cs @@ -18,7 +18,7 @@ namespace NebulaWorld.Chat.Commands; public class InfoCommandHandler : IChatCommandHandler { - private static readonly string[] s_separator = { "]:" }; + private static readonly string[] s_separator = ["]:"]; public void Execute(ChatWindow window, string[] parameters) { @@ -73,7 +73,7 @@ public string GetDescription() public string[] GetUsage() { - return new[] { "[full]" }; + return ["[full]"]; } public static string GetServerInfoText(IServer server, IPUtils.IpInfo ipInfo, bool full) @@ -105,17 +105,17 @@ public static string GetServerInfoText(IServer server, IPUtils.IpInfo ipInfo, bo { if (server.NgrokActive) { - sb.Append("\n ").Append("Ngrok address: ".Translate()) + sb.Append("\n ").Append("Ngrok address: ".Translate()) .Append(FormatCopyString(server.NgrokAddress, true, NgrokAddressFilter)); } else { - sb.Append("\n ").Append("Ngrok address: Tunnel Inactive!".Translate()); + sb.Append("\n ").Append("Ngrok address: Tunnel Inactive!".Translate()); } - if (server.NgrokLastErrorCode != null) + if (!string.IsNullOrWhiteSpace(server.NgrokLastErrorCode)) { - sb.Append($" ({FormatCopyString(server.NgrokLastErrorCode)})"); + sb.Append($" ({FormatCopyString(server.NgrokLastErrorCode)}){FormatCopyString(server.NgrokLastErrorCodeDesc)}"); } } From 952fd5737259b6e1c8472966d0e65f4659302d88 Mon Sep 17 00:00:00 2001 From: Chris Yeninas <844685+PhantomGamers@users.noreply.github.com> Date: Wed, 5 Jun 2024 08:03:30 -0400 Subject: [PATCH 6/8] Update NgrokManager.cs --- NebulaNetwork/Ngrok/NgrokManager.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/NebulaNetwork/Ngrok/NgrokManager.cs b/NebulaNetwork/Ngrok/NgrokManager.cs index e00898d2d..2f574621a 100644 --- a/NebulaNetwork/Ngrok/NgrokManager.cs +++ b/NebulaNetwork/Ngrok/NgrokManager.cs @@ -113,14 +113,14 @@ public NgrokManager(int port, string authToken = null, string region = null) if (!StartNgrok()) { Log.WarnInform( - string.Format("Failed to start Ngrok tunnel! LastErrorCode: {0}".Translate(), NgrokLastErrorCode)); + string.Format("Failed to start Ngrok tunnel! LastErrorCode: {0} {1}".Translate(), NgrokLastErrorCode, NgrokLastErrorCodeDesc)); return; } if (!IsNgrokActive()) { - Log.WarnInform(string.Format("Ngrok tunnel has exited prematurely! LastErrorCode: {0}".Translate(), - NgrokLastErrorCode)); + Log.WarnInform(string.Format("Ngrok tunnel has exited prematurely! LastErrorCode: {0} {1}".Translate(), + NgrokLastErrorCode, NgrokLastErrorCodeDesc)); } }); } @@ -313,13 +313,13 @@ public Task GetNgrokAddressAsync() if (!IsNgrokActive()) { throw new Exception( - $"Not able to get Ngrok tunnel address because Ngrok is not started (or exited prematurely)! LastErrorCode: {NgrokLastErrorCode}"); + $"Not able to get Ngrok tunnel address because Ngrok is not started (or exited prematurely)! LastErrorCode: {NgrokLastErrorCode} {NgrokLastErrorCodeDesc}"); } if (!_ngrokAddressObtainedSource.Task.Wait(TimeSpan.FromSeconds(15))) { throw new TimeoutException( - $"Not able to get Ngrok tunnel address because 15s timeout was exceeded! LastErrorCode: {NgrokLastErrorCode} ({NgrokLastErrorCodeDesc})"); + $"Not able to get Ngrok tunnel address because 15s timeout was exceeded! LastErrorCode: {NgrokLastErrorCode} {NgrokLastErrorCodeDesc}"); } return NgrokAddress; @@ -331,7 +331,7 @@ public async Task GetTunnelAddressFromAPI() if (!IsNgrokActive()) { throw new Exception( - $"Not able to get Ngrok tunnel address from API because Ngrok is not started (or exited prematurely)! LastErrorCode: {NgrokLastErrorCode}"); + $"Not able to get Ngrok tunnel address from API because Ngrok is not started (or exited prematurely)! LastErrorCode: {NgrokLastErrorCode} {NgrokLastErrorCodeDesc}"); } if (_ngrokAPIAddress == null) From 909ee66816f4ce0208015c2164eee3f4da101a18 Mon Sep 17 00:00:00 2001 From: Chris Yeninas <844685+PhantomGamers@users.noreply.github.com> Date: Wed, 5 Jun 2024 08:08:24 -0400 Subject: [PATCH 7/8] Update NgrokManager.cs add more common ngrok error descriptions --- NebulaNetwork/Ngrok/NgrokManager.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/NebulaNetwork/Ngrok/NgrokManager.cs b/NebulaNetwork/Ngrok/NgrokManager.cs index 2f574621a..d09bc5302 100644 --- a/NebulaNetwork/Ngrok/NgrokManager.cs +++ b/NebulaNetwork/Ngrok/NgrokManager.cs @@ -260,7 +260,9 @@ private void ErrorDataReceivedEventHandler(object sender, DataReceivedEventArgs NgrokLastErrorCode = errorCodeMatches[errorCodeMatches.Count - 1].Value; NgrokLastErrorCodeDesc = NgrokLastErrorCode switch { - "ERR_NGROK_105" => "Authtoken is invalid".Translate(), + "ERR_NGROK_105" => "Authtoken is empty or expired".Translate(), + "ERR_NGROK_108" => "Session limit reached".Translate(), + "ERR_NGROK_123" => "Account email not verified".Translate(), _ => string.Empty }; if (!string.IsNullOrWhiteSpace(NgrokLastErrorCodeDesc)) From c30b81169ea76416c05b14d43f40c5a5a9bfd553 Mon Sep 17 00:00:00 2001 From: Chris Yeninas <844685+PhantomGamers@users.noreply.github.com> Date: Wed, 5 Jun 2024 08:12:14 -0400 Subject: [PATCH 8/8] Update NgrokManager.cs --- NebulaNetwork/Ngrok/NgrokManager.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/NebulaNetwork/Ngrok/NgrokManager.cs b/NebulaNetwork/Ngrok/NgrokManager.cs index d09bc5302..fc1b11da8 100644 --- a/NebulaNetwork/Ngrok/NgrokManager.cs +++ b/NebulaNetwork/Ngrok/NgrokManager.cs @@ -265,10 +265,7 @@ private void ErrorDataReceivedEventHandler(object sender, DataReceivedEventArgs "ERR_NGROK_123" => "Account email not verified".Translate(), _ => string.Empty }; - if (!string.IsNullOrWhiteSpace(NgrokLastErrorCodeDesc)) - { - NgrokLastErrorCodeDesc = $"({NgrokLastErrorCodeDesc})"; - } + NgrokLastErrorCodeDesc = !string.IsNullOrWhiteSpace(NgrokLastErrorCodeDesc) ? $"({NgrokLastErrorCodeDesc})" : string.Empty; Log.WarnInform(string.Format("Ngrok Error! Code: {0} {1}".Translate(), NgrokLastErrorCode, NgrokLastErrorCodeDesc)); }