internal void Update()
        {
            if (this.timedOut <= 0)
            {
                this.Close("disconnect.timeout");
            }
            this.timedOut--;

            if (this.ackQueue.Count > 0)
            {
                ACK ack = new ACK();
                ack.packets = this.ackQueue.Values.ToArray();
                this.server.SendPacket(ack, this.point.Address, this.point.Port);
                this.ackQueue.Clear();
            }

            if (this.nackQueue.Count > 0)
            {
                NACK nack = new NACK();
                nack.packets = this.nackQueue.Values.ToArray();
                this.server.SendPacket(nack, this.point.Address, this.point.Port);
                this.nackQueue.Clear();
            }

            int[] a = this.receivedWindow.Values.ToArray();
            for (int i = 0; i < this.receivedWindow.Values.Count; ++i)
            {
                int seq = a[i];
                if (seq < this.startSeq)
                {
                    if (this.receivedWindow.ContainsKey(seq))
                    {
                        this.receivedWindow.Remove(seq);
                    }
                }
                else
                {
                    break;
                }
            }

            if (packetToSend.Count > 0)
            {
                foreach (DataPacket pk in packetToSend.Values)
                {
                    this.server.SendPacket(pk, point.Address, point.Port);
                }
                packetToSend.Clear();
            }

            SendQueuePackets();
        }
        internal void DataPacketHandle(Packet pk)
        {
            if (pk is DataPacket)
            {
                DataPacket packet = (DataPacket)pk;
                packet.Decode();

                this.timedOut = 1000;

                if (packet.SeqNumber < this.startSeq || packet.SeqNumber > this.endSeq || this.receivedWindow.ContainsKey(packet.SeqNumber))
                {
                    return;
                }

                int diff = packet.SeqNumber - this.lastSeqNumber;

                if (this.nackQueue.ContainsKey(packet.SeqNumber))
                {
                    this.nackQueue.Remove(packet.SeqNumber);
                }

                if (!this.receivedWindow.ContainsKey(packet.SeqNumber))
                {
                    this.receivedWindow.Add(packet.SeqNumber, packet.SeqNumber);
                }

                if (!this.ackQueue.ContainsKey(packet.SeqNumber))
                {
                    this.ackQueue.Add(packet.SeqNumber, packet.SeqNumber);
                }

                if (diff != 1)
                {
                    for (int i = 0; i < diff; ++i)
                    {
                        if (!this.receivedWindow.ContainsKey(packet.SeqNumber - i))
                        {
                            if (!this.nackQueue.ContainsKey(packet.SeqNumber - i))
                            {
                                this.nackQueue.Add(packet.SeqNumber - i, packet.SeqNumber - i);
                            }
                        }
                    }
                }

                if (diff >= 1)
                {
                    this.lastSeqNumber = packet.SeqNumber;
                    this.startSeq     += diff;
                    this.endSeq       += diff;
                }

                for (int i = 0; i < packet.Packets.Length; ++i)
                {
                    if (packet.Packets[i] is EncapsulatedPacket)
                    {
                        this.EncapsulatedPacketHandle((EncapsulatedPacket)packet.Packets[i]);
                    }
                }

                packet.Packets = null;
            }
            else
            {
                if (pk is ACK)
                {
                    ACK ack = (ACK)pk;
                    pk.Decode();
                    for (int i = 0; i < ack.packets.Length; ++i)
                    {
                        if (recoveryQueue.ContainsKey(ack.packets[i]))
                        {
                            recoveryQueue.Remove(ack.packets[i]);
                        }
                    }
                }
                else if (pk is NACK)
                {
                    NACK nack = (NACK)pk;
                    pk.Decode();
                    for (int i = 0; i < nack.packets.Length; ++i)
                    {
                        if (recoveryQueue.ContainsKey(nack.packets[i]))
                        {
                            DataPacket dp = recoveryQueue[nack.packets[i]];
                            dp.SeqNumber = this.sendSeqNumber++;
                            packetToSend.Add(nack.packets[i], dp);
                            recoveryQueue.Remove(nack.packets[i]);
                        }
                        else
                        {
                            Logger.Log("Not Recovery Packet");
                        }
                    }
                }
            }
        }