mirror of
https://github.com/shadowsocks/shadowsocks-libev.git
synced 2026-10-24 09:23:46 +00:00
* Seal the heap: bounded library heaps and zero-allocation program tests The programs point libuv, c-ares and Mbed TLS (MBEDTLS_PLATFORM_MEMORY in the bundled build) at their own FixedHeap before anything runs, mark the end of startup with heap_seal(), and in verbose mode report heap use and any allocation after it at exit. The library build keeps the host's allocator. measure_alloc.py gains --udp, and the alloc_steady_programs_* tests now fail on any malloc per relayed TCP connection (by name and by address) or UDP association, for every cipher family. * Fix GCC -Wsign-compare errors in the converted C modules GCC enables -Wsign-compare with -Wall for C++ (clang does not), which turned a few signed/unsigned comparisons in base64, netutils, server and manager into errors; udp.cpp needed <ctime>. * Add --max-connections and --max-udp-sessions The TCP connection pool and the UDP session table are sized from these options (or max_connections / max_udp_sessions in the configuration file) at startup instead of fixed constants; the DNS query pool follows the connection limit. test_limits.py checks that a connection beyond the limit is refused and that accepting resumes once one closes.
68 lines
2.5 KiB
Python
68 lines
2.5 KiB
Python
#!/usr/bin/env python3
|
|
"""--max-connections: connections beyond the limit are refused, and accepting
|
|
resumes once a slot frees."""
|
|
import argparse
|
|
from pathlib import Path
|
|
import socket
|
|
import threading
|
|
import time
|
|
|
|
from interop import TCPHandler, TCPOrigin, free_port, peers, receive, socks
|
|
|
|
|
|
def echo_once(sock):
|
|
sock.sendall(b"ping")
|
|
return receive(sock, 4) == b"ping"
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("--bin", required=True, type=Path)
|
|
args = parser.parse_args()
|
|
bins = args.bin.resolve()
|
|
with TCPOrigin(("127.0.0.1", 0), TCPHandler) as origin:
|
|
threading.Thread(target=origin.serve_forever, daemon=True).start()
|
|
sport, lport = free_port(), free_port()
|
|
server = [str(bins / "ss-server"), "-s", "127.0.0.1", "-p", str(sport), "-k", "pw", "-m", "aes-256-gcm",
|
|
"--max-connections", "2"]
|
|
local = [str(bins / "ss-local"), "-s", "127.0.0.1", "-p", str(sport), "-l", str(lport), "-k", "pw",
|
|
"-m", "aes-256-gcm"]
|
|
with peers([server, local], [sport, lport]):
|
|
target = ("127.0.0.1", origin.server_address[1])
|
|
held = []
|
|
for _ in range(2):
|
|
sock, _ = socks(lport, 1, target)
|
|
assert echo_once(sock), "connection within the limit failed"
|
|
held.append(sock)
|
|
# The third is refused by ss-server, so ss-local drops it.
|
|
third, _ = socks(lport, 1, target)
|
|
third.settimeout(3)
|
|
try:
|
|
refused = not echo_once(third)
|
|
except (OSError, AssertionError):
|
|
refused = True
|
|
third.close()
|
|
assert refused, "a connection beyond --max-connections was served"
|
|
# Free a slot; accepting resumes.
|
|
held.pop().close()
|
|
deadline = time.monotonic() + 5
|
|
while True:
|
|
try:
|
|
sock, _ = socks(lport, 1, target)
|
|
sock.settimeout(3)
|
|
if echo_once(sock):
|
|
held.append(sock)
|
|
break
|
|
except (OSError, AssertionError):
|
|
pass
|
|
assert time.monotonic() < deadline, "accepting did not resume after a slot freed"
|
|
time.sleep(.1)
|
|
for sock in held:
|
|
sock.close()
|
|
print("PASS --max-connections refuses and recovers")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|