From d288a47cb1bf80dbb89e952f2e0e0fc2b3bfd82b Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Tue, 1 Apr 2025 19:22:22 +0200 Subject: [PATCH 1/2] fix: create listener socket with specific IP version Create listener sockets when using unicast with specific IP version as well, just like in `new_respond_socket()`. --- src/zeroconf/_utils/net.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/zeroconf/_utils/net.py b/src/zeroconf/_utils/net.py index c2312e01..b4f3ef77 100644 --- a/src/zeroconf/_utils/net.py +++ b/src/zeroconf/_utils/net.py @@ -421,11 +421,12 @@ def create_sockets( else: respond_socket = None else: + is_v6 = isinstance(i, tuple) respond_socket = new_socket( port=0, - ip_version=ip_version, + ip_version=IPVersion.V6Only if is_v6 else IPVersion.V4Only, apple_p2p=apple_p2p, - bind_addr=i[0] if isinstance(i, tuple) else (i,), + bind_addr=cast(tuple[tuple[str, int, int], int], i)[0] if is_v6 else (cast(str, i),), ) if respond_socket is not None: From f16a92295f7ba42bd5424120bbbf01132cd329b0 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Tue, 1 Apr 2025 20:52:54 +0200 Subject: [PATCH 2/2] chore(tests): add unit test for socket creation with unicast addressing --- tests/utils/test_net.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/tests/utils/test_net.py b/tests/utils/test_net.py index f763b655..ad8648de 100644 --- a/tests/utils/test_net.py +++ b/tests/utils/test_net.py @@ -298,3 +298,35 @@ 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 # type: ignore[arg-type] + + +def test_create_sockets(): + """Test create_sockets with unicast and IPv4.""" + + with ( + patch("zeroconf._utils.net.new_socket") as mock_new_socket, + patch( + "zeroconf._utils.net.ifaddr.get_adapters", + return_value=_generate_mock_adapters(), + ), + ): + mock_socket = Mock(spec=socket.socket) + mock_new_socket.return_value = mock_socket + + listen_socket, respond_sockets = r.create_sockets( + interfaces=r.InterfaceChoice.All, unicast=True, ip_version=r.IPVersion.All + ) + + assert listen_socket is None + mock_new_socket.assert_any_call( + port=0, + ip_version=r.IPVersion.V6Only, + apple_p2p=False, + bind_addr=("2001:db8::", 1, 1), + ) + mock_new_socket.assert_any_call( + port=0, + ip_version=r.IPVersion.V4Only, + apple_p2p=False, + bind_addr=("192.168.1.5",), + )