---
title: SAIF.Framework.DNS architecture
summary: Architectural responsibilities, boundaries, and interaction patterns.
status: draft
owner: <owner>
last_reviewed: 2026-07-23
library: SAIF.Framework.DNS
reference_type: package
---

# SAIF.Framework.DNS architecture

SAIF.Framework.DNS is a small, self-contained, low-level DNS client that performs lookups over raw UDP sockets in accordance with RFC1035 message framing. It has zero dependencies on other SAIF framework components and performs no I/O other than DNS UDP requests.

## Responsibilities
- Build DNS query messages from caller-supplied domain, type, and class values (`Request`, `Question`).
- Transmit query messages over UDP to a caller-specified DNS server on port 53, with retry and timeout handling (`Resolver`).
- Parse raw UDP reply bytes into a structured `Response`, including header flags/counts and Question/Answer/NameServer/AdditionalRecord sections (`Response`, `Pointer`).
- Decode individual resource-record RDATA into typed records (`ANameRecord`, `MXRecord`, `NSRecord`, `SoaRecord`) based on the record's `DnsType`, skipping unrecognized types.
- Provide a convenience MX-lookup operation that filters and sorts MX answers by preference (`Resolver.MXLookup`).
- Signal failure conditions via typed exceptions (`NoResponseException`, `InvalidResponseException`).

## Component boundaries
- `Resolver`: static-only (sealed, private constructor) entry-point facade exposing `Lookup` and `MXLookup`; owns UDP socket transfer and retry logic.
- `Request`: caller-facing message builder; holds one or more `Question` instances and serializes them to wire format via `GetMessage()`.
- `Question`: represents a single DNS query (domain/type/class); validates inputs and can also be constructed internally from a `Pointer` when decoding an embedded question in a response.
- `Response`: parses a raw reply byte array into `ReturnCode`, questions, and resource-record arrays.
- `ResourceRecord` (and semantic subtypes `Answer`, `NameServer`, `AdditionalRecord`): shared RR wire-format parser producing a `RecordBase` payload.
- `RecordBase` subtypes (`ANameRecord`, `MXRecord`, `NSRecord`, `SoaRecord`): typed RDATA payloads for the record kinds this library understands.
- `Pointer`: internal byte-array cursor used across parsing components to decode domain names (including RFC1035 message-compression pointers) and primitive wire values.
- `Enums` (`DnsType`, `DnsClass`, `ReturnCode`, `Opcode`): shared value types used across the request/response boundary.
- `InvalidResponseException` / `NoResponseException`: typed failure signals surfaced to callers.
- `MXHelper.cs` (namespace `SAIF.Framework.DNSLib`): a parallel, independent MX-lookup implementation (its own `UdpClient`-based transport and a distinct `MXRecord` type) that is **not** part of the compiled component boundary — see [Design constraints](#design-constraints).

## Interaction model
- Caller constructs a `Request` and adds one or more `Question` objects.
- `Resolver.Lookup(request, dnsServer)` serializes the request via `Request.GetMessage()`, sends it over UDP to port 53 with up to `_udpRetryAttempts` (2) retries and a 1-second receive timeout, then wraps the raw reply in a `Response`.
- `Response`'s constructor parses the DNS message header (flags, counts) and, via an internal `Pointer` cursor, decodes `Question`, `Answer`, `NameServer`, and `AdditionalRecord` arrays in wire order.
- Each `ResourceRecord` decodes its RDATA into a `RecordBase` subtype based on `DnsType`; unrecognized types are skipped by advancing the pointer past the record length.
- `Resolver.MXLookup(domain, dnsServer)` is a convenience wrapper that issues an MX question, filters `Answer`s to `MXRecord` instances, and returns them sorted by preference using `MXRecord`'s `IComparable` implementation.
- The library does not call into any other SAIF assembly, database, configuration system, or security component; all interaction is confined to the caller and the target DNS server over UDP.

## Architecture diagram
The following diagram shows the high-level component interactions for a lookup request.

```mermaid
flowchart TD
	Caller[Caller] --> Request[Request / Question]
	Request --> Resolver[Resolver]
	Resolver -->|UDP port 53, retry x2, 1s timeout| DnsServer[External DNS server]
	DnsServer -->|raw reply bytes| Resolver
	Resolver --> Response[Response]
	Response --> Pointer[Pointer<br>wire-format cursor]
	Pointer --> Records[RecordBase subtypes<br>ANameRecord / MXRecord / NSRecord / SoaRecord]
	Records --> Caller
```

## Sequence diagram
The following diagram shows the primary request/response sequence for a lookup, including the retry path.

```mermaid
sequenceDiagram
	participant Caller
	participant Resolver
	participant DnsServer as External DNS server
	participant Response
	Caller->>Resolver: Lookup(request, dnsServer) / MXLookup(domain, dnsServer)
	Resolver->>DnsServer: UDP datagram (stamped transaction id)
	alt matching-id reply received within 1s
		DnsServer-->>Resolver: UDP reply bytes
	else timeout or SocketException
		Resolver->>DnsServer: retry (up to 2 additional attempts)
		DnsServer-->>Resolver: UDP reply bytes
	end
	Resolver->>Response: new Response(replyBytes)
	Response-->>Resolver: parsed Answer/NameServer/AdditionalRecord arrays
	Resolver-->>Caller: Response (or thrown NoResponseException)
```

## Design constraints
- `Resolver` is a static-only utility class (private constructor, `sealed`), consistent with a stateless helper; it holds no instance state across calls.
- Unrecognized resource-record types are skipped rather than causing a parse failure, so the response model is intentionally tolerant of unknown `DnsType` values.
- A returned UDP datagram is only accepted if its 2-byte transaction id matches the request's stamped id; mismatched packets are ignored, implicitly triggering the retry loop.
- Malformed embedded questions during response parsing abort construction via `InvalidResponseException` rather than returning a partially-parsed `Response`.
- **Dead/parallel implementation**: `MXHelper.cs` (namespace `SAIF.Framework.DNSLib`) implements an independent, self-contained MX-lookup mechanism with its own raw `UdpClient` transport, manual DNS wire encode/decode, and its own distinct `MXRecord` type. It is present in the project folder but is **not** included in the `<Compile>` item group of `SAIF.BOF.Framework.DNS.csproj`, so it has no effect on the assembly's public surface or runtime behavior. Its source is nonetheless captured by the repository-wide packaging nuspec glob (`SAIF.Framework.Core\SAIF.BOF.Framework.Core.nuspec`), which bundles it as loose source under the package's `src` folder even though it never executes*. Maintainers should treat this file as dead code and consider removing it or restoring it to the compile list to avoid confusion about which MX-lookup implementation is authoritative. It is not documented as part of the API reference for this library because it is not part of the compiled public surface.

> **Note:** Statements marked with * were inferred from code structure, naming conventions, or
> contextual evidence where direct confirmation was not available in source artifacts. Statements
> marked with ** could not be confirmed; treat as unknown until verified.

## Related documentation
- [Index](index.md)
- [Overview](overview.md)
- [Dependencies](dependencies.md)
- [Operations and processes](operations-processes.md)
- [Business rules](business-rules.md)
- [Configuration](configuration.md)
- [API reference](api/index.md)

## Sources
- SAIF.Framework.DNS\SAIF.BOF.Framework.DNS.csproj
- SAIF.Framework.DNS\Resolver.cs
- SAIF.Framework.DNS\Request.cs
- SAIF.Framework.DNS\Question.cs
- SAIF.Framework.DNS\Response.cs
- SAIF.Framework.DNS\ResourceRecord.cs
- SAIF.Framework.DNS\RecordBase.cs
- SAIF.Framework.DNS\ANameRecord.cs
- SAIF.Framework.DNS\MXRecord.cs
- SAIF.Framework.DNS\NSRecord.cs
- SAIF.Framework.DNS\SoaRecord.cs
- SAIF.Framework.DNS\Pointer.cs
- SAIF.Framework.DNS\Enums.cs
- SAIF.Framework.DNS\InvalidResponseException.cs
- SAIF.Framework.DNS\NoResponseException.cs
- SAIF.Framework.DNS\MXHelper.cs
- SAIF.Framework.Core\SAIF.BOF.Framework.Core.nuspec
