Skip to content

Commit 69b33be

Browse files
authored
feat: improve performance responding to queries (#1217)
1 parent 844c554 commit 69b33be

2 files changed

Lines changed: 43 additions & 31 deletions

File tree

src/zeroconf/_services/info.py

Lines changed: 42 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
from ..const import (
4747
_ADDRESS_RECORD_TYPES,
4848
_CLASS_IN,
49-
_CLASS_UNIQUE,
49+
_CLASS_IN_UNIQUE,
5050
_DNS_HOST_TTL,
5151
_DNS_OTHER_TTL,
5252
_FLAGS_QR_QUERY,
@@ -388,7 +388,7 @@ def _unpack_text_into_properties(self) -> None:
388388

389389
def get_name(self) -> str:
390390
"""Name accessor"""
391-
return self.name[: len(self.name) - len(self.type) - 1]
391+
return self._name[: len(self._name) - len(self.type) - 1]
392392

393393
def _get_ip_addresses_from_cache_lifo(
394394
self, zc: 'Zeroconf', now: float, type: int
@@ -409,15 +409,21 @@ def _get_ip_addresses_from_cache_lifo(
409409

410410
def _set_ipv6_addresses_from_cache(self, zc: 'Zeroconf', now: float) -> None:
411411
"""Set IPv6 addresses from the cache."""
412-
self._ipv6_addresses = cast(
413-
"List[IPv6Address]", self._get_ip_addresses_from_cache_lifo(zc, now, _TYPE_AAAA)
414-
)
412+
if TYPE_CHECKING:
413+
self._ipv6_addresses = cast(
414+
"List[IPv6Address]", self._get_ip_addresses_from_cache_lifo(zc, now, _TYPE_AAAA)
415+
)
416+
else:
417+
self._ipv6_addresses = self._get_ip_addresses_from_cache_lifo(zc, now, _TYPE_AAAA)
415418

416419
def _set_ipv4_addresses_from_cache(self, zc: 'Zeroconf', now: float) -> None:
417420
"""Set IPv4 addresses from the cache."""
418-
self._ipv4_addresses = cast(
419-
"List[IPv4Address]", self._get_ip_addresses_from_cache_lifo(zc, now, _TYPE_A)
420-
)
421+
if TYPE_CHECKING:
422+
self._ipv4_addresses = cast(
423+
"List[IPv4Address]", self._get_ip_addresses_from_cache_lifo(zc, now, _TYPE_A)
424+
)
425+
else:
426+
self._ipv4_addresses = self._get_ip_addresses_from_cache_lifo(zc, now, _TYPE_A)
421427

422428
def update_record(self, zc: 'Zeroconf', now: float, record: Optional[DNSRecord]) -> None:
423429
"""Updates service information from a DNS record.
@@ -523,9 +529,9 @@ def dns_addresses(
523529
created: Optional[float] = None,
524530
) -> List[DNSAddress]:
525531
"""Return matching DNSAddress from ServiceInfo."""
526-
name = self.server or self.name
532+
name = self.server or self._name
527533
ttl = override_ttl if override_ttl is not None else self.host_ttl
528-
class_ = _CLASS_IN | _CLASS_UNIQUE
534+
class_ = _CLASS_IN_UNIQUE
529535
version_value = version.value
530536
return [
531537
DNSAddress(
@@ -546,30 +552,33 @@ def dns_pointer(self, override_ttl: Optional[int] = None, created: Optional[floa
546552
_TYPE_PTR,
547553
_CLASS_IN,
548554
override_ttl if override_ttl is not None else self.other_ttl,
549-
self.name,
555+
self._name,
550556
created,
551557
)
552558

553559
def dns_service(self, override_ttl: Optional[int] = None, created: Optional[float] = None) -> DNSService:
554560
"""Return DNSService from ServiceInfo."""
561+
port = self.port
562+
if TYPE_CHECKING:
563+
assert isinstance(port, int)
555564
return DNSService(
556-
self.name,
565+
self._name,
557566
_TYPE_SRV,
558-
_CLASS_IN | _CLASS_UNIQUE,
567+
_CLASS_IN_UNIQUE,
559568
override_ttl if override_ttl is not None else self.host_ttl,
560569
self.priority,
561570
self.weight,
562-
cast(int, self.port),
563-
self.server or self.name,
571+
port,
572+
self.server or self._name,
564573
created,
565574
)
566575

567576
def dns_text(self, override_ttl: Optional[int] = None, created: Optional[float] = None) -> DNSText:
568577
"""Return DNSText from ServiceInfo."""
569578
return DNSText(
570-
self.name,
579+
self._name,
571580
_TYPE_TXT,
572-
_CLASS_IN | _CLASS_UNIQUE,
581+
_CLASS_IN_UNIQUE,
573582
override_ttl if override_ttl is not None else self.other_ttl,
574583
self.text,
575584
created,
@@ -580,11 +589,11 @@ def dns_nsec(
580589
) -> DNSNsec:
581590
"""Return DNSNsec from ServiceInfo."""
582591
return DNSNsec(
583-
self.name,
592+
self._name,
584593
_TYPE_NSEC,
585-
_CLASS_IN | _CLASS_UNIQUE,
594+
_CLASS_IN_UNIQUE,
586595
override_ttl if override_ttl is not None else self.host_ttl,
587-
self.name,
596+
self._name,
588597
missing_types,
589598
created,
590599
)
@@ -593,12 +602,11 @@ def get_address_and_nsec_records(
593602
self, override_ttl: Optional[int] = None, created: Optional[float] = None
594603
) -> Set[DNSRecord]:
595604
"""Build a set of address records and NSEC records for non-present record types."""
596-
seen_types: Set[int] = set()
605+
missing_types: Set[int] = _ADDRESS_RECORD_TYPES.copy()
597606
records: Set[DNSRecord] = set()
598607
for dns_address in self.dns_addresses(override_ttl, IPVersion.All, created):
599-
seen_types.add(dns_address.type)
608+
missing_types.discard(dns_address.type)
600609
records.add(dns_address)
601-
missing_types: Set[int] = _ADDRESS_RECORD_TYPES - seen_types
602610
if missing_types:
603611
assert self.server is not None, "Service server must be set for NSEC record."
604612
records.add(self.dns_nsec(list(missing_types), override_ttl, created))
@@ -616,7 +624,7 @@ def set_server_if_missing(self) -> None:
616624
This function is for backwards compatibility.
617625
"""
618626
if self.server is None:
619-
self.server = self.name
627+
self.server = self._name
620628
self.server_key = self.server.lower()
621629

622630
def load_from_cache(self, zc: 'Zeroconf', now: Optional[float] = None) -> bool:
@@ -627,10 +635,10 @@ def load_from_cache(self, zc: 'Zeroconf', now: Optional[float] = None) -> bool:
627635
if not now:
628636
now = current_time_millis()
629637
original_server_key = self.server_key
630-
cached_srv_record = zc.cache.get_by_details(self.name, _TYPE_SRV, _CLASS_IN)
638+
cached_srv_record = zc.cache.get_by_details(self._name, _TYPE_SRV, _CLASS_IN)
631639
if cached_srv_record:
632640
self._process_record_threadsafe(zc, cached_srv_record, now)
633-
cached_txt_record = zc.cache.get_by_details(self.name, _TYPE_TXT, _CLASS_IN)
641+
cached_txt_record = zc.cache.get_by_details(self._name, _TYPE_TXT, _CLASS_IN)
634642
if cached_txt_record:
635643
self._process_record_threadsafe(zc, cached_txt_record, now)
636644
if original_server_key == self.server_key:
@@ -732,18 +740,21 @@ def generate_request_query(
732740
) -> DNSOutgoing:
733741
"""Generate the request query."""
734742
out = DNSOutgoing(_FLAGS_QR_QUERY)
735-
out.add_question_or_one_cache(zc.cache, now, self.name, _TYPE_SRV, _CLASS_IN)
736-
out.add_question_or_one_cache(zc.cache, now, self.name, _TYPE_TXT, _CLASS_IN)
737-
out.add_question_or_all_cache(zc.cache, now, self.server or self.name, _TYPE_A, _CLASS_IN)
738-
out.add_question_or_all_cache(zc.cache, now, self.server or self.name, _TYPE_AAAA, _CLASS_IN)
743+
name = self._name
744+
server_or_name = self.server or name
745+
cache = zc.cache
746+
out.add_question_or_one_cache(cache, now, name, _TYPE_SRV, _CLASS_IN)
747+
out.add_question_or_one_cache(cache, now, name, _TYPE_TXT, _CLASS_IN)
748+
out.add_question_or_all_cache(cache, now, server_or_name, _TYPE_A, _CLASS_IN)
749+
out.add_question_or_all_cache(cache, now, server_or_name, _TYPE_AAAA, _CLASS_IN)
739750
if question_type == DNSQuestionType.QU:
740751
for question in out.questions:
741752
question.unicast = True
742753
return out
743754

744755
def __eq__(self, other: object) -> bool:
745756
"""Tests equality of service name"""
746-
return isinstance(other, ServiceInfo) and other.name == self.name
757+
return isinstance(other, ServiceInfo) and other._name == self._name
747758

748759
def __repr__(self) -> str:
749760
"""String representation"""

src/zeroconf/const.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@
8484
_CLASS_ANY = 255
8585
_CLASS_MASK = 0x7FFF
8686
_CLASS_UNIQUE = 0x8000
87+
_CLASS_IN_UNIQUE = _CLASS_IN | _CLASS_UNIQUE
8788

8889
_TYPE_A = 1
8990
_TYPE_NS = 2

0 commit comments

Comments
 (0)