ooni-probe-cli/internal/netxlite/dialer.go

191 lines
5.4 KiB
Go
Raw Normal View History

2021-06-23 15:53:12 +02:00
package netxlite
import (
"context"
"errors"
2021-06-23 15:53:12 +02:00
"net"
"sync"
2021-06-23 15:53:12 +02:00
"time"
)
// Dialer establishes network connections.
type Dialer interface {
// DialContext behaves like net.Dialer.DialContext.
DialContext(ctx context.Context, network, address string) (net.Conn, error)
// CloseIdleConnections closes idle connections, if any.
CloseIdleConnections()
2021-06-23 15:53:12 +02:00
}
// NewDialerWithResolver creates a dialer using the given resolver and logger.
func NewDialerWithResolver(logger Logger, resolver Resolver) Dialer {
return &dialerLogger{
Dialer: &dialerResolver{
Dialer: &dialerLogger{
Dialer: &dialerSystem{},
Logger: logger,
operationSuffix: "_address",
},
Resolver: resolver,
},
Logger: logger,
}
}
// NewDialerWithoutResolver creates a dialer that uses the given
// logger and fails with ErrNoResolver when it is passed a domain name.
func NewDialerWithoutResolver(logger Logger) Dialer {
return NewDialerWithResolver(logger, &nullResolver{})
}
// underlyingDialer is the Dialer we use by default.
var underlyingDialer = &net.Dialer{
2021-06-23 15:53:12 +02:00
Timeout: 15 * time.Second,
KeepAlive: 15 * time.Second,
}
// dialerSystem dials using Go stdlib.
type dialerSystem struct{}
// DialContext implements Dialer.DialContext.
func (d *dialerSystem) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
return underlyingDialer.DialContext(ctx, network, address)
}
// CloseIdleConnections implements Dialer.CloseIdleConnections.
func (d *dialerSystem) CloseIdleConnections() {
// nothing
}
var defaultDialer Dialer = &dialerSystem{}
2021-06-23 15:53:12 +02:00
refactor(netxlite): hide details without breaking the rest of the tree (#454) ## Description This PR continues the refactoring of `netx` under the following principles: 1. do not break the rest of the tree and do not engage in extensive tree-wide refactoring yet 2. move under `netxlite` clearly related subpackages (e.g., `iox`, `netxmocks`) 3. move into `internal/netxlite/internal` stuff that is clearly private of `netxlite` 4. hide implementation details in `netxlite` pending new factories 5. refactor `tls` code in `netxlite` to clearly separate `crypto/tls` code from `utls` code After each commit, I run `go test -short -race ./...` locally. Each individual commit explains what it does. I will squash, but this operation will preserve the original commit titles, so this will give further insight on each step. ## Commits * refactor: rename netxmocks -> netxlite/mocks Part of https://github.com/ooni/probe/issues/1591 * refactor: rename quicx -> netxlite/quicx See https://github.com/ooni/probe/issues/1591 * refactor: rename iox -> netxlite/iox Regenerate sources and make sure the tests pass. See https://github.com/ooni/probe/issues/1591. * refactor(iox): move MockableReader to netxlite/mocks See https://github.com/ooni/probe/issues/1591 * refactor(netxlite): generator is an implementation detail See https://github.com/ooni/probe/issues/1591 * refactor(netxlite): separate tls and utls code See https://github.com/ooni/probe/issues/1591 * refactor(netxlite): hide most types but keep old names as legacy With this change we avoid breaking the rest of the tree, but we start hiding some implementation details a bit. Factories will follow. See https://github.com/ooni/probe/issues/1591
2021-09-05 14:49:38 +02:00
// dialerResolver is a dialer that uses the configured Resolver to resolver a
2021-06-23 15:53:12 +02:00
// domain name to IP addresses, and the configured Dialer to connect.
refactor(netxlite): hide details without breaking the rest of the tree (#454) ## Description This PR continues the refactoring of `netx` under the following principles: 1. do not break the rest of the tree and do not engage in extensive tree-wide refactoring yet 2. move under `netxlite` clearly related subpackages (e.g., `iox`, `netxmocks`) 3. move into `internal/netxlite/internal` stuff that is clearly private of `netxlite` 4. hide implementation details in `netxlite` pending new factories 5. refactor `tls` code in `netxlite` to clearly separate `crypto/tls` code from `utls` code After each commit, I run `go test -short -race ./...` locally. Each individual commit explains what it does. I will squash, but this operation will preserve the original commit titles, so this will give further insight on each step. ## Commits * refactor: rename netxmocks -> netxlite/mocks Part of https://github.com/ooni/probe/issues/1591 * refactor: rename quicx -> netxlite/quicx See https://github.com/ooni/probe/issues/1591 * refactor: rename iox -> netxlite/iox Regenerate sources and make sure the tests pass. See https://github.com/ooni/probe/issues/1591. * refactor(iox): move MockableReader to netxlite/mocks See https://github.com/ooni/probe/issues/1591 * refactor(netxlite): generator is an implementation detail See https://github.com/ooni/probe/issues/1591 * refactor(netxlite): separate tls and utls code See https://github.com/ooni/probe/issues/1591 * refactor(netxlite): hide most types but keep old names as legacy With this change we avoid breaking the rest of the tree, but we start hiding some implementation details a bit. Factories will follow. See https://github.com/ooni/probe/issues/1591
2021-09-05 14:49:38 +02:00
type dialerResolver struct {
2021-06-23 15:53:12 +02:00
// Dialer is the underlying Dialer.
Dialer Dialer
// Resolver is the underlying Resolver.
Resolver Resolver
}
refactor(netxlite): hide details without breaking the rest of the tree (#454) ## Description This PR continues the refactoring of `netx` under the following principles: 1. do not break the rest of the tree and do not engage in extensive tree-wide refactoring yet 2. move under `netxlite` clearly related subpackages (e.g., `iox`, `netxmocks`) 3. move into `internal/netxlite/internal` stuff that is clearly private of `netxlite` 4. hide implementation details in `netxlite` pending new factories 5. refactor `tls` code in `netxlite` to clearly separate `crypto/tls` code from `utls` code After each commit, I run `go test -short -race ./...` locally. Each individual commit explains what it does. I will squash, but this operation will preserve the original commit titles, so this will give further insight on each step. ## Commits * refactor: rename netxmocks -> netxlite/mocks Part of https://github.com/ooni/probe/issues/1591 * refactor: rename quicx -> netxlite/quicx See https://github.com/ooni/probe/issues/1591 * refactor: rename iox -> netxlite/iox Regenerate sources and make sure the tests pass. See https://github.com/ooni/probe/issues/1591. * refactor(iox): move MockableReader to netxlite/mocks See https://github.com/ooni/probe/issues/1591 * refactor(netxlite): generator is an implementation detail See https://github.com/ooni/probe/issues/1591 * refactor(netxlite): separate tls and utls code See https://github.com/ooni/probe/issues/1591 * refactor(netxlite): hide most types but keep old names as legacy With this change we avoid breaking the rest of the tree, but we start hiding some implementation details a bit. Factories will follow. See https://github.com/ooni/probe/issues/1591
2021-09-05 14:49:38 +02:00
var _ Dialer = &dialerResolver{}
2021-06-23 15:53:12 +02:00
// DialContext implements Dialer.DialContext.
refactor(netxlite): hide details without breaking the rest of the tree (#454) ## Description This PR continues the refactoring of `netx` under the following principles: 1. do not break the rest of the tree and do not engage in extensive tree-wide refactoring yet 2. move under `netxlite` clearly related subpackages (e.g., `iox`, `netxmocks`) 3. move into `internal/netxlite/internal` stuff that is clearly private of `netxlite` 4. hide implementation details in `netxlite` pending new factories 5. refactor `tls` code in `netxlite` to clearly separate `crypto/tls` code from `utls` code After each commit, I run `go test -short -race ./...` locally. Each individual commit explains what it does. I will squash, but this operation will preserve the original commit titles, so this will give further insight on each step. ## Commits * refactor: rename netxmocks -> netxlite/mocks Part of https://github.com/ooni/probe/issues/1591 * refactor: rename quicx -> netxlite/quicx See https://github.com/ooni/probe/issues/1591 * refactor: rename iox -> netxlite/iox Regenerate sources and make sure the tests pass. See https://github.com/ooni/probe/issues/1591. * refactor(iox): move MockableReader to netxlite/mocks See https://github.com/ooni/probe/issues/1591 * refactor(netxlite): generator is an implementation detail See https://github.com/ooni/probe/issues/1591 * refactor(netxlite): separate tls and utls code See https://github.com/ooni/probe/issues/1591 * refactor(netxlite): hide most types but keep old names as legacy With this change we avoid breaking the rest of the tree, but we start hiding some implementation details a bit. Factories will follow. See https://github.com/ooni/probe/issues/1591
2021-09-05 14:49:38 +02:00
func (d *dialerResolver) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
2021-06-23 15:53:12 +02:00
onlyhost, onlyport, err := net.SplitHostPort(address)
if err != nil {
return nil, err
}
addrs, err := d.lookupHost(ctx, onlyhost)
2021-06-23 15:53:12 +02:00
if err != nil {
return nil, err
}
// TODO(bassosimone): here we should be using multierror rather
// than just calling ReduceErrors. We are not ready to do that
// yet, though. To do that, we need first to modify nettests so
// that we actually avoid dialing when measuring.
//
// See also the quirks.go file. This is clearly a QUIRK.
addrs = quirkSortIPAddrs(addrs)
2021-06-23 15:53:12 +02:00
var errorslist []error
for _, addr := range addrs {
target := net.JoinHostPort(addr, onlyport)
conn, err := d.Dialer.DialContext(ctx, network, target)
if err == nil {
return conn, nil
}
errorslist = append(errorslist, err)
}
return nil, quirkReduceErrors(errorslist)
2021-06-23 15:53:12 +02:00
}
// lookupHost performs a domain name resolution.
refactor(netxlite): hide details without breaking the rest of the tree (#454) ## Description This PR continues the refactoring of `netx` under the following principles: 1. do not break the rest of the tree and do not engage in extensive tree-wide refactoring yet 2. move under `netxlite` clearly related subpackages (e.g., `iox`, `netxmocks`) 3. move into `internal/netxlite/internal` stuff that is clearly private of `netxlite` 4. hide implementation details in `netxlite` pending new factories 5. refactor `tls` code in `netxlite` to clearly separate `crypto/tls` code from `utls` code After each commit, I run `go test -short -race ./...` locally. Each individual commit explains what it does. I will squash, but this operation will preserve the original commit titles, so this will give further insight on each step. ## Commits * refactor: rename netxmocks -> netxlite/mocks Part of https://github.com/ooni/probe/issues/1591 * refactor: rename quicx -> netxlite/quicx See https://github.com/ooni/probe/issues/1591 * refactor: rename iox -> netxlite/iox Regenerate sources and make sure the tests pass. See https://github.com/ooni/probe/issues/1591. * refactor(iox): move MockableReader to netxlite/mocks See https://github.com/ooni/probe/issues/1591 * refactor(netxlite): generator is an implementation detail See https://github.com/ooni/probe/issues/1591 * refactor(netxlite): separate tls and utls code See https://github.com/ooni/probe/issues/1591 * refactor(netxlite): hide most types but keep old names as legacy With this change we avoid breaking the rest of the tree, but we start hiding some implementation details a bit. Factories will follow. See https://github.com/ooni/probe/issues/1591
2021-09-05 14:49:38 +02:00
func (d *dialerResolver) lookupHost(ctx context.Context, hostname string) ([]string, error) {
2021-06-23 15:53:12 +02:00
if net.ParseIP(hostname) != nil {
return []string{hostname}, nil
}
return d.Resolver.LookupHost(ctx, hostname)
}
// CloseIdleConnections implements Dialer.CloseIdleConnections.
func (d *dialerResolver) CloseIdleConnections() {
d.Dialer.CloseIdleConnections()
d.Resolver.CloseIdleConnections()
}
refactor(netxlite): hide details without breaking the rest of the tree (#454) ## Description This PR continues the refactoring of `netx` under the following principles: 1. do not break the rest of the tree and do not engage in extensive tree-wide refactoring yet 2. move under `netxlite` clearly related subpackages (e.g., `iox`, `netxmocks`) 3. move into `internal/netxlite/internal` stuff that is clearly private of `netxlite` 4. hide implementation details in `netxlite` pending new factories 5. refactor `tls` code in `netxlite` to clearly separate `crypto/tls` code from `utls` code After each commit, I run `go test -short -race ./...` locally. Each individual commit explains what it does. I will squash, but this operation will preserve the original commit titles, so this will give further insight on each step. ## Commits * refactor: rename netxmocks -> netxlite/mocks Part of https://github.com/ooni/probe/issues/1591 * refactor: rename quicx -> netxlite/quicx See https://github.com/ooni/probe/issues/1591 * refactor: rename iox -> netxlite/iox Regenerate sources and make sure the tests pass. See https://github.com/ooni/probe/issues/1591. * refactor(iox): move MockableReader to netxlite/mocks See https://github.com/ooni/probe/issues/1591 * refactor(netxlite): generator is an implementation detail See https://github.com/ooni/probe/issues/1591 * refactor(netxlite): separate tls and utls code See https://github.com/ooni/probe/issues/1591 * refactor(netxlite): hide most types but keep old names as legacy With this change we avoid breaking the rest of the tree, but we start hiding some implementation details a bit. Factories will follow. See https://github.com/ooni/probe/issues/1591
2021-09-05 14:49:38 +02:00
// dialerLogger is a Dialer with logging.
type dialerLogger struct {
// Dialer is the underlying dialer.
Dialer Dialer
// Logger is the underlying logger.
2021-06-23 15:53:12 +02:00
Logger Logger
// operationSuffix is appended to the operation name.
//
// We use this suffix to distinguish the output from dialing
// with the output from dialing an IP address when we are
// using a dialer without resolver, where otherwise both lines
// would read something like `dial 8.8.8.8:443...`
operationSuffix string
2021-06-23 15:53:12 +02:00
}
refactor(netxlite): hide details without breaking the rest of the tree (#454) ## Description This PR continues the refactoring of `netx` under the following principles: 1. do not break the rest of the tree and do not engage in extensive tree-wide refactoring yet 2. move under `netxlite` clearly related subpackages (e.g., `iox`, `netxmocks`) 3. move into `internal/netxlite/internal` stuff that is clearly private of `netxlite` 4. hide implementation details in `netxlite` pending new factories 5. refactor `tls` code in `netxlite` to clearly separate `crypto/tls` code from `utls` code After each commit, I run `go test -short -race ./...` locally. Each individual commit explains what it does. I will squash, but this operation will preserve the original commit titles, so this will give further insight on each step. ## Commits * refactor: rename netxmocks -> netxlite/mocks Part of https://github.com/ooni/probe/issues/1591 * refactor: rename quicx -> netxlite/quicx See https://github.com/ooni/probe/issues/1591 * refactor: rename iox -> netxlite/iox Regenerate sources and make sure the tests pass. See https://github.com/ooni/probe/issues/1591. * refactor(iox): move MockableReader to netxlite/mocks See https://github.com/ooni/probe/issues/1591 * refactor(netxlite): generator is an implementation detail See https://github.com/ooni/probe/issues/1591 * refactor(netxlite): separate tls and utls code See https://github.com/ooni/probe/issues/1591 * refactor(netxlite): hide most types but keep old names as legacy With this change we avoid breaking the rest of the tree, but we start hiding some implementation details a bit. Factories will follow. See https://github.com/ooni/probe/issues/1591
2021-09-05 14:49:38 +02:00
var _ Dialer = &dialerLogger{}
2021-06-23 15:53:12 +02:00
// DialContext implements Dialer.DialContext
refactor(netxlite): hide details without breaking the rest of the tree (#454) ## Description This PR continues the refactoring of `netx` under the following principles: 1. do not break the rest of the tree and do not engage in extensive tree-wide refactoring yet 2. move under `netxlite` clearly related subpackages (e.g., `iox`, `netxmocks`) 3. move into `internal/netxlite/internal` stuff that is clearly private of `netxlite` 4. hide implementation details in `netxlite` pending new factories 5. refactor `tls` code in `netxlite` to clearly separate `crypto/tls` code from `utls` code After each commit, I run `go test -short -race ./...` locally. Each individual commit explains what it does. I will squash, but this operation will preserve the original commit titles, so this will give further insight on each step. ## Commits * refactor: rename netxmocks -> netxlite/mocks Part of https://github.com/ooni/probe/issues/1591 * refactor: rename quicx -> netxlite/quicx See https://github.com/ooni/probe/issues/1591 * refactor: rename iox -> netxlite/iox Regenerate sources and make sure the tests pass. See https://github.com/ooni/probe/issues/1591. * refactor(iox): move MockableReader to netxlite/mocks See https://github.com/ooni/probe/issues/1591 * refactor(netxlite): generator is an implementation detail See https://github.com/ooni/probe/issues/1591 * refactor(netxlite): separate tls and utls code See https://github.com/ooni/probe/issues/1591 * refactor(netxlite): hide most types but keep old names as legacy With this change we avoid breaking the rest of the tree, but we start hiding some implementation details a bit. Factories will follow. See https://github.com/ooni/probe/issues/1591
2021-09-05 14:49:38 +02:00
func (d *dialerLogger) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
d.Logger.Debugf("dial%s %s/%s...", d.operationSuffix, address, network)
2021-06-23 15:53:12 +02:00
start := time.Now()
conn, err := d.Dialer.DialContext(ctx, network, address)
elapsed := time.Since(start)
if err != nil {
d.Logger.Debugf("dial%s %s/%s... %s in %s", d.operationSuffix,
address, network, err, elapsed)
return nil, err
}
d.Logger.Debugf("dial%s %s/%s... ok in %s", d.operationSuffix,
address, network, elapsed)
return conn, nil
2021-06-23 15:53:12 +02:00
}
// CloseIdleConnections implements Dialer.CloseIdleConnections.
func (d *dialerLogger) CloseIdleConnections() {
d.Dialer.CloseIdleConnections()
}
// ErrNoConnReuse indicates we cannot reuse the connection provided
// to a single use (possibly TLS) dialer.
var ErrNoConnReuse = errors.New("cannot reuse connection")
// NewSingleUseDialer returns a dialer that returns the given connection once
// and after that always fails with the ErrNoConnReuse error.
func NewSingleUseDialer(conn net.Conn) Dialer {
return &dialerSingleUse{conn: conn}
}
// dialerSingleUse is the type of Dialer returned by NewSingleDialer.
type dialerSingleUse struct {
sync.Mutex
conn net.Conn
}
var _ Dialer = &dialerSingleUse{}
// DialContext implements Dialer.DialContext.
func (s *dialerSingleUse) DialContext(ctx context.Context, network string, addr string) (net.Conn, error) {
defer s.Unlock()
s.Lock()
if s.conn == nil {
return nil, ErrNoConnReuse
}
var conn net.Conn
conn, s.conn = s.conn, nil
return conn, nil
}
// CloseIdleConnections closes idle connections.
func (s *dialerSingleUse) CloseIdleConnections() {
// nothing
}