import io
import os

os.chdir(r"C:/Users/decid/Documents/projects/spt-core/.worktrees/hertz-inbound-probe")
P = "crates/spt-daemon/tests/twohost_web.rs"
s = io.open(P, encoding="utf-8", newline="").read()
CR, LF = chr(13), chr(10)
CRLF = s.count(CR + LF) > s.count(LF) // 2


def term(t):
    return t.replace(CR + LF, LF).replace(LF, CR + LF) if CRLF else t.replace(CR + LF, LF)


old = """    let socket = UdpSocket::bind(SocketAddr::new(IpAddr::from([0, 0, 0, 0]), port))
        .unwrap_or_else(|e| panic!("INBOUND_PROBE: role A could not bind udp {port}: {e}"));
    socket
        .set_read_timeout(Some(Duration::from_millis(250)))
        .expect("probe socket takes a read timeout");"""
new = """    let socket = UdpSocket::bind(SocketAddr::new(IpAddr::from([0, 0, 0, 0]), port))
        .unwrap_or_else(|e| panic!("INBOUND_PROBE: role A could not bind udp {port}: {e}"));
    socket
        .set_read_timeout(Some(Duration::from_millis(250)))
        .expect("probe socket takes a read timeout");
    // \u26a0 THE LISTENING SOCKET NEVER SENDS. THAT IS THE WHOLE DESIGN.
    //
    // Every outbound datagram from `port` — a beacon, an ack, anything — opens
    // stateful firewall / NAT return state for that port, so B's probe then
    // arrives as SOLICITED return traffic and crosses under exactly the two
    // faults this cell exists to detect. That is this file's own warning —
    // "solicited return traffic works under either fault, so an echo reply
    // proves nothing about this direction" — applied to the guard rather than to
    // the ceremony.
    //
    // MEASURED, not reasoned (2026-09-09): with the beacon sharing the listening
    // socket, the out-of-grant control arm (probe port forced to 7509, outside
    // the operator's udp 7460-7499 rule) went GREEN — the probe certified a path
    // that a listen-only run had measured as BLOCKED eight minutes earlier. The
    // beacon and the ack therefore both leave this ephemeral socket, and B sends
    // from an ephemeral port of its own, so no run repeats a 4-tuple a previous
    // run opened and none can poison the next.
    let beacon_socket = UdpSocket::bind(SocketAddr::new(IpAddr::from([0, 0, 0, 0]), 0))
        .expect("probe beacon binds an ephemeral port");"""
old, new = term(old), term(new)
assert s.count(old) == 1
s = s.replace(old, new)

old_send = term("            match socket.send_to(PROBE_BEACON, beacon_target) {")
new_send = term("            match beacon_socket.send_to(PROBE_BEACON, beacon_target) {")
assert s.count(old_send) == 1
s = s.replace(old_send, new_send)

io.open(P, "w", encoding="utf-8", newline="").write(s)
print("A: beacon on its own ephemeral socket")
