Skip to content

Commit d904c23

Browse files
authored
bpo-27500: Fix static version of getaddrinfo to resolve IPv6 (GH-7993)
1 parent 41cb0ba commit d904c23

File tree

3 files changed

+33
-6
lines changed

3 files changed

+33
-6
lines changed

Lib/asyncio/base_events.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@
6161
_FATAL_ERROR_IGNORE = (BrokenPipeError,
6262
ConnectionResetError, ConnectionAbortedError)
6363

64+
_HAS_IPv6 = hasattr(socket, 'AF_INET6')
65+
6466

6567
def _format_handle(handle):
6668
cb = handle._callback
@@ -123,7 +125,7 @@ def _ipaddr_info(host, port, family, type, proto):
123125

124126
if family == socket.AF_UNSPEC:
125127
afs = [socket.AF_INET]
126-
if hasattr(socket, 'AF_INET6'):
128+
if _HAS_IPv6:
127129
afs.append(socket.AF_INET6)
128130
else:
129131
afs = [family]
@@ -139,7 +141,10 @@ def _ipaddr_info(host, port, family, type, proto):
139141
try:
140142
socket.inet_pton(af, host)
141143
# The host has already been resolved.
142-
return af, type, proto, '', (host, port)
144+
if _HAS_IPv6 and af == socket.AF_INET6:
145+
return af, type, proto, '', (host, port, 0, 0)
146+
else:
147+
return af, type, proto, '', (host, port)
143148
except OSError:
144149
pass
145150

@@ -1309,7 +1314,6 @@ async def create_server(
13091314
raise ValueError(
13101315
'host/port and sock can not be specified at the same time')
13111316

1312-
AF_INET6 = getattr(socket, 'AF_INET6', 0)
13131317
if reuse_address is None:
13141318
reuse_address = os.name == 'posix' and sys.platform != 'cygwin'
13151319
sockets = []
@@ -1349,7 +1353,9 @@ async def create_server(
13491353
# Disable IPv4/IPv6 dual stack support (enabled by
13501354
# default on Linux) which makes a single socket
13511355
# listen on both address families.
1352-
if af == AF_INET6 and hasattr(socket, 'IPPROTO_IPV6'):
1356+
if (_HAS_IPv6 and
1357+
af == socket.AF_INET6 and
1358+
hasattr(socket, 'IPPROTO_IPV6')):
13531359
sock.setsockopt(socket.IPPROTO_IPV6,
13541360
socket.IPV6_V6ONLY,
13551361
True)

Lib/test/test_asyncio/test_base_events.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,11 @@ def test_ipaddr_info(self):
9797
base_events._ipaddr_info('1.2.3.4', 1, INET6, STREAM, TCP))
9898

9999
self.assertEqual(
100-
(INET6, STREAM, TCP, '', ('::3', 1)),
100+
(INET6, STREAM, TCP, '', ('::3', 1, 0, 0)),
101101
base_events._ipaddr_info('::3', 1, INET6, STREAM, TCP))
102102

103103
self.assertEqual(
104-
(INET6, STREAM, TCP, '', ('::3', 1)),
104+
(INET6, STREAM, TCP, '', ('::3', 1, 0, 0)),
105105
base_events._ipaddr_info('::3', 1, UNSPEC, STREAM, TCP))
106106

107107
# IPv6 address with family IPv4.
@@ -1077,6 +1077,26 @@ def test_create_server_stream_bittype(self):
10771077
srv.close()
10781078
self.loop.run_until_complete(srv.wait_closed())
10791079

1080+
@unittest.skipUnless(hasattr(socket, 'AF_INET6'), 'no IPv6 support')
1081+
def test_create_server_ipv6(self):
1082+
async def main():
1083+
srv = await asyncio.start_server(
1084+
lambda: None, '::1', 0, loop=self.loop)
1085+
try:
1086+
self.assertGreater(len(srv.sockets), 0)
1087+
finally:
1088+
srv.close()
1089+
await srv.wait_closed()
1090+
1091+
try:
1092+
self.loop.run_until_complete(main())
1093+
except OSError as ex:
1094+
if (hasattr(errno, 'EADDRNOTAVAIL') and
1095+
ex.errno == errno.EADDRNOTAVAIL):
1096+
self.skipTest('failed to bind to ::1')
1097+
else:
1098+
raise
1099+
10801100
def test_create_datagram_endpoint_wrong_sock(self):
10811101
sock = socket.socket(socket.AF_INET)
10821102
with sock:
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix getaddrinfo to resolve IPv6 addresses correctly.

0 commit comments

Comments
 (0)