Skip to content

Commit 754b787

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 389a8a2 commit 754b787

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
@@ -252,6 +252,7 @@ def new_socket(
252252
# https://opensource.apple.com/source/xnu/xnu-4570.41.2/bsd/sys/socket.h
253253
s.setsockopt(socket.SOL_SOCKET, 0x1104, 1)
254254

255+
# Bind expects (address, port) for AF_INET and (address, port, flowinfo, scope_id) for AF_INET6
255256
bind_tup = (bind_addr[0], port, *bind_addr[1:])
256257
try:
257258
s.bind(bind_tup)
@@ -370,15 +371,27 @@ def add_multicast_member(
370371
def new_respond_socket(
371372
interface: str | tuple[tuple[str, int, int], int],
372373
apple_p2p: bool = False,
374+
unicast: bool = False,
373375
) -> socket.socket | None:
376+
"""Create interface specific socket for responding to multicast queries."""
374377
is_v6 = isinstance(interface, tuple)
378+
379+
# For response sockets:
380+
# - Bind explicitly to the interface address
381+
# - Use ephemeral ports if in unicast mode
382+
# - Create socket according to the interface IP type (IPv4 or IPv6)
375383
respond_socket = new_socket(
384+
bind_addr=cast(tuple[tuple[str, int, int], int], interface)[0] if is_v6 else (cast(str, interface),),
385+
port=0 if unicast else _MDNS_PORT,
376386
ip_version=(IPVersion.V6Only if is_v6 else IPVersion.V4Only),
377387
apple_p2p=apple_p2p,
378-
bind_addr=cast(tuple[tuple[str, int, int], int], interface)[0] if is_v6 else (cast(str, interface),),
379388
)
389+
if unicast:
390+
return respond_socket
391+
380392
if not respond_socket:
381393
return None
394+
382395
log.debug("Configuring socket %s with multicast interface %s", respond_socket, interface)
383396
if is_v6:
384397
iface_bin = struct.pack("@I", cast(int, interface[1]))
@@ -401,33 +414,25 @@ def create_sockets(
401414
if unicast:
402415
listen_socket = None
403416
else:
404-
listen_socket = new_socket(ip_version=ip_version, apple_p2p=apple_p2p, bind_addr=("",))
417+
listen_socket = new_socket(bind_addr=("",), ip_version=ip_version, apple_p2p=apple_p2p)
405418

406419
normalized_interfaces = normalize_interface_choice(interfaces, ip_version)
407420

408421
# If we are using InterfaceChoice.Default we can use
409422
# a single socket to listen and respond.
410423
if not unicast and interfaces is InterfaceChoice.Default:
411-
for i in normalized_interfaces:
412-
add_multicast_member(cast(socket.socket, listen_socket), i)
424+
for interface in normalized_interfaces:
425+
add_multicast_member(cast(socket.socket, listen_socket), interface)
413426
return listen_socket, [cast(socket.socket, listen_socket)]
414427

415428
respond_sockets = []
416429

417-
for i in normalized_interfaces:
418-
if not unicast:
419-
if add_multicast_member(cast(socket.socket, listen_socket), i):
420-
respond_socket = new_respond_socket(i, apple_p2p=apple_p2p)
421-
else:
422-
respond_socket = None
423-
else:
424-
is_v6 = isinstance(i, tuple)
425-
respond_socket = new_socket(
426-
port=0,
427-
ip_version=IPVersion.V6Only if is_v6 else IPVersion.V4Only,
428-
apple_p2p=apple_p2p,
429-
bind_addr=cast(tuple[tuple[str, int, int], int], i)[0] if is_v6 else (cast(str, i),),
430-
)
430+
for interface in normalized_interfaces:
431+
# Only create response socket if unicast or becoming multicast member was successful
432+
if not unicast and not add_multicast_member(cast(socket.socket, listen_socket), interface):
433+
continue
434+
435+
respond_socket = new_respond_socket(interface, apple_p2p=apple_p2p, unicast=unicast)
431436

432437
if respond_socket is not None:
433438
respond_sockets.append(respond_socket)

0 commit comments

Comments
 (0)