]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Move socket accept loop from HTTPServer to netutil.
authorBen Darnell <ben@bendarnell.com>
Sat, 9 Jul 2011 21:35:59 +0000 (14:35 -0700)
committerBen Darnell <ben@bendarnell.com>
Sat, 9 Jul 2011 21:35:59 +0000 (14:35 -0700)
tornado/httpserver.py
tornado/netutil.py

index 6d58d0d2c7c14f4914678050b41fdb26c3858b35..deb8dcbc0aff730326c437503a8ea41dfdd8a8e8 100644 (file)
@@ -167,8 +167,8 @@ class HTTPServer(object):
             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."""
@@ -238,43 +238,36 @@ class HTTPServer(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."""
index 05921dfaeba40c246ac2fdeee9271f9a47efa767..557b227ab9ae4c198b84c7a1c6ce900f26142530 100644 (file)
@@ -21,6 +21,7 @@ import os
 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):
@@ -102,3 +103,25 @@ if hasattr(socket, 'AF_UNIX'):
         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)