From: Matt Joiner Date: Fri, 4 Jul 2025 06:13:59 +0000 (+1000) Subject: Fixes for webseed peers not having request state X-Git-Tag: v1.59.0~44 X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=02377275fc51f0e6859a39a5c9143252c6e09ac7;p=btrtrc.git Fixes for webseed peers not having request state --- diff --git a/conn-stats.go b/conn-stats.go index c574a4d0..12e00287 100644 --- a/conn-stats.go +++ b/conn-stats.go @@ -8,9 +8,10 @@ import ( // Various connection-level metrics. At the Torrent level these are aggregates. Chunks are messages // with data payloads. Data is actual torrent content without any overhead. Useful is something we -// needed locally. Unwanted is something we didn't ask for (but may still be useful). Written is -// things sent to the peer, and Read is stuff received from them. Due to the implementation of -// Count, must be aligned on some platforms: See https://github.com/anacrolix/torrent/issues/262. +// needed locally. Intended is something we were expecting (I think such as when we cancel a request +// but it arrives anyway). Written is things sent to the peer, and Read is stuff received from them. +// Due to the implementation of Count, must be aligned on some platforms: See +// https://github.com/anacrolix/torrent/issues/262. type ConnStats struct { // Total bytes on the wire. Includes handshakes and encryption. BytesWritten Count diff --git a/peer-impl.go b/peer-impl.go index 7cd2d57c..5586e43b 100644 --- a/peer-impl.go +++ b/peer-impl.go @@ -2,6 +2,7 @@ package torrent import ( "github.com/RoaringBitmap/roaring" + pp "github.com/anacrolix/torrent/peer_protocol" "github.com/anacrolix/torrent/metainfo" ) @@ -44,7 +45,7 @@ type legacyPeerImpl interface { type newHotPeerImpl interface { lastWriteUploadRate() float64 // Bookkeeping for a chunk being received and any specific checks. - checkReceivedChunk(ri RequestIndex) error + checkReceivedChunk(ri RequestIndex, msg *pp.Message, req Request) (intended bool, err error) // Whether we're expecting to receive chunks because we have outstanding requests. Used for // example to calculate download rate. expectingChunks() bool diff --git a/peer.go b/peer.go index 2d79a4bf..9b031fb8 100644 --- a/peer.go +++ b/peer.go @@ -626,36 +626,11 @@ func (c *Peer) receiveChunk(msg *pp.Message) error { ChunksReceived.Add("while choked", 1) } - err = c.peerImpl.checkReceivedChunk(req) + intended, err := c.peerImpl.checkReceivedChunk(req, msg, ppReq) if err != nil { return err } - if c.peerChoking && c.peerAllowedFast.Contains(pieceIndex(ppReq.Index)) { - ChunksReceived.Add("due to allowed fast", 1) - } - - // The request needs to be deleted immediately to prevent cancels occurring asynchronously when - // have actually already received the piece, while we have the Client unlocked to write the data - // out. - intended := false - { - if c.requestState.Requests.Contains(req) { - for _, f := range c.callbacks.ReceivedRequested { - f(PeerMessageEvent{c, msg}) - } - } - // Request has been satisfied. - if c.deleteRequest(req) || c.requestState.Cancelled.CheckedRemove(req) { - intended = true - if c.isLowOnRequests() { - c.onNeedUpdateRequests("Peer.receiveChunk deleted request") - } - } else { - ChunksReceived.Add("unintended", 1) - } - } - cl := t.cl // Do we actually want this chunk? diff --git a/peerconn.go b/peerconn.go index 95d7972c..5ccf23ce 100644 --- a/peerconn.go +++ b/peerconn.go @@ -1492,11 +1492,36 @@ func (me *PeerConn) setPeerLoggers(a log.Logger, s *slog.Logger) { me.protocolLogger = me.logger.WithNames(protocolLoggingName) } -func (c *PeerConn) checkReceivedChunk(req RequestIndex) error { +func (c *PeerConn) checkReceivedChunk(req RequestIndex, msg *pp.Message, ppReq Request) (intended bool, err error) { if c.validReceiveChunks[req] <= 0 { ChunksReceived.Add("unexpected", 1) - return errors.New("received unexpected chunk") + err = errors.New("received unexpected chunk") + return } c.decExpectedChunkReceive(req) - return nil + + if c.peerChoking && c.peerAllowedFast.Contains(pieceIndex(ppReq.Index)) { + ChunksReceived.Add("due to allowed fast", 1) + } + // The request needs to be deleted immediately to prevent cancels occurring asynchronously when + // have actually already received the piece, while we have the Client unlocked to write the data + // out. + { + if c.requestState.Requests.Contains(req) { + for _, f := range c.callbacks.ReceivedRequested { + f(PeerMessageEvent{c.peerPtr(), msg}) + } + } + // Request has been satisfied. + if c.deleteRequest(req) || c.requestState.Cancelled.CheckedRemove(req) { + intended = true + if c.isLowOnRequests() { + c.onNeedUpdateRequests("Peer.receiveChunk deleted request") + } + } else { + ChunksReceived.Add("unintended", 1) + } + } + + return } diff --git a/webseed-peer.go b/webseed-peer.go index 6fd865b2..45b8c9be 100644 --- a/webseed-peer.go +++ b/webseed-peer.go @@ -41,8 +41,8 @@ func (me *webseedPeer) expectingChunks() bool { return len(me.activeRequests) > 0 } -func (me *webseedPeer) checkReceivedChunk(ri RequestIndex) error { - return nil +func (me *webseedPeer) checkReceivedChunk(RequestIndex, *pp.Message, Request) (bool, error) { + return true, nil } func (me *webseedPeer) numRequests() int { @@ -121,7 +121,7 @@ func (ws *webseedPeer) spawnRequest(begin, end RequestIndex) { "begin", begin, "end", end, "len", end-begin, - "avail", ws.peer.requestState.Requests.GetCardinality()) + ) go ws.runRequest(&wsReq) }