silk.net.dns.query.
Send one DNS question to the servers of a configuration, with retries and TCP fallback, without doing any input or output.
When to use#
Use an Exchange to drive a query from your own sockets and timers, for example in an event
loop. For a plain native program, silk.net.dns.client_native drives an Exchange with system
sockets.
Details#
Make an exchange with Exchange.make, then loop:
Call
Exchange.pollwith the time of aMonotonicClock.For
Step.Send, sendExchange.packetto the server of the step: as one UDP datagram, or on a new TCP connection, where the packet already has its two-byte length.For
Step.Wait, wait for a reply or until the time of the step, whichever is first. Give each UDP datagram from a server, and each whole TCP message, toExchange.receive. TellExchange.transportFailedwhen a send fails or a TCP connection breaks.For
Step.Done, callExchange.finishfor the result.
The exchange tries each server in turn, for attempts rounds. It waits timeout for each server
in the first round, and doubles the wait in each later round, up to 8 times timeout. A reply with
the TC bit is asked again over TCP from the same server. A server that answers SERVFAIL, NOTIMP or
REFUSED is skipped at once. A FORMERR answer to a query with EDNS is asked again without EDNS.
A late UDP answer from a server that was asked before is accepted.
Gotchas#
The exchange checks the identifier and the question of each reply, but it cannot see where a datagram came from. Use one connected UDP socket for each server, or check the source address yourself, and give only datagrams from a server of the configuration.
Import as Exchange with import silk.net.dns.query { Exchange }.
Public declarations: 7.
EDNS_PAYLOAD_SIZE#
pub const EDNS_PAYLOAD_SIZE: u16The UDP payload size that queries with EDNS announce: 1232 bytes, which avoids IP fragmentation on most networks.
Transport#
pub enum TransportHow a packet goes to a server.
Udp#
UdpOne UDP datagram.
Tcp#
TcpA TCP connection. The packet starts with its length in two bytes.
Implementation Debug for Transport#
impl Debug for TransportOperation debug#
effect fn debug(self: &Self, formatter: &mut Formatter) -> ()
! WriterError
? &mut WriterWrites the name of the variant, such as Udp.
Step#
pub union StepWhat the owner of an Exchange must do next.
Send#
SendSend Exchange.packet for transport to endpoint, then call Exchange.poll again.
Field server#
pub server: usizeThe position of the server in the configuration.
Field endpoint#
pub endpoint: EndpointThe address of the server.
Field transport#
pub transport: TransportHow to send the packet.
Wait#
WaitWait for a reply until until, then call Exchange.poll again.
Field until#
pub until: InstantThe time on the MonotonicClock at which the current try ends.
Done#
DoneThe exchange has a result. Call Exchange.finish.
QueryError#
pub union QueryErrorA query that failed.
NoServers#
NoServersThe configuration has no servers.
Timeout#
TimeoutNo server answered before the last try ended.
Rejected#
RejectedThe last server that answered refused the query, with SERVFAIL, NOTIMP, REFUSED or FORMERR.
Field responseCode#
pub responseCode: u16The response code, such as RCODE_SERVER_FAILURE.
Field server#
pub server: usizeThe position of the server in the configuration.
BadResponse#
BadResponseThe last server that answered over TCP sent a message that cannot be read, or that does not answer the question.
Field reason#
pub reason: MessageReasonThe problem in the message.
Field server#
pub server: usizeThe position of the server in the configuration.
Unreachable#
UnreachableA send to the last server failed, or its TCP connection broke, as Exchange.transportFailed reported.
Field server#
pub server: usizeThe position of the server in the configuration.
Implementation Copy for QueryError#
impl Copy for QueryErrorImplementation Debug for QueryError#
impl Debug for QueryErrorOperation debug#
effect fn debug(self: &Self, formatter: &mut Formatter) -> ()
! WriterError
? &mut WriterWrites the name of the variant and its fields, such as Rejected { ... }.
Reply#
pub struct ReplyThe answer to a query.
Field message#
pub message: MessageThe message that the server sent.
Field bytes#
pub bytes: BytesThe message as it was on the wire, without the TCP length.
Field server#
pub server: usizeThe position of the server in the configuration.
Field transport#
pub transport: TransportHow the message came.
Receipt#
pub enum ReceiptWhat Exchange.receive did with a message.
Answer#
AnswerThe message answers the query. Exchange.poll now returns Step.Done.
Retry#
RetryThe message made the exchange retry: over TCP, without EDNS, or at the next server.
Ignored#
IgnoredThe message is not for this query, or came when no reply was expected from that server. It changed nothing.
Exchange#
pub struct ExchangeOne question sent to the servers of a configuration. See the module documentation for the protocol.
Implementation Exchange#
impl ExchangeAssociated function make#
pub effect fn make(config: &ResolverConfig, question: Question, id: u16, first: usize) -> Exchange
! MessageError | OutOfMemoryError
? &mut AllocatorReturns an exchange that asks question with the identifier id.
Details#
The exchange uses the servers, timeout, attempts, edns and useTcp of config, and starts
at server first, modulo the number of servers. To follow the rotate option, give a different
first to each query. Take id from a Random provider, so that an attacker cannot guess it.
Errors#
MessageErrorif the query does not fit in a message, which happens only for a wrong class or type.OutOfMemoryErrorif theAllocatorcannot supply the packets.
Method endpoint#
pub fn endpoint(self: &Self, server: usize) -> EndpointReturns the address of server server, its position in the configuration. server must be less
than the number of servers.
Method id#
pub fn id(self: &Self) -> u16Returns the identifier of the query.
Method packet#
pub fn packet(self: &Self, transport: Transport) -> &[u8]Returns the packet to send for transport: one DNS message for UDP, or the message after its
two-byte length for TCP.
Method poll#
pub fn poll(self: &mut Self, now: &Instant) -> StepReturns the next thing to do at the time now of a MonotonicClock.
Details#
Step.Send starts a try, and the next call returns Step.Wait with the end of that try. When
now reaches the end, the exchange moves to the next server and returns Step.Send again. After
the last try it returns Step.Done, and Exchange.finish gives QueryError.Timeout or the
last problem a server reported.
Method receive#
pub effect fn receive(
self: &mut Self,
server: usize,
transport: Transport,
bytes: &[u8],
) -> Receipt
! OutOfMemoryError
? &mut AllocatorGives the exchange a message from server server: one UDP datagram, or one TCP message without
its two-byte length.
Details#
A message with another identifier or question is ignored, as is a UDP message from a server that was not asked over UDP, or a TCP message when no TCP answer is expected from that server. A UDP message that cannot be read is ignored too, because anyone can send one. A TCP message that cannot be read makes the exchange move to the next server.
Errors#
OutOfMemoryErrorif theAllocatorcannot supply the message or new packets.
Method transportFailed#
pub fn transportFailed(self: &mut Self, server: usize, transport: Transport) -> ()Tells the exchange that sending to server with transport failed, or that its TCP connection
broke before a whole answer came.
Details#
If the current try uses that server and transport, the exchange moves to the next server at once. Otherwise nothing changes.
Method isDone#
pub fn isDone(self: &Self) -> boolReturns true once Exchange.poll returns Step.Done.
Method finish#
pub fn finish(self: Self) -> Result<Reply, QueryError>Returns the result: the reply, or why there is none.
Details#
A reply can have any response code other than SERVFAIL, NOTIMP, REFUSED and FORMERR, such as
RCODE_NAME_ERROR for a name that does not exist. Check reply.message.header.responseCode.
Errors#
QueryError.Timeoutif the exchange is not done, or no server answered in time.The last problem that a server reported, if no server answered.
Category: Networking.
Profiles: aarch64-apple-darwin, aarch64-unknown-linux-gnu, aarch64-unknown-linux-gnu-no-libc, x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu-no-libc, wasm32-unknown-unknown, wasm32-wasip1, wasm32-wasip2, x86_64-pc-windows-msvc, wasm64-unknown-unknown.