2
0
mirror of synced 2025-02-23 22:28:11 +00:00

Support different hosts for each network

CircleCI's localhost hostname doesn't resolve for IPv6.
This commit is contained in:
Matt Joiner 2018-04-12 15:06:53 +10:00
parent 319e57d1c6
commit b5df073217
7 changed files with 51 additions and 30 deletions

View File

@ -225,7 +225,7 @@ func NewClient(cfg *Config) (cl *Client, err error) {
} }
} }
cl.conns, err = listenAll(cl.enabledPeerNetworks(), cl.config.ListenAddr) cl.conns, err = listenAll(cl.enabledPeerNetworks(), cl.config.ListenHost, cl.config.ListenPort)
if err != nil { if err != nil {
return return
} }

View File

@ -9,6 +9,7 @@ import (
"net" "net"
"os" "os"
"path/filepath" "path/filepath"
"strings"
"sync" "sync"
"testing" "testing"
"time" "time"
@ -31,7 +32,13 @@ import (
func TestingConfig() *Config { func TestingConfig() *Config {
return &Config{ return &Config{
ListenAddr: "localhost:0", ListenHost: func(network string) string {
if strings.Contains(network, "4") {
return "127.0.0.1"
} else {
return "::1"
}
},
NoDHT: true, NoDHT: true,
DataDir: tempDir(), DataDir: tempDir(),
DisableTrackers: true, DisableTrackers: true,
@ -540,7 +547,7 @@ func BenchmarkAddLargeTorrent(b *testing.B) {
cfg := TestingConfig() cfg := TestingConfig()
cfg.DisableTCP = true cfg.DisableTCP = true
cfg.DisableUTP = true cfg.DisableUTP = true
cfg.ListenAddr = "redonk" cfg.ListenHost = func(string) string { return "redonk" }
cl, err := NewClient(cfg) cl, err := NewClient(cfg)
require.NoError(b, err) require.NoError(b, err)
defer cl.Close() defer cl.Close()
@ -756,7 +763,7 @@ func TestAddTorrentPiecesNotAlreadyCompleted(t *testing.T) {
func TestAddMetainfoWithNodes(t *testing.T) { func TestAddMetainfoWithNodes(t *testing.T) {
cfg := TestingConfig() cfg := TestingConfig()
cfg.ListenAddr = ":0" cfg.ListenHost = func(string) string { return "" }
cfg.NoDHT = false cfg.NoDHT = false
cfg.DhtStartingNodes = func() ([]dht.Addr, error) { return nil, nil } cfg.DhtStartingNodes = func() ([]dht.Addr, error) { return nil, nil }
// For now, we want to just jam the nodes into the table, without // For now, we want to just jam the nodes into the table, without
@ -1065,8 +1072,7 @@ func TestClientAddressInUse(t *testing.T) {
if s != nil { if s != nil {
defer s.Close() defer s.Close()
} }
cfg := TestingConfig() cfg := TestingConfig().SetListenAddr(":50007")
cfg.ListenAddr = ":50007"
cl, err := NewClient(cfg) cl, err := NewClient(cfg)
require.Error(t, err) require.Error(t, err)
require.Nil(t, cl) require.Nil(t, cl)

View File

@ -162,7 +162,7 @@ func main() {
clientConfig.DefaultStorage = storage.NewMMap("") clientConfig.DefaultStorage = storage.NewMMap("")
} }
if flags.Addr != nil { if flags.Addr != nil {
clientConfig.ListenAddr = flags.Addr.String() clientConfig.SetListenAddr(flags.Addr.String())
} }
if flags.UploadRate != -1 { if flags.UploadRate != -1 {
clientConfig.UploadRateLimiter = rate.NewLimiter(rate.Limit(flags.UploadRate), 256<<10) clientConfig.UploadRateLimiter = rate.NewLimiter(rate.Limit(flags.UploadRate), 256<<10)

View File

@ -86,12 +86,13 @@ func mainExitCode() int {
defer fuse.Unmount(args.MountDir) defer fuse.Unmount(args.MountDir)
// TODO: Think about the ramifications of exiting not due to a signal. // TODO: Think about the ramifications of exiting not due to a signal.
defer conn.Close() defer conn.Close()
client, err := torrent.NewClient(&torrent.Config{ cfg := torrent.Config{
DataDir: args.DownloadDir, DataDir: args.DownloadDir,
DisableTrackers: args.DisableTrackers, DisableTrackers: args.DisableTrackers,
ListenAddr: args.ListenAddr.String(),
NoUpload: true, // Ensure that downloads are responsive. NoUpload: true, // Ensure that downloads are responsive.
}) }
cfg.SetListenAddr(args.ListenAddr.String())
client, err := torrent.NewClient(&cfg)
if err != nil { if err != nil {
log.Print(err) log.Print(err)
return 1 return 1

View File

@ -9,6 +9,8 @@ import (
"golang.org/x/time/rate" "golang.org/x/time/rate"
"github.com/anacrolix/dht" "github.com/anacrolix/dht"
"github.com/anacrolix/missinggo"
"github.com/anacrolix/missinggo/expect"
"github.com/anacrolix/torrent/iplist" "github.com/anacrolix/torrent/iplist"
"github.com/anacrolix/torrent/storage" "github.com/anacrolix/torrent/storage"
) )
@ -33,7 +35,8 @@ type Config struct {
// The address to listen for new uTP and TCP bittorrent protocol // The address to listen for new uTP and TCP bittorrent protocol
// connections. DHT shares a UDP socket with uTP unless configured // connections. DHT shares a UDP socket with uTP unless configured
// otherwise. // otherwise.
ListenAddr string `long:"listen-addr" value-name:"HOST:PORT"` ListenHost func(network string) string
ListenPort int
NoDefaultPortForwarding bool NoDefaultPortForwarding bool
// Don't announce to trackers. This only leaves DHT to discover peers. // Don't announce to trackers. This only leaves DHT to discover peers.
DisableTrackers bool `long:"disable-trackers"` DisableTrackers bool `long:"disable-trackers"`
@ -112,6 +115,14 @@ type Config struct {
PublicIp6 net.IP PublicIp6 net.IP
} }
func (cfg *Config) SetListenAddr(addr string) *Config {
host, port, err := missinggo.ParseHostPort(addr)
expect.Nil(err)
cfg.ListenHost = func(string) string { return host }
cfg.ListenPort = port
return cfg
}
func (cfg *Config) setDefaults() { func (cfg *Config) setDefaults() {
if cfg.HTTP == nil { if cfg.HTTP == nil {
cfg.HTTP = DefaultHTTPClient cfg.HTTP = DefaultHTTPClient

View File

@ -165,13 +165,12 @@ func TestDownloadOnDemand(t *testing.T) {
layout, err := newGreetingLayout() layout, err := newGreetingLayout()
require.NoError(t, err) require.NoError(t, err)
defer layout.Destroy() defer layout.Destroy()
seeder, err := torrent.NewClient(&torrent.Config{ seeder, err := torrent.NewClient((&torrent.Config{
DataDir: layout.Completed, DataDir: layout.Completed,
DisableTrackers: true, DisableTrackers: true,
NoDHT: true, NoDHT: true,
ListenAddr: "localhost:0",
Seed: true, Seed: true,
}) }).SetListenAddr("localhost:0"))
require.NoError(t, err) require.NoError(t, err)
defer seeder.Close() defer seeder.Close()
testutil.ExportStatusWriter(seeder, "s") testutil.ExportStatusWriter(seeder, "s")
@ -184,16 +183,15 @@ func TestDownloadOnDemand(t *testing.T) {
<-seederTorrent.GotInfo() <-seederTorrent.GotInfo()
seederTorrent.VerifyData() seederTorrent.VerifyData()
}() }()
leecher, err := torrent.NewClient(&torrent.Config{ leecher, err := torrent.NewClient((&torrent.Config{
DisableTrackers: true, DisableTrackers: true,
NoDHT: true, NoDHT: true,
ListenAddr: "localhost:0",
DisableTCP: true, DisableTCP: true,
DefaultStorage: storage.NewMMap(filepath.Join(layout.BaseDir, "download")), DefaultStorage: storage.NewMMap(filepath.Join(layout.BaseDir, "download")),
// This can be used to check if clients can connect to other clients // This can be used to check if clients can connect to other clients
// with the same ID. // with the same ID.
// PeerID: seeder.PeerID(), // PeerID: seeder.PeerID(),
}) }).SetListenAddr("localhost:0"))
require.NoError(t, err) require.NoError(t, err)
testutil.ExportStatusWriter(leecher, "l") testutil.ExportStatusWriter(leecher, "l")
defer leecher.Close() defer leecher.Close()

View File

@ -61,26 +61,31 @@ func setPort(addr string, port int) string {
return net.JoinHostPort(host, strconv.FormatInt(int64(port), 10)) return net.JoinHostPort(host, strconv.FormatInt(int64(port), 10))
} }
func listenAll(networks []string, addr string) ([]socket, error) { func listenAll(networks []string, getHost func(string) string, port int) ([]socket, error) {
if len(networks) == 0 { if len(networks) == 0 {
return nil, nil return nil, nil
} }
var nahs []networkAndHost
for _, n := range networks {
nahs = append(nahs, networkAndHost{n, getHost(n)})
}
for { for {
ss, retry, err := listenAllRetry(networks, addr) ss, retry, err := listenAllRetry(nahs, port)
if !retry { if !retry {
return ss, err return ss, err
} }
} }
} }
func listenAllRetry(networks []string, addr string) (ss []socket, retry bool, err error) { type networkAndHost struct {
_, port, err := missinggo.ParseHostPort(addr) Network string
if err != nil { Host string
err = fmt.Errorf("error parsing addr: %s", err) }
return
} func listenAllRetry(nahs []networkAndHost, port int) (ss []socket, retry bool, err error) {
ss = make([]socket, 1, len(networks)) ss = make([]socket, 1, len(nahs))
ss[0], err = listen(networks[0], addr) portStr := strconv.FormatInt(int64(port), 10)
ss[0], err = listen(nahs[0].Network, net.JoinHostPort(nahs[0].Host, portStr))
if err != nil { if err != nil {
return nil, false, fmt.Errorf("first listen: %s", err) return nil, false, fmt.Errorf("first listen: %s", err)
} }
@ -92,9 +97,9 @@ func listenAllRetry(networks []string, addr string) (ss []socket, retry bool, er
ss = nil ss = nil
} }
}() }()
restAddr := setPort(addr, missinggo.AddrPort(ss[0].Addr())) portStr = strconv.FormatInt(int64(missinggo.AddrPort(ss[0].Addr())), 10)
for _, n := range networks[1:] { for _, nah := range nahs[1:] {
s, err := listen(n, restAddr) s, err := listen(nah.Network, net.JoinHostPort(nah.Host, portStr))
if err != nil { if err != nil {
return ss, return ss,
missinggo.IsAddrInUse(err) && port == 0, missinggo.IsAddrInUse(err) && port == 0,