|
23 | 23 | import ipaddress |
24 | 24 | import random |
25 | 25 | import socket |
| 26 | +from functools import lru_cache |
26 | 27 | from typing import TYPE_CHECKING, Any, Dict, List, Optional, Set, Union, cast |
27 | 28 |
|
28 | 29 | from .._dns import ( |
@@ -79,6 +80,9 @@ def instance_name_from_service_info(info: "ServiceInfo") -> str: |
79 | 80 | return info.name[: -len(service_name) - 1] |
80 | 81 |
|
81 | 82 |
|
| 83 | +_cached_ip_addresses = lru_cache(maxsize=256)(ipaddress.ip_address) |
| 84 | + |
| 85 | + |
82 | 86 | class ServiceInfo(RecordUpdateListener): |
83 | 87 | """Service information. |
84 | 88 |
|
@@ -196,7 +200,7 @@ def addresses(self, value: List[bytes]) -> None: |
196 | 200 |
|
197 | 201 | for address in value: |
198 | 202 | try: |
199 | | - addr = ipaddress.ip_address(address) |
| 203 | + addr = _cached_ip_addresses(address) |
200 | 204 | except ValueError: |
201 | 205 | raise TypeError( |
202 | 206 | "Addresses must either be IPv4 or IPv6 strings, bytes, or integers;" |
@@ -245,7 +249,7 @@ def parsed_scoped_addresses(self, version: IPVersion = IPVersion.All) -> List[st |
245 | 249 | return self.parsed_addresses(version) |
246 | 250 |
|
247 | 251 | def is_link_local(addr_str: str) -> Any: |
248 | | - addr = ipaddress.ip_address(addr_str) |
| 252 | + addr = _cached_ip_addresses(addr_str) |
249 | 253 | return addr.version == 6 and addr.is_link_local |
250 | 254 |
|
251 | 255 | ll_addrs = list(filter(is_link_local, self.parsed_addresses(version))) |
@@ -346,7 +350,7 @@ def _process_record_threadsafe(self, record: DNSRecord, now: float) -> None: |
346 | 350 | if record.key != self.server_key: |
347 | 351 | return |
348 | 352 | try: |
349 | | - ip_addr = ipaddress.ip_address(record.address) |
| 353 | + ip_addr = _cached_ip_addresses(record.address) |
350 | 354 | except ValueError as ex: |
351 | 355 | log.warning("Encountered invalid address while processing %s: %s", record, ex) |
352 | 356 | return |
|
0 commit comments