| Copyright | (c) Viktor Dukhovni 2026 |
|---|---|
| License | BSD-3-Clause |
| Maintainer | ietf-dane@dukhovni.org |
| Stability | unstable |
| Safe Haskell | None |
| Language | GHC2024 |
Net.DNSBase.RData.SVCB
Description
The Service Binding RR (T_svcb) and its HTTPS-specific
variant (T_https), defined by RFC 9460. Both share a wire
format with three fields — priority, target name, and a list
of typed (key, value) service parameters — represented
internally by the X_svcb data type, indexed by a type-level
natural that determines the specific RR type.
The service-parameter machinery is split across submodules:
- Net.DNSBase.RData.SVCB.SVCParamKey — the 16-bit key codes, with pattern synonyms for the registered keys.
- Net.DNSBase.RData.SVCB.SVCParamValue — the
KnownSVCParamValuetypeclass, the existentialSVCParamValuewrapper, and theOpaqueSPVfallback for unrecognised keys. - Net.DNSBase.RData.SVCB.SPV — the concrete value types
(
SPV_alpn,SPV_port, ...). - Net.DNSBase.RData.SVCB.SPVSet — the (key-indexed) collection holding the parameters of a single SVCB/HTTPS record.
New service-parameter value types can be installed at runtime via
extendRRwithType on the SVCB or HTTPS
RR type — see Net.DNSBase.Extensible for a worked example. The
mandatory key (codepoint 0) is reserved and cannot be replaced
by user code.
Synopsis
- data X_svcb (n :: Nat) where
- type family XsvcbConName (n :: Nat) :: Symbol where ...
- type T_https = X_svcb N_https
- httpsPriority :: T_https -> Word16
- httpsTarget :: T_https -> Domain
- httpsParamValues :: T_https -> SPVSet
- type T_svcb = X_svcb N_svcb
- svcPriority :: T_svcb -> Word16
- svcTarget :: T_svcb -> Domain
- svcParamValues :: T_svcb -> SPVSet
- class (Typeable a, Eq a, Ord a, Show a, Presentable a) => KnownSVCParamValue a where
- spvKey :: forall b -> b ~ a => SVCParamKey
- spvKeyPres :: forall b -> b ~ a => Builder -> Builder
- encodeSPV :: ErrorContext r => a -> SPut s r
- decodeSPV :: forall b -> b ~ a => Int -> SGet SVCParamValue
- data SPVSet where
- pattern SPVMap :: IntMap SVCParamValue -> SPVSet
- spvLookup :: KnownSVCParamValue a => SPVSet -> Maybe a
- module Net.DNSBase.RData.SVCB.SPV
- module Net.DNSBase.RData.SVCB.SVCParamValue
- module Net.DNSBase.RData.SVCB.SVCParamKey
SVCB and HTTPS
data X_svcb (n :: Nat) Source #
Shared wire-format representation for the SVCB service
binding record
(RFC 9460 section 2)
and its HTTPS-specific variant
(RFC 9460 section 9).
1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | SvcPriority | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / TargetName / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / SvcParams / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
The type parameter n (either N_https or N_svcb)
determines the RR type. Each has its own type synonym
(T_https, T_svcb) and matching record pattern synonym
(T_HTTPS, T_SVCB) with the corresponding field-name prefix
(https, svcb). The wire format is shared, but the type
role of n is nominal: a T_svcb value cannot be used where
a T_https is expected. This is deliberate — the two RR types
serve different transports, and future SvcParamKeys may apply
to only one of them.
Note that T_https and T_svcb are just type aliases! The T_HTTPS
and T_SVCB record pattern synonyms and their fields are
bundled with the underlying X_svcb data type. In many cases it
is sufficient to import just X_svcb(..), but if you also need
the type aliases, they need to be imported separately:
import Net.DNSBase (X_svcb(..), T_https, T_svcb)
The target field is not subject to wire-form name compression
(RFC 3597 section 4)
and is not in the
RFC 4034 section 6.2
list of types that lower-case their RDATA names — it is
compared case-sensitively in canonical form. The Ord
instance compares structurally on the parsed fields rather
than on the wire form, so it is not canonical: callers that
need RFC 4034 canonical ordering must serialise to wire form
first.
The SvcParams field is a list of (key, length, value)
triples — possibly empty — making up the rest of the RData:
1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | SvcParamKey | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | SvcParamLen | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / SvcParamValue / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
On the wire the list must be in strictly ascending key order;
the presentation form may list keys in any order. Each value
has the type associated with its key in the decoder state
configured for the RR type — keys absent from the state decode
as OpaqueSPV, preserving the raw bytes.
The record pattern synonyms T_SVCB and T_HTTPS build the
corresponding T_svcb or T_https value directly, with their
own field-name prefixes (svc and https):
let s = T_SVCB { svcPriority = 0
, svcTarget = RootDomain
, svcParamValues = [] }
h = T_HTTPS { httpsPriority = 0
, httpsTarget = RootDomain
, httpsParamValues = [] }
in RData s : RData h : []Functions that work on either RR type can use the
underscore-prefixed selectors on the shared X_svcb record:
aliasDomain :: forall n. X_svcb n -> Maybe Domain
aliasDomain r | x_svcPriority r == 0 = Just $ x_svcTarget r
| otherwise = NothingConstructors
| X_SVCB | |
Fields
| |
Bundled Patterns
| pattern T_SVCB | Record pattern synonym viewing the shared |
| pattern T_HTTPS | Record pattern synonym viewing the shared |
Instances
| Presentable (X_svcb n) Source # | |||||
Defined in Net.DNSBase.RData.SVCB Methods present :: X_svcb n -> Builder -> Builder Source # presentLazy :: X_svcb n -> ByteString -> ByteString Source # | |||||
| (Nat16 n, KnownSymbol (XsvcbConName n)) => KnownRData (X_svcb n) Source # | |||||
Defined in Net.DNSBase.RData.SVCB Associated Types
Methods rdataExtensionVal :: forall b -> b ~ X_svcb n => RDataExtensionVal (X_svcb n) Source # rdType :: forall b -> b ~ X_svcb n => RRTYPE Source # rdTypePres :: forall b -> b ~ X_svcb n => Builder -> Builder Source # rdDecode :: forall b -> b ~ X_svcb n => RDataExtensionVal (X_svcb n) -> Int -> SGet RData Source # | |||||
| KnownSymbol (XsvcbConName n) => Show (X_svcb n) Source # | |||||
| Eq (X_svcb n) Source # | |||||
| Ord (X_svcb n) Source # | |||||
Defined in Net.DNSBase.RData.SVCB | |||||
| type RDataExtensionVal (X_svcb n) Source # | |||||
Defined in Net.DNSBase.RData.SVCB | |||||
| type TypeExtensionArg (X_svcb n) b Source # | |||||
Defined in Net.DNSBase.RData.SVCB | |||||
type family XsvcbConName (n :: Nat) :: Symbol where ... Source #
Equations
| XsvcbConName N_svcb = "T_SVCB" | |
| XsvcbConName N_https = "T_HTTPS" | |
| XsvcbConName n = TypeError ('ShowType n ':<>: 'Text " is not a SVCB-based RRTYPE") :: Symbol |
T_HTTPS pattern record synonym fields
type T_https = X_svcb N_https Source #
X_svcb specialised to HTTPS records.
Note that T_https is just a type alias! The T_HTTPS record pattern
synonym and its fields are bundled with the underlying X_svcb
data type. In many cases it is sufficient to import just
X_svcb(..), but if you also need the type alias, it needs to be
imported separately:
import Net.DNSBase (X_svcb(..), T_https)
httpsPriority :: T_https -> Word16 Source #
httpsTarget :: T_https -> Domain Source #
httpsParamValues :: T_https -> SPVSet Source #
T_SVCB pattern record synonym fields
type T_svcb = X_svcb N_svcb Source #
X_svcb specialised to SVCB records.
Note that T_svcb is just a type alias! The T_SCVB record pattern
synonym and its fields are bundled with the underlying X_svcb
data type. In many cases it is sufficient to import just
X_svcb(..), but if you also need the type alias, it needs to be
imported separately:
import Net.DNSBase (X_svcb(..), T_svcb)
svcPriority :: T_svcb -> Word16 Source #
svcParamValues :: T_svcb -> SPVSet Source #
Service parameter values
class (Typeable a, Eq a, Ord a, Show a, Presentable a) => KnownSVCParamValue a where Source #
The class of types representing the value side of a service
parameter inside an SVCB or HTTPS record. Each instance
corresponds to a specific SVCParamKey; the encodeSPV and
decodeSPV methods handle only the value bytes.
The Presentable instance builds the RFC 9460 zone-file
presentation form: the key name followed (where the value is
non-empty) by = and the value. The Show instance is
typically derived and aims to produce syntactically valid
Haskell.
Methods
spvKey :: forall b -> b ~ a => SVCParamKey Source #
The associated key number
spvKeyPres :: forall b -> b ~ a => Builder -> Builder Source #
CPS presentation form builder for the key
encodeSPV :: ErrorContext r => a -> SPut s r Source #
Encode value to wire form.
The surrounding (key, length) frame is owned by the
SVCB-record encoder: encodeSPV writes just the payload,
and the framework wraps the result in the 2-byte length
prefix. For valueless parameters this means encodeSPV
is just pure ().
decodeSPV :: forall b -> b ~ a => Int -> SGet SVCParamValue Source #
Decode value from wire form. The overall SVCB RData decoder gives each parameter decoder a view into a buffer of exactly the indicated length, and makes sure exactly that many bytes are consumed. The length argument is only needed in decoders that read variable-length fields that run to the end of the record.
Instances
The set of service parameters in an SVCB or HTTPS record,
with at most one value per SVCParamKey. The Monoid
instance provides the empty set; the Semigroup instance is
left-biased on key collisions.
Bundled Patterns
| pattern SPVMap | One-sided pattern that exposes the underlying |
Fields
| |
Instances
| Presentable SPVSet Source # | |
Defined in Net.DNSBase.RData.SVCB.SPVSet Methods present :: SPVSet -> Builder -> Builder Source # presentLazy :: SPVSet -> ByteString -> ByteString Source # | |
| Monoid SPVSet Source # | |
| Semigroup SPVSet Source # | |
| IsList SPVSet Source # | Construction is via |
| Show SPVSet Source # | |
| Eq SPVSet Source # | |
| type Item SPVSet Source # | |
Defined in Net.DNSBase.RData.SVCB.SPVSet | |
spvLookup :: KnownSVCParamValue a => SPVSet -> Maybe a Source #
Look up the parameter at the key associated with type a,
returning a Just only when the stored value really is of type
a. A value of the same key code but held as OpaqueSPV
(because the typed instance was not registered when the record
was decoded) does not match — opaque values must be
retrieved through SPVMap.
module Net.DNSBase.RData.SVCB.SPV