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
82 changes: 53 additions & 29 deletions src/zeroconf/_dns.pxd
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@

import cython


cdef object _LEN_BYTE
Expand All @@ -12,67 +13,90 @@ cdef object _EXPIRE_FULL_TIME_MS
cdef object _EXPIRE_STALE_TIME_MS
cdef object _RECENT_TIME_MS

cdef object _CLASS_UNIQUE
cdef object _CLASS_MASK

cdef class DNSEntry:

cdef public key
cdef public name
cdef public type
cdef public class_
cdef public unique
cdef public object key
cdef public object name
cdef public object type
cdef public object class_
cdef public object unique

cdef _dns_entry_matches(self, DNSEntry other)

cdef class DNSQuestion(DNSEntry):

cdef public _hash
cdef public cython.int _hash

cdef class DNSRecord(DNSEntry):

cdef public ttl
cdef public created
cdef public object ttl
cdef public object created

cdef _suppressed_by_answer(self, DNSRecord answer)


cdef class DNSAddress(DNSRecord):

cdef public _hash
cdef public address
cdef public scope_id
cdef public cython.int _hash
cdef public object address
cdef public object scope_id

cdef _eq(self, DNSAddress other)


cdef class DNSHinfo(DNSRecord):

cdef public _hash
cdef public cpu
cdef public os
cdef public cython.int _hash
cdef public object cpu
cdef public object os

cdef _eq(self, DNSHinfo other)


cdef class DNSPointer(DNSRecord):

cdef public _hash
cdef public alias
cdef public cython.int _hash
cdef public object alias

cdef _eq(self, DNSPointer other)


cdef class DNSText(DNSRecord):

cdef public _hash
cdef public text
cdef public cython.int _hash
cdef public object text

cdef _eq(self, DNSText other)


cdef class DNSService(DNSRecord):

cdef public _hash
cdef public priority
cdef public weight
cdef public port
cdef public server
cdef public server_key
cdef public cython.int _hash
cdef public object priority
cdef public object weight
cdef public object port
cdef public object server
cdef public object server_key

cdef _eq(self, DNSService other)


cdef class DNSNsec(DNSRecord):

cdef public _hash
cdef public next_name
cdef public rdtypes
cdef public cython.int _hash
cdef public object next_name
cdef public cython.list rdtypes

cdef _eq(self, DNSNsec other)


cdef class DNSRRSet:

cdef _records
cdef _lookup
cdef cython.dict _lookup

cdef _dns_entry_matches(DNSEntry entry, object key, object type_, object class_)
@cython.locals(other=DNSRecord)
cpdef suppresses(self, DNSRecord record)
94 changes: 51 additions & 43 deletions src/zeroconf/_dns.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,12 @@ def __init__(self, name: str, type_: int, class_: int) -> None:
self.class_ = class_ & _CLASS_MASK
self.unique = (class_ & _CLASS_UNIQUE) != 0

def _dns_entry_matches(self, other) -> bool: # type: ignore[no-untyped-def]
return self.key == other.key and self.type == other.type and self.class_ == other.class_

def __eq__(self, other: Any) -> bool:
"""Equality test on key (lowercase name), type, and class"""
return _dns_entry_matches(other, self.key, self.type, self.class_) and isinstance(other, DNSEntry)
return isinstance(other, DNSEntry) and self._dns_entry_matches(other)

@staticmethod
def get_class_(class_: int) -> str:
Expand Down Expand Up @@ -117,7 +120,7 @@ def __hash__(self) -> int:

def __eq__(self, other: Any) -> bool:
"""Tests equality on dns question."""
return isinstance(other, DNSQuestion) and _dns_entry_matches(other, self.key, self.type, self.class_)
return isinstance(other, DNSQuestion) and self._dns_entry_matches(other)

@property
def max_size(self) -> int:
Expand Down Expand Up @@ -169,9 +172,9 @@ def __eq__(self, other: Any) -> bool: # pylint: disable=no-self-use
def suppressed_by(self, msg: 'DNSIncoming') -> bool:
"""Returns true if any answer in a message can suffice for the
information held in this record."""
return any(self.suppressed_by_answer(record) for record in msg.answers)
return any(self._suppressed_by_answer(record) for record in msg.answers)

def suppressed_by_answer(self, other: 'DNSRecord') -> bool:
def _suppressed_by_answer(self, other) -> bool: # type: ignore[no-untyped-def]
"""Returns true if another record has same name, type and class,
and if its TTL is at least half of this record's."""
return self == other and other.ttl > (self.ttl / 2)
Expand Down Expand Up @@ -246,11 +249,13 @@ def write(self, out: 'DNSOutgoing') -> None:

def __eq__(self, other: Any) -> bool:
"""Tests equality on address"""
return isinstance(other, DNSAddress) and self._eq(other)

def _eq(self, other) -> bool: # type: ignore[no-untyped-def]
return (
isinstance(other, DNSAddress)
and self.address == other.address
self.address == other.address
and self.scope_id == other.scope_id
and _dns_entry_matches(other, self.key, self.type, self.class_)
and self._dns_entry_matches(other)
)

def __hash__(self) -> int:
Expand Down Expand Up @@ -289,13 +294,12 @@ def write(self, out: 'DNSOutgoing') -> None:
out.write_character_string(self.os.encode('utf-8'))

def __eq__(self, other: Any) -> bool:
"""Tests equality on cpu and os"""
return (
isinstance(other, DNSHinfo)
and self.cpu == other.cpu
and self.os == other.os
and _dns_entry_matches(other, self.key, self.type, self.class_)
)
"""Tests equality on cpu and os."""
return isinstance(other, DNSHinfo) and self._eq(other)

def _eq(self, other) -> bool: # type: ignore[no-untyped-def]
"""Tests equality on cpu and os."""
return self.cpu == other.cpu and self.os == other.os and self._dns_entry_matches(other)

def __hash__(self) -> int:
"""Hash to compare like DNSHinfo."""
Expand Down Expand Up @@ -334,12 +338,12 @@ def write(self, out: 'DNSOutgoing') -> None:
out.write_name(self.alias)

def __eq__(self, other: Any) -> bool:
"""Tests equality on alias"""
return (
isinstance(other, DNSPointer)
and self.alias == other.alias
and _dns_entry_matches(other, self.key, self.type, self.class_)
)
"""Tests equality on alias."""
return isinstance(other, DNSPointer) and self._eq(other)

def _eq(self, other) -> bool: # type: ignore[no-untyped-def]
"""Tests equality on alias."""
return self.alias == other.alias and self._dns_entry_matches(other)

def __hash__(self) -> int:
"""Hash to compare like DNSPointer."""
Expand Down Expand Up @@ -373,12 +377,12 @@ def __hash__(self) -> int:
return self._hash

def __eq__(self, other: Any) -> bool:
"""Tests equality on text"""
return (
isinstance(other, DNSText)
and self.text == other.text
and _dns_entry_matches(other, self.key, self.type, self.class_)
)
"""Tests equality on text."""
return isinstance(other, DNSText) and self._eq(other)

def _eq(self, other) -> bool: # type: ignore[no-untyped-def]
"""Tests equality on text."""
return self.text == other.text and self._dns_entry_matches(other)

def __repr__(self) -> str:
"""String representation"""
Expand Down Expand Up @@ -422,13 +426,16 @@ def write(self, out: 'DNSOutgoing') -> None:

def __eq__(self, other: Any) -> bool:
"""Tests equality on priority, weight, port and server"""
return isinstance(other, DNSService) and self._eq(other)

def _eq(self, other) -> bool: # type: ignore[no-untyped-def]
"""Tests equality on priority, weight, port and server."""
return (
isinstance(other, DNSService)
and self.priority == other.priority
self.priority == other.priority
and self.weight == other.weight
and self.port == other.port
and self.server == other.server
and _dns_entry_matches(other, self.key, self.type, self.class_)
and self._dns_entry_matches(other)
)

def __hash__(self) -> int:
Expand Down Expand Up @@ -478,12 +485,15 @@ def write(self, out: 'DNSOutgoing') -> None:
out.write_string(out_bytes)

def __eq__(self, other: Any) -> bool:
"""Tests equality on cpu and os"""
"""Tests equality on next_name and rdtypes."""
return isinstance(other, DNSNsec) and self._eq(other)

def _eq(self, other) -> bool: # type: ignore[no-untyped-def]
"""Tests equality on next_name and rdtypes."""
return (
isinstance(other, DNSNsec)
and self.next_name == other.next_name
self.next_name == other.next_name
and self.rdtypes == other.rdtypes
and _dns_entry_matches(other, self.key, self.type, self.class_)
and self._dns_entry_matches(other)
)

def __hash__(self) -> int:
Expand All @@ -497,6 +507,9 @@ def __repr__(self) -> str:
)


_DNSRecord = DNSRecord


class DNSRRSet:
"""A set of dns records independent of the ttl."""

Expand All @@ -514,20 +527,15 @@ def lookup(self) -> Dict[DNSRecord, DNSRecord]:
self._lookup = {record: record for record in self._records}
return self._lookup

def suppresses(self, record: DNSRecord) -> bool:
def suppresses(self, record: _DNSRecord) -> bool:
"""Returns true if any answer in the rrset can suffice for the
information held in this record."""
other = self.lookup.get(record)
if self._lookup is None:
other = self.lookup.get(record)
else:
other = self._lookup.get(record)
return bool(other and other.ttl > (record.ttl / 2))

def __contains__(self, record: DNSRecord) -> bool:
"""Returns true if the rrset contains the record."""
return record in self.lookup


_DNSEntry = DNSEntry
_str = str


def _dns_entry_matches(entry: _DNSEntry, key: _str, type_: int, class_: int) -> bool:
return key == entry.key and type_ == entry.type and class_ == entry.class_