973501dd11
This functionality should be helpful to test that the general interface of the tunnel package is okay from the engine package. Part of https://github.com/ooni/probe/issues/985
68 lines
1.4 KiB
Go
68 lines
1.4 KiB
Go
package tunnel
|
|
|
|
import (
|
|
"context"
|
|
"net"
|
|
"net/url"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/armon/go-socks5"
|
|
)
|
|
|
|
// fakeTunnel is a fake tunnel.
|
|
type fakeTunnel struct {
|
|
addr net.Addr
|
|
bootstrapTime time.Duration
|
|
listener net.Listener
|
|
once sync.Once
|
|
}
|
|
|
|
// BootstrapTime implements Tunnel.BootstrapTime.
|
|
func (t *fakeTunnel) BootstrapTime() time.Duration {
|
|
return t.bootstrapTime
|
|
}
|
|
|
|
// Stop implements Tunnel.Stop.
|
|
func (t *fakeTunnel) Stop() {
|
|
// Implementation note: closing the listener causes
|
|
// the socks5 server.Serve to return an error
|
|
t.once.Do(func() { t.listener.Close() })
|
|
}
|
|
|
|
// SOCKS5ProxyURL returns the SOCKS5 proxy URL.
|
|
func (t *fakeTunnel) SOCKS5ProxyURL() *url.URL {
|
|
return &url.URL{
|
|
Scheme: "socks5",
|
|
Host: t.addr.String(),
|
|
}
|
|
}
|
|
|
|
// fakeStart starts the fake tunnel.
|
|
func fakeStart(ctx context.Context, config *Config) (Tunnel, error) {
|
|
select {
|
|
case <-ctx.Done():
|
|
return nil, ctx.Err() // simplifies unit testing this code
|
|
default:
|
|
}
|
|
if config.TunnelDir == "" {
|
|
return nil, ErrEmptyTunnelDir
|
|
}
|
|
server, err := config.socks5New(&socks5.Config{})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
start := time.Now()
|
|
listener, err := config.netListen("tcp", "127.0.0.1:0")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
bootstrapTime := time.Since(start)
|
|
go server.Serve(listener)
|
|
return &fakeTunnel{
|
|
addr: listener.Addr(),
|
|
bootstrapTime: bootstrapTime,
|
|
listener: listener,
|
|
}, nil
|
|
}
|