using System; using System.Net; using System.Net.Sockets; using System.Threading.Tasks; namespace ZeroLevel.Services.Network.Proxies { public class Proxy : IDisposable { private readonly ProxyBalancer _balancer = new ProxyBalancer(); public void AppendServer(IPEndPoint ep) => _balancer.AddEndpoint(ep); private Socket _incomingSocket; public Proxy(IPEndPoint listenEndpoint) { _incomingSocket = new Socket(listenEndpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); _incomingSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, true); _incomingSocket.Bind(listenEndpoint); } public void Run() { Task.Factory.StartNew(async () => { try { _incomingSocket.Listen(100); while (true) { var socket = await _incomingSocket.AcceptAsync(); // no await! Task.Run(async () => { await CreateProxyConnection(socket); }); } } catch (Exception ex) { Log.Error(ex, "[Proxy.Run]"); } }); } private async Task CreateProxyConnection(Socket connection) { try { var endpoint = _balancer.GetServerProxy(); var server = new Socket(endpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, true); server.Connect(endpoint); using (var bind = new ProxyBinding(connection, server)) { await bind.Bind(); } } catch (Exception ex) { } } public void Dispose() { try { _incomingSocket.Shutdown(SocketShutdown.Both); _incomingSocket.Dispose(); } catch (Exception ex) { } } } }