private void ReceivedPong(double rtSeconds, NetMessage pong)
        {
            double now = NetTime.Now;

            m_lastPongReceived = now;
            if (pong != null)
            {
                ushort remote = pong.m_data.ReadUInt16();
                ushort local  = NetTime.Encoded(now);
                int    diff   = local - remote - (int)(rtSeconds * 1000.0);
                if (diff < 0)
                {
                    diff += ushort.MaxValue;
                }
                m_remoteTimeOffset = diff;                 // TODO: slowly go towards? (m_remoteTimeOffset + diff) / 2;
                m_owner.LogVerbose("Got pong; roundtrip was " + (int)(rtSeconds * 1000) + " ms");
            }

            m_latencyHistory[2]   = m_latencyHistory[1];
            m_latencyHistory[1]   = m_latencyHistory[0];
            m_latencyHistory[0]   = rtSeconds;
            m_currentAvgRoundtrip = ((rtSeconds * 3) + (m_latencyHistory[1] * 2) + m_latencyHistory[2]) / 6.0;

            m_ackMaxDelayTime = (float)(
                m_owner.m_config.m_maxAckWithholdTime * rtSeconds * m_owner.m_config.m_resendTimeMultiplier
                );
        }
        internal static void QueuePing(NetBase netBase, IPEndPoint toEndPoint, double now)
        {
            ushort    nowEnc = NetTime.Encoded(now);
            NetBuffer buffer = netBase.m_scratchBuffer;

            buffer.Reset();
            buffer.Write(nowEnc);
            netBase.QueueSingleUnreliableSystemMessage(
                NetSystemType.Ping,
                buffer,
                toEndPoint,
                false
                );
        }