From 492565b979eeb07491632ca07dc1752f4d7e81ae Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Sun, 12 Sep 2004 10:12:16 +0000 Subject: [PATCH] *** empty log message *** --- docs/manual.html | 31 +++++++------ docs/manual.rst | 34 +++++++------- include/libtorrent/alert_types.hpp | 3 ++ include/libtorrent/bencode.hpp | 4 -- include/libtorrent/torrent.hpp | 10 +++- include/libtorrent/torrent_handle.hpp | 3 ++ include/libtorrent/torrent_info.hpp | 6 +-- src/torrent.cpp | 66 +++++++++++++++++++++------ src/torrent_handle.cpp | 16 +++++++ src/torrent_info.cpp | 24 ++-------- 10 files changed, 119 insertions(+), 78 deletions(-) diff --git a/docs/manual.html b/docs/manual.html index 10ace1e2c..9e964b499 100755 --- a/docs/manual.html +++ b/docs/manual.html @@ -39,7 +39,7 @@
  • begin_files() end_files() rbegin_files() rend_files()
  • num_files() file_at()
  • print()
  • -
  • trackers() prioritize_tracker()
  • +
  • trackers()
  • total_size() piece_length() piece_size() num_pieces()
  • hash_for_piece() info_hash()
  • name() comment() creation_date()
  • @@ -635,7 +635,7 @@ class torrent_info { public: - torrent_info(const entry& torrent_file) + torrent_info(entry const& torrent_file) torrent_info(int piece_size, const char* name); entry create_torrent() const; @@ -645,7 +645,7 @@ public: void add_tracker(std::string const& url, int tier = 0); void add_file(boost::filesystem::path file, size_type size); - typedef std::vector>file_entry>::const_iterator file_iterator; + typedef std::vector<file_entry>::const_iterator file_iterator; typedef std::vector<file_entry>::const_reverse_iterator reverse_file_iterator; file_iterator begin_files() const; @@ -654,11 +654,9 @@ public: reverse_file_iterator rend_files() const; int num_files() const; - const file_entry& file_at(int index) const; + file_entry const& file_at(int index) const; - const std::vector<announce_entry>& trackers() const; - - int prioritize_tracker(int index); + std::vector<announce_entry> const& trackers() const; size_type total_size() const; size_type piece_length() const; @@ -720,12 +718,11 @@ void print(std::ostream& os) const;

    The print() function is there for debug purposes only. It will print the info from the torrent file to the given outstream.

    -
    -

    trackers() prioritize_tracker()

    +
    +

    trackers()

     const std::vector<announce_entry>& trackers() const;
    -int prioritize_tracker(int index);
     

    The trackers() function will return a sorted vector of announce_entry. @@ -735,14 +732,11 @@ ones with lower tier will always be tried before the one with higher tier number

     struct announce_entry
     {
    +        announce_entry(std::string const& url);
             std::string url;
             int tier;
     };
     
    -

    The prioritize_tracker() is used internally to move a tracker to the front -of its tier group. i.e. It will never be moved pass a tracker with a different tier -number. For more information about how multiple trackers are dealt with, see the -specification.

    total_size() piece_length() piece_size() num_pieces()

    @@ -813,6 +807,9 @@ struct torrent_handle void set_tracker_login(std::string const& username, std::string const& password); + std::vector<announce_entry> const& trackers() const; + void replace_trackers(std::vector<announce_entry> const&); + void set_ratio(float ratio); void set_max_uploads(int max_uploads); void set_max_connections(int max_connections); @@ -840,6 +837,7 @@ struct torrent_handle

    The default constructor will initialize the handle to an invalid state. Which means you cannot perform any operation on it, unless you first assign it a valid handle. If you try to perform any operation on an uninitialized handle, it will throw invalid_handle.

    +

    TODO: document ``trackers()`` and ``replace_trackers()``

    save_path()

    @@ -1691,13 +1689,16 @@ struct file_error_alert: alert

    This alert is generated on tracker time outs, premature disconnects, invalid response or a HTTP response other than "200 OK". From the alert you can get the handle to the torrent the tracker belongs to. This alert is generated as severity level warning.

    +

    The times_in_row member says how many times in a row this tracker has failed.

     struct tracker_alert: alert
     {
    -        tracker_alert(const torrent_handle& h, const std::string& msg);
    +        tracker_alert(const torrent_handle& h, int times
    +                , const std::string& msg);
             virtual std::auto_ptr<alert> clone() const;
     
             torrent_handle handle;
    +        int times_in_row;
     };
     
    diff --git a/docs/manual.rst b/docs/manual.rst index f3a21aae8..7bdf66ba8 100755 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -559,7 +559,7 @@ The ``torrent_info`` has the following synopsis:: { public: - torrent_info(const entry& torrent_file) + torrent_info(entry const& torrent_file) torrent_info(int piece_size, const char* name); entry create_torrent() const; @@ -569,7 +569,7 @@ The ``torrent_info`` has the following synopsis:: void add_tracker(std::string const& url, int tier = 0); void add_file(boost::filesystem::path file, size_type size); - typedef std::vector>file_entry>::const_iterator file_iterator; + typedef std::vector::const_iterator file_iterator; typedef std::vector::const_reverse_iterator reverse_file_iterator; file_iterator begin_files() const; @@ -578,11 +578,9 @@ The ``torrent_info`` has the following synopsis:: reverse_file_iterator rend_files() const; int num_files() const; - const file_entry& file_at(int index) const; + file_entry const& file_at(int index) const; - const std::vector& trackers() const; - - int prioritize_tracker(int index); + std::vector const& trackers() const; size_type total_size() const; size_type piece_length() const; @@ -649,13 +647,12 @@ The ``print()`` function is there for debug purposes only. It will print the inf the torrent file to the given outstream. -trackers() prioritize_tracker() -------------------------------- +trackers() +---------- :: const std::vector& trackers() const; - int prioritize_tracker(int index); The ``trackers()`` function will return a sorted vector of ``announce_entry``. Each announce entry contains a string, which is the tracker url, and a tier index. The @@ -666,17 +663,11 @@ ones with lower tier will always be tried before the one with higher tier number struct announce_entry { + announce_entry(std::string const& url); std::string url; int tier; }; -The ``prioritize_tracker()`` is used internally to move a tracker to the front -of its tier group. i.e. It will never be moved pass a tracker with a different tier -number. For more information about how multiple trackers are dealt with, see the -specification_. - -.. _specification: http://home.elp.rr.com/tur/multitracker-spec.txt - total_size() piece_length() piece_size() num_pieces() ----------------------------------------------------- @@ -756,6 +747,9 @@ Its declaration looks like this:: void set_tracker_login(std::string const& username, std::string const& password); + std::vector const& trackers() const; + void replace_trackers(std::vector const&); + void set_ratio(float ratio); void set_max_uploads(int max_uploads); void set_max_connections(int max_connections); @@ -784,6 +778,7 @@ The default constructor will initialize the handle to an invalid state. Which me perform any operation on it, unless you first assign it a valid handle. If you try to perform any operation on an uninitialized handle, it will throw ``invalid_handle``. +*TODO: document ``trackers()`` and ``replace_trackers()``* save_path() ----------- @@ -1709,17 +1704,22 @@ This alert is generated on tracker time outs, premature disconnects, invalid res a HTTP response other than "200 OK". From the alert you can get the handle to the torrent the tracker belongs to. This alert is generated as severity level ``warning``. +The ``times_in_row`` member says how many times in a row this tracker has failed. + :: struct tracker_alert: alert { - tracker_alert(const torrent_handle& h, const std::string& msg); + tracker_alert(const torrent_handle& h, int times + , const std::string& msg); virtual std::auto_ptr clone() const; torrent_handle handle; + int times_in_row; }; + hash_failed_alert ----------------- diff --git a/include/libtorrent/alert_types.hpp b/include/libtorrent/alert_types.hpp index edede69db..4c2b6e726 100755 --- a/include/libtorrent/alert_types.hpp +++ b/include/libtorrent/alert_types.hpp @@ -43,15 +43,18 @@ namespace libtorrent struct tracker_alert: alert { tracker_alert(const torrent_handle& h + , int times , const std::string& msg) : alert(alert::warning, msg) , handle(h) + , times_in_row(times) {} virtual std::auto_ptr clone() const { return std::auto_ptr(new tracker_alert(*this)); } torrent_handle handle; + int times_in_row; }; struct hash_failed_alert: alert diff --git a/include/libtorrent/bencode.hpp b/include/libtorrent/bencode.hpp index f9372b8bd..a4cf74afb 100755 --- a/include/libtorrent/bencode.hpp +++ b/include/libtorrent/bencode.hpp @@ -93,10 +93,6 @@ namespace libtorrent struct invalid_encoding: std::exception { - invalid_encoding() - { - int i = 0; - } virtual const char* what() const throw() { return "invalid bencoding"; } }; diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp index 4863273df..df8a1be2d 100755 --- a/include/libtorrent/torrent.hpp +++ b/include/libtorrent/torrent.hpp @@ -301,6 +301,11 @@ namespace libtorrent piece_manager& filesystem(); torrent_info const& torrent_file() const { return m_torrent_file; } + std::vector const& trackers() const + { return m_trackers; } + + void replace_trackers(std::vector const& urls); + torrent_handle get_handle() const; // DEBUG @@ -343,6 +348,7 @@ namespace libtorrent private: void try_next_tracker(); + int prioritize_tracker(int tracker_index); torrent_info m_torrent_file; @@ -396,11 +402,13 @@ namespace libtorrent std::auto_ptr m_picker; + std::vector m_trackers; // this is an index into m_torrent_file.trackers() int m_last_working_tracker; int m_currently_trying_tracker; // the number of connection attempts that has - // failed in a row + // failed in a row, this is currently used to + // determine the timeout until next try. int m_failed_trackers; // this is a counter that is increased every diff --git a/include/libtorrent/torrent_handle.hpp b/include/libtorrent/torrent_handle.hpp index 3c9e638e3..7b7714796 100755 --- a/include/libtorrent/torrent_handle.hpp +++ b/include/libtorrent/torrent_handle.hpp @@ -183,6 +183,9 @@ namespace libtorrent torrent_status status() const; void get_download_queue(std::vector& queue) const; + std::vector const& trackers() const; + void replace_trackers(std::vector const&); + bool has_metadata() const; const torrent_info& get_torrent_info() const; bool is_valid() const; diff --git a/include/libtorrent/torrent_info.hpp b/include/libtorrent/torrent_info.hpp index 61d323edb..35b774cbc 100755 --- a/include/libtorrent/torrent_info.hpp +++ b/include/libtorrent/torrent_info.hpp @@ -67,6 +67,7 @@ namespace libtorrent struct announce_entry { + announce_entry(std::string const& u): url(u), tier(0) {} std::string url; int tier; }; @@ -115,11 +116,6 @@ namespace libtorrent const std::vector& trackers() const { return m_urls; } - // this will move the tracker with the given index - // to a prioritized position in the list (move it towards - // the begining) and return the new index to the tracker. - int prioritize_tracker(int index); - size_type total_size() const { assert(m_piece_length > 0); return m_total_size; } size_type piece_length() const { assert(m_piece_length > 0); return m_piece_length; } int num_pieces() const { assert(m_piece_length > 0); return (int)m_piece_hash.size(); } diff --git a/src/torrent.cpp b/src/torrent.cpp index 276bcaf57..07e4430a2 100755 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -162,6 +162,7 @@ namespace libtorrent , m_policy() , m_ses(ses) , m_picker(0) + , m_trackers(m_torrent_file.trackers()) , m_last_working_tracker(-1) , m_currently_trying_tracker(0) , m_failed_trackers(0) @@ -213,6 +214,7 @@ namespace libtorrent , m_download_bandwidth_limit(std::numeric_limits::max()) , m_save_path(save_path) { + m_trackers.push_back(announce_entry(tracker_url)); m_requested_metadata.resize(256, 0); m_policy.reset(new policy(this)); m_torrent_file.add_tracker(tracker_url); @@ -265,7 +267,7 @@ namespace libtorrent if (interval < 60) interval = 60; m_last_working_tracker - = m_torrent_file.prioritize_tracker(m_currently_trying_tracker); + = prioritize_tracker(m_currently_trying_tracker); m_next_request = boost::posix_time::second_clock::local_time() + boost::posix_time::seconds(m_duration); m_currently_trying_tracker = 0; @@ -416,15 +418,20 @@ namespace libtorrent // decrease the trust point of all peers that sent // parts of this piece. - for (std::vector
    ::iterator i = downloaders.begin(); - i != downloaders.end(); - ++i) + // first, build a set of all peers that participated + std::set
    peers; + std::copy(downloaders.begin(), downloaders.end(), std::inserter(peers, peers.begin())); + + for (std::set
    ::iterator i = peers.begin() + , end(peers.end()); i != end; ++i) { peer_iterator p = m_connections.find(*i); if (p == m_connections.end()) continue; p->second->received_invalid_data(); - if (p->second->trust_points() <= -7) + // either, we have received too many failed hashes + // or this was the only peer that sent us this piece. + if (p->second->trust_points() <= -7 || peers.size() == 1) { // we don't trust this peer anymore // ban it. @@ -467,9 +474,11 @@ namespace libtorrent // increase the trust point of all peers that sent // parts of this piece. - for (std::vector
    ::iterator i = downloaders.begin(); - i != downloaders.end(); - ++i) + std::set
    peers; + std::copy(downloaders.begin(), downloaders.end(), std::inserter(peers, peers.begin())); + + for (std::set
    ::iterator i = peers.begin() + , end(peers.end()); i != end; ++i) { peer_iterator p = m_connections.find(*i); if (p == m_connections.end()) continue; @@ -487,6 +496,15 @@ namespace libtorrent return m_username + ":" + m_password; } + void torrent::replace_trackers(std::vector const& urls) + { + assert(!urls.empty()); + m_trackers = urls; + if (m_currently_trying_tracker >= (int)m_trackers.size()) + m_currently_trying_tracker = m_trackers.size()-1; + m_last_working_tracker = -1; + } + tracker_request torrent::generate_tracker_request() { m_duration = 1800; @@ -502,7 +520,7 @@ namespace libtorrent req.left = bytes_left(); if (req.left == -1) req.left = 1000; req.event = m_event; - req.url = m_torrent_file.trackers()[m_currently_trying_tracker].url; + req.url = m_trackers[m_currently_trying_tracker].url; req.num_want = std::max( (m_policy->get_max_connections() - m_policy->num_peers()), 0); @@ -637,12 +655,27 @@ namespace libtorrent force_tracker_request(); } + // this will move the tracker with the given index + // to a prioritized position in the list (move it towards + // the begining) and return the new index to the tracker. + int torrent::prioritize_tracker(int index) + { + assert(index >= 0); + if (index >= (int)m_trackers.size()) return (int)m_trackers.size()-1; + + while (index > 0 && m_trackers[index].tier == m_trackers[index-1].tier) + { + std::swap(m_trackers[index].url, m_trackers[index-1].url); + --index; + } + return index; + } void torrent::try_next_tracker() { ++m_currently_trying_tracker; - if ((unsigned)m_currently_trying_tracker >= m_torrent_file.trackers().size()) + if ((unsigned)m_currently_trying_tracker >= m_trackers.size()) { int delay = tracker_retry_delay_min + std::min(m_failed_trackers, (int)tracker_failed_max) @@ -659,6 +692,7 @@ namespace libtorrent // don't delay before trying the next tracker m_next_request = boost::posix_time::second_clock::local_time(); } + } void torrent::check_files(detail::piece_checker_data& data, @@ -921,7 +955,7 @@ namespace libtorrent if (m_last_working_tracker >= 0) { st.current_tracker - = m_torrent_file.trackers()[m_last_working_tracker].url; + = m_trackers[m_last_working_tracker].url; } st.progress = st.total_done @@ -1060,9 +1094,10 @@ namespace libtorrent { std::stringstream s; s << "tracker: \"" - << m_torrent_file.trackers()[m_currently_trying_tracker].url + << m_trackers[m_currently_trying_tracker].url << "\" timed out"; - m_ses.m_alerts.post_alert(tracker_alert(get_handle(), s.str())); + m_ses.m_alerts.post_alert(tracker_alert(get_handle() + , m_failed_trackers, s.str())); } try_next_tracker(); } @@ -1079,9 +1114,10 @@ namespace libtorrent { std::stringstream s; s << "tracker: \"" - << m_torrent_file.trackers()[m_currently_trying_tracker].url + << m_trackers[m_currently_trying_tracker].url << "\" " << str; - m_ses.m_alerts.post_alert(tracker_alert(get_handle(), s.str())); + m_ses.m_alerts.post_alert(tracker_alert(get_handle() + , m_failed_trackers, s.str())); } diff --git a/src/torrent_handle.cpp b/src/torrent_handle.cpp index 954afefd5..65f9bc37f 100755 --- a/src/torrent_handle.cpp +++ b/src/torrent_handle.cpp @@ -313,6 +313,22 @@ namespace libtorrent throw invalid_handle(); } + std::vector const& torrent_handle::trackers() const + { + INVARIANT_CHECK; + + return call_member const&>(m_ses + , m_chk, m_info_hash, boost::bind(&torrent::trackers, _1)); + } + + void torrent_handle::replace_trackers(std::vector const& urls) + { + INVARIANT_CHECK; + + call_member(m_ses, m_chk, m_info_hash + , boost::bind(&torrent::replace_trackers, _1, urls)); + } + const torrent_info& torrent_handle::get_torrent_info() const { INVARIANT_CHECK; diff --git a/src/torrent_info.cpp b/src/torrent_info.cpp index 6667b8f97..a1251c2e6 100755 --- a/src/torrent_info.cpp +++ b/src/torrent_info.cpp @@ -193,9 +193,8 @@ namespace libtorrent const entry::list_type& ll = j->list(); for (entry::list_type::const_iterator k = ll.begin(); k != ll.end(); ++k) { - announce_entry e; + announce_entry e(k->string()); e.tier = (int)std::distance(l.begin(), j); - e.url = k->string(); m_urls.push_back(e); } } @@ -220,10 +219,7 @@ namespace libtorrent { i = torrent_file.find_key("announce"); if (i == 0) throw invalid_torrent_file(); - announce_entry e; - e.tier = 0; - e.url = i->string(); - m_urls.push_back(e); + m_urls.push_back(announce_entry(i->string())); } // extract creation date @@ -271,8 +267,7 @@ namespace libtorrent void torrent_info::add_tracker(std::string const& url, int tier) { - announce_entry e; - e.url = url; + announce_entry e(url); e.tier = tier; m_urls.push_back(e); } @@ -414,19 +409,6 @@ namespace libtorrent assert(false); } - int torrent_info::prioritize_tracker(int index) - { - assert(index >= 0); - if (index >= (int)m_urls.size()) return (int)m_urls.size()-1; - - while (index > 0 && m_urls[index].tier == m_urls[index-1].tier) - { - std::swap(m_urls[index].url, m_urls[index-1].url); - --index; - } - return index; - } - void torrent_info::print(std::ostream& os) const { os << "trackers:\n";