@@ -212,17 +212,16 @@ class AsyncListener(asyncio.Protocol, QuietLogger):
212212 It requires registration with an Engine object in order to have
213213 the read() method called when a socket is available for reading."""
214214
215+ __slots__ = ('zc' , 'data' , 'last_time' , 'transport' , 'sock_description' , '_deferred' , '_timers' )
216+
215217 def __init__ (self , zc : 'Zeroconf' ) -> None :
216218 self .zc = zc
217219 self .data : Optional [bytes ] = None
218220 self .last_time : float = 0
219221 self .transport : Optional [asyncio .DatagramTransport ] = None
220- self .sock_name : Optional [str ] = None
221222 self .sock_description : Optional [str ] = None
222- self .sock_fileno : Optional [int ] = None
223223 self ._deferred : Dict [str , List [DNSIncoming ]] = {}
224224 self ._timers : Dict [str , asyncio .TimerHandle ] = {}
225-
226225 super ().__init__ ()
227226
228227 def suppress_duplicate_packet (self , data : bytes , now : float ) -> bool :
@@ -361,14 +360,52 @@ def error_received(self, exc: Exception) -> None:
361360
362361 def connection_made (self , transport : asyncio .BaseTransport ) -> None :
363362 self .transport = cast (asyncio .DatagramTransport , transport )
364- self . sock_name = self .transport .get_extra_info ('sockname' )
365- self . sock_fileno = self .transport .get_extra_info ('socket' ).fileno ()
366- self .sock_description = f"{ self . sock_fileno } ({ self . sock_name } )"
363+ sock_name = self .transport .get_extra_info ('sockname' )
364+ sock_fileno = self .transport .get_extra_info ('socket' ).fileno ()
365+ self .sock_description = f"{ sock_fileno } ({ sock_name } )"
367366
368367 def connection_lost (self , exc : Optional [Exception ]) -> None :
369368 """Handle connection lost."""
370369
371370
371+ def async_send_with_transport (
372+ log_debug : bool ,
373+ transport : asyncio .DatagramTransport ,
374+ packet : bytes ,
375+ packet_num : int ,
376+ out : DNSOutgoing ,
377+ addr : Optional [str ],
378+ port : int ,
379+ v6_flow_scope : Union [Tuple [()], Tuple [int , int ]] = (),
380+ ) -> None :
381+ s = transport .get_extra_info ('socket' )
382+ ipv6_socket = s .family == socket .AF_INET6
383+ if addr is None :
384+ real_addr = _MDNS_ADDR6 if ipv6_socket else _MDNS_ADDR
385+ else :
386+ real_addr = addr
387+ if not can_send_to (ipv6_socket , real_addr ):
388+ return
389+ if log_debug :
390+ log .debug (
391+ 'Sending to (%s, %d) via [socket %s (%s)] (%d bytes #%d) %r as %r...' ,
392+ real_addr ,
393+ port or _MDNS_PORT ,
394+ s .fileno (),
395+ transport .get_extra_info ('sockname' ),
396+ len (packet ),
397+ packet_num + 1 ,
398+ out ,
399+ packet ,
400+ )
401+ # Get flowinfo and scopeid for the IPV6 socket to create a complete IPv6
402+ # address tuple: https://docs.python.org/3.6/library/socket.html#socket-families
403+ if ipv6_socket and not v6_flow_scope :
404+ _ , _ , sock_flowinfo , sock_scopeid = s .getsockname ()
405+ v6_flow_scope = (sock_flowinfo , sock_scopeid )
406+ transport .sendto (packet , (real_addr , port or _MDNS_PORT , * v6_flow_scope ))
407+
408+
372409class Zeroconf (QuietLogger ):
373410
374411 """Implementation of Zeroconf Multicast DNS Service Discovery
@@ -824,48 +861,10 @@ def async_send(
824861 self .log_warning_once ("Dropping %r over-sized packet (%d bytes) %r" , out , len (packet ), packet )
825862 return
826863 for send_transport in transports :
827- self . _async_send_transport (
864+ async_send_with_transport (
828865 log_debug , send_transport , packet , packet_num , out , addr , port , v6_flow_scope
829866 )
830867
831- def _async_send_transport (
832- self ,
833- log_debug : bool ,
834- transport : asyncio .DatagramTransport ,
835- packet : bytes ,
836- packet_num : int ,
837- out : DNSOutgoing ,
838- addr : Optional [str ],
839- port : int ,
840- v6_flow_scope : Union [Tuple [()], Tuple [int , int ]] = (),
841- ) -> None :
842- s = transport .get_extra_info ('socket' )
843- ipv6_socket = s .family == socket .AF_INET6
844- if addr is None :
845- real_addr = _MDNS_ADDR6 if ipv6_socket else _MDNS_ADDR
846- else :
847- real_addr = addr
848- if not can_send_to (ipv6_socket , real_addr ):
849- return
850- if log_debug :
851- log .debug (
852- 'Sending to (%s, %d) via [socket %s (%s)] (%d bytes #%d) %r as %r...' ,
853- real_addr ,
854- port or _MDNS_PORT ,
855- s .fileno (),
856- transport .get_extra_info ('sockname' ),
857- len (packet ),
858- packet_num + 1 ,
859- out ,
860- packet ,
861- )
862- # Get flowinfo and scopeid for the IPV6 socket to create a complete IPv6
863- # address tuple: https://docs.python.org/3.6/library/socket.html#socket-families
864- if ipv6_socket and not v6_flow_scope :
865- _ , _ , sock_flowinfo , sock_scopeid = s .getsockname ()
866- v6_flow_scope = (sock_flowinfo , sock_scopeid )
867- transport .sendto (packet , (real_addr , port or _MDNS_PORT , * v6_flow_scope ))
868-
869868 def _close (self ) -> None :
870869 """Set global done and remove all service listeners."""
871870 if self .done :
0 commit comments