From 32ed6c3b1ddfa4f7f8ee80239efff53505579912 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A7=8B=E9=9B=A8=E8=90=BD?= Date: Wed, 10 Jan 2024 10:46:16 +0800 Subject: [PATCH] :sparkles: Client library. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 秋雨落 --- CrystalConnector.Client/ConnectorClient.cs | 99 +++++++++++++++++++ .../CrystalConnector.Client.csproj | 24 +++++ .../Extensions/WebsocketClientExtension.cs | 12 +++ .../Entities/NamespacedId.cs | 20 ++++ .../Utilities/NamespacedNameExtensions.cs | 12 +++ .../Utilities/PacketHelperExtensions.cs | 25 ----- 6 files changed, 167 insertions(+), 25 deletions(-) create mode 100644 CrystalConnector.Client/ConnectorClient.cs create mode 100644 CrystalConnector.Client/CrystalConnector.Client.csproj create mode 100644 CrystalConnector.Client/Extensions/WebsocketClientExtension.cs create mode 100644 CrystalConnector.Protocol/Entities/NamespacedId.cs create mode 100644 CrystalConnector.Protocol/Utilities/NamespacedNameExtensions.cs delete mode 100644 CrystalConnector.Protocol/Utilities/PacketHelperExtensions.cs diff --git a/CrystalConnector.Client/ConnectorClient.cs b/CrystalConnector.Client/ConnectorClient.cs new file mode 100644 index 0000000..a934307 --- /dev/null +++ b/CrystalConnector.Client/ConnectorClient.cs @@ -0,0 +1,99 @@ +using System.Net.WebSockets; +using System.Reactive.Linq; +using CrystalConnector.Client.Extensions; +using CrystalConnector.Protocol.Entities; +using CrystalConnector.Protocol.Messages; +using CrystalConnector.Protocol.Packets; +using CrystalConnector.Protocol.Packets.C2S; +using CrystalConnector.Protocol.Packets.S2C; +using Microsoft.Extensions.Logging; +using Websocket.Client; + +namespace CrystalConnector.Client; + +public class ConnectorClient +{ + public delegate void PayloadHandler(ConnectorClient client, ForwardPacket packet); + + public event PayloadHandler? OnPayload; + + private WebsocketClient Client { get; } + + private List Channels { get; } = new(); + + private ILogger? Logger { get; } + + public ConnectorClient(NamespacedId id, string name, string key, + IEnumerable> channels, Uri uri) + { + Client = new WebsocketClient(uri); + + Channels.AddRange(channels.Select(ch => new Channel + { + Id = ch.Item1.ToName(), + Direction = ch.Item2 + }).ToList()); + + Client.ReconnectTimeout = null; + Client.ReconnectionHappened.Subscribe(info => + { + Logger?.LogInformation("Connected! Type: {Type}", info.Type); + + var packet = new AuthenticatePacket(id.ToName(), name, key, Channels); + Client.Send(packet); + }); + + Client.MessageReceived.Where(msg => msg.MessageType == WebSocketMessageType.Binary) + .Subscribe(message => + { + try + { + var packet = IPacket.From(message.Binary!); + switch (packet) + { + case ForwardPacket forwardPacket: + { + OnPayload?.Invoke(this, forwardPacket); + break; + } + case ResultPacket resultPacket: + { + if (resultPacket.ResultOneofCase != Result.ResultOneofCase.Successful) + { + Logger?.LogWarning("Warn {Error}", resultPacket.Error.ToString()); + } + break; + } + } + } + catch (Exception ex) + { + Logger?.LogWarning(ex, "Bad packet!"); + } + }); + } + + public ConnectorClient(NamespacedId id, string name, string key, + IEnumerable> channels, Uri uri, ILogger logger) + : this(id, name, key, channels, uri) + { + Logger = logger; + } + + public async Task Start() + { + Logger?.LogInformation("Connector connecting..."); + await Client.Start(); + } + + public async Task Stop() + { + Logger?.LogInformation("Connector disconnecting..."); + await Client.Stop(WebSocketCloseStatus.NormalClosure, ""); + } + + public void Send(NamespacedId channel, string payload) + { + Client.Send(new PublishPacket(channel, payload)); + } +} \ No newline at end of file diff --git a/CrystalConnector.Client/CrystalConnector.Client.csproj b/CrystalConnector.Client/CrystalConnector.Client.csproj new file mode 100644 index 0000000..30e76da --- /dev/null +++ b/CrystalConnector.Client/CrystalConnector.Client.csproj @@ -0,0 +1,24 @@ + + + + net8.0 + enable + enable + True + qyl27,MeowCraftMC + https://github.com/MeowCraftMC/CrystalConnector + Apache-2.0 + True + True + https://github.com/MeowCraftMC/CrystalConnector + + + + + + + + + + + diff --git a/CrystalConnector.Client/Extensions/WebsocketClientExtension.cs b/CrystalConnector.Client/Extensions/WebsocketClientExtension.cs new file mode 100644 index 0000000..615318e --- /dev/null +++ b/CrystalConnector.Client/Extensions/WebsocketClientExtension.cs @@ -0,0 +1,12 @@ +using CrystalConnector.Protocol.Packets; +using Websocket.Client; + +namespace CrystalConnector.Client.Extensions; + +public static class WebsocketClientExtension +{ + public static void Send(this WebsocketClient client, IPacket packet) + { + client.Send(packet.Write()); + } +} \ No newline at end of file diff --git a/CrystalConnector.Protocol/Entities/NamespacedId.cs b/CrystalConnector.Protocol/Entities/NamespacedId.cs new file mode 100644 index 0000000..bd46d1f --- /dev/null +++ b/CrystalConnector.Protocol/Entities/NamespacedId.cs @@ -0,0 +1,20 @@ +using CrystalConnector.Protocol.Messages; + +namespace CrystalConnector.Protocol.Entities; + +public record NamespacedId(string Namespace, string Name) +{ + public NamespacedName ToName() + { + return new NamespacedName + { + Namespace = Namespace, + Name = Name + }; + } + + public override string ToString() + { + return $"{Namespace}:{Name}"; + } +} \ No newline at end of file diff --git a/CrystalConnector.Protocol/Utilities/NamespacedNameExtensions.cs b/CrystalConnector.Protocol/Utilities/NamespacedNameExtensions.cs new file mode 100644 index 0000000..b2edb55 --- /dev/null +++ b/CrystalConnector.Protocol/Utilities/NamespacedNameExtensions.cs @@ -0,0 +1,12 @@ +using CrystalConnector.Protocol.Entities; +using CrystalConnector.Protocol.Messages; + +namespace CrystalConnector.Protocol.Utilities; + +public static class NamespacedNameExtensions +{ + public static NamespacedId ToId(this NamespacedName name) + { + return new NamespacedId(name.Namespace, name.Name); + } +} \ No newline at end of file diff --git a/CrystalConnector.Protocol/Utilities/PacketHelperExtensions.cs b/CrystalConnector.Protocol/Utilities/PacketHelperExtensions.cs deleted file mode 100644 index f781221..0000000 --- a/CrystalConnector.Protocol/Utilities/PacketHelperExtensions.cs +++ /dev/null @@ -1,25 +0,0 @@ -using CrystalConnector.Protocol.Messages; - -namespace CrystalConnector.Protocol.Utilities; - -public static class PacketHelperExtensions -{ - public static (string Namespace, string Name) ToTuple(this NamespacedName name) - { - return (name.Namespace, name.Name); - } - - public static NamespacedName ToName(this (string Namespace, string Name) name) - { - return new NamespacedName - { - Namespace = name.Namespace, - Name = name.Name - }; - } - - public static string ToIdString(this (string Namespace, string Name) name) - { - return $"{name.Namespace}:{name.Name}"; - } -} \ No newline at end of file