self.io_loop = ioloop.IOLoop.instance()
for sock in sockets:
self._sockets[sock.fileno()] = sock
- self.io_loop.add_handler(sock.fileno(), self._handle_events,
- ioloop.IOLoop.READ)
+ netutil.add_accept_handler(sock, self._handle_connection,
+ io_loop=self.io_loop)
def add_socket(self, socket):
"""Singular version of `add_sockets`. Takes a single socket object."""
self.io_loop.remove_handler(fd)
sock.close()
- def _handle_events(self, fd, events):
- while True:
+ def _handle_connection(self, connection, address):
+ if self.ssl_options is not None:
+ assert ssl, "Python 2.6+ and OpenSSL required for SSL"
try:
- connection, address = self._sockets[fd].accept()
- except socket.error, e:
- if e.args[0] in (errno.EWOULDBLOCK, errno.EAGAIN):
- return
- raise
- if self.ssl_options is not None:
- assert ssl, "Python 2.6+ and OpenSSL required for SSL"
- try:
- connection = ssl.wrap_socket(connection,
- server_side=True,
- do_handshake_on_connect=False,
- **self.ssl_options)
- except ssl.SSLError, err:
- if err.args[0] == ssl.SSL_ERROR_EOF:
- return connection.close()
- else:
- raise
- except socket.error, err:
- if err.args[0] == errno.ECONNABORTED:
- return connection.close()
- else:
- raise
- try:
- if self.ssl_options is not None:
- stream = iostream.SSLIOStream(connection, io_loop=self.io_loop)
+ connection = ssl.wrap_socket(connection,
+ server_side=True,
+ do_handshake_on_connect=False,
+ **self.ssl_options)
+ except ssl.SSLError, err:
+ if err.args[0] == ssl.SSL_ERROR_EOF:
+ return connection.close()
+ else:
+ raise
+ except socket.error, err:
+ if err.args[0] == errno.ECONNABORTED:
+ return connection.close()
else:
- stream = iostream.IOStream(connection, io_loop=self.io_loop)
- if connection.family not in (socket.AF_INET, socket.AF_INET6):
- # Unix (or other) socket; fake the remote address
- address = ('0.0.0.0', 0)
- HTTPConnection(stream, address, self.request_callback,
- self.no_keep_alive, self.xheaders)
- except Exception:
- logging.error("Error in connection callback", exc_info=True)
+ raise
+ try:
+ 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)
+ if connection.family not in (socket.AF_INET, socket.AF_INET6):
+ # Unix (or other) socket; fake the remote address
+ address = ('0.0.0.0', 0)
+ HTTPConnection(stream, address, self.request_callback,
+ self.no_keep_alive, self.xheaders)
+ except Exception:
+ logging.error("Error in connection callback", exc_info=True)
class _BadRequestException(Exception):
"""Exception class for malformed HTTP requests."""
import socket
import stat
+from tornado.ioloop import IOLoop
from tornado.platform.auto import set_close_exec
def bind_sockets(port, address=None, family=socket.AF_UNSPEC, backlog=128):
os.chmod(file, mode)
sock.listen(backlog)
return sock
+
+def add_accept_handler(sock, callback, io_loop=None):
+ """Adds an ``IOLoop`` event handler to accept new connections on ``sock``.
+
+ When a connection is accepted, ``callback(connection, address)`` will
+ be run (``connection`` is a socket object, and ``address`` is the
+ address of the other end of the connection). Note that this signature
+ is different from the ``callback(fd, events)`` signature used for
+ ``IOLoop`` handlers.
+ """
+ if io_loop is None:
+ io_loop = IOLoop.instance()
+ def accept_handler(fd, events):
+ while True:
+ try:
+ connection, address = sock.accept()
+ except socket.error, e:
+ if e.args[0] in (errno.EWOULDBLOCK, errno.EAGAIN):
+ return
+ raise
+ callback(connection, address)
+ io_loop.add_handler(sock.fileno(), accept_handler, IOLoop.READ)