Issue #20951: SSLSocket.send() now raises either SSLWantReadError or SSLWantWriteError on a non-blocking socket if the operation would block. Previously, it would return 0.
Patch by Nikolaus Rath.
This commit is contained in:
parent
727a463aa6
commit
b4bebdafe3
|
@ -1604,8 +1604,25 @@ the sockets in non-blocking mode and use an event loop).
|
||||||
Notes on non-blocking sockets
|
Notes on non-blocking sockets
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
|
||||||
When working with non-blocking sockets, there are several things you need
|
SSL sockets behave slightly different than regular sockets in
|
||||||
to be aware of:
|
non-blocking mode. When working with non-blocking sockets, there are
|
||||||
|
thus several things you need to be aware of:
|
||||||
|
|
||||||
|
- Most :class:`SSLSocket` methods will raise either
|
||||||
|
:exc:`SSLWantWriteError` or :exc:`SSLWantReadError` instead of
|
||||||
|
:exc:`BlockingIOError` if an I/O operation would
|
||||||
|
block. :exc:`SSLWantReadError` will be raised if a read operation on
|
||||||
|
the underlying socket is necessary, and :exc:`SSLWantWriteError` for
|
||||||
|
a write operation on the underlying socket. Note that attempts to
|
||||||
|
*write* to an SSL socket may require *reading* from the underlying
|
||||||
|
socket first, and attempts to *read* from the SSL socket may require
|
||||||
|
a prior *write* to the underlying socket.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.5
|
||||||
|
|
||||||
|
In earlier Python versions, the :meth:`!SSLSocket.send` method
|
||||||
|
returned zero instead of raising :exc:`SSLWantWriteError` or
|
||||||
|
:exc:`SSLWantReadError`.
|
||||||
|
|
||||||
- Calling :func:`~select.select` tells you that the OS-level socket can be
|
- Calling :func:`~select.select` tells you that the OS-level socket can be
|
||||||
read from (or written to), but it does not imply that there is sufficient
|
read from (or written to), but it does not imply that there is sufficient
|
||||||
|
|
12
Lib/ssl.py
12
Lib/ssl.py
|
@ -664,17 +664,7 @@ class SSLSocket(socket):
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"non-zero flags not allowed in calls to send() on %s" %
|
"non-zero flags not allowed in calls to send() on %s" %
|
||||||
self.__class__)
|
self.__class__)
|
||||||
try:
|
return self._sslobj.write(data)
|
||||||
v = self._sslobj.write(data)
|
|
||||||
except SSLError as x:
|
|
||||||
if x.args[0] == SSL_ERROR_WANT_READ:
|
|
||||||
return 0
|
|
||||||
elif x.args[0] == SSL_ERROR_WANT_WRITE:
|
|
||||||
return 0
|
|
||||||
else:
|
|
||||||
raise
|
|
||||||
else:
|
|
||||||
return v
|
|
||||||
else:
|
else:
|
||||||
return socket.send(self, data, flags)
|
return socket.send(self, data, flags)
|
||||||
|
|
||||||
|
|
|
@ -2547,6 +2547,36 @@ else:
|
||||||
s.write(b"over\n")
|
s.write(b"over\n")
|
||||||
s.close()
|
s.close()
|
||||||
|
|
||||||
|
def test_nonblocking_send(self):
|
||||||
|
server = ThreadedEchoServer(CERTFILE,
|
||||||
|
certreqs=ssl.CERT_NONE,
|
||||||
|
ssl_version=ssl.PROTOCOL_TLSv1,
|
||||||
|
cacerts=CERTFILE,
|
||||||
|
chatty=True,
|
||||||
|
connectionchatty=False)
|
||||||
|
with server:
|
||||||
|
s = ssl.wrap_socket(socket.socket(),
|
||||||
|
server_side=False,
|
||||||
|
certfile=CERTFILE,
|
||||||
|
ca_certs=CERTFILE,
|
||||||
|
cert_reqs=ssl.CERT_NONE,
|
||||||
|
ssl_version=ssl.PROTOCOL_TLSv1)
|
||||||
|
s.connect((HOST, server.port))
|
||||||
|
s.setblocking(False)
|
||||||
|
|
||||||
|
# If we keep sending data, at some point the buffers
|
||||||
|
# will be full and the call will block
|
||||||
|
buf = bytearray(8192)
|
||||||
|
def fill_buffer():
|
||||||
|
while True:
|
||||||
|
s.send(buf)
|
||||||
|
self.assertRaises((ssl.SSLWantWriteError,
|
||||||
|
ssl.SSLWantReadError), fill_buffer)
|
||||||
|
|
||||||
|
# Now read all the output and discard it
|
||||||
|
s.setblocking(True)
|
||||||
|
s.close()
|
||||||
|
|
||||||
def test_handshake_timeout(self):
|
def test_handshake_timeout(self):
|
||||||
# Issue #5103: SSL handshake must respect the socket timeout
|
# Issue #5103: SSL handshake must respect the socket timeout
|
||||||
server = socket.socket(socket.AF_INET)
|
server = socket.socket(socket.AF_INET)
|
||||||
|
|
|
@ -60,6 +60,10 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #20951: SSLSocket.send() now raises either SSLWantReadError or
|
||||||
|
SSLWantWriteError on a non-blocking socket if the operation would block.
|
||||||
|
Previously, it would return 0. Patch by Nikolaus Rath.
|
||||||
|
|
||||||
- Issue #13248: removed previously deprecated asyncore.dispatcher __getattr__
|
- Issue #13248: removed previously deprecated asyncore.dispatcher __getattr__
|
||||||
cheap inheritance hack.
|
cheap inheritance hack.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue