*** empty log message ***
This commit is contained in:
parent
1fba488c4d
commit
410b35f95e
|
@ -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
|
||||
|
|
|
@ -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 |
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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));
|
||||
|
|
128
src/policy.cpp
128
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<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,16 +565,19 @@ 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();
|
||||
}
|
||||
|
@ -560,10 +588,10 @@ namespace libtorrent
|
|||
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;
|
||||
}
|
||||
|
@ -710,9 +739,9 @@ namespace libtorrent
|
|||
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,15 +749,12 @@ 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());
|
||||
if (i == m_peers.end()) return;
|
||||
assert(i->connection == &c);
|
||||
|
||||
i->connected = boost::posix_time::second_clock::local_time();
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ------------------------------------------------------
|
||||
|
|
184
src/torrent.cpp
184
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> 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;
|
||||
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])
|
||||
{
|
||||
have_bytes -= m_torrent_file.piece_length()
|
||||
- m_torrent_file.piece_size(last_piece);
|
||||
total_done -= m_torrent_file.piece_length();
|
||||
total_done += m_torrent_file.piece_size(last_piece);
|
||||
}
|
||||
|
||||
return m_torrent_file.total_size()
|
||||
- have_bytes;
|
||||
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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue