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(); }
internal void HandleDataReceived(object sender, DataReceivedFromClientEventArgs args) { DataReceived?.Invoke(sender, args); }