cleanup: remove unnecessary legacy interfaces (#656)
This diff addresses another point of https://github.com/ooni/probe/issues/1956: > - [ ] observe that we're still using a bunch of private interfaces for common interfaces such as the `Dialer`, so we can get rid of these private interfaces and always use the ones in `model`, which allows us to remove a bunch of legacy wrappers Additional cleanups may still be possible. The more I cleanup, the more I see there's extra legacy code we can dispose of (which seems good?).
This commit is contained in:
parent
1c057d322d
commit
566c6b246a
|
@ -4,20 +4,22 @@ package uncensored
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/experiment/urlgetter"
|
"github.com/ooni/probe-cli/v3/internal/engine/experiment/urlgetter"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx"
|
"github.com/ooni/probe-cli/v3/internal/engine/netx"
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
"github.com/ooni/probe-cli/v3/internal/runtimex"
|
"github.com/ooni/probe-cli/v3/internal/runtimex"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Client is DNS, HTTP, and TCP client.
|
// Client is DNS, HTTP, and TCP client.
|
||||||
type Client struct {
|
type Client struct {
|
||||||
dnsClient *netx.DNSClient
|
dnsClient *netx.DNSClient
|
||||||
httpTransport netx.HTTPRoundTripper
|
httpTransport model.HTTPTransport
|
||||||
dialer netx.Dialer
|
dialer model.Dialer
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClient creates a new Client.
|
// NewClient creates a new Client.
|
||||||
|
@ -48,7 +50,7 @@ func Must(client *Client, err error) *Client {
|
||||||
// DefaultClient is the default client for DNS, HTTP, and TCP.
|
// DefaultClient is the default client for DNS, HTTP, and TCP.
|
||||||
var DefaultClient = Must(NewClient(""))
|
var DefaultClient = Must(NewClient(""))
|
||||||
|
|
||||||
var _ netx.Resolver = DefaultClient
|
var _ model.Resolver = DefaultClient
|
||||||
|
|
||||||
// Address implements netx.Resolver.Address
|
// Address implements netx.Resolver.Address
|
||||||
func (c *Client) Address() string {
|
func (c *Client) Address() string {
|
||||||
|
@ -60,19 +62,24 @@ func (c *Client) LookupHost(ctx context.Context, domain string) ([]string, error
|
||||||
return c.dnsClient.LookupHost(ctx, domain)
|
return c.dnsClient.LookupHost(ctx, domain)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LookupHTTPS implements model.Resolver.LookupHTTPS.
|
||||||
|
func (c *Client) LookupHTTPS(ctx context.Context, domain string) (*model.HTTPSSvc, error) {
|
||||||
|
return nil, errors.New("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
// Network implements netx.Resolver.Network
|
// Network implements netx.Resolver.Network
|
||||||
func (c *Client) Network() string {
|
func (c *Client) Network() string {
|
||||||
return c.dnsClient.Network()
|
return c.dnsClient.Network()
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ netx.Dialer = DefaultClient
|
var _ model.Dialer = DefaultClient
|
||||||
|
|
||||||
// DialContext implements netx.Dialer.DialContext
|
// DialContext implements netx.Dialer.DialContext
|
||||||
func (c *Client) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
|
func (c *Client) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
|
||||||
return c.dialer.DialContext(ctx, network, address)
|
return c.dialer.DialContext(ctx, network, address)
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ netx.HTTPRoundTripper = DefaultClient
|
var _ model.HTTPTransport = DefaultClient
|
||||||
|
|
||||||
// CloseIdleConnections implement netx.HTTPRoundTripper.CloseIdleConnections
|
// CloseIdleConnections implement netx.HTTPRoundTripper.CloseIdleConnections
|
||||||
func (c *Client) CloseIdleConnections() {
|
func (c *Client) CloseIdleConnections() {
|
||||||
|
|
|
@ -2,13 +2,14 @@ package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ooni/probe-cli/v3/internal/atomicx"
|
"github.com/ooni/probe-cli/v3/internal/atomicx"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx"
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -49,7 +50,13 @@ func (c FakeResolver) Address() string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ netx.Resolver = FakeResolver{}
|
func (c FakeResolver) CloseIdleConnections() {}
|
||||||
|
|
||||||
|
func (c FakeResolver) LookupHTTPS(ctx context.Context, domain string) (*model.HTTPSSvc, error) {
|
||||||
|
return nil, errors.New("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ model.Resolver = FakeResolver{}
|
||||||
|
|
||||||
type FakeTransport struct {
|
type FakeTransport struct {
|
||||||
Err error
|
Err error
|
||||||
|
@ -75,7 +82,7 @@ func (txp FakeTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||||
|
|
||||||
func (txp FakeTransport) CloseIdleConnections() {}
|
func (txp FakeTransport) CloseIdleConnections() {}
|
||||||
|
|
||||||
var _ netx.HTTPRoundTripper = FakeTransport{}
|
var _ model.HTTPTransport = FakeTransport{}
|
||||||
|
|
||||||
type FakeBody struct {
|
type FakeBody struct {
|
||||||
Data []byte
|
Data []byte
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/experiment/webstepsx"
|
"github.com/ooni/probe-cli/v3/internal/engine/experiment/webstepsx"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx"
|
"github.com/ooni/probe-cli/v3/internal/engine/netx"
|
||||||
"github.com/ooni/probe-cli/v3/internal/measurex"
|
"github.com/ooni/probe-cli/v3/internal/measurex"
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
"github.com/ooni/probe-cli/v3/internal/runtimex"
|
"github.com/ooni/probe-cli/v3/internal/runtimex"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -21,7 +22,7 @@ var (
|
||||||
ctx, cancel = context.WithCancel(context.Background())
|
ctx, cancel = context.WithCancel(context.Background())
|
||||||
debug = flag.Bool("debug", false, "Toggle debug mode")
|
debug = flag.Bool("debug", false, "Toggle debug mode")
|
||||||
httpClient *http.Client
|
httpClient *http.Client
|
||||||
resolver netx.Resolver
|
resolver model.Resolver
|
||||||
server = flag.String("server", "", "URL of the test helper")
|
server = flag.String("server", "", "URL of the test helper")
|
||||||
target = flag.String("target", "", "Target URL for the test helper")
|
target = flag.String("target", "", "Target URL for the test helper")
|
||||||
fwebsteps = flag.Bool("websteps", false, "Use the websteps TH")
|
fwebsteps = flag.Bool("websteps", false, "Use the websteps TH")
|
||||||
|
|
|
@ -5,8 +5,8 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/experiment/webconnectivity"
|
"github.com/ooni/probe-cli/v3/internal/engine/experiment/webconnectivity"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx"
|
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/archival"
|
"github.com/ooni/probe-cli/v3/internal/engine/netx/archival"
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ type CtrlDNSResult = webconnectivity.ControlDNSResult
|
||||||
type DNSConfig struct {
|
type DNSConfig struct {
|
||||||
Domain string
|
Domain string
|
||||||
Out chan CtrlDNSResult
|
Out chan CtrlDNSResult
|
||||||
Resolver netx.Resolver
|
Resolver model.Resolver
|
||||||
Wg *sync.WaitGroup
|
Wg *sync.WaitGroup
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,13 +2,14 @@ package webconnectivity
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ooni/probe-cli/v3/internal/atomicx"
|
"github.com/ooni/probe-cli/v3/internal/atomicx"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx"
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -49,7 +50,13 @@ func (c FakeResolver) Address() string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ netx.Resolver = FakeResolver{}
|
func (c FakeResolver) CloseIdleConnections() {}
|
||||||
|
|
||||||
|
func (c FakeResolver) LookupHTTPS(ctx context.Context, domain string) (*model.HTTPSSvc, error) {
|
||||||
|
return nil, errors.New("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ model.Resolver = FakeResolver{}
|
||||||
|
|
||||||
type FakeTransport struct {
|
type FakeTransport struct {
|
||||||
Err error
|
Err error
|
||||||
|
@ -75,7 +82,7 @@ func (txp FakeTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||||
|
|
||||||
func (txp FakeTransport) CloseIdleConnections() {}
|
func (txp FakeTransport) CloseIdleConnections() {}
|
||||||
|
|
||||||
var _ netx.HTTPRoundTripper = FakeTransport{}
|
var _ model.HTTPTransport = FakeTransport{}
|
||||||
|
|
||||||
type FakeBody struct {
|
type FakeBody struct {
|
||||||
Data []byte
|
Data []byte
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/experiment/webconnectivity"
|
"github.com/ooni/probe-cli/v3/internal/engine/experiment/webconnectivity"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx"
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
@ -22,9 +22,9 @@ type (
|
||||||
// MeasureConfig contains configuration for Measure.
|
// MeasureConfig contains configuration for Measure.
|
||||||
type MeasureConfig struct {
|
type MeasureConfig struct {
|
||||||
Client *http.Client
|
Client *http.Client
|
||||||
Dialer netx.Dialer
|
Dialer model.Dialer
|
||||||
MaxAcceptableBody int64
|
MaxAcceptableBody int64
|
||||||
Resolver netx.Resolver
|
Resolver model.Resolver
|
||||||
}
|
}
|
||||||
|
|
||||||
// Measure performs the measurement described by the request and
|
// Measure performs the measurement described by the request and
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/experiment/webconnectivity"
|
"github.com/ooni/probe-cli/v3/internal/engine/experiment/webconnectivity"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx"
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ type TCPResultPair struct {
|
||||||
|
|
||||||
// TCPConfig configures the TCP connect check.
|
// TCPConfig configures the TCP connect check.
|
||||||
type TCPConfig struct {
|
type TCPConfig struct {
|
||||||
Dialer netx.Dialer
|
Dialer model.Dialer
|
||||||
Endpoint string
|
Endpoint string
|
||||||
Out chan TCPResultPair
|
Out chan TCPResultPair
|
||||||
Wg *sync.WaitGroup
|
Wg *sync.WaitGroup
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx"
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||||
"github.com/ooni/probe-cli/v3/internal/runtimex"
|
"github.com/ooni/probe-cli/v3/internal/runtimex"
|
||||||
"github.com/ooni/probe-cli/v3/internal/version"
|
"github.com/ooni/probe-cli/v3/internal/version"
|
||||||
|
@ -15,9 +15,9 @@ import (
|
||||||
// Handler implements the Web Connectivity test helper HTTP API.
|
// Handler implements the Web Connectivity test helper HTTP API.
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
Client *http.Client
|
Client *http.Client
|
||||||
Dialer netx.Dialer
|
Dialer model.Dialer
|
||||||
MaxAcceptableBody int64
|
MaxAcceptableBody int64
|
||||||
Resolver netx.Resolver
|
Resolver model.Resolver
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
func (h Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"net"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -52,7 +51,7 @@ const requestWithoutDomainName = `{
|
||||||
func TestWorkingAsIntended(t *testing.T) {
|
func TestWorkingAsIntended(t *testing.T) {
|
||||||
handler := Handler{
|
handler := Handler{
|
||||||
Client: http.DefaultClient,
|
Client: http.DefaultClient,
|
||||||
Dialer: new(net.Dialer),
|
Dialer: netxlite.DefaultDialer,
|
||||||
MaxAcceptableBody: 1 << 24,
|
MaxAcceptableBody: 1 << 24,
|
||||||
Resolver: &netxlite.ResolverSystem{},
|
Resolver: &netxlite.ResolverSystem{},
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
|
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/experiment/websteps"
|
"github.com/ooni/probe-cli/v3/internal/engine/experiment/websteps"
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||||
"github.com/ooni/probe-cli/v3/internal/runtimex"
|
"github.com/ooni/probe-cli/v3/internal/runtimex"
|
||||||
utls "gitlab.com/yawning/utls.git"
|
utls "gitlab.com/yawning/utls.git"
|
||||||
|
@ -28,7 +29,7 @@ type Explorer interface {
|
||||||
|
|
||||||
// DefaultExplorer is the default Explorer.
|
// DefaultExplorer is the default Explorer.
|
||||||
type DefaultExplorer struct {
|
type DefaultExplorer struct {
|
||||||
resolver netxlite.ResolverLegacy
|
resolver model.Resolver
|
||||||
}
|
}
|
||||||
|
|
||||||
// Explore returns a list of round trips sorted so that the first
|
// Explore returns a list of round trips sorted so that the first
|
||||||
|
@ -138,8 +139,7 @@ func (e *DefaultExplorer) getH3(h3URL *h3URL, headers map[string][]string) (*htt
|
||||||
}
|
}
|
||||||
// Rationale for using log.Log here: we're already using log.Log
|
// Rationale for using log.Log here: we're already using log.Log
|
||||||
// in this package, so it seems fair to use it also here
|
// in this package, so it seems fair to use it also here
|
||||||
transport := netxlite.NewHTTP3Transport(log.Log,
|
transport := netxlite.NewHTTP3Transport(log.Log, dialer, tlsConf)
|
||||||
netxlite.NewQUICDialerFromContextDialerAdapter(dialer), tlsConf)
|
|
||||||
// TODO(bassosimone): here we should use runtimex.PanicOnError
|
// TODO(bassosimone): here we should use runtimex.PanicOnError
|
||||||
jarjar, _ := cookiejar.New(nil)
|
jarjar, _ := cookiejar.New(nil)
|
||||||
clnt := &http.Client{
|
clnt := &http.Client{
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
|
|
||||||
"github.com/lucas-clemente/quic-go"
|
"github.com/lucas-clemente/quic-go"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/experiment/websteps"
|
"github.com/ooni/probe-cli/v3/internal/engine/experiment/websteps"
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Generate is the third step of the algorithm. Given the
|
// Generate is the third step of the algorithm. Given the
|
||||||
|
@ -22,9 +22,9 @@ type Generator interface {
|
||||||
|
|
||||||
// DefaultGenerator is the default Generator.
|
// DefaultGenerator is the default Generator.
|
||||||
type DefaultGenerator struct {
|
type DefaultGenerator struct {
|
||||||
dialer netxlite.DialerLegacy
|
dialer model.Dialer
|
||||||
quicDialer netxlite.QUICContextDialer
|
quicDialer model.QUICDialer
|
||||||
resolver netxlite.ResolverLegacy
|
resolver model.Resolver
|
||||||
transport http.RoundTripper
|
transport http.RoundTripper
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,8 @@ func (d fakeQUICDialer) DialContext(ctx context.Context, network, address string
|
||||||
return nil, d.err
|
return nil, d.err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d fakeQUICDialer) CloseIdleConnections() {}
|
||||||
|
|
||||||
type fakeDialer struct {
|
type fakeDialer struct {
|
||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
@ -44,6 +46,8 @@ func (d fakeDialer) DialContext(ctx context.Context, network, address string) (n
|
||||||
return nil, d.err
|
return nil, d.err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d fakeDialer) CloseIdleConnections() {}
|
||||||
|
|
||||||
func TestGenerateDNSFailure(t *testing.T) {
|
func TestGenerateDNSFailure(t *testing.T) {
|
||||||
u, err := url.Parse("https://www.google.google")
|
u, err := url.Parse("https://www.google.google")
|
||||||
runtimex.PanicOnError(err, "url.Parse failed")
|
runtimex.PanicOnError(err, "url.Parse failed")
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
// InitialChecks is the first step of the test helper algorithm. We
|
// InitialChecks is the first step of the test helper algorithm. We
|
||||||
|
@ -31,7 +31,7 @@ type InitChecker interface {
|
||||||
|
|
||||||
// DefaultInitChecker is the default InitChecker.
|
// DefaultInitChecker is the default InitChecker.
|
||||||
type DefaultInitChecker struct {
|
type DefaultInitChecker struct {
|
||||||
resolver netxlite.ResolverLegacy
|
resolver model.Resolver
|
||||||
}
|
}
|
||||||
|
|
||||||
// InitialChecks checks whether the URL is valid and whether the
|
// InitialChecks checks whether the URL is valid and whether the
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/experiment/websteps"
|
"github.com/ooni/probe-cli/v3/internal/engine/experiment/websteps"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx"
|
"github.com/ooni/probe-cli/v3/internal/engine/netx"
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||||
"github.com/ooni/probe-cli/v3/internal/runtimex"
|
"github.com/ooni/probe-cli/v3/internal/runtimex"
|
||||||
)
|
)
|
||||||
|
@ -24,7 +25,7 @@ type Config struct {
|
||||||
checker InitChecker
|
checker InitChecker
|
||||||
explorer Explorer
|
explorer Explorer
|
||||||
generator Generator
|
generator Generator
|
||||||
resolver netxlite.ResolverLegacy
|
resolver model.Resolver
|
||||||
}
|
}
|
||||||
|
|
||||||
// Measure performs the three consecutive steps of the testhelper algorithm:
|
// Measure performs the three consecutive steps of the testhelper algorithm:
|
||||||
|
@ -90,12 +91,10 @@ func newDNSFailedResponse(err error, URL string) *ControlResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
// newResolver creates a new DNS resolver instance
|
// newResolver creates a new DNS resolver instance
|
||||||
func newResolver() netxlite.ResolverLegacy {
|
func newResolver() model.Resolver {
|
||||||
childResolver, err := netx.NewDNSClient(netx.Config{Logger: log.Log}, "doh://google")
|
childResolver, err := netx.NewDNSClient(netx.Config{Logger: log.Log}, "doh://google")
|
||||||
runtimex.PanicOnError(err, "NewDNSClient failed")
|
runtimex.PanicOnError(err, "NewDNSClient failed")
|
||||||
var r netxlite.ResolverLegacy = childResolver
|
var r model.Resolver = childResolver
|
||||||
r = &netxlite.ResolverIDNA{
|
r = &netxlite.ResolverIDNA{Resolver: r}
|
||||||
Resolver: netxlite.NewResolverLegacyAdapter(r),
|
|
||||||
}
|
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,16 +13,17 @@ import (
|
||||||
"github.com/ooni/probe-cli/v3/internal/cmd/oohelperd/internal/websteps"
|
"github.com/ooni/probe-cli/v3/internal/cmd/oohelperd/internal/websteps"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/experiment/webstepsx"
|
"github.com/ooni/probe-cli/v3/internal/engine/experiment/webstepsx"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx"
|
"github.com/ooni/probe-cli/v3/internal/engine/netx"
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
"github.com/ooni/probe-cli/v3/internal/runtimex"
|
"github.com/ooni/probe-cli/v3/internal/runtimex"
|
||||||
)
|
)
|
||||||
|
|
||||||
const maxAcceptableBody = 1 << 24
|
const maxAcceptableBody = 1 << 24
|
||||||
|
|
||||||
var (
|
var (
|
||||||
dialer netx.Dialer
|
dialer model.Dialer
|
||||||
endpoint = flag.String("endpoint", ":8080", "Endpoint where to listen")
|
endpoint = flag.String("endpoint", ":8080", "Endpoint where to listen")
|
||||||
httpx *http.Client
|
httpx *http.Client
|
||||||
resolver netx.Resolver
|
resolver model.Resolver
|
||||||
srvcancel context.CancelFunc
|
srvcancel context.CancelFunc
|
||||||
srvctx context.Context
|
srvctx context.Context
|
||||||
srvwg = new(sync.WaitGroup)
|
srvwg = new(sync.WaitGroup)
|
||||||
|
|
|
@ -286,7 +286,7 @@ func (e *Experiment) OpenReportContext(ctx context.Context) error {
|
||||||
// use custom client to have proper byte accounting
|
// use custom client to have proper byte accounting
|
||||||
httpClient := &http.Client{
|
httpClient := &http.Client{
|
||||||
Transport: &httptransport.ByteCountingTransport{
|
Transport: &httptransport.ByteCountingTransport{
|
||||||
RoundTripper: e.session.httpDefaultTransport, // proxy is OK
|
HTTPTransport: e.session.httpDefaultTransport, // proxy is OK
|
||||||
Counter: e.byteCounter,
|
Counter: e.byteCounter,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -234,7 +234,7 @@ func (m *Measurer) Run(
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Measurer) lookupHost(ctx context.Context, hostname string, r netx.Resolver) ([]string, error) {
|
func (m *Measurer) lookupHost(ctx context.Context, hostname string, r model.Resolver) ([]string, error) {
|
||||||
ctx, cancel := context.WithTimeout(ctx, 20*time.Second)
|
ctx, cancel := context.WithTimeout(ctx, 20*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
return r.LookupHost(ctx, hostname)
|
return r.LookupHost(ctx, hostname)
|
||||||
|
|
|
@ -17,7 +17,6 @@ import (
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/experiment/urlgetter"
|
"github.com/ooni/probe-cli/v3/internal/engine/experiment/urlgetter"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/httpheader"
|
"github.com/ooni/probe-cli/v3/internal/engine/httpheader"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/archival"
|
"github.com/ooni/probe-cli/v3/internal/engine/netx/archival"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/dialer"
|
|
||||||
"github.com/ooni/probe-cli/v3/internal/model"
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||||
"github.com/ooni/probe-cli/v3/internal/randx"
|
"github.com/ooni/probe-cli/v3/internal/randx"
|
||||||
|
@ -311,7 +310,7 @@ type JSONHeaders struct {
|
||||||
// guarantee that the connection is used for a single request and that
|
// guarantee that the connection is used for a single request and that
|
||||||
// such a request does not contain any body.
|
// such a request does not contain any body.
|
||||||
type Dialer struct {
|
type Dialer struct {
|
||||||
Dialer dialer.Dialer // used for testing
|
Dialer model.SimpleDialer // used for testing
|
||||||
Headers map[string]string
|
Headers map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,8 @@ func (d FakeDialer) DialContext(ctx context.Context, network, address string) (n
|
||||||
return d.Conn, d.Err
|
return d.Conn, d.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d FakeDialer) CloseIdleConnections() {}
|
||||||
|
|
||||||
type FakeConn struct {
|
type FakeConn struct {
|
||||||
ReadError error
|
ReadError error
|
||||||
ReadData []byte
|
ReadData []byte
|
||||||
|
|
|
@ -251,7 +251,7 @@ func (meth squidCacheManager) Run(ctx context.Context, config MethodConfig) {
|
||||||
type RunMethodConfig struct {
|
type RunMethodConfig struct {
|
||||||
MethodConfig
|
MethodConfig
|
||||||
Name string
|
Name string
|
||||||
NewDialer func(config netx.Config) netx.Dialer
|
NewDialer func(config netx.Config) model.Dialer
|
||||||
RequestLine string
|
RequestLine string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -388,7 +388,7 @@ func TestRunMethodDialFailure(t *testing.T) {
|
||||||
Out: out,
|
Out: out,
|
||||||
},
|
},
|
||||||
Name: "random_invalid_version_number",
|
Name: "random_invalid_version_number",
|
||||||
NewDialer: func(config netx.Config) netx.Dialer {
|
NewDialer: func(config netx.Config) model.Dialer {
|
||||||
return FakeDialer{Err: expected}
|
return FakeDialer{Err: expected}
|
||||||
},
|
},
|
||||||
RequestLine: "GET / HTTP/ABC",
|
RequestLine: "GET / HTTP/ABC",
|
||||||
|
@ -435,7 +435,7 @@ func TestRunMethodSetDeadlineFailure(t *testing.T) {
|
||||||
Out: out,
|
Out: out,
|
||||||
},
|
},
|
||||||
Name: "random_invalid_version_number",
|
Name: "random_invalid_version_number",
|
||||||
NewDialer: func(config netx.Config) netx.Dialer {
|
NewDialer: func(config netx.Config) model.Dialer {
|
||||||
return FakeDialer{Conn: &FakeConn{
|
return FakeDialer{Conn: &FakeConn{
|
||||||
SetDeadlineError: expected,
|
SetDeadlineError: expected,
|
||||||
}}
|
}}
|
||||||
|
@ -484,7 +484,7 @@ func TestRunMethodWriteFailure(t *testing.T) {
|
||||||
Out: out,
|
Out: out,
|
||||||
},
|
},
|
||||||
Name: "random_invalid_version_number",
|
Name: "random_invalid_version_number",
|
||||||
NewDialer: func(config netx.Config) netx.Dialer {
|
NewDialer: func(config netx.Config) model.Dialer {
|
||||||
return FakeDialer{Conn: &FakeConn{
|
return FakeDialer{Conn: &FakeConn{
|
||||||
WriteError: expected,
|
WriteError: expected,
|
||||||
}}
|
}}
|
||||||
|
@ -532,7 +532,7 @@ func TestRunMethodReadEOFWithWrongData(t *testing.T) {
|
||||||
Out: out,
|
Out: out,
|
||||||
},
|
},
|
||||||
Name: "random_invalid_version_number",
|
Name: "random_invalid_version_number",
|
||||||
NewDialer: func(config netx.Config) netx.Dialer {
|
NewDialer: func(config netx.Config) model.Dialer {
|
||||||
return FakeDialer{Conn: &FakeConn{
|
return FakeDialer{Conn: &FakeConn{
|
||||||
ReadData: []byte("0xdeadbeef"),
|
ReadData: []byte("0xdeadbeef"),
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -8,7 +8,6 @@ import (
|
||||||
|
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/dialer"
|
"github.com/ooni/probe-cli/v3/internal/engine/netx/dialer"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/resolver"
|
|
||||||
"github.com/ooni/probe-cli/v3/internal/model"
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||||
)
|
)
|
||||||
|
@ -34,9 +33,9 @@ func newDialManager(ndt7URL string, logger model.Logger, userAgent string) dialM
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mgr dialManager) dialWithTestName(ctx context.Context, testName string) (*websocket.Conn, error) {
|
func (mgr dialManager) dialWithTestName(ctx context.Context, testName string) (*websocket.Conn, error) {
|
||||||
var reso resolver.Resolver = &netxlite.ResolverSystem{}
|
var reso model.Resolver = &netxlite.ResolverSystem{}
|
||||||
reso = &netxlite.ResolverLogger{
|
reso = &netxlite.ResolverLogger{
|
||||||
Resolver: netxlite.NewResolverLegacyAdapter(reso),
|
Resolver: reso,
|
||||||
Logger: mgr.logger,
|
Logger: mgr.logger,
|
||||||
}
|
}
|
||||||
dlr := dialer.New(&dialer.Config{
|
dlr := dialer.New(&dialer.Config{
|
||||||
|
|
|
@ -13,7 +13,6 @@ import (
|
||||||
|
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx"
|
"github.com/ooni/probe-cli/v3/internal/engine/netx"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/archival"
|
"github.com/ooni/probe-cli/v3/internal/engine/netx/archival"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/dialer"
|
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||||
"github.com/ooni/probe-cli/v3/internal/model"
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||||
|
@ -134,7 +133,7 @@ func (tk *TestKeys) run(
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tk *TestKeys) do(
|
func (tk *TestKeys) do(
|
||||||
ctx context.Context, config Config, dialer dialer.Dialer, endpoint string) error {
|
ctx context.Context, config Config, dialer model.Dialer, endpoint string) error {
|
||||||
dialContext := dialer.DialContext
|
dialContext := dialer.DialContext
|
||||||
if config.dialContext != nil {
|
if config.dialContext != nil {
|
||||||
dialContext = config.dialContext
|
dialContext = config.dialContext
|
||||||
|
|
|
@ -5,14 +5,14 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx"
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Dialer creates net.Conn instances where (1) we delay writes if
|
// Dialer creates net.Conn instances where (1) we delay writes if
|
||||||
// a delay is configured and (2) we split outgoing buffers if there
|
// a delay is configured and (2) we split outgoing buffers if there
|
||||||
// is a configured splitter function.
|
// is a configured splitter function.
|
||||||
type Dialer struct {
|
type Dialer struct {
|
||||||
netx.Dialer
|
model.Dialer
|
||||||
Delay time.Duration
|
Delay time.Duration
|
||||||
Splitter func([]byte) [][]byte
|
Splitter func([]byte) [][]byte
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,8 @@ func (d FakeDialer) DialContext(ctx context.Context, network, address string) (n
|
||||||
return d.Conn, d.Err
|
return d.Conn, d.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d FakeDialer) CloseIdleConnections() {}
|
||||||
|
|
||||||
type FakeConn struct {
|
type FakeConn struct {
|
||||||
ReadError error
|
ReadError error
|
||||||
ReadData []byte
|
ReadData []byte
|
||||||
|
|
|
@ -4,12 +4,12 @@ package internal
|
||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx"
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DialerConfig contains the config for creating a dialer
|
// DialerConfig contains the config for creating a dialer
|
||||||
type DialerConfig struct {
|
type DialerConfig struct {
|
||||||
Dialer netx.Dialer
|
Dialer model.Dialer
|
||||||
Delay time.Duration
|
Delay time.Duration
|
||||||
SNI string
|
SNI string
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
|
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/experiment/tlstool/internal"
|
"github.com/ooni/probe-cli/v3/internal/engine/experiment/tlstool/internal"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx"
|
"github.com/ooni/probe-cli/v3/internal/engine/netx"
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
var config = internal.DialerConfig{
|
var config = internal.DialerConfig{
|
||||||
|
@ -14,7 +15,7 @@ var config = internal.DialerConfig{
|
||||||
SNI: "dns.google",
|
SNI: "dns.google",
|
||||||
}
|
}
|
||||||
|
|
||||||
func dial(t *testing.T, d netx.Dialer) {
|
func dial(t *testing.T, d model.Dialer) {
|
||||||
td := netx.NewTLSDialer(netx.Config{Dialer: d})
|
td := netx.NewTLSDialer(netx.Config{Dialer: d})
|
||||||
conn, err := td.DialTLSContext(context.Background(), "tcp", "dns.google:853")
|
conn, err := td.DialTLSContext(context.Background(), "tcp", "dns.google:853")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -107,7 +107,7 @@ func (m Measurer) Run(
|
||||||
return nil // return nil so we always submit the measurement
|
return nil // return nil so we always submit the measurement
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m Measurer) newDialer(logger model.Logger) netx.Dialer {
|
func (m Measurer) newDialer(logger model.Logger) model.Dialer {
|
||||||
// TODO(bassosimone): this is a resolver that should hopefully work
|
// TODO(bassosimone): this is a resolver that should hopefully work
|
||||||
// in many places. Maybe allow to configure it?
|
// in many places. Maybe allow to configure it?
|
||||||
resolver, err := netx.NewDNSClientWithOverrides(netx.Config{Logger: logger},
|
resolver, err := netx.NewDNSClientWithOverrides(netx.Config{Logger: logger},
|
||||||
|
|
|
@ -5,13 +5,14 @@ import (
|
||||||
|
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx"
|
"github.com/ooni/probe-cli/v3/internal/engine/netx"
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||||
"github.com/ooni/probe-cli/v3/internal/runtimex"
|
"github.com/ooni/probe-cli/v3/internal/runtimex"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DNSConfig struct {
|
type DNSConfig struct {
|
||||||
Domain string
|
Domain string
|
||||||
Resolver netxlite.ResolverLegacy
|
Resolver model.Resolver
|
||||||
}
|
}
|
||||||
|
|
||||||
// DNSDo performs the DNS check.
|
// DNSDo performs the DNS check.
|
||||||
|
@ -22,7 +23,7 @@ func DNSDo(ctx context.Context, config DNSConfig) ([]string, error) {
|
||||||
runtimex.PanicOnError(err, "NewDNSClient failed")
|
runtimex.PanicOnError(err, "NewDNSClient failed")
|
||||||
resolver = childResolver
|
resolver = childResolver
|
||||||
resolver = &netxlite.ResolverIDNA{
|
resolver = &netxlite.ResolverIDNA{
|
||||||
Resolver: netxlite.NewResolverLegacyAdapter(resolver),
|
Resolver: resolver,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return resolver.LookupHost(ctx, config.Domain)
|
return resolver.LookupHost(ctx, config.Domain)
|
||||||
|
|
|
@ -32,11 +32,11 @@ func NewRequest(ctx context.Context, URL *url.URL, headers http.Header) *http.Re
|
||||||
|
|
||||||
// NewDialerResolver contructs a new dialer for TCP connections,
|
// NewDialerResolver contructs a new dialer for TCP connections,
|
||||||
// with default, errorwrapping and resolve functionalities
|
// with default, errorwrapping and resolve functionalities
|
||||||
func NewDialerResolver(resolver netxlite.ResolverLegacy) model.Dialer {
|
func NewDialerResolver(resolver model.Resolver) model.Dialer {
|
||||||
var d model.Dialer = netxlite.DefaultDialer
|
var d model.Dialer = netxlite.DefaultDialer
|
||||||
d = &netxlite.ErrorWrapperDialer{Dialer: d}
|
d = &netxlite.ErrorWrapperDialer{Dialer: d}
|
||||||
d = &netxlite.DialerResolver{
|
d = &netxlite.DialerResolver{
|
||||||
Resolver: netxlite.NewResolverLegacyAdapter(resolver),
|
Resolver: resolver,
|
||||||
Dialer: d,
|
Dialer: d,
|
||||||
}
|
}
|
||||||
return d
|
return d
|
||||||
|
@ -44,7 +44,7 @@ func NewDialerResolver(resolver netxlite.ResolverLegacy) model.Dialer {
|
||||||
|
|
||||||
// NewQUICDialerResolver creates a new QUICDialerResolver
|
// NewQUICDialerResolver creates a new QUICDialerResolver
|
||||||
// with default, errorwrapping and resolve functionalities
|
// with default, errorwrapping and resolve functionalities
|
||||||
func NewQUICDialerResolver(resolver netxlite.ResolverLegacy) model.QUICDialer {
|
func NewQUICDialerResolver(resolver model.Resolver) model.QUICDialer {
|
||||||
var ql model.QUICListener = &netxlite.QUICListenerStdlib{}
|
var ql model.QUICListener = &netxlite.QUICListenerStdlib{}
|
||||||
ql = &netxlite.ErrorWrapperQUICListener{QUICListener: ql}
|
ql = &netxlite.ErrorWrapperQUICListener{QUICListener: ql}
|
||||||
var dialer model.QUICDialer = &netxlite.QUICDialerQUICGo{
|
var dialer model.QUICDialer = &netxlite.QUICDialerQUICGo{
|
||||||
|
@ -52,7 +52,7 @@ func NewQUICDialerResolver(resolver netxlite.ResolverLegacy) model.QUICDialer {
|
||||||
}
|
}
|
||||||
dialer = &netxlite.ErrorWrapperQUICDialer{QUICDialer: dialer}
|
dialer = &netxlite.ErrorWrapperQUICDialer{QUICDialer: dialer}
|
||||||
dialer = &netxlite.QUICDialerResolver{
|
dialer = &netxlite.QUICDialerResolver{
|
||||||
Resolver: netxlite.NewResolverLegacyAdapter(resolver),
|
Resolver: resolver,
|
||||||
Dialer: dialer,
|
Dialer: dialer,
|
||||||
}
|
}
|
||||||
return dialer
|
return dialer
|
||||||
|
@ -79,12 +79,12 @@ func NewSingleTransport(conn net.Conn) http.RoundTripper {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSingleTransport creates a new HTTP transport with a custom dialer and handshaker.
|
// NewSingleTransport creates a new HTTP transport with a custom dialer and handshaker.
|
||||||
func NewTransportWithDialer(dialer netxlite.DialerLegacy, tlsConfig *tls.Config, handshaker model.TLSHandshaker) http.RoundTripper {
|
func NewTransportWithDialer(dialer model.Dialer, tlsConfig *tls.Config, handshaker model.TLSHandshaker) http.RoundTripper {
|
||||||
transport := newBaseTransport()
|
transport := newBaseTransport()
|
||||||
transport.DialContext = dialer.DialContext
|
transport.DialContext = dialer.DialContext
|
||||||
transport.DialTLSContext = (&netxlite.TLSDialerLegacy{
|
transport.DialTLSContext = (&netxlite.TLSDialerLegacy{
|
||||||
Config: tlsConfig,
|
Config: tlsConfig,
|
||||||
Dialer: netxlite.NewDialerLegacyAdapter(dialer),
|
Dialer: dialer,
|
||||||
TLSHandshaker: handshaker,
|
TLSHandshaker: handshaker,
|
||||||
}).DialTLSContext
|
}).DialTLSContext
|
||||||
return transport
|
return transport
|
||||||
|
|
|
@ -5,13 +5,14 @@ import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
|
|
||||||
"github.com/lucas-clemente/quic-go"
|
"github.com/lucas-clemente/quic-go"
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||||
)
|
)
|
||||||
|
|
||||||
type QUICConfig struct {
|
type QUICConfig struct {
|
||||||
Endpoint string
|
Endpoint string
|
||||||
QUICDialer netxlite.QUICContextDialer
|
QUICDialer model.QUICDialer
|
||||||
Resolver netxlite.ResolverLegacy
|
Resolver model.Resolver
|
||||||
TLSConf *tls.Config
|
TLSConf *tls.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,13 +4,14 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TCPConfig struct {
|
type TCPConfig struct {
|
||||||
Dialer netxlite.DialerLegacy
|
Dialer model.Dialer
|
||||||
Endpoint string
|
Endpoint string
|
||||||
Resolver netxlite.ResolverLegacy
|
Resolver model.Resolver
|
||||||
}
|
}
|
||||||
|
|
||||||
// TCPDo performs the TCP check.
|
// TCPDo performs the TCP check.
|
||||||
|
|
|
@ -89,19 +89,12 @@ type resolverIPLookupper interface {
|
||||||
LookupResolverIP(ctx context.Context) (addr string, err error)
|
LookupResolverIP(ctx context.Context) (addr string, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolver is a DNS resolver.
|
|
||||||
type Resolver interface {
|
|
||||||
LookupHost(ctx context.Context, domain string) ([]string, error)
|
|
||||||
Network() string
|
|
||||||
Address() string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Config contains configuration for a geolocate Task.
|
// Config contains configuration for a geolocate Task.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
// Resolver is the resolver we should use when
|
// Resolver is the resolver we should use when
|
||||||
// making requests for discovering the IP. When
|
// making requests for discovering the IP. When
|
||||||
// this field is not set, we use the stdlib.
|
// this field is not set, we use the stdlib.
|
||||||
Resolver Resolver
|
Resolver model.Resolver
|
||||||
|
|
||||||
// Logger is the logger to use. If not set, then we will
|
// Logger is the logger to use. If not set, then we will
|
||||||
// use a logger that discards all messages.
|
// use a logger that discards all messages.
|
||||||
|
|
|
@ -65,7 +65,7 @@ var (
|
||||||
|
|
||||||
type ipLookupClient struct {
|
type ipLookupClient struct {
|
||||||
// Resolver is the resolver to use for HTTP.
|
// Resolver is the resolver to use for HTTP.
|
||||||
Resolver Resolver
|
Resolver model.Resolver
|
||||||
|
|
||||||
// Logger is the logger to use
|
// Logger is the logger to use
|
||||||
Logger model.Logger
|
Logger model.Logger
|
||||||
|
|
|
@ -110,6 +110,11 @@ func (r *Resolver) Stats() string {
|
||||||
return fmt.Sprintf("sessionresolver: %s", string(data))
|
return fmt.Sprintf("sessionresolver: %s", string(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LookupHTTPS implements Resolver.LookupHTTPS.
|
||||||
|
func (r *Resolver) LookupHTTPS(ctx context.Context, domain string) (*model.HTTPSSvc, error) {
|
||||||
|
return nil, errors.New("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
// ErrLookupHost indicates that LookupHost failed.
|
// ErrLookupHost indicates that LookupHost failed.
|
||||||
var ErrLookupHost = errors.New("sessionresolver: LookupHost failed")
|
var ErrLookupHost = errors.New("sessionresolver: LookupHost failed")
|
||||||
|
|
||||||
|
|
|
@ -5,12 +5,13 @@ import (
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"github.com/ooni/probe-cli/v3/internal/bytecounter"
|
"github.com/ooni/probe-cli/v3/internal/bytecounter"
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
// byteCounterDialer is a byte-counting-aware dialer. To perform byte counting, you
|
// byteCounterDialer is a byte-counting-aware dialer. To perform byte counting, you
|
||||||
// should make sure that you insert this dialer in the dialing chain.
|
// should make sure that you insert this dialer in the dialing chain.
|
||||||
type byteCounterDialer struct {
|
type byteCounterDialer struct {
|
||||||
Dialer
|
model.Dialer
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialContext implements Dialer.DialContext
|
// DialContext implements Dialer.DialContext
|
||||||
|
|
|
@ -16,7 +16,7 @@ import (
|
||||||
func dorequest(ctx context.Context, url string) error {
|
func dorequest(ctx context.Context, url string) error {
|
||||||
txp := http.DefaultTransport.(*http.Transport).Clone()
|
txp := http.DefaultTransport.(*http.Transport).Clone()
|
||||||
defer txp.CloseIdleConnections()
|
defer txp.CloseIdleConnections()
|
||||||
dialer := &byteCounterDialer{Dialer: new(net.Dialer)}
|
dialer := &byteCounterDialer{Dialer: netxlite.DefaultDialer}
|
||||||
txp.DialContext = dialer.DialContext
|
txp.DialContext = dialer.DialContext
|
||||||
client := &http.Client{Transport: txp}
|
client := &http.Client{Transport: txp}
|
||||||
req, err := http.NewRequestWithContext(ctx, "GET", "http://www.google.com", nil)
|
req, err := http.NewRequestWithContext(ctx, "GET", "http://www.google.com", nil)
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package dialer
|
package dialer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"net"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||||
|
@ -10,18 +8,6 @@ import (
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Dialer establishes network connections.
|
|
||||||
type Dialer interface {
|
|
||||||
// DialContext behaves like net.Dialer.DialContext.
|
|
||||||
DialContext(ctx context.Context, network, address string) (net.Conn, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resolver is the interface we expect from a DNS resolver.
|
|
||||||
type Resolver interface {
|
|
||||||
// LookupHost behaves like net.Resolver.LookupHost.
|
|
||||||
LookupHost(ctx context.Context, hostname string) (addrs []string, err error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Config contains the settings for New.
|
// Config contains the settings for New.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
// ContextByteCounting optionally configures context-based
|
// ContextByteCounting optionally configures context-based
|
||||||
|
@ -59,11 +45,11 @@ type Config struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new Dialer from the specified config and resolver.
|
// New creates a new Dialer from the specified config and resolver.
|
||||||
func New(config *Config, resolver Resolver) Dialer {
|
func New(config *Config, resolver model.Resolver) model.Dialer {
|
||||||
var d Dialer = &netxlite.ErrorWrapperDialer{Dialer: netxlite.DefaultDialer}
|
var d model.Dialer = &netxlite.ErrorWrapperDialer{Dialer: netxlite.DefaultDialer}
|
||||||
if config.Logger != nil {
|
if config.Logger != nil {
|
||||||
d = &netxlite.DialerLogger{
|
d = &netxlite.DialerLogger{
|
||||||
Dialer: netxlite.NewDialerLegacyAdapter(d),
|
Dialer: d,
|
||||||
DebugLogger: config.Logger,
|
DebugLogger: config.Logger,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,8 +60,8 @@ func New(config *Config, resolver Resolver) Dialer {
|
||||||
d = &saverConnDialer{Dialer: d, Saver: config.ReadWriteSaver}
|
d = &saverConnDialer{Dialer: d, Saver: config.ReadWriteSaver}
|
||||||
}
|
}
|
||||||
d = &netxlite.DialerResolver{
|
d = &netxlite.DialerResolver{
|
||||||
Resolver: netxlite.NewResolverLegacyAdapter(resolver),
|
Resolver: resolver,
|
||||||
Dialer: netxlite.NewDialerLegacyAdapter(d),
|
Dialer: d,
|
||||||
}
|
}
|
||||||
d = &proxyDialer{ProxyURL: config.ProxyURL, Dialer: d}
|
d = &proxyDialer{ProxyURL: config.ProxyURL, Dialer: d}
|
||||||
if config.ContextByteCounting {
|
if config.ContextByteCounting {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package dialer
|
package dialer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
@ -18,7 +17,7 @@ func TestNewCreatesTheExpectedChain(t *testing.T) {
|
||||||
Logger: log.Log,
|
Logger: log.Log,
|
||||||
ProxyURL: &url.URL{},
|
ProxyURL: &url.URL{},
|
||||||
ReadWriteSaver: saver,
|
ReadWriteSaver: saver,
|
||||||
}, &net.Resolver{})
|
}, netxlite.DefaultResolver)
|
||||||
shd, ok := dlr.(*shapingDialer)
|
shd, ok := dlr.(*shapingDialer)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not a shapingDialer")
|
t.Fatal("not a shapingDialer")
|
||||||
|
@ -35,11 +34,7 @@ func TestNewCreatesTheExpectedChain(t *testing.T) {
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not a dnsDialer")
|
t.Fatal("not a dnsDialer")
|
||||||
}
|
}
|
||||||
dad, ok := dnsd.Dialer.(*netxlite.DialerLegacyAdapter)
|
scd, ok := dnsd.Dialer.(*saverConnDialer)
|
||||||
if !ok {
|
|
||||||
t.Fatal("invalid type")
|
|
||||||
}
|
|
||||||
scd, ok := dad.DialerLegacy.(*saverConnDialer)
|
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not a saverConnDialer")
|
t.Fatal("not a saverConnDialer")
|
||||||
}
|
}
|
||||||
|
@ -51,11 +46,7 @@ func TestNewCreatesTheExpectedChain(t *testing.T) {
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not a loggingDialer")
|
t.Fatal("not a loggingDialer")
|
||||||
}
|
}
|
||||||
dad, ok = ld.Dialer.(*netxlite.DialerLegacyAdapter)
|
ewd, ok := ld.Dialer.(*netxlite.ErrorWrapperDialer)
|
||||||
if !ok {
|
|
||||||
t.Fatal("invalid type")
|
|
||||||
}
|
|
||||||
ewd, ok := dad.DialerLegacy.(*netxlite.ErrorWrapperDialer)
|
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not an errorWrappingDialer")
|
t.Fatal("not an errorWrappingDialer")
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,11 @@ package dialer_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/dialer"
|
"github.com/ooni/probe-cli/v3/internal/engine/netx/dialer"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Example() {
|
func Example() {
|
||||||
|
@ -16,7 +16,7 @@ func Example() {
|
||||||
DialSaver: saver,
|
DialSaver: saver,
|
||||||
Logger: log.Log,
|
Logger: log.Log,
|
||||||
ReadWriteSaver: saver,
|
ReadWriteSaver: saver,
|
||||||
}, &net.Resolver{})
|
}, netxlite.DefaultResolver)
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
conn, err := dlr.DialContext(ctx, "tcp", "8.8.8.8:53")
|
conn, err := dlr.DialContext(ctx, "tcp", "8.8.8.8:53")
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
package dialer_test
|
package dialer_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/dialer"
|
"github.com/ooni/probe-cli/v3/internal/engine/netx/dialer"
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDialerNewSuccess(t *testing.T) {
|
func TestDialerNewSuccess(t *testing.T) {
|
||||||
|
@ -14,7 +14,7 @@ func TestDialerNewSuccess(t *testing.T) {
|
||||||
t.Skip("skip test in short mode")
|
t.Skip("skip test in short mode")
|
||||||
}
|
}
|
||||||
log.SetLevel(log.DebugLevel)
|
log.SetLevel(log.DebugLevel)
|
||||||
d := dialer.New(&dialer.Config{Logger: log.Log}, &net.Resolver{})
|
d := dialer.New(&dialer.Config{Logger: log.Log}, netxlite.DefaultResolver)
|
||||||
txp := &http.Transport{DialContext: d.DialContext}
|
txp := &http.Transport{DialContext: d.DialContext}
|
||||||
client := &http.Client{Transport: txp}
|
client := &http.Client{Transport: txp}
|
||||||
resp, err := client.Get("http://www.google.com")
|
resp, err := client.Get("http://www.google.com")
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
"golang.org/x/net/proxy"
|
"golang.org/x/net/proxy"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -13,7 +14,7 @@ import (
|
||||||
// dialer is a passthrough for the next Dialer in chain. Otherwise, it will internally
|
// dialer is a passthrough for the next Dialer in chain. Otherwise, it will internally
|
||||||
// create a SOCKS5 dialer that will connect to the proxy using the underlying Dialer.
|
// create a SOCKS5 dialer that will connect to the proxy using the underlying Dialer.
|
||||||
type proxyDialer struct {
|
type proxyDialer struct {
|
||||||
Dialer
|
model.Dialer
|
||||||
ProxyURL *url.URL
|
ProxyURL *url.URL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +48,7 @@ func (d *proxyDialer) dial(
|
||||||
//
|
//
|
||||||
// See https://git.io/JfJ4g.
|
// See https://git.io/JfJ4g.
|
||||||
type proxyDialerWrapper struct {
|
type proxyDialerWrapper struct {
|
||||||
Dialer
|
model.Dialer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *proxyDialerWrapper) Dial(network, address string) (net.Conn, error) {
|
func (d *proxyDialerWrapper) Dial(network, address string) (net.Conn, error) {
|
||||||
|
|
|
@ -6,12 +6,13 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||||
)
|
)
|
||||||
|
|
||||||
// saverDialer saves events occurring during the dial
|
// saverDialer saves events occurring during the dial
|
||||||
type saverDialer struct {
|
type saverDialer struct {
|
||||||
Dialer
|
model.Dialer
|
||||||
Saver *trace.Saver
|
Saver *trace.Saver
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +35,7 @@ func (d *saverDialer) DialContext(ctx context.Context, network, address string)
|
||||||
// saverConnDialer wraps the returned connection such that we
|
// saverConnDialer wraps the returned connection such that we
|
||||||
// collect all the read/write events that occur.
|
// collect all the read/write events that occur.
|
||||||
type saverConnDialer struct {
|
type saverConnDialer struct {
|
||||||
Dialer
|
model.Dialer
|
||||||
Saver *trace.Saver
|
Saver *trace.Saver
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,6 +83,6 @@ func (c *saverConn) Write(p []byte) (int, error) {
|
||||||
return count, err
|
return count, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ Dialer = &saverDialer{}
|
var _ model.Dialer = &saverDialer{}
|
||||||
var _ Dialer = &saverConnDialer{}
|
var _ model.Dialer = &saverConnDialer{}
|
||||||
var _ net.Conn = &saverConn{}
|
var _ net.Conn = &saverConn{}
|
||||||
|
|
|
@ -6,13 +6,15 @@ package dialer
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
// shapingDialer ensures we don't use too much bandwidth
|
// shapingDialer ensures we don't use too much bandwidth
|
||||||
// when using integration tests at GitHub. To select
|
// when using integration tests at GitHub. To select
|
||||||
// the implementation with shaping use `-tags shaping`.
|
// the implementation with shaping use `-tags shaping`.
|
||||||
type shapingDialer struct {
|
type shapingDialer struct {
|
||||||
Dialer
|
model.Dialer
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialContext implements Dialer.DialContext
|
// DialContext implements Dialer.DialContext
|
||||||
|
|
|
@ -7,13 +7,15 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
// shapingDialer ensures we don't use too much bandwidth
|
// shapingDialer ensures we don't use too much bandwidth
|
||||||
// when using integration tests at GitHub. To select
|
// when using integration tests at GitHub. To select
|
||||||
// the implementation with shaping use `-tags shaping`.
|
// the implementation with shaping use `-tags shaping`.
|
||||||
type shapingDialer struct {
|
type shapingDialer struct {
|
||||||
Dialer
|
model.Dialer
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialContext implements Dialer.DialContext
|
// DialContext implements Dialer.DialContext
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
package dialer
|
package dialer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestShapingDialerGood(t *testing.T) {
|
func TestShapingDialerGood(t *testing.T) {
|
||||||
d := &shapingDialer{Dialer: &net.Dialer{}}
|
d := &shapingDialer{Dialer: netxlite.DefaultDialer}
|
||||||
txp := &http.Transport{DialContext: d.DialContext}
|
txp := &http.Transport{DialContext: d.DialContext}
|
||||||
client := &http.Client{Transport: txp}
|
client := &http.Client{Transport: txp}
|
||||||
resp, err := client.Get("https://www.google.com/")
|
resp, err := client.Get("https://www.google.com/")
|
||||||
|
|
|
@ -19,6 +19,8 @@ func (d FakeDialer) DialContext(ctx context.Context, network, address string) (n
|
||||||
return d.Conn, d.Err
|
return d.Conn, d.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d FakeDialer) CloseIdleConnections() {}
|
||||||
|
|
||||||
type FakeTransport struct {
|
type FakeTransport struct {
|
||||||
Err error
|
Err error
|
||||||
Func func(*http.Request) (*http.Response, error)
|
Func func(*http.Request) (*http.Response, error)
|
||||||
|
|
|
@ -5,11 +5,12 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/ooni/probe-cli/v3/internal/bytecounter"
|
"github.com/ooni/probe-cli/v3/internal/bytecounter"
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ByteCountingTransport is a RoundTripper that counts bytes.
|
// ByteCountingTransport is a RoundTripper that counts bytes.
|
||||||
type ByteCountingTransport struct {
|
type ByteCountingTransport struct {
|
||||||
RoundTripper
|
model.HTTPTransport
|
||||||
Counter *bytecounter.Counter
|
Counter *bytecounter.Counter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +21,7 @@ func (txp ByteCountingTransport) RoundTrip(req *http.Request) (*http.Response, e
|
||||||
ReadCloser: req.Body, Account: txp.Counter.CountBytesSent}
|
ReadCloser: req.Body, Account: txp.Counter.CountBytesSent}
|
||||||
}
|
}
|
||||||
txp.estimateRequestMetadata(req)
|
txp.estimateRequestMetadata(req)
|
||||||
resp, err := txp.RoundTripper.RoundTrip(req)
|
resp, err := txp.HTTPTransport.RoundTrip(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -70,4 +71,4 @@ func (r byteCountingBody) Read(p []byte) (int, error) {
|
||||||
return count, err
|
return count, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ RoundTripper = ByteCountingTransport{}
|
var _ model.HTTPTransport = ByteCountingTransport{}
|
||||||
|
|
|
@ -17,7 +17,7 @@ func TestByteCounterFailure(t *testing.T) {
|
||||||
counter := bytecounter.New()
|
counter := bytecounter.New()
|
||||||
txp := httptransport.ByteCountingTransport{
|
txp := httptransport.ByteCountingTransport{
|
||||||
Counter: counter,
|
Counter: counter,
|
||||||
RoundTripper: httptransport.FakeTransport{
|
HTTPTransport: httptransport.FakeTransport{
|
||||||
Err: io.EOF,
|
Err: io.EOF,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ func TestByteCounterSuccess(t *testing.T) {
|
||||||
counter := bytecounter.New()
|
counter := bytecounter.New()
|
||||||
txp := httptransport.ByteCountingTransport{
|
txp := httptransport.ByteCountingTransport{
|
||||||
Counter: counter,
|
Counter: counter,
|
||||||
RoundTripper: httptransport.FakeTransport{
|
HTTPTransport: httptransport.FakeTransport{
|
||||||
Resp: &http.Response{
|
Resp: &http.Response{
|
||||||
Body: io.NopCloser(strings.NewReader("1234567")),
|
Body: io.NopCloser(strings.NewReader("1234567")),
|
||||||
Header: http.Header{
|
Header: http.Header{
|
||||||
|
@ -89,7 +89,7 @@ func TestByteCounterSuccessWithEOF(t *testing.T) {
|
||||||
counter := bytecounter.New()
|
counter := bytecounter.New()
|
||||||
txp := httptransport.ByteCountingTransport{
|
txp := httptransport.ByteCountingTransport{
|
||||||
Counter: counter,
|
Counter: counter,
|
||||||
RoundTripper: httptransport.FakeTransport{
|
HTTPTransport: httptransport.FakeTransport{
|
||||||
Resp: &http.Response{
|
Resp: &http.Response{
|
||||||
Body: bodyReaderWithEOF{},
|
Body: bodyReaderWithEOF{},
|
||||||
Header: http.Header{
|
Header: http.Header{
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package httptransport
|
package httptransport
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -9,12 +10,11 @@ import (
|
||||||
// Deprecation warning
|
// Deprecation warning
|
||||||
//
|
//
|
||||||
// New code should use netxlite.NewHTTP3Transport instead.
|
// New code should use netxlite.NewHTTP3Transport instead.
|
||||||
func NewHTTP3Transport(config Config) RoundTripper {
|
func NewHTTP3Transport(config Config) model.HTTPTransport {
|
||||||
// Rationale for using NoLogger here: previously this code did
|
// Rationale for using NoLogger here: previously this code did
|
||||||
// not use a logger as well, so it's fine to keep it as is.
|
// not use a logger as well, so it's fine to keep it as is.
|
||||||
return netxlite.NewHTTP3Transport(&NoLogger{},
|
return netxlite.NewHTTP3Transport(&NoLogger{},
|
||||||
netxlite.NewQUICDialerFromContextDialerAdapter(config.QUICDialer),
|
config.QUICDialer, config.TLSConfig)
|
||||||
config.TLSConfig)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type NoLogger struct{}
|
type NoLogger struct{}
|
||||||
|
|
|
@ -2,46 +2,15 @@
|
||||||
package httptransport
|
package httptransport
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/lucas-clemente/quic-go"
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Config contains the configuration required for constructing an HTTP transport
|
// Config contains the configuration required for constructing an HTTP transport
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Dialer Dialer
|
Dialer model.Dialer
|
||||||
QUICDialer QUICDialer
|
QUICDialer model.QUICDialer
|
||||||
TLSDialer TLSDialer
|
TLSDialer model.TLSDialer
|
||||||
TLSConfig *tls.Config
|
TLSConfig *tls.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dialer is the definition of dialer assumed by this package.
|
|
||||||
type Dialer interface {
|
|
||||||
DialContext(ctx context.Context, network, address string) (net.Conn, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TLSDialer is the definition of a TLS dialer assumed by this package.
|
|
||||||
type TLSDialer interface {
|
|
||||||
DialTLSContext(ctx context.Context, network, address string) (net.Conn, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// QUICDialer is the definition of dialer for QUIC assumed by this package.
|
|
||||||
type QUICDialer interface {
|
|
||||||
DialContext(ctx context.Context, network, addr string, tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlySession, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RoundTripper is the definition of http.RoundTripper used by this package.
|
|
||||||
type RoundTripper interface {
|
|
||||||
RoundTrip(req *http.Request) (*http.Response, error)
|
|
||||||
CloseIdleConnections()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
|
||||||
|
|
|
@ -10,13 +10,14 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SaverPerformanceHTTPTransport is a RoundTripper that saves
|
// SaverPerformanceHTTPTransport is a RoundTripper that saves
|
||||||
// performance events occurring during the round trip
|
// performance events occurring during the round trip
|
||||||
type SaverPerformanceHTTPTransport struct {
|
type SaverPerformanceHTTPTransport struct {
|
||||||
RoundTripper
|
model.HTTPTransport
|
||||||
Saver *trace.Saver
|
Saver *trace.Saver
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,13 +39,13 @@ func (txp SaverPerformanceHTTPTransport) RoundTrip(req *http.Request) (*http.Res
|
||||||
}
|
}
|
||||||
req = req.WithContext(httptrace.WithClientTrace(req.Context(), tracep))
|
req = req.WithContext(httptrace.WithClientTrace(req.Context(), tracep))
|
||||||
}
|
}
|
||||||
return txp.RoundTripper.RoundTrip(req)
|
return txp.HTTPTransport.RoundTrip(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SaverMetadataHTTPTransport is a RoundTripper that saves
|
// SaverMetadataHTTPTransport is a RoundTripper that saves
|
||||||
// events related to HTTP request and response metadata
|
// events related to HTTP request and response metadata
|
||||||
type SaverMetadataHTTPTransport struct {
|
type SaverMetadataHTTPTransport struct {
|
||||||
RoundTripper
|
model.HTTPTransport
|
||||||
Saver *trace.Saver
|
Saver *trace.Saver
|
||||||
Transport string
|
Transport string
|
||||||
}
|
}
|
||||||
|
@ -59,7 +60,7 @@ func (txp SaverMetadataHTTPTransport) RoundTrip(req *http.Request) (*http.Respon
|
||||||
Name: "http_request_metadata",
|
Name: "http_request_metadata",
|
||||||
Time: time.Now(),
|
Time: time.Now(),
|
||||||
})
|
})
|
||||||
resp, err := txp.RoundTripper.RoundTrip(req)
|
resp, err := txp.HTTPTransport.RoundTrip(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -88,7 +89,7 @@ func (txp SaverMetadataHTTPTransport) CloneHeaders(req *http.Request) http.Heade
|
||||||
// SaverTransactionHTTPTransport is a RoundTripper that saves
|
// SaverTransactionHTTPTransport is a RoundTripper that saves
|
||||||
// events related to the HTTP transaction
|
// events related to the HTTP transaction
|
||||||
type SaverTransactionHTTPTransport struct {
|
type SaverTransactionHTTPTransport struct {
|
||||||
RoundTripper
|
model.HTTPTransport
|
||||||
Saver *trace.Saver
|
Saver *trace.Saver
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +99,7 @@ func (txp SaverTransactionHTTPTransport) RoundTrip(req *http.Request) (*http.Res
|
||||||
Name: "http_transaction_start",
|
Name: "http_transaction_start",
|
||||||
Time: time.Now(),
|
Time: time.Now(),
|
||||||
})
|
})
|
||||||
resp, err := txp.RoundTripper.RoundTrip(req)
|
resp, err := txp.HTTPTransport.RoundTrip(req)
|
||||||
txp.Saver.Write(trace.Event{
|
txp.Saver.Write(trace.Event{
|
||||||
Err: err,
|
Err: err,
|
||||||
Name: "http_transaction_done",
|
Name: "http_transaction_done",
|
||||||
|
@ -110,7 +111,7 @@ func (txp SaverTransactionHTTPTransport) RoundTrip(req *http.Request) (*http.Res
|
||||||
// SaverBodyHTTPTransport is a RoundTripper that saves
|
// SaverBodyHTTPTransport is a RoundTripper that saves
|
||||||
// body events occurring during the round trip
|
// body events occurring during the round trip
|
||||||
type SaverBodyHTTPTransport struct {
|
type SaverBodyHTTPTransport struct {
|
||||||
RoundTripper
|
model.HTTPTransport
|
||||||
Saver *trace.Saver
|
Saver *trace.Saver
|
||||||
SnapshotSize int
|
SnapshotSize int
|
||||||
}
|
}
|
||||||
|
@ -135,7 +136,7 @@ func (txp SaverBodyHTTPTransport) RoundTrip(req *http.Request) (*http.Response,
|
||||||
Time: time.Now(),
|
Time: time.Now(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
resp, err := txp.RoundTripper.RoundTrip(req)
|
resp, err := txp.HTTPTransport.RoundTrip(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -184,7 +185,7 @@ type saverReadCloser struct {
|
||||||
io.Reader
|
io.Reader
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ RoundTripper = SaverPerformanceHTTPTransport{}
|
var _ model.HTTPTransport = SaverPerformanceHTTPTransport{}
|
||||||
var _ RoundTripper = SaverMetadataHTTPTransport{}
|
var _ model.HTTPTransport = SaverMetadataHTTPTransport{}
|
||||||
var _ RoundTripper = SaverBodyHTTPTransport{}
|
var _ model.HTTPTransport = SaverBodyHTTPTransport{}
|
||||||
var _ RoundTripper = SaverTransactionHTTPTransport{}
|
var _ model.HTTPTransport = SaverTransactionHTTPTransport{}
|
||||||
|
|
|
@ -22,11 +22,11 @@ func TestSaverPerformanceNoMultipleEvents(t *testing.T) {
|
||||||
saver := &trace.Saver{}
|
saver := &trace.Saver{}
|
||||||
// register twice - do we see events twice?
|
// register twice - do we see events twice?
|
||||||
txp := httptransport.SaverPerformanceHTTPTransport{
|
txp := httptransport.SaverPerformanceHTTPTransport{
|
||||||
RoundTripper: http.DefaultTransport.(*http.Transport),
|
HTTPTransport: http.DefaultTransport.(*http.Transport),
|
||||||
Saver: saver,
|
Saver: saver,
|
||||||
}
|
}
|
||||||
txp = httptransport.SaverPerformanceHTTPTransport{
|
txp = httptransport.SaverPerformanceHTTPTransport{
|
||||||
RoundTripper: txp,
|
HTTPTransport: txp,
|
||||||
Saver: saver,
|
Saver: saver,
|
||||||
}
|
}
|
||||||
req, err := http.NewRequest("GET", "https://www.google.com", nil)
|
req, err := http.NewRequest("GET", "https://www.google.com", nil)
|
||||||
|
@ -67,7 +67,7 @@ func TestSaverMetadataSuccess(t *testing.T) {
|
||||||
}
|
}
|
||||||
saver := &trace.Saver{}
|
saver := &trace.Saver{}
|
||||||
txp := httptransport.SaverMetadataHTTPTransport{
|
txp := httptransport.SaverMetadataHTTPTransport{
|
||||||
RoundTripper: http.DefaultTransport.(*http.Transport),
|
HTTPTransport: http.DefaultTransport.(*http.Transport),
|
||||||
Saver: saver,
|
Saver: saver,
|
||||||
}
|
}
|
||||||
req, err := http.NewRequest("GET", "https://www.google.com", nil)
|
req, err := http.NewRequest("GET", "https://www.google.com", nil)
|
||||||
|
@ -121,7 +121,7 @@ func TestSaverMetadataFailure(t *testing.T) {
|
||||||
expected := errors.New("mocked error")
|
expected := errors.New("mocked error")
|
||||||
saver := &trace.Saver{}
|
saver := &trace.Saver{}
|
||||||
txp := httptransport.SaverMetadataHTTPTransport{
|
txp := httptransport.SaverMetadataHTTPTransport{
|
||||||
RoundTripper: httptransport.FakeTransport{
|
HTTPTransport: httptransport.FakeTransport{
|
||||||
Err: expected,
|
Err: expected,
|
||||||
},
|
},
|
||||||
Saver: saver,
|
Saver: saver,
|
||||||
|
@ -165,7 +165,7 @@ func TestSaverTransactionSuccess(t *testing.T) {
|
||||||
}
|
}
|
||||||
saver := &trace.Saver{}
|
saver := &trace.Saver{}
|
||||||
txp := httptransport.SaverTransactionHTTPTransport{
|
txp := httptransport.SaverTransactionHTTPTransport{
|
||||||
RoundTripper: http.DefaultTransport.(*http.Transport),
|
HTTPTransport: http.DefaultTransport.(*http.Transport),
|
||||||
Saver: saver,
|
Saver: saver,
|
||||||
}
|
}
|
||||||
req, err := http.NewRequest("GET", "https://www.google.com", nil)
|
req, err := http.NewRequest("GET", "https://www.google.com", nil)
|
||||||
|
@ -206,7 +206,7 @@ func TestSaverTransactionFailure(t *testing.T) {
|
||||||
expected := errors.New("mocked error")
|
expected := errors.New("mocked error")
|
||||||
saver := &trace.Saver{}
|
saver := &trace.Saver{}
|
||||||
txp := httptransport.SaverTransactionHTTPTransport{
|
txp := httptransport.SaverTransactionHTTPTransport{
|
||||||
RoundTripper: httptransport.FakeTransport{
|
HTTPTransport: httptransport.FakeTransport{
|
||||||
Err: expected,
|
Err: expected,
|
||||||
},
|
},
|
||||||
Saver: saver,
|
Saver: saver,
|
||||||
|
@ -246,7 +246,7 @@ func TestSaverTransactionFailure(t *testing.T) {
|
||||||
func TestSaverBodySuccess(t *testing.T) {
|
func TestSaverBodySuccess(t *testing.T) {
|
||||||
saver := new(trace.Saver)
|
saver := new(trace.Saver)
|
||||||
txp := httptransport.SaverBodyHTTPTransport{
|
txp := httptransport.SaverBodyHTTPTransport{
|
||||||
RoundTripper: httptransport.FakeTransport{
|
HTTPTransport: httptransport.FakeTransport{
|
||||||
Func: func(req *http.Request) (*http.Response, error) {
|
Func: func(req *http.Request) (*http.Response, error) {
|
||||||
data, err := netxlite.ReadAllContext(context.Background(), req.Body)
|
data, err := netxlite.ReadAllContext(context.Background(), req.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -317,7 +317,7 @@ func TestSaverBodySuccess(t *testing.T) {
|
||||||
func TestSaverBodyRequestReadError(t *testing.T) {
|
func TestSaverBodyRequestReadError(t *testing.T) {
|
||||||
saver := new(trace.Saver)
|
saver := new(trace.Saver)
|
||||||
txp := httptransport.SaverBodyHTTPTransport{
|
txp := httptransport.SaverBodyHTTPTransport{
|
||||||
RoundTripper: httptransport.FakeTransport{
|
HTTPTransport: httptransport.FakeTransport{
|
||||||
Func: func(req *http.Request) (*http.Response, error) {
|
Func: func(req *http.Request) (*http.Response, error) {
|
||||||
panic("should not be called")
|
panic("should not be called")
|
||||||
},
|
},
|
||||||
|
@ -348,7 +348,7 @@ func TestSaverBodyRoundTripError(t *testing.T) {
|
||||||
saver := new(trace.Saver)
|
saver := new(trace.Saver)
|
||||||
expected := errors.New("mocked error")
|
expected := errors.New("mocked error")
|
||||||
txp := httptransport.SaverBodyHTTPTransport{
|
txp := httptransport.SaverBodyHTTPTransport{
|
||||||
RoundTripper: httptransport.FakeTransport{
|
HTTPTransport: httptransport.FakeTransport{
|
||||||
Err: expected,
|
Err: expected,
|
||||||
},
|
},
|
||||||
SnapshotSize: 4,
|
SnapshotSize: 4,
|
||||||
|
@ -388,7 +388,7 @@ func TestSaverBodyResponseReadError(t *testing.T) {
|
||||||
saver := new(trace.Saver)
|
saver := new(trace.Saver)
|
||||||
expected := errors.New("mocked error")
|
expected := errors.New("mocked error")
|
||||||
txp := httptransport.SaverBodyHTTPTransport{
|
txp := httptransport.SaverBodyHTTPTransport{
|
||||||
RoundTripper: httptransport.FakeTransport{
|
HTTPTransport: httptransport.FakeTransport{
|
||||||
Func: func(req *http.Request) (*http.Response, error) {
|
Func: func(req *http.Request) (*http.Response, error) {
|
||||||
return &http.Response{
|
return &http.Response{
|
||||||
StatusCode: 200,
|
StatusCode: 200,
|
||||||
|
|
|
@ -2,6 +2,8 @@ package httptransport
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewSystemTransport creates a new "system" HTTP transport. That is a transport
|
// NewSystemTransport creates a new "system" HTTP transport. That is a transport
|
||||||
|
@ -10,7 +12,7 @@ import (
|
||||||
// Deprecation warning
|
// Deprecation warning
|
||||||
//
|
//
|
||||||
// New code should use netxlite.NewHTTPTransport instead.
|
// New code should use netxlite.NewHTTPTransport instead.
|
||||||
func NewSystemTransport(config Config) RoundTripper {
|
func NewSystemTransport(config Config) model.HTTPTransport {
|
||||||
txp := http.DefaultTransport.(*http.Transport).Clone()
|
txp := http.DefaultTransport.(*http.Transport).Clone()
|
||||||
txp.DialContext = config.Dialer.DialContext
|
txp.DialContext = config.Dialer.DialContext
|
||||||
txp.DialTLSContext = config.TLSDialer.DialTLSContext
|
txp.DialTLSContext = config.TLSDialer.DialTLSContext
|
||||||
|
@ -25,4 +27,4 @@ func NewSystemTransport(config Config) RoundTripper {
|
||||||
return txp
|
return txp
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ RoundTripper = &http.Transport{}
|
var _ model.HTTPTransport = &http.Transport{}
|
||||||
|
|
|
@ -30,7 +30,6 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
"github.com/lucas-clemente/quic-go"
|
|
||||||
"github.com/ooni/probe-cli/v3/internal/bytecounter"
|
"github.com/ooni/probe-cli/v3/internal/bytecounter"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/dialer"
|
"github.com/ooni/probe-cli/v3/internal/engine/netx/dialer"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/httptransport"
|
"github.com/ooni/probe-cli/v3/internal/engine/netx/httptransport"
|
||||||
|
@ -42,41 +41,13 @@ import (
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Dialer is the definition of dialer assumed by this package.
|
|
||||||
type Dialer interface {
|
|
||||||
DialContext(ctx context.Context, network, address string) (net.Conn, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// QUICDialer is the definition of a dialer for QUIC assumed by this package.
|
|
||||||
type QUICDialer interface {
|
|
||||||
DialContext(ctx context.Context, network, addr string, tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlySession, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TLSDialer is the definition of a TLS dialer assumed by this package.
|
|
||||||
type TLSDialer interface {
|
|
||||||
DialTLSContext(ctx context.Context, network, address string) (net.Conn, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// HTTPRoundTripper is the definition of http.HTTPRoundTripper used by this package.
|
|
||||||
type HTTPRoundTripper interface {
|
|
||||||
RoundTrip(req *http.Request) (*http.Response, error)
|
|
||||||
CloseIdleConnections()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
// Config contains configuration for creating a new transport. When any
|
||||||
// field of Config is nil/empty, we will use a suitable default.
|
// field of Config is nil/empty, we will use a suitable default.
|
||||||
//
|
//
|
||||||
// We use different savers for different kind of events such that the
|
// We use different savers for different kind of events such that the
|
||||||
// user of this library can choose what to save.
|
// user of this library can choose what to save.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
BaseResolver Resolver // default: system resolver
|
BaseResolver model.Resolver // default: system resolver
|
||||||
BogonIsError bool // default: bogon is not error
|
BogonIsError bool // default: bogon is not error
|
||||||
ByteCounter *bytecounter.Counter // default: no explicit byte counting
|
ByteCounter *bytecounter.Counter // default: no explicit byte counting
|
||||||
CacheResolutions bool // default: no caching
|
CacheResolutions bool // default: no caching
|
||||||
|
@ -84,9 +55,9 @@ type Config struct {
|
||||||
ContextByteCounting bool // default: no implicit byte counting
|
ContextByteCounting bool // default: no implicit byte counting
|
||||||
DNSCache map[string][]string // default: cache is empty
|
DNSCache map[string][]string // default: cache is empty
|
||||||
DialSaver *trace.Saver // default: not saving dials
|
DialSaver *trace.Saver // default: not saving dials
|
||||||
Dialer Dialer // default: dialer.DNSDialer
|
Dialer model.Dialer // default: dialer.DNSDialer
|
||||||
FullResolver Resolver // default: base resolver + goodies
|
FullResolver model.Resolver // default: base resolver + goodies
|
||||||
QUICDialer QUICDialer // default: quicdialer.DNSDialer
|
QUICDialer model.QUICDialer // default: quicdialer.DNSDialer
|
||||||
HTTP3Enabled bool // default: disabled
|
HTTP3Enabled bool // default: disabled
|
||||||
HTTPSaver *trace.Saver // default: not saving HTTP
|
HTTPSaver *trace.Saver // default: not saving HTTP
|
||||||
Logger model.DebugLogger // default: no logging
|
Logger model.DebugLogger // default: no logging
|
||||||
|
@ -95,7 +66,7 @@ type Config struct {
|
||||||
ReadWriteSaver *trace.Saver // default: not saving read/write
|
ReadWriteSaver *trace.Saver // default: not saving read/write
|
||||||
ResolveSaver *trace.Saver // default: not saving resolves
|
ResolveSaver *trace.Saver // default: not saving resolves
|
||||||
TLSConfig *tls.Config // default: attempt using h2
|
TLSConfig *tls.Config // default: attempt using h2
|
||||||
TLSDialer TLSDialer // default: dialer.TLSDialer
|
TLSDialer model.TLSDialer // default: dialer.TLSDialer
|
||||||
TLSSaver *trace.Saver // default: not saving TLS
|
TLSSaver *trace.Saver // default: not saving TLS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,13 +78,13 @@ type tlsHandshaker interface {
|
||||||
var defaultCertPool *x509.CertPool = netxlite.NewDefaultCertPool()
|
var defaultCertPool *x509.CertPool = netxlite.NewDefaultCertPool()
|
||||||
|
|
||||||
// NewResolver creates a new resolver from the specified config
|
// NewResolver creates a new resolver from the specified config
|
||||||
func NewResolver(config Config) Resolver {
|
func NewResolver(config Config) model.Resolver {
|
||||||
if config.BaseResolver == nil {
|
if config.BaseResolver == nil {
|
||||||
config.BaseResolver = &netxlite.ResolverSystem{}
|
config.BaseResolver = &netxlite.ResolverSystem{}
|
||||||
}
|
}
|
||||||
var r Resolver = config.BaseResolver
|
var r model.Resolver = config.BaseResolver
|
||||||
r = &resolver.AddressResolver{
|
r = &netxlite.AddressResolver{
|
||||||
Resolver: netxlite.NewResolverLegacyAdapter(r),
|
Resolver: r,
|
||||||
}
|
}
|
||||||
if config.CacheResolutions {
|
if config.CacheResolutions {
|
||||||
r = &resolver.CacheResolver{Resolver: r}
|
r = &resolver.CacheResolver{Resolver: r}
|
||||||
|
@ -128,21 +99,21 @@ func NewResolver(config Config) Resolver {
|
||||||
if config.BogonIsError {
|
if config.BogonIsError {
|
||||||
r = resolver.BogonResolver{Resolver: r}
|
r = resolver.BogonResolver{Resolver: r}
|
||||||
}
|
}
|
||||||
r = &netxlite.ErrorWrapperResolver{Resolver: netxlite.NewResolverLegacyAdapter(r)}
|
r = &netxlite.ErrorWrapperResolver{Resolver: r}
|
||||||
if config.Logger != nil {
|
if config.Logger != nil {
|
||||||
r = &netxlite.ResolverLogger{
|
r = &netxlite.ResolverLogger{
|
||||||
Logger: config.Logger,
|
Logger: config.Logger,
|
||||||
Resolver: netxlite.NewResolverLegacyAdapter(r),
|
Resolver: r,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if config.ResolveSaver != nil {
|
if config.ResolveSaver != nil {
|
||||||
r = resolver.SaverResolver{Resolver: r, Saver: config.ResolveSaver}
|
r = resolver.SaverResolver{Resolver: r, Saver: config.ResolveSaver}
|
||||||
}
|
}
|
||||||
return &resolver.IDNAResolver{Resolver: netxlite.NewResolverLegacyAdapter(r)}
|
return &netxlite.ResolverIDNA{Resolver: r}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDialer creates a new Dialer from the specified config
|
// NewDialer creates a new Dialer from the specified config
|
||||||
func NewDialer(config Config) Dialer {
|
func NewDialer(config Config) model.Dialer {
|
||||||
if config.FullResolver == nil {
|
if config.FullResolver == nil {
|
||||||
config.FullResolver = NewResolver(config)
|
config.FullResolver = NewResolver(config)
|
||||||
}
|
}
|
||||||
|
@ -156,11 +127,11 @@ func NewDialer(config Config) Dialer {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewQUICDialer creates a new DNS Dialer for QUIC, with the resolver from the specified config
|
// NewQUICDialer creates a new DNS Dialer for QUIC, with the resolver from the specified config
|
||||||
func NewQUICDialer(config Config) QUICDialer {
|
func NewQUICDialer(config Config) model.QUICDialer {
|
||||||
if config.FullResolver == nil {
|
if config.FullResolver == nil {
|
||||||
config.FullResolver = NewResolver(config)
|
config.FullResolver = NewResolver(config)
|
||||||
}
|
}
|
||||||
var ql quicdialer.QUICListener = &netxlite.QUICListenerStdlib{}
|
var ql model.QUICListener = &netxlite.QUICListenerStdlib{}
|
||||||
ql = &netxlite.ErrorWrapperQUICListener{QUICListener: ql}
|
ql = &netxlite.ErrorWrapperQUICListener{QUICListener: ql}
|
||||||
if config.ReadWriteSaver != nil {
|
if config.ReadWriteSaver != nil {
|
||||||
ql = &quicdialer.QUICListenerSaver{
|
ql = &quicdialer.QUICListenerSaver{
|
||||||
|
@ -168,24 +139,24 @@ func NewQUICDialer(config Config) QUICDialer {
|
||||||
Saver: config.ReadWriteSaver,
|
Saver: config.ReadWriteSaver,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var d quicdialer.ContextDialer = &netxlite.QUICDialerQUICGo{
|
var d model.QUICDialer = &netxlite.QUICDialerQUICGo{
|
||||||
QUICListener: ql,
|
QUICListener: ql,
|
||||||
}
|
}
|
||||||
d = &netxlite.ErrorWrapperQUICDialer{
|
d = &netxlite.ErrorWrapperQUICDialer{
|
||||||
QUICDialer: netxlite.NewQUICDialerFromContextDialerAdapter(d),
|
QUICDialer: d,
|
||||||
}
|
}
|
||||||
if config.TLSSaver != nil {
|
if config.TLSSaver != nil {
|
||||||
d = quicdialer.HandshakeSaver{Saver: config.TLSSaver, Dialer: d}
|
d = quicdialer.HandshakeSaver{Saver: config.TLSSaver, QUICDialer: d}
|
||||||
}
|
}
|
||||||
d = &netxlite.QUICDialerResolver{
|
d = &netxlite.QUICDialerResolver{
|
||||||
Resolver: netxlite.NewResolverLegacyAdapter(config.FullResolver),
|
Resolver: config.FullResolver,
|
||||||
Dialer: netxlite.NewQUICDialerFromContextDialerAdapter(d),
|
Dialer: d,
|
||||||
}
|
}
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTLSDialer creates a new TLSDialer from the specified config
|
// NewTLSDialer creates a new TLSDialer from the specified config
|
||||||
func NewTLSDialer(config Config) TLSDialer {
|
func NewTLSDialer(config Config) model.TLSDialer {
|
||||||
if config.Dialer == nil {
|
if config.Dialer == nil {
|
||||||
config.Dialer = NewDialer(config)
|
config.Dialer = NewDialer(config)
|
||||||
}
|
}
|
||||||
|
@ -207,14 +178,14 @@ func NewTLSDialer(config Config) TLSDialer {
|
||||||
config.TLSConfig.InsecureSkipVerify = config.NoTLSVerify
|
config.TLSConfig.InsecureSkipVerify = config.NoTLSVerify
|
||||||
return &netxlite.TLSDialerLegacy{
|
return &netxlite.TLSDialerLegacy{
|
||||||
Config: config.TLSConfig,
|
Config: config.TLSConfig,
|
||||||
Dialer: netxlite.NewDialerLegacyAdapter(config.Dialer),
|
Dialer: config.Dialer,
|
||||||
TLSHandshaker: h,
|
TLSHandshaker: h,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewHTTPTransport creates a new HTTPRoundTripper. You can further extend the returned
|
// NewHTTPTransport creates a new HTTPRoundTripper. You can further extend the returned
|
||||||
// HTTPRoundTripper before wrapping it into an http.Client.
|
// HTTPRoundTripper before wrapping it into an http.Client.
|
||||||
func NewHTTPTransport(config Config) HTTPRoundTripper {
|
func NewHTTPTransport(config Config) model.HTTPTransport {
|
||||||
if config.Dialer == nil {
|
if config.Dialer == nil {
|
||||||
config.Dialer = NewDialer(config)
|
config.Dialer = NewDialer(config)
|
||||||
}
|
}
|
||||||
|
@ -233,27 +204,27 @@ func NewHTTPTransport(config Config) HTTPRoundTripper {
|
||||||
|
|
||||||
if config.ByteCounter != nil {
|
if config.ByteCounter != nil {
|
||||||
txp = httptransport.ByteCountingTransport{
|
txp = httptransport.ByteCountingTransport{
|
||||||
Counter: config.ByteCounter, RoundTripper: txp}
|
Counter: config.ByteCounter, HTTPTransport: txp}
|
||||||
}
|
}
|
||||||
if config.Logger != nil {
|
if config.Logger != nil {
|
||||||
txp = &netxlite.HTTPTransportLogger{Logger: config.Logger, HTTPTransport: txp}
|
txp = &netxlite.HTTPTransportLogger{Logger: config.Logger, HTTPTransport: txp}
|
||||||
}
|
}
|
||||||
if config.HTTPSaver != nil {
|
if config.HTTPSaver != nil {
|
||||||
txp = httptransport.SaverMetadataHTTPTransport{
|
txp = httptransport.SaverMetadataHTTPTransport{
|
||||||
RoundTripper: txp, Saver: config.HTTPSaver, Transport: transport}
|
HTTPTransport: txp, Saver: config.HTTPSaver, Transport: transport}
|
||||||
txp = httptransport.SaverBodyHTTPTransport{
|
txp = httptransport.SaverBodyHTTPTransport{
|
||||||
RoundTripper: txp, Saver: config.HTTPSaver}
|
HTTPTransport: txp, Saver: config.HTTPSaver}
|
||||||
txp = httptransport.SaverPerformanceHTTPTransport{
|
txp = httptransport.SaverPerformanceHTTPTransport{
|
||||||
RoundTripper: txp, Saver: config.HTTPSaver}
|
HTTPTransport: txp, Saver: config.HTTPSaver}
|
||||||
txp = httptransport.SaverTransactionHTTPTransport{
|
txp = httptransport.SaverTransactionHTTPTransport{
|
||||||
RoundTripper: txp, Saver: config.HTTPSaver}
|
HTTPTransport: txp, Saver: config.HTTPSaver}
|
||||||
}
|
}
|
||||||
return txp
|
return txp
|
||||||
}
|
}
|
||||||
|
|
||||||
// httpTransportInfo contains the constructing function as well as the transport name
|
// httpTransportInfo contains the constructing function as well as the transport name
|
||||||
type httpTransportInfo struct {
|
type httpTransportInfo struct {
|
||||||
Factory func(httptransport.Config) httptransport.RoundTripper
|
Factory func(httptransport.Config) model.HTTPTransport
|
||||||
TransportName string
|
TransportName string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,7 +242,7 @@ var allTransportsInfo = map[bool]httpTransportInfo{
|
||||||
// DNSClient is a DNS client. It wraps a Resolver and it possibly
|
// DNSClient is a DNS client. It wraps a Resolver and it possibly
|
||||||
// also wraps an HTTP client, but only when we're using DoH.
|
// also wraps an HTTP client, but only when we're using DoH.
|
||||||
type DNSClient struct {
|
type DNSClient struct {
|
||||||
Resolver
|
model.Resolver
|
||||||
httpClient *http.Client
|
httpClient *http.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -351,7 +322,7 @@ func NewDNSClientWithOverrides(config Config, URL, hostOverride, SNIOverride,
|
||||||
return c, err
|
return c, err
|
||||||
}
|
}
|
||||||
var txp resolver.RoundTripper = resolver.NewDNSOverUDP(
|
var txp resolver.RoundTripper = resolver.NewDNSOverUDP(
|
||||||
netxlite.NewDialerLegacyAdapter(dialer), endpoint)
|
dialer, endpoint)
|
||||||
if config.ResolveSaver != nil {
|
if config.ResolveSaver != nil {
|
||||||
txp = resolver.SaverDNSTransport{
|
txp = resolver.SaverDNSTransport{
|
||||||
RoundTripper: txp,
|
RoundTripper: txp,
|
||||||
|
|
|
@ -22,27 +22,19 @@ import (
|
||||||
|
|
||||||
func TestNewResolverVanilla(t *testing.T) {
|
func TestNewResolverVanilla(t *testing.T) {
|
||||||
r := netx.NewResolver(netx.Config{})
|
r := netx.NewResolver(netx.Config{})
|
||||||
ir, ok := r.(*resolver.IDNAResolver)
|
ir, ok := r.(*netxlite.ResolverIDNA)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not the resolver we expected")
|
t.Fatal("not the resolver we expected")
|
||||||
}
|
}
|
||||||
rla, ok := ir.Resolver.(*netxlite.ResolverLegacyAdapter)
|
ewr, ok := ir.Resolver.(*netxlite.ErrorWrapperResolver)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not the resolver we expected")
|
t.Fatal("not the resolver we expected")
|
||||||
}
|
}
|
||||||
ewr, ok := rla.ResolverLegacy.(*netxlite.ErrorWrapperResolver)
|
ar, ok := ewr.Resolver.(*netxlite.AddressResolver)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not the resolver we expected")
|
t.Fatal("not the resolver we expected")
|
||||||
}
|
}
|
||||||
ar, ok := ewr.Resolver.(*netxlite.ResolverLegacyAdapter).ResolverLegacy.(*resolver.AddressResolver)
|
_, ok = ar.Resolver.(*netxlite.ResolverSystem)
|
||||||
if !ok {
|
|
||||||
t.Fatal("not the resolver we expected")
|
|
||||||
}
|
|
||||||
arw, ok := ar.Resolver.(*netxlite.ResolverLegacyAdapter)
|
|
||||||
if !ok {
|
|
||||||
t.Fatal("not the resolver we expected")
|
|
||||||
}
|
|
||||||
_, ok = arw.ResolverLegacy.(*netxlite.ResolverSystem)
|
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not the resolver we expected")
|
t.Fatal("not the resolver we expected")
|
||||||
}
|
}
|
||||||
|
@ -54,27 +46,19 @@ func TestNewResolverSpecificResolver(t *testing.T) {
|
||||||
// not initialized because it doesn't matter in this context
|
// not initialized because it doesn't matter in this context
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
ir, ok := r.(*resolver.IDNAResolver)
|
ir, ok := r.(*netxlite.ResolverIDNA)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not the resolver we expected")
|
t.Fatal("not the resolver we expected")
|
||||||
}
|
}
|
||||||
rla, ok := ir.Resolver.(*netxlite.ResolverLegacyAdapter)
|
ewr, ok := ir.Resolver.(*netxlite.ErrorWrapperResolver)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not the resolver we expected")
|
t.Fatal("not the resolver we expected")
|
||||||
}
|
}
|
||||||
ewr, ok := rla.ResolverLegacy.(*netxlite.ErrorWrapperResolver)
|
ar, ok := ewr.Resolver.(*netxlite.AddressResolver)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not the resolver we expected")
|
t.Fatal("not the resolver we expected")
|
||||||
}
|
}
|
||||||
ar, ok := ewr.Resolver.(*netxlite.ResolverLegacyAdapter).ResolverLegacy.(*resolver.AddressResolver)
|
_, ok = ar.Resolver.(resolver.BogonResolver)
|
||||||
if !ok {
|
|
||||||
t.Fatal("not the resolver we expected")
|
|
||||||
}
|
|
||||||
arw, ok := ar.Resolver.(*netxlite.ResolverLegacyAdapter)
|
|
||||||
if !ok {
|
|
||||||
t.Fatal("not the resolver we expected")
|
|
||||||
}
|
|
||||||
_, ok = arw.ResolverLegacy.(resolver.BogonResolver)
|
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not the resolver we expected")
|
t.Fatal("not the resolver we expected")
|
||||||
}
|
}
|
||||||
|
@ -84,31 +68,23 @@ func TestNewResolverWithBogonFilter(t *testing.T) {
|
||||||
r := netx.NewResolver(netx.Config{
|
r := netx.NewResolver(netx.Config{
|
||||||
BogonIsError: true,
|
BogonIsError: true,
|
||||||
})
|
})
|
||||||
ir, ok := r.(*resolver.IDNAResolver)
|
ir, ok := r.(*netxlite.ResolverIDNA)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not the resolver we expected")
|
t.Fatal("not the resolver we expected")
|
||||||
}
|
}
|
||||||
rla, ok := ir.Resolver.(*netxlite.ResolverLegacyAdapter)
|
ewr, ok := ir.Resolver.(*netxlite.ErrorWrapperResolver)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not the resolver we expected")
|
t.Fatal("not the resolver we expected")
|
||||||
}
|
}
|
||||||
ewr, ok := rla.ResolverLegacy.(*netxlite.ErrorWrapperResolver)
|
br, ok := ewr.Resolver.(resolver.BogonResolver)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not the resolver we expected")
|
t.Fatal("not the resolver we expected")
|
||||||
}
|
}
|
||||||
br, ok := ewr.Resolver.(*netxlite.ResolverLegacyAdapter).ResolverLegacy.(resolver.BogonResolver)
|
ar, ok := br.Resolver.(*netxlite.AddressResolver)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not the resolver we expected")
|
t.Fatal("not the resolver we expected")
|
||||||
}
|
}
|
||||||
ar, ok := br.Resolver.(*resolver.AddressResolver)
|
_, ok = ar.Resolver.(*netxlite.ResolverSystem)
|
||||||
if !ok {
|
|
||||||
t.Fatal("not the resolver we expected")
|
|
||||||
}
|
|
||||||
arw, ok := ar.Resolver.(*netxlite.ResolverLegacyAdapter)
|
|
||||||
if !ok {
|
|
||||||
t.Fatal("not the resolver we expected")
|
|
||||||
}
|
|
||||||
_, ok = arw.ResolverLegacy.(*netxlite.ResolverSystem)
|
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not the resolver we expected")
|
t.Fatal("not the resolver we expected")
|
||||||
}
|
}
|
||||||
|
@ -118,46 +94,26 @@ func TestNewResolverWithLogging(t *testing.T) {
|
||||||
r := netx.NewResolver(netx.Config{
|
r := netx.NewResolver(netx.Config{
|
||||||
Logger: log.Log,
|
Logger: log.Log,
|
||||||
})
|
})
|
||||||
ir, ok := r.(*resolver.IDNAResolver)
|
ir, ok := r.(*netxlite.ResolverIDNA)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not the resolver we expected")
|
t.Fatal("not the resolver we expected")
|
||||||
}
|
}
|
||||||
rla, ok := ir.Resolver.(*netxlite.ResolverLegacyAdapter)
|
lr, ok := ir.Resolver.(*netxlite.ResolverLogger)
|
||||||
if !ok {
|
|
||||||
t.Fatal("not the resolver we expected")
|
|
||||||
}
|
|
||||||
lr, ok := rla.ResolverLegacy.(*netxlite.ResolverLogger)
|
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not the resolver we expected")
|
t.Fatal("not the resolver we expected")
|
||||||
}
|
}
|
||||||
if lr.Logger != log.Log {
|
if lr.Logger != log.Log {
|
||||||
t.Fatal("not the logger we expected")
|
t.Fatal("not the logger we expected")
|
||||||
}
|
}
|
||||||
rla, ok = ir.Resolver.(*netxlite.ResolverLegacyAdapter)
|
ewr, ok := lr.Resolver.(*netxlite.ErrorWrapperResolver)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("not the resolver we expected")
|
||||||
|
}
|
||||||
|
ar, ok := ewr.Resolver.(*netxlite.AddressResolver)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not the resolver we expected")
|
t.Fatal("not the resolver we expected")
|
||||||
}
|
}
|
||||||
lr, ok = rla.ResolverLegacy.(*netxlite.ResolverLogger)
|
_, ok = ar.Resolver.(*netxlite.ResolverSystem)
|
||||||
if !ok {
|
|
||||||
t.Fatal("not the resolver we expected")
|
|
||||||
}
|
|
||||||
rla, ok = lr.Resolver.(*netxlite.ResolverLegacyAdapter)
|
|
||||||
if !ok {
|
|
||||||
t.Fatal("not the resolver we expected")
|
|
||||||
}
|
|
||||||
ewr, ok := rla.ResolverLegacy.(*netxlite.ErrorWrapperResolver)
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("not the resolver we expected %T", rla.ResolverLegacy)
|
|
||||||
}
|
|
||||||
ar, ok := ewr.Resolver.(*netxlite.ResolverLegacyAdapter).ResolverLegacy.(*resolver.AddressResolver)
|
|
||||||
if !ok {
|
|
||||||
t.Fatal("not the resolver we expected")
|
|
||||||
}
|
|
||||||
arw, ok := ar.Resolver.(*netxlite.ResolverLegacyAdapter)
|
|
||||||
if !ok {
|
|
||||||
t.Fatal("not the resolver we expected")
|
|
||||||
}
|
|
||||||
_, ok = arw.ResolverLegacy.(*netxlite.ResolverSystem)
|
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not the resolver we expected")
|
t.Fatal("not the resolver we expected")
|
||||||
}
|
}
|
||||||
|
@ -168,15 +124,11 @@ func TestNewResolverWithSaver(t *testing.T) {
|
||||||
r := netx.NewResolver(netx.Config{
|
r := netx.NewResolver(netx.Config{
|
||||||
ResolveSaver: saver,
|
ResolveSaver: saver,
|
||||||
})
|
})
|
||||||
ir, ok := r.(*resolver.IDNAResolver)
|
ir, ok := r.(*netxlite.ResolverIDNA)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not the resolver we expected")
|
t.Fatal("not the resolver we expected")
|
||||||
}
|
}
|
||||||
rla, ok := ir.Resolver.(*netxlite.ResolverLegacyAdapter)
|
sr, ok := ir.Resolver.(resolver.SaverResolver)
|
||||||
if !ok {
|
|
||||||
t.Fatal("not the resolver we expected")
|
|
||||||
}
|
|
||||||
sr, ok := rla.ResolverLegacy.(resolver.SaverResolver)
|
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not the resolver we expected")
|
t.Fatal("not the resolver we expected")
|
||||||
}
|
}
|
||||||
|
@ -187,15 +139,11 @@ func TestNewResolverWithSaver(t *testing.T) {
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not the resolver we expected")
|
t.Fatal("not the resolver we expected")
|
||||||
}
|
}
|
||||||
ar, ok := ewr.Resolver.(*netxlite.ResolverLegacyAdapter).ResolverLegacy.(*resolver.AddressResolver)
|
ar, ok := ewr.Resolver.(*netxlite.AddressResolver)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not the resolver we expected")
|
t.Fatal("not the resolver we expected")
|
||||||
}
|
}
|
||||||
arw, ok := ar.Resolver.(*netxlite.ResolverLegacyAdapter)
|
_, ok = ar.Resolver.(*netxlite.ResolverSystem)
|
||||||
if !ok {
|
|
||||||
t.Fatal("not the resolver we expected")
|
|
||||||
}
|
|
||||||
_, ok = arw.ResolverLegacy.(*netxlite.ResolverSystem)
|
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not the resolver we expected")
|
t.Fatal("not the resolver we expected")
|
||||||
}
|
}
|
||||||
|
@ -205,34 +153,26 @@ func TestNewResolverWithReadWriteCache(t *testing.T) {
|
||||||
r := netx.NewResolver(netx.Config{
|
r := netx.NewResolver(netx.Config{
|
||||||
CacheResolutions: true,
|
CacheResolutions: true,
|
||||||
})
|
})
|
||||||
ir, ok := r.(*resolver.IDNAResolver)
|
ir, ok := r.(*netxlite.ResolverIDNA)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not the resolver we expected")
|
t.Fatal("not the resolver we expected")
|
||||||
}
|
}
|
||||||
rla, ok := ir.Resolver.(*netxlite.ResolverLegacyAdapter)
|
ewr, ok := ir.Resolver.(*netxlite.ErrorWrapperResolver)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not the resolver we expected")
|
t.Fatal("not the resolver we expected")
|
||||||
}
|
}
|
||||||
ewr, ok := rla.ResolverLegacy.(*netxlite.ErrorWrapperResolver)
|
cr, ok := ewr.Resolver.(*resolver.CacheResolver)
|
||||||
if !ok {
|
|
||||||
t.Fatal("not the resolver we expected")
|
|
||||||
}
|
|
||||||
cr, ok := ewr.Resolver.(*netxlite.ResolverLegacyAdapter).ResolverLegacy.(*resolver.CacheResolver)
|
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not the resolver we expected")
|
t.Fatal("not the resolver we expected")
|
||||||
}
|
}
|
||||||
if cr.ReadOnly != false {
|
if cr.ReadOnly != false {
|
||||||
t.Fatal("expected readwrite cache here")
|
t.Fatal("expected readwrite cache here")
|
||||||
}
|
}
|
||||||
ar, ok := cr.Resolver.(*resolver.AddressResolver)
|
ar, ok := cr.Resolver.(*netxlite.AddressResolver)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not the resolver we expected")
|
t.Fatal("not the resolver we expected")
|
||||||
}
|
}
|
||||||
arw, ok := ar.Resolver.(*netxlite.ResolverLegacyAdapter)
|
_, ok = ar.Resolver.(*netxlite.ResolverSystem)
|
||||||
if !ok {
|
|
||||||
t.Fatal("not the resolver we expected")
|
|
||||||
}
|
|
||||||
_, ok = arw.ResolverLegacy.(*netxlite.ResolverSystem)
|
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not the resolver we expected")
|
t.Fatal("not the resolver we expected")
|
||||||
}
|
}
|
||||||
|
@ -244,19 +184,15 @@ func TestNewResolverWithPrefilledReadonlyCache(t *testing.T) {
|
||||||
"dns.google.com": {"8.8.8.8"},
|
"dns.google.com": {"8.8.8.8"},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
ir, ok := r.(*resolver.IDNAResolver)
|
ir, ok := r.(*netxlite.ResolverIDNA)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not the resolver we expected")
|
t.Fatal("not the resolver we expected")
|
||||||
}
|
}
|
||||||
rla, ok := ir.Resolver.(*netxlite.ResolverLegacyAdapter)
|
ewr, ok := ir.Resolver.(*netxlite.ErrorWrapperResolver)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not the resolver we expected")
|
t.Fatal("not the resolver we expected")
|
||||||
}
|
}
|
||||||
ewr, ok := rla.ResolverLegacy.(*netxlite.ErrorWrapperResolver)
|
cr, ok := ewr.Resolver.(*resolver.CacheResolver)
|
||||||
if !ok {
|
|
||||||
t.Fatal("not the resolver we expected")
|
|
||||||
}
|
|
||||||
cr, ok := ewr.Resolver.(*netxlite.ResolverLegacyAdapter).ResolverLegacy.(*resolver.CacheResolver)
|
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not the resolver we expected")
|
t.Fatal("not the resolver we expected")
|
||||||
}
|
}
|
||||||
|
@ -266,15 +202,11 @@ func TestNewResolverWithPrefilledReadonlyCache(t *testing.T) {
|
||||||
if cr.Get("dns.google.com")[0] != "8.8.8.8" {
|
if cr.Get("dns.google.com")[0] != "8.8.8.8" {
|
||||||
t.Fatal("cache not correctly prefilled")
|
t.Fatal("cache not correctly prefilled")
|
||||||
}
|
}
|
||||||
ar, ok := cr.Resolver.(*resolver.AddressResolver)
|
ar, ok := cr.Resolver.(*netxlite.AddressResolver)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not the resolver we expected")
|
t.Fatal("not the resolver we expected")
|
||||||
}
|
}
|
||||||
arw, ok := ar.Resolver.(*netxlite.ResolverLegacyAdapter)
|
_, ok = ar.Resolver.(*netxlite.ResolverSystem)
|
||||||
if !ok {
|
|
||||||
t.Fatal("not the resolver we expected")
|
|
||||||
}
|
|
||||||
_, ok = arw.ResolverLegacy.(*netxlite.ResolverSystem)
|
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not the resolver we expected")
|
t.Fatal("not the resolver we expected")
|
||||||
}
|
}
|
||||||
|
@ -548,7 +480,7 @@ func TestNewWithByteCounter(t *testing.T) {
|
||||||
if bctxp.Counter != counter {
|
if bctxp.Counter != counter {
|
||||||
t.Fatal("not the byte counter we expected")
|
t.Fatal("not the byte counter we expected")
|
||||||
}
|
}
|
||||||
if _, ok := bctxp.RoundTripper.(*http.Transport); !ok {
|
if _, ok := bctxp.HTTPTransport.(*http.Transport); !ok {
|
||||||
t.Fatal("not the transport we expected")
|
t.Fatal("not the transport we expected")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -581,28 +513,28 @@ func TestNewWithSaver(t *testing.T) {
|
||||||
if stxptxp.Saver != saver {
|
if stxptxp.Saver != saver {
|
||||||
t.Fatal("not the logger we expected")
|
t.Fatal("not the logger we expected")
|
||||||
}
|
}
|
||||||
sptxp, ok := stxptxp.RoundTripper.(httptransport.SaverPerformanceHTTPTransport)
|
sptxp, ok := stxptxp.HTTPTransport.(httptransport.SaverPerformanceHTTPTransport)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not the transport we expected")
|
t.Fatal("not the transport we expected")
|
||||||
}
|
}
|
||||||
if sptxp.Saver != saver {
|
if sptxp.Saver != saver {
|
||||||
t.Fatal("not the logger we expected")
|
t.Fatal("not the logger we expected")
|
||||||
}
|
}
|
||||||
sbtxp, ok := sptxp.RoundTripper.(httptransport.SaverBodyHTTPTransport)
|
sbtxp, ok := sptxp.HTTPTransport.(httptransport.SaverBodyHTTPTransport)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not the transport we expected")
|
t.Fatal("not the transport we expected")
|
||||||
}
|
}
|
||||||
if sbtxp.Saver != saver {
|
if sbtxp.Saver != saver {
|
||||||
t.Fatal("not the logger we expected")
|
t.Fatal("not the logger we expected")
|
||||||
}
|
}
|
||||||
smtxp, ok := sbtxp.RoundTripper.(httptransport.SaverMetadataHTTPTransport)
|
smtxp, ok := sbtxp.HTTPTransport.(httptransport.SaverMetadataHTTPTransport)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("not the transport we expected")
|
t.Fatal("not the transport we expected")
|
||||||
}
|
}
|
||||||
if smtxp.Saver != saver {
|
if smtxp.Saver != saver {
|
||||||
t.Fatal("not the logger we expected")
|
t.Fatal("not the logger we expected")
|
||||||
}
|
}
|
||||||
if _, ok := smtxp.RoundTripper.(*http.Transport); !ok {
|
if _, ok := smtxp.HTTPTransport.(*http.Transport); !ok {
|
||||||
t.Fatal("not the transport we expected")
|
t.Fatal("not the transport we expected")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
package quicdialer
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"crypto/tls"
|
|
||||||
|
|
||||||
"github.com/lucas-clemente/quic-go"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ContextDialer is a dialer for QUIC using Context.
|
|
||||||
type ContextDialer interface {
|
|
||||||
// Note: assumes that tlsCfg and cfg are not nil.
|
|
||||||
DialContext(ctx context.Context, network, host string,
|
|
||||||
tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlySession, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resolver is the interface we expect from a resolver.
|
|
||||||
type Resolver interface {
|
|
||||||
LookupHost(ctx context.Context, hostname string) (addrs []string, err error)
|
|
||||||
}
|
|
|
@ -7,13 +7,14 @@ import (
|
||||||
|
|
||||||
"github.com/lucas-clemente/quic-go"
|
"github.com/lucas-clemente/quic-go"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||||
)
|
)
|
||||||
|
|
||||||
// HandshakeSaver saves events occurring during the handshake
|
// HandshakeSaver saves events occurring during the handshake
|
||||||
type HandshakeSaver struct {
|
type HandshakeSaver struct {
|
||||||
Saver *trace.Saver
|
Saver *trace.Saver
|
||||||
Dialer ContextDialer
|
model.QUICDialer
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialContext implements ContextDialer.DialContext
|
// DialContext implements ContextDialer.DialContext
|
||||||
|
@ -31,7 +32,7 @@ func (h HandshakeSaver) DialContext(ctx context.Context, network string,
|
||||||
TLSServerName: tlsCfg.ServerName,
|
TLSServerName: tlsCfg.ServerName,
|
||||||
Time: start,
|
Time: start,
|
||||||
})
|
})
|
||||||
sess, err := h.Dialer.DialContext(ctx, network, host, tlsCfg, cfg)
|
sess, err := h.QUICDialer.DialContext(ctx, network, host, tlsCfg, cfg)
|
||||||
stop := time.Now()
|
stop := time.Now()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.Saver.Write(trace.Event{
|
h.Saver.Write(trace.Event{
|
||||||
|
|
|
@ -11,12 +11,13 @@ import (
|
||||||
"github.com/lucas-clemente/quic-go"
|
"github.com/lucas-clemente/quic-go"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/quicdialer"
|
"github.com/ooni/probe-cli/v3/internal/engine/netx/quicdialer"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite/quictesting"
|
"github.com/ooni/probe-cli/v3/internal/netxlite/quictesting"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MockDialer struct {
|
type MockDialer struct {
|
||||||
Dialer quicdialer.ContextDialer
|
Dialer model.QUICDialer
|
||||||
Sess quic.EarlySession
|
Sess quic.EarlySession
|
||||||
Err error
|
Err error
|
||||||
}
|
}
|
||||||
|
@ -38,7 +39,7 @@ func TestHandshakeSaverSuccess(t *testing.T) {
|
||||||
}
|
}
|
||||||
saver := &trace.Saver{}
|
saver := &trace.Saver{}
|
||||||
dlr := quicdialer.HandshakeSaver{
|
dlr := quicdialer.HandshakeSaver{
|
||||||
Dialer: &netxlite.QUICDialerQUICGo{
|
QUICDialer: &netxlite.QUICDialerQUICGo{
|
||||||
QUICListener: &netxlite.QUICListenerStdlib{},
|
QUICListener: &netxlite.QUICListenerStdlib{},
|
||||||
},
|
},
|
||||||
Saver: saver,
|
Saver: saver,
|
||||||
|
@ -96,7 +97,7 @@ func TestHandshakeSaverHostNameError(t *testing.T) {
|
||||||
}
|
}
|
||||||
saver := &trace.Saver{}
|
saver := &trace.Saver{}
|
||||||
dlr := quicdialer.HandshakeSaver{
|
dlr := quicdialer.HandshakeSaver{
|
||||||
Dialer: &netxlite.QUICDialerQUICGo{
|
QUICDialer: &netxlite.QUICDialerQUICGo{
|
||||||
QUICListener: &netxlite.QUICListenerStdlib{},
|
QUICListener: &netxlite.QUICListenerStdlib{},
|
||||||
},
|
},
|
||||||
Saver: saver,
|
Saver: saver,
|
||||||
|
|
|
@ -9,16 +9,10 @@ import (
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||||
)
|
)
|
||||||
|
|
||||||
// QUICListener listens for QUIC connections.
|
|
||||||
type QUICListener interface {
|
|
||||||
// Listen creates a new listening UDPConn.
|
|
||||||
Listen(addr *net.UDPAddr) (model.UDPLikeConn, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// QUICListenerSaver is a QUICListener that also implements saving events.
|
// QUICListenerSaver is a QUICListener that also implements saving events.
|
||||||
type QUICListenerSaver struct {
|
type QUICListenerSaver struct {
|
||||||
// QUICListener is the underlying QUICListener.
|
// QUICListener is the underlying QUICListener.
|
||||||
QUICListener QUICListener
|
model.QUICListener
|
||||||
|
|
||||||
// Saver is the underlying Saver.
|
// Saver is the underlying Saver.
|
||||||
Saver *trace.Saver
|
Saver *trace.Saver
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
package resolver
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
|
||||||
)
|
|
||||||
|
|
||||||
// AddressResolver is a resolver that knows how to correctly
|
|
||||||
// resolve IP addresses to themselves.
|
|
||||||
type AddressResolver = netxlite.AddressResolver
|
|
|
@ -3,6 +3,7 @@ package resolver
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -14,7 +15,7 @@ import (
|
||||||
// This resolver is deprecated. The right thing to do would be to check
|
// This resolver is deprecated. The right thing to do would be to check
|
||||||
// for bogons right after a domain name resolution in the nettest.
|
// for bogons right after a domain name resolution in the nettest.
|
||||||
type BogonResolver struct {
|
type BogonResolver struct {
|
||||||
Resolver
|
model.Resolver
|
||||||
}
|
}
|
||||||
|
|
||||||
// LookupHost implements Resolver.LookupHost
|
// LookupHost implements Resolver.LookupHost
|
||||||
|
@ -28,4 +29,4 @@ func (r BogonResolver) LookupHost(ctx context.Context, hostname string) ([]strin
|
||||||
return addrs, err
|
return addrs, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ Resolver = BogonResolver{}
|
var _ model.Resolver = BogonResolver{}
|
||||||
|
|
|
@ -3,12 +3,14 @@ package resolver
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CacheResolver is a resolver that caches successful replies.
|
// CacheResolver is a resolver that caches successful replies.
|
||||||
type CacheResolver struct {
|
type CacheResolver struct {
|
||||||
ReadOnly bool
|
ReadOnly bool
|
||||||
Resolver
|
model.Resolver
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
cache map[string][]string
|
cache map[string][]string
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,11 +6,12 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/resolver"
|
"github.com/ooni/probe-cli/v3/internal/engine/netx/resolver"
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCacheFailure(t *testing.T) {
|
func TestCacheFailure(t *testing.T) {
|
||||||
expected := errors.New("mocked error")
|
expected := errors.New("mocked error")
|
||||||
var r resolver.Resolver = resolver.FakeResolver{
|
var r model.Resolver = resolver.FakeResolver{
|
||||||
Err: expected,
|
Err: expected,
|
||||||
}
|
}
|
||||||
cache := &resolver.CacheResolver{Resolver: r}
|
cache := &resolver.CacheResolver{Resolver: r}
|
||||||
|
@ -27,7 +28,7 @@ func TestCacheFailure(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCacheHitSuccess(t *testing.T) {
|
func TestCacheHitSuccess(t *testing.T) {
|
||||||
var r resolver.Resolver = resolver.FakeResolver{
|
var r model.Resolver = resolver.FakeResolver{
|
||||||
Err: errors.New("mocked error"),
|
Err: errors.New("mocked error"),
|
||||||
}
|
}
|
||||||
cache := &resolver.CacheResolver{Resolver: r}
|
cache := &resolver.CacheResolver{Resolver: r}
|
||||||
|
@ -42,7 +43,7 @@ func TestCacheHitSuccess(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCacheMissSuccess(t *testing.T) {
|
func TestCacheMissSuccess(t *testing.T) {
|
||||||
var r resolver.Resolver = resolver.FakeResolver{
|
var r model.Resolver = resolver.FakeResolver{
|
||||||
Result: []string{"8.8.8.8"},
|
Result: []string{"8.8.8.8"},
|
||||||
}
|
}
|
||||||
cache := &resolver.CacheResolver{Resolver: r}
|
cache := &resolver.CacheResolver{Resolver: r}
|
||||||
|
@ -59,7 +60,7 @@ func TestCacheMissSuccess(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCacheReadonlySuccess(t *testing.T) {
|
func TestCacheReadonlySuccess(t *testing.T) {
|
||||||
var r resolver.Resolver = resolver.FakeResolver{
|
var r model.Resolver = resolver.FakeResolver{
|
||||||
Result: []string{"8.8.8.8"},
|
Result: []string{"8.8.8.8"},
|
||||||
}
|
}
|
||||||
cache := &resolver.CacheResolver{Resolver: r, ReadOnly: true}
|
cache := &resolver.CacheResolver{Resolver: r, ReadOnly: true}
|
||||||
|
|
|
@ -2,13 +2,15 @@ package resolver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ChainResolver is a chain resolver. The primary resolver is used first and, if that
|
// ChainResolver is a chain resolver. The primary resolver is used first and, if that
|
||||||
// fails, we then attempt with the secondary resolver.
|
// fails, we then attempt with the secondary resolver.
|
||||||
type ChainResolver struct {
|
type ChainResolver struct {
|
||||||
Primary Resolver
|
Primary model.Resolver
|
||||||
Secondary Resolver
|
Secondary model.Resolver
|
||||||
}
|
}
|
||||||
|
|
||||||
// LookupHost implements Resolver.LookupHost
|
// LookupHost implements Resolver.LookupHost
|
||||||
|
@ -30,4 +32,20 @@ func (c ChainResolver) Address() string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ Resolver = ChainResolver{}
|
// CloseIdleConnections implements Resolver.CloseIdleConnections.
|
||||||
|
func (c ChainResolver) CloseIdleConnections() {
|
||||||
|
c.Primary.CloseIdleConnections()
|
||||||
|
c.Secondary.CloseIdleConnections()
|
||||||
|
}
|
||||||
|
|
||||||
|
// LookupHTTPS implements Resolver.LookupHTTPS
|
||||||
|
func (c ChainResolver) LookupHTTPS(
|
||||||
|
ctx context.Context, domain string) (*model.HTTPSSvc, error) {
|
||||||
|
https, err := c.Primary.LookupHTTPS(ctx, domain)
|
||||||
|
if err != nil {
|
||||||
|
https, err = c.Secondary.LookupHTTPS(ctx, domain)
|
||||||
|
}
|
||||||
|
return https, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ model.Resolver = ChainResolver{}
|
||||||
|
|
|
@ -2,11 +2,13 @@ package resolver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ooni/probe-cli/v3/internal/atomicx"
|
"github.com/ooni/probe-cli/v3/internal/atomicx"
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FakeDialer struct {
|
type FakeDialer struct {
|
||||||
|
@ -143,4 +145,11 @@ func (c FakeResolver) Address() string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ Resolver = FakeResolver{}
|
func (c FakeResolver) CloseIdleConnections() {}
|
||||||
|
|
||||||
|
func (c FakeResolver) LookupHTTPS(
|
||||||
|
ctx context.Context, domain string) (*model.HTTPSSvc, error) {
|
||||||
|
return nil, errors.New("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ model.Resolver = FakeResolver{}
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
package resolver
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
|
||||||
)
|
|
||||||
|
|
||||||
// IDNAResolver is to support resolving Internationalized Domain Names.
|
|
||||||
// See RFC3492 for more information.
|
|
||||||
type IDNAResolver = netxlite.ResolverIDNA
|
|
||||||
|
|
||||||
var _ Resolver = &IDNAResolver{}
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
|
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/resolver"
|
"github.com/ooni/probe-cli/v3/internal/engine/netx/resolver"
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -15,13 +16,13 @@ func init() {
|
||||||
log.SetLevel(log.DebugLevel)
|
log.SetLevel(log.DebugLevel)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testresolverquick(t *testing.T, reso resolver.Resolver) {
|
func testresolverquick(t *testing.T, reso model.Resolver) {
|
||||||
if testing.Short() {
|
if testing.Short() {
|
||||||
t.Skip("skip test in short mode")
|
t.Skip("skip test in short mode")
|
||||||
}
|
}
|
||||||
reso = &netxlite.ResolverLogger{
|
reso = &netxlite.ResolverLogger{
|
||||||
Logger: log.Log,
|
Logger: log.Log,
|
||||||
Resolver: netxlite.NewResolverLegacyAdapter(reso),
|
Resolver: reso,
|
||||||
}
|
}
|
||||||
addrs, err := reso.LookupHost(context.Background(), "dns.google.com")
|
addrs, err := reso.LookupHost(context.Background(), "dns.google.com")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -43,14 +44,14 @@ func testresolverquick(t *testing.T, reso resolver.Resolver) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensuring we can handle Internationalized Domain Names (IDNs) without issues
|
// Ensuring we can handle Internationalized Domain Names (IDNs) without issues
|
||||||
func testresolverquickidna(t *testing.T, reso resolver.Resolver) {
|
func testresolverquickidna(t *testing.T, reso model.Resolver) {
|
||||||
if testing.Short() {
|
if testing.Short() {
|
||||||
t.Skip("skip test in short mode")
|
t.Skip("skip test in short mode")
|
||||||
}
|
}
|
||||||
reso = &resolver.IDNAResolver{
|
reso = &netxlite.ResolverIDNA{
|
||||||
Resolver: &netxlite.ResolverLogger{
|
Resolver: &netxlite.ResolverLogger{
|
||||||
Logger: log.Log,
|
Logger: log.Log,
|
||||||
Resolver: netxlite.NewResolverLegacyAdapter(reso),
|
Resolver: reso,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
addrs, err := reso.LookupHost(context.Background(), "яндекс.рф")
|
addrs, err := reso.LookupHost(context.Background(), "яндекс.рф")
|
||||||
|
@ -70,14 +71,14 @@ func TestNewResolverSystem(t *testing.T) {
|
||||||
|
|
||||||
func TestNewResolverUDPAddress(t *testing.T) {
|
func TestNewResolverUDPAddress(t *testing.T) {
|
||||||
reso := resolver.NewSerialResolver(
|
reso := resolver.NewSerialResolver(
|
||||||
resolver.NewDNSOverUDP(netxlite.NewDialerLegacyAdapter(&net.Dialer{}), "8.8.8.8:53"))
|
resolver.NewDNSOverUDP(netxlite.DefaultDialer, "8.8.8.8:53"))
|
||||||
testresolverquick(t, reso)
|
testresolverquick(t, reso)
|
||||||
testresolverquickidna(t, reso)
|
testresolverquickidna(t, reso)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewResolverUDPDomain(t *testing.T) {
|
func TestNewResolverUDPDomain(t *testing.T) {
|
||||||
reso := resolver.NewSerialResolver(
|
reso := resolver.NewSerialResolver(
|
||||||
resolver.NewDNSOverUDP(netxlite.NewDialerLegacyAdapter(&net.Dialer{}), "dns.google.com:53"))
|
resolver.NewDNSOverUDP(netxlite.DefaultDialer, "dns.google.com:53"))
|
||||||
testresolverquick(t, reso)
|
testresolverquick(t, reso)
|
||||||
testresolverquickidna(t, reso)
|
testresolverquickidna(t, reso)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
package resolver
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Resolver is a DNS resolver. The *net.Resolver used by Go implements
|
|
||||||
// this interface, but other implementations are possible.
|
|
||||||
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
|
|
||||||
}
|
|
|
@ -5,11 +5,12 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SaverResolver is a resolver that saves events
|
// SaverResolver is a resolver that saves events
|
||||||
type SaverResolver struct {
|
type SaverResolver struct {
|
||||||
Resolver
|
model.Resolver
|
||||||
Saver *trace.Saver
|
Saver *trace.Saver
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,5 +70,5 @@ func (txp SaverDNSTransport) RoundTrip(ctx context.Context, query []byte) ([]byt
|
||||||
return reply, err
|
return reply, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ Resolver = SaverResolver{}
|
var _ model.Resolver = SaverResolver{}
|
||||||
var _ RoundTripper = SaverDNSTransport{}
|
var _ RoundTripper = SaverDNSTransport{}
|
||||||
|
|
|
@ -7,12 +7,13 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SaverTLSHandshaker saves events occurring during the handshake
|
// SaverTLSHandshaker saves events occurring during the handshake
|
||||||
type SaverTLSHandshaker struct {
|
type SaverTLSHandshaker struct {
|
||||||
TLSHandshaker
|
model.TLSHandshaker
|
||||||
Saver *trace.Saver
|
Saver *trace.Saver
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,4 +47,4 @@ func (h SaverTLSHandshaker) Handshake(
|
||||||
return tlsconn, state, err
|
return tlsconn, state, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ TLSHandshaker = SaverTLSHandshaker{}
|
var _ model.TLSHandshaker = SaverTLSHandshaker{}
|
||||||
|
|
|
@ -3,7 +3,6 @@ package tlsdialer_test
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"net"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
@ -23,9 +22,7 @@ func TestSaverTLSHandshakerSuccessWithReadWrite(t *testing.T) {
|
||||||
saver := &trace.Saver{}
|
saver := &trace.Saver{}
|
||||||
tlsdlr := &netxlite.TLSDialerLegacy{
|
tlsdlr := &netxlite.TLSDialerLegacy{
|
||||||
Config: &tls.Config{NextProtos: nextprotos},
|
Config: &tls.Config{NextProtos: nextprotos},
|
||||||
Dialer: netxlite.NewDialerLegacyAdapter(
|
Dialer: dialer.New(&dialer.Config{ReadWriteSaver: saver}, netxlite.DefaultResolver),
|
||||||
dialer.New(&dialer.Config{ReadWriteSaver: saver}, &net.Resolver{}),
|
|
||||||
),
|
|
||||||
TLSHandshaker: tlsdialer.SaverTLSHandshaker{
|
TLSHandshaker: tlsdialer.SaverTLSHandshaker{
|
||||||
TLSHandshaker: &netxlite.TLSHandshakerConfigurable{},
|
TLSHandshaker: &netxlite.TLSHandshakerConfigurable{},
|
||||||
Saver: saver,
|
Saver: saver,
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
// Package tlsdialer contains code to establish TLS connections.
|
|
||||||
package tlsdialer
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"crypto/tls"
|
|
||||||
"net"
|
|
||||||
)
|
|
||||||
|
|
||||||
// UnderlyingDialer is the underlying dialer type.
|
|
||||||
type UnderlyingDialer interface {
|
|
||||||
DialContext(ctx context.Context, network, address string) (net.Conn, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TLSHandshaker is the generic TLS handshaker
|
|
||||||
type TLSHandshaker interface {
|
|
||||||
Handshake(ctx context.Context, conn net.Conn, config *tls.Config) (
|
|
||||||
net.Conn, tls.ConnectionState, error)
|
|
||||||
}
|
|
|
@ -51,7 +51,7 @@ type Session struct {
|
||||||
availableProbeServices []model.OOAPIService
|
availableProbeServices []model.OOAPIService
|
||||||
availableTestHelpers map[string][]model.OOAPIService
|
availableTestHelpers map[string][]model.OOAPIService
|
||||||
byteCounter *bytecounter.Counter
|
byteCounter *bytecounter.Counter
|
||||||
httpDefaultTransport netx.HTTPRoundTripper
|
httpDefaultTransport model.HTTPTransport
|
||||||
kvStore model.KeyValueStore
|
kvStore model.KeyValueStore
|
||||||
location *geolocate.Results
|
location *geolocate.Results
|
||||||
logger model.Logger
|
logger model.Logger
|
||||||
|
|
|
@ -1,14 +1,5 @@
|
||||||
package netxlite
|
package netxlite
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"crypto/tls"
|
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/lucas-clemente/quic-go"
|
|
||||||
"github.com/ooni/probe-cli/v3/internal/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
// These vars export internal names to legacy ooni/probe-cli code.
|
// These vars export internal names to legacy ooni/probe-cli code.
|
||||||
//
|
//
|
||||||
// Deprecated: do not use these names in new code.
|
// Deprecated: do not use these names in new code.
|
||||||
|
@ -44,143 +35,3 @@ type (
|
||||||
TLSDialerLegacy = tlsDialer
|
TLSDialerLegacy = tlsDialer
|
||||||
AddressResolver = resolverShortCircuitIPAddr
|
AddressResolver = resolverShortCircuitIPAddr
|
||||||
)
|
)
|
||||||
|
|
||||||
// ResolverLegacy performs domain name resolutions.
|
|
||||||
//
|
|
||||||
// Deprecated: new code should use Resolver.
|
|
||||||
//
|
|
||||||
// Existing code in ooni/probe-cli is still using this definition.
|
|
||||||
type ResolverLegacy interface {
|
|
||||||
// LookupHost behaves like net.Resolver.LookupHost.
|
|
||||||
LookupHost(ctx context.Context, hostname string) (addrs []string, err error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewResolverLegacyAdapter adapts a ResolverLegacy to
|
|
||||||
// become compatible with the Resolver definition.
|
|
||||||
func NewResolverLegacyAdapter(reso ResolverLegacy) model.Resolver {
|
|
||||||
return &ResolverLegacyAdapter{reso}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResolverLegacyAdapter makes a ResolverLegacy behave like a Resolver.
|
|
||||||
type ResolverLegacyAdapter struct {
|
|
||||||
ResolverLegacy
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ model.Resolver = &ResolverLegacyAdapter{}
|
|
||||||
|
|
||||||
type resolverLegacyNetworker interface {
|
|
||||||
Network() string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Network implements Resolver.Network.
|
|
||||||
func (r *ResolverLegacyAdapter) Network() string {
|
|
||||||
if rn, ok := r.ResolverLegacy.(resolverLegacyNetworker); ok {
|
|
||||||
return rn.Network()
|
|
||||||
}
|
|
||||||
return "adapter"
|
|
||||||
}
|
|
||||||
|
|
||||||
type resolverLegacyAddresser interface {
|
|
||||||
Address() string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Address implements Resolver.Address.
|
|
||||||
func (r *ResolverLegacyAdapter) Address() string {
|
|
||||||
if ra, ok := r.ResolverLegacy.(resolverLegacyAddresser); ok {
|
|
||||||
return ra.Address()
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
type resolverLegacyIdleConnectionsCloser interface {
|
|
||||||
CloseIdleConnections()
|
|
||||||
}
|
|
||||||
|
|
||||||
// CloseIdleConnections implements Resolver.CloseIdleConnections.
|
|
||||||
func (r *ResolverLegacyAdapter) CloseIdleConnections() {
|
|
||||||
if ra, ok := r.ResolverLegacy.(resolverLegacyIdleConnectionsCloser); ok {
|
|
||||||
ra.CloseIdleConnections()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// LookupHTTPS always returns ErrDNSNoTransport.
|
|
||||||
func (r *ResolverLegacyAdapter) LookupHTTPS(
|
|
||||||
ctx context.Context, domain string) (*model.HTTPSSvc, error) {
|
|
||||||
return nil, ErrNoDNSTransport
|
|
||||||
}
|
|
||||||
|
|
||||||
// DialerLegacy establishes network connections.
|
|
||||||
//
|
|
||||||
// Deprecated: please use Dialer instead.
|
|
||||||
//
|
|
||||||
// Existing code in probe-cli can use it until we
|
|
||||||
// have finished refactoring it.
|
|
||||||
type DialerLegacy interface {
|
|
||||||
// DialContext behaves like net.Dialer.DialContext.
|
|
||||||
DialContext(ctx context.Context, network, address string) (net.Conn, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewDialerLegacyAdapter adapts a DialerrLegacy to
|
|
||||||
// become compatible with the Dialer definition.
|
|
||||||
//
|
|
||||||
// Deprecated: do not use this function in new code.
|
|
||||||
func NewDialerLegacyAdapter(d DialerLegacy) model.Dialer {
|
|
||||||
return &DialerLegacyAdapter{d}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DialerLegacyAdapter makes a DialerLegacy behave like
|
|
||||||
// it was a Dialer type. If DialerLegacy is actually also
|
|
||||||
// a Dialer, this adapter will just forward missing calls,
|
|
||||||
// otherwise it will implement a sensible default action.
|
|
||||||
type DialerLegacyAdapter struct {
|
|
||||||
DialerLegacy
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ model.Dialer = &DialerLegacyAdapter{}
|
|
||||||
|
|
||||||
type dialerLegacyIdleConnectionsCloser interface {
|
|
||||||
CloseIdleConnections()
|
|
||||||
}
|
|
||||||
|
|
||||||
// CloseIdleConnections implements Dialer.CloseIdleConnections.
|
|
||||||
func (d *DialerLegacyAdapter) CloseIdleConnections() {
|
|
||||||
if ra, ok := d.DialerLegacy.(dialerLegacyIdleConnectionsCloser); ok {
|
|
||||||
ra.CloseIdleConnections()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// QUICContextDialer is a dialer for QUIC using Context.
|
|
||||||
//
|
|
||||||
// Deprecated: new code should use QUICDialer.
|
|
||||||
//
|
|
||||||
// Use NewQUICDialerFromContextDialerAdapter if you need to
|
|
||||||
// adapt to QUICDialer.
|
|
||||||
type QUICContextDialer interface {
|
|
||||||
// DialContext establishes a new QUIC session using the given
|
|
||||||
// network and address. The tlsConfig and the quicConfig arguments
|
|
||||||
// MUST NOT be nil. Returns either the session or an error.
|
|
||||||
DialContext(ctx context.Context, network, address string,
|
|
||||||
tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlySession, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewQUICDialerFromContextDialerAdapter creates a new
|
|
||||||
// QUICDialer from a QUICContextDialer.
|
|
||||||
func NewQUICDialerFromContextDialerAdapter(d QUICContextDialer) model.QUICDialer {
|
|
||||||
return &QUICContextDialerAdapter{d}
|
|
||||||
}
|
|
||||||
|
|
||||||
// QUICContextDialerAdapter adapts a QUICContextDialer to be a QUICDialer.
|
|
||||||
type QUICContextDialerAdapter struct {
|
|
||||||
QUICContextDialer
|
|
||||||
}
|
|
||||||
|
|
||||||
type quicContextDialerConnectionsCloser interface {
|
|
||||||
CloseIdleConnections()
|
|
||||||
}
|
|
||||||
|
|
||||||
// CloseIdleConnections implements QUICDialer.CloseIdleConnections.
|
|
||||||
func (d *QUICContextDialerAdapter) CloseIdleConnections() {
|
|
||||||
if o, ok := d.QUICContextDialer.(quicContextDialerConnectionsCloser); ok {
|
|
||||||
o.CloseIdleConnections()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,100 +0,0 @@
|
||||||
package netxlite
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"net"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/ooni/probe-cli/v3/internal/model/mocks"
|
|
||||||
nlmocks "github.com/ooni/probe-cli/v3/internal/netxlite/mocks"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestResolverLegacyAdapter(t *testing.T) {
|
|
||||||
t.Run("with compatible type", func(t *testing.T) {
|
|
||||||
var called bool
|
|
||||||
r := NewResolverLegacyAdapter(&mocks.Resolver{
|
|
||||||
MockNetwork: func() string {
|
|
||||||
return "network"
|
|
||||||
},
|
|
||||||
MockAddress: func() string {
|
|
||||||
return "address"
|
|
||||||
},
|
|
||||||
MockCloseIdleConnections: func() {
|
|
||||||
called = true
|
|
||||||
},
|
|
||||||
})
|
|
||||||
if r.Network() != "network" {
|
|
||||||
t.Fatal("invalid Network")
|
|
||||||
}
|
|
||||||
if r.Address() != "address" {
|
|
||||||
t.Fatal("invalid Address")
|
|
||||||
}
|
|
||||||
r.CloseIdleConnections()
|
|
||||||
if !called {
|
|
||||||
t.Fatal("not called")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("with incompatible type", func(t *testing.T) {
|
|
||||||
r := NewResolverLegacyAdapter(&net.Resolver{})
|
|
||||||
if r.Network() != "adapter" {
|
|
||||||
t.Fatal("invalid Network")
|
|
||||||
}
|
|
||||||
if r.Address() != "" {
|
|
||||||
t.Fatal("invalid Address")
|
|
||||||
}
|
|
||||||
r.CloseIdleConnections() // does not crash
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("for LookupHTTPS", func(t *testing.T) {
|
|
||||||
r := NewResolverLegacyAdapter(&net.Resolver{})
|
|
||||||
https, err := r.LookupHTTPS(context.Background(), "x.org")
|
|
||||||
if !errors.Is(err, ErrNoDNSTransport) {
|
|
||||||
t.Fatal("not the error we expected")
|
|
||||||
}
|
|
||||||
if https != nil {
|
|
||||||
t.Fatal("expected nil result")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDialerLegacyAdapter(t *testing.T) {
|
|
||||||
t.Run("with compatible type", func(t *testing.T) {
|
|
||||||
var called bool
|
|
||||||
r := NewDialerLegacyAdapter(&mocks.Dialer{
|
|
||||||
MockCloseIdleConnections: func() {
|
|
||||||
called = true
|
|
||||||
},
|
|
||||||
})
|
|
||||||
r.CloseIdleConnections()
|
|
||||||
if !called {
|
|
||||||
t.Fatal("not called")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("with incompatible type", func(t *testing.T) {
|
|
||||||
r := NewDialerLegacyAdapter(&net.Dialer{})
|
|
||||||
r.CloseIdleConnections() // does not crash
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestQUICContextDialerAdapter(t *testing.T) {
|
|
||||||
t.Run("with compatible type", func(t *testing.T) {
|
|
||||||
var called bool
|
|
||||||
d := NewQUICDialerFromContextDialerAdapter(&mocks.QUICDialer{
|
|
||||||
MockCloseIdleConnections: func() {
|
|
||||||
called = true
|
|
||||||
},
|
|
||||||
})
|
|
||||||
d.CloseIdleConnections()
|
|
||||||
if !called {
|
|
||||||
t.Fatal("not called")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("with incompatible type", func(t *testing.T) {
|
|
||||||
d := NewQUICDialerFromContextDialerAdapter(&nlmocks.QUICContextDialer{})
|
|
||||||
d.CloseIdleConnections() // does not crash
|
|
||||||
})
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user