Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 15 additions & 12 deletions Lib/asyncio/base_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ def _ipaddr_info(host, port, family, type, proto):
if '%' in host:
# Linux's inet_pton doesn't accept an IPv6 zone index after host,
# like '::1%lo0'.
# Such hosts should be resolved by getaddrinfo() to obtain the
# appropriate scope ID, and to have the zone part removed.
return None

for af in afs:
Expand Down Expand Up @@ -917,16 +919,16 @@ async def create_connection(
'host/port and sock can not be specified at the same time')

infos = await self._ensure_resolved(
(host, port), family=family,
type=socket.SOCK_STREAM, proto=proto, flags=flags, loop=self)
host, port, family=family,
type=socket.SOCK_STREAM, proto=proto, flags=flags)
if not infos:
raise OSError('getaddrinfo() returned empty list')

if local_addr is not None:
laddr_infos = await self._ensure_resolved(
local_addr, family=family,
local_addr[0], local_addr[1], family=family,
type=socket.SOCK_STREAM, proto=proto,
flags=flags, loop=self)
flags=flags)
if not laddr_infos:
raise OSError('getaddrinfo() returned empty list')

Expand Down Expand Up @@ -1195,8 +1197,8 @@ async def create_datagram_endpoint(self, protocol_factory,
'2-tuple is expected')

infos = await self._ensure_resolved(
addr, family=family, type=socket.SOCK_DGRAM,
proto=proto, flags=flags, loop=self)
*addr, family=family, type=socket.SOCK_DGRAM,
proto=proto, flags=flags)
if not infos:
raise OSError('getaddrinfo() returned empty list')

Expand Down Expand Up @@ -1277,22 +1279,23 @@ async def create_datagram_endpoint(self, protocol_factory,

return transport, protocol

async def _ensure_resolved(self, address, *,
async def _ensure_resolved(self, host, port, *,
family=0, type=socket.SOCK_STREAM,
proto=0, flags=0, loop):
host, port = address[:2]
proto=0, flags=0):
# Resolve (host, port) into a socket address tuple, skipping
# getaddrinfo() when possible.
info = _ipaddr_info(host, port, family, type, proto)
if info is not None:
# "host" is already a resolved IP.
return [info]
else:
return await loop.getaddrinfo(host, port, family=family, type=type,
return await self.getaddrinfo(host, port, family=family, type=type,
proto=proto, flags=flags)

async def _create_server_getaddrinfo(self, host, port, family, flags):
infos = await self._ensure_resolved((host, port), family=family,
infos = await self._ensure_resolved(host, port, family=family,
type=socket.SOCK_STREAM,
flags=flags, loop=self)
flags=flags)
if not infos:
raise OSError(f'getaddrinfo({host!r}) returned empty list')
return infos
Expand Down
9 changes: 4 additions & 5 deletions Lib/asyncio/selector_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -458,16 +458,15 @@ def _sock_sendall(self, fut, sock, data):
async def sock_connect(self, sock, address):
"""Connect to a remote socket at address.

`address` must be a socket address tuple(i.e. (ipv4_address, port) for
IPv4 or (ipv6_address, port, flowinfo, scopeid) for IPv6). It must
not be a (host, port) tuple that still needs to be resolved.

This method is a coroutine.
"""
if self._debug and sock.gettimeout() != 0:
raise ValueError("the socket must be non-blocking")

if not hasattr(socket, 'AF_UNIX') or sock.family != socket.AF_UNIX:
resolved = await self._ensure_resolved(
address, family=sock.family, proto=sock.proto, loop=self)
_, _, _, _, address = resolved[0]

fut = self.create_future()
self._sock_connect(fut, sock, address)
return await fut
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix mishandling of scoped IPv6 addresses in
BaseEventLoop.create_connection().