// // TcpServer.cs // // Copyright (c) František Boháček. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System.Data; using System.Net; using System.Net.Sockets; using NosSmooth.Comms.Data; using Remora.Results; namespace NosSmooth.Comms.Core.Tcp; /// /// A server using tcp. /// public class TcpServer : IServer, IDisposable { private readonly TcpListener _listener; private readonly List _connections; /// /// Initializes a new instance of the class. /// /// The ip to bind to. /// The port to bind to. public TcpServer(IPAddress ip, int port) { _listener = new TcpListener(ip, port); _connections = new List(); } /// public IReadOnlyList Clients => _connections.AsReadOnly(); /// public async Task> WaitForConnectionAsync(CancellationToken ct = default) { var tcpClient = await _listener.AcceptTcpClientAsync(ct); var connection = new TcpConnection(tcpClient); _connections.Add(connection); return connection; } /// public Task ListenAsync(CancellationToken stopToken = default) { try { _listener.Start(); return Task.FromResult(Result.FromSuccess()); } catch (Exception e) { return Task.FromResult(e); } } /// public void Close() { _listener.Stop(); } private class TcpConnection : IConnection, IDisposable { private readonly System.Net.Sockets.TcpClient _client; public TcpConnection(System.Net.Sockets.TcpClient client) { _client = client; } public ConnectionState State => _client.Connected ? ConnectionState.Open : ConnectionState.Closed; public Stream ReadStream => _client.GetStream(); public Stream WriteStream => _client.GetStream(); public void Disconnect() { _client.Close(); } public void Dispose() { _client.Dispose(); } } /// public void Dispose() { foreach (var connection in _connections.Cast()) { connection.Dispose(); } } }