Example #1
0
        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();
            }
        }