Skip to content

Commit c00144c

Browse files
miss-islington1st1
andauthored
bpo-27500: Fix static version of getaddrinfo to resolve IPv6 (GH-7993)
(cherry picked from commit d904c23) Co-authored-by: Yury Selivanov <[email protected]>
1 parent 0ebd1bc commit c00144c

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
@@ -54,6 +54,8 @@
5454
_FATAL_ERROR_IGNORE = (BrokenPipeError,
5555
ConnectionResetError, ConnectionAbortedError)
5656

57+
_HAS_IPv6 = hasattr(socket, 'AF_INET6')
58+
5759

5860
def _format_handle(handle):
5961
cb = handle._callback
@@ -136,7 +138,7 @@ def _ipaddr_info(host, port, family, type, proto):
136138

137139
if family == socket.AF_UNSPEC:
138140
afs = [socket.AF_INET]
139-
if hasattr(socket, 'AF_INET6'):
141+
if _HAS_IPv6:
140142
afs.append(socket.AF_INET6)
141143
else:
142144
afs = [family]
@@ -152,7 +154,10 @@ def _ipaddr_info(host, port, family, type, proto):
152154
try:
153155
socket.inet_pton(af, host)
154156
# The host has already been resolved.
155-
return af, type, proto, '', (host, port)
157+
if _HAS_IPv6 and af == socket.AF_INET6:
158+
return af, type, proto, '', (host, port, 0, 0)
159+
else:
160+
return af, type, proto, '', (host, port)
156161
except OSError:
157162
pass
158163

@@ -997,7 +1002,6 @@ def create_server(self, protocol_factory, host=None, port=None,
9971002
raise ValueError(
9981003
'host/port and sock can not be specified at the same time')
9991004

1000-
AF_INET6 = getattr(socket, 'AF_INET6', 0)
10011005
if reuse_address is None:
10021006
reuse_address = os.name == 'posix' and sys.platform != 'cygwin'
10031007
sockets = []
@@ -1037,7 +1041,9 @@ def create_server(self, protocol_factory, host=None, port=None,
10371041
# Disable IPv4/IPv6 dual stack support (enabled by
10381042
# default on Linux) which makes a single socket
10391043
# listen on both address families.
1040-
if af == AF_INET6 and hasattr(socket, 'IPPROTO_IPV6'):
1044+
if (_HAS_IPv6 and
1045+
af == socket.AF_INET6 and
1046+
hasattr(socket, 'IPPROTO_IPV6')):
10411047
sock.setsockopt(socket.IPPROTO_IPV6,
10421048
socket.IPV6_V6ONLY,
10431049
True)

Lib/test/test_asyncio/test_base_events.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,11 @@ def test_ipaddr_info(self):
101101
base_events._ipaddr_info('1.2.3.4', 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, INET6, STREAM, TCP))
106106

107107
self.assertEqual(
108-
(INET6, STREAM, TCP, '', ('::3', 1)),
108+
(INET6, STREAM, TCP, '', ('::3', 1, 0, 0)),
109109
base_events._ipaddr_info('::3', 1, UNSPEC, STREAM, TCP))
110110

111111
# IPv6 address with family IPv4.
@@ -1067,6 +1067,26 @@ def test_create_server_stream_bittype(self):
10671067
srv.close()
10681068
self.loop.run_until_complete(srv.wait_closed())
10691069

1070+
@unittest.skipUnless(hasattr(socket, 'AF_INET6'), 'no IPv6 support')
1071+
def test_create_server_ipv6(self):
1072+
async def main():
1073+
srv = await asyncio.start_server(
1074+
lambda: None, '::1', 0, loop=self.loop)
1075+
try:
1076+
self.assertGreater(len(srv.sockets), 0)
1077+
finally:
1078+
srv.close()
1079+
await srv.wait_closed()
1080+
1081+
try:
1082+
self.loop.run_until_complete(main())
1083+
except OSError as ex:
1084+
if (hasattr(errno, 'EADDRNOTAVAIL') and
1085+
ex.errno == errno.EADDRNOTAVAIL):
1086+
self.skipTest('failed to bind to ::1')
1087+
else:
1088+
raise
1089+
10701090
def test_create_datagram_endpoint_wrong_sock(self):
10711091
sock = socket.socket(socket.AF_INET)
10721092
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)