static bool StreamTcpPacketIsOutdatedAck(TcpSession *ssn, Packet *p)
{
    if (ssn->state < TCP_ESTABLISHED)
        return false;
    if (p->payload_len != 0)
        return false;
    if ((p->tcph->th_flags & (TH_ACK | TH_SYN | TH_FIN | TH_RST)) != TH_ACK)
        return false;

    /* lets see if this is a packet that is entirely eclipsed by earlier ACKs */
    if (PKT_IS_TOSERVER(p)) {
        if (SEQ_EQ(TCP_GET_SEQ(p), ssn->client.next_seq) &&
                SEQ_LT(TCP_GET_ACK(p), ssn->server.last_ack)) {
            if (!TCP_HAS_SACK(p)) {
                SCLogDebug("outdated ACK (no SACK, SEQ %u vs next_seq %u)", TCP_GET_SEQ(p),
                        ssn->client.next_seq);
                return true;
            }

            if (StreamTcpSackPacketIsOutdated(&ssn->server, p)) {
                SCLogDebug("outdated ACK (have SACK, SEQ %u vs next_seq %u)", TCP_GET_SEQ(p),
                        ssn->client.next_seq);
                return true;
            }
        }
    } else {
        if (SEQ_EQ(TCP_GET_SEQ(p), ssn->server.next_seq) &&
                SEQ_LT(TCP_GET_ACK(p), ssn->client.last_ack)) {
            if (!TCP_HAS_SACK(p)) {
                SCLogDebug("outdated ACK (no SACK, SEQ %u vs next_seq %u)", TCP_GET_SEQ(p),
                        ssn->client.next_seq);
                return true;
            }

            if (StreamTcpSackPacketIsOutdated(&ssn->client, p)) {
                SCLogDebug("outdated ACK (have SACK, SEQ %u vs next_seq %u)", TCP_GET_SEQ(p),
                        ssn->client.next_seq);
                return true;
            }
        }
    }
    return false;
}
static bool StreamTcpPacketIsOutdatedAck(TcpSession *ssn, Packet *p)
{
    if (ssn->state < TCP_ESTABLISHED)
        return false;
    if (p->payload_len != 0)
        return false;
    if ((p->tcph->th_flags & (TH_ACK | TH_SYN | TH_FIN | TH_RST)) != TH_ACK)
        return false;

     
    if (PKT_IS_TOSERVER(p)) {
        if (SEQ_EQ(TCP_GET_SEQ(p), ssn->client.next_seq) &&
                SEQ_LT(TCP_GET_ACK(p), ssn->server.last_ack)) {
            if (!TCP_HAS_SACK(p)) {
                SCLogDebug("outdated ACK (no SACK, SEQ %u vs next_seq %u)", TCP_GET_SEQ(p),
                        ssn->client.next_seq);
                return true;
            }

            if (StreamTcpSackPacketIsOutdated(&ssn->server, p)) {
                SCLogDebug("outdated ACK (have SACK, SEQ %u vs next_seq %u)", TCP_GET_SEQ(p),
                        ssn->client.next_seq);
                return true;
            }
        }
    } else {
        if (SEQ_EQ(TCP_GET_SEQ(p), ssn->server.next_seq) &&
                SEQ_LT(TCP_GET_ACK(p), ssn->client.last_ack)) {
            if (!TCP_HAS_SACK(p)) {
                SCLogDebug("outdated ACK (no SACK, SEQ %u vs next_seq %u)", TCP_GET_SEQ(p),
                        ssn->client.next_seq);
                return true;
            }

            if (StreamTcpSackPacketIsOutdated(&ssn->client, p)) {
                SCLogDebug("outdated ACK (have SACK, SEQ %u vs next_seq %u)", TCP_GET_SEQ(p),
                        ssn->client.next_seq);
                return true;
            }
        }
    }
    return false;
}