private async void ServerOnClientConnected(object sender, TcpClientEventArgs e)
        {
            _server.BeginAccept();

            var client = new Socks5Client(e.Client)
            {
                ProxySending = args => ProxySending?.Invoke(this, args),
                ProxyReceiving = args => ProxyReceiving?.Invoke(this, args)
            };

            client.InternalClient.ClientDisconnected += (o, args) 
                => ClientDisconnected?.Invoke(this, new SocksClientEventArgs(client));

            if (await HandleGreeting(client))
                ClientConnected?.Invoke(this, new SocksClientEventArgs(client));
            else
                InvalidClientConnected?.Invoke(this, new TcpClientEventArgs(e.Client));

            await HandleConnectionInitiate(client);

            var buf = client.Receive(new byte[100]);
            client.StartTunneling();

            _clients.Add(client);
        }
        private static async Task<bool> HandleGreeting(Socks5Client client)
        {
            // TODO: Add state or something?
            var greetingRequest = await client.InternalClient.ReceiveSerializable<Socks5GreetingRequest>();
            if (greetingRequest == null)
                return false;

            // TODO: Authentication handling
            var greetingResponse = new Socks5GreetingResponse(SocksAuthentication.NoAuthentication);
            return await client.InternalClient.SendSerializable(greetingResponse);
        }
        private static async Task<bool> HandleConnectionInitiate(Socks5Client client)
        {
            var connectionRequest = await client.InternalClient.ReceiveSerializable<Socks5ConnectionRequest>();
            if (connectionRequest == null)
                return false;

            // TODO: Add validation etc.
            var success = await client.ConnectWith(connectionRequest.EndPoint);
            var status = success ? SocksResponseStatus.OK : SocksResponseStatus.GeneralFailure;
            
            var connectionResponse = new Socks5ConnectionResponse(status, connectionRequest);
            return await client.InternalClient.SendSerializable(connectionResponse);
        }
 public ClientEventArgs(Socks5Client client)
 {
     Client = client;
 }