Skip to content

Commit

Permalink
x
Browse files Browse the repository at this point in the history
  • Loading branch information
bassosimone committed Sep 11, 2023
1 parent 8aeb5f8 commit 3c9d305
Show file tree
Hide file tree
Showing 7 changed files with 26 additions and 94 deletions.
6 changes: 0 additions & 6 deletions internal/model/netx.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,6 @@ type DNSEncoder interface {
Encode(domain string, qtype uint16, padding bool) DNSQuery
}

// DNSTransportWrapper is a type that takes in input a DNSTransport
// and returns in output a wrapped DNSTransport.
type DNSTransportWrapper interface {
WrapDNSTransport(txp DNSTransport) DNSTransport
}

// DNSTransport represents an abstract DNS transport.
type DNSTransport interface {
// RoundTrip sends a DNS query and receives the reply.
Expand Down
2 changes: 1 addition & 1 deletion internal/netxlite/dialer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func TestNewDialerWithStdlibResolver(t *testing.T) {
}
// typecheck the resolver
reso := logger.Dialer.(*dialerResolverWithTracing)
typecheckForSystemResolver(t, reso.Resolver, model.DiscardLogger) // FIXME
typeCheckForSystemResolver(t, reso.Resolver, model.DiscardLogger) // FIXME
// typecheck the dialer
logger = reso.Dialer.(*dialerLogger)
if logger.DebugLogger != model.DiscardLogger {
Expand Down
13 changes: 2 additions & 11 deletions internal/netxlite/dnstransport.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,11 @@ import (
"github.com/ooni/probe-cli/v3/internal/model"
)

// WrapDNSTransport wraps a DNSTransport to provide error wrapping. This function will
// apply all the provided wrappers around the default transport wrapping. If any of the
// wrappers is nil, we just silently and gracefully ignore it.
func WrapDNSTransport(txp model.DNSTransport,
wrappers ...model.DNSTransportWrapper) (out model.DNSTransport) {
// WrapDNSTransport wraps a DNSTransport to provide error wrapping.
func WrapDNSTransport(txp model.DNSTransport) (out model.DNSTransport) {
out = &dnsTransportErrWrapper{
DNSTransport: txp,
}
for _, wrapper := range wrappers {
if wrapper == nil {
continue // skip as documented
}
out = wrapper.WrapDNSTransport(out) // compose with user-provided wrappers
}
return
}

Expand Down
7 changes: 1 addition & 6 deletions internal/netxlite/dnstransport_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,7 @@ func (*dnsTransportWrapperSecond) WrapDNSTransport(txp model.DNSTransport) model

func TestWrapDNSTransport(t *testing.T) {
orig := &mocks.DNSTransport{}
extensions := []model.DNSTransportWrapper{
&dnsTransportWrapperFirst{},
nil, // explicitly test for documented use case
&dnsTransportWrapperSecond{},
}
txp := WrapDNSTransport(orig, extensions...)
txp := WrapDNSTransport(orig)
ext2 := txp.(*dnsTransportExtensionSecond)
ext1 := ext2.DNSTransport.(*dnsTransportExtensionFirst)
errWrapper := ext1.DNSTransport.(*dnsTransportErrWrapper)
Expand Down
35 changes: 13 additions & 22 deletions internal/netxlite/resolvercore.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,16 @@ import (
var ErrNoDNSTransport = errors.New("operation requires a DNS transport")

// NewStdlibResolver creates a new Resolver by combining WrapResolver
// with an internal "stdlib" resolver type. The list of optional wrappers
// allow to wrap the underlying getaddrinfo transport. Any nil wrapper
// will be silently ignored by the code that performs the wrapping.
func (netx *Netx) NewStdlibResolver(logger model.DebugLogger, wrappers ...model.DNSTransportWrapper) model.Resolver {
return WrapResolver(logger, netx.newUnwrappedStdlibResolver(wrappers...))
// with an internal "stdlib" resolver type.
func (netx *Netx) NewStdlibResolver(logger model.DebugLogger) model.Resolver {
return WrapResolver(logger, netx.newUnwrappedStdlibResolver())
}

// NewStdlibResolver is equivalent to creating an empty [*Netx]
// and callings its NewStdlibResolver method.
func NewStdlibResolver(logger model.DebugLogger, wrappers ...model.DNSTransportWrapper) model.Resolver {
func NewStdlibResolver(logger model.DebugLogger) model.Resolver {
netx := &Netx{Underlying: nil}
return netx.NewStdlibResolver(logger, wrappers...)
return netx.NewStdlibResolver(logger)
}

// NewParallelDNSOverHTTPSResolver creates a new DNS over HTTPS resolver
Expand All @@ -47,18 +45,18 @@ func NewParallelDNSOverHTTPSResolver(logger model.DebugLogger, URL string) model
return WrapResolver(logger, NewUnwrappedParallelResolver(txp))
}

func (netx *Netx) newUnwrappedStdlibResolver(wrappers ...model.DNSTransportWrapper) model.Resolver {
func (netx *Netx) newUnwrappedStdlibResolver() model.Resolver {
return &resolverSystem{
t: WrapDNSTransport(netx.newDNSOverGetaddrinfoTransport(), wrappers...),
t: WrapDNSTransport(netx.newDNSOverGetaddrinfoTransport()),
}
}

// NewUnwrappedStdlibResolver returns a new, unwrapped resolver using the standard
// library (i.e., getaddrinfo if possible and &net.Resolver{} otherwise). As the name
// implies, this function returns an unwrapped resolver.
func NewUnwrappedStdlibResolver(wrappers ...model.DNSTransportWrapper) model.Resolver {
func NewUnwrappedStdlibResolver() model.Resolver {
netx := &Netx{Underlying: nil}
return netx.newUnwrappedStdlibResolver(wrappers...)
return netx.newUnwrappedStdlibResolver()
}

// NewSerialUDPResolver creates a new Resolver using DNS-over-UDP
Expand All @@ -73,13 +71,9 @@ func NewUnwrappedStdlibResolver(wrappers ...model.DNSTransportWrapper) model.Res
// - dialer is the dialer to create and connect UDP conns
//
// - address is the server address (e.g., 1.1.1.1:53)
//
// - wrappers is the optional list of wrappers to wrap the underlying
// transport. Any nil wrapper will be silently ignored.
func NewSerialUDPResolver(logger model.DebugLogger, dialer model.Dialer,
address string, wrappers ...model.DNSTransportWrapper) model.Resolver {
func NewSerialUDPResolver(logger model.DebugLogger, dialer model.Dialer, address string) model.Resolver {
return WrapResolver(logger, NewUnwrappedSerialResolver(
WrapDNSTransport(NewUnwrappedDNSOverUDPTransport(dialer, address), wrappers...),
WrapDNSTransport(NewUnwrappedDNSOverUDPTransport(dialer, address)),
))
}

Expand All @@ -93,13 +87,10 @@ func NewSerialUDPResolver(logger model.DebugLogger, dialer model.Dialer,
// - dialer is the dialer to create and connect UDP conns
//
// - address is the server address (e.g., 1.1.1.1:53)
//
// - wrappers is the optional list of wrappers to wrap the underlying
// transport. Any nil wrapper will be silently ignored.
func NewParallelUDPResolver(logger model.DebugLogger, dialer model.Dialer,
address string, wrappers ...model.DNSTransportWrapper) model.Resolver {
address string) model.Resolver {
return WrapResolver(logger, NewUnwrappedParallelResolver(
WrapDNSTransport(NewUnwrappedDNSOverUDPTransport(dialer, address), wrappers...),
WrapDNSTransport(NewUnwrappedDNSOverUDPTransport(dialer, address)),
))
}

Expand Down
55 changes: 8 additions & 47 deletions internal/netxlite/resolvercore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,63 +17,24 @@ import (
"github.com/ooni/probe-cli/v3/internal/testingx"
)

type dnsTransportWrapperForTesting struct {
txp model.DNSTransport
}

var _ model.DNSTransport = &dnsTransportWrapperForTesting{}

// Address implements model.DNSTransport.
func (t *dnsTransportWrapperForTesting) Address() string {
return t.txp.Address()
}

// CloseIdleConnections implements model.DNSTransport.
func (t *dnsTransportWrapperForTesting) CloseIdleConnections() {
t.txp.CloseIdleConnections()
}

// Network implements model.DNSTransport.
func (t *dnsTransportWrapperForTesting) Network() string {
return t.txp.Network()
}

// RequiresPadding implements model.DNSTransport.
func (t *dnsTransportWrapperForTesting) RequiresPadding() bool {
return t.txp.RequiresPadding()
}

// RoundTrip implements model.DNSTransport.
func (t *dnsTransportWrapperForTesting) RoundTrip(ctx context.Context, query model.DNSQuery) (model.DNSResponse, error) {
return t.txp.RoundTrip(ctx, query)
}

type dnsTransportWrapperFactoryForTesting struct{}

var _ model.DNSTransportWrapper = &dnsTransportWrapperFactoryForTesting{}

// WrapDNSTransport implements model.DNSTransportWrapper.
func (*dnsTransportWrapperFactoryForTesting) WrapDNSTransport(txp model.DNSTransport) model.DNSTransport {
return &dnsTransportWrapperForTesting{txp}
}

func TestNewResolverSystem(t *testing.T) {
// TODO(bassosimone): we need to extend this test to make sure we honour wrapping.
resolver := NewStdlibResolver(model.DiscardLogger, &dnsTransportWrapperFactoryForTesting{})

func typeCheckForSystemResolver(t *testing.T, resolver model.Resolver, logger model.DebugLogger) {
idna := resolver.(*resolverIDNA)
loggerReso := idna.Resolver.(*resolverLogger)
if loggerReso.Logger != model.DiscardLogger {
if loggerReso.Logger != logger {
t.Fatal("invalid logger")
}
shortCircuit := loggerReso.Resolver.(*resolverShortCircuitIPAddr)
errWrapper := shortCircuit.Resolver.(*resolverErrWrapper)
reso := errWrapper.Resolver.(*resolverSystem)
txpExternal := reso.t.(*dnsTransportWrapperForTesting)
txpErrWrapper := txpExternal.txp.(*dnsTransportErrWrapper)
txpErrWrapper := reso.t.(*dnsTransportErrWrapper)
_ = txpErrWrapper.DNSTransport.(*dnsOverGetaddrinfoTransport)
}

func TestNewResolverSystem(t *testing.T) {
resolver := NewStdlibResolver(model.DiscardLogger)
typeCheckForSystemResolver(t, resolver, model.DiscardLogger)
}

func TestNewSerialUDPResolver(t *testing.T) {
d := NewDialerWithoutResolver(log.Log)
resolver := NewSerialUDPResolver(log.Log, d, "1.1.1.1:53")
Expand Down
2 changes: 1 addition & 1 deletion internal/testingx/tlssniproxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (
// TLSSNIProxyNetx is how [TLSSNIProxy] views [*netxlite.Netx].
type TLSSNIProxyNetx interface {
NewDialerWithResolver(dl model.DebugLogger, r model.Resolver, w ...model.DialerWrapper) model.Dialer
NewStdlibResolver(logger model.DebugLogger, wrappers ...model.DNSTransportWrapper) model.Resolver
NewStdlibResolver(logger model.DebugLogger) model.Resolver
}

// TLSSNIProxy is a proxy using the SNI to figure out where to connect to.
Expand Down

0 comments on commit 3c9d305

Please sign in to comment.