Handle invalid zeroconf messages in Android TV Remote (#128819)

pull/128730/head
tronikos 2024-10-20 00:56:30 -07:00 committed by GitHub
parent 87c9c0c3b1
commit 5f662988ff
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 65 additions and 1 deletions

View File

@ -151,7 +151,18 @@ class AndroidTVRemoteConfigFlow(ConfigFlow, domain=DOMAIN):
if not (mac := discovery_info.properties.get("bt")):
return self.async_abort(reason="cannot_connect")
self.mac = mac
await self.async_set_unique_id(format_mac(self.mac))
existing_config_entry = await self.async_set_unique_id(format_mac(mac))
# Sometimes, devices send an invalid zeroconf message with multiple addresses
# and one of them, which could end up being in discovery_info.host, is from a
# different device. If any of the discovery_info.ip_addresses matches the
# existing host, don't update the host.
if existing_config_entry and len(discovery_info.ip_addresses) > 1:
existing_host = existing_config_entry.data[CONF_HOST]
if existing_host != self.host:
if existing_host in [
str(ip_address) for ip_address in discovery_info.ip_addresses
]:
self.host = existing_host
self._abort_if_unique_id_configured(
updates={CONF_HOST: self.host, CONF_NAME: self.name}
)

View File

@ -757,6 +757,59 @@ async def test_zeroconf_flow_abort_if_mac_is_missing(
assert result["reason"] == "cannot_connect"
async def test_zeroconf_flow_already_configured_zeroconf_has_multiple_invalid_ip_addresses(
hass: HomeAssistant,
mock_setup_entry: AsyncMock,
mock_unload_entry: AsyncMock,
mock_api: MagicMock,
) -> None:
"""Test we abort the zeroconf flow if already configured and zeroconf has invalid ip addresses."""
host = "1.2.3.4"
name = "My Android TV"
mac = "1A:2B:3C:4D:5E:6F"
unique_id = "1a:2b:3c:4d:5e:6f"
name_existing = name
host_existing = host
mock_config_entry = MockConfigEntry(
title=name,
domain=DOMAIN,
data={
"host": host_existing,
"name": name_existing,
"mac": mac,
},
unique_id=unique_id,
state=ConfigEntryState.LOADED,
)
mock_config_entry.add_to_hass(hass)
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": config_entries.SOURCE_ZEROCONF},
data=zeroconf.ZeroconfServiceInfo(
ip_address=ip_address("1.2.3.5"),
ip_addresses=[ip_address("1.2.3.5"), ip_address(host)],
port=6466,
hostname=host,
type="mock_type",
name=name + "._androidtvremote2._tcp.local.",
properties={"bt": mac},
),
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
await hass.async_block_till_done()
assert hass.config_entries.async_entries(DOMAIN)[0].data == {
"host": host,
"name": name,
"mac": mac,
}
assert len(mock_unload_entry.mock_calls) == 0
assert len(mock_setup_entry.mock_calls) == 0
async def test_reauth_flow_success(
hass: HomeAssistant,
mock_setup_entry: AsyncMock,