| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -602,6 +602,11 @@ def generate_unregister_all_services(self) -> DNSOutgoing | None: | |||
| 602 | 602 | return out | |
| 603 | 603 | ||
| 604 | 604 | async def async_unregister_all_services(self) -> None: | |
| 605 | + """Send goodbye packets for every registered service and drop them all. | ||
| 606 | + | ||
| 607 | + Runs only at shutdown, so unlike the single service calls it | ||
| 608 | + returns nothing to await separately. | ||
| 609 | + """ | ||
| 605 | 610 | # Send Goodbye packets https://datatracker.ietf.org/doc/html/rfc6762#section-10.1 | |
| 606 | 611 | out = self.generate_unregister_all_services() | |
| 607 | 612 | if not out: | |
@@ -612,6 +617,11 @@ async def async_unregister_all_services(self) -> None: | |||
| 612 | 617 | self.async_send(out) | |
| 613 | 618 | ||
| 614 | 619 | def unregister_all_services(self) -> None: | |
| 620 | + """Send goodbye packets for every registered service and drop them all. | ||
| 621 | + | ||
| 622 | + May raise EventLoopBlocked when the event loop cannot finish the | ||
| 623 | + shutdown broadcasts in time. | ||
| 624 | + """ | ||
| 615 | 625 | assert self.loop is not None | |
| 616 | 626 | run_coro_with_timeout( | |
| 617 | 627 | self.async_unregister_all_services(), | |
@@ -700,6 +710,7 @@ def send( | |||
| 700 | 710 | v6_flow_scope: tuple[()] | tuple[int, int] = (), | |
| 701 | 711 | transport: _WrappedTransport | None = None, | |
| 702 | 712 | ) -> None: | |
| 713 | + """Queue a packet for transmission from any thread.""" | ||
| 703 | 714 | assert self.loop is not None | |
| 704 | 715 | self.loop.call_soon_threadsafe(self.async_send, out, addr, port, v6_flow_scope, transport) | |
| 705 | 716 | ||
@@ -711,6 +722,7 @@ def async_send( | |||
| 711 | 722 | v6_flow_scope: tuple[()] | tuple[int, int] = (), | |
| 712 | 723 | transport: _WrappedTransport | None = None, | |
| 713 | 724 | ) -> None: | |
| 725 | + """Transmit a packet from the event loop.""" | ||
| 714 | 726 | if self.done: | |
| 715 | 727 | return | |
| 716 | 728 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -83,6 +83,7 @@ def _dns_entry_matches(self, other: DNSEntry) -> bool: | |||
| 83 | 83 | return self.key == other.key and self.type == other.type and self.class_ == other.class_ | |
| 84 | 84 | ||
| 85 | 85 | def __eq__(self, other: Any) -> bool: | |
| 86 | + """Equal when key, type and class match.""" | ||
| 86 | 87 | return isinstance(other, DNSEntry) and self._dns_entry_matches(other) | |
| 87 | 88 | ||
| 88 | 89 | @staticmethod | |
@@ -124,6 +125,7 @@ def __hash__(self) -> int: | |||
| 124 | 125 | return self._hash | |
| 125 | 126 | ||
| 126 | 127 | def __eq__(self, other: Any) -> bool: | |
| 128 | + """Equal when the entry fields match a question.""" | ||
| 127 | 129 | return isinstance(other, DNSQuestion) and self._dns_entry_matches(other) | |
| 128 | 130 | ||
| 129 | 131 | @property | |
@@ -268,6 +270,7 @@ def write(self, out: DNSOutgoing) -> None: | |||
| 268 | 270 | out.write_string(self.address) | |
| 269 | 271 | ||
| 270 | 272 | def __eq__(self, other: Any) -> bool: | |
| 273 | + """Equal when address and the entry fields match.""" | ||
| 271 | 274 | return isinstance(other, DNSAddress) and self._eq(other) | |
| 272 | 275 | ||
| 273 | 276 | def _eq(self, other: DNSAddress) -> bool: | |
@@ -377,6 +380,7 @@ def write(self, out: DNSOutgoing) -> None: | |||
| 377 | 380 | out.write_name(self.alias) | |
| 378 | 381 | ||
| 379 | 382 | def __eq__(self, other: Any) -> bool: | |
| 383 | + """Equal when alias and the entry fields match.""" | ||
| 380 | 384 | return isinstance(other, DNSPointer) and self._eq(other) | |
| 381 | 385 | ||
| 382 | 386 | def _eq(self, other: DNSPointer) -> bool: | |
@@ -421,6 +425,7 @@ def __hash__(self) -> int: | |||
| 421 | 425 | return self._hash | |
| 422 | 426 | ||
| 423 | 427 | def __eq__(self, other: Any) -> bool: | |
| 428 | + """Equal when text and the entry fields match.""" | ||
| 424 | 429 | return isinstance(other, DNSText) and self._eq(other) | |
| 425 | 430 | ||
| 426 | 431 | def _eq(self, other: DNSText) -> bool: | |
@@ -502,6 +507,8 @@ def __repr__(self) -> str: | |||
| 502 | 507 | ||
| 503 | 508 | ||
| 504 | 509 | class DNSNsec(DNSRecord): | |
| 510 | + """NSEC record asserting which record types exist for a name.""" | ||
| 511 | + | ||
| 505 | 512 | __slots__ = ("_hash", "next_name", "rdtypes") | |
| 506 | 513 | ||
| 507 | 514 | def __init__( | |
@@ -552,6 +559,7 @@ def write(self, out: DNSOutgoing) -> None: | |||
| 552 | 559 | out.write_string(out_bytes) | |
| 553 | 560 | ||
| 554 | 561 | def __eq__(self, other: Any) -> bool: | |
| 562 | + """Equal when next_name, rdtypes and the entry fields match.""" | ||
| 555 | 563 | return isinstance(other, DNSNsec) and self._eq(other) | |
| 556 | 564 | ||
| 557 | 565 | def _eq(self, other: DNSNsec) -> bool: | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -447,6 +447,7 @@ def _read_record( | |||
| 447 | 447 | return None | |
| 448 | 448 | ||
| 449 | 449 | def _read_bitmap(self, end: _int) -> list[int]: | |
| 450 | + """Decode the NSEC type bitmap.""" | ||
| 450 | 451 | rdtypes = [] | |
| 451 | 452 | if end > self._data_len: | |
| 452 | 453 | raise IncomingDecodeError( | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -162,6 +162,41 @@ def add_authorative_answer(self, record: DNSPointer) -> None: | |||
| 162 | 162 | self.authorities.append(record) | |
| 163 | 163 | ||
| 164 | 164 | def add_additional_answer(self, record: DNSRecord) -> None: | |
| 165 | + """Append a record to the additional section per DNS-SD guidance. | ||
| 166 | + | ||
| 167 | + From: RFC 6763, DNS-Based Service Discovery, February 2013 | ||
| 168 | + | ||
| 169 | + 12. DNS Additional Record Generation | ||
| 170 | + | ||
| 171 | + DNS has an efficiency feature whereby a DNS server may place | ||
| 172 | + additional records in the additional section of the DNS message. | ||
| 173 | + These additional records are records that the client did not | ||
| 174 | + explicitly request, but the server has reasonable grounds to expect | ||
| 175 | + that the client might request them shortly, so including them can | ||
| 176 | + save the client from having to issue additional queries. | ||
| 177 | + | ||
| 178 | + This section recommends which additional records SHOULD be generated | ||
| 179 | + to improve network efficiency, for both Unicast and Multicast DNS-SD | ||
| 180 | + responses. | ||
| 181 | + | ||
| 182 | + 12.1. PTR Records | ||
| 183 | + | ||
| 184 | + When including a DNS-SD Service Instance Enumeration or Selective | ||
| 185 | + Instance Enumeration (subtype) PTR record in a response packet, the | ||
| 186 | + server/responder SHOULD include the following additional records: | ||
| 187 | + | ||
| 188 | + o The SRV record(s) named in the PTR rdata. | ||
| 189 | + o The TXT record(s) named in the PTR rdata. | ||
| 190 | + o All address records (type "A" and "AAAA") named in the SRV rdata. | ||
| 191 | + | ||
| 192 | + 12.2. SRV Records | ||
| 193 | + | ||
| 194 | + When including an SRV record in a response packet, the | ||
| 195 | + server/responder SHOULD include the following additional records: | ||
| 196 | + | ||
| 197 | + o All address records (type "A" and "AAAA") named in the SRV rdata. | ||
| 198 | + | ||
| 199 | + """ | ||
| 165 | 200 | self.additionals.append(record) | |
| 166 | 201 | ||
| 167 | 202 | def _write_byte(self, value: int_) -> None: | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -41,6 +41,8 @@ def service_type_name(type_: str, *, strict: bool = True) -> str: # pylint: dis | |||
| 41 | 41 | """ | |
| 42 | 42 | Validate a fully qualified service name, instance or subtype. [rfc6763] | |
| 43 | 43 | ||
| 44 | + Returns the name in its validated, fully qualified form. | ||
| 45 | + | ||
| 44 | 46 | Domain names used by mDNS-SD take the following forms: | |
| 45 | 47 | ||
| 46 | 48 | <sn> . <_tcp|_udp> . local. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -28,6 +28,11 @@ | |||
| 28 | 28 | ||
| 29 | 29 | ||
| 30 | 30 | def current_time_millis() -> _float: | |
| 31 | + """Monotonic clock reading in milliseconds. | ||
| 32 | + | ||
| 33 | + Must stay aligned with asyncio.loop.time(); the backing clock is an | ||
| 34 | + implementation detail and may change. | ||
| 35 | + """ | ||
| 31 | 36 | return time.monotonic() * 1000 | |
| 32 | 37 | ||
| 33 | 38 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -171,6 +171,11 @@ async def async_register_service( | |||
| 171 | 171 | ) | |
| 172 | 172 | ||
| 173 | 173 | async def async_unregister_all_services(self) -> None: | |
| 174 | + """Send goodbye packets for every registered service and drop them all. | ||
| 175 | + | ||
| 176 | + Runs only at shutdown, so unlike the single service calls it | ||
| 177 | + returns nothing to await separately. | ||
| 178 | + """ | ||
| 174 | 179 | await self.zeroconf.async_unregister_all_services() | |
| 175 | 180 | ||
| 176 | 181 | async def async_unregister_service(self, info: ServiceInfo) -> Awaitable: | |
| Back | FazBrowse Home | New Git URL |
0 commit comments