"""
Produce a FTP command connection sending 500 PORT commands in quick succession
to exercise the expected data connection path.

Generated by GPT-5.5, adapted to gzip compress by default.
"""

import gzip

from scapy.all import IP, TCP, Ether, Raw, wrpcap

CLIENT = "10.0.0.1"
SERVER = "10.0.0.2"
SPORT = 49152
DPORT = 21
BASE_TIME = 1_700_000_000.0


def pkt(src, dst, sport, dport, seq, ack, flags, payload=b"", ts=0):
    p = (
        Ether(src="02:00:00:00:00:01", dst="02:00:00:00:00:02")
        / IP(src=src, dst=dst)
        / TCP(sport=sport, dport=dport, seq=seq, ack=ack, flags=flags)
    )
    if payload:
        p = p / Raw(payload)
    p.time = BASE_TIME + ts
    return p


def main():
    packets = []
    cseq = 1000
    sseq = 5000
    t = 0.0

    packets.append(pkt(CLIENT, SERVER, SPORT, DPORT, cseq, 0, "S", ts=t))
    t += 0.001
    packets.append(pkt(SERVER, CLIENT, DPORT, SPORT, sseq, cseq + 1, "SA", ts=t))
    t += 0.001
    cseq += 1
    sseq += 1
    packets.append(pkt(CLIENT, SERVER, SPORT, DPORT, cseq, sseq, "A", ts=t))

    greeting = b"220 ready\r\n"
    t += 0.001
    packets.append(pkt(SERVER, CLIENT, DPORT, SPORT, sseq, cseq, "PA", greeting, ts=t))
    sseq += len(greeting)
    t += 0.001
    packets.append(pkt(CLIENT, SERVER, SPORT, DPORT, cseq, sseq, "A", ts=t))

    # Each valid PORT command creates/replaces one expected FTP-DATA entry keyed
    # by the advertised responder address and port. Use unique ports so entries
    # accumulate until their five-minute read expiration.
    for i in range(1, 501):
        p1 = (20000 + i) // 256
        p2 = (20000 + i) % 256
        payload = f"PORT 10,0,0,200,{p1},{p2}\r\n".encode()
        t += 0.001
        packets.append(
            pkt(CLIENT, SERVER, SPORT, DPORT, cseq, sseq, "PA", payload, ts=t)
        )
        cseq += len(payload)
        t += 0.001
        packets.append(pkt(SERVER, CLIENT, DPORT, SPORT, sseq, cseq, "A", ts=t))

    t += 0.001
    packets.append(pkt(CLIENT, SERVER, SPORT, DPORT, cseq, sseq, "FA", ts=t))
    cseq += 1
    t += 0.001
    packets.append(pkt(SERVER, CLIENT, DPORT, SPORT, sseq, cseq, "FA", ts=t))
    sseq += 1
    t += 0.001
    packets.append(pkt(CLIENT, SERVER, SPORT, DPORT, cseq, sseq, "A", ts=t))

    with gzip.GzipFile("ftp-many-port-expected.pcap.gz", "wb", mtime=0) as f:
        wrpcap(f, packets)


if __name__ == "__main__":
    main()
