@@ -83,14 +83,20 @@ def _is_ip_address(address):
83
83
_SSL .WantReadError , _SSL .WantWriteError , _SSL .WantX509LookupError )
84
84
85
85
86
+ def _ragged_eof (exc ):
87
+ """Return True if the OpenSSL.SSL.SysCallError is a ragged EOF."""
88
+ return exc .args == (- 1 , 'Unexpected EOF' )
89
+
90
+
86
91
# https://github.com/pyca/pyopenssl/issues/168
87
92
# https://github.com/pyca/pyopenssl/issues/176
88
93
# https://docs.python.org/3/library/ssl.html#notes-on-non-blocking-sockets
89
94
class _sslConn (_SSL .Connection ):
90
95
91
- def __init__ (self , * args , ** kwargs ):
96
+ def __init__ (self , ctx , sock , suppress_ragged_eofs ):
92
97
self .socket_checker = _SocketChecker ()
93
- super (_sslConn , self ).__init__ (* args , ** kwargs )
98
+ self .suppress_ragged_eofs = suppress_ragged_eofs
99
+ super (_sslConn , self ).__init__ (ctx , sock )
94
100
95
101
def _call (self , call , * args , ** kwargs ):
96
102
timeout = self .gettimeout ()
@@ -110,10 +116,22 @@ def do_handshake(self, *args, **kwargs):
110
116
return self ._call (super (_sslConn , self ).do_handshake , * args , ** kwargs )
111
117
112
118
def recv (self , * args , ** kwargs ):
113
- return self ._call (super (_sslConn , self ).recv , * args , ** kwargs )
119
+ try :
120
+ return self ._call (super (_sslConn , self ).recv , * args , ** kwargs )
121
+ except _SSL .SysCallError as exc :
122
+ # Suppress ragged EOFs to match the stdlib.
123
+ if self .suppress_ragged_eofs and _ragged_eof (exc ):
124
+ return b""
125
+ raise
114
126
115
127
def recv_into (self , * args , ** kwargs ):
116
- return self ._call (super (_sslConn , self ).recv_into , * args , ** kwargs )
128
+ try :
129
+ return self ._call (super (_sslConn , self ).recv_into , * args , ** kwargs )
130
+ except _SSL .SysCallError as exc :
131
+ # Suppress ragged EOFs to match the stdlib.
132
+ if self .suppress_ragged_eofs and _ragged_eof (exc ):
133
+ return 0
134
+ raise
117
135
118
136
def sendall (self , buf , flags = 0 ):
119
137
view = memoryview (buf )
@@ -266,12 +284,12 @@ def set_default_verify_paths(self):
266
284
267
285
def wrap_socket (self , sock , server_side = False ,
268
286
do_handshake_on_connect = True ,
269
- suppress_ragged_eofs = True , # TODO: Add support to _sslConn.
287
+ suppress_ragged_eofs = True ,
270
288
server_hostname = None , session = None ):
271
289
"""Wrap an existing Python socket sock and return a TLS socket
272
290
object.
273
291
"""
274
- ssl_conn = _sslConn (self ._ctx , sock )
292
+ ssl_conn = _sslConn (self ._ctx , sock , suppress_ragged_eofs )
275
293
if session :
276
294
ssl_conn .set_session (session )
277
295
if server_side is True :
0 commit comments