Rename Config->ClientConfig and change how defaults work
This is a very breaking change.
This commit is contained in:
parent
ad5e44eaf5
commit
e97f487d2e
27
client.go
27
client.go
|
@ -27,7 +27,6 @@ import (
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/dustin/go-humanize"
|
"github.com/dustin/go-humanize"
|
||||||
"github.com/google/btree"
|
"github.com/google/btree"
|
||||||
"golang.org/x/time/rate"
|
|
||||||
|
|
||||||
"github.com/anacrolix/torrent/bencode"
|
"github.com/anacrolix/torrent/bencode"
|
||||||
"github.com/anacrolix/torrent/iplist"
|
"github.com/anacrolix/torrent/iplist"
|
||||||
|
@ -44,7 +43,7 @@ type Client struct {
|
||||||
event sync.Cond
|
event sync.Cond
|
||||||
closed missinggo.Event
|
closed missinggo.Event
|
||||||
|
|
||||||
config Config
|
config *ClientConfig
|
||||||
logger *log.Logger
|
logger *log.Logger
|
||||||
|
|
||||||
halfOpenLimit int
|
halfOpenLimit int
|
||||||
|
@ -56,8 +55,6 @@ type Client struct {
|
||||||
ipBlockList iplist.Ranger
|
ipBlockList iplist.Ranger
|
||||||
// Our BitTorrent protocol extension bytes, sent in our BT handshakes.
|
// Our BitTorrent protocol extension bytes, sent in our BT handshakes.
|
||||||
extensionBytes peerExtensionBytes
|
extensionBytes peerExtensionBytes
|
||||||
uploadLimit *rate.Limiter
|
|
||||||
downloadLimit *rate.Limiter
|
|
||||||
|
|
||||||
// Set of addresses that have our client ID. This intentionally will
|
// Set of addresses that have our client ID. This intentionally will
|
||||||
// include ourselves if we end up trying to connect to our own address
|
// include ourselves if we end up trying to connect to our own address
|
||||||
|
@ -173,12 +170,10 @@ func (cl *Client) announceKey() int32 {
|
||||||
return int32(binary.BigEndian.Uint32(cl.peerID[16:20]))
|
return int32(binary.BigEndian.Uint32(cl.peerID[16:20]))
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClient(cfg *Config) (cl *Client, err error) {
|
func NewClient(cfg *ClientConfig) (cl *Client, err error) {
|
||||||
if cfg == nil {
|
if cfg == nil {
|
||||||
cfg = &Config{}
|
cfg = NewDefaultClientConfig()
|
||||||
}
|
}
|
||||||
cfg.setDefaults()
|
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cl = nil
|
cl = nil
|
||||||
|
@ -186,7 +181,7 @@ func NewClient(cfg *Config) (cl *Client, err error) {
|
||||||
}()
|
}()
|
||||||
cl = &Client{
|
cl = &Client{
|
||||||
halfOpenLimit: cfg.HalfOpenConnsPerTorrent,
|
halfOpenLimit: cfg.HalfOpenConnsPerTorrent,
|
||||||
config: *cfg,
|
config: cfg,
|
||||||
dopplegangerAddrs: make(map[string]struct{}),
|
dopplegangerAddrs: make(map[string]struct{}),
|
||||||
torrents: make(map[metainfo.Hash]*Torrent),
|
torrents: make(map[metainfo.Hash]*Torrent),
|
||||||
}
|
}
|
||||||
|
@ -198,16 +193,6 @@ func NewClient(cfg *Config) (cl *Client, err error) {
|
||||||
}
|
}
|
||||||
cl.Close()
|
cl.Close()
|
||||||
}()
|
}()
|
||||||
if cfg.UploadRateLimiter == nil {
|
|
||||||
cl.uploadLimit = unlimited
|
|
||||||
} else {
|
|
||||||
cl.uploadLimit = cfg.UploadRateLimiter
|
|
||||||
}
|
|
||||||
if cfg.DownloadRateLimiter == nil {
|
|
||||||
cl.downloadLimit = unlimited
|
|
||||||
} else {
|
|
||||||
cl.downloadLimit = cfg.DownloadRateLimiter
|
|
||||||
}
|
|
||||||
cl.extensionBytes = defaultPeerExtensionBytes()
|
cl.extensionBytes = defaultPeerExtensionBytes()
|
||||||
cl.event.L = &cl.mu
|
cl.event.L = &cl.mu
|
||||||
storageImpl := cfg.DefaultStorage
|
storageImpl := cfg.DefaultStorage
|
||||||
|
@ -492,7 +477,7 @@ func dialUTP(ctx context.Context, addr string, sock utpSocket) (c net.Conn, err
|
||||||
|
|
||||||
var allPeerNetworks = []string{"tcp4", "tcp6", "udp4", "udp6"}
|
var allPeerNetworks = []string{"tcp4", "tcp6", "udp4", "udp6"}
|
||||||
|
|
||||||
func peerNetworkEnabled(network string, cfg Config) bool {
|
func peerNetworkEnabled(network string, cfg *ClientConfig) bool {
|
||||||
c := func(s string) bool {
|
c := func(s string) bool {
|
||||||
return strings.Contains(network, s)
|
return strings.Contains(network, s)
|
||||||
}
|
}
|
||||||
|
@ -1178,7 +1163,7 @@ func (cl *Client) newConnection(nc net.Conn, outgoing bool) (c *connection) {
|
||||||
c.writerCond.L = &cl.mu
|
c.writerCond.L = &cl.mu
|
||||||
c.setRW(connStatsReadWriter{nc, c})
|
c.setRW(connStatsReadWriter{nc, c})
|
||||||
c.r = &rateLimitedReader{
|
c.r = &rateLimitedReader{
|
||||||
l: cl.downloadLimit,
|
l: cl.config.DownloadRateLimiter,
|
||||||
r: c.r,
|
r: c.r,
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|
|
@ -30,15 +30,14 @@ import (
|
||||||
"github.com/anacrolix/torrent/storage"
|
"github.com/anacrolix/torrent/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestingConfig() *Config {
|
func TestingConfig() *ClientConfig {
|
||||||
return &Config{
|
cfg := NewDefaultClientConfig()
|
||||||
ListenHost: LoopbackListenHost,
|
cfg.ListenHost = LoopbackListenHost
|
||||||
NoDHT: true,
|
cfg.NoDHT = true
|
||||||
DataDir: tempDir(),
|
cfg.DataDir = tempDir()
|
||||||
DisableTrackers: true,
|
cfg.DisableTrackers = true
|
||||||
NoDefaultPortForwarding: true,
|
cfg.NoDefaultPortForwarding = true
|
||||||
// Debug: true,
|
return cfg
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestClientDefault(t *testing.T) {
|
func TestClientDefault(t *testing.T) {
|
||||||
|
@ -105,7 +104,9 @@ func TestPieceHashSize(t *testing.T) {
|
||||||
func TestTorrentInitialState(t *testing.T) {
|
func TestTorrentInitialState(t *testing.T) {
|
||||||
dir, mi := testutil.GreetingTestTorrent()
|
dir, mi := testutil.GreetingTestTorrent()
|
||||||
defer os.RemoveAll(dir)
|
defer os.RemoveAll(dir)
|
||||||
cl := &Client{}
|
cl := &Client{
|
||||||
|
config: &ClientConfig{},
|
||||||
|
}
|
||||||
cl.initLogger()
|
cl.initLogger()
|
||||||
tor := cl.newTorrent(
|
tor := cl.newTorrent(
|
||||||
mi.HashInfoBytes(),
|
mi.HashInfoBytes(),
|
||||||
|
@ -138,8 +139,7 @@ func TestUnmarshalPEXMsg(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestReducedDialTimeout(t *testing.T) {
|
func TestReducedDialTimeout(t *testing.T) {
|
||||||
cfg := &Config{}
|
cfg := NewDefaultClientConfig()
|
||||||
cfg.setDefaults()
|
|
||||||
for _, _case := range []struct {
|
for _, _case := range []struct {
|
||||||
Max time.Duration
|
Max time.Duration
|
||||||
HalfOpenLimit int
|
HalfOpenLimit int
|
||||||
|
@ -357,7 +357,9 @@ func testClientTransfer(t *testing.T, ps testClientTransferParams) {
|
||||||
// Create seeder and a Torrent.
|
// Create seeder and a Torrent.
|
||||||
cfg := TestingConfig()
|
cfg := TestingConfig()
|
||||||
cfg.Seed = true
|
cfg.Seed = true
|
||||||
|
if ps.SeederUploadRateLimiter != nil {
|
||||||
cfg.UploadRateLimiter = ps.SeederUploadRateLimiter
|
cfg.UploadRateLimiter = ps.SeederUploadRateLimiter
|
||||||
|
}
|
||||||
// cfg.ListenAddr = "localhost:4000"
|
// cfg.ListenAddr = "localhost:4000"
|
||||||
if ps.SeederStorage != nil {
|
if ps.SeederStorage != nil {
|
||||||
cfg.DefaultStorage = ps.SeederStorage(greetingTempDir)
|
cfg.DefaultStorage = ps.SeederStorage(greetingTempDir)
|
||||||
|
@ -380,12 +382,15 @@ func testClientTransfer(t *testing.T, ps testClientTransferParams) {
|
||||||
leecherDataDir, err := ioutil.TempDir("", "")
|
leecherDataDir, err := ioutil.TempDir("", "")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer os.RemoveAll(leecherDataDir)
|
defer os.RemoveAll(leecherDataDir)
|
||||||
|
cfg = TestingConfig()
|
||||||
if ps.LeecherStorage == nil {
|
if ps.LeecherStorage == nil {
|
||||||
cfg.DataDir = leecherDataDir
|
cfg.DataDir = leecherDataDir
|
||||||
} else {
|
} else {
|
||||||
cfg.DefaultStorage = ps.LeecherStorage(leecherDataDir)
|
cfg.DefaultStorage = ps.LeecherStorage(leecherDataDir)
|
||||||
}
|
}
|
||||||
|
if ps.LeecherDownloadRateLimiter != nil {
|
||||||
cfg.DownloadRateLimiter = ps.LeecherDownloadRateLimiter
|
cfg.DownloadRateLimiter = ps.LeecherDownloadRateLimiter
|
||||||
|
}
|
||||||
cfg.Seed = false
|
cfg.Seed = false
|
||||||
leecher, err := NewClient(cfg)
|
leecher, err := NewClient(cfg)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -443,6 +448,7 @@ func assertReadAllGreeting(t *testing.T, r io.ReadSeeker) {
|
||||||
func TestSeedAfterDownloading(t *testing.T) {
|
func TestSeedAfterDownloading(t *testing.T) {
|
||||||
greetingTempDir, mi := testutil.GreetingTestTorrent()
|
greetingTempDir, mi := testutil.GreetingTestTorrent()
|
||||||
defer os.RemoveAll(greetingTempDir)
|
defer os.RemoveAll(greetingTempDir)
|
||||||
|
|
||||||
cfg := TestingConfig()
|
cfg := TestingConfig()
|
||||||
cfg.Seed = true
|
cfg.Seed = true
|
||||||
cfg.DataDir = greetingTempDir
|
cfg.DataDir = greetingTempDir
|
||||||
|
@ -454,6 +460,9 @@ func TestSeedAfterDownloading(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
seederTorrent.VerifyData()
|
seederTorrent.VerifyData()
|
||||||
|
|
||||||
|
cfg = TestingConfig()
|
||||||
|
cfg.Seed = true
|
||||||
cfg.DataDir, err = ioutil.TempDir("", "")
|
cfg.DataDir, err = ioutil.TempDir("", "")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer os.RemoveAll(cfg.DataDir)
|
defer os.RemoveAll(cfg.DataDir)
|
||||||
|
@ -461,6 +470,8 @@ func TestSeedAfterDownloading(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer leecher.Close()
|
defer leecher.Close()
|
||||||
testutil.ExportStatusWriter(leecher, "l")
|
testutil.ExportStatusWriter(leecher, "l")
|
||||||
|
|
||||||
|
cfg = TestingConfig()
|
||||||
cfg.Seed = false
|
cfg.Seed = false
|
||||||
cfg.DataDir, err = ioutil.TempDir("", "")
|
cfg.DataDir, err = ioutil.TempDir("", "")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -982,8 +993,11 @@ func TestSetMaxEstablishedConn(t *testing.T) {
|
||||||
defer ss.Close()
|
defer ss.Close()
|
||||||
var tts []*Torrent
|
var tts []*Torrent
|
||||||
ih := testutil.GreetingMetaInfo().HashInfoBytes()
|
ih := testutil.GreetingMetaInfo().HashInfoBytes()
|
||||||
|
cfg := TestingConfig()
|
||||||
|
cfg.DisableAcceptRateLimiting = true
|
||||||
|
cfg.dropDuplicatePeerIds = true
|
||||||
for i := range iter.N(3) {
|
for i := range iter.N(3) {
|
||||||
cl, err := NewClient(TestingConfig())
|
cl, err := NewClient(cfg)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer cl.Close()
|
defer cl.Close()
|
||||||
tt, _ := cl.AddTorrentInfoHash(ih)
|
tt, _ := cl.AddTorrentInfoHash(ih)
|
||||||
|
|
86
config.go
86
config.go
|
@ -16,20 +16,10 @@ import (
|
||||||
"github.com/anacrolix/torrent/storage"
|
"github.com/anacrolix/torrent/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
var DefaultHTTPClient = &http.Client{
|
|
||||||
Timeout: time.Second * 15,
|
|
||||||
Transport: &http.Transport{
|
|
||||||
Dial: (&net.Dialer{
|
|
||||||
Timeout: 15 * time.Second,
|
|
||||||
}).Dial,
|
|
||||||
TLSHandshakeTimeout: 15 * time.Second,
|
|
||||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
var DefaultHTTPUserAgent = "Go-Torrent/1.0"
|
var DefaultHTTPUserAgent = "Go-Torrent/1.0"
|
||||||
|
|
||||||
// Override Client defaults.
|
// Probably not safe to modify this after it's given to a Client.
|
||||||
type Config struct {
|
type ClientConfig struct {
|
||||||
// Store torrent file data in this directory unless .DefaultStorage is
|
// Store torrent file data in this directory unless .DefaultStorage is
|
||||||
// specified.
|
// specified.
|
||||||
DataDir string `long:"data-dir" description:"directory to store downloaded torrent data"`
|
DataDir string `long:"data-dir" description:"directory to store downloaded torrent data"`
|
||||||
|
@ -120,7 +110,7 @@ type Config struct {
|
||||||
PublicIp6 net.IP
|
PublicIp6 net.IP
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *Config) SetListenAddr(addr string) *Config {
|
func (cfg *ClientConfig) SetListenAddr(addr string) *ClientConfig {
|
||||||
host, port, err := missinggo.ParseHostPort(addr)
|
host, port, err := missinggo.ParseHostPort(addr)
|
||||||
expect.Nil(err)
|
expect.Nil(err)
|
||||||
cfg.ListenHost = func(string) string { return host }
|
cfg.ListenHost = func(string) string { return host }
|
||||||
|
@ -128,53 +118,35 @@ func (cfg *Config) SetListenAddr(addr string) *Config {
|
||||||
return cfg
|
return cfg
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *Config) setDefaults() {
|
func NewDefaultClientConfig() *ClientConfig {
|
||||||
if cfg.HTTP == nil {
|
return &ClientConfig{
|
||||||
cfg.HTTP = DefaultHTTPClient
|
HTTP: &http.Client{
|
||||||
if cfg.ProxyURL != "" {
|
Timeout: time.Second * 15,
|
||||||
cfg.setProxyURL()
|
Transport: &http.Transport{
|
||||||
}
|
Dial: (&net.Dialer{
|
||||||
}
|
Timeout: 15 * time.Second,
|
||||||
if cfg.HTTPUserAgent == "" {
|
}).Dial,
|
||||||
cfg.HTTPUserAgent = DefaultHTTPUserAgent
|
TLSHandshakeTimeout: 15 * time.Second,
|
||||||
}
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
if cfg.ExtendedHandshakeClientVersion == "" {
|
}},
|
||||||
cfg.ExtendedHandshakeClientVersion = "go.torrent dev 20150624"
|
HTTPUserAgent: DefaultHTTPUserAgent,
|
||||||
}
|
ExtendedHandshakeClientVersion: "go.torrent dev 20150624",
|
||||||
if cfg.Bep20 == "" {
|
Bep20: "-GT0001-",
|
||||||
cfg.Bep20 = "-GT0001-"
|
NominalDialTimeout: 30 * time.Second,
|
||||||
}
|
MinDialTimeout: 5 * time.Second,
|
||||||
if cfg.NominalDialTimeout == 0 {
|
EstablishedConnsPerTorrent: 50,
|
||||||
cfg.NominalDialTimeout = 30 * time.Second
|
HalfOpenConnsPerTorrent: 25,
|
||||||
}
|
TorrentPeersHighWater: 500,
|
||||||
if cfg.MinDialTimeout == 0 {
|
TorrentPeersLowWater: 50,
|
||||||
cfg.MinDialTimeout = 5 * time.Second
|
HandshakesTimeout: 20 * time.Second,
|
||||||
}
|
DhtStartingNodes: dht.GlobalBootstrapAddrs,
|
||||||
if cfg.EstablishedConnsPerTorrent == 0 {
|
ListenHost: func(string) string { return "" },
|
||||||
cfg.EstablishedConnsPerTorrent = 50
|
UploadRateLimiter: unlimited,
|
||||||
}
|
DownloadRateLimiter: unlimited,
|
||||||
if cfg.HalfOpenConnsPerTorrent == 0 {
|
|
||||||
cfg.HalfOpenConnsPerTorrent = (cfg.EstablishedConnsPerTorrent + 1) / 2
|
|
||||||
}
|
|
||||||
if cfg.TorrentPeersHighWater == 0 {
|
|
||||||
// Memory and freshness are the concern here.
|
|
||||||
cfg.TorrentPeersHighWater = 500
|
|
||||||
}
|
|
||||||
if cfg.TorrentPeersLowWater == 0 {
|
|
||||||
cfg.TorrentPeersLowWater = 2 * cfg.HalfOpenConnsPerTorrent
|
|
||||||
}
|
|
||||||
if cfg.HandshakesTimeout == 0 {
|
|
||||||
cfg.HandshakesTimeout = 20 * time.Second
|
|
||||||
}
|
|
||||||
if cfg.DhtStartingNodes == nil {
|
|
||||||
cfg.DhtStartingNodes = dht.GlobalBootstrapAddrs
|
|
||||||
}
|
|
||||||
if cfg.ListenHost == nil {
|
|
||||||
cfg.ListenHost = func(string) string { return "" }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *Config) setProxyURL() {
|
func (cfg *ClientConfig) setProxyURL() {
|
||||||
fixedURL, err := url.Parse(cfg.ProxyURL)
|
fixedURL, err := url.Parse(cfg.ProxyURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
|
|
@ -1308,7 +1308,7 @@ another:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for r := range c.PeerRequests {
|
for r := range c.PeerRequests {
|
||||||
res := c.t.cl.uploadLimit.ReserveN(time.Now(), int(r.Length))
|
res := c.t.cl.config.UploadRateLimiter.ReserveN(time.Now(), int(r.Length))
|
||||||
if !res.OK() {
|
if !res.OK() {
|
||||||
panic(fmt.Sprintf("upload rate limiter burst size < %d", r.Length))
|
panic(fmt.Sprintf("upload rate limiter burst size < %d", r.Length))
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,9 @@ import (
|
||||||
// Have that would potentially alter it.
|
// Have that would potentially alter it.
|
||||||
func TestSendBitfieldThenHave(t *testing.T) {
|
func TestSendBitfieldThenHave(t *testing.T) {
|
||||||
r, w := io.Pipe()
|
r, w := io.Pipe()
|
||||||
var cl Client
|
cl := Client{
|
||||||
|
config: &ClientConfig{DownloadRateLimiter: unlimited},
|
||||||
|
}
|
||||||
cl.initLogger()
|
cl.initLogger()
|
||||||
c := cl.newConnection(nil, false)
|
c := cl.newConnection(nil, false)
|
||||||
c.setTorrent(cl.newTorrent(metainfo.Hash{}, nil))
|
c.setTorrent(cl.newTorrent(metainfo.Hash{}, nil))
|
||||||
|
@ -87,7 +89,9 @@ func (me *torrentStorage) WriteAt(b []byte, _ int64) (int, error) {
|
||||||
|
|
||||||
func BenchmarkConnectionMainReadLoop(b *testing.B) {
|
func BenchmarkConnectionMainReadLoop(b *testing.B) {
|
||||||
cl := &Client{
|
cl := &Client{
|
||||||
downloadLimit: unlimited,
|
config: &ClientConfig{
|
||||||
|
DownloadRateLimiter: unlimited,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
ts := &torrentStorage{}
|
ts := &torrentStorage{}
|
||||||
t := &Torrent{
|
t := &Torrent{
|
||||||
|
|
Loading…
Reference in New Issue