lt sync 2453
This commit is contained in:
parent
eeedd79f45
commit
6cb4d27b7e
|
@ -394,14 +394,7 @@ namespace libtorrent
|
|||
bool err = false;
|
||||
detail::bdecode_recursive(start, end, e, err, 0);
|
||||
TORRENT_ASSERT(e.m_type_queried == false);
|
||||
if (err)
|
||||
{
|
||||
#ifdef BOOST_NO_EXCEPTIONS
|
||||
return entry();
|
||||
#else
|
||||
throw invalid_encoding();
|
||||
#endif
|
||||
}
|
||||
if (err) return entry();
|
||||
return e;
|
||||
}
|
||||
|
||||
|
@ -414,14 +407,7 @@ namespace libtorrent
|
|||
detail::bdecode_recursive(start, end, e, err, 0);
|
||||
len = std::distance(s, start);
|
||||
TORRENT_ASSERT(len >= 0);
|
||||
if (err)
|
||||
{
|
||||
#ifdef BOOST_NO_EXCEPTIONS
|
||||
return entry();
|
||||
#else
|
||||
throw invalid_encoding();
|
||||
#endif
|
||||
}
|
||||
if (err) return entry();
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -459,11 +459,6 @@ namespace libtorrent
|
|||
int block_size() const { TORRENT_ASSERT(m_block_size > 0); return m_block_size; }
|
||||
peer_request to_req(piece_block const& p);
|
||||
|
||||
// this will tell all peers that we just got his piece
|
||||
// and also let the piece picker know that we have this piece
|
||||
// so it wont pick it for download
|
||||
void announce_piece(int index);
|
||||
|
||||
void disconnect_all();
|
||||
int disconnect_peers(int num);
|
||||
|
||||
|
@ -504,7 +499,22 @@ namespace libtorrent
|
|||
// each time a piece has failed the hash
|
||||
// test
|
||||
void piece_finished(int index, int passed_hash_check);
|
||||
|
||||
// piece_passed is called when a piece passes the hash check
|
||||
// this will tell all peers that we just got his piece
|
||||
// and also let the piece picker know that we have this piece
|
||||
// so it wont pick it for download
|
||||
void piece_passed(int index);
|
||||
|
||||
// piece_failed is called when a piece fails the hash check
|
||||
void piece_failed(int index);
|
||||
|
||||
// this will restore the piece picker state for a piece
|
||||
// by re marking all the requests to blocks in this piece
|
||||
// that are still outstanding in peers' download queues.
|
||||
// this is done when a piece fails
|
||||
void restore_piece_state(int index);
|
||||
|
||||
void received_redundant_data(int num_bytes)
|
||||
{ TORRENT_ASSERT(num_bytes > 0); m_total_redundant_bytes += num_bytes; }
|
||||
|
||||
|
|
|
@ -226,13 +226,7 @@ namespace libtorrent
|
|||
|
||||
// handle tracker response
|
||||
entry e;
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
try {
|
||||
#endif
|
||||
e = bdecode(data, data + size);
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
} catch (std::exception&) {}
|
||||
#endif
|
||||
|
||||
if (e.type() != entry::undefined_t)
|
||||
{
|
||||
|
|
|
@ -444,6 +444,15 @@ namespace libtorrent { namespace dht
|
|||
TORRENT_ASSERT(bytes_transferred > 0);
|
||||
|
||||
entry e = bdecode(buf, buf + bytes_transferred);
|
||||
if (e.type() == entry::undefined_t)
|
||||
{
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
std::string msg(buf, buf + bytes_transferred);
|
||||
TORRENT_LOG(dht_tracker) << "invalid incoming packet: "
|
||||
<< e.what() << "\n" << msg << "\n";
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
std::stringstream log_line;
|
||||
|
|
|
@ -53,6 +53,8 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/socket_type.hpp"
|
||||
#include "libtorrent/assert.hpp"
|
||||
|
||||
//#define TORRENT_CORRUPT_DATA
|
||||
|
||||
using boost::bind;
|
||||
using boost::shared_ptr;
|
||||
using libtorrent::aux::session_impl;
|
||||
|
@ -1447,6 +1449,15 @@ namespace libtorrent
|
|||
TORRENT_ASSERT(!m_disk_recv_buffer);
|
||||
TORRENT_ASSERT(m_disk_recv_buffer_size == 0);
|
||||
|
||||
#ifdef TORRENT_CORRUPT_DATA
|
||||
// corrupt all pieces from certain peers
|
||||
if (m_remote.address().is_v4()
|
||||
&& (m_remote.address().to_v4().to_ulong() & 0xf) == 0)
|
||||
{
|
||||
data.get()[0] = ~data.get()[0];
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
for (extension_list_t::iterator i = m_extensions.begin()
|
||||
, end(m_extensions.end()); i != end; ++i)
|
||||
|
|
|
@ -1775,18 +1775,13 @@ namespace libtorrent
|
|||
TORRENT_ASSERT(block.piece_index < (int)m_piece_map.size());
|
||||
TORRENT_ASSERT(block.block_index < blocks_in_piece(block.piece_index));
|
||||
|
||||
// this might be the case if a piece fails, is restored, and then
|
||||
// completed from a different peer (from which the piece was requested
|
||||
// before it failed the hash check)
|
||||
if (m_piece_map[block.piece_index].downloading == 0)
|
||||
mark_as_downloading(block, peer, piece_picker::none);
|
||||
|
||||
TORRENT_ASSERT(m_piece_map[block.piece_index].downloading);
|
||||
|
||||
std::vector<downloading_piece>::iterator i
|
||||
= std::find_if(m_downloads.begin(), m_downloads.end(), has_index(block.piece_index));
|
||||
TORRENT_ASSERT(i != m_downloads.end());
|
||||
block_info& info = i->info[block.block_index];
|
||||
|
||||
info.peer = peer;
|
||||
TORRENT_ASSERT(info.state == block_info::state_requested);
|
||||
if (info.state == block_info::state_requested) --i->requested;
|
||||
|
|
|
@ -1445,6 +1445,9 @@ namespace libtorrent
|
|||
slots.push_back((*i >= 0) ? *i : unassigned);
|
||||
}
|
||||
}
|
||||
|
||||
rd["allocation"] = m_storage_mode == storage_mode_sparse?"sparse"
|
||||
:m_storage_mode == storage_mode_allocate?"full":"compact";
|
||||
}
|
||||
|
||||
void piece_manager::mark_failed(int piece_index)
|
||||
|
@ -1838,7 +1841,7 @@ namespace libtorrent
|
|||
return check_no_fastresume(error);
|
||||
}
|
||||
|
||||
if (storage_mode == storage_mode_compact)
|
||||
if (m_storage_mode == storage_mode_compact)
|
||||
{
|
||||
int num_pieces = int(m_files.num_pieces());
|
||||
m_slot_to_piece.resize(num_pieces, unallocated);
|
||||
|
@ -1931,6 +1934,42 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
}
|
||||
else if (m_storage_mode == storage_mode_compact)
|
||||
{
|
||||
// read piece map
|
||||
entry const* pieces = rd.find_key("pieces");
|
||||
if (pieces == 0 || pieces->type() != entry::string_t)
|
||||
{
|
||||
error = "missing pieces entry";
|
||||
return check_no_fastresume(error);
|
||||
}
|
||||
|
||||
if ((int)pieces->string().size() != m_files.num_pieces())
|
||||
{
|
||||
error = "file has more slots than torrent (slots: "
|
||||
+ boost::lexical_cast<std::string>(pieces->string().size()) + " size: "
|
||||
+ boost::lexical_cast<std::string>(m_files.num_pieces()) + " )";
|
||||
return check_no_fastresume(error);
|
||||
}
|
||||
|
||||
int num_pieces = int(m_files.num_pieces());
|
||||
m_slot_to_piece.resize(num_pieces, unallocated);
|
||||
m_piece_to_slot.resize(num_pieces, has_no_slot);
|
||||
std::string const& have_pieces = pieces->string();
|
||||
for (int i = 0; i < num_pieces; ++i)
|
||||
{
|
||||
if (have_pieces[i] & 1)
|
||||
{
|
||||
m_slot_to_piece[i] = i;
|
||||
m_piece_to_slot[i] = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_free_slots.push_back(i);
|
||||
}
|
||||
}
|
||||
if (m_unallocated_slots.empty()) switch_to_full_mode();
|
||||
}
|
||||
|
||||
return check_init_storage(error);
|
||||
}
|
||||
|
|
|
@ -1238,47 +1238,13 @@ namespace libtorrent
|
|||
?"disk failed":"failed") << " ]\n";
|
||||
#endif
|
||||
|
||||
bool was_finished = m_picker->num_filtered() + num_have()
|
||||
== torrent_file().num_pieces();
|
||||
TORRENT_ASSERT(valid_metadata());
|
||||
|
||||
if (passed_hash_check == 0)
|
||||
{
|
||||
if (m_ses.m_alerts.should_post(alert::debug))
|
||||
{
|
||||
m_ses.m_alerts.post_alert(piece_finished_alert(get_handle()
|
||||
, index, "piece finished"));
|
||||
}
|
||||
// the following call may cause picker to become invalid
|
||||
// in case we just became a seed
|
||||
announce_piece(index);
|
||||
TORRENT_ASSERT(valid_metadata());
|
||||
// if we just became a seed, picker is now invalid, since it
|
||||
// is deallocated by the torrent once it starts seeding
|
||||
|
||||
// since this piece just passed, we might have
|
||||
// become uninterested in some peers where this
|
||||
// was the last piece we were interested in
|
||||
for (peer_iterator i = m_connections.begin()
|
||||
, end(m_connections.end()); i != end; ++i)
|
||||
{
|
||||
peer_connection* p = *i;
|
||||
// if we're not interested already, no need to check
|
||||
if (!p->is_interesting()) continue;
|
||||
// if the peer doesn't have the piece we just got, it
|
||||
// wouldn't affect our interest
|
||||
if (!p->has_piece(index)) continue;
|
||||
p->update_interest();
|
||||
}
|
||||
|
||||
if (!was_finished&& is_finished())
|
||||
{
|
||||
TORRENT_ASSERT(passed_hash_check == 0);
|
||||
// torrent finished
|
||||
// i.e. all the pieces we're interested in have
|
||||
// been downloaded. Release the files (they will open
|
||||
// in read only mode if needed)
|
||||
finished();
|
||||
}
|
||||
piece_passed(index);
|
||||
}
|
||||
else if (passed_hash_check == -2)
|
||||
{
|
||||
|
@ -1289,6 +1255,88 @@ namespace libtorrent
|
|||
{
|
||||
TORRENT_ASSERT(passed_hash_check == -1);
|
||||
m_picker->restore_piece(index);
|
||||
restore_piece_state(index);
|
||||
}
|
||||
}
|
||||
|
||||
void torrent::piece_passed(int index)
|
||||
{
|
||||
// INVARIANT_CHECK;
|
||||
|
||||
TORRENT_ASSERT(index >= 0);
|
||||
TORRENT_ASSERT(index < m_torrent_file->num_pieces());
|
||||
|
||||
if (m_ses.m_alerts.should_post(alert::debug))
|
||||
{
|
||||
m_ses.m_alerts.post_alert(piece_finished_alert(get_handle()
|
||||
, index, "piece finished"));
|
||||
}
|
||||
|
||||
bool was_finished = m_picker->num_filtered() + num_have()
|
||||
== torrent_file().num_pieces();
|
||||
|
||||
std::vector<void*> downloaders;
|
||||
m_picker->get_downloaders(downloaders, index);
|
||||
|
||||
// increase the trust point of all peers that sent
|
||||
// parts of this piece.
|
||||
std::set<void*> peers;
|
||||
std::copy(downloaders.begin(), downloaders.end(), std::inserter(peers, peers.begin()));
|
||||
|
||||
m_picker->we_have(index);
|
||||
for (peer_iterator i = m_connections.begin(); i != m_connections.end(); ++i)
|
||||
(*i)->announce_piece(index);
|
||||
|
||||
for (std::set<void*>::iterator i = peers.begin()
|
||||
, end(peers.end()); i != end; ++i)
|
||||
{
|
||||
policy::peer* p = static_cast<policy::peer*>(*i);
|
||||
if (p == 0) continue;
|
||||
p->on_parole = false;
|
||||
++p->trust_points;
|
||||
// TODO: make this limit user settable
|
||||
if (p->trust_points > 20) p->trust_points = 20;
|
||||
if (p->connection) p->connection->received_valid_data(index);
|
||||
}
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
for (extension_list_t::iterator i = m_extensions.begin()
|
||||
, end(m_extensions.end()); i != end; ++i)
|
||||
{
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
try {
|
||||
#endif
|
||||
(*i)->on_piece_pass(index);
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
} catch (std::exception&) {}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
// since this piece just passed, we might have
|
||||
// become uninterested in some peers where this
|
||||
// was the last piece we were interested in
|
||||
for (peer_iterator i = m_connections.begin()
|
||||
, end(m_connections.end()); i != end; ++i)
|
||||
{
|
||||
peer_connection* p = *i;
|
||||
// if we're not interested already, no need to check
|
||||
if (!p->is_interesting()) continue;
|
||||
// if the peer doesn't have the piece we just got, it
|
||||
// wouldn't affect our interest
|
||||
if (!p->has_piece(index)) continue;
|
||||
p->update_interest();
|
||||
}
|
||||
|
||||
if (!was_finished && is_finished())
|
||||
{
|
||||
// torrent finished
|
||||
// i.e. all the pieces we're interested in have
|
||||
// been downloaded. Release the files (they will open
|
||||
// in read only mode if needed)
|
||||
finished();
|
||||
// if we just became a seed, picker is now invalid, since it
|
||||
// is deallocated by the torrent once it starts seeding
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1402,6 +1450,7 @@ namespace libtorrent
|
|||
// start with redownloading the pieces that the client
|
||||
// that has sent the least number of pieces
|
||||
m_picker->restore_piece(index);
|
||||
restore_piece_state(index);
|
||||
TORRENT_ASSERT(m_storage);
|
||||
|
||||
TORRENT_ASSERT(m_picker->have_piece(index) == false);
|
||||
|
@ -1419,6 +1468,32 @@ namespace libtorrent
|
|||
#endif
|
||||
}
|
||||
|
||||
void torrent::restore_piece_state(int index)
|
||||
{
|
||||
TORRENT_ASSERT(has_picker());
|
||||
for (peer_iterator i = m_connections.begin();
|
||||
i != m_connections.end(); ++i)
|
||||
{
|
||||
peer_connection* p = *i;
|
||||
std::deque<piece_block> const& dq = p->download_queue();
|
||||
std::deque<piece_block> const& rq = p->request_queue();
|
||||
for (std::deque<piece_block>::const_iterator k = dq.begin()
|
||||
, end(dq.end()); k != end; ++k)
|
||||
{
|
||||
if (k->piece_index != index) continue;
|
||||
m_picker->mark_as_downloading(*k, p->peer_info_struct()
|
||||
, (piece_picker::piece_state_t)p->peer_speed());
|
||||
}
|
||||
for (std::deque<piece_block>::const_iterator k = rq.begin()
|
||||
, end(rq.end()); k != end; ++k)
|
||||
{
|
||||
if (k->piece_index != index) continue;
|
||||
m_picker->mark_as_downloading(*k, p->peer_info_struct()
|
||||
, (piece_picker::piece_state_t)p->peer_speed());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void torrent::abort()
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
@ -1525,52 +1600,6 @@ namespace libtorrent
|
|||
}
|
||||
}
|
||||
|
||||
void torrent::announce_piece(int index)
|
||||
{
|
||||
// INVARIANT_CHECK;
|
||||
|
||||
TORRENT_ASSERT(index >= 0);
|
||||
TORRENT_ASSERT(index < m_torrent_file->num_pieces());
|
||||
|
||||
std::vector<void*> downloaders;
|
||||
m_picker->get_downloaders(downloaders, index);
|
||||
|
||||
// increase the trust point of all peers that sent
|
||||
// parts of this piece.
|
||||
std::set<void*> peers;
|
||||
std::copy(downloaders.begin(), downloaders.end(), std::inserter(peers, peers.begin()));
|
||||
|
||||
m_picker->we_have(index);
|
||||
for (peer_iterator i = m_connections.begin(); i != m_connections.end(); ++i)
|
||||
(*i)->announce_piece(index);
|
||||
|
||||
for (std::set<void*>::iterator i = peers.begin()
|
||||
, end(peers.end()); i != end; ++i)
|
||||
{
|
||||
policy::peer* p = static_cast<policy::peer*>(*i);
|
||||
if (p == 0) continue;
|
||||
p->on_parole = false;
|
||||
++p->trust_points;
|
||||
// TODO: make this limit user settable
|
||||
if (p->trust_points > 20) p->trust_points = 20;
|
||||
if (p->connection) p->connection->received_valid_data(index);
|
||||
}
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
for (extension_list_t::iterator i = m_extensions.begin()
|
||||
, end(m_extensions.end()); i != end; ++i)
|
||||
{
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
try {
|
||||
#endif
|
||||
(*i)->on_piece_pass(index);
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
} catch (std::exception&) {}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string torrent::tracker_login() const
|
||||
{
|
||||
if (m_username.empty() && m_password.empty()) return "";
|
||||
|
@ -2433,9 +2462,6 @@ namespace libtorrent
|
|||
ret["num_seeds"] = seeds;
|
||||
ret["num_downloaders"] = downloaders;
|
||||
|
||||
ret["allocation"] = m_storage_mode == storage_mode_sparse?"sparse"
|
||||
:m_storage_mode == storage_mode_allocate?"full":"compact";
|
||||
|
||||
const sha1_hash& info_hash = torrent_file().info_hash();
|
||||
ret["info-hash"] = std::string((char*)info_hash.begin(), (char*)info_hash.end());
|
||||
|
||||
|
@ -3175,6 +3201,11 @@ namespace libtorrent
|
|||
{
|
||||
if (m_sequential_download)
|
||||
picker().sequential_download(m_sequential_download);
|
||||
|
||||
// if we just finished checking and we're not a seed, we are
|
||||
// likely to be unpaused
|
||||
if (m_ses.m_auto_manage_time_scaler > 1)
|
||||
m_ses.m_auto_manage_time_scaler = 1;
|
||||
}
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
|
|
|
@ -306,7 +306,7 @@ namespace libtorrent { namespace
|
|||
|
||||
if (length > 17 * 1024)
|
||||
{
|
||||
m_pc.disconnect("ut_metadata message larger than 17 kB");
|
||||
m_pc.disconnect("ut_metadata message larger than 17 kB", 2);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -314,6 +314,11 @@ namespace libtorrent { namespace
|
|||
|
||||
int len;
|
||||
entry msg = bdecode(body.begin, body.end, len);
|
||||
if (msg.type() == entry::undefined_t)
|
||||
{
|
||||
m_pc.disconnect("invalid bencoding in ut_metadata message", 2);
|
||||
return true;
|
||||
}
|
||||
|
||||
int type = msg["msg_type"].integer();
|
||||
int piece = msg["piece"].integer();
|
||||
|
@ -364,7 +369,7 @@ namespace libtorrent { namespace
|
|||
{
|
||||
std::stringstream msg;
|
||||
msg << "unknown ut_metadata extension message: " << type;
|
||||
m_pc.disconnect(msg.str().c_str());
|
||||
m_pc.disconnect(msg.str().c_str(), 2);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -216,13 +216,18 @@ namespace libtorrent { namespace
|
|||
|
||||
if (length > 500 * 1024)
|
||||
{
|
||||
m_pc.disconnect("peer exchange message larger than 500 kB");
|
||||
m_pc.disconnect("peer exchange message larger than 500 kB", 2);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (body.left() < length) return true;
|
||||
|
||||
entry pex_msg = bdecode(body.begin, body.end);
|
||||
if (pex_msg.type() == entry::undefined_t)
|
||||
{
|
||||
m_pc.disconnect("invalid bencoding in ut_metadata message", 2);
|
||||
return true;
|
||||
}
|
||||
|
||||
entry const* p = pex_msg.find_key("added");
|
||||
entry const* pf = pex_msg.find_key("added.f");
|
||||
|
|
Loading…
Reference in New Issue