using System.Net.Quic; using DTLib.Logging; using Meum.Core.Messages; namespace Meum.Server; public class ClientConnection : IAsyncDisposable { private readonly QuicConnection _quicConnection; private QuicStreamWrapper _systemStream; private ContextLogger _logger; private CancellationTokenSource _connectionCts = new(); public int Id { get; } public bool IsAuthorized { get; private set; } private ClientConnection(int id, QuicConnection quicConnection, QuicStreamWrapper systemStream, ILogger logger) { Id = id; _quicConnection = quicConnection; _systemStream = systemStream; _logger = new ContextLogger($"Connection-{id}", logger); } public static async Task OpenAsync(int id, QuicConnection quicConnection, ILogger logger, CancellationToken ct) { var systemStream = await quicConnection.AcceptStreamAsync(QuicStreamType.Bidirectional, ct); await systemStream.ReceivePingSendPong(); var clientConnection = new ClientConnection(id, quicConnection, systemStream, logger); clientConnection.HandleRequestsAsync(ct); return clientConnection; } private async void HandleRequestsAsync(CancellationToken ct) { try { while (!_connectionCts.IsCancellationRequested) { try { var header = await _systemStream.ReadDataMessageHeaderAsync(ct); if(IsAuthorized) HandleAuthorizedRequest(header); else HandleUnauthorizedRequest(header); } catch (Exception ex) { _logger.LogWarn(ex); } } await DisposeAsync(); } catch (Exception ex) { _logger.LogError(ex); } } private void HandleUnauthorizedRequest(DataMessageHeader header) { switch (header.type_code) { default: throw new Exception($"New connection sent unexpected message: {header.type_code}"); case MessageTypeCode.RegistrationRequest: // TODO: registration break; case MessageTypeCode.AuthorizationRequest: // TODO: authorization IsAuthorized = true; break; } } private void HandleAuthorizedRequest(DataMessageHeader header) { switch (header.type_code) { default: throw new Exception($"New connection sent unexpected message: {header.type_code}"); } } public override int GetHashCode() => Id; public async ValueTask DisposeAsync() { await _quicConnection.DisposeAsync(); } }