Files
ExploreDNS/internal/output/runner.go
T
9aa85d8e5d
CI / test (pull_request) Failing after 2m13s
docs: comprehensive documentation for ExploreDNS
- 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>
2026-06-08 04:01:51 +10:00

72 lines
2.0 KiB
Go

package output
import (
"context"
"fmt"
"net"
"github.com/hits/ExploreDNS/internal/fingerprint"
"github.com/hits/ExploreDNS/internal/traverse"
)
// RunTraversal is the high-level entry point that wires together a Traverser,
// a Config, and a Formatter. It:
//
// 1. Attaches output hooks to traverser so events are formatted in real time.
// 2. Calls traverser.Traverse(ctx, domain) to perform the traversal.
// 3. Optionally fingerprints encountered servers (when ShowVersions && ShowServers).
// 4. Writes the summary and flushes the formatter.
//
// Returns all TraversalResults and any error from the traversal or output.
func RunTraversal(ctx context.Context, traverser *traverse.Traverser, cfg *Config, formatter Formatter, domain string) ([]traverse.TraversalResult, error) {
if traverser == nil {
return nil, fmt.Errorf("traverser is required")
}
if cfg == nil {
cfg = DefaultConfig()
}
if formatter == nil {
formatter = NewFormatter(cfg, nil)
}
traverser.SetHooks(AttachHooks(cfg, formatter))
results, err := traverser.Traverse(ctx, domain)
if err != nil {
return results, err
}
// Fingerprint servers when both ShowVersions and ShowServers are enabled.
// Gating on ShowServers avoids unnecessary network calls when versions
// would not be displayed anyway.
if cfg.ShowVersions && cfg.ShowServers {
cfg.Fingerprints = fingerprint.New().FingerprintAll(ctx, collectUniqueServerIPs(results))
}
if err := formatter.WriteSummary(results); err != nil {
return results, err
}
if err := formatter.Flush(); err != nil {
return results, err
}
return results, nil
}
// collectUniqueServerIPs returns the set of unique server IPs seen in results.
func collectUniqueServerIPs(results []traverse.TraversalResult) []net.IP {
seen := make(map[string]bool)
var ips []net.IP
for _, r := range results {
if r.Response == nil || r.Response.Server == nil {
continue
}
key := r.Response.Server.String()
if !seen[key] {
seen[key] = true
ips = append(ips, r.Response.Server)
}
}
return ips
}