mirror of
https://github.com/python/cpython.git
synced 2025-09-27 10:50:04 +00:00
bpo-27500: Fix static version of getaddrinfo to resolve IPv6 (GH-7993)
This commit is contained in:
parent
41cb0baea9
commit
d904c238ca
3 changed files with 33 additions and 6 deletions
|
@ -61,6 +61,8 @@ _MIN_CANCELLED_TIMER_HANDLES_FRACTION = 0.5
|
||||||
_FATAL_ERROR_IGNORE = (BrokenPipeError,
|
_FATAL_ERROR_IGNORE = (BrokenPipeError,
|
||||||
ConnectionResetError, ConnectionAbortedError)
|
ConnectionResetError, ConnectionAbortedError)
|
||||||
|
|
||||||
|
_HAS_IPv6 = hasattr(socket, 'AF_INET6')
|
||||||
|
|
||||||
|
|
||||||
def _format_handle(handle):
|
def _format_handle(handle):
|
||||||
cb = handle._callback
|
cb = handle._callback
|
||||||
|
@ -123,7 +125,7 @@ def _ipaddr_info(host, port, family, type, proto):
|
||||||
|
|
||||||
if family == socket.AF_UNSPEC:
|
if family == socket.AF_UNSPEC:
|
||||||
afs = [socket.AF_INET]
|
afs = [socket.AF_INET]
|
||||||
if hasattr(socket, 'AF_INET6'):
|
if _HAS_IPv6:
|
||||||
afs.append(socket.AF_INET6)
|
afs.append(socket.AF_INET6)
|
||||||
else:
|
else:
|
||||||
afs = [family]
|
afs = [family]
|
||||||
|
@ -139,7 +141,10 @@ def _ipaddr_info(host, port, family, type, proto):
|
||||||
try:
|
try:
|
||||||
socket.inet_pton(af, host)
|
socket.inet_pton(af, host)
|
||||||
# The host has already been resolved.
|
# 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:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -1309,7 +1314,6 @@ class BaseEventLoop(events.AbstractEventLoop):
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
'host/port and sock can not be specified at the same time')
|
'host/port and sock can not be specified at the same time')
|
||||||
|
|
||||||
AF_INET6 = getattr(socket, 'AF_INET6', 0)
|
|
||||||
if reuse_address is None:
|
if reuse_address is None:
|
||||||
reuse_address = os.name == 'posix' and sys.platform != 'cygwin'
|
reuse_address = os.name == 'posix' and sys.platform != 'cygwin'
|
||||||
sockets = []
|
sockets = []
|
||||||
|
@ -1349,7 +1353,9 @@ class BaseEventLoop(events.AbstractEventLoop):
|
||||||
# Disable IPv4/IPv6 dual stack support (enabled by
|
# Disable IPv4/IPv6 dual stack support (enabled by
|
||||||
# default on Linux) which makes a single socket
|
# default on Linux) which makes a single socket
|
||||||
# listen on both address families.
|
# 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,
|
sock.setsockopt(socket.IPPROTO_IPV6,
|
||||||
socket.IPV6_V6ONLY,
|
socket.IPV6_V6ONLY,
|
||||||
True)
|
True)
|
||||||
|
|
|
@ -97,11 +97,11 @@ class BaseEventTests(test_utils.TestCase):
|
||||||
base_events._ipaddr_info('1.2.3.4', 1, INET6, STREAM, TCP))
|
base_events._ipaddr_info('1.2.3.4', 1, INET6, STREAM, TCP))
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
(INET6, STREAM, TCP, '', ('::3', 1)),
|
(INET6, STREAM, TCP, '', ('::3', 1, 0, 0)),
|
||||||
base_events._ipaddr_info('::3', 1, INET6, STREAM, TCP))
|
base_events._ipaddr_info('::3', 1, INET6, STREAM, TCP))
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
(INET6, STREAM, TCP, '', ('::3', 1)),
|
(INET6, STREAM, TCP, '', ('::3', 1, 0, 0)),
|
||||||
base_events._ipaddr_info('::3', 1, UNSPEC, STREAM, TCP))
|
base_events._ipaddr_info('::3', 1, UNSPEC, STREAM, TCP))
|
||||||
|
|
||||||
# IPv6 address with family IPv4.
|
# IPv6 address with family IPv4.
|
||||||
|
@ -1077,6 +1077,26 @@ class BaseEventLoopWithSelectorTests(test_utils.TestCase):
|
||||||
srv.close()
|
srv.close()
|
||||||
self.loop.run_until_complete(srv.wait_closed())
|
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):
|
def test_create_datagram_endpoint_wrong_sock(self):
|
||||||
sock = socket.socket(socket.AF_INET)
|
sock = socket.socket(socket.AF_INET)
|
||||||
with sock:
|
with sock:
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Fix getaddrinfo to resolve IPv6 addresses correctly.
|
Loading…
Add table
Add a link
Reference in a new issue