private static unsafe TcpStateStatistics GetStatistics(byte[] data, AddressFamily addressFamily,
                                                               TcpStateStatistics stats, int?pidFilter, int?portFilter)
        {
            fixed(byte *b = data)
            {
                var count = *(int *)b;

                if (addressFamily == AddressFamily.AF_INET)
                {
                    var ptr = (MIB_TCPROW_OWNER_PID *)(b + 4);

                    for (var i = 0; i < count; i++)
                    {
                        AddToStats(ref stats, ptr[i].dwState, ptr[i].dwOwningPid, ptr[i].dwLocalPort, pidFilter, portFilter);
                    }

                    return(stats);
                }

                if (addressFamily == AddressFamily.AF_INET6)
                {
                    var ptr = (MIB_TCP6ROW_OWNER_PID *)(b + 4);

                    for (var i = 0; i < count; i++)
                    {
                        AddToStats(ref stats, ptr[i].dwState, ptr[i].dwOwningPid, ptr[i].dwLocalPort, pidFilter, portFilter);
                    }
                }
                return(stats);
            }
        }
        private static void Add(TcpStateStatistics stats, MIB_TCP_STATE state)
        {
            switch (state)
            {
            case MIB_TCP_STATE.MIB_TCP_STATE_CLOSED:
                stats.Closed++;
                break;

            case MIB_TCP_STATE.MIB_TCP_STATE_LISTEN:
                stats.Listen++;
                break;

            case MIB_TCP_STATE.MIB_TCP_STATE_SYN_SENT:
                stats.SynSent++;
                break;

            case MIB_TCP_STATE.MIB_TCP_STATE_SYN_RCVD:
                stats.SynRcvd++;
                break;

            case MIB_TCP_STATE.MIB_TCP_STATE_ESTAB:
                stats.Established++;
                break;

            case MIB_TCP_STATE.MIB_TCP_STATE_FIN_WAIT1:
                stats.FinWait1++;
                break;

            case MIB_TCP_STATE.MIB_TCP_STATE_FIN_WAIT2:
                stats.FinWait2++;
                break;

            case MIB_TCP_STATE.MIB_TCP_STATE_CLOSE_WAIT:
                stats.CloseWait++;
                break;

            case MIB_TCP_STATE.MIB_TCP_STATE_CLOSING:
                stats.Closing++;
                break;

            case MIB_TCP_STATE.MIB_TCP_STATE_LAST_ACK:
                stats.LastAck++;
                break;

            case MIB_TCP_STATE.MIB_TCP_STATE_TIME_WAIT:
                stats.TimeWait++;
                break;

            case MIB_TCP_STATE.MIB_TCP_STATE_DELETE_TCB:
                stats.DeleteTcb++;
                break;

            default:
                stats.Unknown++;
                break;
            }
        }
        public static void GetTcpStats(AddressFamily addressFamily, TcpStateStatistics stats, int?pidFilter = null, int?portFilter = null)
        {
            ThrowOnUnknownAddressFamily(addressFamily);

            var pool = addressFamily == AddressFamily.AF_INET ? ArrayBufferPoolV4 : ArrayBufferPoolV6;

            using (var arrayBuffer = pool.AcquireHandle())
            {
                GetTcpTableWithPid(addressFamily, arrayBuffer);
                GetStatistics(arrayBuffer.Resource.Buffer, addressFamily, stats, pidFilter, portFilter);
            }
        }
        private static void AddToStats(ref TcpStateStatistics stats, MIB_TCP_STATE tcpState, int pid, int rawPort, int?pidFilter, int?portFilter)
        {
            if (pidFilter.HasValue && pid != pidFilter)
            {
                return;
            }
            var port = GetPort(rawPort);

            if (portFilter.HasValue && port != portFilter)
            {
                return;
            }
            Add(stats, tcpState);
        }
        private static unsafe void GetStatisticsForAllProcesses(byte[] data, AddressFamily addressFamily, Dictionary <int, TcpStateStatistics> stats)
        {
            fixed(byte *b = data)
            {
                var count = *(int *)b;

                if (addressFamily == AddressFamily.AF_INET)
                {
                    var ptr = (MIB_TCPROW_OWNER_PID *)(b + 4);

                    for (var i = 0; i < count; i++)
                    {
                        var pid = ptr[i].dwOwningPid;
                        if (!stats.TryGetValue(pid, out var stat))
                        {
                            stats[pid] = stat = new TcpStateStatistics();
                        }
                        Add(stat, ptr[i].dwState);
                    }
                }

                if (addressFamily == AddressFamily.AF_INET6)
                {
                    var ptr = (MIB_TCP6ROW_OWNER_PID *)(b + 4);

                    for (var i = 0; i < count; i++)
                    {
                        var pid = ptr[i].dwOwningPid;
                        if (!stats.TryGetValue(pid, out var stat))
                        {
                            stats[pid] = stat = new TcpStateStatistics();
                        }
                        Add(stat, ptr[i].dwState);
                    }
                }
            }
        }