using System.Net; using System.Net.Quic; using System.Net.Security; using System.Security.Cryptography.X509Certificates; using DTLib.Logging; namespace Meum.Server; public class Server { private readonly ServerConfig _config; private readonly X509Certificate _certificate; private readonly ILogger _logger; private QuicListener? _listener; public Server(ServerConfig config, ILogger logger, X509Certificate? certificate = null) { _config = config; _logger = logger; _certificate = certificate ?? X509Certificate2.CreateFromPemFile(config.certificate_path, config.key_path); } public async ValueTask ListenAsync() { var serverConnectionOptions = new QuicServerConnectionOptions { DefaultStreamErrorCode = Constants.DefaultStreamErrorCode, DefaultCloseErrorCode = Constants.DefaultCloseErrorCode, ServerAuthenticationOptions = new SslServerAuthenticationOptions { ApplicationProtocols = Constants.ApplicationProtocols, ServerCertificate = _certificate, ClientCertificateRequired = false } }; var listenerOptions = new QuicListenerOptions { ListenEndPoint = new IPEndPoint(IPAddress.Parse(_config.listener_ip), _config.listener_port), ApplicationProtocols = Constants.ApplicationProtocols, ConnectionOptionsCallback = (_, _, _) => ValueTask.FromResult(serverConnectionOptions) }; _listener = await QuicListener.ListenAsync(listenerOptions); } public async Task AcceptConnectionAsync(CancellationToken ct = default) { if (_listener == null) throw new Exception("Server is not listening"); while (true) { ct.ThrowIfCancellationRequested(); var quicConnection = await _listener.AcceptConnectionAsync(ct); var clientConnection = new ClientConnection(quicConnection, _logger); await clientConnection.HandleClientRequestsAsync(ct); return clientConnection; } } }