namespace TanksServer.Interactivity; internal abstract class WebsocketServerConnection( ILogger logger, ByteChannelWebSocket socket ) : IDisposable { private readonly SemaphoreSlim _mutex = new(1); protected readonly ByteChannelWebSocket Socket = socket; protected readonly ILogger Logger = logger; public Task CloseAsync() { Logger.LogDebug("closing connection"); return Socket.CloseAsync(); } public async Task ReceiveAsync() { await foreach (var buffer in Socket.ReadAllAsync()) await LockedAsync(() => HandleMessageLockedAsync(buffer)); Logger.LogTrace("done receiving"); } protected abstract ValueTask HandleMessageLockedAsync(Memory buffer); protected async ValueTask LockedAsync(Func action) { await _mutex.WaitAsync(); try { await action(); } finally { _mutex.Release(); } } public void Dispose() => _mutex.Dispose(); }