lt sync 2453

This commit is contained in:
Andrew Resch 2008-06-23 22:58:46 +00:00
parent eeedd79f45
commit 6cb4d27b7e
10 changed files with 207 additions and 122 deletions

View File

@ -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;
}
}

View File

@ -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; }

View File

@ -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)
{

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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);
}

View File

@ -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

View File

@ -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;

View File

@ -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");