context: #region References
  using System;
  using System.Collections.Generic;
  using System.Net.Sockets;
  using System.Threading;
  
  using Server.Diagnostics;
  #endregion
  
  namespace Server.Network
  {
  	public class MessagePump
  	{
  		private Queue<NetState> m_Queue;
  		private Queue<NetState> m_WorkingQueue;
  		private readonly Queue<NetState> m_Throttled;
  
  		public Listener[] Listeners { get; set; }
  		
  		public MessagePump()
  		{
  			var ipep = Listener.EndPoints;
  
  			Listeners = new Listener[ipep.Length];
  
  			bool success = false;
  
  			do
  			{
  				for (int i = 0; i < ipep.Length; i++)
  				{
  					Listeners[i] = new Listener(ipep[i]);
  
  					success = true;
  				}
  
  				if (!success)
  				{
  					Utility.PushColor(ConsoleColor.Yellow);
  					Console.WriteLine("Retrying...");
  					Utility.PopColor();
  
  					Thread.Sleep(10000);
  				}
  			}
  			while (!success);
  
  			m_Queue = new Queue<NetState>();
  			m_WorkingQueue = new Queue<NetState>();
  			m_Throttled = new Queue<NetState>();
  		}
  
  		public void AddListener(Listener l)
  		{
  			var old = Listeners;
  
  			Listeners = new Listener[old.Length + 1];
  
  			for (int i = 0; i < old.Length; ++i)
  			{
  				Listeners[i] = old[i];
  			}
  
  			Listeners[old.Length] = l;
  		}
  
  		private void CheckListener()
  		{
  			foreach (Listener l in Listeners)
  			{
  				var accepted = l.Slice();
  
  				foreach (Socket s in accepted)
  				{
  					NetState ns = new NetState(s, this);
  
  					ns.Start();
  
  					if (ns.Running)
  					{
  						Utility.PushColor(ConsoleColor.Green);
  						Console.WriteLine("Client: {0}: Connected. [{1} Online]", ns, NetState.Instances.Count);
  						Utility.PopColor();
  					}
  				}
  			}
  		}
  
  		public void OnReceive(NetState ns)
  		{
  			lock (this)
  				m_Queue.Enqueue(ns);
  
  			Core.Set();
  		}
  
  		public void Slice()
  		{
  			CheckListener();
  
  			lock (this)
  			{
  				var temp = m_WorkingQueue;
  				m_WorkingQueue = m_Queue;
  				m_Queue = temp;
  			}
  
  			while (m_WorkingQueue.Count > 0)
  			{
  				NetState ns = m_WorkingQueue.Dequeue();
  
  				if (ns.Running)
  				{
  					HandleReceive(ns);
  				}
  			}
  
  			lock (this)
  			{
  				while (m_Throttled.Count > 0)
  				{
  					m_Queue.Enqueue(m_Throttled.Dequeue());
  				}
  			}
  		}
  
  		private const int BufferSize = 4096;
  		private readonly BufferPool m_Buffers = new BufferPool("Processor", 4, BufferSize);
  
  		public static bool HandleSeed(NetState ns, ByteQueue buffer)
  		{
  			if (buffer.GetPacketID() == 0xEF)
  			{
  				// new packet in client	6.0.5.0	replaces the traditional seed method with a	seed packet
  				// 0xEF	= 239 =	multicast IP, so this should never appear in a normal seed.	 So	this is	backwards compatible with older	clients.
  				ns.Seeded = true;
  				return true;
  			}
  			
  			if (buffer.Length >= 4)
  			{
  				var m_Peek = new byte[4];
  
  				buffer.Dequeue(m_Peek, 0, 4);
  
  				uint seed = (uint)((m_Peek[0] << 24) | (m_Peek[1] << 16) | (m_Peek[2] << 8) | m_Peek[3]);
  
  				if (seed == 0)
  				{
  					Utility.PushColor(ConsoleColor.Red);
  					Console.WriteLine("Login: {0}: Invalid Client", ns);
  					Utility.PopColor();
  
  					ns.Dispose();
  
  					return false;
  				}
  
  				ns.Seed = seed;
  				ns.Seeded = true;
  
  				return true;
  			}
  
  			return false;
  		}
  
  		public static bool CheckEncrypted(NetState ns, int packetID)
  		{
  			if (!ns.SentFirstPacket && packetID != 0xF0 && packetID != 0xF1 && packetID != 0xCF && packetID != 0x80 &&
  				packetID != 0x91 && packetID != 0xA4 && packetID != 0xEF && packetID != 0xE4 && packetID != 0xFF)
  			{
  				Utility.PushColor(ConsoleColor.Red);
  				Console.WriteLine("Client: {0}: Encrypted Client Unsupported", ns);
  				Utility.PopColor();
  				
  				ns.Dispose();
  
  				return true;
  			}
  
  			return false;
  		}
  
  		public void HandleReceive(NetState ns)
  		{
  			ByteQueue buffer = ns.Buffer;
  
  			if (buffer == null || buffer.Length <= 0)
  			{
  				return;
  			}
  
  			lock (buffer)
  			{
  				if (!ns.Seeded && !HandleSeed(ns, buffer))
  				{
  					return;
  				}
  
  				int length = buffer.Length;
  
  				while (length > 0 && ns.Running)
  				{
  					int packetID = buffer.GetPacketID();
  
  					if (CheckEncrypted(ns, packetID))
  					{
  						return;
  					}
  
  					PacketHandler handler = ns.GetHandler(packetID);
  
  					if (handler == null)
  					{
  						var data = new byte[length];
  
gt: 						length = buffer.Dequeue(data, 0, length);