silk.net.dns.client_native.

Ask DNS servers questions from a native program, with system UDP and TCP sockets.

When to use#

Use a NativeDnsClient to look up any record type, such as MX or TXT, in a program without an event loop. It blocks the thread until the answer comes or the last try ends. To use your own sockets or loop, drive a silk.net.dns.query.Exchange instead. To turn a host name into addresses with the system rules, such as /etc/hosts, use silk.net.resolver_native.

Details#

NativeDnsClient.query drives an Exchange with the servers and options of a ResolverConfig. Each server gets its own connected UDP socket, so the system drops datagrams that come from another address. A TCP try opens a new connection with silk.net.socket_native. Query identifiers come from the Random service.

Examples#

Ask a test server#

This program starts no server, so the query fails with Unreachable or Timeout.

silk
import silk.mem.allocator { Allocator, OutOfMemoryError }
import silk.collections.list { List }
import silk.core.effect { Effect }
import silk.core.result { Result }
import silk.net.address { Endpoint, IpAddress, Ipv4Address, Port }
import silk.net.dns.client_native { NativeDnsClient }
import silk.net.dns.config { ResolverConfig }
import silk.net.dns.message { CLASS_IN, MessageError, Name, Question, TYPE_A }
import silk.net.dns.query { QueryError, Reply }
import silk.system.monotonic_clock { MonotonicClock }
import silk.system.monotonic_clock_native { OsMonotonicClock }
import silk.system.random { Random }
import silk.system.random_native { OsRandom }

effect fn program() -> i32
  ! MessageError | OutOfMemoryError
  ? &mut Allocator | &mut MonotonicClock | &mut Random {
  let mut servers = List<Endpoint>.make()
  let loopback = IpAddress.V4 { value: Ipv4Address.fromOctets([127, 0, 0, 1]) }
  run List<Endpoint>.append(&mut servers, Endpoint.make(loopback, Port.fromU16(9)))
  let mut config = ResolverConfig.make(move servers)
  config.timeout = 100000000
  config.attempts = 1
  let name = match Name.parse("example.com") {
    Result<Name, MessageError>.Success { value } => value
    Result<Name, MessageError>.Failure {..} => {
      return 1
    }
  }
  let mut client = NativeDnsClient.make(move config)
  let result = run Effect.result(NativeDnsClient.query(
    &mut client,
    Question { name: name, kind: TYPE_A, class: CLASS_IN },
  ))
  return match move result {
    Result<Reply, QueryError | MessageError | OutOfMemoryError>.Success {..} => 1
    Result<Reply, QueryError | MessageError | OutOfMemoryError>.Failure {..} => 0
  }
}

effect fn failed<E>(error: E) -> i32 {
  drop error
  return 1
}

pub fn main() -> i32 {
  let mut allocator = Allocator.systemAllocatorProvider()
  let mut clock = OsMonotonicClock.make()
  let mut random = OsRandom.make()
  return run Effect.catchAll(program(), failed)
    |> Effect.provideMut<Allocator>(&mut allocator)
    |> Effect.provideMut<MonotonicClock>(&mut clock)
    |> Effect.provideMut<Random>(&mut random)
}

Import as NativeDnsClient with import silk.net.dns.client_native { NativeDnsClient }.

Public declarations: 1.

NativeDnsClient#

silk
pub struct NativeDnsClient

A blocking DNS client for native programs.

Details#

The client keeps its ResolverConfig. With the rotate option, each query starts at the next server.

Implementation NativeDnsClient#

silk
impl NativeDnsClient

Associated function make#

silk
pub fn make(config: ResolverConfig) -> NativeDnsClient

Returns a client for config.

Method config#

silk
pub fn config(self: &Self) -> &ResolverConfig

Returns the configuration of the client.

Method query#

silk
pub effect fn query(self: &mut Self, question: Question) -> Reply
    ! QueryError | MessageError | OutOfMemoryError
    ? &mut Allocator | &mut MonotonicClock | &mut Random

Asks question and returns the answer.

Details#

The 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. A server that cannot be reached, because a socket cannot be opened or a send fails, is skipped.

Errors#

  • QueryError if no server answered: Timeout, NoServers, or the last problem that a server reported.

  • MessageError if the question does not fit in a message.

  • OutOfMemoryError if the Allocator cannot supply the packets or the reply.

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.

View the source of this page