client.go | 6 +++++- config.go | 2 ++ torrent.go | 9 +++++++-- diff --git a/client.go b/client.go index fafb6e2d72d7f94d96cc2d4f5eb67f29b6595622..6292d778fdbb31c5e6b82b6f421b44d625c3ffa5 100644 --- a/client.go +++ b/client.go @@ -75,6 +75,7 @@ torrents map[InfoHash]*Torrent acceptLimiter map[ipStr]int dialRateLimiter *rate.Limiter + numHalfOpen int websocketTrackers websocketTrackers } @@ -658,7 +659,10 @@ if _, ok := t.halfOpen[addr]; !ok { panic("invariant broken") } delete(t.halfOpen, addr) - t.openNewConns() + cl.numHalfOpen-- + for _, t := range cl.torrents { + t.openNewConns() + } } // Performs initiator handshakes and returns a connection. Returns nil *connection if no connection diff --git a/config.go b/config.go index c28ee124560d8e063a16d1e8e39ad19d1f5790d6..4af86cf6826f873b0b6ccecd4d127c8782302ec3 100644 --- a/config.go +++ b/config.go @@ -102,6 +102,7 @@ // Minimum peer dial timeout to use (even if we have lots of peers). MinDialTimeout time.Duration EstablishedConnsPerTorrent int HalfOpenConnsPerTorrent int + TotalHalfOpenConns int // Maximum number of peer addresses in reserve. TorrentPeersHighWater int // Minumum number of peers before effort is made to obtain more peers. @@ -155,6 +156,7 @@ NominalDialTimeout: 20 * time.Second, MinDialTimeout: 3 * time.Second, EstablishedConnsPerTorrent: 50, HalfOpenConnsPerTorrent: 25, + TotalHalfOpenConns: 100, TorrentPeersHighWater: 500, TorrentPeersLowWater: 50, HandshakesTimeout: 4 * time.Second, diff --git a/torrent.go b/torrent.go index 639e330e21ad61f2cbeb2ea778c7b4554e9e3846..21069ec5fe0cd0324b42aaf2a460f01dc36a9785 100644 --- a/torrent.go +++ b/torrent.go @@ -1075,7 +1075,7 @@ // upset an oversupply of received connections. return int(min(max(5, extraIncoming)+establishedHeadroom, int64(t.cl.config.HalfOpenConnsPerTorrent))) } -func (t *Torrent) openNewConns() { +func (t *Torrent) openNewConns() (initiated int) { defer t.updateWantPeersEvent() for t.peers.Len() != 0 { if !t.wantConns() { @@ -1087,9 +1087,14 @@ } if len(t.cl.dialers) == 0 { return } + if t.cl.numHalfOpen >= t.cl.config.TotalHalfOpenConns { + return + } p := t.peers.PopMax() t.initiateConn(p) + initiated++ } + return } func (t *Torrent) getConnPieceInclination() []int { @@ -1889,7 +1894,6 @@ func (t *Torrent) initiateConn(peer PeerInfo) { if peer.Id == t.cl.peerID { return } - if t.cl.badPeerAddr(peer.Addr) && !peer.Trusted { return } @@ -1897,6 +1901,7 @@ addr := peer.Addr if t.addrActive(addr.String()) { return } + t.cl.numHalfOpen++ t.halfOpen[addr.String()] = peer go t.cl.outgoingConnection(t, addr, peer.Source, peer.Trusted) }