diff --git a/include/libtorrent/peer_connection.hpp b/include/libtorrent/peer_connection.hpp index 39b86b43c..3b68cc879 100644 --- a/include/libtorrent/peer_connection.hpp +++ b/include/libtorrent/peer_connection.hpp @@ -480,6 +480,9 @@ namespace libtorrent void incoming_allowed_fast(int index); void incoming_suggest(int index); + void set_has_metadata(bool m) { m_has_metadata = m; } + bool has_metadata() const { return m_has_metadata; } + // the following functions appends messages // to the send buffer bool send_choke(); @@ -1164,6 +1167,10 @@ namespace libtorrent // buffer, and send it once we're uncorked. bool m_corked:1; + // set to true if this peer has metadata, and false + // otherwise. + bool m_has_metadata:1; + template struct handler_storage { diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index 2c2ba7f03..ded43a9d1 100644 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -193,6 +193,7 @@ namespace libtorrent , m_holepunch_mode(false) , m_ignore_stats(false) , m_corked(false) + , m_has_metadata(true) #if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS , m_in_constructor(true) , m_disconnect_started(false) @@ -1100,7 +1101,9 @@ namespace libtorrent void peer_connection::received_valid_data(int index) { - INVARIANT_CHECK; + // this fails because we haven't had time to disconnect + // seeds yet, and we might have just become one +// INVARIANT_CHECK; #ifndef TORRENT_DISABLE_EXTENSIONS for (extension_list_t::iterator i = m_extensions.begin() @@ -1562,6 +1565,12 @@ namespace libtorrent m_peer_interested = true; if (is_disconnecting()) return; + // if the peer is ready to download stuff, it must have metadata + m_has_metadata = true; + + disconnect_if_redundant(); + if (is_disconnecting()) return; + if (is_choked()) { if (ignore_unchoke_slots()) @@ -1710,7 +1719,7 @@ namespace libtorrent if (!t->valid_metadata() && index >= int(m_have_piece.size())) { - if (index < 65536) + if (index < 131072) { // if we don't have metadata // and we might not have received a bitfield @@ -1776,7 +1785,10 @@ namespace libtorrent // update bytes downloaded since last timer m_remote_bytes_dled += t->torrent_file().piece_size(index); } - + + // if the peer is downloading stuff, it must have metadata + m_has_metadata = true; + // it's important to not disconnect before we have // updated the piece picker, otherwise we will incorrectly // decrement the piece count without first incrementing it @@ -1994,6 +2006,12 @@ namespace libtorrent boost::shared_ptr t = m_torrent.lock(); if (!t) return; + // if we don't have the metadata yet, don't disconnect + // also, if the peer doesn't have metadata we shouldn't + // disconnect it, since it may want to request the + // metadata from us + if (!t->valid_metadata() || !has_metadata()) return; + // don't close connections in share mode, we don't know if we need them if (t->share_mode()) return; diff --git a/src/ut_metadata.cpp b/src/ut_metadata.cpp index 8ccdd7222..e74ac74ac 100644 --- a/src/ut_metadata.cpp +++ b/src/ut_metadata.cpp @@ -132,7 +132,7 @@ namespace libtorrent { namespace void metadata_size(int size) { - if (m_metadata_size > 0 || size <= 0 || size > 2 * 1024 * 1024) return; + if (m_metadata_size > 0 || size <= 0 || size > 4 * 1024 * 1024) return; m_metadata_size = size; m_metadata.reset(new char[size]); m_requested_metadata.resize(div_round_up(size, 16 * 1024)); @@ -206,6 +206,9 @@ namespace libtorrent { namespace int metadata_size = h.dict_find_int_value("metadata_size"); if (metadata_size > 0) m_tp.metadata_size(metadata_size); + else + m_pc.set_has_metadata(false); + maybe_send_request(); return true; }