Use tornado's bind_sockets again
MODIFY
dummyserver/server.py
dummyserver/server.py
@@ -5,7 +5,6 @@ Dummy server used for unit testing.
"""
from __future__ import print_function
-import errno
import logging
import os
import random
@@ -19,9 +18,9 @@ from datetime import datetime
from urllib3.exceptions import HTTPWarning
-from tornado.platform.auto import set_close_exec
import tornado.httpserver
import tornado.ioloop
+import tornado.netutil
import tornado.web
@@ -150,84 +149,6 @@ class SocketServerThread(threading.Thread):
self.server = self._start_server()
-# FIXME: there is a pull request patching bind_sockets in Tornado directly.
-# If it gets merged and released we can drop this and use
-# `tornado.netutil.bind_sockets` again.
-# https://github.com/facebook/tornado/pull/977
-
-
-def bind_sockets(port, address=None, family=socket.AF_UNSPEC, backlog=128, flags=None):
- """Creates listening sockets bound to the given port and address.
-
- Returns a list of socket objects (multiple sockets are returned if
- the given address maps to multiple IP addresses, which is most common
- for mixed IPv4 and IPv6 use).
-
- Address may be either an IP address or hostname. If it's a hostname,
- the server will listen on all IP addresses associated with the
- name. Address may be an empty string or None to listen on all
- available interfaces. Family may be set to either `socket.AF_INET`
- or `socket.AF_INET6` to restrict to IPv4 or IPv6 addresses, otherwise
- both will be used if available.
-
- The ``backlog`` argument has the same meaning as for
- `socket.listen() <socket.socket.listen>`.
-
- ``flags`` is a bitmask of AI_* flags to `~socket.getaddrinfo`, like
- ``socket.AI_PASSIVE | socket.AI_NUMERICHOST``.
- """
- sockets = []
- if address == "":
- address = None
- if not HAS_IPV6 and family == socket.AF_UNSPEC:
- # Python can be compiled with --disable-ipv6, which causes
- # operations on AF_INET6 sockets to fail, but does not
- # automatically exclude those results from getaddrinfo
- # results.
- # http://bugs.python.org/issue16208
- family = socket.AF_INET
- if flags is None:
- flags = socket.AI_PASSIVE
- binded_port = None
- for res in set(
- socket.getaddrinfo(address, port, family, socket.SOCK_STREAM, 0, flags)
- ):
- af, socktype, proto, canonname, sockaddr = res
- try:
- sock = socket.socket(af, socktype, proto)
- except socket.error as e:
- if e.args[0] == errno.EAFNOSUPPORT:
- continue
- raise
- set_close_exec(sock.fileno())
- if os.name != "nt":
- sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- if af == socket.AF_INET6:
- # On linux, ipv6 sockets accept ipv4 too by default,
- # but this makes it impossible to bind to both
- # 0.0.0.0 in ipv4 and :: in ipv6. On other systems,
- # separate sockets *must* be used to listen for both ipv4
- # and ipv6. For consistency, always disable ipv4 on our
- # ipv6 sockets and use a separate ipv4 socket when needed.
- #
- # Python 2.x on windows doesn't have IPPROTO_IPV6.
- if hasattr(socket, "IPPROTO_IPV6"):
- sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 1)
-
- # automatic port allocation with port=None
- # should bind on the same port on IPv4 and IPv6
- host, requested_port = sockaddr[:2]
- if requested_port == 0 and binded_port is not None:
- sockaddr = tuple([host, binded_port] + list(sockaddr[2:]))
-
- sock.setblocking(0)
- sock.bind(sockaddr)
- binded_port = sock.getsockname()[1]
- sock.listen(backlog)
- sockets.append(sock)
- return sockets
-
-
def run_tornado_app(app, io_loop, certs, scheme, host):
assert io_loop == tornado.ioloop.IOLoop.current()
@@ -240,7 +161,7 @@ def run_tornado_app(app, io_loop, certs, scheme, host):
else:
http_server = tornado.httpserver.HTTPServer(app)
- sockets = bind_sockets(None, address=host)
+ sockets = tornado.netutil.bind_sockets(None, address=host)
port = sockets[0].getsockname()[1]
http_server.add_sockets(sockets)
return http_server, port

Use tornado's bind_sockets again (#1728)