Never keep more requests in flight to one peer than it queues: the peer's own "reqq", or 500 when it sent none.

The request pipe to a peer is sized from that peer's download rate:

    src/protocol/request_list.cc, calculate_pipe_size()
        if (rate < 20) return rate + 2;      // rate in KB/s
        else           return rate / 5 + 18;

rate / 5 blocks of 16 KiB is 3.2 seconds of data in flight, with no ceiling. The peer on the other end queues a
limited number of requests and ignores the rest: libtorrent itself answers "request_ignored" past
ProtocolExtension::max_request_queue_size (2048) and says so as "reqq" in its extension handshake;
libtorrent-rasterbar and Transmission queue 500 to 2000, uTorrent 255. A pipe of 2048 is reached at 10 MiB/s
from one peer. Past it the connection holds requests nobody will answer, sends no new ones because the pipe is
full, and the transfer drops until the stalled requests time out. A private tracker's two or three seedboxes
are exactly such peers.

This patch caps the pipe at the peer's "reqq" from its extension handshake (clamped to max_request_queue_size),
and at 500 blocks when the peer sent none (Transmission's rule; reviewer fffe on rakshasa/libtorrent#991).
ProtocolExtension::parse_handshake() reads "reqq"; PeerConnectionBase and PeerConnectionMetadata hand it to the
request list before sizing the pipe. The formula below the cap is unchanged. Until 2026-10-07 the cap was
min(500, reqq); docs/notes/2026-10-07-request-pipe-rule-measurements.md measured both on 0.16.25 + #1001 against an
rtorrent seeder (reqq 2048): the same at 20 ms (0 ignored), 110 against 33.5 MiB/s at 100 ms and 1 Gbit/s.

Measured 2026-09-25 (tools/coldstart-rig style: one seeder, plain rtorrent 0.16.24, tc netem 20 ms and 400 Mbit/s
on its egress, the leecher into tmpfs, 2 GiB payload, 40 s, two runs each, seeder's request_ignored counted):

                                         MiB at 40 s    requests the seeder ignored
    rtorrent 0.16.24                     1148, 1154     ~10 000
    + pipe-size-cold-start               1410, 1426     ~13 500 (the transfer stalls from 5 s)
    + pipe-size-cold-start + this        1796, 1800     0
    + this alone                         1728, 1734     0

On TorrentLeech (two seedboxes after the first seconds) plain 0.16.24 took 14 s for 1 GB and rtorrent16 21-27 s:
the five-second counter of pipe-size-cold-start fills the pipe past 2048 within a second or two, where the
thirty-second counter of plain rtorrent reaches it only after about ten.

Tests: test/protocol/test_request_list.cc test_pipe_size_limit (patches/tests/).

diff --git a/src/protocol/extensions.cc b/src/protocol/extensions.cc
index b666bd5..a7ee95e 100644
--- a/src/protocol/extensions.cc
+++ b/src/protocol/extensions.cc
@@ -315,6 +315,13 @@ ProtocolExtension::parse_handshake() {
   if (message[key_metadataSize].is_value())
     m_download->set_metadata_size(message[key_metadataSize].as_value());
 
+  if (message[key_reqq].is_value()) {
+    int64_t reqq = message[key_reqq].as_value();
+
+    if (reqq > 0)
+      m_peer_request_queue = std::min<int64_t>(reqq, max_request_queue_size);
+  }
+
   m_flags &= ~flag_initial_handshake;
 
   return true;
diff --git a/src/protocol/extensions.h b/src/protocol/extensions.h
index 33d0468..e7ef851 100644
--- a/src/protocol/extensions.h
+++ b/src/protocol/extensions.h
@@ -94,6 +94,9 @@ public:
 
   bool                is_default() const               { return m_flags & flag_default; }
 
+  // The number of requests the peer said it queues ("reqq" in its extension handshake), 0 when it said nothing.
+  uint32_t            peer_request_queue() const       { return m_peer_request_queue; }
+
   // Initial PEX message after peer enables PEX needs to send full list
   // of peers instead of the delta list, so keep track of that.
   bool                is_initial_handshake() const     { return m_flags & flag_initial_handshake; }
@@ -129,6 +132,7 @@ private:
   // Set HANDSHAKE as enabled and supported. Those bits should not be
   // touched.
   int                 m_flags{flag_local_enabled_base | flag_remote_supported_base | flag_initial_handshake};
+  uint32_t            m_peer_request_queue{0};
   PeerInfo*           m_peerInfo{};
   DownloadMain*       m_download{};
   PeerConnectionBase* m_connection{};
diff --git a/src/protocol/peer_connection_base.cc b/src/protocol/peer_connection_base.cc
index e90d7c9..89343c2 100644
--- a/src/protocol/peer_connection_base.cc
+++ b/src/protocol/peer_connection_base.cc
@@ -920,6 +920,7 @@ PeerConnectionBase::try_request_pieces() {
   if (request_list()->queued_empty())
     m_down_stall = 0;
 
+  request_list()->set_peer_request_queue(m_extensions->peer_request_queue());
   uint32_t pipeSize = request_list()->calculate_pipe_size(m_peer_chunks.download_throttle()->rate_recent()->rate());
 
   // Don't start requesting if we can't do it in large enough chunks.
diff --git a/src/protocol/peer_connection_metadata.cc b/src/protocol/peer_connection_metadata.cc
index 077b212..5dfdb0f 100644
--- a/src/protocol/peer_connection_metadata.cc
+++ b/src/protocol/peer_connection_metadata.cc
@@ -382,6 +382,7 @@ PeerConnectionMetadata::try_request_metadata_pieces() {
   if (request_list()->queued_empty())
     m_down_stall = 0;
 
+  request_list()->set_peer_request_queue(m_extensions->peer_request_queue());
   uint32_t pipeSize = request_list()->calculate_pipe_size(m_peer_chunks.download_throttle()->rate_recent()->rate());
 
   // Don't start requesting if we can't do it in large enough chunks.
diff --git a/src/protocol/request_list.cc b/src/protocol/request_list.cc
index 36e0656..275e217 100644
--- a/src/protocol/request_list.cc
+++ b/src/protocol/request_list.cc
@@ -324,18 +324,23 @@ RequestList::calculate_pipe_size(uint32_t rate) {
   // Change into KB.
   rate /= 1024;
 
+  uint32_t pipe;
+
   if (!m_delegator->get_aggressive()) {
     if (rate < 20)
-      return rate + 2;
+      pipe = rate + 2;
     else
-      return rate / 5 + 18;
+      pipe = rate / 5 + 18;
 
   } else {
     if (rate < 10)
-      return rate / 5 + 1;
+      pipe = rate / 5 + 1;
     else
-      return rate / 10 + 2;
+      pipe = rate / 10 + 2;
   }
+
+  // Never more than the peer queues: its "reqq", or max_pipe_size when it did not send one.
+  return std::min(pipe, m_peer_request_queue != 0 ? m_peer_request_queue : max_pipe_size);
 }
 
 } // namespace torrent
diff --git a/src/protocol/request_list.h b/src/protocol/request_list.h
index 4a5f81f..75b2418 100644
--- a/src/protocol/request_list.h
+++ b/src/protocol/request_list.h
@@ -80,6 +80,10 @@ public:
   uint32_t             pipe_size() const;
   uint32_t             calculate_pipe_size(uint32_t rate);
 
+  // The pipe never passes the peer's "reqq" from its extension handshake, or max_pipe_size when it gave none (0).
+  static constexpr uint32_t max_pipe_size = 500;
+  void                 set_peer_request_queue(uint32_t v) { m_peer_request_queue = v; }
+
   Delegator*           delegator()                       { return m_delegator; }
   void                 set_delegator(Delegator* d)       { m_delegator = d; }
 
@@ -98,6 +102,7 @@ private:
   void                 delay_process_unordered();
 
   Delegator*           m_delegator{};
+  uint32_t             m_peer_request_queue{0};
   PeerChunks*          m_peer_chunks{};
 
   BlockTransfer*       m_transfer{};
