fix: always answer QU questions when the exact same packet is receive… · python-zeroconf/python-zeroconf@74d7ba1
@@ -37,19 +37,17 @@
3737)
38383939from ._cache import DNSCache, _UniqueRecordsType
40-from ._dns import DNSAddress, DNSNsec, DNSPointer, DNSQuestion, DNSRecord, DNSRRSet
40+from ._dns import DNSAddress, DNSPointer, DNSQuestion, DNSRecord, DNSRRSet
4141from ._history import QuestionHistory
4242from ._logger import log
4343from ._protocol.incoming import DNSIncoming
4444from ._protocol.outgoing import DNSOutgoing
45-from ._services.info import ServiceInfo
4645from ._services.registry import ServiceRegistry
4746from ._updates import RecordUpdate, RecordUpdateListener
4847from ._utils.time import current_time_millis, millis_to_seconds
4948from .const import (
5049_ADDRESS_RECORD_TYPES,
5150_CLASS_IN,
52-_CLASS_UNIQUE,
5351_DNS_OTHER_TTL,
5452_DNS_PTR_MIN_TTL,
5553_FLAGS_AA,
@@ -90,15 +88,6 @@ class AnswerGroup(NamedTuple):
9088answers: _AnswerWithAdditionalsType
9189929093-def construct_nsec_record(name: str, types: List[int], now: float) -> DNSNsec:
94-"""Construct an NSEC record for name and a list of dns types.
95-96- This function should only be used for SRV/A/AAAA records
97- which have a TTL of _DNS_OTHER_TTL
98- """
99-return DNSNsec(name, _TYPE_NSEC, _CLASS_IN | _CLASS_UNIQUE, _DNS_OTHER_TTL, name, types, created=now)
100-101-10291def construct_outgoing_multicast_answers(answers: _AnswerWithAdditionalsType) -> DNSOutgoing:
10392"""Add answers and additionals to a DNSOutgoing."""
10493out = DNSOutgoing(_FLAGS_QR_RESPONSE | _FLAGS_AA, multicast=True)
@@ -217,20 +206,6 @@ def _has_mcast_record_in_last_second(self, record: DNSRecord) -> bool:
217206return bool(maybe_entry and self._now - maybe_entry.created < _ONE_SECOND)
218207219208220-def _get_address_and_nsec_records(service: ServiceInfo, now: float) -> Set[DNSRecord]:
221-"""Build a set of address records and NSEC records for non-present record types."""
222-seen_types: Set[int] = set()
223-records: Set[DNSRecord] = set()
224-for dns_address in service.dns_addresses(created=now):
225-seen_types.add(dns_address.type)
226-records.add(dns_address)
227-missing_types: Set[int] = _ADDRESS_RECORD_TYPES - seen_types
228-if missing_types:
229-assert service.server is not None, "Service server must be set for NSEC record."
230-records.add(construct_nsec_record(service.server, list(missing_types), now))
231-return records
232-233-234209class QueryHandler:
235210"""Query the ServiceRegistry."""
236211@@ -264,9 +239,10 @@ def _add_pointer_answers(
264239dns_pointer = service.dns_pointer(created=now)
265240if known_answers.suppresses(dns_pointer):
266241continue
267-additionals: Set[DNSRecord] = {service.dns_service(created=now), service.dns_text(created=now)}
268-additionals |= _get_address_and_nsec_records(service, now)
269-answer_set[dns_pointer] = additionals
242+answer_set[dns_pointer] = {
243+service.dns_service(created=now),
244+service.dns_text(created=now),
245+ } | service.get_address_and_nsec_records(created=now)
270246271247def _add_address_answers(
272248self,
@@ -291,12 +267,12 @@ def _add_address_answers(
291267if answers:
292268if missing_types:
293269assert service.server is not None, "Service server must be set for NSEC record."
294-additionals.add(construct_nsec_record(service.server, list(missing_types), now))
270+additionals.add(service.dns_nsec(list(missing_types), created=now))
295271for answer in answers:
296272answer_set[answer] = additionals
297273elif type_ in missing_types:
298274assert service.server is not None, "Service server must be set for NSEC record."
299-answer_set[construct_nsec_record(service.server, list(missing_types), now)] = set()
275+answer_set[service.dns_nsec(list(missing_types), created=now)] = set()
300276301277def _answer_question(
302278self,
@@ -327,7 +303,7 @@ def _answer_question(
327303# https://tools.ietf.org/html/rfc6763#section-12.2.
328304dns_service = service.dns_service(created=now)
329305if not known_answers.suppresses(dns_service):
330-answer_set[dns_service] = _get_address_and_nsec_records(service, now)
306+answer_set[dns_service] = service.get_address_and_nsec_records(created=now)
331307if type_ in (_TYPE_TXT, _TYPE_ANY):
332308dns_text = service.dns_text(created=now)
333309if not known_answers.suppresses(dns_text):
@@ -496,7 +472,7 @@ def async_add_listener(
496472 its update_record method called when information is available to
497473 answer the question(s).
498474499- This function is not threadsafe and must be called in the eventloop.
475+ This function is not thread-safe and must be called in the eventloop.
500476 """
501477if not isinstance(listener, RecordUpdateListener):
502478log.error( # type: ignore[unreachable]