(
q: dns.message.Message,
where: str,
url: str,
timeout: float | None = None,
port: int = 443,
source: str | None = None,
source_port: int = 0,
one_rr_per_rrset: bool = False,
ignore_trailing: bool = False,
verify: bool | str | ssl.SSLContext = True,
post: bool = True,
connection: dns.quic.SyncQuicConnection | None = None,
)
| 674 | |
| 675 | |
| 676 | def _http3( |
| 677 | q: dns.message.Message, |
| 678 | where: str, |
| 679 | url: str, |
| 680 | timeout: float | None = None, |
| 681 | port: int = 443, |
| 682 | source: str | None = None, |
| 683 | source_port: int = 0, |
| 684 | one_rr_per_rrset: bool = False, |
| 685 | ignore_trailing: bool = False, |
| 686 | verify: bool | str | ssl.SSLContext = True, |
| 687 | post: bool = True, |
| 688 | connection: dns.quic.SyncQuicConnection | None = None, |
| 689 | ) -> dns.message.Message: |
| 690 | if not dns.quic.have_quic: |
| 691 | raise NoDOH("DNS-over-HTTP3 is not available.") # pragma: no cover |
| 692 | |
| 693 | url_parts = urllib.parse.urlparse(url) |
| 694 | hostname = url_parts.hostname |
| 695 | assert hostname is not None |
| 696 | if url_parts.port is not None: |
| 697 | port = url_parts.port |
| 698 | |
| 699 | q.id = 0 |
| 700 | wire = q.to_wire() |
| 701 | the_connection: dns.quic.SyncQuicConnection |
| 702 | the_manager: dns.quic.SyncQuicManager |
| 703 | if connection: |
| 704 | manager: contextlib.AbstractContextManager = contextlib.nullcontext(None) |
| 705 | else: |
| 706 | manager = dns.quic.SyncQuicManager( |
| 707 | verify_mode=verify, server_name=hostname, h3=True # pyright: ignore |
| 708 | ) |
| 709 | the_manager = manager # for type checking happiness |
| 710 | |
| 711 | with manager: |
| 712 | if connection: |
| 713 | the_connection = connection |
| 714 | else: |
| 715 | the_connection = the_manager.connect( # pyright: ignore |
| 716 | where, port, source, source_port |
| 717 | ) |
| 718 | (start, expiration) = _compute_times(timeout) |
| 719 | with the_connection.make_stream(timeout) as stream: # pyright: ignore |
| 720 | stream.send_h3(url, wire, post) |
| 721 | wire = stream.receive(_remaining(expiration)) |
| 722 | _check_status(stream.headers(), where, wire) |
| 723 | finish = time.time() |
| 724 | r = dns.message.from_wire( |
| 725 | wire, |
| 726 | keyring=q.keyring, |
| 727 | request_mac=q.request_mac, |
| 728 | one_rr_per_rrset=one_rr_per_rrset, |
| 729 | ignore_trailing=ignore_trailing, |
| 730 | ) |
| 731 | r.time = max(finish - start, 0.0) |
| 732 | if not q.is_response(r): |
| 733 | raise BadResponse |
no test coverage detected
searching dependent graphs…