{-# OPTIONS_GHC -Wno-duplicate-exports #-}
{-|
Module      : Net.DNSBase
Description : DNS Stub resolver
Copyright   : (c) Viktor Dukhovni, 2026
License     : BSD-3-Clause
Maintainer  : ietf-dane@dukhovni.org
Stability   : unstable

A DNS stub-resolver library with a typed 'RData' model and a
runtime extension API.  The IO layer is derived from Kazu
Yamamoto's [@dns@](https://hackage.haskell.org/package/dns)
package; what @dnsbase@ layers on top sits in the RR-data model
and the configuration story.

Every RR type's payload is modeled via a dedicated Haskell type
— these include, for example, the recent SVCB \/ HTTPS
service-binding records, with up-to-date extensible SvcParam
coverage.  EDNS option support includes Extended DNS Errors
(EDE) with a user-extensible info-code name table.  Coverage of
both widely used and historical DNS RR types is comprehensive —
only the most marginal obsolete or experimental types remain
unimplemented.  Individual payloads are held uniformly inside
the existential 'RData' wrapper, so an 'RR' value can carry any
type's data.

The basic lookup interface ('lookupA', 'lookupMX', 'lookupTXT',
…) is deliberately similar to @dns@; the differences are
concentrated in the typed-data layer and the configuration
surface.

== Extending the library

Applications can extend the library with any /missing/ RRTYPEs,
EDNS(0) options, or SVCB and HTTPS service parameter values.
Application-specified data types take precedence over any existing
or later added built-in implementations.

Extensions are registered by constructing a pure resolver
configuration value, rather than via IO actions on mutable
global state.  Adding custom data types to the library does not
require a source-code fork.  See
[Adding a custom RR type]("Net.DNSBase.Extensible#customRRtype")
and
[Adding a custom EDNS option]("Net.DNSBase.Extensible#customEDNS")
for detailed examples.

== Concurrency

Like its @dns@ ancestor, @dnsbase@ scales well to thousands of
@forkIO@ threads, with throughput of around ten thousand
distinct queries (not even cache hits) per second observed when
given sufficient concurrency, a high file descriptor limit and
a cooperative upstream iterative resolver.

A single 'ResolvSeed' configuration can be used to derive
per-thread 'Resolver' instances via 'withResolver'.  As in
@dns@, concurrent use of the same 'Resolver' in multiple
threads is not supported.

== A minimal example

> import Net.DNSBase
> import Control.Exception (throwIO)
> import System.IO (stdout)
>
> main :: IO ()
> main = makeResolvSeed defaultResolvConf >>= \ case
>   Left  e    -> throwIO e
>   Right seed -> withResolver seed \ r ->
>     lookupMX r $$(dnLit8 "ietf.org") >>= \ case
>       Left  e   -> throwIO e
>       Right mxs -> hPutBuilder stdout $ foldr presentLn mempty mxs

'makeResolvSeed' builds a 'ResolvSeed' from a 'ResolverConf'; the
default reads @\/etc\/resolv.conf@.  The setters:

* 'setResolverConfTimeout'
* 'setResolverConfRetries'
* 'setResolverConfSource'
* 'setResolverConfQueryControls'

compose with 'defaultResolvConf' to override individual fields.

Inside a 'withResolver' block the per-RRtype lookup combinators,
such as:

* 'lookupA'
* 'lookupAAAA'
* 'lookupMX'
* 'lookupTXT'
* 'lookupNS'
* 'lookupDS'

each return a list of matching records.  Applications that want
to process the full 'DNSMessage' response can use 'lookupRaw'
or 'lookupRawCtl'.

The 'dnLit' and 'dnLit8' Template-Haskell splices make it
possible to validate a literal domain name at compile time.
The @idna2008@ package provides compatible parsers for Unicode
internationalised domain names (IDNs).

== Module tour

This all-in-one module re-exports almost the entire public API.
Specific topics are covered in:

* Resolver setup and queries — "Net.DNSBase.Resolver",
  "Net.DNSBase.Lookup".
* Domain names — "Net.DNSBase.Domain".
* Resource-record types and the 'RData' wrapper —
  "Net.DNSBase.RR", "Net.DNSBase.RData",
  "Net.DNSBase.RRTYPE", "Net.DNSBase.RRCLASS".
* Address records — "Net.DNSBase.RData.A".
* Name-valued records (CNAME, NS, PTR, etc.) —
  "Net.DNSBase.RData.XNAME".
* Mail and service records (SOA, RP, MX, SRV, NAPTR, etc.) —
  "Net.DNSBase.RData.SOA", "Net.DNSBase.RData.SRV".
* Service-binding records (SVCB, HTTPS) —
  "Net.DNSBase.RData.SVCB".
* DNSSEC (DS, DNSKEY, RRSIG, etc.) and denial of existence
  (NSEC, NSEC3, …) — "Net.DNSBase.RData.Dnssec",
  "Net.DNSBase.RData.NSEC".
* DANE certificate bindings (TLSA, SMIMEA, SSHFP, OPENPGPKEY)
  — "Net.DNSBase.RData.TLSA".
* Other RR types (TXT, CAA, CSYNC, etc.) — the corresponding
  @Net.DNSBase.RData.*@ submodules.
* EDNS options —
  "Net.DNSBase.EDNS", "Net.DNSBase.EDNS.Option" and the
  per-option submodules.
* DNS message structure — "Net.DNSBase.Message".
* Extending the library at runtime —
  "Net.DNSBase.Extensible" (long-form guide),
  "Net.DNSBase.Resolver" (the @register@ and @extend@
  combinators).

-}

module Net.DNSBase
    ( -- * Resolver setup
      -- ** Static resolver configuration
       ResolverConf
     , defaultResolvConf
     , NameserverConf(..)
     , NameserverSpec(..)
      -- ** Resolver seeds
     , ResolvSeed
     , makeResolvSeed
     -- ** Derived resolver objects
     , Resolver(..)
     , withResolver
      -- * Queries
    , Lookup
    , extractAnswers
    , lookupRaw
    , lookupRawCtl
    , lookupAnswers
    , lookupA
    , lookupAAAA
    , lookupMX
    , lookupNS
    , lookupCNAME
    , lookupPTR
    , lookupTXT
    , lookupSOA
    , lookupSRV
    , lookupTLSA
    , lookupHTTPS
      -- * Domain names
    , Domain(..)
    , dnLit
    , decodePresentationDomain
    , dnLit8
    , makeDomain8
    , makeDomain8Str
    , shortBytes
    , wireToDomain
      -- * Resource records, RData, and messages
    , RR(..)
    , DnsTriple(..)
    , RData
    , fromRData
    , RRTYPE
    , RRCLASS
    , DNSMessage
    , DNSError(..)
      -- * Common resource record types
    , T_a(..)
    , T_aaaa(..)
    , T_mx(..)
    , T_srv(..)
    , T_txt(..)
    , T_ptr
    , pattern T_PTR
    , T_https
    , pattern T_HTTPS
      -- * Query and EDNS controls
    , QueryControls(QctlFlags, EdnsEnabled, EdnsDisabled, EdnsUdpSize, EdnsOptionCtl)
    , pattern RDflag
    , pattern ADflag
    , pattern CDflag
    , pattern DOflag
    , setFlagBits
    , clearFlagBits
      -- * Extending the library
    , KnownRData
    , registerRRtype
    , extendRRwithType
    , extendRRwithValue
    , KnownEdnsOption
    , registerEdnsOption
    , extendEdnsOptionWithType
    , extendEdnsOptionWithValue
    , KnownSVCParamValue
    , TypeExtensible(..)
    , ValueExtensible(..)
      -- * Chained-composition opt-in
    , DNSIO
    , runDNSIO
    , liftDNS
      -- * Reference: all re-exported modules
    , module Net.DNSBase.Domain
    , module Net.DNSBase.EDNS
    , module Net.DNSBase.EDNS.OptNum
    , module Net.DNSBase.EDNS.Option
    , module Net.DNSBase.EDNS.Option.ECS
    , module Net.DNSBase.EDNS.Option.EDE
    , module Net.DNSBase.EDNS.Option.NSID
    , module Net.DNSBase.EDNS.Option.Opaque
    , module Net.DNSBase.EDNS.Option.Secalgs
    , module Net.DNSBase.Error
    , module Net.DNSBase.Flags
    , module Net.DNSBase.Lookup
    , module Net.DNSBase.Message
    , module Net.DNSBase.NonEmpty
    , module Net.DNSBase.Opcode
    , module Net.DNSBase.RCODE
    , module Net.DNSBase.RData
    , module Net.DNSBase.RData.A
    , module Net.DNSBase.RData.CAA
    , module Net.DNSBase.RData.CSYNC
    , module Net.DNSBase.Bytes
    , module Net.DNSBase.Present
    , module Net.DNSBase.RData.Dnssec
    , module Net.DNSBase.RData.NSEC
    , module Net.DNSBase.RData.SOA
    , module Net.DNSBase.RData.SRV
    , module Net.DNSBase.RData.SVCB
    , module Net.DNSBase.RData.TLSA
    , module Net.DNSBase.RData.TXT
    , module Net.DNSBase.RData.XNAME
    , module Net.DNSBase.Resolver
    , module Net.DNSBase.RR
    , module Net.DNSBase.RRCLASS
    , module Net.DNSBase.RRTYPE
    , module Net.DNSBase.Secalgs
    , module Net.DNSBase.Text
    ) where

import Net.DNSBase.Bytes
import Net.DNSBase.Domain
import Net.DNSBase.EDNS
import Net.DNSBase.EDNS.OptNum
import Net.DNSBase.EDNS.Option
import Net.DNSBase.EDNS.Option.ECS
import Net.DNSBase.EDNS.Option.EDE
import Net.DNSBase.EDNS.Option.NSID
import Net.DNSBase.EDNS.Option.Opaque
import Net.DNSBase.EDNS.Option.Secalgs
import Net.DNSBase.Error
import Net.DNSBase.Extensible
import Net.DNSBase.Flags
import Net.DNSBase.Lookup
import Net.DNSBase.Message
import Net.DNSBase.NonEmpty
import Net.DNSBase.Opcode
import Net.DNSBase.Present
import Net.DNSBase.RCODE
import Net.DNSBase.RData
import Net.DNSBase.RData.A
import Net.DNSBase.RData.CAA
import Net.DNSBase.RData.CSYNC
import Net.DNSBase.RData.Dnssec
import Net.DNSBase.RData.NSEC
import Net.DNSBase.RData.SOA
import Net.DNSBase.RData.SRV
import Net.DNSBase.RData.SVCB
import Net.DNSBase.RData.TLSA
import Net.DNSBase.RData.TXT
import Net.DNSBase.RData.XNAME
import Net.DNSBase.Resolver
import Net.DNSBase.RR
import Net.DNSBase.RRCLASS
import Net.DNSBase.RRTYPE
import Net.DNSBase.Secalgs
import Net.DNSBase.Text