*** 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>
<tr><td><tt class="literal"><span class="pre">blocks</span> <span class="pre">per</span> <span class="pre">piece</span></tt></td> <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 <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 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>
<tr><td><tt class="literal"><span class="pre">slots</span></tt></td> <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 <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; int num_peers;
std::vector<bool> pieces; const std::vector<bool>* pieces;
std::size_t total_done; 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 send and received this session, but only the actual oayload data (i.e the interesting
data), these counters ignore any protocol overhead. data), these counters ignore any protocol overhead.
``pieces`` is the bitmask that representw which pieces we have (set to true) and ``pieces`` is the bitmask that represents which pieces we have (set to true) and
the pieces we don't have. 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 ``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 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 ``upload_queue_length`` is the number of piece-requests we have received from this peer
that we haven't answered with a piece yet. that we haven't answered with a piece yet.
You can know which piece, and which part of that piece, that is currently being 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. 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. ``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 | | ``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 | | | 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 | | ``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]; 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[]) int main(int argc, char* argv[])
{ {
using namespace libtorrent; using namespace libtorrent;
@ -335,15 +345,9 @@ int main(int argc, char* argv[])
out.width(5); out.width(5);
out.fill(' '); out.fill(' ');
out << (s.progress*100) << "% "; out << (s.progress*100) << "% ";
for (int i = 0; i < 50; ++i) out << progress_bar(s.progress, 49);
{
if (i / 50.f > s.progress)
out << "-";
else
out << "#";
}
out << "\n"; out << "\n";
out << "total downloaded: " << s.total_done << " Bytes\n";
out << "peers: " << num_peers << " " out << "peers: " << num_peers << " "
<< "d:" << add_suffix(down) << "/s " << "d:" << add_suffix(down) << "/s "
<< "(" << add_suffix(total_down) << ") " << "(" << add_suffix(total_down) << ") "
@ -354,6 +358,8 @@ int main(int argc, char* argv[])
boost::posix_time::time_duration t = s.next_announce; boost::posix_time::time_duration t = s.next_announce;
out << "next announce: " << boost::posix_time::to_simple_string(t) << "\n"; out << "next announce: " << boost::posix_time::to_simple_string(t) << "\n";
out << "___________________________________\n";
for (std::vector<peer_info>::iterator i = peers.begin(); for (std::vector<peer_info>::iterator i = peers.begin();
i != peers.end(); i != peers.end();
++i) ++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::supports_extensions)?"e":"_")
<< static_cast<const char*>((i->flags & peer_info::local_connection)?"l":"r") << static_cast<const char*>((i->flags & peer_info::local_connection)?"l":"r")
<< "\n"; << "\n";
/*
if (i->downloading_piece_index >= 0) if (i->downloading_piece_index >= 0)
{ {
out.width(5);
out.fill('0');
out << i->downloading_piece_index << ";" out << i->downloading_piece_index << ";"
<< i->downloading_block_index << ": "; << i->downloading_block_index << ": ";
float progress out << progress_bar(
= i->downloading_progress i->downloading_progress / static_cast<float>(i->downloading_total)
/ static_cast<float>(i->downloading_total) , 50);
* 35;
for (int j = 0; j < 35; ++j)
{
if (progress > j) out << "#";
else out << "-";
}
out << "\n"; out << "\n";
} }
*/
} }
/*
out << "___________________________________\n"; out << "___________________________________\n";
i->get_download_queue(queue); 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) for (int j = 0; j < i->blocks_in_piece; ++j)
{ {
if (i->finished_blocks[j]) out << "#"; if (i->finished_blocks[j]) out << "#";
else if (i->requested_blocks[j]) out << "="; else if (i->requested_blocks[j]) out << "+";
else out << "."; else out << ".";
} }
out << "|\n"; out << "|\n";
} }
out << "___________________________________\n"; out << "___________________________________\n";
*/
} }
for (std::deque<std::string>::iterator i = events.begin(); for (std::deque<std::string>::iterator i = events.begin();

View File

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

View File

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

View File

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

View File

@ -101,46 +101,20 @@ namespace libtorrent
void check_invariant(); void check_invariant();
#endif #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 struct peer
{ {
peer(const peer_identification &pid); peer(const address& ip);
int total_download() const; int total_download() const;
int total_upload() const; int total_upload() const;
// the id of the peer. This is needed to store information enum connection_type { local_connection, remote_connection };
// about peers that aren't connected right now. This
// is to avoid peers reconnecting. unconnected entries
// will be saved a limited amount of time
// the ip/port pair this peer is or was connected on // the ip/port pair this peer is or was connected on
// if it was a remote (incoming) connection, type is
peer_identification id; // 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 time when this peer was optimistically unchoked
// the last time. // the last time.
@ -170,34 +144,7 @@ namespace libtorrent
peer_connection* connection; peer_connection* connection;
}; };
// predicate used to check if two peers with likelyness are the same one private:
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;
};
bool unchoke_one_peer(); bool unchoke_one_peer();
peer* find_choke_candidate(); peer* find_choke_candidate();

View File

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

View File

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

View File

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

View File

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

View File

@ -76,8 +76,7 @@ namespace libtorrent
detail::session_impl& ses detail::session_impl& ses
, selector& sel , selector& sel
, torrent* t , torrent* t
, boost::shared_ptr<libtorrent::socket> s , boost::shared_ptr<libtorrent::socket> s)
, const peer_id& p)
: m_state(read_protocol_length) : m_state(read_protocol_length)
, m_timeout(120) , m_timeout(120)
, m_packet_size(1) , m_packet_size(1)
@ -91,7 +90,6 @@ namespace libtorrent
, m_ses(ses) , m_ses(ses)
, m_active(true) , m_active(true)
, m_added_to_selector(false) , m_added_to_selector(false)
, m_peer_id(p)
, m_peer_interested(false) , m_peer_interested(false)
, m_peer_choked(true) , m_peer_choked(true)
, m_interesting(false) , m_interesting(false)
@ -113,6 +111,8 @@ namespace libtorrent
m_logger = m_ses.create_log(s->sender().as_string().c_str()); m_logger = m_ses.create_log(s->sender().as_string().c_str());
#endif #endif
std::fill(m_peer_id.begin(), m_peer_id.end(), 0);
// initialize the extension list to zero, since // initialize the extension list to zero, since
// we don't know which extensions the other // we don't know which extensions the other
// end supports yet // end supports yet
@ -165,6 +165,8 @@ namespace libtorrent
{ {
assert(!m_socket->is_blocking()); assert(!m_socket->is_blocking());
std::fill(m_peer_id.begin(), m_peer_id.end(), 0);
#ifndef NDEBUG #ifndef NDEBUG
m_logger = m_ses.create_log(s->sender().as_string().c_str()); m_logger = m_ses.create_log(s->sender().as_string().c_str());
#endif #endif
@ -696,6 +698,8 @@ namespace libtorrent
if (verified) if (verified)
{ {
m_torrent->announce_piece(p.piece); m_torrent->announce_piece(p.piece);
// TODO: if we bacame a seed, disconnect
// from all seeds
} }
else else
{ {
@ -1128,7 +1132,6 @@ namespace libtorrent
- m_statistics.total_payload_upload(); - m_statistics.total_payload_upload();
} }
void peer_connection::second_tick() void peer_connection::second_tick()
{ {
m_statistics.second_tick(); m_statistics.second_tick();
@ -1372,14 +1375,6 @@ namespace libtorrent
// info_hash and peer_id. If we do. close this connection. // 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()); 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_attached_to_torrent = true;
m_torrent->attach_peer(this); m_torrent->attach_peer(this);
assert(m_torrent->get_policy().has_connection(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 # define for if (false) {} else for
#endif #endif
namespace libtorrent
{
class peer_connection;
}
namespace namespace
{ {
enum enum
@ -261,6 +266,32 @@ namespace
} }
return free_upload; 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 namespace libtorrent
@ -366,10 +397,7 @@ namespace libtorrent
{ {
if(i->connection) continue; if(i->connection) continue;
if(i->banned) continue; if(i->banned) continue;
if(i->id.ip.port()==0) continue; if(i->type == peer::remote_connection) continue;
// TODO: Don't connect to peers that were discovered through
// remote connection, since we don't know the port.
assert(i->connected <= local_time); assert(i->connected <= local_time);
@ -510,13 +538,11 @@ namespace libtorrent
void policy::ban_peer(const peer_connection& c) void policy::ban_peer(const peer_connection& c)
{ {
address a(c.get_socket()->sender()); std::vector<peer>::iterator i = std::find_if(
if(!c.is_local()) m_peers.begin()
a=address(a.ip(),0); , m_peers.end()
peer_identification id(a,c.get_peer_id()); , 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()); assert(i != m_peers.end());
i->banned = true; i->banned = true;
@ -525,12 +551,11 @@ namespace libtorrent
void policy::new_connection(peer_connection& c) void policy::new_connection(peer_connection& c)
{ {
assert(!c.is_local()); 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()
std::vector<peer>::iterator i = , m_peers.end()
std::find_if(m_peers.begin(), m_peers.end(), peer_information_matches(pid)); , match_peer_ip(c.get_socket()->sender()));
if (i == m_peers.end()) if (i == m_peers.end())
{ {
@ -540,30 +565,33 @@ namespace libtorrent
// we don't have ny info about this peer. // we don't have ny info about this peer.
// add a new entry // add a new entry
peer p(pid); peer p(c.get_socket()->sender());
m_peers.push_back(p); m_peers.push_back(p);
i = m_peers.end()-1; i = m_peers.end()-1;
} }
else else
{ {
assert(i->connection == 0); if (i->connection != 0)
if (i->banned) throw protocol_error("ip address banned, disconnected"); throw protocol_error("duplicate connection, closing");
if (i->banned)
throw protocol_error("ip address banned, disconnected");
} }
assert(i->connection == 0);
i->connection = &c; i->connection = &c;
i->connected = boost::posix_time::second_clock::local_time(); i->connected = boost::posix_time::second_clock::local_time();
} }
void policy::peer_from_tracker(const address& remote, const peer_id& id) void policy::peer_from_tracker(const address& remote, const peer_id& id)
{ {
assert(remote.ip()!=0); assert(remote.ip() != 0);
assert(remote.port()!=0); assert(remote.port() != 0);
try try
{ {
peer_identification pid(remote,id); std::vector<peer>::iterator i = std::find_if(
m_peers.begin()
std::vector<peer>::iterator i = , m_peers.end()
std::find_if(m_peers.begin(), m_peers.end(), peer_information_matches(pid)); , match_peer_ip(remote));
if (i == m_peers.end()) if (i == m_peers.end())
{ {
@ -572,20 +600,21 @@ namespace libtorrent
// we don't have ny info about this peer. // we don't have ny info about this peer.
// add a new entry // add a new entry
peer p(pid); peer p(remote);
p.type = peer::local_connection;
m_peers.push_back(p); m_peers.push_back(p);
// the iterator is invalid
// because of the push_back()
i = m_peers.end()-1; i = m_peers.end()-1;
} }
else else
{ {
i->type = peer::local_connection;
// in case we got the ip from a remote connection, port is // in case we got the ip from a remote connection, port is
// not known, so save it. Client may also have changed port // not known, so save it. Client may also have changed port
// for some reason. // for some reason.
i->id.ip=remote; i->id = remote;
// fill in peer id if missing
if(!id.is_all_zeros())
i->id.id=id;
if (i->connection) if (i->connection)
{ {
@ -599,7 +628,7 @@ namespace libtorrent
if (i->banned) return; 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(); i->connected = boost::posix_time::second_clock::local_time();
return; return;
} }
@ -707,12 +736,12 @@ namespace libtorrent
bool policy::connect_one_peer() bool policy::connect_one_peer()
{ {
peer* p = find_connect_candidate(); peer* p = find_connect_candidate();
if (p==0) return false; if (p == 0) return false;
assert(!p->banned); assert(!p->banned);
assert(!p->connection); 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(); p->connected = boost::posix_time::second_clock::local_time();
return true; return true;
} }
@ -720,16 +749,13 @@ namespace libtorrent
// this is called whenever a peer connection is closed // this is called whenever a peer connection is closed
void policy::connection_closed(const peer_connection& c) void policy::connection_closed(const peer_connection& c)
{ {
address a(c.get_socket()->sender()); std::vector<peer>::iterator i = std::find_if(
if(!c.is_local()) m_peers.begin()
a=address(a.ip(),0); , m_peers.end()
, match_peer_connection(c));
peer_identification cid(a,c.get_peer_id()); if (i == m_peers.end()) return;
std::vector<peer>::iterator i = assert(i->connection == &c);
std::find_if(m_peers.begin(), m_peers.end(), peer_information_matches(cid));
assert(i != m_peers.end());
assert(i->connection==&c);
i->connected = boost::posix_time::second_clock::local_time(); i->connected = boost::posix_time::second_clock::local_time();
i->prev_amount_download += c.statistics().total_payload_download(); i->prev_amount_download += c.statistics().total_payload_download();
@ -768,13 +794,10 @@ namespace libtorrent
#ifndef NDEBUG #ifndef NDEBUG
bool policy::has_connection(const peer_connection* c) bool policy::has_connection(const peer_connection* c)
{ {
address a(c->get_socket()->sender()); return std::find_if(
if(!c->is_local()) m_peers.begin()
a=address(a.ip(),0); , m_peers.end()
peer_identification id(a,c->get_peer_id()); , match_peer_ip(c->get_socket()->sender())) != m_peers.end();
return m_peers.end() !=
std::find_if(m_peers.begin(), m_peers.end(), peer_information_matches(id));
} }
void policy::check_invariant() void policy::check_invariant()
@ -792,12 +815,11 @@ namespace libtorrent
} }
#endif #endif
policy::peer::peer( policy::peer::peer(const address& pid)
const peer_identification& pid)
: id(pid) : id(pid)
, type(remote_connection)
, last_optimistically_unchoked( , last_optimistically_unchoked(
boost::gregorian::date(1970,boost::gregorian::Jan,1)) 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)) , connected(boost::gregorian::date(1970,boost::gregorian::Jan,1))
, prev_amount_upload(0) , prev_amount_upload(0)
, prev_amount_download(0) , prev_amount_download(0)
@ -810,18 +832,26 @@ namespace libtorrent
int policy::peer::total_download() const int policy::peer::total_download() const
{ {
if (connection != 0) if (connection != 0)
{
return connection->statistics().total_payload_download() return connection->statistics().total_payload_download()
+ prev_amount_download; + prev_amount_download;
}
else else
{
return prev_amount_download; return prev_amount_download;
}
} }
int policy::peer::total_upload() const int policy::peer::total_upload() const
{ {
if (connection != 0) if (connection != 0)
{
return connection->statistics().total_payload_upload() return connection->statistics().total_payload_upload()
+ prev_amount_upload; + prev_amount_upload;
}
else else
{
return prev_amount_upload; return prev_amount_upload;
}
} }
} }

View File

@ -935,7 +935,7 @@ namespace libtorrent
int num_blocks_per_piece = rd.dict()["blocks per piece"].integer(); 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; return;
// the unfinished pieces // the unfinished pieces

View File

@ -465,7 +465,6 @@ namespace libtorrent {
m_pimpl->export_piece_map(p); 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) void piece_manager::impl::mark_failed(int piece_index)
{ {
// synchronization ------------------------------------------------------ // synchronization ------------------------------------------------------

View File

@ -84,9 +84,9 @@ namespace
} }
// if pieces are too large, adjust the block size // 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 // 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(); const entry::dictionary_type& info = e.dict();
@ -126,6 +126,7 @@ namespace
return ret; return ret;
} }
/*
struct find_peer_by_id struct find_peer_by_id
{ {
find_peer_by_id(const peer_id& i, const torrent* t): id(i), tor(t) {} 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 peer_id& id;
const torrent* tor; const torrent* tor;
}; };
*/
struct find_peer_by_ip struct find_peer_by_ip
{ {
find_peer_by_ip(const address& a, const torrent* t): ip(a), tor(t) {} 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 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; if (tor != c.second->associated_torrent()) return false;
return true; return true;
} }
@ -159,7 +160,6 @@ namespace
const torrent* tor; const torrent* tor;
}; };
struct peer_by_id struct peer_by_id
{ {
peer_by_id(const peer_id& i): id(i) {} peer_by_id(const peer_id& i): id(i) {}
@ -269,7 +269,7 @@ namespace libtorrent
void torrent::tracker_response(const entry& e) void torrent::tracker_response(const entry& e)
{ {
std::vector<peer> peer_list; std::vector<peer_entry> peer_list;
try try
{ {
// parse the response // parse the response
@ -289,7 +289,7 @@ namespace libtorrent
std::stringstream s; std::stringstream s;
s << "interval: " << m_duration << "\n"; s << "interval: " << m_duration << "\n";
s << "peers:\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 != peer_list.end();
++i) ++i)
{ {
@ -300,7 +300,7 @@ namespace libtorrent
debug_log(s.str()); debug_log(s.str());
#endif #endif
// for each of the peers we got from the tracker // 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 != peer_list.end();
++i) ++i)
{ {
@ -310,39 +310,22 @@ namespace libtorrent
address a(i->ip, i->port); 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); m_policy->peer_from_tracker(a, i->id);
} }
} }
catch(type_error& e) catch(type_error& e)
{ {
tracker_request_error(e.what()); tracker_request_error(-1, e.what());
} }
catch(std::runtime_error& e) catch(std::runtime_error& e)
{ {
tracker_request_error(e.what()); tracker_request_error(-1, e.what());
} }
m_got_tracker_response = true; m_got_tracker_response = true;
} }
/*
bool torrent::has_peer(const peer_id& id) const bool torrent::has_peer(const peer_id& id) const
{ {
assert(std::count_if(m_connections.begin() assert(std::count_if(m_connections.begin()
@ -360,21 +343,77 @@ namespace libtorrent
, peer_by_id(id)) , peer_by_id(id))
!= m_connections.end(); != m_connections.end();
} }
*/
torrent::size_type torrent::bytes_left() const torrent::size_type torrent::bytes_left() const
{ {
size_type have_bytes = m_num_pieces * m_torrent_file.piece_length(); return m_torrent_file.total_size() - bytes_done();
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;
} }
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) void torrent::piece_failed(int index)
{ {
@ -422,7 +461,6 @@ namespace libtorrent
m_picker.restore_piece(index); m_picker.restore_piece(index);
m_storage.mark_failed(index); m_storage.mark_failed(index);
// TODO: make sure restore_piece() works
assert(m_have_pieces[index] == false); assert(m_have_pieces[index] == false);
} }
@ -446,32 +484,6 @@ namespace libtorrent
m_picker.we_have(index); m_picker.we_have(index);
for (peer_iterator i = m_connections.begin(); i != m_connections.end(); ++i) for (peer_iterator i = m_connections.begin(); i != m_connections.end(); ++i)
i->second->announce_piece(index); 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) std::string torrent::generate_tracker_request(int port)
@ -515,7 +527,7 @@ namespace libtorrent
return request; 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"); entry::dictionary_type::const_iterator i = e.dict().find("failure reason");
if (i != e.dict().end()) if (i != e.dict().end())
@ -537,7 +549,7 @@ namespace libtorrent
const entry::list_type& l = i->second.list(); const entry::list_type& l = i->second.list();
for(entry::list_type::const_iterator i = l.begin(); i != l.end(); ++i) 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); peer_list.push_back(p);
} }
} }
@ -585,7 +597,7 @@ namespace libtorrent
#endif #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)); boost::shared_ptr<socket> s(new socket(socket::tcp, false));
s->connect(a); s->connect(a);
@ -593,8 +605,7 @@ namespace libtorrent
m_ses m_ses
, m_ses.m_selector , m_ses.m_selector
, this , this
, s , s));
, id));
if (m_ses.m_upload_rate != -1) c->set_send_quota(0); if (m_ses.m_upload_rate != -1) c->set_send_quota(0);
@ -753,25 +764,14 @@ namespace libtorrent
torrent_status torrent::status() const torrent_status torrent::status() const
{ {
assert(std::accumulate(
m_have_pieces.begin()
, m_have_pieces.end()
, 0) == m_num_pieces);
torrent_status st; torrent_status st;
const std::vector<bool>& p = m_have_pieces; st.total_done = bytes_done();
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;
}
// payload transfer // payload transfer
st.total_payload_download = m_stat.total_payload_download(); st.total_payload_download = m_stat.total_payload_download();
@ -787,23 +787,19 @@ namespace libtorrent
st.download_rate = m_stat.download_rate(); st.download_rate = m_stat.download_rate();
st.upload_rate = m_stat.upload_rate(); st.upload_rate = m_stat.upload_rate();
st.progress = (blocks_we_have + unverified_blocks) st.progress = st.total_done
/ static_cast<float>(total_blocks); / static_cast<float>(m_torrent_file.total_size());
st.next_announce = next_announce() st.next_announce = next_announce()
- boost::posix_time::second_clock::local_time(); - boost::posix_time::second_clock::local_time();
st.num_peers = m_connections.size(); st.num_peers = m_connections.size();
// TODO: this is not accurate because it assumes the last st.pieces = &m_have_pieces;
// 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;
if (m_got_tracker_response == false) if (m_got_tracker_response == false)
st.state = torrent_status::connecting_to_tracker; 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; st.state = torrent_status::seeding;
else else
st.state = torrent_status::downloading; st.state = torrent_status::downloading;
@ -837,7 +833,7 @@ namespace libtorrent
// with some codes, we should just consider // with some codes, we should just consider
// the tracker as a failure and not retry // the tracker as a failure and not retry
// it anymore // it anymore
void torrent::tracker_request_error(const char* str) void torrent::tracker_request_error(int response_code, const char* str)
{ {
#ifndef NDEBUG #ifndef NDEBUG
debug_log(std::string("*** tracker error: ") + str); debug_log(std::string("*** tracker error: ") + str);

View File

@ -51,10 +51,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/hasher.hpp" #include "libtorrent/hasher.hpp"
#include "libtorrent/entry.hpp" #include "libtorrent/entry.hpp"
#include "libtorrent/session.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 #if defined(_MSC_VER) && _MSC_VER < 1300
namespace std namespace std
@ -121,8 +117,6 @@ namespace libtorrent
st.state = torrent_status::queued_for_checking; st.state = torrent_status::queued_for_checking;
st.progress = d->progress; st.progress = d->progress;
st.next_announce = boost::posix_time::time_duration(); st.next_announce = boost::posix_time::time_duration();
st.pieces.clear();
st.pieces.resize(d->torrent_ptr->torrent_file().num_pieces(), false);
return st; return st;
} }
} }