public void ClientRecv(byte[] data, int offset)
        {
            //            Console.Out.WriteLine($"KeepAliveHandler.ClientRecv: {Utility.ByteArrayToHexString(data, offset)}.");
            Packets.NaiveParsePacket <FFXIVKeepAliveData>(data, offset, out var pkt);
            //            Console.Out.WriteLine($"KeepAliveHandler.ClientRecv: ID={pkt.Id}, Timestamp={pkt.Timestamp}.");

            OnClientRecv?.Invoke(pkt);
            if (pkt.Id != _currentId)
            {
                return;
            }
            var now    = DateTime.UtcNow;
            var millis = (now - _lastKeepAliveSent).TotalMilliseconds;

            OnPingSample?.Invoke(millis, now);
        }
        private void HandleServerPing(byte[] data, int offset)
        {
            //            Console.Out.WriteLine($"Pong recv: {Utility.ByteArrayToHexString(data, offset)}.");
            Packets.NaiveParsePacket <FFXIVServerIpcPingData>(data, offset, out var pkt);
            //            Console.Out.WriteLine($"HandleServerPing: Timestamp={pkt.Timestamp - 0x000014D00000000}.");

            var index = (uint)(pkt.Timestamp - TIMESTAMP_DELTA);

            if (_pingRecords.TryGetValue(index, out var time))
            {
                var now    = DateTime.UtcNow;
                var millis = (now - time).TotalMilliseconds;
                OnPingSample?.Invoke(millis, now);
                _pingRecords.Remove(index);
            }
            _pingRecords.Keys.Where(it => it < index).ToList().ForEach(it => _pingRecords.Remove(it));
        }
        private void HandleNewSample(double rtt, DateTime sampleTime)
        {
            var now = sampleTime.EpochMillis();

            _records[now] = rtt;

            var windowLeft = now - 5 * 1000; // window size = 5s

            // Remove records out of window
            _records.Keys.TakeWhile(it => it < windowLeft).ToList().ForEach(it => _records.Remove(it));

            // Use the min value in that window as the current ping
            CurrentPing = new ConnectionPing()
            {
                Connection = Connection,
                Ping       = _records.Values.Min(),
                SampleTime = sampleTime,
            };

            OnPingSample?.Invoke(CurrentPing);
        }
 private void MonitorOnOnPingSample(ConnectionPing ping)
 {
     CurrentPing = _connections.Select(it => it.Value.CurrentPing).Max();
     OnPingSample?.Invoke(CurrentPing);
 }