From: Matt Joiner Date: Mon, 25 Oct 2021 02:00:56 +0000 (+1100) Subject: Fix panic when sustaining unrejected requests after being choked X-Git-Tag: v1.34.0^2~12 X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=e884b8079b6b5863d4dd9c2f9d8cab119ebeb525;p=btrtrc.git Fix panic when sustaining unrejected requests after being choked Fixes https://github.com/anacrolix/torrent/issues/680. --- diff --git a/peerconn.go b/peerconn.go index 005c6b7d..c1b98c2a 100644 --- a/peerconn.go +++ b/peerconn.go @@ -556,6 +556,8 @@ func (pc *PeerConn) writeInterested(interested bool) bool { // are okay. type messageWriter func(pp.Message) bool +// This function seems to only used by Peer.request. It's all logic checks, so maybe we can no-op it +// when we want to go fast. func (cn *Peer) shouldRequest(r RequestIndex) error { pi := pieceIndex(r / cn.t.chunksPerRegularPiece()) if !cn.peerHasPiece(pi) { @@ -574,7 +576,11 @@ func (cn *Peer) shouldRequest(r RequestIndex) error { panic("piece is queued for hash") } if cn.peerChoking && !cn.peerAllowedFast.Contains(bitmap.BitIndex(pi)) { - panic("peer choking and piece not allowed fast") + // This could occur if we made a request with the fast extension, and then got choked and + // haven't had the request rejected yet. + if !cn.actualRequestState.Requests.Contains(r) { + panic("peer choking and piece not allowed fast") + } } return nil } diff --git a/requesting.go b/requesting.go index 6d707fde..1d2d5e19 100644 --- a/requesting.go +++ b/requesting.go @@ -216,8 +216,12 @@ func (p *Peer) getDesiredRequestState() (desired requestState) { allowedFast := p.peerAllowedFast.ContainsInt(pieceIndex) rsp.IterPendingChunks.Iter(func(ci request_strategy.ChunkIndex) { if !allowedFast { - // We must signal interest to request this.. + // We must signal interest to request this desired.Interested = true + // We can make or will allow sustaining a request here if we're not choked, or + // have made the request previously (presumably while unchoked), and haven't had + // the peer respond yet (and the request was retained because we are using the + // fast extension). if p.peerChoking && !p.actualRequestState.Requests.Contains(ci) { // We can't request this right now. return