@@ -2608,10 +2608,6 @@ async def client(addr):
2608
2608
self .loop .run_until_complete (client (srv .addr ))
2609
2609
2610
2610
def test_remote_shutdown_receives_trailing_data (self ):
2611
- if self .implementation == 'asyncio' :
2612
- # this is an issue in asyncio
2613
- raise unittest .SkipTest ()
2614
-
2615
2611
CHUNK = 1024 * 16
2616
2612
SIZE = 8
2617
2613
count = 0
@@ -2676,13 +2672,18 @@ def server(sock):
2676
2672
data_len += chunk
2677
2673
except ssl .SSLWantReadError :
2678
2674
incoming .write (sock .recv (16384 ))
2675
+ if not incoming .pending :
2676
+ # EOF received
2677
+ break
2679
2678
except ssl .SSLZeroReturnError :
2680
2679
break
2681
2680
2682
2681
self .assertEqual (data_len , CHUNK * count )
2683
2682
2684
- # verify that close_notify is received
2685
- sslobj .unwrap ()
2683
+ if self .implementation == 'uvloop' :
2684
+ # Verify that close_notify is received. asyncio is currently
2685
+ # not guaranteed to send close_notify before dropping off
2686
+ sslobj .unwrap ()
2686
2687
2687
2688
sock .close ()
2688
2689
@@ -2708,11 +2709,12 @@ async def client(addr):
2708
2709
await asyncio .wait_for (
2709
2710
asyncio .ensure_future (writer .drain ()), 0.5 )
2710
2711
except asyncio .TimeoutError :
2711
- # fill write backlog in a hacky way
2712
- for _ in range (SIZE ):
2713
- writer .transport ._test__append_write_backlog (
2714
- b'x' * CHUNK )
2715
- count += 1
2712
+ # fill write backlog in a hacky way for uvloop
2713
+ if self .implementation == 'uvloop' :
2714
+ for _ in range (SIZE ):
2715
+ writer .transport ._test__append_write_backlog (
2716
+ b'x' * CHUNK )
2717
+ count += 1
2716
2718
2717
2719
data = await reader .read ()
2718
2720
self .assertEqual (data , b'' )
@@ -2929,7 +2931,7 @@ def server(sock):
2929
2931
except ssl .SSLWantReadError :
2930
2932
if outgoing .pending :
2931
2933
sock .send (outgoing .read ())
2932
- # incoming.write(sock.recv(16384))
2934
+ incoming .write (sock .recv (16384 ))
2933
2935
else :
2934
2936
if outgoing .pending :
2935
2937
sock .send (outgoing .read ())
@@ -2963,12 +2965,94 @@ async def client(addr):
2963
2965
tr .pause_reading ()
2964
2966
tr .close ()
2965
2967
2966
- await eof_recvd
2967
- await conn_lost
2968
+ await asyncio . wait_for ( eof_recvd , 10 )
2969
+ await asyncio . wait_for ( conn_lost , 10 )
2968
2970
2969
2971
with self .tcp_server (server ) as srv :
2970
2972
loop .run_until_complete (client (srv .addr ))
2971
2973
2974
+ def test_bpo_39951_discard_trailing_data (self ):
2975
+ sslctx = self ._create_server_ssl_context (self .ONLYCERT , self .ONLYKEY )
2976
+ client_sslctx = self ._create_client_ssl_context ()
2977
+ future = None
2978
+ close_notify = threading .Lock ()
2979
+
2980
+ def server (sock ):
2981
+ incoming = ssl .MemoryBIO ()
2982
+ outgoing = ssl .MemoryBIO ()
2983
+ sslobj = sslctx .wrap_bio (incoming , outgoing , server_side = True )
2984
+
2985
+ while True :
2986
+ try :
2987
+ sslobj .do_handshake ()
2988
+ except ssl .SSLWantReadError :
2989
+ if outgoing .pending :
2990
+ sock .send (outgoing .read ())
2991
+ incoming .write (sock .recv (16384 ))
2992
+ else :
2993
+ if outgoing .pending :
2994
+ sock .send (outgoing .read ())
2995
+ break
2996
+
2997
+ while True :
2998
+ try :
2999
+ data = sslobj .read (4 )
3000
+ except ssl .SSLWantReadError :
3001
+ incoming .write (sock .recv (16384 ))
3002
+ else :
3003
+ break
3004
+
3005
+ self .assertEqual (data , b'ping' )
3006
+ sslobj .write (b'pong' )
3007
+ sock .send (outgoing .read ())
3008
+
3009
+ with close_notify :
3010
+ sslobj .write (b'trailing' )
3011
+ sock .send (outgoing .read ())
3012
+ time .sleep (0.5 ) # allow time for the client to receive
3013
+
3014
+ incoming .write (sock .recv (16384 ))
3015
+ sslobj .unwrap ()
3016
+ sock .send (outgoing .read ())
3017
+ sock .close ()
3018
+
3019
+ async def client (addr ):
3020
+ nonlocal future
3021
+ future = self .loop .create_future ()
3022
+
3023
+ with close_notify :
3024
+ reader , writer = await asyncio .open_connection (
3025
+ * addr ,
3026
+ ssl = client_sslctx ,
3027
+ server_hostname = '' )
3028
+ writer .write (b'ping' )
3029
+ data = await reader .readexactly (4 )
3030
+ self .assertEqual (data , b'pong' )
3031
+
3032
+ writer .close ()
3033
+
3034
+ try :
3035
+ await self .wait_closed (writer )
3036
+ except ssl .SSLError as e :
3037
+ if self .implementation == 'asyncio' and \
3038
+ 'application data after close notify' in str (e ):
3039
+ raise unittest .SkipTest ('bpo-39951' )
3040
+ raise
3041
+ await future
3042
+
3043
+ def run (meth ):
3044
+ def wrapper (sock ):
3045
+ try :
3046
+ meth (sock )
3047
+ except Exception as ex :
3048
+ self .loop .call_soon_threadsafe (future .set_exception , ex )
3049
+ else :
3050
+ self .loop .call_soon_threadsafe (future .set_result , None )
3051
+ return wrapper
3052
+
3053
+ with self .tcp_server (run (server )) as srv :
3054
+ self .loop .run_until_complete (client (srv .addr ))
3055
+
2972
3056
2973
3057
class Test_UV_TCPSSL (_TestSSL , tb .UVTestCase ):
2974
3058
pass
0 commit comments