fixed bug related to ignoring upload slots and made the piece rejection code more robust to handle similar bugs better

This commit is contained in:
Arvid Norberg
2009-03-12 17:06:41 +00:00
parent 59fa30400f
commit 0de21dc815
5 changed files with 40 additions and 3 deletions

View File

@@ -3303,6 +3303,8 @@ that will be sent to the tracker. The user-agent is a good way to identify your
int max_sparse_regions; int max_sparse_regions;
bool lock_disk_cache; bool lock_disk_cache;
int max_rejects;
}; };
``user_agent`` this is the client identification to the tracker. ``user_agent`` this is the client identification to the tracker.
@@ -3638,6 +3640,11 @@ to 0 on all platforms except windows.
that's in use, will be locked in physical memory, preventing it from that's in use, will be locked in physical memory, preventing it from
being swapped out. being swapped out.
``max_rejects`` is the number of piece requests we will reject in a row
while a peer is choked before the peer is considered abusive and is
disconnected.
pe_settings pe_settings
=========== ===========

View File

@@ -820,6 +820,14 @@ namespace libtorrent
// at the remote end. // at the remote end.
boost::uint8_t m_desired_queue_size; boost::uint8_t m_desired_queue_size;
// the number of piece requests we have rejected
// in a row because the peer is choked. This is
// used to re-send the choked message in case the
// other end keeps requesting pieces while being
// choked, and eventuelly disconnect if it keeps
// requesting too many pieces while being choked
boost::uint8_t m_choke_rejects;
// if this is true, the disconnection // if this is true, the disconnection
// timestamp is not updated when the connection // timestamp is not updated when the connection
// is closed. This means the time until we can // is closed. This means the time until we can

View File

@@ -159,6 +159,7 @@ namespace libtorrent
#ifndef TORRENT_DISABLE_MLOCK #ifndef TORRENT_DISABLE_MLOCK
, lock_disk_cache(true) , lock_disk_cache(true)
#endif #endif
, max_rejects(50)
{} {}
// this is the user agent that will be sent to the tracker // this is the user agent that will be sent to the tracker
@@ -523,6 +524,10 @@ namespace libtorrent
// be swapped out // be swapped out
bool lock_disk_cache; bool lock_disk_cache;
#endif #endif
// the number of times to reject requests while being
// choked before disconnecting a peer for being malicious
int max_rejects;
}; };
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT

View File

@@ -117,6 +117,7 @@ namespace libtorrent
, m_rtt(0) , m_rtt(0)
, m_prefer_whole_pieces(0) , m_prefer_whole_pieces(0)
, m_desired_queue_size(2) , m_desired_queue_size(2)
, m_choke_rejects(0)
, m_fast_reconnect(false) , m_fast_reconnect(false)
, m_active(true) , m_active(true)
, m_peer_interested(false) , m_peer_interested(false)
@@ -228,6 +229,7 @@ namespace libtorrent
, m_rtt(0) , m_rtt(0)
, m_prefer_whole_pieces(0) , m_prefer_whole_pieces(0)
, m_desired_queue_size(2) , m_desired_queue_size(2)
, m_choke_rejects(0)
, m_fast_reconnect(false) , m_fast_reconnect(false)
, m_active(false) , m_active(false)
, m_peer_interested(false) , m_peer_interested(false)
@@ -1166,7 +1168,7 @@ namespace libtorrent
#endif #endif
m_peer_interested = true; m_peer_interested = true;
if (is_disconnecting()) return; if (is_disconnecting()) return;
if (ignore_unchoke_slots()) write_unchoke(); if (ignore_unchoke_slots()) send_unchoke();
t->get_policy().interested(*this); t->get_policy().interested(*this);
} }
@@ -1209,7 +1211,7 @@ namespace libtorrent
m_ses.m_unchoke_time_scaler = 0; m_ses.m_unchoke_time_scaler = 0;
} }
if (ignore_unchoke_slots()) write_choke(); if (ignore_unchoke_slots()) send_unchoke();
t->get_policy().not_interested(*this); t->get_policy().not_interested(*this);
if (t->super_seeding() && m_superseed_piece != -1) if (t->super_seeding() && m_superseed_piece != -1)
@@ -1611,6 +1613,7 @@ namespace libtorrent
if (m_choked && m_accept_fast.find(r.piece) == m_accept_fast.end()) if (m_choked && m_accept_fast.find(r.piece) == m_accept_fast.end())
{ {
write_reject_request(r); write_reject_request(r);
++m_choke_rejects;
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
(*m_logger) << time_now_string() (*m_logger) << time_now_string()
<< " *** REJECTING REQUEST [ peer choked and piece not in allowed fast set ]\n"; << " *** REJECTING REQUEST [ peer choked and piece not in allowed fast set ]\n";
@@ -1620,9 +1623,22 @@ namespace libtorrent
"s: " << r.start << " | " "s: " << r.start << " | "
"l: " << r.length << " ]\n"; "l: " << r.length << " ]\n";
#endif #endif
if (m_choke_rejects > m_ses.settings().max_rejects)
{
disconnect("too many piece requests while choked");
return;
}
else if ((m_choke_rejects & 0xf) == 0)
{
// tell the peer it's choked again
// every 16 requests in a row
write_choke();
}
} }
else else
{ {
m_choke_rejects = 0;
m_requests.push_back(r); m_requests.push_back(r);
m_last_incoming_request = time_now(); m_last_incoming_request = time_now();
fill_send_buffer(); fill_send_buffer();
@@ -2437,6 +2453,7 @@ namespace libtorrent
boost::shared_ptr<torrent> t = m_torrent.lock(); boost::shared_ptr<torrent> t = m_torrent.lock();
TORRENT_ASSERT(t); TORRENT_ASSERT(t);
if (has_peer_choked()) return;
if ((int)m_download_queue.size() >= m_desired_queue_size) return; if ((int)m_download_queue.size() >= m_desired_queue_size) return;
bool empty_download_queue = m_download_queue.empty(); bool empty_download_queue = m_download_queue.empty();

View File

@@ -884,7 +884,7 @@ namespace libtorrent
&& ses.num_uploads() < ses.max_uploads() && ses.num_uploads() < ses.max_uploads()
&& !c.ignore_unchoke_slots() && !c.ignore_unchoke_slots()
&& (m_torrent->ratio() == 0 && (m_torrent->ratio() == 0
|| c.share_diff() >= -free_upload_amount || c.share_diff() >= size_type(-free_upload_amount)
|| m_torrent->is_finished())) || m_torrent->is_finished()))
{ {
ses.unchoke_peer(c); ses.unchoke_peer(c);