Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion zeroconf/_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ def async_response( # pylint: disable=unused-argument
threadsafe.
"""
known_answers = DNSRRSet(
itertools.chain(*(msg.answers for msg in msgs if not _message_is_probe(msg)))
itertools.chain.from_iterable(msg.answers for msg in msgs if not _message_is_probe(msg))
)
query_res = _QueryResponse(self.cache, msgs)

Expand Down
33 changes: 25 additions & 8 deletions zeroconf/_protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

import enum
import struct
from typing import Any, Dict, List, Optional, Sequence, Set, TYPE_CHECKING, Tuple, Union, cast
from typing import Any, Callable, Dict, List, Optional, Sequence, Set, TYPE_CHECKING, Tuple, Union, cast


from ._dns import DNSAddress, DNSHinfo, DNSNsec, DNSPointer, DNSQuestion, DNSRecord, DNSService, DNSText
Expand Down Expand Up @@ -96,23 +96,39 @@ def __init__(self, data: bytes, scope_id: Optional[int] = None, now: Optional[fl
self.name_cache: Dict[int, List[str]] = {}
self.seen_pointers: Set[int] = set()
self.questions: List[DNSQuestion] = []
self.answers: List[DNSRecord] = []
self._answers: List[DNSRecord] = []
self.id = 0
self.num_questions = 0
self.num_answers = 0
self.num_authorities = 0
self.num_additionals = 0
self.valid = False
self._read_others = False
self.now = now or current_time_millis()
self.scope_id = scope_id
self._parse_data(self._initial_parse)

try:
self.read_header()
self.read_questions()
def _initial_parse(self) -> None:
"""Parse the data needed to initalize the packet object."""
self.read_header()
self.read_questions()
if not self.num_questions:
self.read_others()
self.valid = True
self.valid = True

def _parse_data(self, parser_call: Callable) -> None:
"""Parse part of the packet and catch exceptions."""
try:
parser_call()
except DECODE_EXCEPTIONS:
self.log_exception_warning('Choked at offset %d while unpacking %r', self.offset, data)
self.log_exception_warning('Choked at offset %d while unpacking %r', self.offset, self.data)

@property
def answers(self) -> List[DNSRecord]:
"""Answers in the packet."""
if not self._read_others:
self._parse_data(self.read_others)
return self._answers

def __repr__(self) -> str:
return '<DNSIncoming:{%s}>' % ', '.join(
Expand Down Expand Up @@ -170,6 +186,7 @@ def read_unsigned_short(self) -> int:
def read_others(self) -> None:
"""Reads the answers, authorities and additionals section of the
packet"""
self._read_others = True
n = self.num_answers + self.num_authorities + self.num_additionals
for _ in range(n):
domain = self.read_name()
Expand All @@ -192,7 +209,7 @@ def read_others(self) -> None:
exc_info=True,
)
if rec is not None:
self.answers.append(rec)
self._answers.append(rec)

def read_record(self, domain: str, type_: int, class_: int, ttl: int, length: int) -> Optional[DNSRecord]:
"""Read known records types and skip unknown ones."""
Expand Down