internal override void HandleReceivedMessage(IncomingNetMessage message, NetworkEndPoint senderEndpoint, double localTimeRecv)
        {
            //LogWrite("NetClient received message " + message);
            double now = NetTime.Now;

            int payLen = message.m_data.LengthBytes;

            // Discovery response?
            if (message.m_type == NetMessageLibraryType.System && payLen > 0)
            {
                NetSystemType sysType = (NetSystemType)message.m_data.PeekByte();

                if (sysType == NetSystemType.DiscoveryResponse)
                {
                    message.m_data.ReadByte();                     // step past system type byte
                    IncomingNetMessage resMsg = m_discovery.HandleResponse(message, senderEndpoint);
                    if (resMsg != null)
                    {
                        resMsg.m_senderEndPoint = senderEndpoint;
                        EnqueueReceivedMessage(resMsg);
                    }
                    return;
                }
            }

            // Out of band?
            if (message.m_type == NetMessageLibraryType.OutOfBand)
            {
                if ((m_enabledMessageTypes & NetMessageType.OutOfBandData) != NetMessageType.OutOfBandData)
                {
                    return;                     // drop
                }
                // just deliver
                message.m_msgType        = NetMessageType.OutOfBandData;
                message.m_senderEndPoint = senderEndpoint;
                EnqueueReceivedMessage(message);
                return;
            }

            if (message.m_sender != m_serverConnection && m_serverConnection != null)
            {
                return;                 // don't talk to strange senders after this
            }
            if (message.m_type == NetMessageLibraryType.Acknowledge)
            {
                m_serverConnection.HandleAckMessage(now, message);
                return;
            }

            // Handle system types
            if (message.m_type == NetMessageLibraryType.System)
            {
                if (payLen < 1)
                {
                    if ((m_enabledMessageTypes & NetMessageType.BadMessageReceived) == NetMessageType.BadMessageReceived)
                    {
                        NotifyApplication(NetMessageType.BadMessageReceived, "Received malformed system message: " + message, m_serverConnection, senderEndpoint);
                    }
                    return;
                }
                NetSystemType sysType = (NetSystemType)message.m_data.Data[0];
                switch (sysType)
                {
                case NetSystemType.ConnectResponse:
                case NetSystemType.Ping:
                case NetSystemType.Pong:
                case NetSystemType.Disconnect:
                case NetSystemType.ConnectionRejected:
                case NetSystemType.StringTableAck:
                    if (m_serverConnection != null)
                    {
                        m_serverConnection.HandleSystemMessage(message, localTimeRecv);
                    }
                    return;

                case NetSystemType.Connect:
                case NetSystemType.ConnectionEstablished:
                case NetSystemType.Discovery:
                case NetSystemType.Error:
                default:
                    if ((m_enabledMessageTypes & NetMessageType.BadMessageReceived) == NetMessageType.BadMessageReceived)
                    {
                        NotifyApplication(NetMessageType.BadMessageReceived, "Undefined behaviour for client and " + sysType, m_serverConnection, senderEndpoint);
                    }
                    return;
                }
            }

            Debug.Assert(
                message.m_type == NetMessageLibraryType.User ||
                message.m_type == NetMessageLibraryType.UserFragmented
                );

            if (m_serverConnection.Status == NetConnectionStatus.Connecting)
            {
                m_serverConnection.Disconnect("Received user message before ConnectResponse", 0.0f, true, true);
                return;

                /*
                 * // lost connectresponse packet?
                 * // Emulate it;
                 * LogVerbose("Received user message before ConnectResponse; emulating ConnectResponse...", m_serverConnection);
                 * IncomingNetMessage emuMsg = CreateIncomingMessage();
                 * emuMsg.m_type = NetMessageLibraryType.System;
                 * emuMsg.m_data.Reset();
                 * emuMsg.m_data.Write((byte)NetSystemType.ConnectResponse);
                 * m_serverConnection.HandleSystemMessage(emuMsg, now);
                 */

                // ... and proceed to pick up user message
            }

            // add to pick-up queue
            m_serverConnection.HandleUserMessage(message, now);
        }