예제 #1
0
        private async Task DataReceiver(ClientMetadata client)
        {
            Logger?.Invoke(_Header + "data receiver started for client " + client.IpPort, TCPLogType.Debug);

            while (true)
            {
                try
                {
                    if (client.Token.IsCancellationRequested ||
                        !IsClientConnected(client.Client))
                    {
                        Logger?.Invoke(_Header + "client " + client.IpPort + " disconnected", TCPLogType.Debug);
                        break;
                    }

                    if (client.Token.IsCancellationRequested)
                    {
                        Logger?.Invoke(_Header + "cancellation requested (data receiver for client " + client.IpPort + ")", TCPLogType.Debug);
                        break;
                    }

                    byte[] m_Buffer = await DataReadAsync(client);

                    if (m_Buffer == null)
                    {
                        await Task.Delay(30);

                        continue;
                    }

                    int BufferStart = 0;
                    int nBytesRec   = m_Buffer.Length;

                    // We support the PROXY protocol (currently v1)
                    // PROXY TCP4 192.168.0.37 192.168.0.121 57307 16248\r\n
                    // PROXY TCP6 ffff:f...f:ffff ffff:f...f:ffff 65535 65535\r\n
                    // \x0D \x0A \x0D \x0A \x00 \x0D \x0A \x51 \x55 \x49 \x54 \x0A
                    // Min 32 bytes, max 108 bytes
                    if (nBytesRec > 32 && m_Buffer[0] == 'P' && m_Buffer[1] == 'R' && m_Buffer[2] == 'O' && m_Buffer[3] == 'X' && m_Buffer[4] == 'Y' && m_Buffer[5] == ' ')
                    {
                        try
                        {
                            string   msg        = Encoding.UTF8.GetString(m_Buffer, 0, Math.Min(108, nBytesRec)); // 108 is the max we need to parse
                            string[] proxy      = msg.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
                            string[] proxyparts = proxy[0].Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);

                            client.OriginalIP       = IPAddress.Parse(proxyparts[2]);
                            client.OriginalSrcPort  = int.Parse(proxyparts[4]);
                            client.OriginalDestPort = int.Parse(proxyparts[5]);

                            client.IsProxied = true;

                            int split = msg.IndexOf("\r\n");

                            if (split > 32)
                            {
                                nBytesRec  -= split + 2;
                                BufferStart = split + 2;
                            }
                        }
                        catch (Exception)
                        {
                        }
                    }

                    byte[] package = new byte[nBytesRec];
                    Buffer.BlockCopy(m_Buffer, BufferStart, package, 0, nBytesRec);

                    var args = new DataReceivedFromClientEventArgs(client.IpPort, package, client.IncomingProtocol, client.Client.Client.RemoteEndPoint);
                    args.Data     = package;
                    args.Protocol = client.IncomingProtocol;

                    if (client.IsWebSocket)
                    {
                        args.WebSocketFrame = DecodeWebSocketMessage(package);

                        if (args.WebSocketFrame.OpCode == 0x9)
                        {
                            package[0] = (byte)((package[0] & 0xF0) + 0xA);
                            Send(client.IpPort, package);

                            return;
                        }
                    }

                    if (client.IsProxied)
                    {
                        args.OriginalIP       = client.OriginalIP;
                        args.OriginalSrcPort  = client.OriginalSrcPort;
                        args.OriginalDestPort = client.OriginalDestPort;
                    }

                    _Events.HandleDataReceived(this, args);
                    _Statistics.ReceivedBytes += package.Length;
                    UpdateClientLastSeen(client.IpPort);
                }
                catch (SocketException)
                {
                    Logger?.Invoke(_Header + "data receiver socket exception (disconnection) for " + client.IpPort, TCPLogType.Debug);
                }
                catch (Exception e)
                {
                    Logger?.Invoke(_Header + "data receiver exception for client " + client.IpPort + ":" +
                                   Environment.NewLine +
                                   e.ToString() +
                                   Environment.NewLine, TCPLogType.Warn);

                    break;
                }
            }

            Logger?.Invoke(_Header + "data receiver terminated for client " + client.IpPort, TCPLogType.Debug);

            if (_ClientsKicked.ContainsKey(client.IpPort))
            {
                _Events.HandleClientDisconnected(this, new ClientDisconnectedEventArgs(client.IpPort, DisconnectReason.Kicked));
            }
            else if (_ClientsTimedout.ContainsKey(client.IpPort))
            {
                _Events.HandleClientDisconnected(this, new ClientDisconnectedEventArgs(client.IpPort, DisconnectReason.Timeout));
            }
            else
            {
                _Events.HandleClientDisconnected(this, new ClientDisconnectedEventArgs(client.IpPort, DisconnectReason.Normal));
            }

            DateTime removedTs;

            _Clients.TryRemove(client.IpPort, out ClientMetadata destroyed);
            _ClientsLastSeen.TryRemove(client.IpPort, out removedTs);
            _ClientsKicked.TryRemove(client.IpPort, out removedTs);
            _ClientsTimedout.TryRemove(client.IpPort, out removedTs);
            client.Dispose();
        }
예제 #2
0
 internal void HandleDataReceived(object sender, DataReceivedFromClientEventArgs args)
 {
     DataReceived?.Invoke(sender, args);
 }