Skip to content

Commit 2704340

Browse files
committed
chore: use new_respond_socket for all responder sockets
This unifies the socket creation for all interface specific responder sockets to use the new_respond_socket function. If the responder socket isn't used for multicast, it won't get bound to the interface explicitly. This mostly deduplicates code and makes it easier to maintain.
1 parent 77a6717 commit 2704340

1 file changed

Lines changed: 23 additions & 18 deletions

File tree

src/zeroconf/_utils/net.py

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ def new_socket(
274274
# https://opensource.apple.com/source/xnu/xnu-4570.41.2/bsd/sys/socket.h
275275
s.setsockopt(socket.SOL_SOCKET, 0x1104, 1)
276276

277+
# Bind expects (address, port) for AF_INET and (address, port, flowinfo, scope_id) for AF_INET6
277278
bind_tup = (bind_addr[0], port, *bind_addr[1:])
278279
try:
279280
s.bind(bind_tup)
@@ -392,15 +393,27 @@ def add_multicast_member(
392393
def new_respond_socket(
393394
interface: str | tuple[tuple[str, int, int], int],
394395
apple_p2p: bool = False,
396+
unicast: bool = False,
395397
) -> socket.socket | None:
398+
"""Create interface specific socket for responding to multicast queries."""
396399
is_v6 = isinstance(interface, tuple)
400+
401+
# For response sockets:
402+
# - Bind explicitly to the interface address
403+
# - Use ephemeral ports if in unicast mode
404+
# - Create socket according to the interface IP type (IPv4 or IPv6)
397405
respond_socket = new_socket(
406+
bind_addr=cast(tuple[tuple[str, int, int], int], interface)[0] if is_v6 else (cast(str, interface),),
407+
port=0 if unicast else _MDNS_PORT,
398408
ip_version=(IPVersion.V6Only if is_v6 else IPVersion.V4Only),
399409
apple_p2p=apple_p2p,
400-
bind_addr=cast(tuple[tuple[str, int, int], int], interface)[0] if is_v6 else (cast(str, interface),),
401410
)
411+
if unicast:
412+
return respond_socket
413+
402414
if not respond_socket:
403415
return None
416+
404417
log.debug("Configuring socket %s with multicast interface %s", respond_socket, interface)
405418
if is_v6:
406419
iface_bin = struct.pack("@I", cast(int, interface[1]))
@@ -423,33 +436,25 @@ def create_sockets(
423436
if unicast:
424437
listen_socket = None
425438
else:
426-
listen_socket = new_socket(ip_version=ip_version, apple_p2p=apple_p2p, bind_addr=("",))
439+
listen_socket = new_socket(bind_addr=("",), ip_version=ip_version, apple_p2p=apple_p2p)
427440

428441
normalized_interfaces = normalize_interface_choice(interfaces, ip_version)
429442

430443
# If we are using InterfaceChoice.Default we can use
431444
# a single socket to listen and respond.
432445
if not unicast and interfaces is InterfaceChoice.Default:
433-
for i in normalized_interfaces:
434-
add_multicast_member(cast(socket.socket, listen_socket), i)
446+
for interface in normalized_interfaces:
447+
add_multicast_member(cast(socket.socket, listen_socket), interface)
435448
return listen_socket, [cast(socket.socket, listen_socket)]
436449

437450
respond_sockets = []
438451

439-
for i in normalized_interfaces:
440-
if not unicast:
441-
if add_multicast_member(cast(socket.socket, listen_socket), i):
442-
respond_socket = new_respond_socket(i, apple_p2p=apple_p2p)
443-
else:
444-
respond_socket = None
445-
else:
446-
is_v6 = isinstance(i, tuple)
447-
respond_socket = new_socket(
448-
port=0,
449-
ip_version=IPVersion.V6Only if is_v6 else IPVersion.V4Only,
450-
apple_p2p=apple_p2p,
451-
bind_addr=cast(tuple[tuple[str, int, int], int], i)[0] if is_v6 else (cast(str, i),),
452-
)
452+
for interface in normalized_interfaces:
453+
# Only create response socket if unicast or becoming multicast member was successful
454+
if not unicast and not add_multicast_member(cast(socket.socket, listen_socket), interface):
455+
continue
456+
457+
respond_socket = new_respond_socket(interface, apple_p2p=apple_p2p, unicast=unicast)
453458

454459
if respond_socket is not None:
455460
respond_sockets.append(respond_socket)

0 commit comments

Comments
 (0)