diff --git a/peer.go b/peer.go index d59c5c4c..151c4b14 100644 --- a/peer.go +++ b/peer.go @@ -6,7 +6,6 @@ import ( "io" "net" "strings" - "sync/atomic" "time" "github.com/RoaringBitmap/roaring" @@ -94,9 +93,7 @@ type ( peerTouchedPieces map[pieceIndex]struct{} peerAllowedFast typedRoaring.Bitmap[pieceIndex] - PeerMaxRequests maxRequests // Maximum pending requests the peer allows. - PeerExtensionIDs map[pp.ExtensionName]pp.ExtensionNumber - PeerClientName atomic.Value + PeerMaxRequests maxRequests // Maximum pending requests the peer allows. logger log.Logger } @@ -188,7 +185,7 @@ func (cn *Peer) locker() *lockWithDeferreds { return cn.t.cl.locker() } -func (cn *Peer) supportsExtension(ext pp.ExtensionName) bool { +func (cn *PeerConn) supportsExtension(ext pp.ExtensionName) bool { _, ok := cn.PeerExtensionIDs[ext] return ok } @@ -513,10 +510,6 @@ func iterBitmapsDistinct(skip *bitmap.Bitmap, bms ...bitmap.Bitmap) iter.Func { } } -func (cn *Peer) peerPiecesChanged() { - cn.t.maybeDropMutuallyCompletePeer(cn) -} - // After handshake, we know what Torrent and Client stats to include for a // connection. func (cn *Peer) postHandshakeStats(f func(*ConnStats)) { @@ -539,25 +532,6 @@ func (cn *Peer) readBytes(n int64) { cn.allStats(add(n, func(cs *ConnStats) *Count { return &cs.BytesRead })) } -// Returns whether the connection could be useful to us. We're seeding and -// they want data, we don't have metainfo and they can provide it, etc. -func (c *Peer) useful() bool { - t := c.t - if c.closed.IsSet() { - return false - } - if !t.haveInfo() { - return c.supportsExtension("ut_metadata") - } - if t.seeding() && c.peerInterested { - return true - } - if c.peerHasWantedPieces() { - return true - } - return false -} - func (c *Peer) lastHelpful() (ret time.Time) { ret = c.lastUsefulChunkReceived if c.t.seeding() && c.lastChunkSent.After(ret) { diff --git a/peerconn.go b/peerconn.go index 68da20f1..ee7aa609 100644 --- a/peerconn.go +++ b/peerconn.go @@ -12,6 +12,7 @@ import ( "net/netip" "strconv" "strings" + "sync/atomic" "time" "github.com/RoaringBitmap/roaring" @@ -54,8 +55,10 @@ type PeerConn struct { messageWriter peerConnMsgWriter - uploadTimer *time.Timer - pex pexConnState + PeerExtensionIDs map[pp.ExtensionName]pp.ExtensionNumber + PeerClientName atomic.Value + uploadTimer *time.Timer + pex pexConnState // The pieces the peer has claimed to have. _peerPieces roaring.Bitmap @@ -1106,3 +1109,26 @@ func (pc *PeerConn) remoteDialAddrPort() (netip.AddrPort, error) { func (pc *PeerConn) bitExtensionEnabled(bit pp.ExtensionBit) bool { return pc.t.cl.config.Extensions.GetBit(bit) && pc.PeerExtensionBytes.GetBit(bit) } + +func (cn *PeerConn) peerPiecesChanged() { + cn.t.maybeDropMutuallyCompletePeer(cn) +} + +// Returns whether the connection could be useful to us. We're seeding and +// they want data, we don't have metainfo and they can provide it, etc. +func (c *PeerConn) useful() bool { + t := c.t + if c.closed.IsSet() { + return false + } + if !t.haveInfo() { + return c.supportsExtension("ut_metadata") + } + if t.seeding() && c.peerInterested { + return true + } + if c.peerHasWantedPieces() { + return true + } + return false +} diff --git a/torrent.go b/torrent.go index 315f7072..82dfc0a5 100644 --- a/torrent.go +++ b/torrent.go @@ -1060,7 +1060,7 @@ func (t *Torrent) havePiece(index pieceIndex) bool { func (t *Torrent) maybeDropMutuallyCompletePeer( // I'm not sure about taking peer here, not all peer implementations actually drop. Maybe that's // okay? - p *Peer, + p *PeerConn, ) { if !t.cl.config.DropMutuallyCompletePeers { return @@ -2220,7 +2220,7 @@ func (t *Torrent) onPieceCompleted(piece pieceIndex) { t.piece(piece).readerCond.Broadcast() for conn := range t.conns { conn.have(piece) - t.maybeDropMutuallyCompletePeer(&conn.Peer) + t.maybeDropMutuallyCompletePeer(conn) } } diff --git a/worse-conns.go b/worse-conns.go index 62895e69..ef33b979 100644 --- a/worse-conns.go +++ b/worse-conns.go @@ -34,7 +34,7 @@ type worseConnLensOpts struct { incomingIsBad, outgoingIsBad bool } -func worseConnInputFromPeer(p *Peer, opts worseConnLensOpts) worseConnInput { +func worseConnInputFromPeer(p *PeerConn, opts worseConnLensOpts) worseConnInput { ret := worseConnInput{ Useful: p.useful(), LastHelpful: p.lastHelpful(), @@ -50,13 +50,6 @@ func worseConnInputFromPeer(p *Peer, opts worseConnLensOpts) worseConnInput { return ret } -func worseConn(_l, _r *Peer) bool { - // TODO: Use generics for ptr to - l := worseConnInputFromPeer(_l, worseConnLensOpts{}) - r := worseConnInputFromPeer(_r, worseConnLensOpts{}) - return l.Less(&r) -} - func (l *worseConnInput) Less(r *worseConnInput) bool { less, ok := multiless.New().Bool( r.BadDirection, l.BadDirection).Bool( @@ -94,7 +87,7 @@ type worseConnSlice struct { func (me *worseConnSlice) initKeys(opts worseConnLensOpts) { me.keys = make([]worseConnInput, len(me.conns)) for i, c := range me.conns { - me.keys[i] = worseConnInputFromPeer(&c.Peer, opts) + me.keys[i] = worseConnInputFromPeer(c, opts) } }