From bb71832f5ff3356bc2b902b0c607e332e6a4aa50 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Fri, 25 May 2007 19:42:10 +0000 Subject: [PATCH] exposed some more peer info --- examples/client_test.cpp | 19 ++- include/libtorrent/bt_peer_connection.hpp | 2 +- include/libtorrent/peer_connection.hpp | 28 ++--- include/libtorrent/peer_info.hpp | 17 ++- include/libtorrent/policy.hpp | 20 ++++ include/libtorrent/web_peer_connection.hpp | 2 +- src/bt_peer_connection.cpp | 62 +--------- src/peer_connection.cpp | 133 ++++++++++++++++----- src/policy.cpp | 5 +- src/torrent.cpp | 7 +- src/web_peer_connection.cpp | 55 +-------- 11 files changed, 173 insertions(+), 177 deletions(-) diff --git a/examples/client_test.cpp b/examples/client_test.cpp index 5b09c940e..6c905fe0d 100644 --- a/examples/client_test.cpp +++ b/examples/client_test.cpp @@ -269,7 +269,7 @@ int peer_index(libtorrent::tcp::endpoint addr, std::vector const& peers) { using namespace libtorrent; - out << " down (total) up (total) q r flags source fail block-progress " + out << " down (total) up (total) que req flags source fail hshf sndb inactive wait block-progress " #ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES "country " #endif @@ -287,20 +287,27 @@ void print_peer_info(std::ostream& out, std::vector const << "(" << add_suffix(i->total_download) << ") " << esc("0") << esc("31") << (i->up_speed > 0 ? add_suffix(i->up_speed) + "/s ": " ") << "(" << add_suffix(i->total_upload) << ") " << esc("0") - << to_string(i->download_queue_length, 2) << " " - << to_string(i->upload_queue_length, 2) << " " + << to_string(i->download_queue_length, 3) << " " + << to_string(i->upload_queue_length, 3) << " " << ((i->flags & peer_info::interesting)?'I':'.') << ((i->flags & peer_info::choked)?'C':'.') << ((i->flags & peer_info::remote_interested)?'i':'.') << ((i->flags & peer_info::remote_choked)?'c':'.') << ((i->flags & peer_info::supports_extensions)?'e':'.') - << ((i->flags & peer_info::local_connection)?'l':'r') << " " + << ((i->flags & peer_info::local_connection)?'l':'r') + << ((i->flags & peer_info::seed)?'s':'.') + << ((i->flags & peer_info::on_parole)?'p':'.') + << " " << ((i->source & peer_info::tracker)?"T":"_") << ((i->source & peer_info::pex)?"P":"_") << ((i->source & peer_info::dht)?"D":"_") << ((i->source & peer_info::lsd)?"L":"_") - << ((i->source & peer_info::resume_data)?"R":"_") << " "; - out << to_string(i->failcount, 4) << " "; + << ((i->source & peer_info::resume_data)?"R":"_") << " " + << to_string(i->failcount, 4) << " " + << to_string(i->num_hashfails, 4) << " " + << to_string(i->send_buffer_size, 4) << " " + << to_string(total_seconds(i->last_active), 8) << " " + << to_string(total_seconds(i->last_request), 4) << " "; if (i->downloading_piece_index >= 0) { diff --git a/include/libtorrent/bt_peer_connection.hpp b/include/libtorrent/bt_peer_connection.hpp index 223bf2650..bd2e9e88b 100755 --- a/include/libtorrent/bt_peer_connection.hpp +++ b/include/libtorrent/bt_peer_connection.hpp @@ -130,7 +130,7 @@ namespace libtorrent void on_receive(asio::error_code const& error , std::size_t bytes_transferred); - virtual void get_peer_info(peer_info& p) const; + virtual void get_specific_peer_info(peer_info& p) const; virtual bool in_handshake() const; #ifndef TORRENT_DISABLE_EXTENSIONS diff --git a/include/libtorrent/peer_connection.hpp b/include/libtorrent/peer_connection.hpp index 9b3de295c..d1ae9c93a 100755 --- a/include/libtorrent/peer_connection.hpp +++ b/include/libtorrent/peer_connection.hpp @@ -174,9 +174,6 @@ namespace libtorrent void set_non_prioritized(bool b) { m_non_prioritized = b; } - bool on_parole() const - { return m_on_parole; } - // this adds an announcement in the announcement queue // it will let the peer know that we have the given piece void announce_piece(int index); @@ -209,6 +206,8 @@ namespace libtorrent void update_interest(); + virtual void get_peer_info(peer_info& p) const; + // returns the torrent this connection is a part of // may be zero if the connection is an incoming connection // and it hasn't received enough information to determine @@ -264,7 +263,6 @@ namespace libtorrent // trust management. void received_valid_data(int index); void received_invalid_data(int index); - int trust_points() const; size_type share_diff() const; @@ -335,7 +333,6 @@ namespace libtorrent ptime m_last_choke; #endif - virtual void get_peer_info(peer_info& p) const = 0; // is true until we can be sure that the other end // speaks our protocol (be it bittorrent or http). @@ -371,6 +368,8 @@ namespace libtorrent protected: + virtual void get_specific_peer_info(peer_info& p) const = 0; + virtual void write_choke() = 0; virtual void write_unchoke() = 0; virtual void write_interested() = 0; @@ -475,6 +474,9 @@ namespace libtorrent // the time when we last got a part of a // piece packet from this peer ptime m_last_piece; + // the time we sent a request to + // this peer the last time + ptime m_last_request; int m_packet_size; int m_recv_pos; @@ -582,14 +584,6 @@ namespace libtorrent // that we give the free upload, to keep the balance. size_type m_free_upload; - // for every valid piece we receive where this - // peer was one of the participants, we increase - // this value. For every invalid piece we receive - // where this peer was a participant, we decrease - // this value. If it sinks below a threshold, its - // considered a bad peer and will be banned. - int m_trust_points; - // if this is true, this peer is assumed to handle all piece // requests in fifo order. All skipped blocks are re-requested // immediately instead of having a looser requirement @@ -645,14 +639,6 @@ namespace libtorrent // are preferred. bool m_prefer_whole_pieces; - // if this is true, the peer has previously participated - // in a piece that failed the piece hash check. This will - // put the peer on parole and only request entire pieces. - // if a piece pass that was partially requested from this - // peer it will leave parole mode and continue download - // pieces as normal peers. - bool m_on_parole; - // if this is true, the blocks picked by the piece // picker will be merged before passed to the // request function. i.e. subsequent blocks are diff --git a/include/libtorrent/peer_info.hpp b/include/libtorrent/peer_info.hpp index 86480ba11..467055c94 100755 --- a/include/libtorrent/peer_info.hpp +++ b/include/libtorrent/peer_info.hpp @@ -54,7 +54,9 @@ namespace libtorrent local_connection = 0x20, handshake = 0x40, connecting = 0x80, - queued = 0x100 + queued = 0x100, + on_parole = 0x200, + seed = 0x400 }; unsigned int flags; @@ -79,10 +81,21 @@ namespace libtorrent size_type total_upload; peer_id pid; std::vector pieces; - bool seed; // true if this is a seed int upload_limit; int download_limit; + // time since last request + time_duration last_request; + + // time since last download or upload + time_duration last_active; + + // the size of the send buffer for this peer + int send_buffer_size; + + // the number of failed hashes for this peer + int num_hashfails; + #ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES // in case the session settings is set // to resolve countries, this is set to diff --git a/include/libtorrent/policy.hpp b/include/libtorrent/policy.hpp index 4fa04cb32..7aae27299 100755 --- a/include/libtorrent/policy.hpp +++ b/include/libtorrent/policy.hpp @@ -138,6 +138,10 @@ namespace libtorrent // the number of failed connection attempts this peer has int failcount; + // the number of times this peer has been + // part of a piece that failed the hash check + int hashfails; + // this is true if the peer is a seed bool seed; @@ -149,6 +153,22 @@ namespace libtorrent // or disconnected if it isn't connected right now libtorrent::ptime connected; + // for every valid piece we receive where this + // peer was one of the participants, we increase + // this value. For every invalid piece we receive + // where this peer was a participant, we decrease + // this value. If it sinks below a threshold, its + // considered a bad peer and will be banned. + int trust_points; + + // if this is true, the peer has previously participated + // in a piece that failed the piece hash check. This will + // put the peer on parole and only request entire pieces. + // if a piece pass that was partially requested from this + // peer it will leave parole mode and continue download + // pieces as normal peers. + bool on_parole; + // this is the accumulated amount of // uploaded and downloaded data to this // peer. It only accounts for what was diff --git a/include/libtorrent/web_peer_connection.hpp b/include/libtorrent/web_peer_connection.hpp index 690066fb2..a84f2e6ff 100755 --- a/include/libtorrent/web_peer_connection.hpp +++ b/include/libtorrent/web_peer_connection.hpp @@ -111,7 +111,7 @@ namespace libtorrent std::string const& url() const { return m_url; } - virtual void get_peer_info(peer_info& p) const; + virtual void get_specific_peer_info(peer_info& p) const; virtual bool in_handshake() const; // the following functions appends messages diff --git a/src/bt_peer_connection.cpp b/src/bt_peer_connection.cpp index 082d856aa..1a59eeab2 100755 --- a/src/bt_peer_connection.cpp +++ b/src/bt_peer_connection.cpp @@ -179,56 +179,10 @@ namespace libtorrent setup_send(); } - void bt_peer_connection::get_peer_info(peer_info& p) const + void bt_peer_connection::get_specific_peer_info(peer_info& p) const { assert(!associated_torrent().expired()); - p.down_speed = statistics().download_rate(); - p.up_speed = statistics().upload_rate(); - p.payload_down_speed = statistics().download_payload_rate(); - p.payload_up_speed = statistics().upload_payload_rate(); - p.pid = pid(); - p.ip = remote(); - -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - p.country[0] = m_country[0]; - p.country[1] = m_country[1]; -#endif - - p.total_download = statistics().total_payload_download(); - p.total_upload = statistics().total_payload_upload(); - - if (m_bandwidth_limit[upload_channel].throttle() == bandwidth_limit::inf) - p.upload_limit = -1; - else - p.upload_limit = m_bandwidth_limit[upload_channel].throttle(); - - if (m_bandwidth_limit[download_channel].throttle() == bandwidth_limit::inf) - p.download_limit = -1; - else - p.download_limit = m_bandwidth_limit[download_channel].throttle(); - - p.load_balancing = total_free_upload(); - - p.download_queue_length = (int)download_queue().size(); - p.upload_queue_length = (int)upload_queue().size(); - - if (boost::optional ret = downloading_piece_progress()) - { - p.downloading_piece_index = ret->piece_index; - p.downloading_block_index = ret->block_index; - p.downloading_progress = ret->bytes_downloaded; - p.downloading_total = ret->full_block_bytes; - } - else - { - p.downloading_piece_index = -1; - p.downloading_block_index = -1; - p.downloading_progress = 0; - p.downloading_total = 0; - } - - p.flags = 0; if (is_interesting()) p.flags |= peer_info::interesting; if (is_choked()) p.flags |= peer_info::choked; if (is_peer_interested()) p.flags |= peer_info::remote_interested; @@ -240,23 +194,9 @@ namespace libtorrent if (is_connecting() && !is_queued()) p.flags |= peer_info::connecting; if (is_queued()) p.flags |= peer_info::queued; - p.pieces = get_bitfield(); - p.seed = is_seed(); - p.client = m_client_version; p.connection_type = peer_info::standard_bittorrent; - if (peer_info_struct()) - { - p.source = peer_info_struct()->source; - p.failcount = peer_info_struct()->failcount; - } - else - { - assert(!is_local()); - p.source = 0; - p.failcount = 0; - } } bool bt_peer_connection::in_handshake() const diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index 7ba83e889..7eb56921b 100755 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -90,6 +90,7 @@ namespace libtorrent , m_max_out_request_queue(m_ses.settings().max_out_request_queue) , m_timeout(m_ses.settings().peer_timeout) , m_last_piece(time_now()) + , m_last_request(time_now()) , m_packet_size(0) , m_recv_pos(0) , m_current_send_buffer(0) @@ -109,7 +110,6 @@ namespace libtorrent , m_num_pieces(0) , m_desired_queue_size(2) , m_free_upload(0) - , m_trust_points(0) , m_assume_fifo(false) , m_num_invalid_requests(0) , m_disconnecting(false) @@ -120,7 +120,6 @@ namespace libtorrent , m_writing(false) , m_reading(false) , m_prefer_whole_pieces(false) - , m_on_parole(false) , m_request_large_blocks(false) , m_non_prioritized(false) , m_refs(0) @@ -164,6 +163,7 @@ namespace libtorrent , m_max_out_request_queue(m_ses.settings().max_out_request_queue) , m_timeout(m_ses.settings().peer_timeout) , m_last_piece(time_now()) + , m_last_request(time_now()) , m_packet_size(0) , m_recv_pos(0) , m_current_send_buffer(0) @@ -181,7 +181,6 @@ namespace libtorrent , m_num_pieces(0) , m_desired_queue_size(2) , m_free_upload(0) - , m_trust_points(0) , m_assume_fifo(false) , m_num_invalid_requests(0) , m_disconnecting(false) @@ -192,7 +191,6 @@ namespace libtorrent , m_writing(false) , m_reading(false) , m_prefer_whole_pieces(false) - , m_on_parole(false) , m_request_large_blocks(false) , m_non_prioritized(false) , m_refs(0) @@ -405,11 +403,14 @@ namespace libtorrent } #endif - m_on_parole = false; - - m_trust_points++; - // TODO: make this limit user settable - if (m_trust_points > 20) m_trust_points = 20; + if (peer_info_struct()) + { + peer_info_struct()->on_parole = false; + int& trust_points = peer_info_struct()->trust_points; + trust_points++; + // TODO: make this limit user settable + if (trust_points > 20) trust_points = 20; + } } void peer_connection::received_invalid_data(int index) @@ -424,20 +425,20 @@ namespace libtorrent } #endif - m_on_parole = true; + if (peer_info_struct()) + { + peer_info_struct()->on_parole = true; + ++peer_info_struct()->hashfails; + int& trust_points = peer_info_struct()->trust_points; - // we decrease more than we increase, to keep the - // allowed failed/passed ratio low. - // TODO: make this limit user settable - m_trust_points -= 2; - if (m_trust_points < -7) m_trust_points = -7; + // we decrease more than we increase, to keep the + // allowed failed/passed ratio low. + // TODO: make this limit user settable + trust_points -= 2; + if (trust_points < -7) trust_points = -7; + } } - int peer_connection::trust_points() const - { - return m_trust_points; - } - size_type peer_connection::total_free_upload() const { return m_free_upload; @@ -1557,9 +1558,14 @@ namespace libtorrent { if (handled = (*i)->write_request(r)) break; } - if (!handled) write_request(r); + if (!handled) + { + write_request(r); + m_last_request = time_now(); + } #else write_request(r); + m_last_request = time_now(); #endif #ifdef TORRENT_VERBOSE_LOGGING @@ -1678,6 +1684,81 @@ namespace libtorrent return false; } + void peer_connection::get_peer_info(peer_info& p) const + { + assert(!associated_torrent().expired()); + + p.down_speed = statistics().download_rate(); + p.up_speed = statistics().upload_rate(); + p.payload_down_speed = statistics().download_payload_rate(); + p.payload_up_speed = statistics().upload_payload_rate(); + p.pid = pid(); + p.ip = remote(); + +#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES + p.country[0] = m_country[0]; + p.country[1] = m_country[1]; +#endif + + p.total_download = statistics().total_payload_download(); + p.total_upload = statistics().total_payload_upload(); + + if (m_bandwidth_limit[upload_channel].throttle() == bandwidth_limit::inf) + p.upload_limit = -1; + else + p.upload_limit = m_bandwidth_limit[upload_channel].throttle(); + + if (m_bandwidth_limit[download_channel].throttle() == bandwidth_limit::inf) + p.download_limit = -1; + else + p.download_limit = m_bandwidth_limit[download_channel].throttle(); + + p.load_balancing = total_free_upload(); + + p.download_queue_length = (int)download_queue().size(); + p.upload_queue_length = (int)upload_queue().size(); + + if (boost::optional ret = downloading_piece_progress()) + { + p.downloading_piece_index = ret->piece_index; + p.downloading_block_index = ret->block_index; + p.downloading_progress = ret->bytes_downloaded; + p.downloading_total = ret->full_block_bytes; + } + else + { + p.downloading_piece_index = -1; + p.downloading_block_index = -1; + p.downloading_progress = 0; + p.downloading_total = 0; + } + + p.pieces = get_bitfield(); + ptime now = time_now(); + p.last_request = now - m_last_request; + p.last_active = now - std::max(m_last_sent, m_last_receive); + + // this will set the flags so that we can update them later + p.flags = 0; + get_specific_peer_info(p); + + p.flags |= is_seed() ? peer_info::seed : 0; + if (peer_info_struct()) + { + p.source = peer_info_struct()->source; + p.failcount = peer_info_struct()->failcount; + p.num_hashfails = peer_info_struct()->hashfails; + p.flags |= peer_info_struct()->on_parole ? peer_info::on_parole : 0; + } + else + { + p.source = 0; + p.failcount = 0; + p.num_hashfails = 0; + } + + p.send_buffer_size = send_buffer_size(); + } void peer_connection::cut_receive_buffer(int size, int packet_size) { @@ -2131,10 +2212,6 @@ namespace libtorrent assert(m_reading); m_reading = false; -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << "read " << bytes_transferred << " bytes\n"; -#endif - if (error) { #ifdef TORRENT_VERBOSE_LOGGING @@ -2146,6 +2223,9 @@ namespace libtorrent do { +#ifdef TORRENT_VERBOSE_LOGGING + (*m_logger) << "read " << bytes_transferred << " bytes\n"; +#endif // correct the dl quota usage, if not all of the buffer was actually read if (!m_ignore_bandwidth_limits) m_bandwidth_limit[download_channel].use_quota(bytes_transferred); @@ -2185,9 +2265,6 @@ namespace libtorrent , max_receive), ec); if (ec && ec != asio::error::would_block) throw asio::system_error(ec); -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << "read_some " << bytes_transferred << " bytes\n"; -#endif } while (bytes_transferred > 0); diff --git a/src/policy.cpp b/src/policy.cpp index bba04f429..7f7f42008 100755 --- a/src/policy.cpp +++ b/src/policy.cpp @@ -187,7 +187,7 @@ namespace libtorrent interesting_pieces.reserve(100); bool prefer_whole_pieces = c.prefer_whole_pieces() - || c.on_parole(); + || (c.peer_info_struct() && c.peer_info_struct()->on_parole); if (!prefer_whole_pieces) { @@ -1394,9 +1394,12 @@ namespace libtorrent : ip(ip_) , type(t) , failcount(0) + , hashfails(0) , seed(false) , last_optimistically_unchoked(min_time()) , connected(min_time()) + , trust_points(0) + , on_parole(false) , prev_amount_upload(0) , prev_amount_download(0) , banned(false) diff --git a/src/torrent.cpp b/src/torrent.cpp index 7310c7b78..408102d2e 100755 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -903,13 +903,16 @@ namespace libtorrent , end(peers.end()); i != end; ++i) { peer_iterator p = m_connections.find(*i); + peer_connection& peer = *p->second; if (p == m_connections.end()) continue; - p->second->received_invalid_data(index); + peer.received_invalid_data(index); // either, we have received too many failed hashes // or this was the only peer that sent us this piece. // TODO: make this a changable setting - if (p->second->trust_points() <= -7 || peers.size() == 1) + if ((peer.peer_info_struct() + && peer.peer_info_struct()->trust_points <= -7) + || peers.size() == 1) { // we don't trust this peer anymore // ban it. diff --git a/src/web_peer_connection.cpp b/src/web_peer_connection.cpp index bbe7c6e66..5a8acf512 100755 --- a/src/web_peer_connection.cpp +++ b/src/web_peer_connection.cpp @@ -592,56 +592,8 @@ namespace libtorrent } } - void web_peer_connection::get_peer_info(peer_info& p) const + void web_peer_connection::get_specific_peer_info(peer_info& p) const { - assert(!associated_torrent().expired()); - - p.down_speed = statistics().download_rate(); - p.up_speed = statistics().upload_rate(); - p.payload_down_speed = statistics().download_payload_rate(); - p.payload_up_speed = statistics().upload_payload_rate(); - p.pid = pid(); - p.ip = remote(); - -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - p.country[0] = m_country[0]; - p.country[1] = m_country[1]; -#endif - - p.total_download = statistics().total_payload_download(); - p.total_upload = statistics().total_payload_upload(); - - if (m_bandwidth_limit[upload_channel].throttle() == bandwidth_limit::inf) - p.upload_limit = -1; - else - p.upload_limit = m_bandwidth_limit[upload_channel].throttle(); - - if (m_bandwidth_limit[download_channel].throttle() == bandwidth_limit::inf) - p.download_limit = -1; - else - p.download_limit = m_bandwidth_limit[download_channel].throttle(); - - p.load_balancing = total_free_upload(); - - p.download_queue_length = (int)download_queue().size(); - p.upload_queue_length = (int)upload_queue().size(); - - if (boost::optional ret = downloading_piece_progress()) - { - p.downloading_piece_index = ret->piece_index; - p.downloading_block_index = ret->block_index; - p.downloading_progress = ret->bytes_downloaded; - p.downloading_total = ret->full_block_bytes; - } - else - { - p.downloading_piece_index = -1; - p.downloading_block_index = -1; - p.downloading_progress = 0; - p.downloading_total = 0; - } - - p.flags = 0; if (is_interesting()) p.flags |= peer_info::interesting; if (is_choked()) p.flags |= peer_info::choked; if (is_peer_interested()) p.flags |= peer_info::remote_interested; @@ -651,14 +603,9 @@ namespace libtorrent p.flags |= peer_info::handshake; if (is_connecting() && !is_queued()) p.flags |= peer_info::connecting; if (is_queued()) p.flags |= peer_info::queued; - - p.pieces = get_bitfield(); - p.seed = is_seed(); p.client = m_server_string; p.connection_type = peer_info::web_seed; - p.source = 0; - p.failcount = 0; } bool web_peer_connection::in_handshake() const