We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
TestSNI:test_hostname_in_first_request_packet hangs
My system supports IPv6 and resolves `localhost` to `127.0.0.1`.
When I run the test suite on my system, `TestSNI:test_hostname_in_first_request_packet` hangs.
This also fail about 80 more tests with `MaxRetryError`.

### Expected Result
1. The test should pass.
2. The test should never hang.

### Actual Result
The test uses `_start_server` to create a `SocketServerThread` that binds on an IPv6 address by default (if possible):
```python
 70 HAS_IPV6_AND_DNS = _has_ipv6("localhost")
...
 90     USE_IPV6 = HAS_IPV6_AND_DNS
...
101         if self.USE_IPV6:
102             sock = socket.socket(socket.AF_INET6)
```
but the client connection might still resolve to IPv4 address and use it:
```python
 61     for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
 62         af, socktype, proto, canonname, sa = res
 63         sock = None
 64         try:
 65             sock = socket.socket(af, socktype, proto)
...
103     if HAS_IPV6:
104         family = socket.AF_UNSPEC
```
The test waits until an event is set, which is never, because the server socket never gets accepted.

### Reproduction Steps
```
$ cat noxfile-single.patch
30a31,32
>         "-o", "log_cli=true",
>         "-k", "test_hostname_in_first_request_packet",
$ patch noxfile.py noxfile-single.patch
patching file noxfile.py
$ nox --sessions test-2.7
nox > Running session test-2.7
nox > Creating virtual environment (virtualenv) using python2.7 in .nox/test-2-7
nox > pip install -r dev-requirements.txt
nox > pip install .[socks,secure,brotli]
nox > pip --version
pip 20.0.2 from /home/user/dev/urllib3/.nox/test-2-7/lib/python2.7/site-packages/pip (python 2.7)
nox > python --version
Python 2.7.17
nox > python -c import struct; print(struct.calcsize('P') * 8)
64
nox > python -m OpenSSL.debug
pyOpenSSL: 19.1.0
cryptography: 2.8
cffi: 1.14.0
cryptography's compiled against OpenSSL: OpenSSL 1.1.1d  10 Sep 2019
cryptography's linked OpenSSL: OpenSSL 1.1.1d  10 Sep 2019
Pythons's OpenSSL: OpenSSL 1.1.1  11 Sep 2018
Python executable: /home/user/dev/urllib3/.nox/test-2-7/bin/python
Python version: 2.7.17 (default, Nov  7 2019, 10:07:09)
[GCC 7.4.0]
Platform: linux2
sys.path: ['', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-x86_64-linux-gnu', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/home/user/dev/urllib3/.nox/test-2-7/lib/python2.7/site-packages']
nox > coverage run --parallel-mode -m pytest -o log_cli=true -k test_hostname_in_first_request_packet -r a --tb=native --no-success-flaky-report test/
==================================== test session starts ====================================
platform linux2 -- Python 2.7.17, pytest-4.6.6, py-1.8.1, pluggy-0.13.1
rootdir: /home/user/dev/urllib3, inifile: setup.cfg
plugins: flaky-3.6.1, timeout-1.3.3
collected 1342 items / 1339 deselected / 3 selected

test/contrib/test_pyopenssl.py::TestSNI::test_hostname_in_first_request_packet
[hangs]
```

### System Information
```
$ git rev-parse --short HEAD
eee53a69
$ cat /etc/hosts
127.0.0.1       localhost
127.0.1.1       ubuntu

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
```

### Fix
I can add a timeout to the test, but that's a solution to the root problem.
I suggest that `ServerSocketThread` treat a system where `localhost` does not resolve to `::1` as having insane IPv6 configuration and use the current IPv4 fallback mechanism.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `dummyserver/server.py`
Content:
```
1 #!/usr/bin/env python
2 
3 """
4 Dummy server used for unit testing.
5 """
6 from __future__ import print_function
7 
8 import logging
9 import os
10 import random
11 import string
12 import sys
13 import threading
14 import socket
15 import warnings
16 import ssl
17 from datetime import datetime
18 
19 from urllib3.exceptions import HTTPWarning
20 
21 from cryptography.hazmat.backends import default_backend
22 from cryptography.hazmat.primitives import serialization
23 import tornado.httpserver
24 import tornado.ioloop
25 import tornado.netutil
26 import tornado.web
27 import trustme
28 
29 
30 log = logging.getLogger(__name__)
31 
32 CERTS_PATH = os.path.join(os.path.dirname(__file__), "certs")
33 DEFAULT_CERTS = {
34     "certfile": os.path.join(CERTS_PATH, "server.crt"),
35     "keyfile": os.path.join(CERTS_PATH, "server.key"),
36     "cert_reqs": ssl.CERT_OPTIONAL,
37     "ca_certs": os.path.join(CERTS_PATH, "cacert.pem"),
38 }
39 DEFAULT_CA = os.path.join(CERTS_PATH, "cacert.pem")
40 DEFAULT_CA_KEY = os.path.join(CERTS_PATH, "cacert.key")
41 
42 
43 def _has_ipv6(host):
44     """ Returns True if the system can bind an IPv6 address. """
45     sock = None
46     has_ipv6 = False
47 
48     if socket.has_ipv6:
49         # has_ipv6 returns true if cPython was compiled with IPv6 support.
50         # It does not tell us if the system has IPv6 support enabled. To
51         # determine that we must bind to an IPv6 address.
52         # https://github.com/urllib3/urllib3/pull/611
53         # https://bugs.python.org/issue658327
54         try:
55             sock = socket.socket(socket.AF_INET6)
56             sock.bind((host, 0))
57             has_ipv6 = True
58         except Exception:
59             pass
60 
61     if sock:
62         sock.close()
63     return has_ipv6
64 
65 
66 # Some systems may have IPv6 support but DNS may not be configured
67 # properly. We can not count that localhost will resolve to ::1 on all
68 # systems. See https://github.com/urllib3/urllib3/pull/611 and
69 # https://bugs.python.org/issue18792
70 HAS_IPV6_AND_DNS = _has_ipv6("localhost")
71 HAS_IPV6 = _has_ipv6("::1")
72 
73 
74 # Different types of servers we have:
75 
76 
77 class NoIPv6Warning(HTTPWarning):
78     "IPv6 is not available"
79     pass
80 
81 
82 class SocketServerThread(threading.Thread):
83     """
84     :param socket_handler: Callable which receives a socket argument for one
85         request.
86     :param ready_event: Event which gets set when the socket handler is
87         ready to receive requests.
88     """
89 
90     USE_IPV6 = HAS_IPV6_AND_DNS
91 
92     def __init__(self, socket_handler, host="localhost", port=8081, ready_event=None):
93         threading.Thread.__init__(self)
94         self.daemon = True
95 
96         self.socket_handler = socket_handler
97         self.host = host
98         self.ready_event = ready_event
99 
100     def _start_server(self):
101         if self.USE_IPV6:
102             sock = socket.socket(socket.AF_INET6)
103         else:
104             warnings.warn("No IPv6 support. Falling back to IPv4.", NoIPv6Warning)
105             sock = socket.socket(socket.AF_INET)
106         if sys.platform != "win32":
107             sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
108         sock.bind((self.host, 0))
109         self.port = sock.getsockname()[1]
110 
111         # Once listen() returns, the server socket is ready
112         sock.listen(1)
113 
114         if self.ready_event:
115             self.ready_event.set()
116 
117         self.socket_handler(sock)
118         sock.close()
119 
120     def run(self):
121         self.server = self._start_server()
122 
123 
124 def run_tornado_app(app, io_loop, certs, scheme, host):
125     assert io_loop == tornado.ioloop.IOLoop.current()
126 
127     # We can't use fromtimestamp(0) because of CPython issue 29097, so we'll
128     # just construct the datetime object directly.
129     app.last_req = datetime(1970, 1, 1)
130 
131     if scheme == "https":
132         http_server = tornado.httpserver.HTTPServer(app, ssl_options=certs)
133     else:
134         http_server = tornado.httpserver.HTTPServer(app)
135 
136     sockets = tornado.netutil.bind_sockets(None, address=host)
137     port = sockets[0].getsockname()[1]
138     http_server.add_sockets(sockets)
139     return http_server, port
140 
141 
142 def run_loop_in_thread(io_loop):
143     t = threading.Thread(target=io_loop.start)
144     t.start()
145     return t
146 
147 
148 def get_unreachable_address():
149     while True:
150         host = "".join(random.choice(string.ascii_lowercase) for _ in range(60))
151         sockaddr = (host, 54321)
152 
153         # check if we are really "lucky" and hit an actual server
154         try:
155             s = socket.create_connection(sockaddr)
156         except socket.error:
157             return sockaddr
158         else:
159             s.close()
160 
161 
162 if __name__ == "__main__":
163     # For debugging dummyserver itself - python -m dummyserver.server
164     from .testcase import TestingApp
165 
166     host = "127.0.0.1"
167 
168     io_loop = tornado.ioloop.IOLoop.current()
169     app = tornado.web.Application([(r".*", TestingApp)])
170     server, port = run_tornado_app(app, io_loop, None, "http", host)
171     server_thread = run_loop_in_thread(io_loop)
172 
173     print("Listening on http://{host}:{port}".format(host=host, port=port))
174 
175 
176 def encrypt_key_pem(private_key_pem, password):
177     private_key = serialization.load_pem_private_key(
178         private_key_pem.bytes(), password=None, backend=default_backend()
179     )
180     encrypted_key = private_key.private_bytes(
181         serialization.Encoding.PEM,
182         serialization.PrivateFormat.TraditionalOpenSSL,
183         serialization.BestAvailableEncryption(password),
184     )
185     return trustme.Blob(encrypted_key)
186
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/dummyserver/server.py b/dummyserver/server.py
--- a/dummyserver/server.py
+++ b/dummyserver/server.py
@@ -40,6 +40,20 @@
 DEFAULT_CA_KEY = os.path.join(CERTS_PATH, "cacert.key")
 
 
+def _resolves_to_ipv6(host):
+    """ Returns True if the system resolves host to an IPv6 address by default. """
+    resolves_to_ipv6 = False
+    try:
+        for res in socket.getaddrinfo(host, None, socket.AF_UNSPEC):
+            af, _, _, _, _ = res
+            if af == socket.AF_INET6:
+                resolves_to_ipv6 = True
+    except socket.gaierror:
+        pass
+
+    return resolves_to_ipv6
+
+
 def _has_ipv6(host):
     """ Returns True if the system can bind an IPv6 address. """
     sock = None
@@ -54,7 +68,7 @@
         try:
             sock = socket.socket(socket.AF_INET6)
             sock.bind((host, 0))
-            has_ipv6 = True
+            has_ipv6 = _resolves_to_ipv6("localhost")
         except Exception:
             pass

{"golden_diff": "diff --git a/dummyserver/server.py b/dummyserver/server.py\n--- a/dummyserver/server.py\n+++ b/dummyserver/server.py\n@@ -40,6 +40,20 @@\n DEFAULT_CA_KEY = os.path.join(CERTS_PATH, \"cacert.key\")\n \n \n+def _resolves_to_ipv6(host):\n+    \"\"\" Returns True if the system resolves host to an IPv6 address by default. \"\"\"\n+    resolves_to_ipv6 = False\n+    try:\n+        for res in socket.getaddrinfo(host, None, socket.AF_UNSPEC):\n+            af, _, _, _, _ = res\n+            if af == socket.AF_INET6:\n+                resolves_to_ipv6 = True\n+    except socket.gaierror:\n+        pass\n+\n+    return resolves_to_ipv6\n+\n+\n def _has_ipv6(host):\n     \"\"\" Returns True if the system can bind an IPv6 address. \"\"\"\n     sock = None\n@@ -54,7 +68,7 @@\n         try:\n             sock = socket.socket(socket.AF_INET6)\n             sock.bind((host, 0))\n-            has_ipv6 = True\n+            has_ipv6 = _resolves_to_ipv6(\"localhost\")\n         except Exception:\n             pass\n", "issue": "TestSNI:test_hostname_in_first_request_packet hangs\nMy system supports IPv6 and resolves `localhost` to `127.0.0.1`.\r\nWhen I run the test suite on my system, `TestSNI:test_hostname_in_first_request_packet` hangs.\r\nThis also fail about 80 more tests with `MaxRetryError`.\r\n\r\n### Expected Result\r\n1. The test should pass.\r\n2. The test should never hang.\r\n\r\n### Actual Result\r\nThe test uses `_start_server` to create a `SocketServerThread` that binds on an IPv6 address by default (if possible):\r\n```python\r\n 70 HAS_IPV6_AND_DNS = _has_ipv6(\"localhost\")\r\n...\r\n 90     USE_IPV6 = HAS_IPV6_AND_DNS\r\n...\r\n101         if self.USE_IPV6:\r\n102             sock = socket.socket(socket.AF_INET6)\r\n```\r\nbut the client connection might still resolve to IPv4 address and use it:\r\n```python\r\n 61     for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):\r\n 62         af, socktype, proto, canonname, sa = res\r\n 63         sock = None\r\n 64         try:\r\n 65             sock = socket.socket(af, socktype, proto)\r\n...\r\n103     if HAS_IPV6:\r\n104         family = socket.AF_UNSPEC\r\n```\r\nThe test waits until an event is set, which is never, because the server socket never gets accepted.\r\n\r\n### Reproduction Steps\r\n```\r\n$ cat noxfile-single.patch\r\n30a31,32\r\n>         \"-o\", \"log_cli=true\",\r\n>         \"-k\", \"test_hostname_in_first_request_packet\",\r\n$ patch noxfile.py noxfile-single.patch\r\npatching file noxfile.py\r\n$ nox --sessions test-2.7\r\nnox > Running session test-2.7\r\nnox > Creating virtual environment (virtualenv) using python2.7 in .nox/test-2-7\r\nnox > pip install -r dev-requirements.txt\r\nnox > pip install .[socks,secure,brotli]\r\nnox > pip --version\r\npip 20.0.2 from /home/user/dev/urllib3/.nox/test-2-7/lib/python2.7/site-packages/pip (python 2.7)\r\nnox > python --version\r\nPython 2.7.17\r\nnox > python -c import struct; print(struct.calcsize('P') * 8)\r\n64\r\nnox > python -m OpenSSL.debug\r\npyOpenSSL: 19.1.0\r\ncryptography: 2.8\r\ncffi: 1.14.0\r\ncryptography's compiled against OpenSSL: OpenSSL 1.1.1d  10 Sep 2019\r\ncryptography's linked OpenSSL: OpenSSL 1.1.1d  10 Sep 2019\r\nPythons's OpenSSL: OpenSSL 1.1.1  11 Sep 2018\r\nPython executable: /home/user/dev/urllib3/.nox/test-2-7/bin/python\r\nPython version: 2.7.17 (default, Nov  7 2019, 10:07:09)\r\n[GCC 7.4.0]\r\nPlatform: linux2\r\nsys.path: ['', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-x86_64-linux-gnu', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/home/user/dev/urllib3/.nox/test-2-7/lib/python2.7/site-packages']\r\nnox > coverage run --parallel-mode -m pytest -o log_cli=true -k test_hostname_in_first_request_packet -r a --tb=native --no-success-flaky-report test/\r\n==================================== test session starts ====================================\r\nplatform linux2 -- Python 2.7.17, pytest-4.6.6, py-1.8.1, pluggy-0.13.1\r\nrootdir: /home/user/dev/urllib3, inifile: setup.cfg\r\nplugins: flaky-3.6.1, timeout-1.3.3\r\ncollected 1342 items / 1339 deselected / 3 selected\r\n\r\ntest/contrib/test_pyopenssl.py::TestSNI::test_hostname_in_first_request_packet\r\n[hangs]\r\n```\r\n\r\n### System Information\r\n```\r\n$ git rev-parse --short HEAD\r\neee53a69\r\n$ cat /etc/hosts\r\n127.0.0.1       localhost\r\n127.0.1.1       ubuntu\r\n\r\n# The following lines are desirable for IPv6 capable hosts\r\n::1     ip6-localhost ip6-loopback\r\nfe00::0 ip6-localnet\r\nff00::0 ip6-mcastprefix\r\nff02::1 ip6-allnodes\r\nff02::2 ip6-allrouters\r\n```\r\n\r\n### Fix\r\nI can add a timeout to the test, but that's a solution to the root problem.\r\nI suggest that `ServerSocketThread` treat a system where `localhost` does not resolve to `::1` as having insane IPv6 configuration and use the current IPv4 fallback mechanism.\n", "before_files": [{"content": "#!/usr/bin/env python\n\n\"\"\"\nDummy server used for unit testing.\n\"\"\"\nfrom __future__ import print_function\n\nimport logging\nimport os\nimport random\nimport string\nimport sys\nimport threading\nimport socket\nimport warnings\nimport ssl\nfrom datetime import datetime\n\nfrom urllib3.exceptions import HTTPWarning\n\nfrom cryptography.hazmat.backends import default_backend\nfrom cryptography.hazmat.primitives import serialization\nimport tornado.httpserver\nimport tornado.ioloop\nimport tornado.netutil\nimport tornado.web\nimport trustme\n\n\nlog = logging.getLogger(__name__)\n\nCERTS_PATH = os.path.join(os.path.dirname(__file__), \"certs\")\nDEFAULT_CERTS = {\n    \"certfile\": os.path.join(CERTS_PATH, \"server.crt\"),\n    \"keyfile\": os.path.join(CERTS_PATH, \"server.key\"),\n    \"cert_reqs\": ssl.CERT_OPTIONAL,\n    \"ca_certs\": os.path.join(CERTS_PATH, \"cacert.pem\"),\n}\nDEFAULT_CA = os.path.join(CERTS_PATH, \"cacert.pem\")\nDEFAULT_CA_KEY = os.path.join(CERTS_PATH, \"cacert.key\")\n\n\ndef _has_ipv6(host):\n    \"\"\" Returns True if the system can bind an IPv6 address. \"\"\"\n    sock = None\n    has_ipv6 = False\n\n    if socket.has_ipv6:\n        # has_ipv6 returns true if cPython was compiled with IPv6 support.\n        # It does not tell us if the system has IPv6 support enabled. To\n        # determine that we must bind to an IPv6 address.\n        # https://github.com/urllib3/urllib3/pull/611\n        # https://bugs.python.org/issue658327\n        try:\n            sock = socket.socket(socket.AF_INET6)\n            sock.bind((host, 0))\n            has_ipv6 = True\n        except Exception:\n            pass\n\n    if sock:\n        sock.close()\n    return has_ipv6\n\n\n# Some systems may have IPv6 support but DNS may not be configured\n# properly. We can not count that localhost will resolve to ::1 on all\n# systems. See https://github.com/urllib3/urllib3/pull/611 and\n# https://bugs.python.org/issue18792\nHAS_IPV6_AND_DNS = _has_ipv6(\"localhost\")\nHAS_IPV6 = _has_ipv6(\"::1\")\n\n\n# Different types of servers we have:\n\n\nclass NoIPv6Warning(HTTPWarning):\n    \"IPv6 is not available\"\n    pass\n\n\nclass SocketServerThread(threading.Thread):\n    \"\"\"\n    :param socket_handler: Callable which receives a socket argument for one\n        request.\n    :param ready_event: Event which gets set when the socket handler is\n        ready to receive requests.\n    \"\"\"\n\n    USE_IPV6 = HAS_IPV6_AND_DNS\n\n    def __init__(self, socket_handler, host=\"localhost\", port=8081, ready_event=None):\n        threading.Thread.__init__(self)\n        self.daemon = True\n\n        self.socket_handler = socket_handler\n        self.host = host\n        self.ready_event = ready_event\n\n    def _start_server(self):\n        if self.USE_IPV6:\n            sock = socket.socket(socket.AF_INET6)\n        else:\n            warnings.warn(\"No IPv6 support. Falling back to IPv4.\", NoIPv6Warning)\n            sock = socket.socket(socket.AF_INET)\n        if sys.platform != \"win32\":\n            sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n        sock.bind((self.host, 0))\n        self.port = sock.getsockname()[1]\n\n        # Once listen() returns, the server socket is ready\n        sock.listen(1)\n\n        if self.ready_event:\n            self.ready_event.set()\n\n        self.socket_handler(sock)\n        sock.close()\n\n    def run(self):\n        self.server = self._start_server()\n\n\ndef run_tornado_app(app, io_loop, certs, scheme, host):\n    assert io_loop == tornado.ioloop.IOLoop.current()\n\n    # We can't use fromtimestamp(0) because of CPython issue 29097, so we'll\n    # just construct the datetime object directly.\n    app.last_req = datetime(1970, 1, 1)\n\n    if scheme == \"https\":\n        http_server = tornado.httpserver.HTTPServer(app, ssl_options=certs)\n    else:\n        http_server = tornado.httpserver.HTTPServer(app)\n\n    sockets = tornado.netutil.bind_sockets(None, address=host)\n    port = sockets[0].getsockname()[1]\n    http_server.add_sockets(sockets)\n    return http_server, port\n\n\ndef run_loop_in_thread(io_loop):\n    t = threading.Thread(target=io_loop.start)\n    t.start()\n    return t\n\n\ndef get_unreachable_address():\n    while True:\n        host = \"\".join(random.choice(string.ascii_lowercase) for _ in range(60))\n        sockaddr = (host, 54321)\n\n        # check if we are really \"lucky\" and hit an actual server\n        try:\n            s = socket.create_connection(sockaddr)\n        except socket.error:\n            return sockaddr\n        else:\n            s.close()\n\n\nif __name__ == \"__main__\":\n    # For debugging dummyserver itself - python -m dummyserver.server\n    from .testcase import TestingApp\n\n    host = \"127.0.0.1\"\n\n    io_loop = tornado.ioloop.IOLoop.current()\n    app = tornado.web.Application([(r\".*\", TestingApp)])\n    server, port = run_tornado_app(app, io_loop, None, \"http\", host)\n    server_thread = run_loop_in_thread(io_loop)\n\n    print(\"Listening on http://{host}:{port}\".format(host=host, port=port))\n\n\ndef encrypt_key_pem(private_key_pem, password):\n    private_key = serialization.load_pem_private_key(\n        private_key_pem.bytes(), password=None, backend=default_backend()\n    )\n    encrypted_key = private_key.private_bytes(\n        serialization.Encoding.PEM,\n        serialization.PrivateFormat.TraditionalOpenSSL,\n        serialization.BestAvailableEncryption(password),\n    )\n    return trustme.Blob(encrypted_key)\n", "path": "dummyserver/server.py"}], "after_files": [{"content": "#!/usr/bin/env python\n\n\"\"\"\nDummy server used for unit testing.\n\"\"\"\nfrom __future__ import print_function\n\nimport logging\nimport os\nimport random\nimport string\nimport sys\nimport threading\nimport socket\nimport warnings\nimport ssl\nfrom datetime import datetime\n\nfrom urllib3.exceptions import HTTPWarning\n\nfrom cryptography.hazmat.backends import default_backend\nfrom cryptography.hazmat.primitives import serialization\nimport tornado.httpserver\nimport tornado.ioloop\nimport tornado.netutil\nimport tornado.web\nimport trustme\n\n\nlog = logging.getLogger(__name__)\n\nCERTS_PATH = os.path.join(os.path.dirname(__file__), \"certs\")\nDEFAULT_CERTS = {\n    \"certfile\": os.path.join(CERTS_PATH, \"server.crt\"),\n    \"keyfile\": os.path.join(CERTS_PATH, \"server.key\"),\n    \"cert_reqs\": ssl.CERT_OPTIONAL,\n    \"ca_certs\": os.path.join(CERTS_PATH, \"cacert.pem\"),\n}\nDEFAULT_CA = os.path.join(CERTS_PATH, \"cacert.pem\")\nDEFAULT_CA_KEY = os.path.join(CERTS_PATH, \"cacert.key\")\n\n\ndef _resolves_to_ipv6(host):\n    \"\"\" Returns True if the system resolves host to an IPv6 address by default. \"\"\"\n    resolves_to_ipv6 = False\n    try:\n        for res in socket.getaddrinfo(host, None, socket.AF_UNSPEC):\n            af, _, _, _, _ = res\n            if af == socket.AF_INET6:\n                resolves_to_ipv6 = True\n    except socket.gaierror:\n        pass\n\n    return resolves_to_ipv6\n\n\ndef _has_ipv6(host):\n    \"\"\" Returns True if the system can bind an IPv6 address. \"\"\"\n    sock = None\n    has_ipv6 = False\n\n    if socket.has_ipv6:\n        # has_ipv6 returns true if cPython was compiled with IPv6 support.\n        # It does not tell us if the system has IPv6 support enabled. To\n        # determine that we must bind to an IPv6 address.\n        # https://github.com/urllib3/urllib3/pull/611\n        # https://bugs.python.org/issue658327\n        try:\n            sock = socket.socket(socket.AF_INET6)\n            sock.bind((host, 0))\n            has_ipv6 = _resolves_to_ipv6(\"localhost\")\n        except Exception:\n            pass\n\n    if sock:\n        sock.close()\n    return has_ipv6\n\n\n# Some systems may have IPv6 support but DNS may not be configured\n# properly. We can not count that localhost will resolve to ::1 on all\n# systems. See https://github.com/urllib3/urllib3/pull/611 and\n# https://bugs.python.org/issue18792\nHAS_IPV6_AND_DNS = _has_ipv6(\"localhost\")\nHAS_IPV6 = _has_ipv6(\"::1\")\n\n\n# Different types of servers we have:\n\n\nclass NoIPv6Warning(HTTPWarning):\n    \"IPv6 is not available\"\n    pass\n\n\nclass SocketServerThread(threading.Thread):\n    \"\"\"\n    :param socket_handler: Callable which receives a socket argument for one\n        request.\n    :param ready_event: Event which gets set when the socket handler is\n        ready to receive requests.\n    \"\"\"\n\n    USE_IPV6 = HAS_IPV6_AND_DNS\n\n    def __init__(self, socket_handler, host=\"localhost\", port=8081, ready_event=None):\n        threading.Thread.__init__(self)\n        self.daemon = True\n\n        self.socket_handler = socket_handler\n        self.host = host\n        self.ready_event = ready_event\n\n    def _start_server(self):\n        if self.USE_IPV6:\n            sock = socket.socket(socket.AF_INET6)\n        else:\n            warnings.warn(\"No IPv6 support. Falling back to IPv4.\", NoIPv6Warning)\n            sock = socket.socket(socket.AF_INET)\n        if sys.platform != \"win32\":\n            sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n        sock.bind((self.host, 0))\n        self.port = sock.getsockname()[1]\n\n        # Once listen() returns, the server socket is ready\n        sock.listen(1)\n\n        if self.ready_event:\n            self.ready_event.set()\n\n        self.socket_handler(sock)\n        sock.close()\n\n    def run(self):\n        self.server = self._start_server()\n\n\ndef run_tornado_app(app, io_loop, certs, scheme, host):\n    assert io_loop == tornado.ioloop.IOLoop.current()\n\n    # We can't use fromtimestamp(0) because of CPython issue 29097, so we'll\n    # just construct the datetime object directly.\n    app.last_req = datetime(1970, 1, 1)\n\n    if scheme == \"https\":\n        http_server = tornado.httpserver.HTTPServer(app, ssl_options=certs)\n    else:\n        http_server = tornado.httpserver.HTTPServer(app)\n\n    sockets = tornado.netutil.bind_sockets(None, address=host)\n    port = sockets[0].getsockname()[1]\n    http_server.add_sockets(sockets)\n    return http_server, port\n\n\ndef run_loop_in_thread(io_loop):\n    t = threading.Thread(target=io_loop.start)\n    t.start()\n    return t\n\n\ndef get_unreachable_address():\n    while True:\n        host = \"\".join(random.choice(string.ascii_lowercase) for _ in range(60))\n        sockaddr = (host, 54321)\n\n        # check if we are really \"lucky\" and hit an actual server\n        try:\n            s = socket.create_connection(sockaddr)\n        except socket.error:\n            return sockaddr\n        else:\n            s.close()\n\n\nif __name__ == \"__main__\":\n    # For debugging dummyserver itself - python -m dummyserver.server\n    from .testcase import TestingApp\n\n    host = \"127.0.0.1\"\n\n    io_loop = tornado.ioloop.IOLoop.current()\n    app = tornado.web.Application([(r\".*\", TestingApp)])\n    server, port = run_tornado_app(app, io_loop, None, \"http\", host)\n    server_thread = run_loop_in_thread(io_loop)\n\n    print(\"Listening on http://{host}:{port}\".format(host=host, port=port))\n\n\ndef encrypt_key_pem(private_key_pem, password):\n    private_key = serialization.load_pem_private_key(\n        private_key_pem.bytes(), password=None, backend=default_backend()\n    )\n    encrypted_key = private_key.private_bytes(\n        serialization.Encoding.PEM,\n        serialization.PrivateFormat.TraditionalOpenSSL,\n        serialization.BestAvailableEncryption(password),\n    )\n    return trustme.Blob(encrypted_key)\n", "path": "dummyserver/server.py"}]}