docs: comprehensive documentation for ExploreDNS
CI / test (pull_request) Failing after 2m13s

- Rewrite README.md with overview, features, installation (go install +
  build from source), quick start, full CLI flag reference table,
  output section descriptions, project structure, and development guide

- Add package-level doc comments to all five internal packages:
  config, dns, fingerprint, output, traverse (via doc.go or existing
  package-declaration files)

- Add GoDoc comments on every exported type, constant, function, and
  method across all packages:
  - internal/config: Config struct fields, all Parse*/Default/Validate
  - internal/dns: QueryConfig, Resolver, BasicResolver, CachingResolver,
    ExchangeFunc, RootServer, RootDiscoveryConfig, DecodedResponse,
    ResponseClassification, all exported helpers
  - internal/fingerprint: Fingerprinter, New, NewWithTimeout, Query,
    FingerprintAll
  - internal/traverse: Traverser, TraverserConfig, TraversalResult,
    Referral, ResolutionState, Response, ResponseType, InfoCache,
    Stack, TraverserHooks, EventStage, TraversalEvent, EventHandler,
    CircularReferralError, UnresolvableNameserverError
  - internal/output: Format, Config, Formatter, SummaryStats,
    NewFormatter, AttachHooks, RunTraversal, DefaultConfig,
    ComputeSummary

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
Gary Hansen
2026-06-08 04:01:51 +10:00
co-authored by Copilot multica-agent
parent fe1afe2a97
commit 9aa85d8e5d
21 changed files with 675 additions and 91 deletions
+17
View File
@@ -10,12 +10,16 @@ import (
"github.com/miekg/dns"
)
// Resolver is the interface for sending DNS queries.
// Implementations may cache, mock, or delegate to the real network.
type Resolver interface {
Query(ctx context.Context, server net.IP, name string, qtype uint16, cfg *QueryConfig) (*dns.Msg, error)
}
// BasicResolver implements Resolver by issuing real UDP/TCP DNS queries.
type BasicResolver struct{}
// NewBasicResolver returns a BasicResolver ready for use.
func NewBasicResolver() *BasicResolver {
return &BasicResolver{}
}
@@ -40,6 +44,10 @@ func (e *cacheEntry) expired() bool {
return time.Now().After(e.expireAt)
}
// CachingResolver wraps another Resolver and caches successful responses.
// Responses are evicted based on the minimum DNS TTL in the message, with a
// configurable fallback default TTL for zero-TTL responses.
// All operations are safe for concurrent use.
type CachingResolver struct {
inner Resolver
mu sync.RWMutex
@@ -47,6 +55,9 @@ type CachingResolver struct {
defaultTTL time.Duration
}
// NewCachingResolver creates a CachingResolver wrapping inner.
// When inner is nil, a BasicResolver is used.
// Optional opts may be supplied to customise the default TTL (see WithDefaultTTL).
func NewCachingResolver(inner Resolver, opts ...CachingResolverOption) *CachingResolver {
if inner == nil {
inner = NewBasicResolver()
@@ -119,6 +130,7 @@ func (cr *CachingResolver) store(key cacheKey, msg *dns.Msg) {
cr.mu.Unlock()
}
// Len returns the current number of entries in the cache, including expired ones.
func (cr *CachingResolver) Len() int {
cr.mu.RLock()
n := len(cr.cache)
@@ -126,12 +138,14 @@ func (cr *CachingResolver) Len() int {
return n
}
// Clear removes all entries from the cache.
func (cr *CachingResolver) Clear() {
cr.mu.Lock()
cr.cache = make(map[cacheKey]*cacheEntry)
cr.mu.Unlock()
}
// PurgeExpired removes all expired entries from the cache and returns the count removed.
func (cr *CachingResolver) PurgeExpired() int {
cr.mu.Lock()
count := 0
@@ -145,12 +159,15 @@ func (cr *CachingResolver) PurgeExpired() int {
return count
}
// CachingResolverOption is a functional option for NewCachingResolver.
type CachingResolverOption func(*cachingResolverConfig)
type cachingResolverConfig struct {
defaultTTL time.Duration
}
// WithDefaultTTL sets the TTL used for cache entries when the DNS response
// contains no TTL information (or when TTL is zero).
func WithDefaultTTL(d time.Duration) CachingResolverOption {
return func(c *cachingResolverConfig) {
c.defaultTTL = d