feat: implement traversal engine (HAN-380) (#6)
CI / test (push) Failing after 1m26s

Co-authored-by: Hansen IT Solutions <gary@hansenits.com>
Co-committed-by: Hansen IT Solutions <gary@hansenits.com>
This commit was merged in pull request #6.
This commit is contained in:
2026-06-06 03:41:14 +00:00
committed by multica-agent
parent 194bc97526
commit 39529dacbb
11 changed files with 2098 additions and 0 deletions
+68
View File
@@ -125,6 +125,74 @@ func QueryWithExchange(ctx context.Context, server net.IP, name string, qtype ui
return nil, fmt.Errorf("query %s %s failed after %d retries: %w", name, QNameType(qtype), cfg.Retries, lastErr)
}
func IterativeQuery(ctx context.Context, server net.IP, name string, qtype uint16, cfg *QueryConfig) (*dns.Msg, error) {
if cfg == nil {
cfg = DefaultQueryConfig()
}
if cfg.UDPSize <= 0 {
cfg.UDPSize = DefaultEDNS0UDPSize()
}
return IterativeQueryWithExchange(ctx, server, name, qtype, cfg, realExchange)
}
func IterativeQueryWithExchange(ctx context.Context, server net.IP, name string, qtype uint16, cfg *QueryConfig, exchangeFn ExchangeFunc) (*dns.Msg, error) {
if cfg == nil {
cfg = DefaultQueryConfig()
}
if cfg.UDPSize <= 0 {
cfg.UDPSize = DefaultEDNS0UDPSize()
}
msg := buildQuery(name, qtype, cfg.UDPSize)
msg.RecursionDesired = false
serverStr := server.String()
var lastErr error
for attempt := 0; attempt < cfg.Retries; attempt++ {
if attempt > 0 {
select {
case <-ctx.Done():
return nil, fmt.Errorf("query retries cancelled: %w", ctx.Err())
case <-time.After(100 * time.Millisecond):
}
}
if cfg.UseTCP {
resp, err := exchangeFn(ctx, serverStr, msg, true)
if err != nil {
lastErr = err
continue
}
return resp, nil
}
resp, err := exchangeFn(ctx, serverStr, msg, false)
if err != nil {
lastErr = err
continue
}
if resp == nil {
lastErr = fmt.Errorf("nil response")
continue
}
if resp.Truncated {
resp, err = exchangeFn(ctx, serverStr, msg, true)
if err != nil {
lastErr = err
continue
}
return resp, nil
}
return resp, nil
}
return nil, fmt.Errorf("iterative query %s %s failed after %d retries: %w", name, QNameType(qtype), cfg.Retries, lastErr)
}
func buildQuery(name string, qtype uint16, udpSize int) *dns.Msg {
m := new(dns.Msg)
m.SetQuestion(dns.Fqdn(name), qtype)