lt sync 2388

This commit is contained in:
Andrew Resch 2008-06-07 18:58:33 +00:00
parent bf00795050
commit 7107413d0e
19 changed files with 408 additions and 240 deletions

View File

@ -13,7 +13,7 @@ object pieces(torrent_status const& s)
{ {
list result; list result;
for (bitfield::const_iterator i(s.pieces->begin()), e(s.pieces->end()); i != e; ++i) for (bitfield::const_iterator i(s.pieces.begin()), e(s.pieces.end()); i != e; ++i)
result.append(*i); result.append(*i);
return result; return result;

View File

@ -209,7 +209,7 @@ namespace libtorrent
void write_not_interested(); void write_not_interested();
void write_request(peer_request const& r); void write_request(peer_request const& r);
void write_cancel(peer_request const& r); void write_cancel(peer_request const& r);
void write_bitfield(bitfield const& bits); void write_bitfield();
void write_have(int index); void write_have(int index);
void write_piece(peer_request const& r, disk_buffer_holder& buffer); void write_piece(peer_request const& r, disk_buffer_holder& buffer);
void write_handshake(); void write_handshake();

View File

@ -34,6 +34,7 @@ POSSIBILITY OF SUCH DAMAGE.
#define TORRENT_CONFIG_HPP_INCLUDED #define TORRENT_CONFIG_HPP_INCLUDED
#include <boost/config.hpp> #include <boost/config.hpp>
#include <boost/version.hpp>
#if defined(__GNUC__) && __GNUC__ >= 4 #if defined(__GNUC__) && __GNUC__ >= 4
@ -81,7 +82,12 @@ POSSIBILITY OF SUCH DAMAGE.
#define TORRENT_BSD #define TORRENT_BSD
#endif #endif
// should wpath or path be used?
#if defined UNICODE && !defined BOOST_FILESYSTEM_NARROW_ONLY && BOOST_VERSION >= 103400
#define TORRENT_USE_WPATH 1
#else
#define TORRENT_USE_WPATH 0
#endif
#endif // TORRENT_CONFIG_HPP_INCLUDED #endif // TORRENT_CONFIG_HPP_INCLUDED

View File

@ -129,18 +129,13 @@ namespace libtorrent
boost::int16_t requested; boost::int16_t requested;
}; };
piece_picker(int blocks_per_piece piece_picker();
, int total_num_blocks);
void get_availability(std::vector<int>& avail) const; void get_availability(std::vector<int>& avail) const;
void sequential_download(bool sd); void sequential_download(bool sd);
bool sequential_download() const { return m_sequential_download >= 0; } bool sequential_download() const { return m_sequential_download >= 0; }
// the vector tells which pieces we already have
// and which we don't have.
void init(bitfield const& pieces);
// increases the peer count for the given piece // increases the peer count for the given piece
// (is used when a HAVE message is received) // (is used when a HAVE message is received)
void inc_refcount(int index); void inc_refcount(int index);
@ -164,6 +159,17 @@ namespace libtorrent
// we are not interested in this piece anymore // we are not interested in this piece anymore
// (i.e. we don't have to maintain a refcount) // (i.e. we don't have to maintain a refcount)
void we_have(int index); void we_have(int index);
void we_dont_have(int index);
void init(int blocks_per_piece, int total_num_blocks);
int num_pieces() const { return int(m_piece_map.size()); }
bool have_piece(int index) const
{
TORRENT_ASSERT(index >= 0);
TORRENT_ASSERT(index < int(m_piece_map.size()));
return m_piece_map[index].index == piece_pos::we_have_index;
}
// sets the priority of a piece. // sets the priority of a piece.
// returns true if the priority was changed from 0 to non-0 // returns true if the priority was changed from 0 to non-0
@ -276,6 +282,8 @@ namespace libtorrent
// the number of filtered pieces we already have // the number of filtered pieces we already have
int num_have_filtered() const { return m_num_have_filtered; } int num_have_filtered() const { return m_num_have_filtered; }
int num_have() const { return m_num_have; }
#ifndef NDEBUG #ifndef NDEBUG
// used in debug mode // used in debug mode
void verify_priority(int start, int end, int prio) const; void verify_priority(int start, int end, int prio) const;
@ -350,6 +358,7 @@ namespace libtorrent
bool have() const { return index == we_have_index; } bool have() const { return index == we_have_index; }
void set_have() { index = we_have_index; TORRENT_ASSERT(have()); } void set_have() { index = we_have_index; TORRENT_ASSERT(have()); }
void set_not_have() { index = 0; TORRENT_ASSERT(!have()); }
bool filtered() const { return piece_priority == filter_priority; } bool filtered() const { return piece_priority == filter_priority; }
void filtered(bool f) { piece_priority = f ? filter_priority : 0; } void filtered(bool f) { piece_priority = f ? filter_priority : 0; }
@ -466,10 +475,6 @@ namespace libtorrent
// if this is set to true, it means update_pieces() // if this is set to true, it means update_pieces()
// has to be called before accessing m_pieces. // has to be called before accessing m_pieces.
mutable bool m_dirty; mutable bool m_dirty;
#ifndef NDEBUG
bool m_files_checked_called;
#endif
}; };
inline int piece_picker::blocks_in_piece(int index) const inline int piece_picker::blocks_in_piece(int index) const

View File

@ -129,7 +129,7 @@ namespace libtorrent
, resume_data(0) , resume_data(0)
, storage_mode(storage_mode_sparse) , storage_mode(storage_mode_sparse)
, paused(true) , paused(true)
, auto_managed(false) , auto_managed(true)
, duplicate_is_error(false) , duplicate_is_error(false)
, storage(sc) , storage(sc)
, userdata(0) , userdata(0)

View File

@ -149,6 +149,7 @@ namespace libtorrent
void init(); void init();
void on_resume_data_checked(int ret, disk_io_job const& j); void on_resume_data_checked(int ret, disk_io_job const& j);
void on_force_recheck(int ret, disk_io_job const& j);
void on_piece_checked(int ret, disk_io_job const& j); void on_piece_checked(int ret, disk_io_job const& j);
void files_checked(); void files_checked();
void start_checking(); void start_checking();
@ -180,6 +181,7 @@ namespace libtorrent
std::string name() const; std::string name() const;
stat statistics() const { return m_stat; } stat statistics() const { return m_stat; }
void add_stats(stat const& s) { m_stat += s; }
size_type bytes_left() const; size_type bytes_left() const;
boost::tuples::tuple<size_type, size_type> bytes_done() const; boost::tuples::tuple<size_type, size_type> bytes_done() const;
size_type quantized_bytes_done() const; size_type quantized_bytes_done() const;
@ -190,6 +192,7 @@ namespace libtorrent
void pause(); void pause();
void resume(); void resume();
bool is_paused() const { return m_paused; } bool is_paused() const { return m_paused; }
void force_recheck();
void save_resume_data(); void save_resume_data();
bool is_auto_managed() const { return m_auto_managed; } bool is_auto_managed() const { return m_auto_managed; }
@ -377,14 +380,15 @@ namespace libtorrent
// returns true if we have downloaded the given piece // returns true if we have downloaded the given piece
bool have_piece(int index) const bool have_piece(int index) const
{ {
TORRENT_ASSERT(index >= 0 && index < (signed)m_have_pieces.size()); return has_picker()?m_picker->have_piece(index):true;
return m_have_pieces[index];
} }
bitfield const& pieces() const int num_have() const
{ return m_have_pieces; } {
return has_picker()
int num_pieces() const { return m_num_pieces; } ?m_picker->num_have()
:m_torrent_file->num_pieces();
}
// when we get a have message, this is called for that piece // when we get a have message, this is called for that piece
void peer_has(int index) void peer_has(int index)
@ -392,7 +396,6 @@ namespace libtorrent
if (m_picker.get()) if (m_picker.get())
{ {
TORRENT_ASSERT(!is_seed()); TORRENT_ASSERT(!is_seed());
TORRENT_ASSERT(index >= 0 && index < (signed)m_have_pieces.size());
m_picker->inc_refcount(index); m_picker->inc_refcount(index);
} }
#ifndef NDEBUG #ifndef NDEBUG
@ -439,7 +442,6 @@ namespace libtorrent
if (m_picker.get()) if (m_picker.get())
{ {
TORRENT_ASSERT(!is_seed()); TORRENT_ASSERT(!is_seed());
TORRENT_ASSERT(index >= 0 && index < (signed)m_have_pieces.size());
m_picker->dec_refcount(index); m_picker->dec_refcount(index);
} }
#ifndef NDEBUG #ifndef NDEBUG
@ -506,7 +508,9 @@ namespace libtorrent
bool is_seed() const bool is_seed() const
{ {
return valid_metadata() return valid_metadata()
&& m_num_pieces == m_torrent_file->num_pieces(); && (!m_picker
|| m_state == torrent_status::seeding
|| m_picker->num_have() == m_picker->num_pieces());
} }
// this is true if we have all the pieces that we want // this is true if we have all the pieces that we want
@ -514,7 +518,7 @@ namespace libtorrent
{ {
if (is_seed()) return true; if (is_seed()) return true;
return valid_metadata() && m_torrent_file->num_pieces() return valid_metadata() && m_torrent_file->num_pieces()
- m_num_pieces - m_picker->num_filtered() == 0; - m_picker->num_have() - m_picker->num_filtered() == 0;
} }
fs::path save_path() const; fs::path save_path() const;
@ -740,9 +744,6 @@ namespace libtorrent
std::vector<announce_entry> m_trackers; std::vector<announce_entry> m_trackers;
// this is an index into m_trackers // this is an index into m_trackers
// the bitmask that says which pieces we have
bitfield m_have_pieces;
// the number of bytes that has been // the number of bytes that has been
// downloaded that failed the hash-test // downloaded that failed the hash-test
size_type m_total_failed_bytes; size_type m_total_failed_bytes;
@ -781,11 +782,6 @@ namespace libtorrent
float m_progress; float m_progress;
// the number of pieces we have. The same as
// std::accumulate(m_have_pieces.begin(),
// m_have_pieces.end(), 0)
int m_num_pieces;
// the upload/download ratio that each peer // the upload/download ratio that each peer
// tries to maintain. // tries to maintain.
// 0 is infinite // 0 is infinite
@ -908,9 +904,14 @@ namespace libtorrent
// has been initialized with files_checked(). // has been initialized with files_checked().
bool m_connections_initialized:1; bool m_connections_initialized:1;
#ifndef NDEBUG // is set to true every time there is an incoming
// connection to this torrent
bool m_has_incoming:1;
// this is set to true when the files are checked
// before the files are checked, we don't try to
// connect to peers
bool m_files_checked:1; bool m_files_checked:1;
#endif
}; };
inline ptime torrent::next_announce() const inline ptime torrent::next_announce() const

View File

@ -100,7 +100,6 @@ namespace libtorrent
, num_incomplete(-1) , num_incomplete(-1)
, list_seeds(0) , list_seeds(0)
, list_peers(0) , list_peers(0)
, pieces(0)
, num_pieces(0) , num_pieces(0)
, total_done(0) , total_done(0)
, total_wanted_done(0) , total_wanted_done(0)
@ -120,6 +119,7 @@ namespace libtorrent
, seeding_time(0) , seeding_time(0)
, seed_rank(0) , seed_rank(0)
, last_scrape(0) , last_scrape(0)
, has_incoming(false)
{} {}
enum state_t enum state_t
@ -200,7 +200,7 @@ namespace libtorrent
// we potentially could connect to // we potentially could connect to
int connect_candidates; int connect_candidates;
bitfield const* pieces; bitfield pieces;
// this is the number of pieces the client has // this is the number of pieces the client has
// downloaded. it is equal to: // downloaded. it is equal to:
@ -266,6 +266,10 @@ namespace libtorrent
// number of seconds since last scrape, or -1 if // number of seconds since last scrape, or -1 if
// there hasn't been a scrape // there hasn't been a scrape
int last_scrape; int last_scrape;
// true if there are incoming connections to this
// torrent
bool has_incoming;
}; };
struct TORRENT_EXPORT block_info struct TORRENT_EXPORT block_info
@ -341,6 +345,7 @@ namespace libtorrent
bool is_paused() const; bool is_paused() const;
void pause() const; void pause() const;
void resume() const; void resume() const;
void force_recheck() const;
void save_resume_data() const; void save_resume_data() const;
bool is_auto_managed() const; bool is_auto_managed() const;

View File

@ -173,6 +173,9 @@ namespace libtorrent
// response. used to know where in the buffer the // response. used to know where in the buffer the
// next response starts // next response starts
int m_received_body; int m_received_body;
// position in the current range response
int m_range_pos;
}; };
} }

View File

@ -245,7 +245,7 @@ namespace libtorrent
{ {
boost::shared_ptr<torrent> t = associated_torrent().lock(); boost::shared_ptr<torrent> t = associated_torrent().lock();
TORRENT_ASSERT(t); TORRENT_ASSERT(t);
write_bitfield(t->pieces()); write_bitfield();
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT
if (m_supports_dht_port && m_ses.m_dht) if (m_supports_dht_port && m_ses.m_dht)
write_dht_port(m_ses.get_dht_settings().service_port); write_dht_port(m_ses.get_dht_settings().service_port);
@ -1416,7 +1416,7 @@ namespace libtorrent
send_buffer(msg, sizeof(msg)); send_buffer(msg, sizeof(msg));
} }
void bt_peer_connection::write_bitfield(bitfield const& bits) void bt_peer_connection::write_bitfield()
{ {
INVARIANT_CHECK; INVARIANT_CHECK;
@ -1426,7 +1426,7 @@ namespace libtorrent
TORRENT_ASSERT(t->valid_metadata()); TORRENT_ASSERT(t->valid_metadata());
// in this case, have_all or have_none should be sent instead // in this case, have_all or have_none should be sent instead
TORRENT_ASSERT(!m_supports_fast || !t->is_seed() || t->num_pieces() != 0); TORRENT_ASSERT(!m_supports_fast || !t->is_seed() || t->num_have() != 0);
if (m_supports_fast && t->is_seed()) if (m_supports_fast && t->is_seed())
{ {
@ -1434,13 +1434,13 @@ namespace libtorrent
send_allowed_set(); send_allowed_set();
return; return;
} }
else if (m_supports_fast && t->num_pieces() == 0) else if (m_supports_fast && t->num_have() == 0)
{ {
write_have_none(); write_have_none();
send_allowed_set(); send_allowed_set();
return; return;
} }
else if (t->num_pieces() == 0) else if (t->num_have() == 0)
{ {
// don't send a bitfield if we don't have any pieces // don't send a bitfield if we don't have any pieces
#ifndef NDEBUG #ifndef NDEBUG
@ -1449,14 +1449,11 @@ namespace libtorrent
return; return;
} }
int num_pieces = bits.size(); int num_pieces = t->torrent_file().num_pieces();
int lazy_pieces[50]; int lazy_pieces[50];
int num_lazy_pieces = 0; int num_lazy_pieces = 0;
int lazy_piece = 0; int lazy_piece = 0;
TORRENT_ASSERT(t->is_seed() == (bits.count()
== num_pieces));
if (t->is_seed() && m_ses.settings().lazy_bitfields) if (t->is_seed() && m_ses.settings().lazy_bitfields)
{ {
num_lazy_pieces = (std::min)(50, num_pieces / 10); num_lazy_pieces = (std::min)(50, num_pieces / 10);
@ -1470,26 +1467,6 @@ namespace libtorrent
lazy_piece = 0; lazy_piece = 0;
} }
#ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << time_now_string() << " ==> BITFIELD ";
std::stringstream bitfield_string;
for (int i = 0; i < (int)get_bitfield().size(); ++i)
{
if (lazy_piece < num_lazy_pieces
&& lazy_pieces[lazy_piece] == i)
{
bitfield_string << "0";
++lazy_piece;
continue;
}
if (bits[i]) bitfield_string << "1";
else bitfield_string << "0";
}
bitfield_string << "\n";
(*m_logger) << bitfield_string.str();
lazy_piece = 0;
#endif
const int packet_size = (num_pieces + 7) / 8 + 5; const int packet_size = (num_pieces + 7) / 8 + 5;
buffer::interval i = allocate_send_buffer(packet_size); buffer::interval i = allocate_send_buffer(packet_size);
@ -1498,15 +1475,46 @@ namespace libtorrent
detail::write_int32(packet_size - 4, i.begin); detail::write_int32(packet_size - 4, i.begin);
detail::write_uint8(msg_bitfield, i.begin); detail::write_uint8(msg_bitfield, i.begin);
memcpy(i.begin, bits.bytes(), packet_size - 5); if (t->is_seed())
{
memset(i.begin, 0xff, packet_size - 5);
}
else
{
memset(i.begin, 0, packet_size - 5);
piece_picker const& p = t->picker();
int mask = 0x80;
unsigned char* byte = (unsigned char*)i.begin;
for (int i = 0; i < num_pieces; ++i)
{
if (p.have_piece(i)) *byte |= mask;
mask >>= 1;
if (mask == 0)
{
mask = 0x80;
++byte;
}
}
}
for (int c = 0; c < num_lazy_pieces; ++c) for (int c = 0; c < num_lazy_pieces; ++c)
i.begin[lazy_pieces[c] / 8] &= ~(0x80 >> (lazy_pieces[c] & 7)); i.begin[lazy_pieces[c] / 8] &= ~(0x80 >> (lazy_pieces[c] & 7));
TORRENT_ASSERT(i.end - i.begin == (num_pieces + 7) / 8); TORRENT_ASSERT(i.end - i.begin == (num_pieces + 7) / 8);
#ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << time_now_string() << " ==> BITFIELD ";
std::stringstream bitfield_string;
for (int k = 0; k < num_pieces; ++k)
{
if (i.begin[k / 8] & (0x80 >> (k % 8))) bitfield_string << "1";
else bitfield_string << "0";
}
bitfield_string << "\n";
(*m_logger) << bitfield_string.str();
#endif
#ifndef NDEBUG #ifndef NDEBUG
m_sent_bitfield = true; m_sent_bitfield = true;
#endif #endif
setup_send();
if (num_lazy_pieces > 0) if (num_lazy_pieces > 0)
{ {
@ -1522,6 +1530,7 @@ namespace libtorrent
if (m_supports_fast) if (m_supports_fast)
send_allowed_set(); send_allowed_set();
setup_send();
} }
#ifndef TORRENT_DISABLE_EXTENSIONS #ifndef TORRENT_DISABLE_EXTENSIONS
@ -2377,7 +2386,7 @@ namespace libtorrent
// sent the handshake // sent the handshake
if (!is_local()) write_handshake(); if (!is_local()) write_handshake();
// if (t->valid_metadata()) // if (t->valid_metadata())
// write_bitfield(t->pieces()); // write_bitfield();
if (is_disconnecting()) return; if (is_disconnecting()) return;
@ -2511,7 +2520,7 @@ namespace libtorrent
reset_recv_buffer(5); reset_recv_buffer(5);
if (t->valid_metadata()) if (t->valid_metadata())
{ {
write_bitfield(t->pieces()); write_bitfield();
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT
if (m_supports_dht_port && m_ses.m_dht) if (m_supports_dht_port && m_ses.m_dht)
write_dht_port(m_ses.get_dht_settings().service_port); write_dht_port(m_ses.get_dht_settings().service_port);

View File

@ -301,8 +301,11 @@ void http_connection::connect(int ticket, tcp::endpoint target_address)
void http_connection::on_connect(error_code const& e) void http_connection::on_connect(error_code const& e)
{ {
TORRENT_ASSERT(m_connection_ticket >= 0); if (m_connection_ticket >= 0)
m_cc.done(m_connection_ticket); {
m_cc.done(m_connection_ticket);
m_connection_ticket = -1;
}
m_last_receive = time_now(); m_last_receive = time_now();
if (!e) if (!e)

View File

@ -63,9 +63,10 @@ namespace libtorrent
{ {
TORRENT_ASSERT(recv_buffer.left() >= m_recv_buffer.left()); TORRENT_ASSERT(recv_buffer.left() >= m_recv_buffer.left());
boost::tuple<int, int> ret(0, 0); boost::tuple<int, int> ret(0, 0);
int start_pos = m_recv_buffer.left();
// early exit if there's nothing new in the receive buffer // early exit if there's nothing new in the receive buffer
if (recv_buffer.left() == m_recv_buffer.left()) return ret; if (start_pos == recv_buffer.left()) return ret;
m_recv_buffer = recv_buffer; m_recv_buffer = recv_buffer;
if (m_state == error_state) if (m_state == error_state)
@ -80,7 +81,11 @@ namespace libtorrent
TORRENT_ASSERT(!m_finished); TORRENT_ASSERT(!m_finished);
char const* newline = std::find(pos, recv_buffer.end, '\n'); char const* newline = std::find(pos, recv_buffer.end, '\n');
// if we don't have a full line yet, wait. // if we don't have a full line yet, wait.
if (newline == recv_buffer.end) return ret; if (newline == recv_buffer.end)
{
boost::get<1>(ret) += m_recv_buffer.left() - start_pos;
return ret;
}
if (newline == pos) if (newline == pos)
{ {
@ -96,7 +101,7 @@ namespace libtorrent
++newline; ++newline;
int incoming = (int)std::distance(pos, newline); int incoming = (int)std::distance(pos, newline);
m_recv_pos += incoming; m_recv_pos += incoming;
boost::get<1>(ret) += incoming; boost::get<1>(ret) += newline - (m_recv_buffer.begin + start_pos);
pos = newline; pos = newline;
line >> m_protocol; line >> m_protocol;
@ -114,6 +119,7 @@ namespace libtorrent
m_status_code = 0; m_status_code = 0;
} }
m_state = read_header; m_state = read_header;
start_pos = pos - recv_buffer.begin;
} }
if (m_state == read_header) if (m_state == read_header)
@ -131,7 +137,6 @@ namespace libtorrent
line.assign(pos, line_end); line.assign(pos, line_end);
++newline; ++newline;
m_recv_pos += newline - pos; m_recv_pos += newline - pos;
boost::get<1>(ret) += newline - pos;
pos = newline; pos = newline;
std::string::size_type separator = line.find(':'); std::string::size_type separator = line.find(':');
@ -187,6 +192,7 @@ namespace libtorrent
TORRENT_ASSERT(m_recv_pos <= (int)recv_buffer.left()); TORRENT_ASSERT(m_recv_pos <= (int)recv_buffer.left());
newline = std::find(pos, recv_buffer.end, '\n'); newline = std::find(pos, recv_buffer.end, '\n');
} }
boost::get<1>(ret) += newline - (m_recv_buffer.begin + start_pos);
} }
if (m_state == read_body) if (m_state == read_body)

View File

@ -225,7 +225,14 @@ namespace libtorrent
} }
// handle tracker response // handle tracker response
entry e = bdecode(data, data + size); 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) if (e.type() != entry::undefined_t)
{ {

View File

@ -326,15 +326,19 @@ namespace libtorrent
TORRENT_ASSERT(t); TORRENT_ASSERT(t);
bool interested = false; bool interested = false;
bitfield const& we_have = t->pieces(); if (!t->is_finished())
for (int j = 0; j != (int)we_have.size(); ++j)
{ {
if (!we_have[j] piece_picker const& p = t->picker();
&& t->piece_priority(j) > 0 int num_pieces = p.num_pieces();
&& m_have_piece[j]) for (int j = 0; j != num_pieces; ++j)
{ {
interested = true; if (!p.have_piece(j)
break; && t->piece_priority(j) > 0
&& m_have_piece[j])
{
interested = true;
break;
}
} }
} }
try try
@ -2218,6 +2222,10 @@ namespace libtorrent
if (t) if (t)
{ {
// make sure we keep all the stats!
calc_ip_overhead();
t->add_stats(statistics());
if (t->has_picker()) if (t->has_picker())
{ {
piece_picker& picker = t->picker(); piece_picker& picker = t->picker();

View File

@ -58,10 +58,9 @@ POSSIBILITY OF SUCH DAMAGE.
namespace libtorrent namespace libtorrent
{ {
piece_picker::piece_picker(int blocks_per_piece, int total_num_blocks) piece_picker::piece_picker()
: m_seeds(0) : m_seeds(0)
, m_priority_boundries(1, int(m_pieces.size())) , m_priority_boundries(1, int(m_pieces.size()))
, m_piece_map((total_num_blocks + blocks_per_piece-1) / blocks_per_piece)
, m_num_filtered(0) , m_num_filtered(0)
, m_num_have_filtered(0) , m_num_have_filtered(0)
, m_num_have(0) , m_num_have(0)
@ -69,13 +68,22 @@ namespace libtorrent
, m_dirty(false) , m_dirty(false)
{ {
#ifdef TORRENT_PICKER_LOG #ifdef TORRENT_PICKER_LOG
std::cout << "new piece_picker" << std::endl; std::cerr << "new piece_picker" << std::endl;
#endif #endif
#ifndef NDEBUG
check_invariant();
#endif
}
void piece_picker::init(int blocks_per_piece, int total_num_blocks)
{
TORRENT_ASSERT(blocks_per_piece > 0); TORRENT_ASSERT(blocks_per_piece > 0);
TORRENT_ASSERT(total_num_blocks >= 0); TORRENT_ASSERT(total_num_blocks >= 0);
#ifndef NDEBUG
m_files_checked_called = false; // allocate the piece_map to cover all pieces
#endif // and make them invalid (as if we don't have a single piece)
m_piece_map.resize((total_num_blocks + blocks_per_piece-1) / blocks_per_piece
, piece_pos(0, 0));
// the piece index is stored in 20 bits, which limits the allowed // the piece index is stored in 20 bits, which limits the allowed
// number of pieces somewhat // number of pieces somewhat
@ -87,15 +95,6 @@ namespace libtorrent
if (m_blocks_in_last_piece == 0) m_blocks_in_last_piece = blocks_per_piece; if (m_blocks_in_last_piece == 0) m_blocks_in_last_piece = blocks_per_piece;
TORRENT_ASSERT(m_blocks_in_last_piece <= m_blocks_per_piece); TORRENT_ASSERT(m_blocks_in_last_piece <= m_blocks_per_piece);
// allocate the piece_map to cover all pieces
// and make them invalid (as if we don't have a single piece)
std::fill(m_piece_map.begin(), m_piece_map.end()
, piece_pos(0, 0));
m_num_have = 0;
#ifndef NDEBUG
check_invariant();
#endif
} }
void piece_picker::sequential_download(bool sd) void piece_picker::sequential_download(bool sd)
@ -122,24 +121,6 @@ namespace libtorrent
} }
} }
// pieces is a bitmask with the pieces we have
void piece_picker::init(bitfield const& pieces)
{
TORRENT_PIECE_PICKER_INVARIANT_CHECK;
#ifndef NDEBUG
m_files_checked_called = true;
#endif
int index = 0;
for (bitfield::const_iterator i = pieces.begin();
i != pieces.end(); ++i, ++index)
{
TORRENT_ASSERT(index < pieces.size());
piece_pos& p = m_piece_map[index];
if (*i) we_have(index);
else TORRENT_ASSERT(p.index == 0);
}
}
void piece_picker::piece_info(int index, piece_picker::downloading_piece& st) const void piece_picker::piece_info(int index, piece_picker::downloading_piece& st) const
{ {
TORRENT_PIECE_PICKER_INVARIANT_CHECK; TORRENT_PIECE_PICKER_INVARIANT_CHECK;
@ -249,7 +230,7 @@ namespace libtorrent
for (std::vector<int>::const_iterator i = m_priority_boundries.begin() for (std::vector<int>::const_iterator i = m_priority_boundries.begin()
, end(m_priority_boundries.end()); i != end; ++i) , end(m_priority_boundries.end()); i != end; ++i)
{ {
std::cout << *i << " "; std::cerr << *i << " ";
} }
std::cout << std::endl; std::cout << std::endl;
int index = 0; int index = 0;
@ -260,12 +241,12 @@ namespace libtorrent
if (*i == -1) break; if (*i == -1) break;
while (j != m_priority_boundries.end() && *j <= index) while (j != m_priority_boundries.end() && *j <= index)
{ {
std::cout << "| "; std::cerr << "| ";
++j; ++j;
} }
std::cout << *i << "(" << m_piece_map[*i].index << ") "; std::cerr << *i << "(" << m_piece_map[*i].index << ") ";
} }
std::cout << std::endl; std::cerr << std::endl;
} }
void piece_picker::check_invariant(const torrent* t) const void piece_picker::check_invariant(const torrent* t) const
@ -534,7 +515,7 @@ namespace libtorrent
else new_index = rand() % (range_end - range_start) + range_start; else new_index = rand() % (range_end - range_start) + range_start;
#ifdef TORRENT_PICKER_LOG #ifdef TORRENT_PICKER_LOG
std::cout << "add " << index << " (" << priority << ")" << std::endl; std::cerr << "add " << index << " (" << priority << ")" << std::endl;
print_pieces(); print_pieces();
#endif #endif
m_pieces.push_back(-1); m_pieces.push_back(-1);
@ -554,7 +535,7 @@ namespace libtorrent
new_index = temp; new_index = temp;
#ifdef TORRENT_PICKER_LOG #ifdef TORRENT_PICKER_LOG
print_pieces(); print_pieces();
std::cout << " index: " << index std::cerr << " index: " << index
<< " prio: " << priority << " prio: " << priority
<< " new_index: " << new_index << " new_index: " << new_index
<< std::endl; << std::endl;
@ -581,7 +562,7 @@ namespace libtorrent
TORRENT_ASSERT(m_sequential_download == -1); TORRENT_ASSERT(m_sequential_download == -1);
#ifdef TORRENT_PICKER_LOG #ifdef TORRENT_PICKER_LOG
std::cout << "remove " << m_pieces[elem_index] << " (" << priority << ")" << std::endl; std::cerr << "remove " << m_pieces[elem_index] << " (" << priority << ")" << std::endl;
#endif #endif
int next_index = elem_index; int next_index = elem_index;
TORRENT_ASSERT(m_piece_map[m_pieces[elem_index]].priority(this) == -1); TORRENT_ASSERT(m_piece_map[m_pieces[elem_index]].priority(this) == -1);
@ -624,7 +605,6 @@ namespace libtorrent
TORRENT_ASSERT(!m_dirty); TORRENT_ASSERT(!m_dirty);
TORRENT_ASSERT(priority >= 0); TORRENT_ASSERT(priority >= 0);
TORRENT_ASSERT(elem_index >= 0); TORRENT_ASSERT(elem_index >= 0);
TORRENT_ASSERT(m_files_checked_called);
TORRENT_ASSERT(m_sequential_download == -1); TORRENT_ASSERT(m_sequential_download == -1);
TORRENT_ASSERT(int(m_priority_boundries.size()) > priority); TORRENT_ASSERT(int(m_priority_boundries.size()) > priority);
@ -648,7 +628,7 @@ namespace libtorrent
m_priority_boundries.resize(new_priority + 1, m_pieces.size()); m_priority_boundries.resize(new_priority + 1, m_pieces.size());
#ifdef TORRENT_PICKER_LOG #ifdef TORRENT_PICKER_LOG
std::cout << "update " << index << " (" << priority << "->" << new_priority << ")" << std::endl; std::cerr << "update " << index << " (" << priority << "->" << new_priority << ")" << std::endl;
#endif #endif
if (priority > new_priority) if (priority > new_priority)
{ {
@ -772,7 +752,6 @@ namespace libtorrent
TORRENT_ASSERT(index >= 0); TORRENT_ASSERT(index >= 0);
TORRENT_ASSERT(index < (int)m_piece_map.size()); TORRENT_ASSERT(index < (int)m_piece_map.size());
TORRENT_ASSERT(m_files_checked_called);
TORRENT_ASSERT(m_piece_map[index].downloading == 1); TORRENT_ASSERT(m_piece_map[index].downloading == 1);
@ -804,7 +783,6 @@ namespace libtorrent
void piece_picker::inc_refcount_all() void piece_picker::inc_refcount_all()
{ {
TORRENT_PIECE_PICKER_INVARIANT_CHECK; TORRENT_PIECE_PICKER_INVARIANT_CHECK;
TORRENT_ASSERT(m_files_checked_called);
++m_seeds; ++m_seeds;
if (m_sequential_download >= 0) return; if (m_sequential_download >= 0) return;
if (m_seeds == 1) if (m_seeds == 1)
@ -819,7 +797,6 @@ namespace libtorrent
void piece_picker::dec_refcount_all() void piece_picker::dec_refcount_all()
{ {
TORRENT_PIECE_PICKER_INVARIANT_CHECK; TORRENT_PIECE_PICKER_INVARIANT_CHECK;
TORRENT_ASSERT(m_files_checked_called);
if (m_sequential_download >= 0) if (m_sequential_download >= 0)
{ {
@ -935,7 +912,7 @@ namespace libtorrent
TORRENT_ASSERT(m_sequential_download == -1); TORRENT_ASSERT(m_sequential_download == -1);
if (m_priority_boundries.empty()) m_priority_boundries.resize(1, 0); if (m_priority_boundries.empty()) m_priority_boundries.resize(1, 0);
#ifdef TORRENT_PICKER_LOG #ifdef TORRENT_PICKER_LOG
std::cout << "update_pieces" << std::endl; std::cerr << "update_pieces" << std::endl;
#endif #endif
std::fill(m_priority_boundries.begin(), m_priority_boundries.end(), 0); std::fill(m_priority_boundries.begin(), m_priority_boundries.end(), 0);
for (std::vector<piece_pos>::iterator i = m_piece_map.begin() for (std::vector<piece_pos>::iterator i = m_piece_map.begin()
@ -1004,6 +981,33 @@ namespace libtorrent
#endif #endif
} }
void piece_picker::we_dont_have(int index)
{
TORRENT_PIECE_PICKER_INVARIANT_CHECK;
TORRENT_ASSERT(index >= 0);
TORRENT_ASSERT(index < (int)m_piece_map.size());
piece_pos& p = m_piece_map[index];
TORRENT_ASSERT(p.downloading == 0);
if (!p.have()) return;
if (m_sequential_download > index)
m_sequential_download = index;
if (p.filtered())
{
++m_num_filtered;
--m_num_have_filtered;
}
--m_num_have;
p.set_not_have();
if (m_dirty) return;
if (!p.filtered()) add(index);
}
// this is used to indicate that we succesfully have // this is used to indicate that we succesfully have
// downloaded a piece, and that no further attempts // downloaded a piece, and that no further attempts
// to pick that piece should be made. The piece will // to pick that piece should be made. The piece will
@ -1167,7 +1171,6 @@ namespace libtorrent
TORRENT_PIECE_PICKER_INVARIANT_CHECK; TORRENT_PIECE_PICKER_INVARIANT_CHECK;
TORRENT_ASSERT(num_blocks > 0); TORRENT_ASSERT(num_blocks > 0);
TORRENT_ASSERT(pieces.size() == m_piece_map.size()); TORRENT_ASSERT(pieces.size() == m_piece_map.size());
TORRENT_ASSERT(m_files_checked_called);
TORRENT_ASSERT(!m_priority_boundries.empty() TORRENT_ASSERT(!m_priority_boundries.empty()
|| m_sequential_download >= 0 || m_sequential_download >= 0

View File

@ -200,7 +200,7 @@ namespace libtorrent
int prefer_whole_pieces = c.prefer_whole_pieces(); int prefer_whole_pieces = c.prefer_whole_pieces();
bool rarest_first = t.num_pieces() >= t.settings().initial_picker_threshold; bool rarest_first = t.num_have() >= t.settings().initial_picker_threshold;
if (prefer_whole_pieces == 0) if (prefer_whole_pieces == 0)
{ {
@ -644,7 +644,7 @@ namespace libtorrent
error_code ec; error_code ec;
TORRENT_ASSERT(c.remote() == c.get_socket()->remote_endpoint(ec) || ec); TORRENT_ASSERT(c.remote() == c.get_socket()->remote_endpoint(ec) || ec);
if (m_peers.size() >= m_torrent->settings().max_peerlist_size) if (int(m_peers.size()) >= m_torrent->settings().max_peerlist_size)
{ {
c.disconnect("peer list size exceeded, refusing incoming connection"); c.disconnect("peer list size exceeded, refusing incoming connection");
return false; return false;
@ -773,7 +773,7 @@ namespace libtorrent
return 0; return 0;
} }
if (m_peers.size() >= m_torrent->settings().max_peerlist_size) if (int(m_peers.size()) >= m_torrent->settings().max_peerlist_size)
return 0; return 0;
// we don't have any info about this peer. // we don't have any info about this peer.
@ -1018,11 +1018,14 @@ namespace libtorrent
TORRENT_ASSERT(!p->second.connection); TORRENT_ASSERT(!p->second.connection);
TORRENT_ASSERT(p->second.type == peer::connectable); TORRENT_ASSERT(p->second.type == peer::connectable);
TORRENT_ASSERT(is_connect_candidate(p->second, m_torrent->is_finished()));
if (!m_torrent->connect_to_peer(&p->second)) if (!m_torrent->connect_to_peer(&p->second))
{ {
++p->second.failcount; ++p->second.failcount;
return false; return false;
} }
TORRENT_ASSERT(!is_connect_candidate(p->second, m_torrent->is_finished()));
--m_num_connect_candidates;
return true; return true;
} }

View File

@ -95,9 +95,12 @@ POSSIBILITY OF SUCH DAMAGE.
#include <sys/mount.h> #include <sys/mount.h>
#endif #endif
#if defined(_WIN32) && defined(UNICODE) #if TORRENT_USE_WPATH
#ifdef BOOST_WINDOWS
#include <windows.h> #include <windows.h>
#endif
#include <boost/filesystem/exception.hpp> #include <boost/filesystem/exception.hpp>
#include "libtorrent/utf8.hpp" #include "libtorrent/utf8.hpp"
#include "libtorrent/buffer.hpp" #include "libtorrent/buffer.hpp"
@ -249,7 +252,53 @@ namespace
namespace libtorrent namespace libtorrent
{ {
template <class Path>
void recursive_copy(Path const& old_path, Path const& new_path, std::string& error)
{
using boost::filesystem::directory_iterator;
#ifndef BOOST_NO_EXCEPTIONS
try {
#endif
TORRENT_ASSERT(error.empty());
if (is_directory(old_path))
{
create_directory(new_path);
for (directory_iterator i(old_path), end; i != end; ++i)
{
recursive_copy(i->path(), new_path / i->leaf(), error);
if (!error.empty()) return;
}
}
else
{
copy_file(old_path, new_path);
}
#ifndef BOOST_NO_EXCEPTIONS
} catch (std::exception& e) { error = e.what(); }
#endif
}
template <class Path>
void recursive_remove(Path const& old_path)
{
using boost::filesystem::directory_iterator;
#ifndef BOOST_NO_EXCEPTIONS
try {
#endif
if (is_directory(old_path))
{
for (directory_iterator i(old_path), end; i != end; ++i)
recursive_remove(i->path());
remove(old_path);
}
else
{
remove(old_path);
}
#ifndef BOOST_NO_EXCEPTIONS
} catch (std::exception& e) {}
#endif
}
std::vector<std::pair<size_type, std::time_t> > get_filesizes( std::vector<std::pair<size_type, std::time_t> > get_filesizes(
file_storage const& s, fs::path p) file_storage const& s, fs::path p)
{ {
@ -260,7 +309,7 @@ namespace libtorrent
{ {
size_type size = 0; size_type size = 0;
std::time_t time = 0; std::time_t time = 0;
#if defined(_WIN32) && defined(UNICODE) #if TORRENT_USE_WPATH
fs::wpath f = safe_convert((p / i->path).string()); fs::wpath f = safe_convert((p / i->path).string());
#else #else
fs::path f = p / i->path; fs::path f = p / i->path;
@ -310,7 +359,7 @@ namespace libtorrent
size_type size = 0; size_type size = 0;
std::time_t time = 0; std::time_t time = 0;
#if defined(_WIN32) && defined(UNICODE) #if TORRENT_USE_WPATH
fs::wpath f = safe_convert((p / i->path).string()); fs::wpath f = safe_convert((p / i->path).string());
#else #else
fs::path f = p / i->path; fs::path f = p / i->path;
@ -443,7 +492,7 @@ namespace libtorrent
last_path = dir; last_path = dir;
if (!exists_win(last_path)) if (!exists_win(last_path))
create_directories_win(last_path); create_directories_win(last_path);
#elif defined(_WIN32) && defined(UNICODE) #elif TORRENT_USE_WPATH
last_path = dir; last_path = dir;
fs::wpath wp = safe_convert(last_path.string()); fs::wpath wp = safe_convert(last_path.string());
if (!exists(wp)) if (!exists(wp))
@ -506,9 +555,9 @@ namespace libtorrent
fs::path old_name = m_save_path / files().at(index).path; fs::path old_name = m_save_path / files().at(index).path;
m_pool.release(old_name); m_pool.release(old_name);
#if defined(_WIN32) && defined(UNICODE) && BOOST_VERSION >= 103400 #if TORRENT_USE_WPATH
fs::wpath old_path = safe_convert(old_name); fs::wpath old_path = safe_convert(old_name.string());
fs::wpath new_path = safe_convert(m_save_path / new_filename); fs::wpath new_path = safe_convert((m_save_path / new_filename).string());
#else #else
fs::path const& old_path = old_name; fs::path const& old_path = old_name;
fs::path new_path = m_save_path / new_filename; fs::path new_path = m_save_path / new_filename;
@ -565,7 +614,7 @@ namespace libtorrent
std::pair<iter_t, bool> ret = directories.insert((m_save_path / bp).string()); std::pair<iter_t, bool> ret = directories.insert((m_save_path / bp).string());
bp = bp.branch_path(); bp = bp.branch_path();
} }
#if defined(_WIN32) && defined(UNICODE) #if TORRENT_USE_WPATH
try try
{ fs::remove(safe_convert(p)); } { fs::remove(safe_convert(p)); }
catch (std::exception& e) catch (std::exception& e)
@ -590,7 +639,7 @@ namespace libtorrent
for (std::set<std::string>::reverse_iterator i = directories.rbegin() for (std::set<std::string>::reverse_iterator i = directories.rbegin()
, end(directories.rend()); i != end; ++i) , end(directories.rend()); i != end; ++i)
{ {
#if defined(_WIN32) && defined(UNICODE) #if TORRENT_USE_WPATH
try try
{ fs::remove(safe_convert(*i)); } { fs::remove(safe_convert(*i)); }
catch (std::exception& e) catch (std::exception& e)
@ -725,7 +774,7 @@ namespace libtorrent
// returns true on success // returns true on success
bool storage::move_storage(fs::path save_path) bool storage::move_storage(fs::path save_path)
{ {
#if defined(_WIN32) && defined(UNICODE) && BOOST_VERSION >= 103400 #if TORRENT_USE_WPATH
fs::wpath old_path; fs::wpath old_path;
fs::wpath new_path; fs::wpath new_path;
#else #else
@ -741,7 +790,7 @@ namespace libtorrent
CreateDirectory(wsave_path.c_str(), 0); CreateDirectory(wsave_path.c_str(), 0);
else if ((GetFileAttributes(wsave_path.c_str()) & FILE_ATTRIBUTE_DIRECTORY) == 0) else if ((GetFileAttributes(wsave_path.c_str()) & FILE_ATTRIBUTE_DIRECTORY) == 0)
return false; return false;
#elif defined(_WIN32) && defined(UNICODE) #elif TORRENT_USE_WPATH
fs::wpath wp = safe_convert(save_path.string()); fs::wpath wp = safe_convert(save_path.string());
if (!exists(wp)) if (!exists(wp))
create_directory(wp); create_directory(wp);
@ -756,7 +805,7 @@ namespace libtorrent
m_pool.release(this); m_pool.release(this);
#if defined(_WIN32) && defined(UNICODE) && BOOST_VERSION >= 103400 #if TORRENT_USE_WPATH
old_path = safe_convert((m_save_path / files().name()).string()); old_path = safe_convert((m_save_path / files().name()).string());
new_path = safe_convert((save_path / files().name()).string()); new_path = safe_convert((save_path / files().name()).string());
#else #else
@ -770,7 +819,6 @@ namespace libtorrent
#endif #endif
#if defined(_WIN32) && defined(UNICODE) && BOOST_VERSION < 103400 #if defined(_WIN32) && defined(UNICODE) && BOOST_VERSION < 103400
rename_win(old_path, new_path); rename_win(old_path, new_path);
rename(old_path, new_path);
#else #else
rename(old_path, new_path); rename(old_path, new_path);
#endif #endif
@ -780,8 +828,15 @@ namespace libtorrent
} }
catch (std::exception& e) catch (std::exception& e)
{ {
set_error((m_save_path / files().name()).string(), e.what()); std::string err;
return true; recursive_copy(old_path, new_path, err);
if (!err.empty())
{
set_error((m_save_path / files().name()).string(), e.what());
return true;
}
m_save_path = save_path;
recursive_remove(old_path);
} }
#endif #endif
return false; return false;
@ -1648,7 +1703,7 @@ namespace libtorrent
#endif #endif
#if defined(_WIN32) && defined(UNICODE) && BOOST_VERSION < 103400 #if defined(_WIN32) && defined(UNICODE) && BOOST_VERSION < 103400
file_exists = exists_win(f); file_exists = exists_win(f);
#elif defined(_WIN32) && defined(UNICODE) #elif TORRENT_USE_WPATH
fs::wpath wf = safe_convert(f.string()); fs::wpath wf = safe_convert(f.string());
file_exists = exists(wf); file_exists = exists(wf);
#else #else

View File

@ -164,7 +164,7 @@ namespace libtorrent
, m_last_dht_announce(time_now() - minutes(15)) , m_last_dht_announce(time_now() - minutes(15))
#endif #endif
, m_ses(ses) , m_ses(ses)
, m_picker(0) , m_picker(new piece_picker())
, m_trackers(m_torrent_file->trackers()) , m_trackers(m_torrent_file->trackers())
, m_total_failed_bytes(0) , m_total_failed_bytes(0)
, m_total_redundant_bytes(0) , m_total_redundant_bytes(0)
@ -175,7 +175,6 @@ namespace libtorrent
, m_settings(ses.settings()) , m_settings(ses.settings())
, m_storage_constructor(sc) , m_storage_constructor(sc)
, m_progress(0.f) , m_progress(0.f)
, m_num_pieces(0)
, m_ratio(0.f) , m_ratio(0.f)
, m_max_uploads((std::numeric_limits<int>::max)()) , m_max_uploads((std::numeric_limits<int>::max)())
, m_num_uploads(0) , m_num_uploads(0)
@ -201,11 +200,10 @@ namespace libtorrent
, m_sequential_download(false) , m_sequential_download(false)
, m_got_tracker_response(false) , m_got_tracker_response(false)
, m_connections_initialized(true) , m_connections_initialized(true)
, m_has_incoming(false)
, m_files_checked(false)
{ {
if (resume_data) m_resume_data = *resume_data; if (resume_data) m_resume_data = *resume_data;
#ifndef NDEBUG
m_files_checked = false;
#endif
} }
torrent::torrent( torrent::torrent(
@ -239,7 +237,7 @@ namespace libtorrent
, m_last_dht_announce(time_now() - minutes(15)) , m_last_dht_announce(time_now() - minutes(15))
#endif #endif
, m_ses(ses) , m_ses(ses)
, m_picker(0) , m_picker(new piece_picker())
, m_total_failed_bytes(0) , m_total_failed_bytes(0)
, m_total_redundant_bytes(0) , m_total_redundant_bytes(0)
, m_net_interface(net_interface.address(), 0) , m_net_interface(net_interface.address(), 0)
@ -249,7 +247,6 @@ namespace libtorrent
, m_settings(ses.settings()) , m_settings(ses.settings())
, m_storage_constructor(sc) , m_storage_constructor(sc)
, m_progress(0.f) , m_progress(0.f)
, m_num_pieces(0)
, m_ratio(0.f) , m_ratio(0.f)
, m_max_uploads((std::numeric_limits<int>::max)()) , m_max_uploads((std::numeric_limits<int>::max)())
, m_num_uploads(0) , m_num_uploads(0)
@ -275,6 +272,7 @@ namespace libtorrent
, m_sequential_download(false) , m_sequential_download(false)
, m_got_tracker_response(false) , m_got_tracker_response(false)
, m_connections_initialized(false) , m_connections_initialized(false)
, m_has_incoming(false)
{ {
if (resume_data) m_resume_data = *resume_data; if (resume_data) m_resume_data = *resume_data;
#ifndef NDEBUG #ifndef NDEBUG
@ -308,10 +306,10 @@ namespace libtorrent
if (m_ses.m_listen_sockets.empty()) return false; if (m_ses.m_listen_sockets.empty()) return false;
if (!m_ses.m_dht) return false; if (!m_ses.m_dht) return false;
if (!m_files_checked) return false;
// don't announce private torrents // don't announce private torrents
if (m_torrent_file->is_valid() && m_torrent_file->priv()) return false; if (m_torrent_file->is_valid() && m_torrent_file->priv()) return false;
if (m_trackers.empty()) return true; if (m_trackers.empty()) return true;
return m_failed_trackers > 0 || !m_ses.settings().use_dht_as_fallback; return m_failed_trackers > 0 || !m_ses.settings().use_dht_as_fallback;
@ -407,16 +405,14 @@ namespace libtorrent
TORRENT_ASSERT(m_torrent_file->num_files() > 0); TORRENT_ASSERT(m_torrent_file->num_files() > 0);
TORRENT_ASSERT(m_torrent_file->total_size() >= 0); TORRENT_ASSERT(m_torrent_file->total_size() >= 0);
m_have_pieces.resize(m_torrent_file->num_pieces(), false);
// the shared_from_this() will create an intentional // the shared_from_this() will create an intentional
// cycle of ownership, se the hpp file for description. // cycle of ownership, se the hpp file for description.
m_owning_storage = new piece_manager(shared_from_this(), m_torrent_file m_owning_storage = new piece_manager(shared_from_this(), m_torrent_file
, m_save_path, m_ses.m_files, m_ses.m_disk_thread, m_storage_constructor , m_save_path, m_ses.m_files, m_ses.m_disk_thread, m_storage_constructor
, m_storage_mode); , m_storage_mode);
m_storage = m_owning_storage.get(); m_storage = m_owning_storage.get();
m_picker.reset(new piece_picker( m_picker->init(m_torrent_file->piece_length() / m_block_size
m_torrent_file->piece_length() / m_block_size , int((m_torrent_file->total_size()+m_block_size-1)/m_block_size));
, int((m_torrent_file->total_size()+m_block_size-1)/m_block_size)));
std::vector<std::string> const& url_seeds = m_torrent_file->url_seeds(); std::vector<std::string> const& url_seeds = m_torrent_file->url_seeds();
std::copy(url_seeds.begin(), url_seeds.end(), std::inserter(m_web_seeds std::copy(url_seeds.begin(), url_seeds.end(), std::inserter(m_web_seeds
@ -473,8 +469,6 @@ namespace libtorrent
" ]\n"; " ]\n";
#endif #endif
} }
m_have_pieces.clear_all();
m_num_pieces = 0;
m_error = j.str; m_error = j.str;
pause(); pause();
return; return;
@ -548,8 +542,6 @@ namespace libtorrent
// there are either no files for this torrent // there are either no files for this torrent
// or the resume_data was accepted // or the resume_data was accepted
m_num_pieces = 0;
m_have_pieces.clear_all();
if (!fastresume_rejected) if (!fastresume_rejected)
{ {
TORRENT_ASSERT(m_resume_data.type() == entry::dictionary_t); TORRENT_ASSERT(m_resume_data.type() == entry::dictionary_t);
@ -563,8 +555,7 @@ namespace libtorrent
for (int i = 0, end(pieces_str.size()); i < end; ++i) for (int i = 0, end(pieces_str.size()); i < end; ++i)
{ {
if ((pieces_str[i] & 1) == 0) continue; if ((pieces_str[i] & 1) == 0) continue;
m_have_pieces.set_bit(i); m_picker->we_have(i);
++m_num_pieces;
} }
} }
@ -587,11 +578,8 @@ namespace libtorrent
if (piece_index < 0 || piece_index >= torrent_file().num_pieces()) if (piece_index < 0 || piece_index >= torrent_file().num_pieces())
continue; continue;
if (m_have_pieces[piece_index]) if (m_picker->have_piece(piece_index))
{ m_picker->we_dont_have(piece_index);
m_have_pieces.clear_bit(piece_index);
--m_num_pieces;
}
entry const* bitmask_ent = i->find_key("bitmask"); entry const* bitmask_ent = i->find_key("bitmask");
if (bitmask_ent == 0 || bitmask_ent->type() != entry::string_t) break; if (bitmask_ent == 0 || bitmask_ent->type() != entry::string_t) break;
@ -617,13 +605,6 @@ namespace libtorrent
} }
} }
} }
int index = 0;
for (bitfield::const_iterator i = m_have_pieces.begin()
, end(m_have_pieces.end()); i != end; ++i, ++index)
{
if (*i) m_picker->we_have(index);
}
} }
files_checked(); files_checked();
@ -636,6 +617,51 @@ namespace libtorrent
} }
} }
void torrent::force_recheck()
{
disconnect_all();
m_owning_storage->async_release_files();
m_owning_storage = new piece_manager(shared_from_this(), m_torrent_file
, m_save_path, m_ses.m_files, m_ses.m_disk_thread, m_storage_constructor
, m_storage_mode);
m_storage = m_owning_storage.get();
m_picker.reset(new piece_picker);
m_picker->init(m_torrent_file->piece_length() / m_block_size
, int((m_torrent_file->total_size()+m_block_size-1)/m_block_size));
// assume that we don't have anything
m_files_checked = false;
m_state = torrent_status::queued_for_checking;
m_resume_data = entry();
m_storage->async_check_fastresume(&m_resume_data
, bind(&torrent::on_force_recheck
, shared_from_this(), _1, _2));
}
void torrent::on_force_recheck(int ret, disk_io_job const& j)
{
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
if (ret == piece_manager::fatal_disk_error)
{
if (m_ses.m_alerts.should_post(alert::fatal))
{
m_ses.m_alerts.post_alert(file_error_alert(j.error_file, get_handle(), j.str));
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
(*m_ses.m_logger) << time_now_string() << ": fatal disk error ["
" error: " << j.str <<
" torrent: " << torrent_file().name() <<
" ]\n";
#endif
}
m_error = j.str;
pause();
return;
}
m_ses.check_torrent(shared_from_this());
}
void torrent::start_checking() void torrent::start_checking()
{ {
m_state = torrent_status::checking_files; m_state = torrent_status::checking_files;
@ -661,8 +687,6 @@ namespace libtorrent
" ]\n"; " ]\n";
#endif #endif
} }
m_have_pieces.clear_all();
m_num_pieces = 0;
m_error = j.str; m_error = j.str;
pause(); pause();
m_ses.done_checking(shared_from_this()); m_ses.done_checking(shared_from_this());
@ -671,13 +695,9 @@ namespace libtorrent
m_progress = j.piece / float(torrent_file().num_pieces()); m_progress = j.piece / float(torrent_file().num_pieces());
if (j.offset >= 0 && !m_have_pieces[j.offset]) TORRENT_ASSERT(m_picker);
{ if (j.offset >= 0 && !m_picker->have_piece(j.offset))
m_have_pieces.set_bit(j.offset);
++m_num_pieces;
TORRENT_ASSERT(m_picker);
m_picker->we_have(j.offset); m_picker->we_have(j.offset);
}
// we're not done checking yet // we're not done checking yet
// this handler will be called repeatedly until // this handler will be called repeatedly until
@ -793,6 +813,7 @@ namespace libtorrent
// INVARIANT_CHECK; // INVARIANT_CHECK;
if (m_trackers.empty()) return false; if (m_trackers.empty()) return false;
if (!m_files_checked) return false;
if (m_just_paused) if (m_just_paused)
{ {
@ -982,12 +1003,12 @@ namespace libtorrent
const int last_piece = m_torrent_file->num_pieces() - 1; const int last_piece = m_torrent_file->num_pieces() - 1;
size_type total_done size_type total_done
= size_type(m_num_pieces) * m_torrent_file->piece_length(); = size_type(num_have()) * m_torrent_file->piece_length();
// if we have the last piece, we have to correct // if we have the last piece, we have to correct
// the amount we have, since the first calculation // the amount we have, since the first calculation
// assumed all pieces were of equal size // assumed all pieces were of equal size
if (m_have_pieces[last_piece]) if (m_picker->have_piece(last_piece))
{ {
int corr = m_torrent_file->piece_size(last_piece) int corr = m_torrent_file->piece_size(last_piece)
- m_torrent_file->piece_length(); - m_torrent_file->piece_length();
@ -1013,19 +1034,19 @@ namespace libtorrent
return make_tuple(m_torrent_file->total_size() return make_tuple(m_torrent_file->total_size()
, m_torrent_file->total_size()); , m_torrent_file->total_size());
TORRENT_ASSERT(m_num_pieces >= m_picker->num_have_filtered()); TORRENT_ASSERT(num_have() >= m_picker->num_have_filtered());
size_type wanted_done = size_type(m_num_pieces - m_picker->num_have_filtered()) size_type wanted_done = size_type(num_have() - m_picker->num_have_filtered())
* piece_size; * piece_size;
TORRENT_ASSERT(wanted_done >= 0); TORRENT_ASSERT(wanted_done >= 0);
size_type total_done size_type total_done
= size_type(m_num_pieces) * piece_size; = size_type(num_have()) * piece_size;
TORRENT_ASSERT(m_num_pieces < m_torrent_file->num_pieces()); TORRENT_ASSERT(num_have() < m_torrent_file->num_pieces());
// if we have the last piece, we have to correct // if we have the last piece, we have to correct
// the amount we have, since the first calculation // the amount we have, since the first calculation
// assumed all pieces were of equal size // assumed all pieces were of equal size
if (m_have_pieces[last_piece]) if (m_picker->have_piece(last_piece))
{ {
TORRENT_ASSERT(total_done >= piece_size); TORRENT_ASSERT(total_done >= piece_size);
int corr = m_torrent_file->piece_size(last_piece) int corr = m_torrent_file->piece_size(last_piece)
@ -1054,7 +1075,7 @@ namespace libtorrent
{ {
int corr = 0; int corr = 0;
int index = i->index; int index = i->index;
if (m_have_pieces[index]) continue; if (m_picker->have_piece(index)) continue;
TORRENT_ASSERT(i->finished <= m_picker->blocks_in_piece(index)); TORRENT_ASSERT(i->finished <= m_picker->blocks_in_piece(index));
#ifndef NDEBUG #ifndef NDEBUG
@ -1099,7 +1120,7 @@ namespace libtorrent
= pc->downloading_piece_progress(); = pc->downloading_piece_progress();
if (p) if (p)
{ {
if (m_have_pieces[p->piece_index]) if (m_picker->have_piece(p->piece_index))
continue; continue;
piece_block block(p->piece_index, p->block_index); piece_block block(p->piece_index, p->block_index);
@ -1136,16 +1157,16 @@ namespace libtorrent
wanted_done += i->second; wanted_done += i->second;
} }
TORRENT_ASSERT(total_done <= m_torrent_file->total_size());
TORRENT_ASSERT(wanted_done <= m_torrent_file->total_size());
#ifndef NDEBUG #ifndef NDEBUG
if (total_done >= m_torrent_file->total_size()) if (total_done >= m_torrent_file->total_size())
{ {
// Thist happens when a piece has been downloaded completely // Thist happens when a piece has been downloaded completely
// but not yet verified against the hash // but not yet verified against the hash
std::copy(m_have_pieces.begin(), m_have_pieces.end() std::cerr << "num_have: " << num_have() << std::endl;
, std::ostream_iterator<bool>(std::cerr, " "));
std::cerr << std::endl;
std::cerr << "num_pieces: " << m_num_pieces << std::endl;
std::cerr << "unfinished:" << std::endl; std::cerr << "unfinished:" << std::endl;
@ -1195,7 +1216,7 @@ namespace libtorrent
?"disk failed":"failed") << " ]\n"; ?"disk failed":"failed") << " ]\n";
#endif #endif
bool was_finished = m_picker->num_filtered() + num_pieces() bool was_finished = m_picker->num_filtered() + num_have()
== torrent_file().num_pieces(); == torrent_file().num_pieces();
if (passed_hash_check == 0) if (passed_hash_check == 0)
@ -1226,7 +1247,7 @@ namespace libtorrent
if (!was_finished if (!was_finished
&& (is_seed() && (is_seed()
|| m_picker->num_filtered() + num_pieces() || m_picker->num_filtered() + num_have()
== torrent_file().num_pieces())) == torrent_file().num_pieces()))
{ {
TORRENT_ASSERT(passed_hash_check == 0); TORRENT_ASSERT(passed_hash_check == 0);
@ -1350,7 +1371,7 @@ namespace libtorrent
m_picker->restore_piece(index); m_picker->restore_piece(index);
TORRENT_ASSERT(m_storage); TORRENT_ASSERT(m_storage);
TORRENT_ASSERT(m_have_pieces[index] == false); TORRENT_ASSERT(m_picker->have_piece(index) == false);
#ifndef NDEBUG #ifndef NDEBUG
for (std::vector<void*>::iterator i = downloaders.begin() for (std::vector<void*>::iterator i = downloaders.begin()
@ -1486,13 +1507,6 @@ namespace libtorrent
std::set<void*> peers; std::set<void*> peers;
std::copy(downloaders.begin(), downloaders.end(), std::inserter(peers, peers.begin())); std::copy(downloaders.begin(), downloaders.end(), std::inserter(peers, peers.begin()));
if (!m_have_pieces[index])
m_num_pieces++;
m_have_pieces.set_bit(index);
TORRENT_ASSERT(std::accumulate(m_have_pieces.begin(), m_have_pieces.end(), 0)
== m_num_pieces);
m_picker->we_have(index); m_picker->we_have(index);
for (peer_iterator i = m_connections.begin(); i != m_connections.end(); ++i) for (peer_iterator i = m_connections.begin(); i != m_connections.end(); ++i)
(*i)->announce_piece(index); (*i)->announce_piece(index);
@ -1558,7 +1572,7 @@ namespace libtorrent
bool was_finished = is_finished(); bool was_finished = is_finished();
bool filter_updated = m_picker->set_piece_priority(index, priority); bool filter_updated = m_picker->set_piece_priority(index, priority);
TORRENT_ASSERT(m_num_pieces >= m_picker->num_have_filtered()); TORRENT_ASSERT(num_have() >= m_picker->num_have_filtered());
if (filter_updated) update_peer_interest(was_finished); if (filter_updated) update_peer_interest(was_finished);
} }
@ -1596,7 +1610,7 @@ namespace libtorrent
TORRENT_ASSERT(*i >= 0); TORRENT_ASSERT(*i >= 0);
TORRENT_ASSERT(*i <= 7); TORRENT_ASSERT(*i <= 7);
filter_updated |= m_picker->set_piece_priority(index, *i); filter_updated |= m_picker->set_piece_priority(index, *i);
TORRENT_ASSERT(m_num_pieces >= m_picker->num_have_filtered()); TORRENT_ASSERT(num_have() >= m_picker->num_have_filtered());
} }
if (filter_updated) update_peer_interest(was_finished); if (filter_updated) update_peer_interest(was_finished);
} }
@ -2442,8 +2456,16 @@ namespace libtorrent
// write have bitmask // write have bitmask
entry::string_type& pieces = ret["pieces"].string(); entry::string_type& pieces = ret["pieces"].string();
pieces.resize(m_torrent_file->num_pieces()); pieces.resize(m_torrent_file->num_pieces());
for (int i = 0, end(pieces.size()); i < end; ++i) if (is_seed())
pieces[i] = m_have_pieces[i] ? 1 : 0; {
for (int i = 0, end(pieces.size()); i < end; ++i)
pieces[i] = 1;
}
else
{
for (int i = 0, end(pieces.size()); i < end; ++i)
pieces[i] = m_picker->have_piece(i) ? 1 : 0;
}
// write local peers // write local peers
@ -2714,6 +2736,8 @@ namespace libtorrent
TORRENT_ASSERT(p != 0); TORRENT_ASSERT(p != 0);
TORRENT_ASSERT(!p->is_local()); TORRENT_ASSERT(!p->is_local());
m_has_incoming = true;
if ((m_state == torrent_status::queued_for_checking if ((m_state == torrent_status::queued_for_checking
|| m_state == torrent_status::checking_files) || m_state == torrent_status::checking_files)
&& valid_metadata()) && valid_metadata())
@ -3115,7 +3139,6 @@ namespace libtorrent
if (!is_seed()) if (!is_seed())
{ {
m_picker->init(m_have_pieces);
if (m_sequential_download) if (m_sequential_download)
picker().sequential_download(m_sequential_download); picker().sequential_download(m_sequential_download);
} }
@ -3169,9 +3192,7 @@ namespace libtorrent
, "torrent finished checking")); , "torrent finished checking"));
} }
#ifndef NDEBUG
m_files_checked = true; m_files_checked = true;
#endif
} }
alert_manager& torrent::alerts() const alert_manager& torrent::alerts() const
@ -3289,16 +3310,16 @@ namespace libtorrent
if (!m_picker->is_downloaded(i->first)) if (!m_picker->is_downloaded(i->first))
TORRENT_ASSERT(m_picker->num_peers(i->first) == i->second); TORRENT_ASSERT(m_picker->num_peers(i->first) == i->second);
} }
TORRENT_ASSERT(m_num_pieces >= m_picker->num_have_filtered()); TORRENT_ASSERT(num_have() >= m_picker->num_have_filtered());
} }
if (valid_metadata()) if (valid_metadata())
{ {
TORRENT_ASSERT(m_abort || int(m_have_pieces.size()) == m_torrent_file->num_pieces()); TORRENT_ASSERT(m_abort || !m_picker || m_picker->num_pieces() == m_torrent_file->num_pieces());
} }
else else
{ {
TORRENT_ASSERT(m_abort || m_have_pieces.empty()); TORRENT_ASSERT(m_abort || m_picker->num_pieces() == 0);
} }
for (policy::const_iterator i = m_policy.begin_peer() for (policy::const_iterator i = m_policy.begin_peer()
@ -3313,7 +3334,7 @@ namespace libtorrent
if (is_seed()) if (is_seed())
TORRENT_ASSERT(total_done == m_torrent_file->total_size()); TORRENT_ASSERT(total_done == m_torrent_file->total_size());
else else
TORRENT_ASSERT(total_done != m_torrent_file->total_size()); TORRENT_ASSERT(total_done != m_torrent_file->total_size() || !m_files_checked);
} }
else else
{ {
@ -3344,8 +3365,6 @@ namespace libtorrent
} }
// This check is very expensive. // This check is very expensive.
TORRENT_ASSERT(m_num_pieces
== std::count(m_have_pieces.begin(), m_have_pieces.end(), true));
TORRENT_ASSERT(!valid_metadata() || m_block_size > 0); TORRENT_ASSERT(!valid_metadata() || m_block_size > 0);
TORRENT_ASSERT(!valid_metadata() || (m_torrent_file->piece_length() % m_block_size) == 0); TORRENT_ASSERT(!valid_metadata() || (m_torrent_file->piece_length() % m_block_size) == 0);
// if (is_seed()) TORRENT_ASSERT(m_picker.get() == 0); // if (is_seed()) TORRENT_ASSERT(m_picker.get() == 0);
@ -3412,6 +3431,9 @@ namespace libtorrent
} }
m_sequence_number = (std::min)(max_seq + 1, p); m_sequence_number = (std::min)(max_seq + 1, p);
} }
if (m_ses.m_auto_manage_time_scaler > 2)
m_ses.m_auto_manage_time_scaler = 2;
} }
void torrent::set_max_uploads(int limit) void torrent::set_max_uploads(int limit)
@ -3814,7 +3836,7 @@ namespace libtorrent
TORRENT_ASSERT(m_storage->refcount() > 0); TORRENT_ASSERT(m_storage->refcount() > 0);
TORRENT_ASSERT(piece_index >= 0); TORRENT_ASSERT(piece_index >= 0);
TORRENT_ASSERT(piece_index < m_torrent_file->num_pieces()); TORRENT_ASSERT(piece_index < m_torrent_file->num_pieces());
TORRENT_ASSERT(piece_index < (int)m_have_pieces.size()); TORRENT_ASSERT(piece_index < (int)m_picker->num_pieces());
#ifndef NDEBUG #ifndef NDEBUG
if (m_picker) if (m_picker)
{ {
@ -3865,6 +3887,12 @@ namespace libtorrent
TORRENT_ASSERT(valid_metadata()); TORRENT_ASSERT(valid_metadata());
fp.clear(); fp.clear();
if (is_seed())
{
fp.resize(m_torrent_file->num_files(), 1.f);
return;
}
fp.resize(m_torrent_file->num_files(), 0.f); fp.resize(m_torrent_file->num_files(), 0.f);
for (int i = 0; i < m_torrent_file->num_files(); ++i) for (int i = 0; i < m_torrent_file->num_files(); ++i)
@ -3885,7 +3913,7 @@ namespace libtorrent
{ {
size_type bytes_step = (std::min)(size_type(m_torrent_file->piece_size(ret.piece) size_type bytes_step = (std::min)(size_type(m_torrent_file->piece_size(ret.piece)
- ret.start), size); - ret.start), size);
if (m_have_pieces[ret.piece]) done += bytes_step; if (m_picker->have_piece(ret.piece)) done += bytes_step;
++ret.piece; ++ret.piece;
ret.start = 0; ret.start = 0;
size -= bytes_step; size -= bytes_step;
@ -3900,15 +3928,11 @@ namespace libtorrent
{ {
INVARIANT_CHECK; INVARIANT_CHECK;
TORRENT_ASSERT(std::accumulate(
m_have_pieces.begin()
, m_have_pieces.end()
, 0) == m_num_pieces);
ptime now = time_now(); ptime now = time_now();
torrent_status st; torrent_status st;
st.has_incoming = m_has_incoming;
st.error = m_error; st.error = m_error;
if (m_last_scrape == min_time()) if (m_last_scrape == min_time())
@ -4030,8 +4054,14 @@ namespace libtorrent
else st.progress = st.total_wanted_done else st.progress = st.total_wanted_done
/ static_cast<float>(st.total_wanted); / static_cast<float>(st.total_wanted);
st.pieces = &m_have_pieces; if (has_picker())
st.num_pieces = m_num_pieces; {
int num_pieces = m_picker->num_pieces();
st.pieces.resize(num_pieces, false);
for (int i = 0; i < num_pieces; ++i)
if (m_picker->have_piece(i)) st.pieces.set_bit(i);
}
st.num_pieces = num_have();
st.num_seeds = num_seeds(); st.num_seeds = num_seeds();
if (m_picker.get()) if (m_picker.get())
st.distributed_copies = m_picker->distributed_copies(); st.distributed_copies = m_picker->distributed_copies();

View File

@ -265,6 +265,12 @@ namespace libtorrent
TORRENT_FORWARD(save_resume_data()); TORRENT_FORWARD(save_resume_data());
} }
void torrent_handle::force_recheck() const
{
INVARIANT_CHECK;
TORRENT_FORWARD(force_recheck());
}
void torrent_handle::resume() const void torrent_handle::resume() const
{ {
INVARIANT_CHECK; INVARIANT_CHECK;

View File

@ -67,6 +67,7 @@ namespace libtorrent
: peer_connection(ses, t, s, remote, peerinfo) : peer_connection(ses, t, s, remote, peerinfo)
, m_url(url) , m_url(url)
, m_first_request(true) , m_first_request(true)
, m_range_pos(0)
{ {
INVARIANT_CHECK; INVARIANT_CHECK;
@ -350,7 +351,8 @@ namespace libtorrent
{ {
bool error = false; bool error = false;
boost::tie(payload, protocol) = m_parser.incoming(recv_buffer, error); boost::tie(payload, protocol) = m_parser.incoming(recv_buffer, error);
m_statistics.received_bytes(payload, protocol); m_statistics.received_bytes(0, protocol);
bytes_transferred -= protocol;
if (error) if (error)
{ {
@ -363,7 +365,12 @@ namespace libtorrent
TORRENT_ASSERT(recv_buffer.left() <= packet_size()); TORRENT_ASSERT(recv_buffer.left() <= packet_size());
// this means the entire status line hasn't been received yet // this means the entire status line hasn't been received yet
if (m_parser.status_code() == -1) break; if (m_parser.status_code() == -1)
{
TORRENT_ASSERT(payload == 0);
TORRENT_ASSERT(bytes_transferred == 0);
break;
}
// if the status code is not one of the accepted ones, abort // if the status code is not one of the accepted ones, abort
if (m_parser.status_code() != 206 // partial content if (m_parser.status_code() != 206 // partial content
@ -388,15 +395,16 @@ namespace libtorrent
disconnect(error_msg.c_str(), 1); disconnect(error_msg.c_str(), 1);
return; return;
} }
if (!m_parser.header_finished()) break; if (!m_parser.header_finished())
{
TORRENT_ASSERT(payload == 0);
TORRENT_ASSERT(bytes_transferred == 0);
break;
}
m_body_start = m_parser.body_start(); m_body_start = m_parser.body_start();
m_received_body = 0; m_received_body = 0;
} }
else
{
m_statistics.received_bytes(bytes_transferred, 0);
}
// we just completed reading the header // we just completed reading the header
if (!header_finished) if (!header_finished)
@ -460,9 +468,11 @@ namespace libtorrent
m_body_start = m_parser.body_start(); m_body_start = m_parser.body_start();
m_received_body = 0; m_received_body = 0;
m_range_pos = 0;
} }
recv_buffer.begin += m_body_start; recv_buffer.begin += m_body_start;
// we only received the header, no data // we only received the header, no data
if (recv_buffer.left() == 0) break; if (recv_buffer.left() == 0) break;
@ -499,6 +509,13 @@ namespace libtorrent
} }
} }
int left_in_response = range_end - range_start - m_range_pos;
int payload_transferred = (std::min)(left_in_response, int(bytes_transferred));
m_statistics.received_bytes(payload_transferred, 0);
bytes_transferred -= payload_transferred;
m_range_pos += payload_transferred;;
if (m_range_pos > range_end - range_start) m_range_pos = range_end - range_start;
// std::cerr << "REQUESTS: m_requests: " << m_requests.size() // std::cerr << "REQUESTS: m_requests: " << m_requests.size()
// << " file_requests: " << m_file_requests.size() << std::endl; // << " file_requests: " << m_file_requests.size() << std::endl;
@ -641,8 +658,9 @@ namespace libtorrent
m_received_body = 0; m_received_body = 0;
continue; continue;
} }
break; if (bytes_transferred == 0) break;
} }
TORRENT_ASSERT(bytes_transferred == 0);
} }
void web_peer_connection::get_specific_peer_info(peer_info& p) const void web_peer_connection::get_specific_peer_info(peer_info& p) const