torsvc: Replace MultiNet with polymorphic Net interface

This commit is contained in:
MeshCollider 2018-01-23 16:59:15 +13:00 committed by Olaoluwa Osuntokun
parent 4affab7bd7
commit 69f207e23f
3 changed files with 69 additions and 44 deletions

@ -191,7 +191,7 @@ type config struct {
Alias string `long:"alias" description:"The node alias. Used as a moniker by peers and intelligence services"` Alias string `long:"alias" description:"The node alias. Used as a moniker by peers and intelligence services"`
Color string `long:"color" description:"The color of the node in hex format (i.e. '#3399FF'). Used to customize node appearance in intelligence services"` Color string `long:"color" description:"The color of the node in hex format (i.e. '#3399FF'). Used to customize node appearance in intelligence services"`
net *torsvc.MultiNet net torsvc.Net
} }
// loadConfig initializes and parses the config using a config file and command // loadConfig initializes and parses the config using a config file and command
@ -301,7 +301,7 @@ func loadConfig() (*config, error) {
// functions. When Tor's proxy is specified, the dial function is set to // functions. When Tor's proxy is specified, the dial function is set to
// the proxy specific dial function and the DNS resolution functions use // the proxy specific dial function and the DNS resolution functions use
// Tor. // Tor.
cfg.net = &torsvc.MultiNet{Tor: false} cfg.net = &torsvc.RegularNet{}
if cfg.Tor.Socks != "" && cfg.Tor.DNS != "" { if cfg.Tor.Socks != "" && cfg.Tor.DNS != "" {
// Validate Tor port number // Validate Tor port number
torport, err := strconv.Atoi(cfg.Tor.Socks) torport, err := strconv.Atoi(cfg.Tor.Socks)
@ -323,8 +323,10 @@ func loadConfig() (*config, error) {
return nil, err return nil, err
} }
cfg.net.TorDNS = cfg.Tor.DNS cfg.net = &torsvc.TorProxyNet{
cfg.net.TorSocks = cfg.Tor.Socks TorDNS: cfg.Tor.DNS,
TorSocks: cfg.Tor.Socks,
}
// If we are using Tor, since we only want connections routed // If we are using Tor, since we only want connections routed
// through Tor, listening is disabled. // through Tor, listening is disabled.

@ -4,10 +4,21 @@ import (
"net" "net"
) )
// Net is an interface housing a Dial function and several DNS functions. // Net is an interface housing a Dial function and several DNS functions, to
// abstract the implementation of these functions over both Regular and Tor
type Net interface { type Net interface {
// Dial accepts a network and address and returns a connection to a remote
// peer.
Dial(string, string) (net.Conn, error) Dial(string, string) (net.Conn, error)
// LookupHost performs DNS resolution on a given hostname and returns
// addresses of that hostname
LookupHost(string) ([]string, error) LookupHost(string) ([]string, error)
// LookupSRV allows a service and network to be specified and makes queries
// to a given DNS server for SRV queries.
LookupSRV(string, string, string) (string, []*net.SRV, error) LookupSRV(string, string, string) (string, []*net.SRV, error)
// ResolveTCPAddr is a used to resolve publicly advertised TCP addresses.
ResolveTCPAddr(string, string) (*net.TCPAddr, error) ResolveTCPAddr(string, string) (*net.TCPAddr, error)
} }

@ -5,54 +5,66 @@ import (
"net" "net"
) )
// MultiNet is an implementation of the Net interface that abstracts away the // RegularNet is an implementation of the Net interface that defines behaviour
// "net" and "torsvc" functions from the user. This can be used to "switch" // for Regular network connections
// Tor functionality on/off based on the MultiNet.Tor boolean. MultiNet allows type RegularNet struct{}
// for callers to call net functions when necessary and torsvc functions when
// necessary
type MultiNet struct {
Tor bool
TorDNS string
TorSocks string
}
// A compile time check to ensure MultiNet implements the Net interface. // Dial on the regular network uses net.Dial
var _ Net = (*MultiNet)(nil) func (r *RegularNet) Dial(network, address string) (net.Conn, error) {
// Dial uses either the "net" or "torsvc" dial function.
func (m *MultiNet) Dial(network, address string) (net.Conn, error) {
if m.Tor {
if network != "tcp" {
return nil, fmt.Errorf("Cannot dial non-tcp network via Tor")
}
return TorDial(address, m.TorSocks)
}
return net.Dial(network, address) return net.Dial(network, address)
} }
// LookupHost uses either the "net" or "torsvc LookupHost function. // LookupHost for regular network uses the net.LookupHost function
func (m *MultiNet) LookupHost(host string) ([]string, error) { func (r *RegularNet) LookupHost(host string) ([]string, error) {
if m.Tor {
return TorLookupHost(host, m.TorSocks)
}
return net.LookupHost(host) return net.LookupHost(host)
} }
// LookupSRV uses either the "net" or "torsvc" LookupSRV function. // LookupSRV for regular network uses net.LookupSRV function
func (m *MultiNet) LookupSRV(service, proto, name string) (string, []*net.SRV, error) { func (r *RegularNet) LookupSRV(service, proto, name string) (string, []*net.SRV, error) {
if m.Tor {
return TorLookupSRV(service, proto, name, m.TorSocks, m.TorDNS)
}
return net.LookupSRV(service, proto, name) return net.LookupSRV(service, proto, name)
} }
// ResolveTCPAddr uses either the "net" or "torsvc" ResolveTCP function. // ResolveTCPAddr for regular network uses net.ResolveTCPAddr function
func (m *MultiNet) ResolveTCPAddr(network, address string) (*net.TCPAddr, error) { func (r *RegularNet) ResolveTCPAddr(network, address string) (*net.TCPAddr, error) {
if m.Tor {
if network != "tcp" {
return nil, fmt.Errorf("Cannot dial non-tcp network via Tor")
}
return TorResolveTCP(address, m.TorSocks)
}
return net.ResolveTCPAddr(network, address) return net.ResolveTCPAddr(network, address)
} }
// TorProxyNet is an implementation of the Net interface that defines behaviour
// for Tor network connections
type TorProxyNet struct {
// TorDNS is the IP:PORT of the DNS server for Tor to use for SRV queries
TorDNS string
// TorSocks is the port which Tor's exposed SOCKS5 proxy is listening on.
// This is used for an outbound-only mode, so the node will not listen for
// incoming connections
TorSocks string
}
// Dial on the Tor network uses the torsvc TorDial() function, and requires
// that network specified be tcp because only that is supported
func (t *TorProxyNet) Dial(network, address string) (net.Conn, error) {
if network != "tcp" {
return nil, fmt.Errorf("Cannot dial non-tcp network via Tor")
}
return TorDial(address, t.TorSocks)
}
// LookupHost on Tor network uses the torsvc TorLookupHost function.
func (t *TorProxyNet) LookupHost(host string) ([]string, error) {
return TorLookupHost(host, t.TorSocks)
}
// LookupSRV on Tor network uses the torsvc TorLookupHost function.
func (t *TorProxyNet) LookupSRV(service, proto, name string) (string, []*net.SRV, error) {
return TorLookupSRV(service, proto, name, t.TorSocks, t.TorDNS)
}
// ResolveTCPAddr on Tor network uses the towsvc TorResolveTCP function, and
// requires network to be "tcp" because only "tcp" is supported
func (t *TorProxyNet) ResolveTCPAddr(network, address string) (*net.TCPAddr, error) {
if network != "tcp" {
return nil, fmt.Errorf("Cannot dial non-tcp network via Tor")
}
return TorResolveTCP(address, t.TorSocks)
}