Skip each ssdp listener that fails to bind (#53670)

This commit is contained in:
J. Nick Koston 2021-07-29 11:07:52 -05:00 committed by GitHub
parent f8750daa09
commit 219348d573
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 76 additions and 2 deletions

View File

@ -256,9 +256,21 @@ class Scanner:
self.hass.bus.async_listen_once(
EVENT_HOMEASSISTANT_STARTED, self.flow_dispatcher.async_start
)
await asyncio.gather(
*(listener.async_start() for listener in self._ssdp_listeners)
results = await asyncio.gather(
*(listener.async_start() for listener in self._ssdp_listeners),
return_exceptions=True,
)
failed_listeners = []
for idx, result in enumerate(results):
if isinstance(result, Exception):
_LOGGER.warning(
"Failed to setup listener for %s: %s",
self._ssdp_listeners[idx].source_ip,
result,
)
failed_listeners.append(self._ssdp_listeners[idx])
for listener in failed_listeners:
self._ssdp_listeners.remove(listener)
self._cancel_scan = async_track_time_interval(
self.hass, self.async_scan, SCAN_INTERVAL
)

View File

@ -790,3 +790,65 @@ async def test_async_detect_interfaces_setting_empty_route(hass):
(IPv4Address("192.168.1.5"), IPv4Address("255.255.255.255")),
(IPv4Address("192.168.1.5"), None),
}
async def test_bind_failure_skips_adapter(hass, caplog):
"""Test that an adapter with a bind failure is skipped."""
mock_get_ssdp = {
"mock-domain": [
{
ssdp.ATTR_UPNP_DEVICE_TYPE: "ABC",
}
]
}
create_args = []
did_search = 0
@callback
def _callback(*_):
nonlocal did_search
did_search += 1
pass
def _generate_failing_ssdp_listener(*args, **kwargs):
create_args.append([args, kwargs])
listener = SSDPListener(*args, **kwargs)
async def _async_callback(*_):
if kwargs["source_ip"] == IPv6Address("2001:db8::"):
raise OSError
pass
listener.async_start = _async_callback
listener.async_search = _callback
return listener
with patch(
"homeassistant.components.ssdp.async_get_ssdp",
return_value=mock_get_ssdp,
), patch(
"homeassistant.components.ssdp.SSDPListener",
new=_generate_failing_ssdp_listener,
), patch(
"homeassistant.components.ssdp.network.async_get_adapters",
return_value=_ADAPTERS_WITH_MANUAL_CONFIG,
):
assert await async_setup_component(hass, ssdp.DOMAIN, {ssdp.DOMAIN: {}})
await hass.async_block_till_done()
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
await hass.async_block_till_done()
argset = set()
for argmap in create_args:
argset.add((argmap[1].get("source_ip"), argmap[1].get("target_ip")))
assert argset == {
(IPv6Address("2001:db8::"), None),
(IPv4Address("192.168.1.5"), IPv4Address("255.255.255.255")),
(IPv4Address("192.168.1.5"), None),
}
assert "Failed to setup listener for" in caplog.text
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=200))
await hass.async_block_till_done()
assert did_search == 2