#!/usr/bin/env python3
"""Split tshark 'follow,tcp,raw' dumps into HTTP request/response bodies.

Usage: python3 -I extract_http.py <capture.pcapng> <out_dir>
Writes stream<N>_req.bin (POST body) and stream<N>_resp.bin (response body).
"""
import os
import subprocess
import sys


def follow(pcap, stream):
    out = subprocess.run(["tshark", "-r", pcap, "-q", "-z", f"follow,tcp,raw,{stream}"],
                         capture_output=True, text=True, check=True).stdout
    c2s, s2c = bytearray(), bytearray()
    for line in out.splitlines():
        if not line or line.startswith(("=", "Follow", "Filter", "Node")):
            continue
        if line.startswith("\t"):
            s2c += bytes.fromhex(line.strip())
        else:
            c2s += bytes.fromhex(line.strip())
    return bytes(c2s), bytes(s2c)


def body(msg):
    head, _, rest = msg.partition(b"\r\n\r\n")
    return head.decode("latin1"), rest


def main():
    pcap, outd = sys.argv[1], sys.argv[2]
    os.makedirs(outd, exist_ok=True)
    n = int(subprocess.run(["tshark", "-r", pcap, "-T", "fields", "-e", "tcp.stream"],
                           capture_output=True, text=True).stdout.split()[-1]) + 1
    for s in range(n):
        c2s, s2c = follow(pcap, s)
        qh, qb = body(c2s)
        rh, rb = body(s2c)
        open(os.path.join(outd, f"stream{s}_req.bin"), "wb").write(qb)
        open(os.path.join(outd, f"stream{s}_resp.bin"), "wb").write(rb)
        print(f"stream {s}: {qh.splitlines()[0]!r} body={len(qb)}  resp={rh.splitlines()[0]!r} body={len(rb)}")


if __name__ == "__main__":
    main()
