]> granicus.if.org Git - python/commitdiff
bpo-27500: Fix static version of getaddrinfo to resolve IPv6 (GH-7993)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Fri, 29 Jun 2018 02:22:39 +0000 (19:22 -0700)
committerGitHub <noreply@github.com>
Fri, 29 Jun 2018 02:22:39 +0000 (19:22 -0700)
(cherry picked from commit d904c238ca3551750cb97d15d827c3e525970867)

Co-authored-by: Yury Selivanov <yury@magic.io>
Lib/asyncio/base_events.py
Lib/test/test_asyncio/test_base_events.py
Misc/NEWS.d/next/Library/2018-06-28-13-00-12.bpo-27500._s1gZ5.rst [new file with mode: 0644]

index 083f45df2ffdf4b312ab52c5490ea18df84da01e..79f0d63c5726e814e72e230a25e9f4b64fdb2fb0 100644 (file)
@@ -54,6 +54,8 @@ _MIN_CANCELLED_TIMER_HANDLES_FRACTION = 0.5
 _FATAL_ERROR_IGNORE = (BrokenPipeError,
                        ConnectionResetError, ConnectionAbortedError)
 
+_HAS_IPv6 = hasattr(socket, 'AF_INET6')
+
 
 def _format_handle(handle):
     cb = handle._callback
@@ -136,7 +138,7 @@ def _ipaddr_info(host, port, family, type, proto):
 
     if family == socket.AF_UNSPEC:
         afs = [socket.AF_INET]
-        if hasattr(socket, 'AF_INET6'):
+        if _HAS_IPv6:
             afs.append(socket.AF_INET6)
     else:
         afs = [family]
@@ -152,7 +154,10 @@ def _ipaddr_info(host, port, family, type, proto):
         try:
             socket.inet_pton(af, host)
             # The host has already been resolved.
-            return af, type, proto, '', (host, port)
+            if _HAS_IPv6 and af == socket.AF_INET6:
+                return af, type, proto, '', (host, port, 0, 0)
+            else:
+                return af, type, proto, '', (host, port)
         except OSError:
             pass
 
@@ -997,7 +1002,6 @@ class BaseEventLoop(events.AbstractEventLoop):
                 raise ValueError(
                     'host/port and sock can not be specified at the same time')
 
-            AF_INET6 = getattr(socket, 'AF_INET6', 0)
             if reuse_address is None:
                 reuse_address = os.name == 'posix' and sys.platform != 'cygwin'
             sockets = []
@@ -1037,7 +1041,9 @@ class BaseEventLoop(events.AbstractEventLoop):
                     # Disable IPv4/IPv6 dual stack support (enabled by
                     # default on Linux) which makes a single socket
                     # listen on both address families.
-                    if af == AF_INET6 and hasattr(socket, 'IPPROTO_IPV6'):
+                    if (_HAS_IPv6 and
+                            af == socket.AF_INET6 and
+                            hasattr(socket, 'IPPROTO_IPV6')):
                         sock.setsockopt(socket.IPPROTO_IPV6,
                                         socket.IPV6_V6ONLY,
                                         True)
index 42c0707e8f21b1edc8e47eadd542fe12754f5ce6..dd61bf0fe59a922787118a9438b7e608018a6cea 100644 (file)
@@ -101,11 +101,11 @@ class BaseEventTests(test_utils.TestCase):
             base_events._ipaddr_info('1.2.3.4', 1, INET6, STREAM, TCP))
 
         self.assertEqual(
-            (INET6, STREAM, TCP, '', ('::3', 1)),
+            (INET6, STREAM, TCP, '', ('::3', 1, 0, 0)),
             base_events._ipaddr_info('::3', 1, INET6, STREAM, TCP))
 
         self.assertEqual(
-            (INET6, STREAM, TCP, '', ('::3', 1)),
+            (INET6, STREAM, TCP, '', ('::3', 1, 0, 0)),
             base_events._ipaddr_info('::3', 1, UNSPEC, STREAM, TCP))
 
         # IPv6 address with family IPv4.
@@ -1067,6 +1067,26 @@ class BaseEventLoopWithSelectorTests(test_utils.TestCase):
             srv.close()
             self.loop.run_until_complete(srv.wait_closed())
 
+    @unittest.skipUnless(hasattr(socket, 'AF_INET6'), 'no IPv6 support')
+    def test_create_server_ipv6(self):
+        async def main():
+            srv = await asyncio.start_server(
+                lambda: None, '::1', 0, loop=self.loop)
+            try:
+                self.assertGreater(len(srv.sockets), 0)
+            finally:
+                srv.close()
+                await srv.wait_closed()
+
+        try:
+            self.loop.run_until_complete(main())
+        except OSError as ex:
+            if (hasattr(errno, 'EADDRNOTAVAIL') and
+                    ex.errno == errno.EADDRNOTAVAIL):
+                self.skipTest('failed to bind to ::1')
+            else:
+                raise
+
     def test_create_datagram_endpoint_wrong_sock(self):
         sock = socket.socket(socket.AF_INET)
         with sock:
diff --git a/Misc/NEWS.d/next/Library/2018-06-28-13-00-12.bpo-27500._s1gZ5.rst b/Misc/NEWS.d/next/Library/2018-06-28-13-00-12.bpo-27500._s1gZ5.rst
new file mode 100644 (file)
index 0000000..4762e27
--- /dev/null
@@ -0,0 +1 @@
+Fix getaddrinfo to resolve IPv6 addresses correctly.