From ef4c0f141301b6c4ea0bf2d02a39095d89d7eb78 Mon Sep 17 00:00:00 2001 From: Matt Joiner Date: Mon, 29 Jan 2018 18:18:08 +1100 Subject: [PATCH] Add Torrent.Stats.ConnectedSeeders Fixes #231 --- connection.go | 24 +++++++++++++++++------- torrent.go | 6 ++++++ torrent_stats.go | 10 ++++++---- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/connection.go b/connection.go index 753bc64f..40d02aba 100644 --- a/connection.go +++ b/connection.go @@ -82,7 +82,7 @@ type connection struct { peerPieces bitmap.Bitmap // The peer has everything. This can occur due to a special message, when // we may not even know the number of pieces in the torrent yet. - peerHasAll bool + peerSentHaveAll bool // The highest possible number of pieces the torrent could have based on // communication with the peer. Generally only useful until we have the // torrent info. @@ -102,6 +102,16 @@ type connection struct { writerCond sync.Cond } +func (cn *connection) peerHasAllPieces() (all bool, known bool) { + if cn.peerSentHaveAll { + return true, true + } + if !cn.t.haveInfo() { + return false, false + } + return bitmap.Flip(cn.peerPieces, 0, cn.t.numPieces()).IsEmpty(), true +} + func (cn *connection) mu() sync.Locker { return &cn.t.cl.mu } @@ -234,7 +244,7 @@ func (cn *connection) Close() { } func (cn *connection) PeerHasPiece(piece int) bool { - return cn.peerHasAll || cn.peerPieces.Contains(piece) + return cn.peerSentHaveAll || cn.peerPieces.Contains(piece) } func (cn *connection) Post(msg pp.Message) { @@ -695,7 +705,7 @@ func (cn *connection) peerSentHave(piece int) error { } func (cn *connection) peerSentBitfield(bf []bool) error { - cn.peerHasAll = false + cn.peerSentHaveAll = false if len(bf)%8 != 0 { panic("expected bitfield length divisible by 8") } @@ -716,8 +726,8 @@ func (cn *connection) peerSentBitfield(bf []bool) error { return nil } -func (cn *connection) peerSentHaveAll() error { - cn.peerHasAll = true +func (cn *connection) onPeerSentHaveAll() error { + cn.peerSentHaveAll = true cn.peerPieces.Clear() cn.peerPiecesChanged() return nil @@ -725,7 +735,7 @@ func (cn *connection) peerSentHaveAll() error { func (cn *connection) peerSentHaveNone() error { cn.peerPieces.Clear() - cn.peerHasAll = false + cn.peerSentHaveAll = false cn.peerPiecesChanged() return nil } @@ -883,7 +893,7 @@ func (c *connection) mainReadLoop() error { case pp.Bitfield: err = c.peerSentBitfield(msg.Bitfield) case pp.HaveAll: - err = c.peerSentHaveAll() + err = c.onPeerSentHaveAll() case pp.HaveNone: err = c.peerSentHaveNone() case pp.Piece: diff --git a/torrent.go b/torrent.go index a215859d..f5d3b2a6 100644 --- a/torrent.go +++ b/torrent.go @@ -1354,6 +1354,12 @@ func (t *Torrent) statsLocked() TorrentStats { t.stats.HalfOpenPeers = len(t.halfOpen) t.stats.PendingPeers = len(t.peers) t.stats.TotalPeers = t.numTotalPeers() + t.stats.ConnectedSeeders = 0 + for c := range t.conns { + if all, ok := c.peerHasAllPieces(); all && ok { + t.stats.ConnectedSeeders++ + } + } return t.stats } diff --git a/torrent_stats.go b/torrent_stats.go index 3dd2716a..f155a0d8 100644 --- a/torrent_stats.go +++ b/torrent_stats.go @@ -3,8 +3,10 @@ package torrent type TorrentStats struct { ConnStats // Aggregates stats over all connections past and present. - ActivePeers int - HalfOpenPeers int - PendingPeers int - TotalPeers int + // Ordered by expected descending quantities (if all is well). + TotalPeers int + PendingPeers int + ActivePeers int + ConnectedSeeders int + HalfOpenPeers int } -- 2.48.1