internal static void HandlePacket(byte[] payload) { // ReSharper disable InconsistentNaming bool SYN = (payload[47] & (1 << 1)) != 0; var ACK = (payload[47] & (1 << 4)) != 0; bool FIN = (payload[47] & (1 << 0)) != 0; bool PSH = (payload[47] & (1 << 3)) != 0; bool RST = (payload[47] & (1 << 2)) != 0; // ReSharper restore InconsistentNaming byte[] sourceIp = Utility.ExtractRangeFromArray(payload, 26, 4); byte[] sourcePort = Utility.ExtractRangeFromArray(payload, 34, 2); byte[] localPort = Utility.ExtractRangeFromArray(payload, 36, 2); ulong connectionId = GenerateConnectionId(payload); Connection con; uint packetSeqNumber = Utility.ExtractRangeFromArray(payload, 38, 4).ToInt(); if (SYN && !ACK) { var connection = _connections[connectionId] as Connection; if (connection != null && (_connections.Contains(connectionId) && connection.IsOpen)) { _connections.Remove(connectionId); } var keys = new ulong[_connections.Count]; _connections.Keys.CopyTo(keys, 0); foreach (ulong key in keys) { con = _connections[key] as Connection; var connection1 = _connections[key] as Connection; if (connection1 != null && Utility.GetMachineTime().Subtract(connection1.LastActivity).Seconds > ConnectionIdleLimit) { con.IsClosing = true; con.SeqNumber++; con.SendAck(false, true); _connections.Remove(key); } } if (!_connections.Contains(connectionId)) { _connections.Add(connectionId, new Connection()); } con = _connections[connectionId] as Connection; if (con != null) { con.RemoteIp = sourceIp; con.RemotePort = sourcePort.ToShort(); con.RemoteMac = Utility.ExtractRangeFromArray(payload, 6, 6); con.LocalPort = localPort.ToShort(); con.SeqNumber = packetSeqNumber + 1; con.StartSeqNumber = packetSeqNumber; con.AckNumber = 2380; con.WindowSize = 1024; con.ReadyForRequest = true; con.SendAck(true); con.AckNumber++; con.IsOpen = true; } } else if (_connections.Contains(connectionId) && (ACK || FIN || PSH || RST)) { con = _connections[connectionId] as Connection; ushort totalLength = Utility.ExtractRangeFromArray(payload, 16, 2).ToShort(); var ipHeaderLength = (ushort)((payload[14] & 0x0f) * 4); var tcpHeaderLength = (ushort)((payload[26 + ipHeaderLength] >> 4) * 4); if (totalLength + 14 > payload.Length) { #if TINYCLR_TRACE if (EthClick._verboseDebugging) { System.Diagnostics.Debug.WriteLine("Bad packet size detected? " + totalLength + "/" + payload.Length); } #endif return; } if (con != null) { con.SeqNumber += (uint)(totalLength - (tcpHeaderLength + ipHeaderLength)); con.WindowSize -= (ushort)(totalLength - (tcpHeaderLength + ipHeaderLength)); if (PSH) { con.SendAck(); } else if (SYN) { con.SeqNumber = packetSeqNumber + 1; con.StartSeqNumber = packetSeqNumber; con.AckNumber++; con.SendAck(); con.IsOpen = true; return; } else if ((FIN || RST) && ACK) { con.IsClosing = true; con.SeqNumber++; con.SendAck(); _connections.Remove(connectionId); return; } else if (FIN) { con.IsClosing = true; con.SeqNumber++; con.SendAck(false, true); return; } else if (RST) { con.IsClosing = true; con.SeqNumber++; return; } else if (con.IsClosing) { _connections.Remove(connectionId); return; } #if TINYCLR_TRACE if (EthClick._verboseDebugging) { System.Diagnostics.Debug.WriteLine("Check for data"); } #endif if ((totalLength - (tcpHeaderLength + ipHeaderLength)) > 0) { byte[] segment = Utility.ExtractRangeFromArray(payload, (14 + ipHeaderLength + tcpHeaderLength), (totalLength - (tcpHeaderLength + ipHeaderLength))); #if TINYCLR_TRACE if (EthClick._verboseDebugging) { System.Diagnostics.Debug.WriteLine("We got some data, PSN: " + packetSeqNumber + ", SSN: " + con.StartSeqNumber + ", header delimiter: " + segment.Locate(HttpRequest.HeaderDelimiter)); } #endif EthClick.FireTcpPacketEvent(segment, packetSeqNumber - con.StartSeqNumber, con); con.FireOnConnectionPacketReceived(new Packet(PacketType.TCP) { SequenceNumber = packetSeqNumber - con.StartSeqNumber, Content = segment, Socket = con }); if (segment.Length < 10 || !(segment[0] == 0x47 && segment[1] == 0x45 && segment[2] == 0x54) && !(segment[0] == 0x50 && segment[1] == 0x4F && segment[2] == 0x53 && segment[3] == 0x54)) { return; // if it is not a get, then we won't handle it through the HTTP Request Handler } if (con.ReadyForRequest) { byte[] lrc = Utility.ExtractRangeFromArray(payload, (30 + ipHeaderLength), 2); if (con.LastRequestChecksum.BytesEqual(lrc)) { #if TINYCLR_TRACE if (EthClick._verboseDebugging) { System.Diagnostics.Debug.WriteLine("Retransmission of Request Ignored!"); } #endif } else { con.LastRequestChecksum = lrc; con.ReadyForRequest = false; EthClick.FireHttpPacketEvent(segment, con); } } } } } else if ((FIN || RST) && ACK) { #if TINYCLR_TRACE if (EthClick._verboseDebugging) { System.Diagnostics.Debug.WriteLine("Handling RST for a connection that no longer exists!!!!!!!!!"); } #endif con = new Connection { RemoteIp = sourceIp, RemotePort = sourcePort.ToShort(), RemoteMac = Utility.ExtractRangeFromArray(payload, 6, 6), LocalPort = localPort.ToShort(), SeqNumber = Utility.ExtractRangeFromArray(payload, 38, 4).ToInt(), AckNumber = Utility.ExtractRangeFromArray(payload, 42, 4).ToInt(), IsClosing = true }; con.SendAck(); } }