Skip to content

Commit

Permalink
resolver: collect transport's Network and Address
Browse files Browse the repository at this point in the history
These are useful bits of information when filling a measurement
because they allow us to understand what transport is used.

Part of #509
  • Loading branch information
bassosimone committed Apr 22, 2020
1 parent 7027883 commit 31d83e2
Show file tree
Hide file tree
Showing 14 changed files with 104 additions and 8 deletions.
2 changes: 1 addition & 1 deletion experiment/ndt7/dial.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func newDialManager(hostname string, proxyURL *url.URL, logger model.Logger) dia
}

func (mgr dialManager) dialWithTestName(ctx context.Context, testName string) (*websocket.Conn, error) {
var reso resolver.Resolver = new(net.Resolver)
var reso resolver.Resolver = resolver.SystemResolver{}
reso = resolver.LoggingResolver{Resolver: reso, Logger: mgr.logger}
var dlr dialer.Dialer = new(net.Dialer)
dlr = dialer.TimeoutDialer{Dialer: dlr}
Expand Down
2 changes: 2 additions & 0 deletions netx/httptransport/httptransport.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ type RoundTripper interface {
// Resolver is the interface we expect from a resolver
type Resolver interface {
LookupHost(ctx context.Context, hostname string) (addrs []string, err error)
Network() string
Address() string
}

// Config contains configuration for creating a new transport. When any
Expand Down
17 changes: 16 additions & 1 deletion netx/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,25 @@ func NewResolver(network, address string) (modelx.DNSResolver, error) {
return newResolver(time.Now(), handlers.NoHandler, network, address)
}

type chainWrapperResolver struct {
modelx.DNSResolver
}

func (r chainWrapperResolver) Network() string {
return "chain"
}

func (r chainWrapperResolver) Address() string {
return ""
}

// ChainResolvers chains a primary and a secondary resolver such that
// we can fallback to the secondary if primary is broken.
func ChainResolvers(primary, secondary modelx.DNSResolver) modelx.DNSResolver {
return resolver.ChainResolver{Primary: primary, Secondary: secondary}
return resolver.ChainResolver{
Primary: chainWrapperResolver{DNSResolver: primary},
Secondary: chainWrapperResolver{DNSResolver: secondary},
}
}

func resolverWrapResolver(r resolver.Resolver) resolver.EmitterResolver {
Expand Down
10 changes: 10 additions & 0 deletions netx/resolver/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,14 @@ func (c ChainResolver) LookupHost(ctx context.Context, hostname string) ([]strin
return addrs, err
}

// Network implements Resolver.Network
func (c ChainResolver) Network() string {
return "chain"
}

// Address implements Resolver.Address
func (c ChainResolver) Address() string {
return ""
}

var _ Resolver = ChainResolver{}
13 changes: 9 additions & 4 deletions netx/resolver/chain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,23 @@ package resolver_test

import (
"context"
"net"
"testing"

"github.com/ooni/probe-engine/netx/resolver"
)

func TestChainLookupHost(t *testing.T) {
client := resolver.ChainResolver{
r := resolver.ChainResolver{
Primary: resolver.NewFakeResolverThatFails(),
Secondary: new(net.Resolver),
Secondary: resolver.SystemResolver{},
}
addrs, err := client.LookupHost(context.Background(), "www.google.com")
if r.Address() != "" {
t.Fatal("invalid address")
}
if r.Network() != "chain" {
t.Fatal("invalid network")
}
addrs, err := r.LookupHost(context.Background(), "www.google.com")
if err != nil {
t.Fatal(err)
}
Expand Down
8 changes: 8 additions & 0 deletions netx/resolver/fake_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,4 +131,12 @@ func (c FakeResolver) LookupHost(ctx context.Context, hostname string) ([]string
return c.Result, nil
}

func (c FakeResolver) Network() string {
return "fake"
}

func (c FakeResolver) Address() string {
return ""
}

var _ Resolver = FakeResolver{}
6 changes: 6 additions & 0 deletions netx/resolver/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,10 @@ import (
type Resolver interface {
// LookupHost resolves a hostname to a list of IP addresses.
LookupHost(ctx context.Context, hostname string) (addrs []string, err error)

// Network returns the network being used by the resolver
Network() string

// Address returns the address being used by the resolver
Address() string
}
8 changes: 8 additions & 0 deletions netx/resolver/saver.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,22 @@ type SaverResolver struct {
func (r SaverResolver) LookupHost(ctx context.Context, hostname string) ([]string, error) {
start := time.Now()
r.Saver.Write(trace.Event{
Address: r.Resolver.Address(),
Hostname: hostname,
Name: "resolve_start",
Proto: r.Resolver.Network(),
Time: start,
})
addrs, err := r.Resolver.LookupHost(ctx, hostname)
stop := time.Now()
r.Saver.Write(trace.Event{
Addresses: addrs,
Address: r.Resolver.Address(),
Duration: stop.Sub(start),
Err: err,
Hostname: hostname,
Name: "resolve_done",
Proto: r.Resolver.Network(),
Time: stop,
})
return addrs, err
Expand All @@ -44,18 +48,22 @@ type SaverDNSTransport struct {
func (txp SaverDNSTransport) RoundTrip(ctx context.Context, query []byte) ([]byte, error) {
start := time.Now()
txp.Saver.Write(trace.Event{
Address: txp.Address(),
DNSQuery: query,
Name: "dns_round_trip_start",
Proto: txp.Network(),
Time: start,
})
reply, err := txp.RoundTripper.RoundTrip(ctx, query)
stop := time.Now()
txp.Saver.Write(trace.Event{
Address: txp.Address(),
DNSQuery: query,
DNSReply: reply,
Duration: stop.Sub(start),
Err: err,
Name: "dns_round_trip_done",
Proto: txp.Network(),
Time: stop,
})
return reply, err
Expand Down
10 changes: 10 additions & 0 deletions netx/resolver/serial.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@ func (r SerialResolver) Transport() RoundTripper {
return r.Txp
}

// Network implements Resolver.Network
func (r SerialResolver) Network() string {
return r.Txp.Network()
}

// Address implements Resolver.Address
func (r SerialResolver) Address() string {
return r.Txp.Address()
}

// LookupHost implements Resolver.LookupHost.
func (r SerialResolver) LookupHost(ctx context.Context, hostname string) ([]string, error) {
var addrs []string
Expand Down
6 changes: 6 additions & 0 deletions netx/resolver/serial_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ func TestUnitOONIGettingTransport(t *testing.T) {
if rtx.Network() != "dot" || rtx.Address() != "8.8.8.8:853" {
t.Fatal("not the transport we expected")
}
if r.Network() != rtx.Network() {
t.Fatal("invalid network seen from the resolver")
}
if r.Address() != rtx.Address() {
t.Fatal("invalid address seen from the resolver")
}
}

func TestUnitOONIEncodeError(t *testing.T) {
Expand Down
10 changes: 10 additions & 0 deletions netx/resolver/system.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,14 @@ func (r SystemResolver) LookupHost(ctx context.Context, hostname string) ([]stri
return net.DefaultResolver.LookupHost(ctx, hostname)
}

// Network implements Resolver.Network
func (r SystemResolver) Network() string {
return "system"
}

// Address implements Resolver.Address
func (r SystemResolver) Address() string {
return ""
}

var _ Resolver = SystemResolver{}
6 changes: 6 additions & 0 deletions netx/resolver/system_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ import (

func TestIntegrationSystemResolverLookupHost(t *testing.T) {
r := resolver.SystemResolver{}
if r.Network() != "system" {
t.Fatal("invalid Network")
}
if r.Address() != "" {
t.Fatal("invalid Address")
}
addrs, err := r.LookupHost(context.Background(), "dns.google.com")
if err != nil {
t.Fatal(err)
Expand Down
4 changes: 2 additions & 2 deletions netx/resolver_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (
"github.com/ooni/probe-engine/netx/modelx"
)

// NewHTTPClientForDoH exposes the factory function we use internally for
// creating DoH optimised clients to unit tests.
func NewHTTPClientForDoH(beginning time.Time, handler modelx.Handler) *http.Client {
return newHTTPClientForDoH(beginning, handler)
}

type ChainWrapperResolver = chainWrapperResolver
10 changes: 10 additions & 0 deletions netx/resolver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,3 +142,13 @@ func TestUnitNewHTTPClientForDoH(t *testing.T) {
t.Fatal("expected to see different client here")
}
}

func TestUnitChainWrapperResolver(t *testing.T) {
r := netx.ChainWrapperResolver{}
if r.Address() != "" {
t.Fatal("invalid Address")
}
if r.Network() != "chain" {
t.Fatal("invalid Network")
}
}

0 comments on commit 31d83e2

Please sign in to comment.