From bdcb6c9fcdebbc5ac8825c11f3177464d95efee1 Mon Sep 17 00:00:00 2001
From: Matt Joiner <anacrolix@gmail.com>
Date: Mon, 15 Jan 2024 12:55:04 +1100
Subject: [PATCH] Fix requests still being made when downloading is disallowed

https://github.com/anacrolix/torrent/issues/889
---
 peer.go       |  3 ---
 requesting.go | 10 +++-------
 torrent.go    | 18 +++++++++++++++---
 3 files changed, 18 insertions(+), 13 deletions(-)

diff --git a/peer.go b/peer.go
index 151c4b14..7d524b7f 100644
--- a/peer.go
+++ b/peer.go
@@ -480,9 +480,6 @@ func (cn *Peer) updateRequests(reason string) {
 	if cn.needRequestUpdate != "" {
 		return
 	}
-	if reason != peerUpdateRequestsTimerReason && !cn.isLowOnRequests() {
-		return
-	}
 	cn.needRequestUpdate = reason
 	cn.handleUpdateRequests()
 }
diff --git a/requesting.go b/requesting.go
index 8b9db971..d961fba4 100644
--- a/requesting.go
+++ b/requesting.go
@@ -173,6 +173,9 @@ func (p *Peer) getDesiredRequestState() (desired desiredRequestState) {
 	if t.closed.IsSet() {
 		return
 	}
+	if t.dataDownloadDisallowed.Bool() {
+		return
+	}
 	input := t.getRequestStrategyInput()
 	requestHeap := desiredPeerRequests{
 		peer:           p,
@@ -257,13 +260,6 @@ func (p *Peer) applyRequestState(next desiredRequestState) {
 
 	t := p.t
 	originalRequestCount := current.Requests.GetCardinality()
-	// We're either here on a timer, or because we ran out of requests. Both are valid reasons to
-	// alter peakRequests.
-	if originalRequestCount != 0 && p.needRequestUpdate != peerUpdateRequestsTimerReason {
-		panic(fmt.Sprintf(
-			"expected zero existing requests (%v) for update reason %q",
-			originalRequestCount, p.needRequestUpdate))
-	}
 	for requestHeap.Len() != 0 && maxRequests(current.Requests.GetCardinality()+current.Cancelled.GetCardinality()) < p.nominalMaxRequests() {
 		req := heap.Pop(requestHeap)
 		existing := t.requestingPeer(req)
diff --git a/torrent.go b/torrent.go
index 8080acf8..2d0cce2e 100644
--- a/torrent.go
+++ b/torrent.go
@@ -2483,15 +2483,27 @@ func (t *Torrent) onWriteChunkErr(err error) {
 }
 
 func (t *Torrent) DisallowDataDownload() {
+	t.cl.lock()
+	defer t.cl.unlock()
 	t.disallowDataDownloadLocked()
 }
 
 func (t *Torrent) disallowDataDownloadLocked() {
 	t.dataDownloadDisallowed.Set()
+	t.iterPeers(func(p *Peer) {
+		// Could check if peer request state is empty/not interested?
+		p.updateRequests("disallow data download")
+		p.cancelAllRequests()
+	})
 }
 
 func (t *Torrent) AllowDataDownload() {
+	t.cl.lock()
+	defer t.cl.unlock()
 	t.dataDownloadDisallowed.Clear()
+	t.iterPeers(func(p *Peer) {
+		p.updateRequests("allow data download")
+	})
 }
 
 // Enables uploading data, if it was disabled.
@@ -2499,9 +2511,9 @@ func (t *Torrent) AllowDataUpload() {
 	t.cl.lock()
 	defer t.cl.unlock()
 	t.dataUploadDisallowed = false
-	for c := range t.conns {
-		c.updateRequests("allow data upload")
-	}
+	t.iterPeers(func(p *Peer) {
+		p.updateRequests("allow data upload")
+	})
 }
 
 // Disables uploading data, if it was enabled.
-- 
2.51.0