@@ -161,6 +161,34 @@ def normalize_interface_choice(
161161 return result
162162
163163
164+ def disable_ipv6_only_or_raise (s : socket .socket ) -> None :
165+ """Make V6 sockets work for both V4 and V6 (required for Windows)."""
166+ try :
167+ s .setsockopt (_IPPROTO_IPV6 , socket .IPV6_V6ONLY , False )
168+ except OSError :
169+ log .error ('Support for dual V4-V6 sockets is not present, use IPVersion.V4 or IPVersion.V6' )
170+ raise
171+
172+
173+ def set_so_reuseport_if_available (s : socket .socket ) -> None :
174+ """Set SO_REUSEADDR on a socket if available."""
175+ # SO_REUSEADDR should be equivalent to SO_REUSEPORT for
176+ # multicast UDP sockets (p 731, "TCP/IP Illustrated,
177+ # Volume 2"), but some BSD-derived systems require
178+ # SO_REUSEPORT to be specified explicitly. Also, not all
179+ # versions of Python have SO_REUSEPORT available.
180+ # Catch OSError and socket.error for kernel versions <3.9 because lacking
181+ # SO_REUSEPORT support.
182+ if not hasattr (socket , 'SO_REUSEPORT' ):
183+ return
184+
185+ try :
186+ s .setsockopt (socket .SOL_SOCKET , socket .SO_REUSEPORT , 1 ) # pylint: disable=no-member
187+ except OSError as err :
188+ if err .errno != errno .ENOPROTOOPT :
189+ raise
190+
191+
164192def new_socket ( # pylint: disable=too-many-branches
165193 bind_addr : Union [Tuple [str ], Tuple [str , int , int ]],
166194 port : int = _MDNS_PORT ,
@@ -180,28 +208,11 @@ def new_socket( # pylint: disable=too-many-branches
180208 s = socket .socket (socket .AF_INET6 , socket .SOCK_DGRAM )
181209
182210 if ip_version == IPVersion .All :
183- # make V6 sockets work for both V4 and V6 (required for Windows)
184- try :
185- s .setsockopt (_IPPROTO_IPV6 , socket .IPV6_V6ONLY , False )
186- except OSError :
187- log .error ('Support for dual V4-V6 sockets is not present, use IPVersion.V4 or IPVersion.V6' )
188- raise
211+ disable_ipv6_only_or_raise (s )
189212
190213 s .setsockopt (socket .SOL_SOCKET , socket .SO_REUSEADDR , 1 )
191214
192- # SO_REUSEADDR should be equivalent to SO_REUSEPORT for
193- # multicast UDP sockets (p 731, "TCP/IP Illustrated,
194- # Volume 2"), but some BSD-derived systems require
195- # SO_REUSEPORT to be specified explicitly. Also, not all
196- # versions of Python have SO_REUSEPORT available.
197- # Catch OSError and socket.error for kernel versions <3.9 because lacking
198- # SO_REUSEPORT support.
199- if hasattr (socket , 'SO_REUSEPORT' ):
200- try :
201- s .setsockopt (socket .SOL_SOCKET , socket .SO_REUSEPORT , 1 ) # pylint: disable=no-member
202- except OSError as err :
203- if err .errno != errno .ENOPROTOOPT :
204- raise
215+ set_so_reuseport_if_available (s )
205216
206217 if port == _MDNS_PORT :
207218 ttl = struct .pack (b'B' , 255 )
0 commit comments