From d823b88cd825bffea65b5e45bfcff4799125e640 Mon Sep 17 00:00:00 2001 From: nexus4880 <38168516+nexus4880@users.noreply.github.com> Date: Wed, 23 Oct 2024 22:13:21 -0700 Subject: [PATCH] Initial commit --- .../PushNotiferGetWebsocketController.cs | 23 +++++++++ Fuyu.Backend.EFT/Servers/EftMainServer.cs | 4 ++ Fuyu.Common/Networking/HttpServer.cs | 3 +- Fuyu.Common/Networking/WsContext.cs | 51 +++++++++++++------ Fuyu.Common/Networking/WsController.cs | 18 +++---- Fuyu.Common/Networking/WsRouter.cs | 21 ++++++-- 6 files changed, 86 insertions(+), 34 deletions(-) create mode 100644 Fuyu.Backend.EFT/Controllers/PushNotiferGetWebsocketController.cs diff --git a/Fuyu.Backend.EFT/Controllers/PushNotiferGetWebsocketController.cs b/Fuyu.Backend.EFT/Controllers/PushNotiferGetWebsocketController.cs new file mode 100644 index 0000000..82c7c1d --- /dev/null +++ b/Fuyu.Backend.EFT/Controllers/PushNotiferGetWebsocketController.cs @@ -0,0 +1,23 @@ +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using Fuyu.Common.Networking; + +namespace Fuyu.Backend.EFT.Controllers +{ + public partial class PushNotiferGetWebsocketController : WsController + { + public PushNotiferGetWebsocketController() : base(PathExpression()) + { + } + + // NOTE: No event registrations as I am not implementing anything + // -- nexus4880, 2024-10-23 + public override Task RunAsync(WsContext context) + { + return Task.CompletedTask; + } + + [GeneratedRegex("^/push/notifier/getwebsocket/(?[A-Za-z0-9]+)$")] + private static partial Regex PathExpression(); + } +} \ No newline at end of file diff --git a/Fuyu.Backend.EFT/Servers/EftMainServer.cs b/Fuyu.Backend.EFT/Servers/EftMainServer.cs index 9891451..11d311e 100644 --- a/Fuyu.Backend.EFT/Servers/EftMainServer.cs +++ b/Fuyu.Backend.EFT/Servers/EftMainServer.cs @@ -14,6 +14,7 @@ public void RegisterServices() // Custom HttpRouter.AddController(); HttpRouter.AddController(); + // EFT HttpRouter.AddController(); HttpRouter.AddController(); @@ -69,6 +70,9 @@ public void RegisterServices() HttpRouter.AddController(); HttpRouter.AddController(); HttpRouter.AddController(); + + // EFT WS + WsRouter.AddController(); } } } \ No newline at end of file diff --git a/Fuyu.Common/Networking/HttpServer.cs b/Fuyu.Common/Networking/HttpServer.cs index 6af83e4..92c4837 100644 --- a/Fuyu.Common/Networking/HttpServer.cs +++ b/Fuyu.Common/Networking/HttpServer.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Net; using System.Threading; using System.Threading.Tasks; @@ -82,10 +83,8 @@ private async Task OnWsRequestAsync(HttpListenerContext listenerContext) try { var context = new WsContext(listenerContext.Request, listenerContext.Response, ws); - var time = DateTime.UtcNow.ToString(); Terminal.WriteLine($"[{time}][{Name}][WS ] {context.Path}"); - await WsRouter.RouteAsync(context); } catch (Exception ex) diff --git a/Fuyu.Common/Networking/WsContext.cs b/Fuyu.Common/Networking/WsContext.cs index 185678e..6a3ee19 100644 --- a/Fuyu.Common/Networking/WsContext.cs +++ b/Fuyu.Common/Networking/WsContext.cs @@ -12,9 +12,13 @@ public class WsContext : WebRouterContext private const int _bufferSize = 32000; private readonly WebSocket _ws; - public Func OnCloseAsync; - public Func OnTextAsync; - public Func OnBinaryAsync; + public delegate Task OnTextEventHandler(WsContext sender, string text); + public delegate Task OnBinaryEventHandler(WsContext sender, byte[] binary); + public delegate Task OnCloseEventHandler(WsContext sender); + + public event OnTextEventHandler OnTextEvent; + public event OnBinaryEventHandler OnBinaryEvent; + public event OnCloseEventHandler OnCloseEvent; public WsContext(HttpListenerRequest request, HttpListenerResponse response, WebSocket ws) : base(request, response) { @@ -26,32 +30,43 @@ public bool IsOpen() return _ws.State == WebSocketState.Open; } - // TODO: - // * use System.Buffers.ArrayPool for receiveBuffer - // -- seionmoya, 2024/09/09 - public async Task ReceiveAsync() + // TODO: + // * use System.Buffers.ArrayPool for receiveBuffer + // -- seionmoya, 2024/09/09 + + // NOTE: Made this internal because consumers + // shouldn't be calling this on their own + // -- nexus4880, 2024-10-23 + internal async Task PollAsync() { var buffer = new byte[_bufferSize]; - var received = await _ws.ReceiveAsync(new ArraySegment(buffer), CancellationToken.None); + var received = await _ws.ReceiveAsync(new ArraySegment(buffer), CancellationToken.None); var data = new byte[received.Count]; Array.Copy(buffer, 0, data, 0, data.Length); switch (received.MessageType) { - case WebSocketMessageType.Close: - await OnCloseAsync(this); - await CloseAsync(); - break; - case WebSocketMessageType.Text: var text = Encoding.UTF8.GetString(data); - await OnTextAsync(this, text); + if (OnTextEvent != null) + { + await OnTextEvent(this, text); + } + break; case WebSocketMessageType.Binary: - await OnBinaryAsync(this, data); + if (OnBinaryEvent != null) + { + await OnBinaryEvent(this, data); + } + break; - } + + case WebSocketMessageType.Close: + await CloseAsync(); + break; + } } public async Task SendTextAsync(string text) @@ -70,6 +85,10 @@ public async Task SendBinaryAsync(byte[] data) public async Task CloseAsync() { await _ws.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None); + if (OnCloseEvent != null) + { + await OnCloseEvent(this); + } } } } \ No newline at end of file diff --git a/Fuyu.Common/Networking/WsController.cs b/Fuyu.Common/Networking/WsController.cs index c10f938..9150338 100644 --- a/Fuyu.Common/Networking/WsController.cs +++ b/Fuyu.Common/Networking/WsController.cs @@ -15,10 +15,14 @@ protected WsController(string path) : base(path) // match static paths } - public virtual Task OnConnectAsync(WsContext context) - { + public override Task RunAsync(WsContext context) + { + context.OnCloseEvent += OnCloseAsync; + context.OnTextEvent += OnTextAsync; + context.OnBinaryEvent += OnBinaryAsync; + return Task.CompletedTask; - } + } public virtual Task OnCloseAsync(WsContext context) { @@ -34,13 +38,5 @@ public virtual Task OnBinaryAsync(WsContext context, byte[] binary) { return Task.CompletedTask; } - - public async Task InitializeAsync(WsContext context) - { - context.OnCloseAsync = OnCloseAsync; - context.OnTextAsync = OnTextAsync; - context.OnBinaryAsync = OnBinaryAsync; - await OnConnectAsync(context); - } } } diff --git a/Fuyu.Common/Networking/WsRouter.cs b/Fuyu.Common/Networking/WsRouter.cs index 33cda1d..638b854 100644 --- a/Fuyu.Common/Networking/WsRouter.cs +++ b/Fuyu.Common/Networking/WsRouter.cs @@ -11,11 +11,22 @@ public WsRouter() : base() public override async Task RouteAsync(WsContext context) { var matches = GetAllMatching(context); - foreach (var match in matches) + var tasks = new Task[matches.Count]; + for (var i = 0; i < matches.Count; i++) { - await match.InitializeAsync(context); - await match.RunAsync(context); + tasks[i] = matches[i].RunAsync(context); } - } - } + + await Task.WhenAll(tasks); + + while (context.IsOpen()) + { + await context.PollAsync(); + } + + // NOTE: No need to call context.CloseAsync here + // because ReceiveAsync will handle that for us + // -- nexus4880, 2024-10-23 + } + } } \ No newline at end of file