[Python-checkins] cpython (merge 3.2 -> default): Issue #12343: Add some notes on behaviour of non-blocking SSL sockets.

antoine.pitrou python-checkins at python.org
Mon Jul 11 01:40:40 CEST 2011


http://hg.python.org/cpython/rev/77334eb5038d
changeset:   71294:77334eb5038d
parent:      71292:661195a92131
parent:      71293:b763c1ba5589
user:        Antoine Pitrou <solipsis at pitrou.net>
date:        Mon Jul 11 01:38:27 2011 +0200
summary:
  Issue #12343: Add some notes on behaviour of non-blocking SSL sockets.

files:
  Doc/library/ssl.rst |  61 +++++++++++++++++++++++---------
  1 files changed, 43 insertions(+), 18 deletions(-)


diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst
--- a/Doc/library/ssl.rst
+++ b/Doc/library/ssl.rst
@@ -440,27 +440,16 @@
   the same limitation)
 - :meth:`~socket.socket.shutdown()`
 
-They also have the following additional methods and attributes:
+However, since the SSL (and TLS) protocol has its own framing atop
+of TCP, the SSL sockets abstraction can, in certain respects, diverge from
+the specification of normal, OS-level sockets.  See especially the
+:ref:`notes on non-blocking sockets <ssl-nonblocking>`.
+
+SSL sockets also have the following additional methods and attributes:
 
 .. method:: SSLSocket.do_handshake()
 
-   Performs the SSL setup handshake.  If the socket is non-blocking, this method
-   may raise :exc:`SSLError` with the value of the exception instance's
-   ``args[0]`` being either :const:`SSL_ERROR_WANT_READ` or
-   :const:`SSL_ERROR_WANT_WRITE`, and should be called again until it stops
-   raising those exceptions.  Here's an example of how to do that::
-
-        while True:
-            try:
-                sock.do_handshake()
-                break
-            except ssl.SSLError as err:
-                if err.args[0] == ssl.SSL_ERROR_WANT_READ:
-                    select.select([sock], [], [])
-                elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
-                    select.select([], [sock], [])
-                else:
-                    raise
+   Performs the SSL setup handshake.
 
 .. method:: SSLSocket.getpeercert(binary_form=False)
 
@@ -949,6 +938,42 @@
 the sockets in non-blocking mode and use an event loop).
 
 
+.. _ssl-nonblocking:
+
+Notes on non-blocking sockets
+-----------------------------
+
+When working with non-blocking sockets, there are several things you need
+to be aware of:
+
+- 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
+  data at the upper SSL layer.  For example, only part of an SSL frame might
+  have arrived.  Therefore, you must be ready to handle :meth:`SSLSocket.recv`
+  and :meth:`SSLSocket.send` failures, and retry after another call to
+  :func:`~select.select`.
+
+  (of course, similar provisions apply when using other primitives such as
+  :func:`~select.poll`)
+
+- The SSL handshake itself will be non-blocking: the
+  :meth:`SSLSocket.do_handshake` method has to be retried until it returns
+  successfully.  Here is a synopsis using :func:`~select.select` to wait for
+  the socket's readiness::
+
+    while True:
+        try:
+            sock.do_handshake()
+            break
+        except ssl.SSLError as err:
+            if err.args[0] == ssl.SSL_ERROR_WANT_READ:
+                select.select([sock], [], [])
+            elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
+                select.select([], [sock], [])
+            else:
+                raise
+
+
 .. _ssl-security:
 
 Security considerations

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list