cpython: 3cf067049211 (original) (raw)
Mercurial > cpython
changeset 90506:3cf067049211
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. [#20951]
Antoine Pitrou solipsis@pitrou.net | |
---|---|
date | Tue, 29 Apr 2014 10:03:28 +0200 |
parents | 817d86f627c4 |
children | b0f6983d63df |
files | Doc/library/ssl.rst Lib/ssl.py Lib/test/test_ssl.py Misc/NEWS |
diffstat | 4 files changed, 54 insertions(+), 13 deletions(-)[+] [-] Doc/library/ssl.rst 21 Lib/ssl.py 12 Lib/test/test_ssl.py 30 Misc/NEWS 4 |
line wrap: on
line diff
--- a/Doc/library/ssl.rst
+++ b/Doc/library/ssl.rst
@@ -1604,8 +1604,25 @@ the sockets in non-blocking mode and use
Notes on non-blocking sockets
-----------------------------
-When working with non-blocking sockets, there are several things you need
-to be aware of:
+SSL sockets behave slightly different than regular sockets in
+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[](#l1.25)
returned zero instead of raising :exc:`SSLWantWriteError` or[](#l1.26)
:exc:`SSLWantReadError`.[](#l1.27)
- 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
--- a/Lib/ssl.py +++ b/Lib/ssl.py @@ -664,17 +664,7 @@ class SSLSocket(socket): raise ValueError( "non-zero flags not allowed in calls to send() on %s" % self.class)
try:[](#l2.7)
v = self._sslobj.write(data)[](#l2.8)
except SSLError as x:[](#l2.9)
if x.args[0] == SSL_ERROR_WANT_READ:[](#l2.10)
return 0[](#l2.11)
elif x.args[0] == SSL_ERROR_WANT_WRITE:[](#l2.12)
return 0[](#l2.13)
else:[](#l2.14)
raise[](#l2.15)
else:[](#l2.16)
return v[](#l2.17)
return self._sslobj.write(data)[](#l2.18) else:[](#l2.19) return socket.send(self, data, flags)[](#l2.20)
--- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -2547,6 +2547,36 @@ else: s.write(b"over\n") s.close()
def test_nonblocking_send(self):[](#l3.7)
server = ThreadedEchoServer(CERTFILE,[](#l3.8)
certreqs=ssl.CERT_NONE,[](#l3.9)
ssl_version=ssl.PROTOCOL_TLSv1,[](#l3.10)
cacerts=CERTFILE,[](#l3.11)
chatty=True,[](#l3.12)
connectionchatty=False)[](#l3.13)
with server:[](#l3.14)
s = ssl.wrap_socket(socket.socket(),[](#l3.15)
server_side=False,[](#l3.16)
certfile=CERTFILE,[](#l3.17)
ca_certs=CERTFILE,[](#l3.18)
cert_reqs=ssl.CERT_NONE,[](#l3.19)
ssl_version=ssl.PROTOCOL_TLSv1)[](#l3.20)
s.connect((HOST, server.port))[](#l3.21)
s.setblocking(False)[](#l3.22)
# If we keep sending data, at some point the buffers[](#l3.24)
# will be full and the call will block[](#l3.25)
buf = bytearray(8192)[](#l3.26)
def fill_buffer():[](#l3.27)
while True:[](#l3.28)
s.send(buf)[](#l3.29)
self.assertRaises((ssl.SSLWantWriteError,[](#l3.30)
ssl.SSLWantReadError), fill_buffer)[](#l3.31)
# Now read all the output and discard it[](#l3.33)
s.setblocking(True)[](#l3.34)
s.close()[](#l3.35)
+ def test_handshake_timeout(self): # Issue #5103: SSL handshake must respect the socket timeout server = socket.socket(socket.AF_INET)
--- a/Misc/NEWS +++ b/Misc/NEWS @@ -60,6 +60,10 @@ Core and Builtins Library ------- +- Issue #20951: SSLSocket.send() now raises either SSLWantReadError or