*** empty log message ***

This commit is contained in:
Arvid Norberg 2004-01-15 16:45:34 +00:00
parent 1fba488c4d
commit 410b35f95e
17 changed files with 251 additions and 281 deletions

View File

@ -1321,9 +1321,10 @@ not trust the fast-resume data and just do the checking.</p>
</tr>
<tr><td><tt class="literal"><span class="pre">blocks</span> <span class="pre">per</span> <span class="pre">piece</span></tt></td>
<td>integer, the number of blocks per piece. Must be: piece_size
/ (16 * 1024). Clamped to be within the range [1, 128]. It
/ (16 * 1024). Clamped to be within the range [1, 256]. It
is the number of blocks per (normal sized) piece. Usually
each block is 16 * 1024 bytes in size.</td>
each block is 16 * 1024 bytes in size. But if piece size is
greater than 4 megabytes, the block size will increase.</td>
</tr>
<tr><td><tt class="literal"><span class="pre">slots</span></tt></td>
<td><p class="first">list of integers. The list mappes slots ti piece indices. It

View File

@ -559,7 +559,7 @@ It contains the following fields::
int num_peers;
std::vector<bool> pieces;
const std::vector<bool>* pieces;
std::size_t total_done;
};
@ -601,8 +601,9 @@ uploaded to all peers, accumulated, *this session* only.
send and received this session, but only the actual oayload data (i.e the interesting
data), these counters ignore any protocol overhead.
``pieces`` is the bitmask that representw which pieces we have (set to true) and
the pieces we don't have.
``pieces`` is the bitmask that represents which pieces we have (set to true) and
the pieces we don't have. It's a pointer and may be set to 0 if the torrent isn't
downloading or seeding.
``download_rate`` and ``upload_rate`` are the total rates for all peers for this
torrent. These will usually have better precision than summing the rates from
@ -750,7 +751,6 @@ that hasn't been answered with a piece yet.
``upload_queue_length`` is the number of piece-requests we have received from this peer
that we haven't answered with a piece yet.
You can know which piece, and which part of that piece, that is currently being
downloaded from a specific peer by looking at the next four members.
``downloading_piece_index`` is the index of the piece that is currently being downloaded.
@ -1401,9 +1401,10 @@ The file format is a bencoded dictionary containing the following fields:
| | |
+----------------------+--------------------------------------------------------------+
| ``blocks per piece`` | integer, the number of blocks per piece. Must be: piece_size |
| | / (16 * 1024). Clamped to be within the range [1, 128]. It |
| | / (16 * 1024). Clamped to be within the range [1, 256]. It |
| | is the number of blocks per (normal sized) piece. Usually |
| | each block is 16 * 1024 bytes in size. |
| | each block is 16 * 1024 bytes in size. But if piece size is |
| | greater than 4 megabytes, the block size will increase. |
| | |
+----------------------+--------------------------------------------------------------+
| ``slots`` | list of integers. The list mappes slots ti piece indices. It |

View File

@ -194,6 +194,16 @@ std::string add_suffix(float val)
return to_string(val, 6) + prefix[i];
}
std::string progress_bar(float progress, int width)
{
std::vector<char> bar;
bar.reserve(width);
std::fill_n(std::back_inserter(bar), progress * width, '#');
std::fill_n(std::back_inserter(bar), width - (progress * width), '-');
return std::string(bar.begin(), bar.end());
}
int main(int argc, char* argv[])
{
using namespace libtorrent;
@ -335,15 +345,9 @@ int main(int argc, char* argv[])
out.width(5);
out.fill(' ');
out << (s.progress*100) << "% ";
for (int i = 0; i < 50; ++i)
{
if (i / 50.f > s.progress)
out << "-";
else
out << "#";
}
out << progress_bar(s.progress, 49);
out << "\n";
out << "total downloaded: " << s.total_done << " Bytes\n";
out << "peers: " << num_peers << " "
<< "d:" << add_suffix(down) << "/s "
<< "(" << add_suffix(total_down) << ") "
@ -354,6 +358,8 @@ int main(int argc, char* argv[])
boost::posix_time::time_duration t = s.next_announce;
out << "next announce: " << boost::posix_time::to_simple_string(t) << "\n";
out << "___________________________________\n";
for (std::vector<peer_info>::iterator i = peers.begin();
i != peers.end();
++i)
@ -375,25 +381,20 @@ int main(int argc, char* argv[])
<< static_cast<const char*>((i->flags & peer_info::supports_extensions)?"e":"_")
<< static_cast<const char*>((i->flags & peer_info::local_connection)?"l":"r")
<< "\n";
/*
if (i->downloading_piece_index >= 0)
{
out.width(5);
out.fill('0');
out << i->downloading_piece_index << ";"
<< i->downloading_block_index << ": ";
float progress
= i->downloading_progress
/ static_cast<float>(i->downloading_total)
* 35;
for (int j = 0; j < 35; ++j)
{
if (progress > j) out << "#";
else out << "-";
}
out << progress_bar(
i->downloading_progress / static_cast<float>(i->downloading_total)
, 50);
out << "\n";
}
*/
}
/*
out << "___________________________________\n";
i->get_download_queue(queue);
@ -407,14 +408,14 @@ int main(int argc, char* argv[])
for (int j = 0; j < i->blocks_in_piece; ++j)
{
if (i->finished_blocks[j]) out << "#";
else if (i->requested_blocks[j]) out << "=";
else if (i->requested_blocks[j]) out << "+";
else out << ".";
}
out << "|\n";
}
out << "___________________________________\n";
*/
}
for (std::deque<std::string>::iterator i = events.begin();

View File

@ -40,18 +40,18 @@ POSSIBILITY OF SUCH DAMAGE.
namespace libtorrent
{
struct peer
struct peer_entry
{
std::string ip;
int port;
peer_id id;
bool operator==(const peer& p) const
bool operator==(const peer_entry& p) const
{
return id == p.id;
}
bool operator<(const peer& p) const
bool operator<(const peer_entry& p) const
{
return id < p.id;
}

View File

@ -199,8 +199,7 @@ namespace libtorrent
detail::session_impl& ses
, selector& sel
, torrent* t
, boost::shared_ptr<libtorrent::socket> s
, const peer_id& p);
, boost::shared_ptr<libtorrent::socket> s);
// with this constructor we have been contacted and we still don't know which torrent the
// connection belongs to

View File

@ -69,7 +69,7 @@ namespace libtorrent
{
public:
enum { max_blocks_per_piece = 128 };
enum { max_blocks_per_piece = 256 };
struct block_info
{
@ -189,6 +189,9 @@ namespace libtorrent
int index;
};
int blocks_in_last_piece() const
{ return m_blocks_in_last_piece; }
private:
struct piece_pos

View File

@ -101,46 +101,20 @@ namespace libtorrent
void check_invariant();
#endif
private:
// TODO: for the moment the peer_id is never updated
// when we get it from the peer. It's kindof useless
// in here right now.
struct peer_identification
{
peer_identification()
: ip(0,0)
{
id.set_to_all_zero();
}
peer_identification(address a, const peer_id &p)
: ip(a)
, id(p)
{
}
// If this info comes from a remote connection,
// port should be set to 0 to denote that the port is unknown.
address ip;
peer_id id;
};
struct peer
{
peer(const peer_identification &pid);
peer(const address& ip);
int total_download() const;
int total_upload() const;
// the id of the peer. This is needed to store information
// about peers that aren't connected right now. This
// is to avoid peers reconnecting. unconnected entries
// will be saved a limited amount of time
enum connection_type { local_connection, remote_connection };
// the ip/port pair this peer is or was connected on
peer_identification id;
// if it was a remote (incoming) connection, type is
// set thereafter. If it was a peer we got from the
// tracker, type is set to local_connection.
address id;
connection_type type;
// the time when this peer was optimistically unchoked
// the last time.
@ -170,34 +144,7 @@ namespace libtorrent
peer_connection* connection;
};
// predicate used to check if two peers with likelyness are the same one
struct peer_information_matches
{
peer_information_matches(const peer_identification &id)
: this_id(id)
{
}
bool operator()(const peer&other_peer) const
{
return operator()(other_peer.id);
}
bool operator()(const peer_identification &other_id) const
{
return
this_id.ip.ip() == other_id.ip.ip()
// && (
// this_id.ip.port() == other_id.ip.port()
// || ((this_id.ip.port() == 0) ^ (other_id.ip.port() == 0)) // one of them unknown
// )
&& (
this_id.id == other_id.id
|| (this_id.id.is_all_zeros() ^ other_id.id.is_all_zeros()) // one of them unknown
);
}
peer_identification this_id;
};
private:
bool unchoke_one_peer();
peer* find_choke_candidate();

View File

@ -85,7 +85,7 @@ namespace libtorrent
// workaround for microsofts
// hardware exceptions that makes
// it hard to debug stuff
#if !defined(NDEBUG) && defined(MSC_VER)
#if !defined(NDEBUG) && defined(_MSC_VER)
struct eh_initializer
{
eh_initializer()

View File

@ -143,12 +143,11 @@ namespace libtorrent
stat statistics() const { return m_stat; }
size_type bytes_left() const;
size_type bytes_done() const;
torrent_status status() const;
peer_connection& connect_to_peer(
const address& a
, const peer_id& id);
peer_connection& connect_to_peer(const address& a);
const torrent_info& torrent_file() const
{ return m_torrent_file; }
@ -174,6 +173,7 @@ namespace libtorrent
// this will remove the peer and make sure all
// the pieces it had have their reference counter
// decreased in the piece_picker
// called from the peer_connection destructor
void remove_peer(peer_connection* p);
peer_connection* connection_for(const address& a)
@ -188,7 +188,7 @@ namespace libtorrent
// returns true if this torrent has a connection
// to a peer with the given peer_id
bool has_peer(const peer_id& id) const;
// bool has_peer(const peer_id& id) const;
typedef std::map<address, peer_connection*>::iterator peer_iterator;
typedef std::map<address, peer_connection*>::const_iterator const_peer_iterator;
@ -207,7 +207,7 @@ namespace libtorrent
// when this torrent got a response from its tracker request
virtual void tracker_response(const entry& e);
virtual void tracker_request_timed_out();
virtual void tracker_request_error(const char* str);
virtual void tracker_request_error(int response_code, const char* str);
// generates a request string for sending
// to the tracker
@ -305,7 +305,7 @@ namespace libtorrent
event_id m_event;
void parse_response(const entry& e, std::vector<peer>& peer_list);
void parse_response(const entry& e, std::vector<peer_entry>& peer_list);
torrent_info m_torrent_file;

View File

@ -63,6 +63,8 @@ namespace libtorrent
struct torrent_status
{
typedef entry::integer_type size_type;
torrent_status()
: state(queued_for_checking)
, progress(0.f)
@ -73,6 +75,7 @@ namespace libtorrent
, download_rate(0)
, upload_rate(0)
, num_peers(0)
, pieces(0)
, total_done(0)
{}
@ -91,12 +94,12 @@ namespace libtorrent
// transferred this session!
// total, payload plus protocol
std::size_t total_download;
std::size_t total_upload;
size_type total_download;
size_type total_upload;
// payload only
std::size_t total_payload_download;
std::size_t total_payload_upload;
size_type total_payload_download;
size_type total_payload_upload;
// current transfer rate
// payload plus protocol
@ -107,10 +110,10 @@ namespace libtorrent
// is connected to.
int num_peers;
std::vector<bool> pieces;
const std::vector<bool>* pieces;
// the number of bytes of the file we have
std::size_t total_done;
size_type total_done;
};
struct partial_piece_info

View File

@ -49,6 +49,7 @@ namespace libtorrent {
void alert_manager::post_alert(const alert& alert_)
{
// TODO: have an internal buffer limit
boost::mutex::scoped_lock lock(m_mutex);
if (m_severity <= alert_.severity())

View File

@ -76,8 +76,7 @@ namespace libtorrent
detail::session_impl& ses
, selector& sel
, torrent* t
, boost::shared_ptr<libtorrent::socket> s
, const peer_id& p)
, boost::shared_ptr<libtorrent::socket> s)
: m_state(read_protocol_length)
, m_timeout(120)
, m_packet_size(1)
@ -91,7 +90,6 @@ namespace libtorrent
, m_ses(ses)
, m_active(true)
, m_added_to_selector(false)
, m_peer_id(p)
, m_peer_interested(false)
, m_peer_choked(true)
, m_interesting(false)
@ -113,6 +111,8 @@ namespace libtorrent
m_logger = m_ses.create_log(s->sender().as_string().c_str());
#endif
std::fill(m_peer_id.begin(), m_peer_id.end(), 0);
// initialize the extension list to zero, since
// we don't know which extensions the other
// end supports yet
@ -165,6 +165,8 @@ namespace libtorrent
{
assert(!m_socket->is_blocking());
std::fill(m_peer_id.begin(), m_peer_id.end(), 0);
#ifndef NDEBUG
m_logger = m_ses.create_log(s->sender().as_string().c_str());
#endif
@ -696,6 +698,8 @@ namespace libtorrent
if (verified)
{
m_torrent->announce_piece(p.piece);
// TODO: if we bacame a seed, disconnect
// from all seeds
}
else
{
@ -1128,7 +1132,6 @@ namespace libtorrent
- m_statistics.total_payload_upload();
}
void peer_connection::second_tick()
{
m_statistics.second_tick();
@ -1372,14 +1375,6 @@ namespace libtorrent
// info_hash and peer_id. If we do. close this connection.
std::copy(m_recv_buffer.begin(), m_recv_buffer.begin() + 20, (char*)m_peer_id.begin());
if (m_torrent->has_peer(m_peer_id))
{
#ifndef NDEBUG
(*m_logger) << " duplicate connection, closing\n";
#endif
throw protocol_error("duplicate connection, closing");
}
m_attached_to_torrent = true;
m_torrent->attach_peer(this);
assert(m_torrent->get_policy().has_connection(this));

View File

@ -47,6 +47,11 @@ POSSIBILITY OF SUCH DAMAGE.
# define for if (false) {} else for
#endif
namespace libtorrent
{
class peer_connection;
}
namespace
{
enum
@ -261,6 +266,32 @@ namespace
}
return free_upload;
}
struct match_peer_ip
{
match_peer_ip(const address& id)
: m_id(id)
{}
bool operator()(const policy::peer& p) const
{ return p.id.ip() == m_id.ip(); }
address m_id;
};
struct match_peer_connection
{
match_peer_connection(const peer_connection& c)
: m_conn(c)
{}
bool operator()(const policy::peer& p) const
{ return p.connection == &m_conn; }
const peer_connection& m_conn;
};
}
namespace libtorrent
@ -366,10 +397,7 @@ namespace libtorrent
{
if(i->connection) continue;
if(i->banned) continue;
if(i->id.ip.port()==0) continue;
// TODO: Don't connect to peers that were discovered through
// remote connection, since we don't know the port.
if(i->type == peer::remote_connection) continue;
assert(i->connected <= local_time);
@ -510,13 +538,11 @@ namespace libtorrent
void policy::ban_peer(const peer_connection& c)
{
address a(c.get_socket()->sender());
if(!c.is_local())
a=address(a.ip(),0);
peer_identification id(a,c.get_peer_id());
std::vector<peer>::iterator i = std::find_if(
m_peers.begin()
, m_peers.end()
, match_peer_connection(c));
std::vector<peer>::iterator i =
std::find_if(m_peers.begin(), m_peers.end(), peer_information_matches(id));
assert(i != m_peers.end());
i->banned = true;
@ -525,12 +551,11 @@ namespace libtorrent
void policy::new_connection(peer_connection& c)
{
assert(!c.is_local());
assert(!c.get_peer_id().is_all_zeros());
peer_identification pid(address(c.get_socket()->sender().ip(),0),c.get_peer_id());
std::vector<peer>::iterator i =
std::find_if(m_peers.begin(), m_peers.end(), peer_information_matches(pid));
std::vector<peer>::iterator i = std::find_if(
m_peers.begin()
, m_peers.end()
, match_peer_ip(c.get_socket()->sender()));
if (i == m_peers.end())
{
@ -540,30 +565,33 @@ namespace libtorrent
// we don't have ny info about this peer.
// add a new entry
peer p(pid);
peer p(c.get_socket()->sender());
m_peers.push_back(p);
i = m_peers.end()-1;
}
else
{
assert(i->connection == 0);
if (i->banned) throw protocol_error("ip address banned, disconnected");
if (i->connection != 0)
throw protocol_error("duplicate connection, closing");
if (i->banned)
throw protocol_error("ip address banned, disconnected");
}
assert(i->connection == 0);
i->connection = &c;
i->connected = boost::posix_time::second_clock::local_time();
}
void policy::peer_from_tracker(const address& remote, const peer_id& id)
{
assert(remote.ip()!=0);
assert(remote.port()!=0);
assert(remote.ip() != 0);
assert(remote.port() != 0);
try
{
peer_identification pid(remote,id);
std::vector<peer>::iterator i =
std::find_if(m_peers.begin(), m_peers.end(), peer_information_matches(pid));
std::vector<peer>::iterator i = std::find_if(
m_peers.begin()
, m_peers.end()
, match_peer_ip(remote));
if (i == m_peers.end())
{
@ -572,20 +600,21 @@ namespace libtorrent
// we don't have ny info about this peer.
// add a new entry
peer p(pid);
peer p(remote);
p.type = peer::local_connection;
m_peers.push_back(p);
// the iterator is invalid
// because of the push_back()
i = m_peers.end()-1;
}
else
{
i->type = peer::local_connection;
// in case we got the ip from a remote connection, port is
// not known, so save it. Client may also have changed port
// for some reason.
i->id.ip=remote;
// fill in peer id if missing
if(!id.is_all_zeros())
i->id.id=id;
i->id = remote;
if (i->connection)
{
@ -599,7 +628,7 @@ namespace libtorrent
if (i->banned) return;
i->connection = &m_torrent->connect_to_peer(remote, id);
i->connection = &m_torrent->connect_to_peer(remote);
i->connected = boost::posix_time::second_clock::local_time();
return;
}
@ -707,12 +736,12 @@ namespace libtorrent
bool policy::connect_one_peer()
{
peer* p = find_connect_candidate();
if (p==0) return false;
if (p == 0) return false;
assert(!p->banned);
assert(!p->connection);
assert(p->id.ip.port()!=0);
assert(p->type != peer::remote_connection);
p->connection = &m_torrent->connect_to_peer(p->id.ip, p->id.id);
p->connection = &m_torrent->connect_to_peer(p->id);
p->connected = boost::posix_time::second_clock::local_time();
return true;
}
@ -720,16 +749,13 @@ namespace libtorrent
// this is called whenever a peer connection is closed
void policy::connection_closed(const peer_connection& c)
{
address a(c.get_socket()->sender());
if(!c.is_local())
a=address(a.ip(),0);
std::vector<peer>::iterator i = std::find_if(
m_peers.begin()
, m_peers.end()
, match_peer_connection(c));
peer_identification cid(a,c.get_peer_id());
std::vector<peer>::iterator i =
std::find_if(m_peers.begin(), m_peers.end(), peer_information_matches(cid));
assert(i != m_peers.end());
assert(i->connection==&c);
if (i == m_peers.end()) return;
assert(i->connection == &c);
i->connected = boost::posix_time::second_clock::local_time();
i->prev_amount_download += c.statistics().total_payload_download();
@ -768,13 +794,10 @@ namespace libtorrent
#ifndef NDEBUG
bool policy::has_connection(const peer_connection* c)
{
address a(c->get_socket()->sender());
if(!c->is_local())
a=address(a.ip(),0);
peer_identification id(a,c->get_peer_id());
return m_peers.end() !=
std::find_if(m_peers.begin(), m_peers.end(), peer_information_matches(id));
return std::find_if(
m_peers.begin()
, m_peers.end()
, match_peer_ip(c->get_socket()->sender())) != m_peers.end();
}
void policy::check_invariant()
@ -792,12 +815,11 @@ namespace libtorrent
}
#endif
policy::peer::peer(
const peer_identification& pid)
policy::peer::peer(const address& pid)
: id(pid)
, type(remote_connection)
, last_optimistically_unchoked(
boost::gregorian::date(1970,boost::gregorian::Jan,1))
//, connected(boost::posix_time::second_clock::local_time())
, connected(boost::gregorian::date(1970,boost::gregorian::Jan,1))
, prev_amount_upload(0)
, prev_amount_download(0)
@ -810,18 +832,26 @@ namespace libtorrent
int policy::peer::total_download() const
{
if (connection != 0)
{
return connection->statistics().total_payload_download()
+ prev_amount_download;
}
else
{
return prev_amount_download;
}
}
int policy::peer::total_upload() const
{
if (connection != 0)
{
return connection->statistics().total_payload_upload()
+ prev_amount_upload;
}
else
{
return prev_amount_upload;
}
}
}

View File

@ -935,7 +935,7 @@ namespace libtorrent
int num_blocks_per_piece = rd.dict()["blocks per piece"].integer();
if (num_blocks_per_piece > 128 || num_blocks_per_piece < 1)
if (num_blocks_per_piece != info.piece_length() / torrent_ptr->block_size())
return;
// the unfinished pieces

View File

@ -465,7 +465,6 @@ namespace libtorrent {
m_pimpl->export_piece_map(p);
}
// TODO: daniel, make sure this function does everything it needs to do
void piece_manager::impl::mark_failed(int piece_index)
{
// synchronization ------------------------------------------------------

View File

@ -84,9 +84,9 @@ namespace
}
// if pieces are too large, adjust the block size
if (i.piece_length() / default_block_size > 128)
if (i.piece_length() / default_block_size > piece_picker::max_blocks_per_piece)
{
return i.piece_length() / 128;
return i.piece_length() / piece_picker::max_blocks_per_piece;
}
// otherwise, go with the default
@ -94,9 +94,9 @@ namespace
}
peer extract_peer_info(const entry& e)
peer_entry extract_peer_info(const entry& e)
{
peer ret;
peer_entry ret;
const entry::dictionary_type& info = e.dict();
@ -126,6 +126,7 @@ namespace
return ret;
}
/*
struct find_peer_by_id
{
find_peer_by_id(const peer_id& i, const torrent* t): id(i), tor(t) {}
@ -143,14 +144,14 @@ namespace
const peer_id& id;
const torrent* tor;
};
*/
struct find_peer_by_ip
{
find_peer_by_ip(const address& a, const torrent* t): ip(a), tor(t) {}
bool operator()(const detail::session_impl::connection_map::value_type& c) const
{
if (c.first->sender() != ip) return false;
if (c.first->sender().ip() != ip.ip()) return false;
if (tor != c.second->associated_torrent()) return false;
return true;
}
@ -159,7 +160,6 @@ namespace
const torrent* tor;
};
struct peer_by_id
{
peer_by_id(const peer_id& i): id(i) {}
@ -269,7 +269,7 @@ namespace libtorrent
void torrent::tracker_response(const entry& e)
{
std::vector<peer> peer_list;
std::vector<peer_entry> peer_list;
try
{
// parse the response
@ -289,7 +289,7 @@ namespace libtorrent
std::stringstream s;
s << "interval: " << m_duration << "\n";
s << "peers:\n";
for (std::vector<peer>::const_iterator i = peer_list.begin();
for (std::vector<peer_entry>::const_iterator i = peer_list.begin();
i != peer_list.end();
++i)
{
@ -300,7 +300,7 @@ namespace libtorrent
debug_log(s.str());
#endif
// for each of the peers we got from the tracker
for (std::vector<peer>::iterator i = peer_list.begin();
for (std::vector<peer_entry>::iterator i = peer_list.begin();
i != peer_list.end();
++i)
{
@ -310,39 +310,22 @@ namespace libtorrent
address a(i->ip, i->port);
// if we aleady have a connection to the person, don't make another one
if (std::find_if(
m_ses.m_connections.begin()
, m_ses.m_connections.end()
, find_peer_by_id(i->id, this)) != m_ses.m_connections.end())
{
continue;
}
if (std::find_if(
m_ses.m_connections.begin()
, m_ses.m_connections.end()
, find_peer_by_ip(a, this)) != m_ses.m_connections.end())
{
continue;
}
m_policy->peer_from_tracker(a, i->id);
}
}
catch(type_error& e)
{
tracker_request_error(e.what());
tracker_request_error(-1, e.what());
}
catch(std::runtime_error& e)
{
tracker_request_error(e.what());
tracker_request_error(-1, e.what());
}
m_got_tracker_response = true;
}
/*
bool torrent::has_peer(const peer_id& id) const
{
assert(std::count_if(m_connections.begin()
@ -360,21 +343,77 @@ namespace libtorrent
, peer_by_id(id))
!= m_connections.end();
}
*/
torrent::size_type torrent::bytes_left() const
{
size_type have_bytes = m_num_pieces * m_torrent_file.piece_length();
int last_piece = m_torrent_file.num_pieces()-1;
if (m_have_pieces[last_piece])
{
have_bytes -= m_torrent_file.piece_length()
- m_torrent_file.piece_size(last_piece);
}
return m_torrent_file.total_size()
- have_bytes;
return m_torrent_file.total_size() - bytes_done();
}
torrent::size_type torrent::bytes_done() const
{
const int last_piece = m_torrent_file.num_pieces()-1;
torrent::size_type total_done
= m_num_pieces * m_torrent_file.piece_length();
// if we have the last piece, we have to correct
// the amount we have, since the first calculation
// assumed all pieces were of equal size
if (m_have_pieces[last_piece])
{
total_done -= m_torrent_file.piece_length();
total_done += m_torrent_file.piece_size(last_piece);
}
const std::vector<piece_picker::downloading_piece>& dl_queue
= m_picker.get_download_queue();
const int blocks_per_piece = m_torrent_file.piece_length() / m_block_size;
for (std::vector<piece_picker::downloading_piece>::const_iterator i =
dl_queue.begin();
i != dl_queue.end();
++i)
{
assert(!m_have_pieces[i->index]);
for (int j = 0; j < blocks_per_piece; ++j)
{
total_done += (i->finished_blocks[j]) * m_block_size;
}
// correction if this was the last piece
// and if we have the last block
if (i->index == last_piece
&& i->finished_blocks[m_picker.blocks_in_last_piece()-1])
{
total_done -= m_block_size;
total_done += m_torrent_file.piece_size(last_piece) % m_block_size;
}
}
// TODO: may report too much if two peers are downloading
// the same block
for (const_peer_iterator i = begin();
i != end();
++i)
{
boost::optional<piece_block_progress> p
= i->second->downloading_piece();
if (p)
{
if (m_have_pieces[p->piece_index])
continue;
if (m_picker.is_finished(piece_block(p->piece_index, p->block_index)))
continue;
total_done += p->bytes_downloaded;
assert(p->bytes_downloaded <= p->full_block_bytes);
}
}
return total_done;
}
void torrent::piece_failed(int index)
{
@ -422,7 +461,6 @@ namespace libtorrent
m_picker.restore_piece(index);
m_storage.mark_failed(index);
// TODO: make sure restore_piece() works
assert(m_have_pieces[index] == false);
}
@ -446,32 +484,6 @@ namespace libtorrent
m_picker.we_have(index);
for (peer_iterator i = m_connections.begin(); i != m_connections.end(); ++i)
i->second->announce_piece(index);
// if we became a seed, disconnect from all other seeds
if (is_seed())
{
for (peer_iterator i = m_connections.begin();
i != m_connections.end();)
{
assert(i->second->associated_torrent() == this);
if (!i->second->is_seed()) continue;
detail::session_impl::connection_map::iterator j =
m_ses.m_connections.find(i->second->get_socket());
assert(j != m_ses.m_connections.end());
// in the destructor of the peer_connection
// it will remove itself from this torrent
// and from the list we're iterating over.
// so we need to increment the iterator riht
// away.
++i;
m_ses.m_connections.erase(j);
}
}
}
std::string torrent::generate_tracker_request(int port)
@ -515,7 +527,7 @@ namespace libtorrent
return request;
}
void torrent::parse_response(const entry& e, std::vector<peer>& peer_list)
void torrent::parse_response(const entry& e, std::vector<peer_entry>& peer_list)
{
entry::dictionary_type::const_iterator i = e.dict().find("failure reason");
if (i != e.dict().end())
@ -537,7 +549,7 @@ namespace libtorrent
const entry::list_type& l = i->second.list();
for(entry::list_type::const_iterator i = l.begin(); i != l.end(); ++i)
{
peer p = extract_peer_info(*i);
peer_entry p = extract_peer_info(*i);
peer_list.push_back(p);
}
}
@ -585,7 +597,7 @@ namespace libtorrent
#endif
}
peer_connection& torrent::connect_to_peer(const address& a, const peer_id& id)
peer_connection& torrent::connect_to_peer(const address& a)
{
boost::shared_ptr<socket> s(new socket(socket::tcp, false));
s->connect(a);
@ -593,8 +605,7 @@ namespace libtorrent
m_ses
, m_ses.m_selector
, this
, s
, id));
, s));
if (m_ses.m_upload_rate != -1) c->set_send_quota(0);
@ -753,25 +764,14 @@ namespace libtorrent
torrent_status torrent::status() const
{
assert(std::accumulate(
m_have_pieces.begin()
, m_have_pieces.end()
, 0) == m_num_pieces);
torrent_status st;
const std::vector<bool>& p = m_have_pieces;
assert(std::accumulate(p.begin(), p.end(), 0) == m_num_pieces);
int total_blocks
= (m_torrent_file.total_size()+m_block_size-1)/m_block_size;
int blocks_per_piece
= m_torrent_file.piece_length() / m_block_size;
int unverified_blocks = m_picker.unverified_blocks();
int blocks_we_have = m_num_pieces * blocks_per_piece;
const int last_piece = m_torrent_file.num_pieces()-1;
if (p[last_piece])
{
blocks_we_have += m_picker.blocks_in_piece(last_piece)
- blocks_per_piece;
}
st.total_done = bytes_done();
// payload transfer
st.total_payload_download = m_stat.total_payload_download();
@ -787,23 +787,19 @@ namespace libtorrent
st.download_rate = m_stat.download_rate();
st.upload_rate = m_stat.upload_rate();
st.progress = (blocks_we_have + unverified_blocks)
/ static_cast<float>(total_blocks);
st.progress = st.total_done
/ static_cast<float>(m_torrent_file.total_size());
st.next_announce = next_announce()
- boost::posix_time::second_clock::local_time();
st.num_peers = m_connections.size();
// TODO: this is not accurate because it assumes the last
// block is m_block_size bytes
// TODO: st.pieces could be a const pointer maybe?
st.total_done = (blocks_we_have + unverified_blocks) * m_block_size;
st.pieces = m_have_pieces;
st.pieces = &m_have_pieces;
if (m_got_tracker_response == false)
st.state = torrent_status::connecting_to_tracker;
else if (m_num_pieces == p.size())
else if (m_num_pieces == m_have_pieces.size())
st.state = torrent_status::seeding;
else
st.state = torrent_status::downloading;
@ -837,7 +833,7 @@ namespace libtorrent
// with some codes, we should just consider
// the tracker as a failure and not retry
// it anymore
void torrent::tracker_request_error(const char* str)
void torrent::tracker_request_error(int response_code, const char* str)
{
#ifndef NDEBUG
debug_log(std::string("*** tracker error: ") + str);

View File

@ -51,10 +51,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/hasher.hpp"
#include "libtorrent/entry.hpp"
#include "libtorrent/session.hpp"
// TODO: peer_connection is only used because of detail::write_int
// and detail::read_int, they should probably be moved to a common
// header.
#include "libtorrent/peer_connection.hpp"
#if defined(_MSC_VER) && _MSC_VER < 1300
namespace std
@ -121,8 +117,6 @@ namespace libtorrent
st.state = torrent_status::queued_for_checking;
st.progress = d->progress;
st.next_announce = boost::posix_time::time_duration();
st.pieces.clear();
st.pieces.resize(d->torrent_ptr->torrent_file().num_pieces(), false);
return st;
}
}