zapret2-fork/nfq2/winnative/tests/check_upstream.py
loop-uh dc41b27493
Some checks failed
build.yml / winws2 native: send the held batch before the receive loop exits (push) Failing after 0s
winws2 native: send the held batch before the receive loop exits
Unmodified packets were held until the next receive. On quit and when the
logical network disappears upstream leaves windivert_recv() before receiving,
so the last run (up to 128 packets) never reached the network. Stress on win10:
20 of 20 stops lost a full run, 2548 packets in total; 0 after the fix.

usleep(0), which starts windivert_recv_exit(), now sends the run and polls the
control events, as cygwin delivered signals there. This also makes the term
event work while the engine waits for a logical network (it used to hang).
WinDivertClose forgets the run of the handle without reading the packets.
tests/check_upstream.py fails the sync if upstream drops that usleep call.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 21:16:34 +03:00

23 lines
1.4 KiB
Python
Executable file

#!/usr/bin/env python3
# The native layer relies on details of upstream code that a merge can silently change. Check them.
#
# batch.c holds unmodified packets until the next receive. On quit and when the logical network disappears
# windivert_recv() returns before receiving, and the caller frees the receive buffer and closes the handle.
# The held packets are sent by usleep : windivert_recv_exit() has to call it before it looks at the exit conditions.
import re
import sys
nfq2 = sys.argv[1]
src = open(nfq2 + "/darkmagic.c", encoding="utf-8", errors="replace").read()
m = re.search(r"static bool windivert_recv_exit\(void\)\s*\{(.*?)\n\}", src, re.S)
if not m:
sys.exit("upstream check: windivert_recv_exit() not found in darkmagic.c")
body = m.group(1)
u, q, n = body.find("usleep("), body.find("bQuit"), body.find("logical_net_filter_match")
if u < 0 or q < 0 or n < 0 or not u < q or not u < n:
sys.exit("upstream check: windivert_recv_exit() must call usleep() before checking bQuit and the logical network. "
"batch.c flushes held packets in usleep, see the comment there")
m = re.search(r"static bool windivert_recv_filter\(.*?\)\s*\{(.*?)\n\}", src, re.S)
if not m or not 0 <= m.group(1).find("windivert_recv_exit()") < m.group(1).find("WinDivertRecvEx("):
sys.exit("upstream check: windivert_recv_filter() must call windivert_recv_exit() before WinDivertRecvEx()")
print("upstream checks: ok")