Skip to content
Merged
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
25 changes: 24 additions & 1 deletion tests/utils/test_net.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@


"""Unit tests for zeroconf._utils.net."""
from unittest.mock import Mock, patch
from unittest.mock import MagicMock, Mock, patch

import errno
import ifaddr
Expand Down Expand Up @@ -198,3 +198,26 @@ def test_add_multicast_member():
# No error should return True
with patch("socket.socket.setsockopt"):
assert netutils.add_multicast_member(sock, interface) is True


def test_bind_raises_skips_address():
"""Test bind failing in new_socket returns None on EADDRNOTAVAIL."""
err = errno.EADDRNOTAVAIL

def _mock_socket(*args, **kwargs):
sock = MagicMock()
sock.bind = MagicMock(side_effect=OSError(err, "Error: {}".format(err)))
return sock

with patch("socket.socket", _mock_socket):
assert netutils.new_socket(("0.0.0.0", 0)) is None

err = errno.EAGAIN
with pytest.raises(OSError), patch("socket.socket", _mock_socket):
netutils.new_socket(("0.0.0.0", 0))


def test_new_respond_socket_new_socket_returns_none():
"""Test new_respond_socket returns None if new_socket returns None."""
with patch.object(netutils, "new_socket", return_value=None):
assert netutils.new_respond_socket(("0.0.0.0", 0)) is None
16 changes: 14 additions & 2 deletions zeroconf/_utils/net.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ def new_socket(
port: int = _MDNS_PORT,
ip_version: IPVersion = IPVersion.V4Only,
apple_p2p: bool = False,
) -> socket.socket:
) -> Optional[socket.socket]:
log.debug(
'Creating new socket with port %s, ip_version %s, apple_p2p %s and bind_addr %r',
port,
Expand All @@ -243,7 +243,17 @@ def new_socket(
# https://opensource.apple.com/source/xnu/xnu-4570.41.2/bsd/sys/socket.h
s.setsockopt(socket.SOL_SOCKET, 0x1104, 1)

s.bind((bind_addr[0], port, *bind_addr[1:]))
bind_tup = (bind_addr[0], port, *bind_addr[1:])
try:
s.bind(bind_tup)
except OSError as ex:
if ex.errno == errno.EADDRNOTAVAIL:
log.warning(
'Address not available when binding to %s, ' 'it is expected to happen on some systems',
bind_tup,
)
return None
raise
log.debug('Created socket %s', s)
return s

Expand Down Expand Up @@ -323,6 +333,8 @@ def new_respond_socket(
apple_p2p=apple_p2p,
bind_addr=cast(Tuple[Tuple[str, int, int], int], interface)[0] if is_v6 else (cast(str, interface),),
)
if not respond_socket:
return None
log.debug('Configuring socket %s with multicast interface %s', respond_socket, interface)
if is_v6:
iface_bin = struct.pack('@I', cast(int, interface[1]))
Expand Down