GeezerVisonThe World Wide Web, restored to 800 pixels of glory. |
| Home|About|Gaming cabinet|Archives|How it works|Starter sites |
GeezerVison is showing github.com — SSL transport drops buffered data when peer closes TCP without close_notify while reading is paused · Issue #792 · MagicStack/uvloop Open DescriptionSummaryWhen a TLS peer sends its data and then closes the TCP connection without sending ReproductionSelf-contained; needs only the """Usage: python repro.py [uvloop|asyncio]""" import asyncio, socket, ssl, subprocess, sys, tempfile, threading SIZE = 2_000_000 def serve(listener, ctx): raw, _ = listener.accept() tls = ctx.wrap_socket(raw, server_side=True) tls.recv(2) tls.sendall(b"x" * SIZE) tls.close() # TCP close, no unwrap(): no close_notify is sent class SlowReader(asyncio.Protocol): def __init__(self, loop): self.loop, self.received = loop, 0 self.closed = loop.create_future() def connection_made(self, transport): self.transport = transport transport.write(b"go") def data_received(self, data): self.received += len(data) self.transport.pause_reading() self.loop.call_later(0.02, self.transport.resume_reading) def connection_lost(self, exc): self.closed.set_result(exc) async def main(port): loop = asyncio.get_running_loop() ctx = ssl.create_default_context() ctx.check_hostname, ctx.verify_mode = False, ssl.CERT_NONE _, proto = await loop.create_connection(lambda: SlowReader(loop), "127.0.0.1", port, ssl=ctx) exc = await asyncio.wait_for(proto.closed, 30) print(f"{type(loop).__module__}: received {proto.received} of {SIZE}, connection_lost({exc!r})") with tempfile.TemporaryDirectory() as d: subprocess.run( ["openssl", "req", "-x509", "-newkey", "rsa:2048", "-nodes", "-days", "1", "-subj", "/CN=localhost", "-keyout", f"{d}/k.pem", "-out", f"{d}/c.pem"], check=True, capture_output=True, ) server_ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) server_ctx.load_cert_chain(f"{d}/c.pem", f"{d}/k.pem") listener = socket.create_server(("127.0.0.1", 0)) threading.Thread(target=serve, args=(listener, server_ctx), daemon=True).start() port = listener.getsockname()[1] if sys.argv[1:] == ["uvloop"]: import uvloop uvloop.run(main(port)) else: asyncio.run(main(port)) Actual vs expectedThe amount lost varies from run to run. If the server calls Real-world impactAmazon S3 answers every 100th request on a keep-alive connection with Versions
ActivityMetadataMetadataAssigneesLabelsNo labels TypeProjectsMilestoneRelationshipsDevelopmentIssue actions |
| You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |