diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2011-07-10 23:35:48 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2011-07-10 23:35:48 (GMT) |
commit | 6f5dcb1ee28f616602d73f22630c9f8e3660e671 (patch) | |
tree | f2134011e072f7b5cff1c7c1fd1fcdb509223556 /Doc/library/ssl.rst | |
parent | cdddf2b875e10f86af55eacb83e81025f1071b39 (diff) | |
download | cpython-6f5dcb1ee28f616602d73f22630c9f8e3660e671.zip cpython-6f5dcb1ee28f616602d73f22630c9f8e3660e671.tar.gz cpython-6f5dcb1ee28f616602d73f22630c9f8e3660e671.tar.bz2 |
Issue #12343: Add some notes on behaviour of non-blocking SSL sockets.
Diffstat (limited to 'Doc/library/ssl.rst')
-rw-r--r-- | Doc/library/ssl.rst | 61 |
1 files changed, 43 insertions, 18 deletions
diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 09a2961..c0b9d4a 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -408,27 +408,16 @@ SSL sockets provide the following methods of :ref:`socket-objects`: 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) @@ -917,6 +906,42 @@ would probably handle each client connection in a separate thread, or put 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 |