ooni-probe-cli/internal/tunnel/fake.go
Simone Basso 3cb6c7c6fb
refactor: move tunnel pkg down one level (#358)
* refactor: move tunnel pkg down one level

While there, reduce unnecessary dependency on external packages.

* file I forgot to commit
2021-06-04 15:15:41 +02:00

81 lines
1.8 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) {
// do the same things other tunnels do:
//
// 1. abort if context is cancelled
//
// 2. check for tunnelDir being not empty
//
// 3. attempt to create tunnelDir
//
// after that, it's all fake and we just create a simple
// socks5 server that we can use
select {
case <-ctx.Done():
return nil, ctx.Err() // simplifies unit testing this code
default:
}
if config.TunnelDir == "" {
return nil, ErrEmptyTunnelDir
}
if err := config.mkdirAll(config.TunnelDir, 0700); err != nil {
return nil, err
}
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
}