Switched to improved mooncore advanced websocket stream version

This commit is contained in:
Marcel Baumgartner 2024-04-16 22:56:42 +02:00
parent be173e1d48
commit f3ad71e33f
6 changed files with 14 additions and 175 deletions

View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MaterialThemeProjectNewConfig">
<option name="metadata">
<MTProjectMetadataState>
<option name="migrated" value="true" />
<option name="pristineConfig" value="false" />
<option name="userId" value="52a374ed:18c1029d858:-8000" />
<option name="version" value="8.13.2" />
</MTProjectMetadataState>
</option>
</component>
</project>

View file

@ -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<int, Type> Packets = new();
public AdvancedWebsocketStream(WebSocket socket)
{
Socket = socket;
}
public void RegisterPacket<T>(int id) => RegisterPacket(id, typeof(T));
public void RegisterPacket(int id, Type type)
{
Packets.Add(id, type);
}
public async Task<object?> 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<T?> ReceivePacket<T>()
{
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;
}
}

View file

@ -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;

View file

@ -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;

View file

@ -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;
}

View file

@ -90,7 +90,7 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="MoonCore" Version="1.2.4" />
<PackageReference Include="MoonCore" Version="1.2.7" />
<PackageReference Include="MoonCoreUI" Version="1.1.5" />
<PackageReference Include="Otp.NET" Version="1.3.0" />
<PackageReference Include="QRCoder" Version="1.4.3" />