@@ -1573,6 +1573,7 @@ def serve(sock):
1573
1573
data = sock .recv_all (len (HELLO_MSG ))
1574
1574
self .assertEqual (len (data ), len (HELLO_MSG ))
1575
1575
1576
+ sock .unwrap ()
1576
1577
sock .shutdown (socket .SHUT_RDWR )
1577
1578
sock .close ()
1578
1579
@@ -1643,6 +1644,7 @@ def serve(sock):
1643
1644
data = sock .recv_all (len (HELLO_MSG ))
1644
1645
self .assertEqual (len (data ), len (HELLO_MSG ))
1645
1646
1647
+ sock .unwrap ()
1646
1648
sock .shutdown (socket .SHUT_RDWR )
1647
1649
sock .close ()
1648
1650
@@ -1798,6 +1800,7 @@ def client(sock, addr):
1798
1800
sock .starttls (client_context )
1799
1801
sock .sendall (HELLO_MSG )
1800
1802
1803
+ sock .unwrap ()
1801
1804
sock .shutdown (socket .SHUT_RDWR )
1802
1805
sock .close ()
1803
1806
@@ -2303,9 +2306,11 @@ def test_write_to_closed_transport(self):
2303
2306
2304
2307
sslctx = self ._create_server_ssl_context (self .ONLYCERT , self .ONLYKEY )
2305
2308
client_sslctx = self ._create_client_ssl_context ()
2309
+ future = None
2306
2310
2307
2311
def server (sock ):
2308
2312
sock .starttls (sslctx , server_side = True )
2313
+ sock .shutdown (socket .SHUT_RDWR )
2309
2314
sock .close ()
2310
2315
2311
2316
def unwrap_server (sock ):
@@ -2320,6 +2325,9 @@ def unwrap_server(sock):
2320
2325
sock .close ()
2321
2326
2322
2327
async def client (addr ):
2328
+ nonlocal future
2329
+ future = self .loop .create_future ()
2330
+
2323
2331
reader , writer = await asyncio .open_connection (
2324
2332
* addr ,
2325
2333
ssl = client_sslctx ,
@@ -2330,7 +2338,7 @@ async def client(addr):
2330
2338
try :
2331
2339
data = await reader .read ()
2332
2340
self .assertEqual (data , b'' )
2333
- except ConnectionResetError :
2341
+ except ( ConnectionResetError , BrokenPipeError ) :
2334
2342
pass
2335
2343
2336
2344
for i in range (25 ):
@@ -2339,11 +2347,23 @@ async def client(addr):
2339
2347
self .assertEqual (
2340
2348
len (writer .transport ._ssl_protocol ._write_backlog ), 0 )
2341
2349
2350
+ await future
2351
+
2352
+ def run (meth ):
2353
+ def wrapper (sock ):
2354
+ try :
2355
+ meth (sock )
2356
+ except Exception as ex :
2357
+ self .loop .call_soon_threadsafe (future .set_exception , ex )
2358
+ else :
2359
+ self .loop .call_soon_threadsafe (future .set_result , None )
2360
+ return wrapper
2361
+
2342
2362
with self ._silence_eof_received_warning ():
2343
- with self .tcp_server (server ) as srv :
2363
+ with self .tcp_server (run ( server ) ) as srv :
2344
2364
self .loop .run_until_complete (client (srv .addr ))
2345
2365
2346
- with self .tcp_server (unwrap_server ) as srv :
2366
+ with self .tcp_server (run ( unwrap_server ) ) as srv :
2347
2367
self .loop .run_until_complete (client (srv .addr ))
2348
2368
2349
2369
def test_flush_before_shutdown (self ):
@@ -2438,6 +2458,98 @@ async def client(addr):
2438
2458
with self .tcp_server (run (openssl_server )) as srv :
2439
2459
self .loop .run_until_complete (client (srv .addr ))
2440
2460
2461
+ def test_remote_shutdown_receives_trailing_data (self ):
2462
+ if self .implementation == 'asyncio' :
2463
+ raise unittest .SkipTest ()
2464
+
2465
+ CHUNK = 1024 * 128
2466
+ SIZE = 32
2467
+
2468
+ sslctx = self ._create_server_ssl_context (self .ONLYCERT , self .ONLYKEY )
2469
+ client_sslctx = self ._create_client_ssl_context ()
2470
+ future = None
2471
+
2472
+ def server (sock ):
2473
+ sock .starttls (sslctx , server_side = True )
2474
+ self .assertEqual (sock .recv_all (4 ), b'ping' )
2475
+ sock .send (b'pong' )
2476
+
2477
+ time .sleep (0.2 ) # wait for the peer to fill its backlog
2478
+
2479
+ # send close_notify but don't wait for response
2480
+ sock .setblocking (0 )
2481
+ with self .assertRaises (ssl .SSLWantReadError ):
2482
+ sock .unwrap ()
2483
+ sock .setblocking (1 )
2484
+
2485
+ # should receive all data
2486
+ data = sock .recv_all (CHUNK * SIZE )
2487
+ self .assertEqual (len (data ), CHUNK * SIZE )
2488
+
2489
+ # wait for close_notify
2490
+ sock .unwrap ()
2491
+
2492
+ sock .close ()
2493
+
2494
+ def eof_server (sock ):
2495
+ sock .starttls (sslctx , server_side = True )
2496
+ self .assertEqual (sock .recv_all (4 ), b'ping' )
2497
+ sock .send (b'pong' )
2498
+
2499
+ time .sleep (0.2 ) # wait for the peer to fill its backlog
2500
+
2501
+ # send EOF
2502
+ sock .shutdown (socket .SHUT_WR )
2503
+
2504
+ # should receive all data
2505
+ data = sock .recv_all (CHUNK * SIZE )
2506
+ self .assertEqual (len (data ), CHUNK * SIZE )
2507
+
2508
+ sock .close ()
2509
+
2510
+ async def client (addr ):
2511
+ nonlocal future
2512
+ future = self .loop .create_future ()
2513
+
2514
+ reader , writer = await asyncio .open_connection (
2515
+ * addr ,
2516
+ ssl = client_sslctx ,
2517
+ server_hostname = '' ,
2518
+ loop = self .loop )
2519
+ writer .write (b'ping' )
2520
+ data = await reader .readexactly (4 )
2521
+ self .assertEqual (data , b'pong' )
2522
+
2523
+ # fill write backlog in a hacky way - renegotiation won't help
2524
+ ssl_protocol = writer .transport ._ssl_protocol
2525
+ for _ in range (SIZE ):
2526
+ ssl_protocol ._write_backlog .append (b'x' * CHUNK )
2527
+ ssl_protocol ._write_buffer_size += CHUNK
2528
+
2529
+ try :
2530
+ data = await reader .read ()
2531
+ self .assertEqual (data , b'' )
2532
+ except (BrokenPipeError , ConnectionResetError ):
2533
+ pass
2534
+
2535
+ await future
2536
+
2537
+ def run (meth ):
2538
+ def wrapper (sock ):
2539
+ try :
2540
+ meth (sock )
2541
+ except Exception as ex :
2542
+ self .loop .call_soon_threadsafe (future .set_exception , ex )
2543
+ else :
2544
+ self .loop .call_soon_threadsafe (future .set_result , None )
2545
+ return wrapper
2546
+
2547
+ with self .tcp_server (run (server )) as srv :
2548
+ self .loop .run_until_complete (client (srv .addr ))
2549
+
2550
+ with self .tcp_server (run (eof_server )) as srv :
2551
+ self .loop .run_until_complete (client (srv .addr ))
2552
+
2441
2553
2442
2554
class Test_UV_TCPSSL (_TestSSL , tb .UVTestCase ):
2443
2555
pass
0 commit comments