@@ -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(
392393def 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