diff --git a/docs/manual.html b/docs/manual.html
index f2f0ff795..9a84eb5cb 100755
--- a/docs/manual.html
+++ b/docs/manual.html
@@ -1321,9 +1321,10 @@ not trust the fast-resume data and just do the checking.
slots |
list of integers. The list mappes slots ti piece indices. It
diff --git a/docs/manual.rst b/docs/manual.rst
index 9cf7c6b56..d4bdc0573 100755
--- a/docs/manual.rst
+++ b/docs/manual.rst
@@ -559,7 +559,7 @@ It contains the following fields::
int num_peers;
- std::vector pieces;
+ const std::vector* 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 |
diff --git a/examples/client_test.cpp b/examples/client_test.cpp
index 78a789c4d..2cd22d5f6 100755
--- a/examples/client_test.cpp
+++ b/examples/client_test.cpp
@@ -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 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::iterator i = peers.begin();
i != peers.end();
++i)
@@ -375,25 +381,20 @@ int main(int argc, char* argv[])
<< static_cast((i->flags & peer_info::supports_extensions)?"e":"_")
<< static_cast((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(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(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::iterator i = events.begin();
diff --git a/include/libtorrent/peer.hpp b/include/libtorrent/peer.hpp
index 2825cccc8..1585c05cf 100755
--- a/include/libtorrent/peer.hpp
+++ b/include/libtorrent/peer.hpp
@@ -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;
}
diff --git a/include/libtorrent/peer_connection.hpp b/include/libtorrent/peer_connection.hpp
index 8ba26be76..8573024a9 100755
--- a/include/libtorrent/peer_connection.hpp
+++ b/include/libtorrent/peer_connection.hpp
@@ -199,8 +199,7 @@ namespace libtorrent
detail::session_impl& ses
, selector& sel
, torrent* t
- , boost::shared_ptr s
- , const peer_id& p);
+ , boost::shared_ptr s);
// with this constructor we have been contacted and we still don't know which torrent the
// connection belongs to
diff --git a/include/libtorrent/piece_picker.hpp b/include/libtorrent/piece_picker.hpp
index b49c72147..fba4e7f14 100755
--- a/include/libtorrent/piece_picker.hpp
+++ b/include/libtorrent/piece_picker.hpp
@@ -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
diff --git a/include/libtorrent/policy.hpp b/include/libtorrent/policy.hpp
index 51ae7a6ae..0e14ac186 100755
--- a/include/libtorrent/policy.hpp
+++ b/include/libtorrent/policy.hpp
@@ -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();
diff --git a/include/libtorrent/session.hpp b/include/libtorrent/session.hpp
index 417eb946f..1dc13662f 100755
--- a/include/libtorrent/session.hpp
+++ b/include/libtorrent/session.hpp
@@ -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()
diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp
index e83c02063..bdf809b7f 100755
--- a/include/libtorrent/torrent.hpp
+++ b/include/libtorrent/torrent.hpp
@@ -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::iterator peer_iterator;
typedef std::map::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_list);
+ void parse_response(const entry& e, std::vector& peer_list);
torrent_info m_torrent_file;
diff --git a/include/libtorrent/torrent_handle.hpp b/include/libtorrent/torrent_handle.hpp
index 042edb1d5..51b618dc1 100755
--- a/include/libtorrent/torrent_handle.hpp
+++ b/include/libtorrent/torrent_handle.hpp
@@ -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 pieces;
+ const std::vector* pieces;
// the number of bytes of the file we have
- std::size_t total_done;
+ size_type total_done;
};
struct partial_piece_info
diff --git a/src/alert.cpp b/src/alert.cpp
index 07dc8afe2..fdae1a2e6 100755
--- a/src/alert.cpp
+++ b/src/alert.cpp
@@ -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())
diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp
index cd944b380..0853be309 100755
--- a/src/peer_connection.cpp
+++ b/src/peer_connection.cpp
@@ -76,8 +76,7 @@ namespace libtorrent
detail::session_impl& ses
, selector& sel
, torrent* t
- , boost::shared_ptr s
- , const peer_id& p)
+ , boost::shared_ptr 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));
diff --git a/src/policy.cpp b/src/policy.cpp
index 1a84818e7..268915031 100755
--- a/src/policy.cpp
+++ b/src/policy.cpp
@@ -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::iterator i = std::find_if(
+ m_peers.begin()
+ , m_peers.end()
+ , match_peer_connection(c));
- std::vector::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::iterator i =
- std::find_if(m_peers.begin(), m_peers.end(), peer_information_matches(pid));
+ std::vector::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::iterator i =
- std::find_if(m_peers.begin(), m_peers.end(), peer_information_matches(pid));
+ std::vector::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::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::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;
+ }
}
}
diff --git a/src/session.cpp b/src/session.cpp
index 0cfa03217..c4667754b 100755
--- a/src/session.cpp
+++ b/src/session.cpp
@@ -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
diff --git a/src/storage.cpp b/src/storage.cpp
index d103dd291..f8ce41f30 100755
--- a/src/storage.cpp
+++ b/src/storage.cpp
@@ -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 ------------------------------------------------------
diff --git a/src/torrent.cpp b/src/torrent.cpp
index d34861b62..991ca9366 100755
--- a/src/torrent.cpp
+++ b/src/torrent.cpp
@@ -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_list;
+ std::vector 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::const_iterator i = peer_list.begin();
+ for (std::vector::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::iterator i = peer_list.begin();
+ for (std::vector::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& dl_queue
+ = m_picker.get_download_queue();
+
+ const int blocks_per_piece = m_torrent_file.piece_length() / m_block_size;
+
+ for (std::vector::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 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_list)
+ void torrent::parse_response(const entry& e, std::vector& 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 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& 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(total_blocks);
+ st.progress = st.total_done
+ / static_cast(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);
diff --git a/src/torrent_handle.cpp b/src/torrent_handle.cpp
index 9012927a4..013eba4c0 100755
--- a/src/torrent_handle.cpp
+++ b/src/torrent_handle.cpp
@@ -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;
}
}
|