//Make sure this runs on the reading thread
		private void OnMessageRecievedCallback(NetPeer peer)
		{
			//Read the entire chunk of messages; not just one
			//The wait handle has been consumed so we have no choice.
			//Can't do one at a time.
			List<NetIncomingMessage> messages = new List<NetIncomingMessage>(10);

			if (peer.ReadMessages(messages) == 0)
				return;

			foreach(NetIncomingMessage message in messages)
			{
				//If the context factory cannot create a context for this
				//message type then we should not enter the lock and attempt to create a context for it.
				if (!messageContextFactory.CanCreateContext(message.MessageType))
					return;

				incomingMessageQueue.syncRoot.EnterWriteLock();
				try
				{
					//enqueues the message including the meaningful context with which it was recieved.
					incomingMessageQueue.Enqueue(messageContextFactory.CreateContext(message));

					//Signal the incoming message handling thread that there is a message to recieve.
					incomingMessageQueue.QueueSemaphore.Release(1);
				}
				finally
				{
					incomingMessageQueue.syncRoot.ExitWriteLock();
				}
			}
		}
        public bool PumpEvents()
        {
            _incomingMessages.Clear();
            _peer.ReadMessages(_incomingMessages);

            foreach (NetIncomingMessage incomingMessage in _incomingMessages)
            {
                try
                {
                    LidgrenTransportChannel transportChannel;
                    switch (incomingMessage.MessageType)
                    {
                    case NetIncomingMessageType.VerboseDebugMessage:
                    case NetIncomingMessageType.DebugMessage:
                        _logger.Debug(incomingMessage.ReadString());
                        break;

                    case NetIncomingMessageType.WarningMessage:
                        _logger.Warning(incomingMessage.ReadString());
                        break;

                    case NetIncomingMessageType.ErrorMessage:
                        _logger.Error(incomingMessage.ReadString());
                        break;

                    case NetIncomingMessageType.StatusChanged:
                        var status = (NetConnectionStatus)incomingMessage.ReadByte();
                        switch (status)
                        {
                        case NetConnectionStatus.InitiatedConnect:
                        case NetConnectionStatus.ReceivedInitiation:
                        case NetConnectionStatus.RespondedAwaitingApproval:
                        case NetConnectionStatus.RespondedConnect:
                        case NetConnectionStatus.Disconnecting:
                            _logger.StatusChanged(status.ToString(), incomingMessage.SenderConnection.RemoteUniqueIdentifier);
                            break;

                        case NetConnectionStatus.Connected:
                            _logger.StatusChanged(status.ToString(), incomingMessage.SenderConnection.RemoteUniqueIdentifier);
                            var channel = new LidgrenTransportChannel(incomingMessage.SenderConnection);
                            _processIncommingConnection(channel);
                            _channels.Add(incomingMessage.SenderConnection.RemoteUniqueIdentifier, channel);
                            break;

                        case NetConnectionStatus.Disconnected:
                            _logger.StatusChanged(status.ToString(), incomingMessage.SenderConnection.RemoteUniqueIdentifier);
                            if (_channels.TryGetValue(incomingMessage.SenderConnection.RemoteUniqueIdentifier, out transportChannel))
                            {
                                transportChannel.OnDisconnect();
                                _channels.Remove(incomingMessage.SenderConnection.RemoteUniqueIdentifier);
                            }
                            break;

                        default:
                            throw new ArgumentOutOfRangeException();
                        }
                        break;

                    case NetIncomingMessageType.Data:
                        int numBytes = incomingMessage.ReadInt32();
                        _logger.OnDataReceived(incomingMessage.SenderConnection.RemoteUniqueIdentifier, numBytes);
                        if (_channels.TryGetValue(incomingMessage.SenderConnection.RemoteUniqueIdentifier, out transportChannel))
                        {
                            incomingMessage.ReadBytes(_buffer, 0, numBytes);
                            transportChannel.OnDataReceived(new ArraySegment <byte>(_buffer, 0, numBytes));
                        }
                        break;

                    default:
                        _logger.Debug("Received " + incomingMessage.MessageType);
                        break;
                    }
                }
                finally
                {
                    _peer.Recycle(incomingMessage);
                }
            }

            return(false);
        }
        public bool PumpEvents()
        {
            _incomingMessages.Clear();
            _peer.ReadMessages(_incomingMessages);

            foreach (NetIncomingMessage incomingMessage in _incomingMessages)
            {
                switch (incomingMessage.MessageType)
                {
                case NetIncomingMessageType.VerboseDebugMessage:
                case NetIncomingMessageType.DebugMessage:
                    Log.Debug(incomingMessage.ReadString());
                    break;

                case NetIncomingMessageType.WarningMessage:
                    Log.Warn(incomingMessage.ReadString());
                    break;

                case NetIncomingMessageType.ErrorMessage:
                    Log.Error(incomingMessage.ReadString());
                    break;

                case NetIncomingMessageType.StatusChanged:
                    var status = (NetConnectionStatus)incomingMessage.ReadByte();
                    switch (status)
                    {
                    case NetConnectionStatus.InitiatedConnect:
                        break;

                    case NetConnectionStatus.ReceivedInitiation:
                        break;

                    case NetConnectionStatus.RespondedAwaitingApproval:
                        break;

                    case NetConnectionStatus.RespondedConnect:
                        break;

                    case NetConnectionStatus.Connected:
                        var channel = new LidgrenNetChannel(incomingMessage.SenderConnection, _bufferManager);
                        INetChannelListener listener = _peerFactory.OnNetConnect(channel);
                        channel.Listener = listener;
                        _channels.Add(incomingMessage.SenderConnection.RemoteUniqueIdentifier, channel);
                        break;

                    case NetConnectionStatus.Disconnecting:
                        Log.Debug("Channel #{0} is disconnecting", incomingMessage.SenderConnection.RemoteUniqueIdentifier);
                        break;

                    case NetConnectionStatus.Disconnected:
                        Log.Debug("Channel #{0} has been disconnected", incomingMessage.SenderConnection.RemoteUniqueIdentifier);
                        LidgrenNetChannel netChannel;
                        if (_channels.TryGetValue(incomingMessage.SenderConnection.RemoteUniqueIdentifier, out netChannel))
                        {
                            netChannel.Listener.OnDisconnected();
                            _channels.Remove(incomingMessage.SenderConnection.RemoteUniqueIdentifier);
                            netChannel.Dispose();
                        }
                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                    }
                    break;

                case NetIncomingMessageType.Data:
                    int numBytes = incomingMessage.ReadInt32();
                    incomingMessage.ReadBytes(_buffer, 0, numBytes);
                    _stream.Position = 0;
                    _channels[incomingMessage.SenderConnection.RemoteUniqueIdentifier].Listener.OnNetData(_reader);
                    break;

                default:
                    Log.Debug("Received " + incomingMessage.MessageType);
                    break;
                }
                _peer.Recycle(incomingMessage);
            }

            return(false);
        }