Пример #1
0
        /// <summary>
        /// Send data to client.
        /// </summary>
        /// <param name="data">Data array to send.</param>
        /// <exception cref="Exception">Thrown if destination is null or destinationPort is 0.</exception>
        /// <exception cref="ArgumentException">Thrown on fatal error (contact support).</exception>
        /// <exception cref="OverflowException">Thrown if data array length is greater than Int32.MaxValue.</exception>
        /// <exception cref="Sys.IO.IOException">Thrown on IO error.</exception>
        /// <exception cref="Exception">Thrown if TCP Status is not ESTABLISHED.</exception>
        public void Send(byte[] data)
        {
            if ((StateMachine.destination == null) || (StateMachine.destinationPort == 0))
            {
                throw new InvalidOperationException("Must establish a default remote host by calling Connect() before using this Send() overload");
            }
            if (StateMachine.Status != Status.ESTABLISHED)
            {
                throw new Exception("Client must be connected before sending data.");
            }
            if (data.Length > 536)
            {
                var chunks = ArrayHelper.ArraySplit(data, 536);

                for (int i = 0; i < chunks.Length; i++)
                {
                    var packet = new TCPPacket(StateMachine.source, StateMachine.destination, (ushort)StateMachine.localPort, (ushort)StateMachine.destinationPort, StateMachine.SequenceNumber, StateMachine.AckNumber, 20, i == chunks.Length - 2 ? (byte)(Flags.PSH | Flags.ACK) : (byte)(Flags.ACK), 0xFAF0, 0, chunks[i]);
                    OutgoingBuffer.AddPacket(packet);
                    NetworkStack.Update();

                    StateMachine.SequenceNumber += (uint)chunks[i].Length;
                }
            }
            else
            {
                var packet = new TCPPacket(StateMachine.source, StateMachine.destination, (ushort)StateMachine.localPort, (ushort)StateMachine.destinationPort, StateMachine.SequenceNumber, StateMachine.AckNumber, 20, (byte)(Flags.PSH | Flags.ACK), 0xFAF0, 0, data);
                OutgoingBuffer.AddPacket(packet);
                NetworkStack.Update();

                StateMachine.SequenceNumber += (uint)data.Length;
            }
            StateMachine.WaitingAck = true;
        }
Пример #2
0
        /// <summary>
        /// Connect to client.
        /// </summary>
        /// <param name="dest">Destination address.</param>
        /// <param name="destPort">Destination port.</param>
        /// <exception cref="Exception">Thrown if TCP Status is not CLOSED.</exception>
        public void Connect(Address dest, int destPort, int timeout = 5000)
        {
            if (StateMachine.Status != Status.CLOSED)
            {
                throw new Exception("Client must be closed before setting a new connection.");
            }

            StateMachine.destination     = dest;
            StateMachine.destinationPort = destPort;

            StateMachine.source = IPConfig.FindNetwork(dest);

            //Generate Random Sequence Number
            var rnd = new Random();

            StateMachine.SequenceNumber = (uint)((rnd.Next(0, Int32.MaxValue)) << 32) | (uint)(rnd.Next(0, Int32.MaxValue));

            // Flags=0x02 -> Syn
            var packet = new TCPPacket(StateMachine.source, StateMachine.destination, (ushort)StateMachine.localPort, (ushort)destPort, StateMachine.SequenceNumber, 0, 20, (byte)Flags.SYN, 0xFAF0, 0);

            OutgoingBuffer.AddPacket(packet);
            NetworkStack.Update();

            StateMachine.Status = Status.SYN_SENT;

            if (StateMachine.WaitStatus(Status.ESTABLISHED, timeout) == false)
            {
                throw new Exception("Failed to open TCP connection!");
            }
        }
Пример #3
0
        /// <summary>
        /// TCP handler.
        /// </summary>
        /// <param name="packetData">Packet data.</param>
        /// <exception cref="sys.ArgumentOutOfRangeException">Thrown on fatal error (contact support).</exception>
        /// <exception cref="sys.IO.IOException">Thrown on IO error.</exception>
        /// <exception cref="sys.ArgumentException">Thrown on fatal error (contact support).</exception>
        /// <exception cref="sys.OverflowException">Thrown if packetData array length is greater than Int32.MaxValue.</exception>
        internal static void TCPHandler(byte[] packetData)
        {
            var packet = new TCPPacket(packetData);

            if (packet.CheckCRC())
            {
                var client = TcpClient.GetClient(packet.DestinationPort);
                if (client != null)
                {
                    client.StateMachine.ReceiveData(packet);
                    return;
                }

                var listener = TcpListener.GetListener(packet.DestinationPort);
                if (listener != null)
                {
                    listener.StateMachine.ReceiveData(packet);
                    return;
                }
            }
            else
            {
                Global.mDebugger.Send("Checksum incorrect! Packet passed.");
            }
        }
Пример #4
0
        /// <summary>
        /// Send acknowledgement packet
        /// </summary>
        private void SendEmptyPacket(Flags flag)
        {
            var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, SequenceNumber, AckNumber, 20, (byte)flag, 0xFAF0, 0);

            OutgoingBuffer.AddPacket(packet);
            NetworkStack.Update();
        }
Пример #5
0
        /// <summary>
        /// Process FIN_WAIT1 Status.
        /// </summary>
        /// <param name="packet">Packet to receive.</param>
        public void ProcessFinWait1(TCPPacket packet)
        {
            if (packet.ACK)
            {
                if (packet.FIN)
                {
                    TCB.RcvNxt++;

                    SendEmptyPacket(Flags.ACK);

                    WaitAndClose();
                }
                else
                {
                    Status = Status.FIN_WAIT2;
                }
            }
            else if (packet.FIN)
            {
                TCB.RcvNxt++;

                SendEmptyPacket(Flags.ACK);

                Status = Status.CLOSING;
            }
        }
Пример #6
0
 /// <summary>
 /// Process CLOSING Status.
 /// </summary>
 /// <param name="packet">Packet to receive.</param>
 public void ProcessClosing(TCPPacket packet)
 {
     if (packet.ACK)
     {
         WaitAndClose();
     }
 }
Пример #7
0
 /// <summary>
 /// Process Close_WAIT Status.
 /// </summary>
 /// <param name="packet">Packet to receive.</param>
 public void ProcessCloseWait(TCPPacket packet)
 {
     if (packet.ACK)
     {
         Status = Status.CLOSED;
     }
 }
Пример #8
0
        /// <summary>
        /// Close connection.
        /// </summary>
        /// <exception cref="ArgumentOutOfRangeException">Thrown on fatal error (contact support).</exception>
        /// <exception cref="Exception">Thrown if TCP Status is CLOSED.</exception>
        public void Close()
        {
            if (StateMachine.Status == Status.CLOSED)
            {
                throw new Exception("Client already closed.");
            }
            if (StateMachine.Status == Status.ESTABLISHED)
            {
                var packet = new TCPPacket(StateMachine.source, StateMachine.destination, (ushort)StateMachine.localPort, (ushort)StateMachine.destinationPort, StateMachine.SequenceNumber, StateMachine.AckNumber, 20, (byte)(Flags.FIN | Flags.ACK), 0xFAF0, 0);
                OutgoingBuffer.AddPacket(packet);
                NetworkStack.Update();

                StateMachine.SequenceNumber++;

                StateMachine.Status = Status.FIN_WAIT1;

                if (StateMachine.WaitStatus(Status.CLOSED, 5000) == false)
                {
                    throw new Exception("Failed to close TCP connection!");
                }
            }

            if (clients.ContainsKey((uint)StateMachine.localPort))
            {
                clients.Remove((uint)StateMachine.localPort);
            }
        }
Пример #9
0
        /// <summary>
        /// Send data to client.
        /// </summary>
        /// <param name="data">Data array to send.</param>
        /// <exception cref="Exception">Thrown if destination is null or destinationPort is 0.</exception>
        /// <exception cref="ArgumentException">Thrown on fatal error (contact support).</exception>
        /// <exception cref="OverflowException">Thrown if data array length is greater than Int32.MaxValue.</exception>
        /// <exception cref="Sys.IO.IOException">Thrown on IO error.</exception>
        /// <exception cref="Exception">Thrown if TCP Status is not ESTABLISHED.</exception>
        public void Send(byte[] data)
        {
            if ((StateMachine.RemoteEndPoint.Address == null) || (StateMachine.RemoteEndPoint.Port == 0))
            {
                throw new InvalidOperationException("Must establish a default remote host by calling Connect() before using this Send() overload");
            }
            if (StateMachine.Status != Status.ESTABLISHED)
            {
                throw new Exception("Client must be connected before sending data.");
            }
            if (data.Length > 536)
            {
                var chunks = ArrayHelper.ArraySplit(data, 536);

                for (int i = 0; i < chunks.Length; i++)
                {
                    var packet = new TCPPacket(StateMachine.LocalEndPoint.Address, StateMachine.RemoteEndPoint.Address, StateMachine.LocalEndPoint.Port, StateMachine.RemoteEndPoint.Port, StateMachine.TCB.SndNxt, StateMachine.TCB.RcvNxt, 20, i == chunks.Length - 2 ? (byte)(Flags.PSH | Flags.ACK) : (byte)(Flags.ACK), StateMachine.TCB.SndWnd, 0, chunks[i]);
                    OutgoingBuffer.AddPacket(packet);
                    NetworkStack.Update();

                    StateMachine.TCB.SndNxt += (uint)chunks[i].Length;
                }
            }
            else
            {
                var packet = new TCPPacket(StateMachine.LocalEndPoint.Address, StateMachine.RemoteEndPoint.Address, StateMachine.LocalEndPoint.Port, StateMachine.RemoteEndPoint.Port, StateMachine.TCB.SndNxt, StateMachine.TCB.RcvNxt, 20, (byte)(Flags.PSH | Flags.ACK), StateMachine.TCB.SndWnd, 0, data);
                OutgoingBuffer.AddPacket(packet);
                NetworkStack.Update();

                StateMachine.TCB.SndNxt += (uint)data.Length;
            }
        }
Пример #10
0
        /// <summary>
        /// Send TCP packet.
        /// </summary>
        private void SendPacket(TCPPacket packet)
        {
            OutgoingBuffer.AddPacket(packet);
            NetworkStack.Update();

            if (packet.SYN || packet.FIN)
            {
                TCB.SndNxt++;
            }
        }
Пример #11
0
        /// <summary>
        /// Process FIN_WAIT2 Status.
        /// </summary>
        /// <param name="packet">Packet to receive.</param>
        public void ProcessFinWait2(TCPPacket packet)
        {
            if (packet.FIN)
            {
                TCB.RcvNxt++;

                SendEmptyPacket(Flags.ACK);

                WaitAndClose();
            }
        }
Пример #12
0
        /// <summary>
        /// Process FIN_WAIT2 Status.
        /// </summary>
        /// <param name="packet">Packet to receive.</param>
        public void ProcessFinWait2(TCPPacket packet)
        {
            if (packet.FIN)
            {
                AckNumber++;

                SendEmptyPacket(Flags.ACK);

                WaitAndClose();
            }
        }
Пример #13
0
        /// <summary>
        /// Handle incoming TCP packets according to current connection status.
        /// </summary>
        /// <param name="packet">Packet to receive.</param>
        /// <exception cref="OverflowException">Thrown on fatal error (contact support).</exception>
        /// <exception cref="Sys.IO.IOException">Thrown on IO error.</exception>
        internal void ReceiveData(TCPPacket packet)
        {
            Global.mDebugger.Send("[" + table[(int)Status] + "] " + packet.ToString());

            switch (Status)
            {
            case Status.LISTEN:
                ProcessListen(packet);
                break;

            case Status.SYN_SENT:
                ProcessSynSent(packet);
                break;

            case Status.SYN_RECEIVED:
                ProcessSynReceived(packet);
                break;

            case Status.ESTABLISHED:
                ProcessEstablished(packet);
                break;

            case Status.FIN_WAIT1:
                ProcessFinWait1(packet);
                break;

            case Status.FIN_WAIT2:
                ProcessFinWait2(packet);
                break;

            case Status.CLOSE_WAIT:
                ProcessCloseWait(packet);
                break;

            case Status.CLOSING:
                ProcessClosing(packet);
                break;

            case Status.LAST_ACK:
                ProcessCloseWait(packet);
                break;

            case Status.TIME_WAIT:
                break;

            case Status.CLOSED:
                break;

            default:
                throw new Exception("Unknown TCP connection state.");
            }
        }
Пример #14
0
        /// <summary>
        /// Process LISTEN Status.
        /// </summary>
        /// <param name="packet">Packet to receive.</param>
        public void ProcessListen(TCPPacket packet)
        {
            if (packet.RST)
            {
                Global.mDebugger.Send("RST received at LISTEN state, packet passed.");

                return;
            }
            else if (packet.FIN)
            {
                Status = Status.CLOSED;

                Global.mDebugger.Send("TCP connection closed! (FIN received on LISTEN state)");
            }
            else if (packet.ACK)
            {
                TCB.RcvNxt = packet.SequenceNumber;
                TCB.SndNxt = packet.AckNumber;

                Status = Status.ESTABLISHED;
            }
            else if (packet.SYN)
            {
                LocalEndPoint.Address  = IPConfig.FindNetwork(packet.SourceIP);
                RemoteEndPoint.Address = packet.SourceIP;
                RemoteEndPoint.Port    = packet.SourcePort;

                var rnd            = new Random();
                var sequenceNumber = (uint)((rnd.Next(0, Int32.MaxValue)) << 32) | (uint)(rnd.Next(0, Int32.MaxValue));

                //Fill TCB
                TCB.SndUna = sequenceNumber;
                TCB.SndNxt = sequenceNumber;
                TCB.SndWnd = Tcp.TcpWindowSize;
                TCB.SndUp  = 0;
                TCB.SndWl1 = packet.SequenceNumber - 1;
                TCB.SndWl2 = 0;
                TCB.ISS    = sequenceNumber;

                TCB.RcvNxt = packet.SequenceNumber + 1;
                TCB.RcvWnd = Tcp.TcpWindowSize;
                TCB.RcvUp  = 0;
                TCB.IRS    = packet.SequenceNumber;

                SendEmptyPacket(Flags.SYN | Flags.ACK);

                Status = Status.SYN_RECEIVED;
            }
        }
Пример #15
0
        /// <summary>
        /// Process SYN_RECEIVED Status.
        /// </summary>
        /// <param name="packet">Packet to receive.</param>
        public void ProcessSynReceived(TCPPacket packet)
        {
            if (packet.RST)
            {
                Status = Status.LISTEN;
            }
            else if (packet.ACK)
            {
                LastSequenceNumber = packet.SequenceNumber - 1; //TODO: Fix this trick (for dup check when PSH ACK)

                SequenceNumber++;

                Status = Status.ESTABLISHED;
            }
        }
Пример #16
0
        /// <summary>
        /// Process SYN_SENT Status.
        /// </summary>
        /// <param name="packet">Packet to receive.</param>
        public void ProcessSynSent(TCPPacket packet)
        {
            if (packet.FIN)
            {
                Status = Status.CLOSED;

                throw new Exception("TCP connection closed! (FIN received on SYN_SENT state)");
            }
            else if (packet.TCPFlags == (byte)Flags.ACK)
            {
                AckNumber      = packet.SequenceNumber;
                SequenceNumber = packet.AckNumber;

                Status = Status.ESTABLISHED;
            }
            else if (packet.RST)
            {
                Status = Status.CLOSED;

                throw new Exception("Connection refused by remote computer.");
            }
            else if (packet.SYN)
            {
                if (packet.ACK)
                {
                    AckNumber = packet.SequenceNumber + 1;
                    SequenceNumber++;

                    LastSequenceNumber = packet.SequenceNumber;

                    SendEmptyPacket(Flags.ACK);

                    Status = Status.ESTABLISHED;
                }
                else if (packet.TCPFlags == (byte)Flags.SYN)
                {
                    Status = Status.CLOSED;

                    throw new NotImplementedException("Simultaneous open not supported.");
                }
                else
                {
                    Status = Status.CLOSED;

                    throw new Exception("TCP connection closed! (Flag " + packet.TCPFlags + " received on SYN_SENT state)");
                }
            }
        }
Пример #17
0
        /// <summary>
        /// Process SYN_RECEIVED Status.
        /// </summary>
        /// <param name="packet">Packet to receive.</param>
        public void ProcessSynReceived(TCPPacket packet)
        {
            if (packet.ACK)
            {
                if (TCB.SndUna <= packet.AckNumber && packet.AckNumber <= TCB.SndNxt)
                {
                    TCB.SndWnd = packet.WindowSize;
                    TCB.SndWl1 = packet.SequenceNumber;
                    TCB.SndWl2 = packet.SequenceNumber;

                    Status = Status.ESTABLISHED;
                }
                else
                {
                    SendEmptyPacket(Flags.RST, packet.AckNumber);
                }
            }
        }
Пример #18
0
        /// <summary>
        /// TCP handler.
        /// </summary>
        /// <param name="packetData">Packet data.</param>
        /// <exception cref="sys.ArgumentOutOfRangeException">Thrown on fatal error (contact support).</exception>
        /// <exception cref="sys.IO.IOException">Thrown on IO error.</exception>
        /// <exception cref="sys.ArgumentException">Thrown on fatal error (contact support).</exception>
        /// <exception cref="sys.OverflowException">Thrown if packetData array length is greater than Int32.MaxValue.</exception>
        internal static void TCPHandler(byte[] packetData)
        {
            var packet = new TCPPacket(packetData);

            if (packet.CheckCRC())
            {
                var connection = Tcp.GetConnection(packet.DestinationPort, packet.SourcePort, packet.DestinationIP, packet.SourceIP);

                if (connection != null)
                {
                    connection.ReceiveData(packet);
                }
            }
            else
            {
                Global.mDebugger.Send("Checksum incorrect! Packet passed.");
            }
        }
Пример #19
0
        /// <summary>
        /// Process LISTEN Status.
        /// </summary>
        /// <param name="packet">Packet to receive.</param>
        public void ProcessListen(TCPPacket packet)
        {
            if (packet.RST)
            {
                Status = Status.CLOSED;

                throw new Exception("TCP connection resetted! (RST received on LISTEN state)");
            }
            else if (packet.FIN)
            {
                Status = Status.CLOSED;

                throw new Exception("TCP connection closed! (FIN received on LISTEN state)");
            }
            else if (packet.ACK)
            {
                AckNumber      = packet.SequenceNumber;
                SequenceNumber = packet.AckNumber;

                Status = Status.ESTABLISHED;
            }
            else if (packet.SYN)
            {
                Status = Status.SYN_RECEIVED;

                source = IPConfig.FindNetwork(packet.SourceIP);

                AckNumber = packet.SequenceNumber + 1;

                var rnd = new Random();
                SequenceNumber = (uint)((rnd.Next(0, Int32.MaxValue)) << 32) | (uint)(rnd.Next(0, Int32.MaxValue));

                destination     = packet.SourceIP;
                destinationPort = packet.SourcePort;

                SendEmptyPacket(Flags.SYN | Flags.ACK);
            }
        }
Пример #20
0
        /// <summary>
        /// Process ESTABLISHED Status.
        /// </summary>
        /// <param name="packet">Packet to receive.</param>
        public void ProcessEstablished(TCPPacket packet)
        {
            if (packet.ACK && !packet.FIN)
            {
                if (packet.PSH)
                {
                    if (packet.SequenceNumber > LastSequenceNumber) //dup check
                    {
                        AckNumber += packet.TCP_DataLength;

                        LastSequenceNumber = packet.SequenceNumber;

                        Data = ArrayHelper.Concat(Data, packet.TCP_Data);

                        rxBuffer.Enqueue(packet);

                        SendEmptyPacket(Flags.ACK);
                    }
                }

                if (WaitingAck)
                {
                    if (packet.AckNumber == SequenceNumber)
                    {
                        WaitingAck = false;
                    }
                }
                else if (!packet.PSH)
                {
                    if (packet.SequenceNumber >= AckNumber && packet.TCP_DataLength > 0) //packet sequencing
                    {
                        AckNumber += packet.TCP_DataLength;

                        Data = ArrayHelper.Concat(Data, packet.TCP_Data);
                    }
                }
                return;
            }
            if (packet.RST)
            {
                Status = Status.CLOSED;

                throw new Exception("TCP Connection resetted!");
            }
            else if (packet.FIN && packet.ACK)
            {
                AckNumber++;

                SendEmptyPacket(Flags.ACK);

                WaitAndClose();
            }
            else if (packet.FIN)
            {
                AckNumber++;

                SendEmptyPacket(Flags.ACK);

                Status = Status.CLOSE_WAIT;

                HAL.Global.PIT.Wait(300);

                SendEmptyPacket(Flags.FIN);

                Status = Status.LAST_ACK;
            }
        }
Пример #21
0
        /// <summary>
        /// Process ESTABLISHED Status.
        /// </summary>
        /// <param name="packet">Packet to receive.</param>
        public void ProcessEstablished(TCPPacket packet)
        {
            if (packet.ACK)
            {
                if (TCB.SndUna < packet.AckNumber && packet.AckNumber <= TCB.SndNxt)
                {
                    TCB.SndUna = packet.AckNumber;

                    //Update Window Size
                    if (TCB.SndWl1 < packet.SequenceNumber || (TCB.SndWl1 == packet.SequenceNumber && TCB.SndWl2 <= packet.AckNumber))
                    {
                        TCB.SndWnd = packet.WindowSize;
                        TCB.SndWl1 = packet.SequenceNumber;
                        TCB.SndWl2 = packet.AckNumber;
                    }
                }

                // Check for duplicate packet
                if (packet.AckNumber < TCB.SndUna)
                {
                    return;
                }

                // Something not yet sent
                if (packet.AckNumber > TCB.SndNxt)
                {
                    SendEmptyPacket(Flags.ACK);
                    return;
                }

                if (packet.PSH)
                {
                    TCB.RcvNxt += packet.TCP_DataLength;

                    Data = ArrayHelper.Concat(Data, packet.TCP_Data);

                    rxBuffer.Enqueue(packet);

                    SendEmptyPacket(Flags.ACK);
                    return;
                }
                else if (packet.FIN)
                {
                    TCB.RcvNxt++;

                    SendEmptyPacket(Flags.ACK);

                    WaitAndClose();

                    return;
                }

                if (packet.TCP_DataLength > 0 && packet.SequenceNumber >= TCB.RcvNxt) //packet sequencing
                {
                    TCB.RcvNxt += packet.TCP_DataLength;

                    Data = ArrayHelper.Concat(Data, packet.TCP_Data);
                }
            }
            if (packet.RST)
            {
                Status = Status.CLOSED;

                Global.mDebugger.Send("TCP Connection resetted!");
            }
            else if (packet.FIN)
            {
                TCB.RcvNxt++;

                SendEmptyPacket(Flags.ACK);

                Status = Status.CLOSE_WAIT;

                HAL.Global.PIT.Wait(300);

                SendEmptyPacket(Flags.FIN);

                Status = Status.LAST_ACK;
            }
        }
Пример #22
0
        /// <summary>
        /// Process SYN_SENT Status.
        /// </summary>
        /// <param name="packet">Packet to receive.</param>
        public void ProcessSynSent(TCPPacket packet)
        {
            if (packet.SYN)
            {
                TCB.IRS    = packet.SequenceNumber;
                TCB.RcvNxt = packet.SequenceNumber + 1;

                if (packet.ACK)
                {
                    TCB.SndUna = packet.AckNumber;
                    TCB.SndWnd = packet.WindowSize;
                    TCB.SndWl1 = packet.SequenceNumber;
                    TCB.SndWl2 = packet.AckNumber;

                    SendEmptyPacket(Flags.ACK);

                    Status = Status.ESTABLISHED;
                }
                else if (packet.TCPFlags == (byte)Flags.SYN)
                {
                    Status = Status.CLOSED;

                    Global.mDebugger.Send("Simultaneous open not supported.");
                }
                else
                {
                    Status = Status.CLOSED;

                    Global.mDebugger.Send("TCP connection closed! (" + packet.getFlags() + " received on SYN_SENT state)");
                }
            }
            else if (packet.ACK)
            {
                //Check for bad ACK packet
                if ((packet.AckNumber - TCB.ISS) < 0 || (packet.AckNumber - TCB.SndNxt) > 0)
                {
                    SendEmptyPacket(Flags.RST, packet.AckNumber);

                    Global.mDebugger.Send("Bad ACK received at SYN_SENT.");
                }
                else
                {
                    TCB.RcvNxt = packet.SequenceNumber;
                    TCB.SndNxt = packet.AckNumber;

                    Status = Status.ESTABLISHED;
                }
            }
            else if (packet.FIN)
            {
                Status = Status.CLOSED;

                Global.mDebugger.Send("TCP connection closed! (FIN received on SYN_SENT state).");
            }
            else if (packet.RST)
            {
                Status = Status.CLOSED;

                Global.mDebugger.Send("Connection refused by remote computer.");
            }
        }
Пример #23
0
        /// <summary>
        /// Handle incoming TCP packets according to current connection status.
        /// </summary>
        /// <param name="packet">Packet to receive.</param>
        /// <exception cref="OverflowException">Thrown on fatal error (contact support).</exception>
        /// <exception cref="Sys.IO.IOException">Thrown on IO error.</exception>
        internal void ReceiveData(TCPPacket packet)
        {
            Global.mDebugger.Send("[" + table[(int)Status] + "] " + packet.ToString());

            if (Status == Status.CLOSED)
            {
                //DO NOTHING
            }
            else if (Status == Status.LISTEN)
            {
                ProcessListen(packet);
            }
            else if (Status == Status.SYN_SENT)
            {
                ProcessSynSent(packet);
            }
            else
            {
                // Check sequence number and segment data.
                if (TCB.RcvNxt <= packet.SequenceNumber && packet.SequenceNumber + packet.TCP_DataLength < TCB.RcvNxt + TCB.RcvWnd)
                {
                    switch (Status)
                    {
                    case Status.SYN_RECEIVED:
                        ProcessSynReceived(packet);
                        break;

                    case Status.ESTABLISHED:
                        ProcessEstablished(packet);
                        break;

                    case Status.FIN_WAIT1:
                        ProcessFinWait1(packet);
                        break;

                    case Status.FIN_WAIT2:
                        ProcessFinWait2(packet);
                        break;

                    case Status.CLOSE_WAIT:
                        ProcessCloseWait(packet);
                        break;

                    case Status.CLOSING:
                        ProcessClosing(packet);
                        break;

                    case Status.LAST_ACK:
                        ProcessCloseWait(packet);
                        break;

                    case Status.TIME_WAIT:
                        break;

                    default:
                        Global.mDebugger.Send("Unknown TCP connection state.");
                        break;
                    }
                }
                else
                {
                    if (!packet.RST)
                    {
                        SendEmptyPacket(Flags.ACK);
                    }

                    Global.mDebugger.Send("Sequence number or segment data invalid, packet passed.");
                }
            }
        }