diff --git a/src/ut_metadata.cpp b/src/ut_metadata.cpp index e74ac74ac..f9cb7c202 100644 --- a/src/ut_metadata.cpp +++ b/src/ut_metadata.cpp @@ -64,6 +64,25 @@ POSSIBILITY OF SUCH DAMAGE. namespace libtorrent { namespace { + enum + { + // this is the max number of bytes we'll + // queue up in the send buffer. If we exceed this, + // we'll wait another second before checking + // the send buffer size again. So, this may limit + // the rate at which we can server metadata to + // 160 kiB/s + send_buffer_limit = 0x4000 * 10, + + // this is the max number of requests we'll queue + // up. If we get more requests tha this, we'll + // start rejecting them, claiming we don't have + // metadata. If the torrent is greater than 16 MiB, + // we may hit this case (and the client requesting + // doesn't throttle its requests) + max_incoming_requests = 1024, + }; + int div_round_up(int numerator, int denominator) { return (numerator + denominator - 1) / denominator; @@ -326,8 +345,12 @@ namespace libtorrent { namespace write_metadata_packet(2, piece); return true; } - // TODO: put the request on the queue in some cases - write_metadata_packet(1, piece); + if (m_pc.send_buffer_size() < send_buffer_limit) + write_metadata_packet(1, piece); + else if (m_incoming_requests.size() < max_incoming_requests) + m_incoming_requests.push_back(piece); + else + write_metadata_packet(2, piece); } break; case 1: // data @@ -371,6 +394,13 @@ namespace libtorrent { namespace virtual void tick() { maybe_send_request(); + while (!m_incoming_requests.empty() + && m_pc.send_buffer_size() < send_buffer_limit) + { + int piece = m_incoming_requests.front(); + m_incoming_requests.erase(m_incoming_requests.begin()); + write_metadata_packet(1, piece); + } } void maybe_send_request()