servicepoint-tanks/TanksServer/ClientScreenServer.cs
2024-04-07 11:19:14 +02:00

75 lines
2.5 KiB
C#

using System.Net.WebSockets;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using TanksServer.Helpers;
using TanksServer.Services;
namespace TanksServer;
internal sealed class ClientScreenServer(
ILogger<ClientScreenServer> logger,
ILoggerFactory loggerFactory,
MapDrawer drawer
) : IHostedLifecycleService, ITickStep
{
private readonly List<ClientScreenServerConnection> _connections = new();
public Task HandleClient(WebSocket socket)
{
logger.LogDebug("HandleClient");
var connection =
new ClientScreenServerConnection(socket, loggerFactory.CreateLogger<ClientScreenServerConnection>(), this);
_connections.Add(connection);
return connection.Done;
}
public Task StoppingAsync(CancellationToken cancellationToken)
{
logger.LogInformation("closing connections");
return Task.WhenAll(_connections.Select(c => c.CloseAsync()));
}
public Task TickAsync()
{
logger.LogTrace("Sending buffer to {} clients", _connections.Count);
return Task.WhenAll(_connections.Select(c => c.SendAsync(drawer.LastFrame)));
}
public Task StartAsync(CancellationToken cancellationToken) => Task.CompletedTask;
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
public Task StartedAsync(CancellationToken cancellationToken) => Task.CompletedTask;
public Task StartingAsync(CancellationToken cancellationToken) => Task.CompletedTask;
public Task StoppedAsync(CancellationToken cancellationToken) => Task.CompletedTask;
private void Remove(ClientScreenServerConnection connection) => _connections.Remove(connection);
private sealed class ClientScreenServerConnection(
WebSocket webSocket,
ILogger<ClientScreenServerConnection> logger,
ClientScreenServer server
) : EasyWebSocket(webSocket, logger, ArraySegment<byte>.Empty)
{
private bool _wantsNewFrame = true;
public Task SendAsync(DisplayPixelBuffer buf)
{
if (!_wantsNewFrame)
return Task.CompletedTask;
_wantsNewFrame = false;
return TrySendAsync(buf.Data);
}
protected override Task ReceiveAsync(ArraySegment<byte> buffer)
{
_wantsNewFrame = true;
return Task.CompletedTask;
}
protected override Task ClosingAsync()
{
server.Remove(this);
return Task.CompletedTask;
}
}
}