3proxy/.github/wintest/rsttest.py
2026-10-11 00:47:32 +03:00

82 lines
2.1 KiB
Python

"""Does closing with unread data reset the connection, and is the reply lost?
The server reads only part of a large upload, answers, and closes in one of
three ways while the client is still sending. The client reports how much of
the reply arrived and what errors it saw.
"""
import socket, sys, threading, time
REPLY = b"R" * 65536
UPLOAD = 1500000
def server(lsock, variant):
c, _ = lsock.accept()
got = 0
while got < 16384:
d = c.recv(16384 - got)
if not d:
break
got += len(d)
c.sendall(REPLY)
if variant == "close":
c.close()
elif variant == "shutrdwr":
c.shutdown(socket.SHUT_RDWR)
c.close()
elif variant == "drain":
c.shutdown(socket.SHUT_WR)
c.settimeout(5)
try:
while c.recv(65536):
pass
except OSError:
pass
c.close()
def run(variant):
lsock = socket.socket()
lsock.bind(("127.0.0.1", 0))
lsock.listen(1)
port = lsock.getsockname()[1]
t = threading.Thread(target=server, args=(lsock, variant))
t.start()
cl = socket.create_connection(("127.0.0.1", port))
errs = {}
def send():
try:
cl.sendall(b"x" * UPLOAD)
cl.shutdown(socket.SHUT_WR)
except OSError as e:
errs["send"] = type(e).__name__
st = threading.Thread(target=send)
st.start()
# read slowly at first, as a client busy uploading would
time.sleep(0.3)
rx = 0
cl.settimeout(5)
try:
while True:
d = cl.recv(65536)
if not d:
break
rx += len(d)
except OSError as e:
errs["recv"] = type(e).__name__
st.join()
t.join()
cl.close()
lsock.close()
return rx, errs
for variant in sys.argv[1:] or ["close", "shutrdwr", "drain"]:
results = [run(variant) for _ in range(5)]
full = sum(1 for rx, _ in results if rx == len(REPLY))
errs = sorted({k + ":" + v for _, e in results for k, v in e.items()})
print("%-9s reply complete %d/5, received %s, errors %s"
% (variant, full, [rx for rx, _ in results], errs or "none"))