Пример #1
0
        private void PacketHandler()
        {
            IncomingPacket incomingPacket = new IncomingPacket();
            Packet         packet         = null;
            Simulator      simulator      = null;

            while (connected)
            {
                // Reset packet to null for the check below
                packet = null;

                if (PacketInbox.Dequeue(200, ref incomingPacket))
                {
                    packet    = incomingPacket.Packet;
                    simulator = incomingPacket.Simulator;

                    if (packet != null)
                    {
                        // Skip the ACK handling on packets synthesized from CAPS messages
                        if (packet.Header.Sequence != 0)
                        {
                            #region ACK accounting
                            // TODO: Replace PacketArchive Queue<> with something more efficient

                            // Check the archives to see whether we already received this packet
                            lock (simulator.PacketArchive)
                            {
                                if (simulator.PacketArchive.Contains(packet.Header.Sequence))
                                {
                                    if (packet.Header.Resent)
                                    {
                                        Client.DebugLog("Received resent packet #" + packet.Header.Sequence);
                                    }
                                    else
                                    {
                                        Client.Log(String.Format("Received a duplicate of packet #{0}, current type: {1}",
                                                                 packet.Header.Sequence, packet.Type), Helpers.LogLevel.Warning);
                                    }

                                    // Avoid firing a callback twice for the same packet
                                    continue;
                                }
                                else
                                {
                                    // Keep the PacketArchive size within a certain capacity
                                    while (simulator.PacketArchive.Count >= Settings.PACKET_ARCHIVE_SIZE)
                                    {
                                        simulator.PacketArchive.Dequeue(); simulator.PacketArchive.Dequeue();
                                        simulator.PacketArchive.Dequeue(); simulator.PacketArchive.Dequeue();
                                    }

                                    simulator.PacketArchive.Enqueue(packet.Header.Sequence);
                                }
                            }

                            #endregion ACK accounting

                            #region ACK handling

                            // Handle appended ACKs
                            if (packet.Header.AppendedAcks)
                            {
                                lock (simulator.NeedAck)
                                {
                                    for (int i = 0; i < packet.Header.AckList.Length; i++)
                                    {
                                        simulator.NeedAck.Remove(packet.Header.AckList[i]);
                                    }
                                }
                            }

                            // Handle PacketAck packets
                            if (packet.Type == PacketType.PacketAck)
                            {
                                PacketAckPacket ackPacket = (PacketAckPacket)packet;

                                lock (simulator.NeedAck)
                                {
                                    for (int i = 0; i < ackPacket.Packets.Length; i++)
                                    {
                                        simulator.NeedAck.Remove(ackPacket.Packets[i].ID);
                                    }
                                }
                            }

                            #endregion ACK handling
                        }

                        #region FireCallbacks

                        if (Client.Settings.SYNC_PACKETCALLBACKS)
                        {
                            PacketEvents.RaiseEvent(PacketType.Default, packet, simulator);
                            PacketEvents.RaiseEvent(packet.Type, packet, simulator);
                        }
                        else
                        {
                            PacketEvents.BeginRaiseEvent(PacketType.Default, packet, simulator);
                            PacketEvents.BeginRaiseEvent(packet.Type, packet, simulator);
                        }

                        #endregion FireCallbacks
                    }
                }
            }
        }