Skip to content

Commit aff625d

Browse files
authored
feat: speed up processing incoming records (#1216)
1 parent 8a9dc0b commit aff625d

3 files changed

Lines changed: 17 additions & 9 deletions

File tree

src/zeroconf/_dns.pxd

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ cdef class DNSRecord(DNSEntry):
4444
)
4545
cpdef suppressed_by(self, object msg)
4646

47+
cpdef get_remaining_ttl(self, cython.float now)
48+
4749
cpdef get_expiration_time(self, cython.uint percent)
4850

4951
cpdef is_expired(self, cython.float now)
@@ -54,6 +56,8 @@ cdef class DNSRecord(DNSEntry):
5456

5557
cpdef reset_ttl(self, DNSRecord other)
5658

59+
cpdef set_created_ttl(self, cython.float now, cython.float ttl)
60+
5761
cdef class DNSAddress(DNSRecord):
5862

5963
cdef public cython.int _hash

src/zeroconf/_dns.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626

2727
from ._exceptions import AbstractMethodException
2828
from ._utils.net import _is_v6_address
29-
from ._utils.time import current_time_millis, millis_to_seconds
29+
from ._utils.time import current_time_millis
3030
from .const import _CLASS_MASK, _CLASS_UNIQUE, _CLASSES, _TYPE_ANY, _TYPES
3131

3232
_LEN_BYTE = 1
@@ -193,7 +193,8 @@ def get_expiration_time(self, percent: _int) -> float:
193193
# TODO: Switch to just int here
194194
def get_remaining_ttl(self, now: _float) -> Union[int, float]:
195195
"""Returns the remaining TTL in seconds."""
196-
return max(0, millis_to_seconds((self.created + (_EXPIRE_FULL_TIME_MS * self.ttl)) - now))
196+
remain = (self.created + (_EXPIRE_FULL_TIME_MS * self.ttl) - now) / 1000.0
197+
return 0 if remain < 0 else remain
197198

198199
def is_expired(self, now: _float) -> bool:
199200
"""Returns true if this record has expired."""
@@ -212,7 +213,7 @@ def reset_ttl(self, other) -> None: # type: ignore[no-untyped-def]
212213
another record."""
213214
self.set_created_ttl(other.created, other.ttl)
214215

215-
def set_created_ttl(self, created: float, ttl: Union[float, int]) -> None:
216+
def set_created_ttl(self, created: _float, ttl: Union[float, int]) -> None:
216217
"""Set the created and ttl of a record."""
217218
self.created = created
218219
self.ttl = ttl

src/zeroconf/_handlers.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,7 @@ def async_updates_from_response(self, msg: DNSIncoming) -> None:
408408
removes: Set[DNSRecord] = set()
409409
now = msg.now
410410
unique_types: Set[Tuple[str, int, int]] = set()
411+
cache = self.cache
411412

412413
for record in msg.answers:
413414
# Protect zeroconf from records that can cause denial of service.
@@ -416,7 +417,9 @@ def async_updates_from_response(self, msg: DNSIncoming) -> None:
416417
# ServiceBrowsers generating excessive queries refresh queries.
417418
# Apple uses a 15s minimum TTL, however we do not have the same
418419
# level of rate limit and safe guards so we use 1/4 of the recommended value.
419-
if record.ttl and record.type == _TYPE_PTR and record.ttl < _DNS_PTR_MIN_TTL:
420+
record_type = record.type
421+
record_ttl = record.ttl
422+
if record_ttl and record_type == _TYPE_PTR and record_ttl < _DNS_PTR_MIN_TTL:
420423
log.debug(
421424
"Increasing effective ttl of %s to minimum of %s to protect against excessive refreshes.",
422425
record,
@@ -425,12 +428,12 @@ def async_updates_from_response(self, msg: DNSIncoming) -> None:
425428
record.set_created_ttl(record.created, _DNS_PTR_MIN_TTL)
426429

427430
if record.unique: # https://tools.ietf.org/html/rfc6762#section-10.2
428-
unique_types.add((record.name, record.type, record.class_))
431+
unique_types.add((record.name, record_type, record.class_))
429432

430433
if TYPE_CHECKING:
431434
record = cast(_UniqueRecordsType, record)
432435

433-
maybe_entry = self.cache.async_get_unique(record)
436+
maybe_entry = cache.async_get_unique(record)
434437
if not record.is_expired(now):
435438
if maybe_entry is not None:
436439
maybe_entry.reset_ttl(record)
@@ -447,7 +450,7 @@ def async_updates_from_response(self, msg: DNSIncoming) -> None:
447450
removes.add(record)
448451

449452
if unique_types:
450-
self.cache.async_mark_unique_records_older_than_1s_to_expire(unique_types, msg.answers, now)
453+
cache.async_mark_unique_records_older_than_1s_to_expire(unique_types, msg.answers, now)
451454

452455
if updates:
453456
self.async_updates(now, updates)
@@ -468,12 +471,12 @@ def async_updates_from_response(self, msg: DNSIncoming) -> None:
468471
# processsed.
469472
new = False
470473
if other_adds or address_adds:
471-
new = self.cache.async_add_records(itertools.chain(address_adds, other_adds))
474+
new = cache.async_add_records(itertools.chain(address_adds, other_adds))
472475
# Removes are processed last since
473476
# ServiceInfo could generate an un-needed query
474477
# because the data was not yet populated.
475478
if removes:
476-
self.cache.async_remove_records(removes)
479+
cache.async_remove_records(removes)
477480
if updates:
478481
self.async_updates_complete(new)
479482

0 commit comments

Comments
 (0)