# Adjust number of pieces requested from peer if we're
# uploading too slowly but downloading very fast so it exhausts the
# queue before we finish sending a piece and can request more. See ticket #1302 - libtorrent.rakshasa.no
Index: libtorrent/src/protocol/peer_connection_base.cc
===================================================================
--- libtorrent/src/protocol/peer_connection_base.cc	(revision 1060)
+++ libtorrent/src/protocol/peer_connection_base.cc	(working copy)
@@ -783,8 +783,11 @@
   if (download_queue()->queued_empty())
     m_downStall = 0;
 
-  uint32_t pipeSize = download_queue()->calculate_pipe_size(m_peerChunks.download_throttle()->rate()->rate());
+  uint32_t upRate = (!m_upChoke.choked() && !m_peerChunks.upload_queue()->empty()) ?
+                    m_peerChunks.upload_throttle()->rate()->rate() : 0;
 
+  uint32_t pipeSize = download_queue()->calculate_pipe_size(m_peerChunks.download_throttle()->rate()->rate(), upRate);
+
   // Don't start requesting if we can't do it in large enough chunks.
   if (download_queue()->queued_size() >= (pipeSize + 10) / 2)
     return false;
Index: libtorrent/src/protocol/request_list.cc
===================================================================
--- libtorrent/src/protocol/request_list.cc	(revision 1060)
+++ libtorrent/src/protocol/request_list.cc	(working copy)
@@ -263,22 +263,30 @@
 }
 
 uint32_t
-RequestList::calculate_pipe_size(uint32_t rate) {
+RequestList::calculate_pipe_size(uint32_t downRate, uint32_t upRate) {
+  // Compute how many pieces we will receive while transmitting one.
+  // Since we can't request during that time, make sure the pipe is
+  // big enough so it doesn't run dry.
+  if (upRate)
+    upRate = downRate / upRate;
+
   // Change into KB.
-  rate /= 1024;
+  downRate /= 1024;
 
   if (!m_delegator->get_aggressive()) {
-    if (rate < 20)
-      return rate + 2;
+    if (downRate < 20)
+      downRate = downRate + 2;
     else
-      return rate / 5 + 18;
+      downRate = downRate / 5 + 18;
 
   } else {
-    if (rate < 10)
-      return rate / 5 + 1;
+    if (downRate < 10)
+      downRate = downRate / 5 + 1;
     else
-      return rate / 10 + 2;
+      downRate = downRate / 10 + 2;
   }
+
+  return std::max(downRate, 1 + upRate);
 }
 
 }
Index: libtorrent/src/protocol/request_list.h
===================================================================
--- libtorrent/src/protocol/request_list.h	(revision 1060)
+++ libtorrent/src/protocol/request_list.h	(working copy)
@@ -87,7 +87,7 @@
   bool                 canceled_empty() const             { return m_canceled.empty(); }
   size_t               canceled_size() const              { return m_queued.size(); }
 
-  uint32_t             calculate_pipe_size(uint32_t rate);
+  uint32_t             calculate_pipe_size(uint32_t downRate, uint32_t upRate);
 
   void                 set_delegator(Delegator* d)       { m_delegator = d; }
   void                 set_peer_chunks(PeerChunks* b)    { m_peerChunks = b; }