raise
if self.ssl_options is not None:
assert ssl, "Python 2.6+ and OpenSSL required for SSL"
- connection = ssl.wrap_socket(
- connection, server_side=True, **self.ssl_options)
+ try:
+ connection = ssl.wrap_socket(connection,
+ server_side=True,
+ do_handshake_on_connect=False,
+ **self.ssl_options)
+ except ssl.SSLError, err:
+ logging.error("SSL Error in SSL wrap:", exc_info=True)
+ if err.args[0] == ssl.SSL_ERROR_EOF:
+ return connection.close()
+ except socket.error, err:
+ logging.error("Socket Error in SSL wrap:", exc_info=True)
+ if err.args[0] == errno.ECONNABORTED:
+ return connection.close()
try:
- stream = iostream.IOStream(connection, io_loop=self.io_loop)
+ if self.ssl_options is not None:
+ stream = iostream.SSLIOStream(connection, io_loop=self.io_loop)
+ else:
+ stream = iostream.IOStream(connection, io_loop=self.io_loop)
HTTPConnection(stream, address, self.request_callback,
self.no_keep_alive, self.xheaders)
except:
from tornado import ioloop
+try:
+ import ssl # Python 2.6+
+except ImportError:
+ ssl = None
+
class IOStream(object):
"""A utility class to write to and read from a non-blocking socket.
if not self._state & state:
self._state = self._state | state
self.io_loop.update_handler(self.socket.fileno(), self._state)
+
+
+class SSLIOStream(IOStream):
+ """Sets up an SSL connection in a non-blocking manner"""
+ def __init__(self, *args, **kwargs):
+ super(SSLIOStream, self).__init__(*args, **kwargs)
+ self._ssl_accepting = True
+ self._do_ssl_handshake()
+
+ def _do_ssl_handshake(self):
+ # Based on code from test_ssl.py in the python stdlib
+ try:
+ self.socket.do_handshake()
+ except ssl.SSLError, err:
+ if err.args[0] == ssl.SSL_ERROR_WANT_READ:
+ self._add_io_state(self.io_loop.READ)
+ return
+ elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
+ self._add_io_state(self.io_loop.WRITE)
+ return
+ elif err.args[0] in (ssl.SSL_ERROR_EOF,
+ ssl.SSL_ERROR_ZERO_RETURN):
+ return self.close()
+ raise
+ except socket.error, err:
+ if err.args[0] == errno.ECONNABORTED:
+ return self.close()
+ else:
+ self._ssl_accepting = False
+
+ def _handle_read(self):
+ if self._ssl_accepting:
+ self._do_ssl_handshake()
+ return
+ super(SSLIOStream, self)._handle_read()
+
+ def _handle_write(self):
+ if self._ssl_accepting:
+ self._do_ssl_handshake()
+ return
+ super(SSLIOStream, self)._handle_write()