Skip to content

Add WithDialer option for custom TCP dialer injection#12

Open
myleshorton wants to merge 3 commits intomainfrom
add-with-dialer
Open

Add WithDialer option for custom TCP dialer injection#12
myleshorton wants to merge 3 commits intomainfrom
add-with-dialer

Conversation

@myleshorton
Copy link
Copy Markdown
Contributor

Summary

  • Adds a WithDialer(func(ctx context.Context, network, addr string) (net.Conn, error)) option to dnstt
  • Threads the custom dialer through both dohDialer and dotDialer transport implementations via new utlsDialContextWithDialer and NewUTLSRoundTripperWithDialer functions
  • Falls back to (&net.Dialer{}).DialContext when no custom dialer is provided (preserving existing behavior)
  • Refactors utlsDialContext, NewUTLSRoundTripper, and makeRoundTripper to delegate to new dialer-aware variants

Test plan

  • go build ./... compiles cleanly
  • go vet ./... passes
  • Existing tests pass (go test ./...)
  • Verify DoH transport works end-to-end with default dialer
  • Verify DoT transport works end-to-end with default dialer
  • Verify custom dialer is called when injected via WithDialer

🤖 Generated with Claude Code

Allow callers to inject a custom dialer function via WithDialer() that
flows through to both DoH and DoT transports and their underlying uTLS
connections. This enables kindling to set a single dialer that
automatically applies to all dnstt connections.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@myleshorton myleshorton requested a review from Copilot February 22, 2026 12:58
myleshorton added a commit to getlantern/kindling that referenced this pull request Feb 22, 2026
Introduce a single WithDialer option at the kindling level that
automatically flows to all transports (fronted, dnstt, amp, smart).

Key changes:
- Add exported DialContextFunc type and WithDialer option
- Add Close() to Kindling interface for resource cleanup
- Rewrite WithDomainFronting to accept fronted.Option params
- Rewrite WithDNSTunnel to accept dnstt.Option params
- Rewrite WithAMPCache to accept amp.Config + amp.Option params
- Update smart dialer to use injected dialer via FuncStreamDialer
- Add streamConnAdapter and closerFunc helper types
- Update tests for new API signatures

The With* functions now construct transport instances internally and
prepend the dialer option, so callers no longer need to create
transport instances themselves.

Requires getlantern/fronted#67 and getlantern/dnstt#12.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
myleshorton added a commit to getlantern/kindling that referenced this pull request Feb 22, 2026
Introduce a single WithDialer option at the kindling level that
automatically flows to all transports (fronted, dnstt, amp, smart).

Key changes:
- Add exported DialContextFunc type and WithDialer option
- Add Close() to Kindling interface for resource cleanup
- Rewrite WithDomainFronting to accept fronted.Option params
- Rewrite WithDNSTunnel to accept dnstt.Option params
- Rewrite WithAMPCache to accept amp.Config + amp.Option params
- Update smart dialer to use injected dialer via FuncStreamDialer
- Add streamConnAdapter and closerFunc helper types
- Update tests for new API signatures

The With* functions now construct transport instances internally and
prepend the dialer option, so callers no longer need to create
transport instances themselves.

Requires getlantern/fronted#67 and getlantern/dnstt#12.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds support for custom TCP dialer injection to the dnstt package, allowing callers to control how TCP connections are established for DNS-over-HTTPS (DoH) and DNS-over-TLS (DoT) transports. This is useful for scenarios like proxying, custom DNS resolution, or network-level connection control.

Changes:

  • Adds WithDialer option to configure a custom TCP dialer function
  • Threads the custom dialer through both DoH and DoT transport implementations
  • Refactors uTLS helper functions to support optional custom dialers while maintaining backward compatibility

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
dnstt.go Adds WithDialer option, injects custom dialer into transport structs via type switch, adds dialContext field to dohDialer and dotDialer structs
utls.go Adds utlsDialContextWithDialer and NewUTLSRoundTripperWithDialer functions, refactors existing functions to delegate to new dialer-aware variants, adds dialContext field to utlsRoundTripper

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread dnstt.go
case *dohDialer:
t.dialContext = dial
case *dotDialer:
t.dialContext = dial
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dialer injection uses a type switch that silently does nothing if the transport is not a recognized type. If a new transport type is added in the future and the developer forgets to update this switch statement, the custom dialer will be silently ignored.

Consider one of these alternatives:

  1. Add a default case that logs a warning or returns an error
  2. Add a method to the transport interface like setDialer(func(...) (net.Conn, error)) to make this more explicit and type-safe
  3. Pass the dialer directly when creating the transport in WithDoH and WithDoT options (though this would require refactoring)
Suggested change
t.dialContext = dial
t.dialContext = dial
default:
slog.Warn("unable to inject custom dialer into transport; unrecognized transport type", "transportType", fmt.Sprintf("%T", t))

Copilot uses AI. Check for mistakes.
Comment thread dnstt.go
Comment on lines +356 to +363
// WithDialer sets a custom dialer function for the dnstt instance. This allows callers to
// inject their own dialer for making TCP connections used by the DNS transport.
func WithDialer(dial func(ctx context.Context, network, addr string) (net.Conn, error)) Option {
return func(d *dnstt) error {
d.dialContext = dial
return nil
}
}
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new WithDialer option lacks test coverage. Consider adding tests to verify:

  1. The custom dialer is actually called when making connections through DoH
  2. The custom dialer is actually called when making connections through DoT
  3. The behavior when no custom dialer is provided (default fallback works correctly)
  4. Error handling when the custom dialer returns an error

This is especially important since the dialer injection happens via type assertion and could fail silently if the code changes in the future.

Copilot uses AI. Check for mistakes.
Comment thread utls.go Outdated
// make future TLS connections using the same TLS configuration and
// ClientHelloID.
func makeRoundTripper(req *http.Request, config *utls.Config, id *utls.ClientHelloID) (http.RoundTripper, error) {
func makeRoundTripper(req *http.Request, dialCtx func(ctx context.Context, network, addr string) (net.Conn, error), config *utls.Config, id *utls.ClientHelloID) (http.RoundTripper, error) {
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter name dialCtx is inconsistent with the naming used elsewhere in the codebase. In utlsDialContextWithDialer and NewUTLSRoundTripperWithDialer, the parameter is named dialContext, but here it's abbreviated to dialCtx.

Consider renaming to dialContext for consistency.

Copilot uses AI. Check for mistakes.
myleshorton and others added 2 commits February 22, 2026 06:42
- Add default case to transport type switch with warning log for
  unrecognized transport types
- Rename dialCtx to dialContext in makeRoundTripper for consistency
- Add tests for WithDialer: DoH injection, DoT injection, default
  fallback behavior

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants