Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Orders ipv6 addresses before v4 in resolution (needs a happy eyeballs implementation that supports feeding in resolved addresses) #233

Closed
wants to merge 3 commits into from
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
19 changes: 13 additions & 6 deletions aioesphomeapi/host_resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,10 @@ async def _async_resolve_host_zeroconf(
return []

addrs: List[AddrInfo] = []
for raw in info.addresses_by_version(zeroconf.IPVersion.All):
rawAddrs = info.addresses_by_version(
zeroconf.IPVersion.V6Only
) + info.addresses_by_version(zeroconf.IPVersion.V4Only)
for raw in rawAddrs:
is_ipv6 = len(raw) == 16
sockaddr: Sockaddr
if is_ipv6:
Expand Down Expand Up @@ -135,7 +138,8 @@ async def _async_resolve_host_getaddrinfo(host: str, port: int) -> List[AddrInfo
except OSError as err:
raise APIConnectionError(f"Error resolving IP address: {err}")

addrs: List[AddrInfo] = []
addrsV4: List[AddrInfo] = []
addrsV6: List[AddrInfo] = []
for family, type_, proto, _, raw in res:
sockaddr: Sockaddr
if family == socket.AF_INET:
Expand All @@ -152,10 +156,13 @@ async def _async_resolve_host_getaddrinfo(host: str, port: int) -> List[AddrInfo
# Unknown family
continue

addrs.append(
AddrInfo(family=family, type=type_, proto=proto, sockaddr=sockaddr)
)
return addrs
addrInfo = AddrInfo(family=family, type=type_, proto=proto, sockaddr=sockaddr)
if family == socket.AF_INET6:
addrsV6.append(addrInfo)
else:
addrsV4.append(addrInfo)

return addrsV6 + addrsV4


def _async_ip_address_to_addrs(host: str, port: int) -> List[AddrInfo]:
Expand Down
40 changes: 24 additions & 16 deletions tests/test_host_resolver.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import asyncio
import socket
from typing import List

import pytest
import zeroconf
from mock import AsyncMock, MagicMock, patch

import aioesphomeapi.host_resolver as hr
Expand All @@ -17,12 +19,6 @@ def async_zeroconf():
@pytest.fixture
def addr_infos():
return [
hr.AddrInfo(
family=socket.AF_INET,
type=socket.SOCK_STREAM,
proto=socket.IPPROTO_TCP,
sockaddr=hr.IPv4Sockaddr(address="10.0.0.42", port=6052),
),
hr.AddrInfo(
family=socket.AF_INET6,
type=socket.SOCK_STREAM,
Expand All @@ -34,16 +30,28 @@ def addr_infos():
scope_id=0,
),
),
hr.AddrInfo(
family=socket.AF_INET,
type=socket.SOCK_STREAM,
proto=socket.IPPROTO_TCP,
sockaddr=hr.IPv4Sockaddr(address="10.0.0.42", port=6052),
),
]


@pytest.mark.asyncio
async def test_resolve_host_zeroconf(async_zeroconf, addr_infos):
def address_for_version(version: zeroconf.IPVersion) -> List[bytes]:
if version == zeroconf.IPVersion.V6Only:
return [
b"\x20\x01\x0d\xb8\x85\xa3\x00\x00\x00\x00\x8a\x2e\x03\x70\x73\x34",
]
return [
b"\x0A\x00\x00\x2A",
]

info = MagicMock()
info.addresses_by_version.return_value = [
b"\n\x00\x00*",
b" \x01\r\xb8\x85\xa3\x00\x00\x00\x00\x8a.\x03ps4",
]
info.addresses_by_version.side_effect = address_for_version
async_zeroconf.async_get_service_info = AsyncMock(return_value=info)
async_zeroconf.async_close = AsyncMock()

Expand Down Expand Up @@ -71,18 +79,18 @@ async def test_resolve_host_getaddrinfo(event_loop, addr_infos):
with patch.object(event_loop, "getaddrinfo") as mock:
mock.return_value = [
(
socket.AF_INET,
socket.AF_INET6,
socket.SOCK_STREAM,
socket.IPPROTO_TCP,
"canon1",
("10.0.0.42", 6052),
"canon2",
("2001:db8:85a3::8a2e:370:7334", 6052, 0, 0),
),
(
socket.AF_INET6,
socket.AF_INET,
socket.SOCK_STREAM,
socket.IPPROTO_TCP,
"canon2",
("2001:db8:85a3::8a2e:370:7334", 6052, 0, 0),
"canon1",
("10.0.0.42", 6052),
),
(-1, socket.SOCK_STREAM, socket.IPPROTO_TCP, "canon3", ("10.0.0.42", 6052)),
]
Expand Down