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