From be173e1d48b4f267001b5e115a0d081e38e34141 Mon Sep 17 00:00:00 2001 From: Marcel Baumgartner Date: Tue, 16 Apr 2024 07:40:48 +0200 Subject: [PATCH 1/6] Working on improved console streaming --- .../Core/Helpers/AdvancedWebsocketStream.cs | 169 ++++++++++++++++++ .../Features/Servers/Helpers/ServerConsole.cs | 20 +-- .../Http/Controllers/ServersControllers.cs | 13 +- Moonlight/Moonlight.csproj | 2 +- 4 files changed, 187 insertions(+), 17 deletions(-) create mode 100644 Moonlight/Core/Helpers/AdvancedWebsocketStream.cs diff --git a/Moonlight/Core/Helpers/AdvancedWebsocketStream.cs b/Moonlight/Core/Helpers/AdvancedWebsocketStream.cs new file mode 100644 index 0000000..5d43791 --- /dev/null +++ b/Moonlight/Core/Helpers/AdvancedWebsocketStream.cs @@ -0,0 +1,169 @@ +using System.Net.WebSockets; +using System.Text; +using MoonCore.Helpers; +using Newtonsoft.Json; + +namespace Moonlight.Core.Helpers; + +public class AdvancedWebsocketStream +{ + private readonly WebSocket Socket; + private readonly Dictionary Packets = new(); + + public AdvancedWebsocketStream(WebSocket socket) + { + Socket = socket; + } + + public void RegisterPacket(int id) => RegisterPacket(id, typeof(T)); + + public void RegisterPacket(int id, Type type) + { + Packets.Add(id, type); + } + + public async Task ReceivePacket() + { + if (Socket.State != WebSocketState.Open) + throw new ArgumentException("The websocket connection needs to be open in order to receive packets"); + + // Length + var lengthBuffer = new byte[4]; + await Socket.ReceiveAsync(lengthBuffer, CancellationToken.None); + var length = BitConverter.ToInt32(lengthBuffer); + + Logger.Debug($"Received length: {length}"); + + if (length <= 0) + throw new ArgumentException("The packet length cannot be less or equal than zero"); + + var packetBuffer = new byte[length]; + var received = await Socket.ReceiveAsync(packetBuffer, CancellationToken.None); + + Logger.Debug($"Lenght expected: {length}. Lenght got: {received.Count}"); + + return DecodePacket(packetBuffer); + } + + public async Task ReceivePacket() + { + var packet = await ReceivePacket(); + + if (packet == null) + return default; + + if (packet is not T) + throw new ArgumentException($"Received packet {packet.GetType().Name} matches not the type {typeof(T).Name}"); + + return (T)packet; + } + + public async Task SendPacket(object packet) + { + if (Socket.State != WebSocketState.Open) + throw new ArgumentException("The websocket connection needs to be open in order to send packets"); + + var buffer = EncodePacket(packet); + + // Send length + var length = buffer.Length; + var lengthBuffer = BitConverter.GetBytes(length); + + await Socket.SendAsync(lengthBuffer, WebSocketMessageType.Binary, WebSocketMessageFlags.None, + CancellationToken.None); + + // Send packet + await Socket.SendAsync(buffer, WebSocketMessageType.Binary, WebSocketMessageFlags.None, CancellationToken.None); + } + + public async Task WaitForClose() + { + var source = new TaskCompletionSource(); + + Task.Run(async () => + { + while (Socket.State == WebSocketState.Open) + await Task.Delay(10); + + source.SetResult(); + }); + + await source.Task; + } + + public async Task Close() + { + if(Socket.State == WebSocketState.Open) + await Socket.CloseOutputAsync(WebSocketCloseStatus.Empty, null, CancellationToken.None); + } + + private byte[] EncodePacket(object packet) + { + var type = packet.GetType(); + + var packetId = Packets.Values.Contains(type) ? Packets.First(x => x.Value == type).Key : -1; + + if (packetId == -1) + throw new ArgumentException($"Sending packet type which has not been registered: {packet.GetType().Name}"); + + // Header + var headerBuffer = BitConverter.GetBytes(packetId); + + // Body + var jsonText = JsonConvert.SerializeObject(packet); + var bodyBuffer = Encoding.UTF8.GetBytes(jsonText); + + return headerBuffer.Concat(bodyBuffer).ToArray(); + } + + private object? DecodePacket(byte[] buffer) + { + if (buffer.Length < 5) // 4 (header) + minimum 1 as body + { + Logger.Warn($"Received buffer is too small ({buffer.Length} bytes)"); + return default; + } + + var headerBuffer = new byte[4]; + Array.Copy(buffer, 0, headerBuffer, 0, 4); + var packetId = BitConverter.ToInt32(headerBuffer); + + Logger.Info($"Packet Id: {packetId}"); + + var packetType = Packets.TryGetValue(packetId, out var packet) ? packet : default; + + if (packetType == null) + { + Logger.Warn($"Received packet id which has not been registered: {packetId}"); + + Logger.Info("Packet dumped: " + Encoding.UTF8.GetString(buffer)); + + return default; + } + + var bodyBuffer = new byte[buffer.Length - 4]; + Array.Copy(buffer, 4, bodyBuffer, 0, buffer.Length - 4); + + var jsonText = Encoding.UTF8.GetString(bodyBuffer); + + if (string.IsNullOrEmpty(jsonText)) + { + Logger.Warn("Received empty json text"); + return default; + } + + object? result = default; + + try + { + result = JsonConvert.DeserializeObject(jsonText, packetType); + } + catch (JsonReaderException e) + { + Logger.Warn($"An error occured while deserializating the json text of the packet {packetType.Name}"); + Logger.Warn(e); + } + + return result; + } +} \ No newline at end of file diff --git a/Moonlight/Features/Servers/Helpers/ServerConsole.cs b/Moonlight/Features/Servers/Helpers/ServerConsole.cs index b1b9ec7..9c13b34 100644 --- a/Moonlight/Features/Servers/Helpers/ServerConsole.cs +++ b/Moonlight/Features/Servers/Helpers/ServerConsole.cs @@ -2,8 +2,8 @@ using MoonCore.Helpers; using Moonlight.Features.Servers.Api.Packets; using Moonlight.Features.Servers.Entities; -using Moonlight.Features.Servers.Models.Abstractions; using Moonlight.Features.Servers.Models.Enums; +using AdvancedWebsocketStream = Moonlight.Core.Helpers.AdvancedWebsocketStream; namespace Moonlight.Features.Servers.Helpers; @@ -23,7 +23,7 @@ public class ServerConsole private readonly Server Server; private ClientWebSocket WebSocket; - private WsPacketConnection PacketConnection; + private AdvancedWebsocketStream WebsocketStream; private CancellationTokenSource Cancellation = new(); @@ -50,11 +50,11 @@ public class ServerConsole wsUrl = $"ws://{Server.Node.Fqdn}:{Server.Node.HttpPort}/servers/{Server.Id}/ws"; await WebSocket.ConnectAsync(new Uri(wsUrl), CancellationToken.None); - PacketConnection = new WsPacketConnection(WebSocket); + WebsocketStream = new AdvancedWebsocketStream(WebSocket); - await PacketConnection.RegisterPacket("output"); - await PacketConnection.RegisterPacket("state"); - await PacketConnection.RegisterPacket("stats"); + WebsocketStream.RegisterPacket(1); + WebsocketStream.RegisterPacket(2); + WebsocketStream.RegisterPacket(3); Task.Run(Worker); } @@ -65,7 +65,7 @@ public class ServerConsole { try { - var packet = await PacketConnection.Receive(); + var packet = await WebsocketStream.ReceivePacket(); if (packet == null) continue; @@ -111,7 +111,7 @@ public class ServerConsole } await OnDisconnected.Invoke(); - await PacketConnection.Close(); + await WebsocketStream.Close(); } public async Task Close() @@ -119,8 +119,8 @@ public class ServerConsole if(!Cancellation.IsCancellationRequested) Cancellation.Cancel(); - if(PacketConnection != null) - await PacketConnection.Close(); + if(WebsocketStream != null) + await WebsocketStream.Close(); } private string[] GetMessageCache() diff --git a/Moonlight/Features/Servers/Http/Controllers/ServersControllers.cs b/Moonlight/Features/Servers/Http/Controllers/ServersControllers.cs index 9a7199b..ba3c5a9 100644 --- a/Moonlight/Features/Servers/Http/Controllers/ServersControllers.cs +++ b/Moonlight/Features/Servers/Http/Controllers/ServersControllers.cs @@ -8,6 +8,7 @@ using Moonlight.Features.Servers.Events; using Moonlight.Features.Servers.Extensions; using Moonlight.Features.Servers.Http.Requests; using Moonlight.Features.Servers.Models.Abstractions; +using AdvancedWebsocketStream = Moonlight.Core.Helpers.AdvancedWebsocketStream; namespace Moonlight.Features.Servers.Http.Controllers; @@ -36,9 +37,9 @@ public class ServersControllers : Controller var websocket = await HttpContext.WebSockets.AcceptWebSocketAsync(); // Build connection wrapper - var wsPacketConnection = new WsPacketConnection(websocket); - await wsPacketConnection.RegisterPacket("amount"); - await wsPacketConnection.RegisterPacket("serverConfiguration"); + var websocketStream = new AdvancedWebsocketStream(websocket); + websocketStream.RegisterPacket(1); + websocketStream.RegisterPacket(2); // Read server data for the node var node = (HttpContext.Items["Node"] as ServerNode)!; @@ -62,13 +63,13 @@ public class ServersControllers : Controller .ToArray(); // Send the amount of configs the node will receive - await wsPacketConnection.Send(servers.Length); + await websocketStream.SendPacket(servers.Length); // Send the server configurations foreach (var serverConfiguration in serverConfigurations) - await wsPacketConnection.Send(serverConfiguration); + await websocketStream.SendPacket(serverConfiguration); - await wsPacketConnection.WaitForClose(); + await websocketStream.WaitForClose(); return Ok(); } diff --git a/Moonlight/Moonlight.csproj b/Moonlight/Moonlight.csproj index f140329..7ac8423 100644 --- a/Moonlight/Moonlight.csproj +++ b/Moonlight/Moonlight.csproj @@ -90,7 +90,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + From f3ad71e33fcb704327e3c1d702e1308cbb784992 Mon Sep 17 00:00:00 2001 From: Marcel Baumgartner Date: Tue, 16 Apr 2024 22:56:42 +0200 Subject: [PATCH 2/6] Switched to improved mooncore advanced websocket stream version --- .../.idea/material_theme_project_new.xml | 13 ++ .../Core/Helpers/AdvancedWebsocketStream.cs | 169 ------------------ .../Features/Servers/Helpers/ServerConsole.cs | 1 - .../Http/Controllers/ServersControllers.cs | 1 - .../Servers/UI/UserViews/Console.razor | 3 - Moonlight/Moonlight.csproj | 2 +- 6 files changed, 14 insertions(+), 175 deletions(-) create mode 100644 .idea/.idea.Moonlight/.idea/material_theme_project_new.xml delete mode 100644 Moonlight/Core/Helpers/AdvancedWebsocketStream.cs diff --git a/.idea/.idea.Moonlight/.idea/material_theme_project_new.xml b/.idea/.idea.Moonlight/.idea/material_theme_project_new.xml new file mode 100644 index 0000000..1a83bdf --- /dev/null +++ b/.idea/.idea.Moonlight/.idea/material_theme_project_new.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/Moonlight/Core/Helpers/AdvancedWebsocketStream.cs b/Moonlight/Core/Helpers/AdvancedWebsocketStream.cs deleted file mode 100644 index 5d43791..0000000 --- a/Moonlight/Core/Helpers/AdvancedWebsocketStream.cs +++ /dev/null @@ -1,169 +0,0 @@ -using System.Net.WebSockets; -using System.Text; -using MoonCore.Helpers; -using Newtonsoft.Json; - -namespace Moonlight.Core.Helpers; - -public class AdvancedWebsocketStream -{ - private readonly WebSocket Socket; - private readonly Dictionary Packets = new(); - - public AdvancedWebsocketStream(WebSocket socket) - { - Socket = socket; - } - - public void RegisterPacket(int id) => RegisterPacket(id, typeof(T)); - - public void RegisterPacket(int id, Type type) - { - Packets.Add(id, type); - } - - public async Task ReceivePacket() - { - if (Socket.State != WebSocketState.Open) - throw new ArgumentException("The websocket connection needs to be open in order to receive packets"); - - // Length - var lengthBuffer = new byte[4]; - await Socket.ReceiveAsync(lengthBuffer, CancellationToken.None); - var length = BitConverter.ToInt32(lengthBuffer); - - Logger.Debug($"Received length: {length}"); - - if (length <= 0) - throw new ArgumentException("The packet length cannot be less or equal than zero"); - - var packetBuffer = new byte[length]; - var received = await Socket.ReceiveAsync(packetBuffer, CancellationToken.None); - - Logger.Debug($"Lenght expected: {length}. Lenght got: {received.Count}"); - - return DecodePacket(packetBuffer); - } - - public async Task ReceivePacket() - { - var packet = await ReceivePacket(); - - if (packet == null) - return default; - - if (packet is not T) - throw new ArgumentException($"Received packet {packet.GetType().Name} matches not the type {typeof(T).Name}"); - - return (T)packet; - } - - public async Task SendPacket(object packet) - { - if (Socket.State != WebSocketState.Open) - throw new ArgumentException("The websocket connection needs to be open in order to send packets"); - - var buffer = EncodePacket(packet); - - // Send length - var length = buffer.Length; - var lengthBuffer = BitConverter.GetBytes(length); - - await Socket.SendAsync(lengthBuffer, WebSocketMessageType.Binary, WebSocketMessageFlags.None, - CancellationToken.None); - - // Send packet - await Socket.SendAsync(buffer, WebSocketMessageType.Binary, WebSocketMessageFlags.None, CancellationToken.None); - } - - public async Task WaitForClose() - { - var source = new TaskCompletionSource(); - - Task.Run(async () => - { - while (Socket.State == WebSocketState.Open) - await Task.Delay(10); - - source.SetResult(); - }); - - await source.Task; - } - - public async Task Close() - { - if(Socket.State == WebSocketState.Open) - await Socket.CloseOutputAsync(WebSocketCloseStatus.Empty, null, CancellationToken.None); - } - - private byte[] EncodePacket(object packet) - { - var type = packet.GetType(); - - var packetId = Packets.Values.Contains(type) ? Packets.First(x => x.Value == type).Key : -1; - - if (packetId == -1) - throw new ArgumentException($"Sending packet type which has not been registered: {packet.GetType().Name}"); - - // Header - var headerBuffer = BitConverter.GetBytes(packetId); - - // Body - var jsonText = JsonConvert.SerializeObject(packet); - var bodyBuffer = Encoding.UTF8.GetBytes(jsonText); - - return headerBuffer.Concat(bodyBuffer).ToArray(); - } - - private object? DecodePacket(byte[] buffer) - { - if (buffer.Length < 5) // 4 (header) + minimum 1 as body - { - Logger.Warn($"Received buffer is too small ({buffer.Length} bytes)"); - return default; - } - - var headerBuffer = new byte[4]; - Array.Copy(buffer, 0, headerBuffer, 0, 4); - var packetId = BitConverter.ToInt32(headerBuffer); - - Logger.Info($"Packet Id: {packetId}"); - - var packetType = Packets.TryGetValue(packetId, out var packet) ? packet : default; - - if (packetType == null) - { - Logger.Warn($"Received packet id which has not been registered: {packetId}"); - - Logger.Info("Packet dumped: " + Encoding.UTF8.GetString(buffer)); - - return default; - } - - var bodyBuffer = new byte[buffer.Length - 4]; - Array.Copy(buffer, 4, bodyBuffer, 0, buffer.Length - 4); - - var jsonText = Encoding.UTF8.GetString(bodyBuffer); - - if (string.IsNullOrEmpty(jsonText)) - { - Logger.Warn("Received empty json text"); - return default; - } - - object? result = default; - - try - { - result = JsonConvert.DeserializeObject(jsonText, packetType); - } - catch (JsonReaderException e) - { - Logger.Warn($"An error occured while deserializating the json text of the packet {packetType.Name}"); - Logger.Warn(e); - } - - return result; - } -} \ No newline at end of file diff --git a/Moonlight/Features/Servers/Helpers/ServerConsole.cs b/Moonlight/Features/Servers/Helpers/ServerConsole.cs index 9c13b34..87d92f8 100644 --- a/Moonlight/Features/Servers/Helpers/ServerConsole.cs +++ b/Moonlight/Features/Servers/Helpers/ServerConsole.cs @@ -3,7 +3,6 @@ using MoonCore.Helpers; using Moonlight.Features.Servers.Api.Packets; using Moonlight.Features.Servers.Entities; using Moonlight.Features.Servers.Models.Enums; -using AdvancedWebsocketStream = Moonlight.Core.Helpers.AdvancedWebsocketStream; namespace Moonlight.Features.Servers.Helpers; diff --git a/Moonlight/Features/Servers/Http/Controllers/ServersControllers.cs b/Moonlight/Features/Servers/Http/Controllers/ServersControllers.cs index ba3c5a9..67ff35e 100644 --- a/Moonlight/Features/Servers/Http/Controllers/ServersControllers.cs +++ b/Moonlight/Features/Servers/Http/Controllers/ServersControllers.cs @@ -8,7 +8,6 @@ using Moonlight.Features.Servers.Events; using Moonlight.Features.Servers.Extensions; using Moonlight.Features.Servers.Http.Requests; using Moonlight.Features.Servers.Models.Abstractions; -using AdvancedWebsocketStream = Moonlight.Core.Helpers.AdvancedWebsocketStream; namespace Moonlight.Features.Servers.Http.Controllers; diff --git a/Moonlight/Features/Servers/UI/UserViews/Console.razor b/Moonlight/Features/Servers/UI/UserViews/Console.razor index 79544e3..f8205ff 100644 --- a/Moonlight/Features/Servers/UI/UserViews/Console.razor +++ b/Moonlight/Features/Servers/UI/UserViews/Console.razor @@ -1,4 +1,3 @@ -@using Moonlight.Features.Servers.Models.Abstractions @using Moonlight.Features.Servers.Services @using Moonlight.Features.Servers.UI.Components @using Moonlight.Features.Servers.Entities @@ -6,7 +5,6 @@ @using Moonlight.Features.Servers.Api.Packets @using Moonlight.Features.Servers.Models.Enums @using MoonCore.Helpers -@using ApexCharts @inject ServerService ServerService @@ -85,7 +83,6 @@ ServerConsole.OnNewMessage += OnMessage; - ServerConsole.OnStatsChange += HandleStats; ServerConsole.OnStateChange += HandleState; } diff --git a/Moonlight/Moonlight.csproj b/Moonlight/Moonlight.csproj index 7ac8423..e37cfbe 100644 --- a/Moonlight/Moonlight.csproj +++ b/Moonlight/Moonlight.csproj @@ -90,7 +90,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + From 48e2e1eb982af37f546492c4b19ed87f76b29491 Mon Sep 17 00:00:00 2001 From: Marcel Baumgartner Date: Wed, 17 Apr 2024 07:31:56 +0200 Subject: [PATCH 3/6] Fixed weird console restore glitch --- Moonlight/Features/Servers/UI/UserViews/Console.razor | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Moonlight/Features/Servers/UI/UserViews/Console.razor b/Moonlight/Features/Servers/UI/UserViews/Console.razor index f8205ff..8197df6 100644 --- a/Moonlight/Features/Servers/UI/UserViews/Console.razor +++ b/Moonlight/Features/Servers/UI/UserViews/Console.razor @@ -77,11 +77,13 @@ var text = ""; foreach (var line in ServerConsole.Messages.TakeLast(50)) - text += line + "\n\r"; + { + var lineModified = line.Replace("\n", "\n\r"); + text += lineModified; + } await Terminal.Write(text); - ServerConsole.OnNewMessage += OnMessage; ServerConsole.OnStatsChange += HandleStats; ServerConsole.OnStateChange += HandleState; @@ -105,7 +107,7 @@ private async Task OnMessage(string message) { - await Terminal.WriteLine(message); + await Terminal.Write(message + "\n\r"); } private async Task SendCommand() From 610501ef1998dfec8d97f163e601cb7d98459175 Mon Sep 17 00:00:00 2001 From: Marcel Baumgartner Date: Wed, 17 Apr 2024 07:49:48 +0200 Subject: [PATCH 4/6] Improved console ui disposing --- Moonlight/Features/Servers/Helpers/ServerConsole.cs | 12 +++++++++++- .../Features/Servers/UI/Layouts/UserLayout.razor | 3 +++ .../Features/Servers/UI/UserViews/Console.razor | 2 +- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Moonlight/Features/Servers/Helpers/ServerConsole.cs b/Moonlight/Features/Servers/Helpers/ServerConsole.cs index 87d92f8..c116526 100644 --- a/Moonlight/Features/Servers/Helpers/ServerConsole.cs +++ b/Moonlight/Features/Servers/Helpers/ServerConsole.cs @@ -6,7 +6,7 @@ using Moonlight.Features.Servers.Models.Enums; namespace Moonlight.Features.Servers.Helpers; -public class ServerConsole +public class ServerConsole : IDisposable { public SmartEventHandler OnStateChange { get; set; } = new(); public SmartEventHandler OnStatsChange { get; set; } = new(); @@ -127,4 +127,14 @@ public class ServerConsole lock (MessageCache) return MessageCache.ToArray(); } + + public async void Dispose() + { + MessageCache.Clear(); + + if (WebSocket.State == WebSocketState.Open) + await WebsocketStream.Close(); + + WebSocket.Dispose(); + } } \ No newline at end of file diff --git a/Moonlight/Features/Servers/UI/Layouts/UserLayout.razor b/Moonlight/Features/Servers/UI/Layouts/UserLayout.razor index 905cfab..014d92a 100644 --- a/Moonlight/Features/Servers/UI/Layouts/UserLayout.razor +++ b/Moonlight/Features/Servers/UI/Layouts/UserLayout.razor @@ -308,7 +308,10 @@ await UpdateTimer.DisposeAsync(); if (Console != null) + { await Console.Close(); + Console.Dispose(); + } } private int GetIndex() diff --git a/Moonlight/Features/Servers/UI/UserViews/Console.razor b/Moonlight/Features/Servers/UI/UserViews/Console.razor index 8197df6..fe50781 100644 --- a/Moonlight/Features/Servers/UI/UserViews/Console.razor +++ b/Moonlight/Features/Servers/UI/UserViews/Console.razor @@ -79,7 +79,7 @@ foreach (var line in ServerConsole.Messages.TakeLast(50)) { var lineModified = line.Replace("\n", "\n\r"); - text += lineModified; + text += lineModified + "\n\r"; } await Terminal.Write(text); From dcfb836b396c23b18169626bc1f64bfba8515aa5 Mon Sep 17 00:00:00 2001 From: Marcel Baumgartner Date: Wed, 17 Apr 2024 15:42:23 +0200 Subject: [PATCH 5/6] Added some documentation it triggered me that this was missing, okay? --- Moonlight/Core/Http/Controllers/AvatarController.cs | 6 +++--- Moonlight/Core/Services/DiagnoseService.cs | 3 +++ Moonlight/Core/Services/UnloadService.cs | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Moonlight/Core/Http/Controllers/AvatarController.cs b/Moonlight/Core/Http/Controllers/AvatarController.cs index 617363d..1b235ff 100644 --- a/Moonlight/Core/Http/Controllers/AvatarController.cs +++ b/Moonlight/Core/Http/Controllers/AvatarController.cs @@ -55,9 +55,9 @@ public class AvatarController : Controller if (!IdentityService.IsLoggedIn) return StatusCode(403); - if (ConfigService.Get().Security.EnforceAvatarPrivacy && - id != IdentityService.CurrentUser.Id && - IdentityService.CurrentUser.Permissions < 1000) + if (ConfigService.Get().Security.EnforceAvatarPrivacy && // Do we need to enforce privacy? + id != IdentityService.CurrentUser.Id && // is the user not viewing his own image? + IdentityService.CurrentUser.Permissions < 1000) // and not an admin? { return StatusCode(403); } diff --git a/Moonlight/Core/Services/DiagnoseService.cs b/Moonlight/Core/Services/DiagnoseService.cs index a38bbe3..b76bbc2 100644 --- a/Moonlight/Core/Services/DiagnoseService.cs +++ b/Moonlight/Core/Services/DiagnoseService.cs @@ -22,13 +22,16 @@ public class DiagnoseService { using var scope = ServiceProvider.CreateScope(); + // Create in memory zip archive using var dataStream = new MemoryStream(); var zipArchive = new ZipArchive(dataStream, ZipArchiveMode.Create, true); + // Call every plugin to perform their modifications to the file await PluginService.ExecuteFuncAsync( async x => await x.GenerateReport(zipArchive, scope.ServiceProvider) ); + // Add a timestamp await zipArchive.AddText("exported_at.txt", Formatter.FormatDate(DateTime.UtcNow)); zipArchive.Dispose(); diff --git a/Moonlight/Core/Services/UnloadService.cs b/Moonlight/Core/Services/UnloadService.cs index 6da5863..d62ced4 100644 --- a/Moonlight/Core/Services/UnloadService.cs +++ b/Moonlight/Core/Services/UnloadService.cs @@ -5,7 +5,7 @@ using MoonCore.Helpers; namespace Moonlight.Core.Services; /// -/// This class provides a event to execute code when a user leaves the page +/// This class provides an event to execute code when a user leaves the page /// [Scoped] From 90eed5c74c95338f6f0794624a9fe3976781a2cc Mon Sep 17 00:00:00 2001 From: Marcel Baumgartner Date: Wed, 17 Apr 2024 15:42:51 +0200 Subject: [PATCH 6/6] Fixed a bug. Improved error handling. Small cleanup of code --- .../Features/Servers/Helpers/ServerConsole.cs | 6 +- .../Servers/UI/Layouts/UserLayout.razor | 85 ++++++++++--------- Moonlight/Moonlight.csproj | 4 +- 3 files changed, 51 insertions(+), 44 deletions(-) diff --git a/Moonlight/Features/Servers/Helpers/ServerConsole.cs b/Moonlight/Features/Servers/Helpers/ServerConsole.cs index c116526..cd10375 100644 --- a/Moonlight/Features/Servers/Helpers/ServerConsole.cs +++ b/Moonlight/Features/Servers/Helpers/ServerConsole.cs @@ -99,9 +99,11 @@ public class ServerConsole : IDisposable } catch (Exception e) { - if (e is not WebSocketException) + if (e is WebSocketException) + Logger.Warn($"Lost connection to daemon server websocket: {e.Message}"); + else { - Logger.Warn("Lost connection to daemon server websocket"); + Logger.Warn("Server console ws disconnected because of application error:"); Logger.Warn(e); } diff --git a/Moonlight/Features/Servers/UI/Layouts/UserLayout.razor b/Moonlight/Features/Servers/UI/Layouts/UserLayout.razor index 014d92a..815e9df 100644 --- a/Moonlight/Features/Servers/UI/Layouts/UserLayout.razor +++ b/Moonlight/Features/Servers/UI/Layouts/UserLayout.razor @@ -113,13 +113,7 @@
- @if (IsInstalling) - { -
- -
- } - else if (IsConsoleDisconnected) + @if (IsConsoleDisconnected) { We lost the connection to the server. Please refresh the page in order to retry. If this error persists please contact the support @@ -137,6 +131,12 @@ The node this server is on is still booting. Please refresh the page in order to retry. If this error persists please contact the support } + else if (IsInstalling) + { +
+ +
+ } else { @@ -217,37 +217,7 @@ Console = new ServerConsole(Server); // Configure - Console.OnStateChange += async state => - { - // General rerender to update the state text in the ui - // NOTE: Obsolete because of the update timer - //await InvokeAsync(StateHasChanged); - - // Change from offline to installing - // This will trigger the initialisation of the install view - if (state == ServerState.Installing && !IsInstalling) - { - IsInstalling = true; - - // After this call, we should have access to the install terminal reference - await InvokeAsync(StateHasChanged); - - Console.OnNewMessage += OnInstallConsoleMessage; - } - // Change from installing to offline - // This will trigger the destruction of the install view - else if (state == ServerState.Offline && IsInstalling) - { - IsInstalling = false; - - Console.OnNewMessage -= OnInstallConsoleMessage; - - // After this call, the install terminal will disappear - await InvokeAsync(StateHasChanged); - - await ToastService.Info("Server installation complete"); - } - }; + Console.OnStateChange += async state => await HandleStateChange(state); Console.OnDisconnected += async () => { @@ -267,7 +237,7 @@ await InvokeAsync(StateHasChanged); return; } - + // We want to check if its an connection error, if yes we want to show the user that its an error with the connection // If not we proceed with the throwing for the soft error handler. @@ -288,6 +258,41 @@ } UpdateTimer = new Timer(async _ => { await InvokeAsync(StateHasChanged); }, null, TimeSpan.Zero, TimeSpan.FromSeconds(1)); + + var state = await ServerService.GetState(Server); + await HandleStateChange(state); + } + + private async Task HandleStateChange(ServerState state) + { + // General rerender to update the state text in the ui + // NOTE: Obsolete because of the update timer + //await InvokeAsync(StateHasChanged); + + // Change from offline to installing + // This will trigger the initialisation of the install view + if (state == ServerState.Installing && !IsInstalling) + { + IsInstalling = true; + + // After this call, we should have access to the install terminal reference + await InvokeAsync(StateHasChanged); + + Console.OnNewMessage += OnInstallConsoleMessage; + } + // Change from installing to offline + // This will trigger the destruction of the install view + else if (state == ServerState.Offline && IsInstalling) + { + IsInstalling = false; + + Console.OnNewMessage -= OnInstallConsoleMessage; + + // After this call, the install terminal will disappear + await InvokeAsync(StateHasChanged); + + await ToastService.Info("Server installation complete"); + } } private async Task OnInstallConsoleMessage(string message) @@ -334,7 +339,7 @@ case "/network": return 2; - + case "/schedules": return 7; diff --git a/Moonlight/Moonlight.csproj b/Moonlight/Moonlight.csproj index e37cfbe..df200a7 100644 --- a/Moonlight/Moonlight.csproj +++ b/Moonlight/Moonlight.csproj @@ -74,8 +74,7 @@ - - + @@ -114,6 +113,7 @@ <_ContentIncludedByDefault Remove="Features\FileManager\UI\Components\FileManager.razor" /> <_ContentIncludedByDefault Remove="Features\FileManager\UI\Components\FileUploader.razor" /> <_ContentIncludedByDefault Remove="Features\FileManager\UI\Components\FileView.razor" /> + <_ContentIncludedByDefault Remove="storage\configs\core.json" />