From: Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> Date: Fri, 29 Jun 2018 02:22:39 +0000 (-0700) Subject: bpo-27500: Fix static version of getaddrinfo to resolve IPv6 (GH-7993) X-Git-Tag: v3.6.7rc1~227 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c00144cd7741a5060662e85717f6559ad46d02aa;p=python bpo-27500: Fix static version of getaddrinfo to resolve IPv6 (GH-7993) (cherry picked from commit d904c238ca3551750cb97d15d827c3e525970867) Co-authored-by: Yury Selivanov --- diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index 083f45df2f..79f0d63c57 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -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) diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index 42c0707e8f..dd61bf0fe5 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -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 index 0000000000..4762e27956 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-06-28-13-00-12.bpo-27500._s1gZ5.rst @@ -0,0 +1 @@ +Fix getaddrinfo to resolve IPv6 addresses correctly.