*** empty log message ***

This commit is contained in:
Arvid Norberg 2003-11-04 23:27:06 +00:00
parent 8b61436561
commit 6325295993
14 changed files with 428 additions and 130 deletions

View File

@ -518,6 +518,7 @@ struct torrent_status
state_t state; state_t state;
float progress; float progress;
boost::posix_time::time_duration next_announce;
std::size_t total_download; std::size_t total_download;
std::size_t total_upload; std::size_t total_upload;
}; };
@ -577,6 +578,10 @@ current task is in the <tt>state</tt> member, it will be one of the following:
</tr> </tr>
</table> </table>
<p>
<tt>next_announce</tt> is the time until the torrent will announce itself to the tracker.
</p>
<p> <p>
<tt>total_download</tt> and <tt>total_upload</tt> is the number of bytes downloaded and <tt>total_download</tt> and <tt>total_upload</tt> is the number of bytes downloaded and
uploaded to all peers, accumulated. uploaded to all peers, accumulated.

View File

@ -36,6 +36,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <exception> #include <exception>
#include <boost/format.hpp> #include <boost/format.hpp>
//#include <boost/date_time/posix_time/posix_time.hpp>
#include "libtorrent/entry.hpp" #include "libtorrent/entry.hpp"
#include "libtorrent/bencode.hpp" #include "libtorrent/bencode.hpp"
@ -115,6 +116,16 @@ bool sleep_and_input(char* c)
return false; return false;
} }
void set_cursor(int x, int y)
{
std::cout << "\033[" << y << ";" << x << "H";
}
void clear()
{
std::cout << "\033[2J";
}
#endif #endif
std::string add_suffix(float val) std::string add_suffix(float val)
@ -237,6 +248,10 @@ int main(int argc, char* argv[])
<< add_suffix(total_down) << ") " << add_suffix(down) << "/s u:(" << add_suffix(total_down) << ") " << add_suffix(down) << "/s u:("
<< add_suffix(total_up) << ") " << add_suffix(up) << "/s\n"; << add_suffix(total_up) << ") " << add_suffix(up) << "/s\n";
boost::posix_time::time_duration t = s.next_announce;
// std::cout << "next announce: " << boost::posix_time::to_simple_string(t) << "\n";
std::cout << "next announce: " << t.hours() << ":" << t.minutes() << ":" << t.seconds() << "\n";
i->get_download_queue(queue); i->get_download_queue(queue);
for (std::vector<partial_piece_info>::iterator i = queue.begin(); for (std::vector<partial_piece_info>::iterator i = queue.begin();
i != queue.end(); i != queue.end();
@ -245,7 +260,7 @@ int main(int argc, char* argv[])
std::cout << i->piece_index << ": "; std::cout << i->piece_index << ": ";
for (int j = 0; j < i->blocks_in_piece; ++j) for (int j = 0; j < i->blocks_in_piece; ++j)
{ {
if (i->finished_blocks[j]) std::cout << "#"; if (i->finished_blocks[j]) std::cout << "+";
else if (i->requested_blocks[j]) std::cout << "-"; else if (i->requested_blocks[j]) std::cout << "-";
else std::cout << "."; else std::cout << ".";
} }

View File

@ -81,17 +81,29 @@ namespace libtorrent
// this is the constructor where the we are teh active part. The peer_conenction // this is the constructor where the we are teh active part. The peer_conenction
// should handshake and verify that the other end has the correct id // should handshake and verify that the other end has the correct id
peer_connection(detail::session_impl* ses, torrent* t, boost::shared_ptr<libtorrent::socket> s, const peer_id& p); peer_connection(
detail::session_impl* ses
, selector& sel
, torrent* t
, boost::shared_ptr<libtorrent::socket> s
, const peer_id& p);
// with this constructor we have been contacted and we still don't know which torrent the // with this constructor we have been contacted and we still don't know which torrent the
// connection belongs to // connection belongs to
peer_connection(detail::session_impl* ses, boost::shared_ptr<libtorrent::socket> s); peer_connection(
detail::session_impl* ses
, selector& sel
, boost::shared_ptr<libtorrent::socket> s);
~peer_connection(); ~peer_connection();
// this adds an announcement in the announcement queue // this adds an announcement in the announcement queue
// it will let the peer know that we have the given piece // it will let the peer know that we have the given piece
void announce_piece(int index) { m_announce_queue.push_back(index); } void announce_piece(int index)
{
m_announce_queue.push_back(index);
send_buffer_updated();
}
// called from the main loop when this connection has any // called from the main loop when this connection has any
// work to do. // work to do.
@ -122,6 +134,7 @@ namespace libtorrent
void interested(); void interested();
void not_interested(); void not_interested();
void request_block(piece_block block); void request_block(piece_block block);
void cancel_block(piece_block block);
bool is_interesting() const throw() { return m_interesting; } bool is_interesting() const throw() { return m_interesting; }
bool has_choked() const throw() { return m_choked; } bool has_choked() const throw() { return m_choked; }
@ -152,6 +165,7 @@ namespace libtorrent
private: private:
bool dispatch_message(); bool dispatch_message();
void send_buffer_updated();
void send_bitfield(); void send_bitfield();
void send_have(int index); void send_have(int index);
@ -200,6 +214,7 @@ namespace libtorrent
boost::posix_time::ptime m_last_receive; boost::posix_time::ptime m_last_receive;
boost::posix_time::ptime m_last_sent; boost::posix_time::ptime m_last_sent;
selector& m_selector;
boost::shared_ptr<libtorrent::socket> m_socket; boost::shared_ptr<libtorrent::socket> m_socket;
torrent* m_torrent; torrent* m_torrent;
detail::session_impl* m_ses; detail::session_impl* m_ses;
@ -207,6 +222,15 @@ namespace libtorrent
// and false if we got an incomming connection // and false if we got an incomming connection
bool m_active; bool m_active;
// this is true as long as this peer's
// socket is added to the selector to
// monitor writability. Each time we do
// something that generates data to be
// sent to this peer, we check this and
// if it's not added to the selector we
// add it.
bool m_added_to_selector;
// remote peer's id // remote peer's id
peer_id m_peer_id; peer_id m_peer_id;
@ -242,6 +266,21 @@ namespace libtorrent
stat m_statistics; stat m_statistics;
}; };
// this is called each time this peer generates some
// data to be sent. It will add this socket to
// the writibility monitor in the selector.
inline void peer_connection::send_buffer_updated()
{
if (!has_data()) return;
if (!m_added_to_selector)
{
m_selector.monitor_writability(m_socket);
m_added_to_selector = true;
}
assert(m_added_to_selector);
assert(m_selector.is_writability_monitored(m_socket));
}
} }
#endif // TORRENT_PEER_CONNECTION_HPP_INCLUDED #endif // TORRENT_PEER_CONNECTION_HPP_INCLUDED

View File

@ -92,7 +92,7 @@ namespace libtorrent
os << std::hex << std::setw(2) << std::setfill('0') os << std::hex << std::setw(2) << std::setfill('0')
<< static_cast<unsigned int>(*i); << static_cast<unsigned int>(*i);
} }
os << std::dec << std::cout << std::setfill(' '); os << std::dec << std::setfill(' ');
return os; return os;
} }

View File

@ -54,6 +54,12 @@ namespace libtorrent
{} {}
int piece_index; int piece_index;
int block_index; int block_index;
bool operator==(const piece_block& b) const
{ return piece_index == b.piece_index && block_index == b.block_index; }
bool operator!=(const piece_block& b) const
{ return piece_index != b.piece_index || block_index != b.block_index; }
}; };
class piece_picker class piece_picker
@ -133,9 +139,11 @@ namespace libtorrent
// or if it already has been successfully downlloaded // or if it already has been successfully downlloaded
bool is_downloading(piece_block block) const; bool is_downloading(piece_block block) const;
bool is_finished(piece_block block) const;
// marks this piece-block as queued for downloading // marks this piece-block as queued for downloading
void mark_as_downloading(piece_block block, const peer_id& peer); void mark_as_downloading(piece_block block, const peer_id& peer);
void mark_as_finished(piece_block block); void mark_as_finished(piece_block block, const peer_id& peer);
// if a piece had a hash-failure, it must be restured and // if a piece had a hash-failure, it must be restured and
// made available for redownloading // made available for redownloading

View File

@ -152,8 +152,14 @@ namespace libtorrent
// the given peer_id (should be kept at max 1) // the given peer_id (should be kept at max 1)
int num_connections(const peer_id& id) const; int num_connections(const peer_id& id) const;
std::vector<peer_connection*>::const_iterator begin() const { return m_connections.begin(); } typedef std::vector<peer_connection*>::iterator peer_iterator;
std::vector<peer_connection*>::const_iterator end() const { return m_connections.end(); } typedef std::vector<peer_connection*>::const_iterator peer_const_iterator;
peer_const_iterator begin() const { return m_connections.begin(); }
peer_const_iterator end() const { return m_connections.end(); }
peer_iterator begin() { return m_connections.begin(); }
peer_iterator end() { return m_connections.end(); }
// -------------------------------------------- // --------------------------------------------
@ -165,13 +171,13 @@ namespace libtorrent
void tracker_request_timed_out() void tracker_request_timed_out()
{ {
std::cout << "TRACKER TIMED OUT\n"; std::cerr << "TRACKER TIMED OUT\n";
try_next_tracker(); try_next_tracker();
} }
void tracker_request_error(const char* str) void tracker_request_error(const char* str)
{ {
std::cout << "TRACKER ERROR: " << str << "\n"; std::cerr << "TRACKER ERROR: " << str << "\n";
try_next_tracker(); try_next_tracker();
} }
@ -179,6 +185,8 @@ namespace libtorrent
// to the tracker // to the tracker
std::string generate_tracker_request(int port); std::string generate_tracker_request(int port);
boost::posix_time::ptime next_announce() const
{ return m_next_request; }
// -------------------------------------------- // --------------------------------------------
// PIECE MANAGEMENT // PIECE MANAGEMENT
@ -216,10 +224,6 @@ namespace libtorrent
logger* spawn_logger(const char* title); logger* spawn_logger(const char* title);
#endif #endif
// the number of blocks downloaded
// that hasn't been verified yet
int m_unverified_blocks;
private: private:
void try_next_tracker(); void try_next_tracker();

View File

@ -34,6 +34,7 @@ POSSIBILITY OF SUCH DAMAGE.
#define TORRENT_TORRENT_HANDLE_HPP_INCLUDED #define TORRENT_TORRENT_HANDLE_HPP_INCLUDED
#include <vector> #include <vector>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include "libtorrent/peer_id.hpp" #include "libtorrent/peer_id.hpp"
#include "libtorrent/peer_info.hpp" #include "libtorrent/peer_info.hpp"
@ -50,7 +51,8 @@ namespace libtorrent
struct duplicate_torrent: std::exception struct duplicate_torrent: std::exception
{ {
virtual const char* what() const { return "torrent already exists in session"; } virtual const char* what() const throw()
{ return "torrent already exists in session"; }
}; };
struct torrent_status struct torrent_status
@ -66,6 +68,7 @@ namespace libtorrent
state_t state; state_t state;
float progress; float progress;
boost::posix_time::time_duration next_announce;
std::size_t total_download; std::size_t total_download;
std::size_t total_upload; std::size_t total_upload;
}; };
@ -84,17 +87,15 @@ namespace libtorrent
struct torrent_handle struct torrent_handle
{ {
friend class session; friend class session;
torrent_handle(): m_ses(0) {} torrent_handle(): m_ses(0) {}
void get_peer_info(std::vector<peer_info>& v);
void abort(); void abort();
void get_peer_info(std::vector<peer_info>& v);
torrent_status status() const; torrent_status status() const;
void get_download_queue(std::vector<partial_piece_info>& queue) const; void get_download_queue(std::vector<partial_piece_info>& queue) const;
// TODO: add a 'time to next announce' query. // TODO: add force reannounce
private: private:

View File

@ -71,17 +71,24 @@ namespace
} }
libtorrent::peer_connection::peer_connection(detail::session_impl* ses, torrent* t, boost::shared_ptr<libtorrent::socket> s, const peer_id& p) libtorrent::peer_connection::peer_connection(
detail::session_impl* ses
, selector& sel
, torrent* t
, boost::shared_ptr<libtorrent::socket> s
, const peer_id& p)
: m_state(read_protocol_length) : m_state(read_protocol_length)
, m_timeout(120) , m_timeout(120)
, m_packet_size(1) , m_packet_size(1)
, m_recv_pos(0) , m_recv_pos(0)
, m_last_receive(std::time(0)) , m_last_receive(std::time(0))
, m_last_sent(std::time(0)) , m_last_sent(std::time(0))
, m_selector(sel)
, m_socket(s) , m_socket(s)
, m_torrent(t) , m_torrent(t)
, m_ses(ses) , m_ses(ses)
, m_active(true) , m_active(true)
, m_added_to_selector(false)
, m_peer_id(p) , m_peer_id(p)
, m_peer_interested(false) , m_peer_interested(false)
, m_peer_choked(true) , m_peer_choked(true)
@ -107,17 +114,22 @@ libtorrent::peer_connection::peer_connection(detail::session_impl* ses, torrent*
send_bitfield(); send_bitfield();
} }
libtorrent::peer_connection::peer_connection(detail::session_impl* ses, boost::shared_ptr<libtorrent::socket> s) libtorrent::peer_connection::peer_connection(
detail::session_impl* ses
, selector& sel
, boost::shared_ptr<libtorrent::socket> s)
: m_state(read_protocol_length) : m_state(read_protocol_length)
, m_timeout(120) , m_timeout(120)
, m_packet_size(1) , m_packet_size(1)
, m_recv_pos(0) , m_recv_pos(0)
, m_last_receive(std::time(0)) , m_last_receive(std::time(0))
, m_last_sent(std::time(0)) , m_last_sent(std::time(0))
, m_selector(sel)
, m_socket(s) , m_socket(s)
, m_torrent(0) , m_torrent(0)
, m_ses(ses) , m_ses(ses)
, m_active(false) , m_active(false)
, m_added_to_selector(false)
, m_peer_id() , m_peer_id()
, m_peer_interested(false) , m_peer_interested(false)
, m_peer_choked(true) , m_peer_choked(true)
@ -161,6 +173,7 @@ void libtorrent::peer_connection::send_handshake()
(*m_logger) << m_socket->sender().as_string() << " ==> HANDSHAKE\n"; (*m_logger) << m_socket->sender().as_string() << " ==> HANDSHAKE\n";
#endif #endif
send_buffer_updated();
} }
bool libtorrent::peer_connection::dispatch_message() bool libtorrent::peer_connection::dispatch_message()
@ -305,6 +318,8 @@ bool libtorrent::peer_connection::dispatch_message()
r.length = read_int(&m_recv_buffer[9]); r.length = read_int(&m_recv_buffer[9]);
m_requests.push_back(r); m_requests.push_back(r);
send_buffer_updated();
#if defined(TORRENT_VERBOSE_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING)
(*m_logger) << m_socket->sender().as_string() << " <== REQUEST [ piece: " << r.piece << " | s: " << r.start << " | l: " << r.length << " ]\n"; (*m_logger) << m_socket->sender().as_string() << " <== REQUEST [ piece: " << r.piece << " | s: " << r.start << " | l: " << r.length << " ]\n";
#endif #endif
@ -351,7 +366,7 @@ bool libtorrent::peer_connection::dispatch_message()
#endif #endif
return false; return false;
} }
/*
piece_block req = m_download_queue.front(); piece_block req = m_download_queue.front();
if (req.piece_index != index) if (req.piece_index != index)
{ {
@ -368,31 +383,48 @@ bool libtorrent::peer_connection::dispatch_message()
#endif #endif
return false; return false;
} }
*/
m_receiving_piece.open(m_torrent->filesystem(), index, piece_file::out, offset);
#if defined(TORRENT_VERBOSE_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING)
(*m_logger) << m_socket->sender().as_string() << " <== PIECE [ piece: " << index << " | s: " << offset << " | l: " << len << " ]\n"; (*m_logger) << m_socket->sender().as_string() << " <== PIECE [ piece: " << index << " | s: " << offset << " | l: " << len << " ]\n";
#endif #endif
m_receiving_piece.write(&m_recv_buffer[9], len);
m_torrent->downloaded_bytes(len); m_torrent->downloaded_bytes(len);
piece_picker& picker = m_torrent->picker(); piece_picker& picker = m_torrent->picker();
piece_block block_finished(index, offset / m_torrent->block_size()); piece_block block_finished(index, offset / m_torrent->block_size());
picker.mark_as_finished(block_finished);
// pop the request that just finished std::vector<piece_block>::iterator b
// from the download queue = std::find(
m_download_queue.erase(m_download_queue.begin()); m_download_queue.begin()
m_torrent->m_unverified_blocks++; , m_download_queue.end()
, block_finished);
if (b != m_download_queue.end())
{
// pop the request that just finished
// from the download queue
m_download_queue.erase(b);
}
else
{
// TODO: cancel the block from the
// peer that has taken over it.
}
if (picker.is_finished(block_finished)) break;
m_receiving_piece.open(m_torrent->filesystem(), index, piece_file::out, offset);
m_receiving_piece.write(&m_recv_buffer[9], len);
m_receiving_piece.close();
picker.mark_as_finished(block_finished, m_peer_id);
// did we just finish the piece? // did we just finish the piece?
if (picker.is_piece_finished(index)) if (picker.is_piece_finished(index))
{ {
m_torrent->m_unverified_blocks -= picker.blocks_in_piece(index); m_receiving_piece.open(m_torrent->filesystem(), index, piece_file::in);
bool verified = m_torrent->filesystem()->verify_piece(m_receiving_piece); bool verified = m_torrent->filesystem()->verify_piece(m_receiving_piece);
m_receiving_piece.close();
if (verified) if (verified)
{ {
m_torrent->announce_piece(index); m_torrent->announce_piece(index);
@ -438,10 +470,15 @@ bool libtorrent::peer_connection::dispatch_message()
m_requests.erase(i); m_requests.erase(i);
} }
if (!has_data() && m_added_to_selector)
{
m_added_to_selector = false;
m_selector.remove_writable(m_socket);
}
#if defined(TORRENT_VERBOSE_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING)
(*m_logger) << m_socket->sender().as_string() << " <== CANCEL [ piece: " << r.piece << " | s: " << r.start << " | l: " << r.length << " ]\n"; (*m_logger) << m_socket->sender().as_string() << " <== CANCEL [ piece: " << r.piece << " | s: " << r.start << " | l: " << r.length << " ]\n";
#endif #endif
m_requests.clear();
break; break;
} }
} }
@ -449,6 +486,55 @@ bool libtorrent::peer_connection::dispatch_message()
return true; return true;
} }
void libtorrent::peer_connection::cancel_block(piece_block block)
{
assert(block.piece_index >= 0);
assert(block.piece_index < m_torrent->torrent_file().num_pieces());
assert(m_torrent->picker().is_downloading(block));
m_torrent->picker().abort_download(block);
std::vector<piece_block>::iterator i
= std::find(m_download_queue.begin(), m_download_queue.end(), block);
assert(i != m_download_queue.end());
m_download_queue.erase(i);
int block_offset = block.block_index * m_torrent->block_size();
int block_size
= std::min((int)m_torrent->torrent_file().piece_size(block.piece_index)-block_offset,
m_torrent->block_size());
assert(block_size > 0);
assert(block_size <= m_torrent->block_size());
char buf[] = {0,0,0,13, msg_cancel};
std::size_t start_offset = m_send_buffer.size();
m_send_buffer.resize(start_offset + 17);
std::copy(buf, buf + 5, m_send_buffer.begin()+start_offset);
start_offset +=5;
// index
write_int(block.piece_index, &m_send_buffer[start_offset]);
start_offset += 4;
// begin
write_int(block_offset, &m_send_buffer[start_offset]);
start_offset += 4;
// length
write_int(block_size, &m_send_buffer[start_offset]);
start_offset += 4;
#if defined(TORRENT_VERBOSE_LOGGING)
(*m_logger) << m_socket->sender().as_string() << " ==> CANCEL [ piece: " << block.piece_index << " | s: " << block_offset << " | l: " << block_size << " | " << block.block_index << " ]\n";
#endif
assert(start_offset == m_send_buffer.size());
send_buffer_updated();
}
void libtorrent::peer_connection::request_block(piece_block block) void libtorrent::peer_connection::request_block(piece_block block)
{ {
assert(block.piece_index >= 0); assert(block.piece_index >= 0);
@ -493,6 +579,7 @@ void libtorrent::peer_connection::request_block(piece_block block)
#endif #endif
assert(start_offset == m_send_buffer.size()); assert(start_offset == m_send_buffer.size());
send_buffer_updated();
} }
void libtorrent::peer_connection::send_bitfield() void libtorrent::peer_connection::send_bitfield()
@ -511,6 +598,7 @@ void libtorrent::peer_connection::send_bitfield()
if (m_torrent->have_piece(i)) if (m_torrent->have_piece(i))
m_send_buffer[old_size + 5 + (i>>3)] |= 1 << (7 - (i&7)); m_send_buffer[old_size + 5 + (i>>3)] |= 1 << (7 - (i&7));
} }
send_buffer_updated();
} }
void libtorrent::peer_connection::choke() void libtorrent::peer_connection::choke()
@ -522,6 +610,7 @@ void libtorrent::peer_connection::choke()
#if defined(TORRENT_VERBOSE_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING)
(*m_logger) << m_socket->sender().as_string() << " ==> CHOKE\n"; (*m_logger) << m_socket->sender().as_string() << " ==> CHOKE\n";
#endif #endif
send_buffer_updated();
} }
void libtorrent::peer_connection::unchoke() void libtorrent::peer_connection::unchoke()
@ -533,6 +622,7 @@ void libtorrent::peer_connection::unchoke()
#if defined(TORRENT_VERBOSE_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING)
(*m_logger) << m_socket->sender().as_string() << " ==> UNCHOKE\n"; (*m_logger) << m_socket->sender().as_string() << " ==> UNCHOKE\n";
#endif #endif
send_buffer_updated();
} }
void libtorrent::peer_connection::interested() void libtorrent::peer_connection::interested()
@ -544,6 +634,7 @@ void libtorrent::peer_connection::interested()
#if defined(TORRENT_VERBOSE_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING)
(*m_logger) << m_socket->sender().as_string() << " ==> INTERESTED\n"; (*m_logger) << m_socket->sender().as_string() << " ==> INTERESTED\n";
#endif #endif
send_buffer_updated();
} }
void libtorrent::peer_connection::not_interested() void libtorrent::peer_connection::not_interested()
@ -555,6 +646,7 @@ void libtorrent::peer_connection::not_interested()
#if defined(TORRENT_VERBOSE_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING)
(*m_logger) << m_socket->sender().as_string() << " ==> NOT_INTERESTED\n"; (*m_logger) << m_socket->sender().as_string() << " ==> NOT_INTERESTED\n";
#endif #endif
send_buffer_updated();
} }
void libtorrent::peer_connection::send_have(int index) void libtorrent::peer_connection::send_have(int index)
@ -565,6 +657,7 @@ void libtorrent::peer_connection::send_have(int index)
#if defined(TORRENT_VERBOSE_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING)
(*m_logger) << m_socket->sender().as_string() << " ==> HAVE [ piece: " << index << " ]\n"; (*m_logger) << m_socket->sender().as_string() << " ==> HAVE [ piece: " << index << " ]\n";
#endif #endif
send_buffer_updated();
} }
@ -784,7 +877,7 @@ bool libtorrent::peer_connection::has_data() const throw()
{ {
// if we have requests or pending data to be sent or announcements to be made // if we have requests or pending data to be sent or announcements to be made
// we want to send data // we want to send data
return !m_requests.empty() || !m_send_buffer.empty() || !m_announce_queue.empty(); return (!m_requests.empty() && !m_choked) || !m_send_buffer.empty() || !m_announce_queue.empty();
} }
// -------------------------- // --------------------------
@ -794,11 +887,17 @@ bool libtorrent::peer_connection::has_data() const throw()
// throws exception when the client should be disconnected // throws exception when the client should be disconnected
void libtorrent::peer_connection::send_data() void libtorrent::peer_connection::send_data()
{ {
assert(m_socket->is_writable());
assert(has_data()); assert(has_data());
// only add new piece-chunks if the send buffer is empty // only add new piece-chunks if the send buffer is small enough
// otherwise there will be no end to how large it will be! // otherwise there will be no end to how large it will be!
if (!m_requests.empty() && m_send_buffer.empty() && m_peer_interested && !m_choked) // TODO: make ths a bit better. Don't always read the entire
// requested block. Have a limit of how much of the requested
// block is actually read at a time.
while (!m_requests.empty()
&& (m_send_buffer.size() < m_torrent->block_size())
&& !m_choked)
{ {
peer_request& r = m_requests.front(); peer_request& r = m_requests.front();
@ -840,23 +939,25 @@ void libtorrent::peer_connection::send_data()
m_sending_piece.read(&m_send_buffer[13], r.length); m_sending_piece.read(&m_send_buffer[13], r.length);
#if defined(TORRENT_VERBOSE_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING)
(*m_logger) << m_socket->sender().as_string() << " ==> PIECE [ idx: " << r.piece << " | s: " << r.start << " | l: " << r.length << " | dest: " << m_socket->sender().as_string() << " ]\n"; (*m_logger) << m_socket->sender().as_string() << " ==> PIECE [ idx: " << r.piece << " | s: " << r.start << " | l: " << r.length << " ]\n";
#endif #endif
// let the torrent keep track of how much we have uploaded // let the torrent keep track of how much we have uploaded
m_torrent->uploaded_bytes(r.length); m_torrent->uploaded_bytes(r.length);
m_requests.erase(m_requests.begin());
} }
else else
{ {
#if defined(TORRENT_VERBOSE_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING)
(*m_logger) << m_socket->sender().as_string() << " *** WARNING [ illegal piece request ]\n"; (*m_logger) << m_socket->sender().as_string() << " *** WARNING [ illegal piece request idx: " << r.piece << " | s: " << r.start << " | l: " << r.length << " ]\n";
#endif #endif
} }
m_requests.erase(m_requests.begin());
} }
if (!m_announce_queue.empty()) if (!m_announce_queue.empty())
{ {
for (std::vector<int>::iterator i = m_announce_queue.begin(); i != m_announce_queue.end(); ++i) for (std::vector<int>::iterator i = m_announce_queue.begin();
i != m_announce_queue.end();
++i)
{ {
// (*m_logger) << "have piece: " << *i << " sent to: " << m_socket->sender().as_string() << "\n"; // (*m_logger) << "have piece: " << *i << " sent to: " << m_socket->sender().as_string() << "\n";
send_have(*i); send_have(*i);
@ -867,12 +968,15 @@ void libtorrent::peer_connection::send_data()
// send the actual buffer // send the actual buffer
if (!m_send_buffer.empty()) if (!m_send_buffer.empty())
{ {
// we have data that's scheduled for sending
std::size_t sent = m_socket->send(&m_send_buffer[0], m_send_buffer.size());
#if defined(TORRENT_VERBOSE_LOGGING) // we have data that's scheduled for sending
int sent = m_socket->send(
&m_send_buffer[0]
, m_send_buffer.size());
#if defined(TORRENT_VERBOSE_LOGGING)
(*m_logger) << m_socket->sender().as_string() << " ==> SENT [ length: " << sent << " ]\n"; (*m_logger) << m_socket->sender().as_string() << " ==> SENT [ length: " << sent << " ]\n";
#endif #endif
if (sent > 0) if (sent > 0)
{ {
@ -882,14 +986,40 @@ void libtorrent::peer_connection::send_data()
// only a part of the buffer could be sent // only a part of the buffer could be sent
// remove the part that was sent from the buffer // remove the part that was sent from the buffer
if (sent == m_send_buffer.size()) if (sent == m_send_buffer.size())
{
m_send_buffer.clear(); m_send_buffer.clear();
}
else else
m_send_buffer.erase(m_send_buffer.begin(), m_send_buffer.begin() + sent); {
m_send_buffer.erase(
m_send_buffer.begin()
, m_send_buffer.begin() + sent);
}
}
else
{
assert(sent == -1);
throw network_error(m_socket->last_error());
} }
m_last_sent = boost::posix_time::second_clock::local_time(); m_last_sent = boost::posix_time::second_clock::local_time();
} }
assert(m_added_to_selector);
if (!has_data())
{
m_selector.remove_writable(m_socket);
m_added_to_selector = false;
}
#ifndef NDEBUG
else
{
if (m_socket->is_writable())
{
std::cout << "ERROR\n";
}
}
#endif
} }
@ -905,6 +1035,6 @@ void libtorrent::peer_connection::keep_alive()
#if defined(TORRENT_VERBOSE_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING)
(*m_logger) << m_socket->sender().as_string() << " ==> NOP\n"; (*m_logger) << m_socket->sender().as_string() << " ==> NOP\n";
#endif #endif
send_buffer_updated();
} }
} }

View File

@ -424,7 +424,7 @@ namespace libtorrent
int piece_blocks = std::min(blocks_in_piece(*i), num_blocks); int piece_blocks = std::min(blocks_in_piece(*i), num_blocks);
for (int j = 0; j < piece_blocks; ++j) for (int j = 0; j < piece_blocks; ++j)
{ {
interesting_blocks.push_back(piece_block(*i, 0)); interesting_blocks.push_back(piece_block(*i, j));
} }
num_blocks -= piece_blocks; num_blocks -= piece_blocks;
if (num_blocks == 0) return num_blocks; if (num_blocks == 0) return num_blocks;
@ -442,6 +442,8 @@ namespace libtorrent
for (int j = 0; j < num_blocks_in_piece; ++j) for (int j = 0; j < num_blocks_in_piece; ++j)
{ {
if (p->finished_blocks[j] == 1) continue;
interesting_blocks.push_back(piece_block(*i, j)); interesting_blocks.push_back(piece_block(*i, j));
if (p->requested_blocks[j] == 0) if (p->requested_blocks[j] == 0)
{ {
@ -483,13 +485,27 @@ namespace libtorrent
return i->requested_blocks[block.block_index]; return i->requested_blocks[block.block_index];
} }
bool piece_picker::is_finished(piece_block block) const
{
assert(block.piece_index < m_piece_map.size());
assert(block.block_index < max_blocks_per_piece);
if (m_piece_map[block.piece_index].index == 0xffffff) return true;
if (m_piece_map[block.piece_index].downloading == 0) return false;
std::vector<downloading_piece>::const_iterator i
= std::find_if(m_downloads.begin(), m_downloads.end(), has_index(block.piece_index));
assert(i != m_downloads.end());
return i->finished_blocks[block.block_index];
}
void piece_picker::mark_as_downloading(piece_block block, const peer_id& peer) void piece_picker::mark_as_downloading(piece_block block, const peer_id& peer)
{ {
#ifndef NDEBUG #ifndef NDEBUG
integrity_check(); integrity_check();
#endif #endif
assert(block.piece_index < m_piece_map.size()); assert(block.piece_index < m_piece_map.size());
assert(block.block_index < max_blocks_per_piece); assert(block.block_index < blocks_in_piece(block.piece_index));
piece_pos& p = m_piece_map[block.piece_index]; piece_pos& p = m_piece_map[block.piece_index];
if (p.downloading == 0) if (p.downloading == 0)
@ -517,27 +533,67 @@ namespace libtorrent
#endif #endif
} }
void piece_picker::mark_as_finished(piece_block block) void piece_picker::mark_as_finished(piece_block block, const peer_id& peer)
{ {
#ifndef NDEBUG #ifndef NDEBUG
integrity_check(); integrity_check();
#endif #endif
assert(block.piece_index < m_piece_map.size()); assert(block.piece_index < m_piece_map.size());
assert(block.block_index < max_blocks_per_piece); assert(block.block_index < blocks_in_piece(block.piece_index));
piece_pos& p = m_piece_map[block.piece_index];
if (p.downloading == 0)
{
p.downloading = 1;
move(false, p.peer_count, p.index);
downloading_piece dp;
dp.index = block.piece_index;
dp.requested_blocks[block.block_index] = 1;
dp.finished_blocks[block.block_index] = 1;
dp.info[block.block_index].peer = peer;
m_downloads.push_back(dp);
}
else
{
std::vector<downloading_piece>::iterator i
= std::find_if(m_downloads.begin(), m_downloads.end(), has_index(block.piece_index));
assert(i != m_downloads.end());
i->info[block.block_index].peer = peer;
i->requested_blocks[block.block_index] = 1;
i->finished_blocks[block.block_index] = 1;
}
#ifndef NDEBUG
integrity_check();
#endif
}
/*
void piece_picker::mark_as_finished(piece_block block, const peer_id& peer)
{
#ifndef NDEBUG
integrity_check();
#endif
assert(block.piece_index < m_piece_map.size());
assert(block.block_index < blocks_in_piece(block.piece_index));
assert(m_piece_map[block.piece_index].downloading == 1); assert(m_piece_map[block.piece_index].downloading == 1);
std::vector<downloading_piece>::iterator i std::vector<downloading_piece>::iterator i
= std::find_if(m_downloads.begin(), m_downloads.end(), has_index(block.piece_index)); = std::find_if(m_downloads.begin(), m_downloads.end(), has_index(block.piece_index));
assert(i != m_downloads.end()); assert(i != m_downloads.end());
assert(i->requested_blocks[block.block_index] == 1);
i->finished_blocks[block.block_index] = 1; i->finished_blocks[block.block_index] = 1;
// the block may have been requested, then cancled
// and requested by a peer that disconnects
// that way we can actually receive the piece
// without the requested bit is set.
i->requested_blocks[block.block_index] = 1;
i->info[block.block_index].num_downloads++; i->info[block.block_index].num_downloads++;
i->info[block.block_index].peer = peer;
#ifndef NDEBUG #ifndef NDEBUG
integrity_check(); integrity_check();
#endif #endif
} }
*/
void piece_picker::get_downloaders(std::vector<peer_id>& d, int index) void piece_picker::get_downloaders(std::vector<peer_id>& d, int index)
{ {
std::vector<downloading_piece>::iterator i std::vector<downloading_piece>::iterator i
@ -569,6 +625,10 @@ namespace libtorrent
std::vector<downloading_piece>::iterator i std::vector<downloading_piece>::iterator i
= std::find_if(m_downloads.begin(), m_downloads.end(), has_index(block.piece_index)); = std::find_if(m_downloads.begin(), m_downloads.end(), has_index(block.piece_index));
assert(i != m_downloads.end()); assert(i != m_downloads.end());
if (i->finished_blocks[block.block_index]) return;
assert(block.block_index < blocks_in_piece(block.piece_index));
assert(i->requested_blocks[block.block_index] == 1); assert(i->requested_blocks[block.block_index] == 1);
// clear this block as being downloaded // clear this block as being downloaded

View File

@ -43,20 +43,54 @@ namespace
{ {
// we try to maintain 4 requested blocks in the download // we try to maintain 4 requested blocks in the download
// queue // queue
request_queue = 4 request_queue = 16
}; };
using namespace libtorrent; using namespace libtorrent;
// TODO: replace these two functions with std::find_first_of
template<class It1, class It2>
bool has_intersection(It1 start1, It1 end1, It2 start2, It2 end2)
{
for (;start1 != end1; ++start1)
for (;start2 != end2; ++start2)
if (*start1 == *start2) return true;
return false;
}
piece_block find_first_common(const std::vector<piece_block>& queue,
const std::vector<piece_block>& busy)
{
for (std::vector<piece_block>::const_reverse_iterator i
= queue.rbegin();
i != queue.rend();
++i)
{
for (std::vector<piece_block>::const_iterator j
= busy.begin();
j != busy.end();
++j)
{
if ((*j) == (*i)) return *i;
}
}
assert(false);
}
void request_a_block(torrent& t, peer_connection& c) void request_a_block(torrent& t, peer_connection& c)
{ {
int num_requests = request_queue - c.download_queue().size();
// if our request queue is already full, we
// don't have to make any new requests yet
if (num_requests <= 0) return;
piece_picker& p = t.picker(); piece_picker& p = t.picker();
std::vector<piece_block> interesting_pieces; std::vector<piece_block> interesting_pieces;
interesting_pieces.reserve(100); interesting_pieces.reserve(100);
int num_requests = request_queue - c.download_queue().size();
if (num_requests <= 0) num_requests = 1;
// picks the interesting pieces from this peer // picks the interesting pieces from this peer
// the integer is the number of pieces that // the integer is the number of pieces that
// should be guaranteed to be available for download // should be guaranteed to be available for download
@ -85,12 +119,53 @@ namespace
// ok, we found a piece that's not being downloaded // ok, we found a piece that's not being downloaded
// by somebody else. request it from this peer // by somebody else. request it from this peer
c.request_block(*i); c.request_block(*i);
num_requests++; num_requests--;
if (num_requests >= request_queue) return; if (num_requests <= 0) return;
} }
// TODO: compare this peer's bandwidth against the if (busy_pieces.empty()) return;
// ones downloading these pieces (busy_pieces)
// first look for blocks that are just queued
// and not actually sent to us yet
// (then we can cancel those and request them
// from this peer instead)
peer_connection* peer = 0;
float down_speed = 0.f;
// find the peer with the lowest download
// speed that also has a piece thatt this
// peer could send us
for (torrent::peer_iterator i = t.begin();
i != t.end();
++i)
{
const std::vector<piece_block>& queue = (*i)->download_queue();
if ((*i)->statistics().down_peak() > down_speed
&& has_intersection(busy_pieces.begin(),
busy_pieces.end(),
queue.begin(),
queue.end()))
{
peer = *i;
down_speed = (*i)->statistics().down_peak();
}
}
assert(peer != 0);
// this peer doesn't have a faster connection than the
// slowest peer. Don't take over any blocks
if (c.statistics().down_peak() <= down_speed) return;
// find a suitable block to take over from this peer
piece_block block = find_first_common(peer->download_queue(), busy_pieces);
peer->cancel_block(block);
c.request_block(block);
// the one we interrupted may need to request a new piece
request_a_block(t, *peer);
num_requests--;
} }
} }

View File

@ -111,9 +111,6 @@ namespace libtorrent
boost::mutex::scoped_lock l(m_mutex); boost::mutex::scoped_lock l(m_mutex);
if (!t->abort) if (!t->abort)
{ {
#ifndef NDEBUG
std::cout << "adding torrent to session!\n";
#endif
boost::mutex::scoped_lock l(m_ses->m_mutex); boost::mutex::scoped_lock l(m_ses->m_mutex);
m_ses->m_torrents.insert( m_ses->m_torrents.insert(
@ -123,7 +120,7 @@ namespace libtorrent
catch(...) catch(...)
{ {
#ifndef NDEBUG #ifndef NDEBUG
std::cout << "error while checking files\n"; std::cerr << "error while checking files\n";
#endif #endif
} }
@ -199,7 +196,8 @@ namespace libtorrent
} }
catch(network_error&) catch(network_error&)
{ {
if (m_listen_port > max_port) throw; if (m_listen_port > max_port)
throw;
m_listen_port++; m_listen_port++;
continue; continue;
} }
@ -230,29 +228,15 @@ namespace libtorrent
std::vector<boost::shared_ptr<socket> > writable_clients; std::vector<boost::shared_ptr<socket> > writable_clients;
std::vector<boost::shared_ptr<socket> > error_clients; std::vector<boost::shared_ptr<socket> > error_clients;
boost::posix_time::ptime timer = boost::posix_time::second_clock::local_time(); boost::posix_time::ptime timer = boost::posix_time::second_clock::local_time();
#ifdef TORRENT_DEBUG_SOCKETS
int num_loops = 0;
#endif
for(;;) for(;;)
{ {
#ifndef NDEBUG
std::clock_t time__ = std::clock();
#endif
// if nothing happens within 500000 microseconds (0.5 seconds) // if nothing happens within 500000 microseconds (0.5 seconds)
// do the loop anyway to check if anything else has changed // do the loop anyway to check if anything else has changed
// (*m_logger) << "sleeping\n"; // (*m_logger) << "sleeping\n";
m_selector.wait(500000, readable_clients, writable_clients, error_clients); m_selector.wait(500000, readable_clients, writable_clients, error_clients);
boost::mutex::scoped_lock l(m_mutex); boost::mutex::scoped_lock l(m_mutex);
#ifdef TORRENT_DEBUG_SOCKETS
num_loops++;
#endif
assert(readable_clients.size() + writable_clients.size() + error_clients.size() > 0
|| (std::clock() - time__) > CLOCKS_PER_SEC / 3);
// +1 for the listen socket // +1 for the listen socket
assert(m_selector.count_read_monitors() == m_connections.size() + 1); assert(m_selector.count_read_monitors() == m_connections.size() + 1);
@ -301,7 +285,7 @@ namespace libtorrent
// s->set_send_bufsize(2048); // s->set_send_bufsize(2048);
// TODO: add some possibility to filter IP:s // TODO: add some possibility to filter IP:s
boost::shared_ptr<peer_connection> c(new peer_connection(this, s)); boost::shared_ptr<peer_connection> c(new peer_connection(this, m_selector, s));
m_connections.insert(std::make_pair(s, c)); m_connections.insert(std::make_pair(s, c));
m_selector.monitor_readability(s); m_selector.monitor_readability(s);
m_selector.monitor_errors(s); m_selector.monitor_errors(s);
@ -356,11 +340,6 @@ namespace libtorrent
assert(p->second->has_data()); assert(p->second->has_data());
// (*m_logger) << "writable: " << p->first->sender().as_string() << "\n"; // (*m_logger) << "writable: " << p->first->sender().as_string() << "\n";
p->second->send_data(); p->second->send_data();
// if the peer doesn't have
// any data left to send, remove it
// from the writabilty monitor
if (!p->second->has_data())
m_selector.remove_writable(p->first);
} }
catch(network_error&) catch(network_error&)
{ {
@ -396,8 +375,9 @@ namespace libtorrent
i != m_connections.end(); i != m_connections.end();
++i) ++i)
{ {
if (m_selector.is_writability_monitored(i->first)) assert(i->second->has_data() == m_selector.is_writability_monitored(i->first));
assert(i->second->has_data()); // if (m_selector.is_writability_monitored(i->first))
// assert(i->second->has_data());
} }
#endif #endif
@ -450,17 +430,6 @@ namespace libtorrent
// THE SECTION BELOW IS EXECUTED ONCE EVERY SECOND // THE SECTION BELOW IS EXECUTED ONCE EVERY SECOND
// ************************ // ************************
#ifdef TORRENT_DEBUG_SOCKETS
std::cout << "\nloops: " << num_loops << "\n";
if (num_loops > 1300)
{
int i = 0;
}
num_loops = 0;
#endif
// do the second_tick() on each connection // do the second_tick() on each connection
// this will update their statistics (download and upload speeds) // this will update their statistics (download and upload speeds)
// also purge sockets that have timed out // also purge sockets that have timed out
@ -482,9 +451,6 @@ namespace libtorrent
} }
j->second->keep_alive(); j->second->keep_alive();
if (j->second->has_data() && !m_selector.is_writability_monitored(j->first))
m_selector.monitor_writability(j->first);
} }
// check each torrent for abortion or // check each torrent for abortion or
@ -538,11 +504,11 @@ namespace libtorrent
} }
catch(const std::exception& e) catch(const std::exception& e)
{ {
std::cout << e.what() << "\n"; std::cerr << e.what() << "\n";
} }
catch(...) catch(...)
{ {
std::cout << "error\n"; std::cerr << "error\n";
} }

View File

@ -286,6 +286,7 @@ void libtorrent::piece_file::seek_forward(int step)
bool libtorrent::storage::verify_piece(piece_file& file) bool libtorrent::storage::verify_piece(piece_file& file)
{ {
int index = file.index(); int index = file.index();
assert(index >= 0 && index < m_have_piece.size());
if (m_have_piece[index]) return true; if (m_have_piece[index]) return true;
std::vector<char> buffer(m_torrent_file->piece_size(index)); std::vector<char> buffer(m_torrent_file->piece_size(index));
@ -353,7 +354,6 @@ void libtorrent::storage::initialize_pieces(torrent* t,
*/ */
// we don't know of any piece we have right now. Initialize // we don't know of any piece we have right now. Initialize
// it to say we don't have anything and fill it in later on. // it to say we don't have anything and fill it in later on.
m_have_piece.resize(m_torrent_file->num_pieces()); m_have_piece.resize(m_torrent_file->num_pieces());
@ -382,10 +382,6 @@ void libtorrent::storage::initialize_pieces(torrent* t,
char zeros[chunksize]; char zeros[chunksize];
std::fill(zeros, zeros+chunksize, 0); std::fill(zeros, zeros+chunksize, 0);
#ifndef NDEBUG
std::cout << "allocating files\n";
#endif
// remember which directories we have created, so // remember which directories we have created, so
// we don't have to ask the filesystem all the time // we don't have to ask the filesystem all the time
std::set<std::string> created_directories; std::set<std::string> created_directories;
@ -491,10 +487,6 @@ void libtorrent::storage::initialize_pieces(torrent* t,
// std::cout << "\n"; // std::cout << "\n";
} }
#ifndef NDEBUG
std::cout << "allocation/checking DONE!\n";
#endif
} }
/* /*
// reads the piece with the given index from disk // reads the piece with the given index from disk

View File

@ -143,7 +143,6 @@ namespace libtorrent
, m_bytes_uploaded(0) , m_bytes_uploaded(0)
, m_bytes_downloaded(0) , m_bytes_downloaded(0)
, m_torrent_file(torrent_file) , m_torrent_file(torrent_file)
, m_unverified_blocks(0)
, m_next_request(boost::posix_time::second_clock::local_time()) , m_next_request(boost::posix_time::second_clock::local_time())
, m_duration(1800) , m_duration(1800)
, m_policy(new policy(this)) , m_policy(new policy(this))
@ -172,6 +171,7 @@ namespace libtorrent
// connect to random peers from the list // connect to random peers from the list
std::random_shuffle(peer_list.begin(), peer_list.end()); std::random_shuffle(peer_list.begin(), peer_list.end());
std::cout << "interval: " << m_duration << "\n"; std::cout << "interval: " << m_duration << "\n";
std::cout << "peers:\n"; std::cout << "peers:\n";
for (std::vector<peer>::const_iterator i = peer_list.begin(); for (std::vector<peer>::const_iterator i = peer_list.begin();
@ -179,15 +179,8 @@ namespace libtorrent
++i) ++i)
{ {
std::cout << " " << std::setfill(' ') << std::setw(16) << i->ip std::cout << " " << std::setfill(' ') << std::setw(16) << i->ip
<< " " << std::setw(5) << std::dec << i->port << " "; << " " << std::setw(5) << std::dec << i->port << " "
for (const unsigned char* j = i->id.begin(); << i->id << " " << extract_fingerprint(i->id) << "\n";
j != i->id.end();
++j)
{
std::cout << std::hex << std::setw(2) << std::setfill('0')
<< static_cast<unsigned int>(*j);
}
std::cout << std::dec << " " << extract_fingerprint(i->id) << "\n";
} }
std::cout << std::setfill(' '); std::cout << std::setfill(' ');
@ -332,7 +325,7 @@ namespace libtorrent
if (p->has_piece(i)) peer_lost(i); if (p->has_piece(i)) peer_lost(i);
} }
std::cout << p->get_socket()->sender().as_string() << " *** DISCONNECT\n"; // std::cout << p->get_socket()->sender().as_string() << " *** DISCONNECT\n";
m_policy->connection_closed(*p); m_policy->connection_closed(*p);
m_connections.erase(i); m_connections.erase(i);
@ -348,14 +341,18 @@ namespace libtorrent
// TODO: the send buffer size should be controllable from the outside // TODO: the send buffer size should be controllable from the outside
// s->set_send_bufsize(2048); // s->set_send_bufsize(2048);
s->connect(a); s->connect(a);
boost::shared_ptr<peer_connection> c(new peer_connection(m_ses, this, s, id)); boost::shared_ptr<peer_connection> c(new peer_connection(
m_ses
, m_ses->m_selector
, this
, s
, id));
detail::session_impl::connection_map::iterator p = detail::session_impl::connection_map::iterator p =
m_ses->m_connections.insert(std::make_pair(s, c)).first; m_ses->m_connections.insert(std::make_pair(s, c)).first;
attach_peer(boost::get_pointer(p->second)); attach_peer(boost::get_pointer(p->second));
m_ses->m_selector.monitor_writability(s);
m_ses->m_selector.monitor_readability(s); m_ses->m_selector.monitor_readability(s);
m_ses->m_selector.monitor_errors(s); m_ses->m_selector.monitor_errors(s);
std::cout << "connecting to: " << a.as_string() << ":" << a.port() << "\n"; // std::cout << "connecting to: " << a.as_string() << ":" << a.port() << "\n";
} }
void torrent::close_all_connections() void torrent::close_all_connections()
@ -415,7 +412,7 @@ namespace libtorrent
int blocks_per_piece int blocks_per_piece
= m_torrent_file.piece_length() / m_block_size; = m_torrent_file.piece_length() / m_block_size;
assert(m_unverified_blocks == m_picker.unverified_blocks()); int unverified_blocks = m_picker.unverified_blocks();
int blocks_we_have = num_pieces * blocks_per_piece; int blocks_we_have = num_pieces * blocks_per_piece;
const int last_piece = m_torrent_file.num_pieces()-1; const int last_piece = m_torrent_file.num_pieces()-1;
@ -428,9 +425,12 @@ namespace libtorrent
// TODO: Implement total download and total_upload // TODO: Implement total download and total_upload
st.total_download = 0; st.total_download = 0;
st.total_upload = 0; st.total_upload = 0;
st.progress = (blocks_we_have + m_unverified_blocks) st.progress = (blocks_we_have + unverified_blocks)
/ static_cast<float>(total_blocks); / static_cast<float>(total_blocks);
st.next_announce = next_announce()
- boost::posix_time::second_clock::local_time();
if (num_pieces == p.size()) if (num_pieces == p.size())
st.state = torrent_status::seeding; st.state = torrent_status::seeding;
else else

View File

@ -72,6 +72,7 @@ namespace libtorrent
st.total_download = 0; st.total_download = 0;
st.progress = 0.f; st.progress = 0.f;
st.state = torrent_status::invalid_handle; st.state = torrent_status::invalid_handle;
st.next_announce = boost::posix_time::time_duration();
return st; return st;
} }
@ -95,6 +96,7 @@ namespace libtorrent
else else
st.state = torrent_status::queued_for_checking; st.state = torrent_status::queued_for_checking;
st.progress = d->progress; st.progress = d->progress;
st.next_announce = boost::posix_time::time_duration();
return st; return st;
} }
} }
@ -104,6 +106,7 @@ namespace libtorrent
st.total_download = 0; st.total_download = 0;
st.progress = 0.f; st.progress = 0.f;
st.state = torrent_status::invalid_handle; st.state = torrent_status::invalid_handle;
st.next_announce = boost::posix_time::time_duration();
return st; return st;
} }