refactor(netx/dialer): we can simplify the proxy (#371)

The socks5 factory always returns a DialContext capable dialer. We just
need to cast to obtain such a dialer.

Also, the code will use the DialContext if passed a dialer that
implements DialContext.

Write a test that proves my point.

Part of https://github.com/ooni/probe/issues/1591.
This commit is contained in:
Simone Basso 2021-06-09 07:11:31 +02:00 committed by GitHub
commit b7a6dbe47b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 31 additions and 148 deletions

View file

@ -17,6 +17,9 @@ type ProxyDialer struct {
ProxyURL *url.URL
}
// ErrProxyUnsupportedScheme indicates we don't support a protocol scheme.
var ErrProxyUnsupportedScheme = errors.New("proxy: unsupported scheme")
// DialContext implements Dialer.DialContext
func (d ProxyDialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
url := d.ProxyURL
@ -24,38 +27,18 @@ func (d ProxyDialer) DialContext(ctx context.Context, network, address string) (
return d.Dialer.DialContext(ctx, network, address)
}
if url.Scheme != "socks5" {
return nil, errors.New("Scheme is not socks5")
return nil, ErrProxyUnsupportedScheme
}
// the code at proxy/socks5.go never fails; see https://git.io/JfJ4g
child, _ := proxy.SOCKS5(
network, url.Host, nil, proxyDialerWrapper{Dialer: d.Dialer})
network, url.Host, nil, proxyDialerWrapper{d.Dialer})
return d.dial(ctx, child, network, address)
}
func (d ProxyDialer) dial(
ctx context.Context, child proxy.Dialer, network, address string) (net.Conn, error) {
connch := make(chan net.Conn)
errch := make(chan error, 1)
go func() {
conn, err := child.Dial(network, address)
if err != nil {
errch <- err
return
}
select {
case connch <- conn:
default:
conn.Close()
}
}()
select {
case <-ctx.Done():
return nil, ctx.Err()
case err := <-errch:
return nil, err
case conn := <-connch:
return conn, nil
}
cd := child.(proxy.ContextDialer) // will work
return cd.DialContext(ctx, network, address)
}
// proxyDialerWrapper is required because SOCKS5 expects a Dialer.Dial type but internally
@ -68,5 +51,5 @@ type proxyDialerWrapper struct {
}
func (d proxyDialerWrapper) Dial(network, address string) (net.Conn, error) {
return d.DialContext(context.Background(), network, address)
panic(errors.New("proxyDialerWrapper.Dial should not be called directly"))
}