using System.Net.Sockets; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Supercell.GUT.Server.Network.Options; namespace Supercell.GUT.Server.Network.Tcp; internal class TcpGateway : IServerGateway { private const int TcpBacklog = 100; private readonly ILogger _logger; private readonly IOptions _options; private readonly IGatewayEventListener _listener; private readonly Socket _socket; private CancellationTokenSource? _listenCancellation; private Task? _listenTask; public TcpGateway(IOptions options, ILogger logger, IGatewayEventListener listener) { _logger = logger; _options = options; _listener = listener; _socket = new(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); } public void Start() { _socket.Bind(_options.Value.ListenEndPoint); _socket.Listen(TcpBacklog); _listenCancellation = new(); _listenTask = RunAsync(_listenCancellation.Token); _logger.LogInformation("Gateway is listening at {ipEndPoint}", _options.Value.ListenEndPoint); } private async Task RunAsync(CancellationToken cancellationToken) { while (!cancellationToken.IsCancellationRequested) { Socket? socket = await _socket.AcceptSocketAsync(cancellationToken); if (socket == null) break; _listener.OnConnect(new TcpSocketEntity(socket)); } } public async Task ShutdownAsync() { if (_listenCancellation != null) { await _listenCancellation.CancelAsync(); await _listenTask!; } _socket.Close(); } }