From ed0ccb8c2bf5cbc1725c783024ad3f42db085362 Mon Sep 17 00:00:00 2001 From: funman300 Date: Tue, 11 Aug 2026 02:34:46 +0000 Subject: [PATCH] blaze-host: check client sessions in BOTH network namespaces Host-side ss cannot see the Python backend's connections: the responders run in a container, so a client session terminates at 172.20.0.2:42130 inside its namespace and the host only sees the NAT'd flow. 'ss | grep ' on the host therefore reports nothing while a session is very much alive. That produced a wrong precondition: 'no .105 Blaze session -- closed' was reported while FIFA was mid-session on Python, and gate 9 was armed against a client that had never exited. Python's own log had the answer -- it logs closes reliably and there was no close for that session. client-state.sh looks in both namespaces, reports Rust and Python separately, and exits non-zero while any session is live. An unreachable container counts as 'cannot confirm', not as 'clear'. Fourth measurement bug in this tooling, and the most consequential: the other three mis-COUNTED, this one mis-STATED a precondition and caused an action. Co-Authored-By: Claude Opus 5 (1M context) --- openfut-blaze-host/client-state.sh | 81 ++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100755 openfut-blaze-host/client-state.sh diff --git a/openfut-blaze-host/client-state.sh b/openfut-blaze-host/client-state.sh new file mode 100755 index 0000000..01b592b --- /dev/null +++ b/openfut-blaze-host/client-state.sh @@ -0,0 +1,81 @@ +#!/usr/bin/env bash +# Is the FIFA client currently connected to anything? +# +# client-state.sh [client-ip] +# +# WHY THIS EXISTS +# +# Host-side `ss` CANNOT see the Python backend's connections. The Python +# responders run inside a container, so a client session terminates at +# 172.20.0.2:42130 in the container's network namespace; the host only ever sees +# the NAT'd flow, and a plain `ss | grep ` on the host reports nothing. +# +# That produced a wrong precondition check: "no .105 Blaze session — closed" was +# reported while FIFA was mid-session on Python, and gate 9 was armed against a +# client that had never exited. Python's own log gave it away — it logs closes +# reliably (45 of them) and there was no close for that session. +# +# So this looks in BOTH namespaces, and reports the Rust sidecar and the Python +# container separately. +# +# Exit 0 when the client has no live session anywhere (safe to start a gate), +# 1 when it does. +set -uo pipefail + +CLIENT="${1:-${OPENFUT_CLIENT_IP:-10.10.0.105}}" +CONTAINER="${OPENFUT_PY_CONTAINER:-openfut-fut-backend}" +live=0 + +decode_tcp() { + # /proc/net/tcp rows -> "local remote state", little-endian hex addresses. + python3 -c " +import sys +def d(x): + ip, port = x.split(':') + return '.'.join(str(int(ip[i:i+2], 16)) for i in (6, 4, 2, 0)) + ':' + str(int(port, 16)) +for line in sys.stdin: + f = line.split() + if len(f) < 4 or not f[0].endswith(':'): + continue + try: + print(d(f[1]), d(f[2]), f[3]) + except Exception: + pass +" +} + +echo "client: $CLIENT" + +# ---- Rust sidecar (host namespace) +rust="$(ss -tn state established 2>/dev/null | grep -F "$CLIENT" | grep -E ':42230' || true)" +if [[ -n "$rust" ]]; then + echo " RUST sidecar : LIVE session(s)" + sed 's/^/ /' <<<"$rust" + live=1 +else + echo " RUST sidecar : none" +fi + +# ---- Python backend (container namespace) +if docker exec "$CONTAINER" true 2>/dev/null; then + py="$(docker exec "$CONTAINER" cat /proc/net/tcp 2>/dev/null | decode_tcp \ + | awk '$3=="01"' | grep -F "$CLIENT" || true)" + if [[ -n "$py" ]]; then + echo " PYTHON backend: LIVE session(s)" + awk '{printf " %-22s <- %-22s ESTABLISHED\n", $1, $2}' <<<"$py" + live=1 + else + echo " PYTHON backend: none" + fi +else + echo " PYTHON backend: container '$CONTAINER' not reachable — CANNOT confirm" + live=1 # unknown is not the same as clear +fi + +echo +if [[ $live -eq 0 ]]; then + echo "RESULT: no live client session — safe to begin a gate" +else + echo "RESULT: client still connected — close FIFA before starting a gate" +fi +exit $live