diff --git a/ChangeLog b/ChangeLog index d194514e8..64993ea5f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,7 @@ * fix uTP edge case where udp socket buffer fills up * fix nagle implementation in uTP + * fix possible starvation in metadata extension * fix crash when creating torrents and optimizing file order with pad files * disable support for large MTUs in uTP until it is more reliable * expose post_torrent_updates and state_update_alert to python bindings diff --git a/src/ut_metadata.cpp b/src/ut_metadata.cpp index 6210494c8..c2317f911 100644 --- a/src/ut_metadata.cpp +++ b/src/ut_metadata.cpp @@ -130,7 +130,7 @@ namespace libtorrent { namespace // returns a piece of the metadata that // we should request. // returns -1 if we should hold off the request - int metadata_request(); + int metadata_request(bool has_metadata); // this is called from the peer_connection for // each piece of metadata it receives @@ -376,7 +376,7 @@ namespace libtorrent { namespace break; case 2: // have no data { - m_request_limit = (std::min)(time_now() + minutes(1), m_request_limit); + m_request_limit = (std::max)(time_now() + minutes(1), m_request_limit); std::vector::iterator i = std::find(m_sent_requests.begin() , m_sent_requests.end(), piece); // unwanted piece? @@ -414,7 +414,7 @@ namespace libtorrent { namespace && m_sent_requests.size() < 2 && has_metadata()) { - int piece = m_tp.metadata_request(); + int piece = m_tp.metadata_request(m_pc.has_metadata()); if (piece == -1) return; m_sent_requests.push_back(piece); @@ -463,7 +463,10 @@ namespace libtorrent { namespace return boost::shared_ptr(new ut_metadata_peer_plugin(m_torrent, *c, *this)); } - int ut_metadata_plugin::metadata_request() + // has_metadata is false if the peer making the request has not announced + // that it has metadata. In this case, it shouldn't prevent other peers + // from requesting this block by setting a timeout on it. + int ut_metadata_plugin::metadata_request(bool has_metadata) { std::vector::iterator i = std::min_element( m_requested_metadata.begin(), m_requested_metadata.end()); @@ -483,7 +486,13 @@ namespace libtorrent { namespace if (now - m_requested_metadata[piece].last_request < 3) return -1; ++m_requested_metadata[piece].num_requests; - m_requested_metadata[piece].last_request = now; + + // only set the timeout on this block, only if the peer + // has metadata. This is to prevent peers with no metadata + // to starve out sending requests to peers with metadata + if (has_metadata) + m_requested_metadata[piece].last_request = now; + return piece; }