From 8410d4dc96a23ed256259bc004b32033984b03f4 Mon Sep 17 00:00:00 2001 From: Simon <63975668+Simyon264@users.noreply.github.com> Date: Wed, 10 Apr 2024 19:30:58 +0200 Subject: [PATCH] Add WebSocket stat count Updates *maybe* a bit too often? Resolves #3 --- Client/Components/App.razor | 43 ++++++++++++++++++- Client/Components/Pages/Home.razor | 1 + Client/Components/Pages/Search.razor | 1 + Server/Api/DataController.cs | 63 +++++++++++++++++++++++++++- Server/Program.cs | 7 ++++ 5 files changed, 112 insertions(+), 3 deletions(-) diff --git a/Client/Components/App.razor b/Client/Components/App.razor index 5dac545..3fde3ff 100644 --- a/Client/Components/App.razor +++ b/Client/Components/App.razor @@ -1,4 +1,7 @@ - +@using Microsoft.Extensions.Configuration +@inject IConfiguration Configuration + + @@ -19,6 +22,44 @@ + \ No newline at end of file diff --git a/Client/Components/Pages/Home.razor b/Client/Components/Pages/Home.razor index cfa1177..d07d89c 100644 --- a/Client/Components/Pages/Home.razor +++ b/Client/Components/Pages/Home.razor @@ -7,6 +7,7 @@ Replay viewer

Replay browser for Space Station 14

+

There is currently 1 user here.



diff --git a/Client/Components/Pages/Search.razor b/Client/Components/Pages/Search.razor index aaf70d9..7091a38 100644 --- a/Client/Components/Pages/Search.razor +++ b/Client/Components/Pages/Search.razor @@ -8,6 +8,7 @@ Replay viewer

Replay browser for Space Station 14

+

There is currently 1 user here.

Search for replays by using the search bar below

Back to main page
diff --git a/Server/Api/DataController.cs b/Server/Api/DataController.cs index 09c750f..6734c71 100644 --- a/Server/Api/DataController.cs +++ b/Server/Api/DataController.cs @@ -1,6 +1,11 @@ -using Microsoft.AspNetCore.Cors; +using System.Collections.Concurrent; +using System.Net.WebSockets; +using System.Text; +using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; +using Serilog; +using Shared; namespace Server.Api; @@ -13,10 +18,13 @@ namespace Server.Api; public class DataController : ControllerBase { private readonly ReplayDbContext _context; - + public static readonly Dictionary ConnectedUsers = new(); + private Timer _timer; + public DataController(ReplayDbContext context) { _context = context; + _timer = new Timer(CheckInactiveConnections, null, TimeSpan.Zero, TimeSpan.FromSeconds(5)); } /// @@ -39,4 +47,55 @@ [FromQuery] string username return Ok(completions); } + + [Route("/ws")] + public async Task Connect() + { + if (HttpContext.WebSockets.IsWebSocketRequest) + { + var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync(); + var userId = Guid.NewGuid(); + ConnectedUsers.Add(userId, webSocket); + Log.Information("User connected with ID {UserId}", userId); + await Echo(webSocket, userId); + } + else + { + HttpContext.Response.StatusCode = 400; + } + } + + private async Task Echo(WebSocket webSocket, Guid userId) + { + var buffer = new byte[1024 * 4]; + var result = await webSocket.ReceiveAsync(new ArraySegment(buffer), CancellationToken.None); + + while (!result.CloseStatus.HasValue) + { + result = await webSocket.ReceiveAsync(new ArraySegment(buffer), CancellationToken.None); + + if (Encoding.UTF8.GetString(buffer).Contains("count")) + { + var count = ConnectedUsers.Count; + var countBytes = Encoding.UTF8.GetBytes(count.ToString()); + await webSocket.SendAsync(new ArraySegment(countBytes), WebSocketMessageType.Text, true, CancellationToken.None); + } + + buffer = new byte[1024 * 4]; + } + + ConnectedUsers.Remove(userId, out _); + await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None); + } + + private void CheckInactiveConnections(object state) + { + foreach (var user in ConnectedUsers) + { + if (user.Value.State == WebSocketState.Open) continue; + + ConnectedUsers.Remove(user.Key, out _); + Log.Information("User disconnected with ID {UserId}", user.Key); + } + } } \ No newline at end of file diff --git a/Server/Program.cs b/Server/Program.cs index 791b89e..e6b6bf6 100644 --- a/Server/Program.cs +++ b/Server/Program.cs @@ -66,6 +66,13 @@ builder.Services.AddMvc(); var app = builder.Build(); + + var webSocketOptions = new WebSocketOptions() + { + KeepAliveInterval = TimeSpan.FromSeconds(10), + }; + + app.UseWebSockets(webSocketOptions); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment())