From f4b36ad045ccfbbfaaadd8e69f9b32c5d81cbd84 Mon Sep 17 00:00:00 2001 From: Quentin Pradet Date: Fri, 1 Nov 2019 16:57:38 +0400 Subject: [PATCH] Use tornado's bind_sockets again (#1728) --- dummyserver/server.py | 83 ++----------------------------------------- 1 file changed, 2 insertions(+), 81 deletions(-) diff --git a/dummyserver/server.py b/dummyserver/server.py index fdf95ec995..f57445f3a2 100755 --- a/dummyserver/server.py +++ b/dummyserver/server.py @@ -5,7 +5,6 @@ """ from __future__ import print_function -import errno import logging import os import random @@ -19,9 +18,9 @@ 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 @@ def run(self): 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() `. - - ``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