forked from premiere/premiere-libtorrent
added support for min_interval
This commit is contained in:
parent
2d627c1f9d
commit
1e654220fa
|
@ -81,6 +81,7 @@
|
|||
* added session::is_dht_running() function
|
||||
* added torrent_handle::force_dht_announce()
|
||||
* added torrent_info::remap_files()
|
||||
* support min_interval tracker extension
|
||||
|
||||
release 0.14.8
|
||||
|
||||
|
|
|
@ -1713,6 +1713,10 @@ ones with lower tier will always be tried before the one with higher tier number
|
|||
{
|
||||
announce_entry(std::string const& url);
|
||||
std::string url;
|
||||
|
||||
int next_announce_in() const;
|
||||
int min_announce_in() const;
|
||||
|
||||
boost::uint8_t tier;
|
||||
boost::uint8_t fail_limit;
|
||||
boost::uint8_t fails;
|
||||
|
@ -1732,6 +1736,10 @@ ones with lower tier will always be tried before the one with higher tier number
|
|||
bool complete_sent:1;
|
||||
};
|
||||
|
||||
``next_announce_in()`` returns the number of seconds to the next announce on
|
||||
this tracker. ``min_announce_in()`` returns the number of seconds until we are
|
||||
allowed to force another tracker update with this tracker.
|
||||
|
||||
``fail_limit`` is the max number of failures to announce to this tracker in
|
||||
a row, before this tracker is not used anymore.
|
||||
|
||||
|
|
|
@ -45,9 +45,10 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#include "libtorrent/config.hpp"
|
||||
#include "libtorrent/lazy_entry.hpp"
|
||||
#include "libtorrent/peer_id.hpp"
|
||||
#include "libtorrent/tracker_manager.hpp"
|
||||
#include "libtorrent/config.hpp"
|
||||
#include "libtorrent/i2p_stream.hpp"
|
||||
|
||||
namespace libtorrent
|
||||
|
@ -95,8 +96,8 @@ namespace libtorrent
|
|||
|
||||
virtual void on_timeout() {}
|
||||
|
||||
void parse(int status_code, const entry& e);
|
||||
bool extract_peer_info(const entry& e, peer_entry& ret);
|
||||
void parse(int status_code, lazy_entry const& e);
|
||||
bool extract_peer_info(lazy_entry const& e, peer_entry& ret);
|
||||
|
||||
tracker_manager& m_man;
|
||||
boost::shared_ptr<http_connection> m_tracker_connection;
|
||||
|
|
|
@ -153,6 +153,7 @@ namespace libtorrent
|
|||
lazy_entry const* dict_find_dict(char const* name) const;
|
||||
lazy_entry const* dict_find_list(char const* name) const;
|
||||
lazy_entry const* dict_find_string(char const* name) const;
|
||||
lazy_entry const* dict_find_int(char const* name) const;
|
||||
|
||||
std::pair<std::string, lazy_entry const*> dict_at(int i) const;
|
||||
|
||||
|
|
|
@ -391,7 +391,7 @@ namespace libtorrent
|
|||
tracker_request const& r
|
||||
, address const& tracker_ip
|
||||
, std::list<address> const& ip_list
|
||||
, std::vector<peer_entry>& e, int interval
|
||||
, std::vector<peer_entry>& e, int interval, int min_interval
|
||||
, int complete, int incomplete, address const& external_ip);
|
||||
virtual void tracker_request_timed_out(
|
||||
tracker_request const& r);
|
||||
|
|
|
@ -89,9 +89,15 @@ namespace libtorrent
|
|||
|
||||
std::string url;
|
||||
|
||||
int next_announce_in() const;
|
||||
int min_announce_in() const;
|
||||
|
||||
// the time of next tracker announce
|
||||
ptime next_announce;
|
||||
|
||||
// no announces before this time
|
||||
ptime min_announce;
|
||||
|
||||
boost::uint8_t tier;
|
||||
// the number of times this tracker can fail
|
||||
// in a row before it's removed. 0 means unlimited
|
||||
|
@ -131,6 +137,7 @@ namespace libtorrent
|
|||
{
|
||||
start_sent = false;
|
||||
next_announce = min_time();
|
||||
min_announce = min_time();
|
||||
}
|
||||
|
||||
void failed();
|
||||
|
@ -138,6 +145,7 @@ namespace libtorrent
|
|||
bool can_announce(ptime now) const
|
||||
{
|
||||
return now >= next_announce
|
||||
&& now >= min_announce
|
||||
&& (fails < fail_limit || fail_limit == 0)
|
||||
&& !updating;
|
||||
}
|
||||
|
|
|
@ -129,6 +129,7 @@ namespace libtorrent
|
|||
, std::list<address> const& ip_list
|
||||
, std::vector<peer_entry>& peers
|
||||
, int interval
|
||||
, int min_interval
|
||||
, int complete
|
||||
, int incomplete
|
||||
, address const& external_ip) = 0;
|
||||
|
|
|
@ -290,16 +290,16 @@ namespace libtorrent
|
|||
received_bytes(size + parser.body_start());
|
||||
|
||||
// handle tracker response
|
||||
entry e;
|
||||
e = bdecode(data, data + size);
|
||||
lazy_entry e;
|
||||
int res = lazy_bdecode(data, data + size, e);
|
||||
|
||||
if (e.type() == entry::dictionary_t)
|
||||
if (res == 0 && e.type() == lazy_entry::dict_t)
|
||||
{
|
||||
parse(parser.status_code(), e);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string error_str("invalid bencoding of tracker response: \"");
|
||||
std::string error_str("invalid encoding of tracker response: \"");
|
||||
for (char const* i = data, *end(data + size); i != end; ++i)
|
||||
{
|
||||
if (*i >= ' ' && *i <= '~') error_str += *i;
|
||||
|
@ -316,23 +316,18 @@ namespace libtorrent
|
|||
close();
|
||||
}
|
||||
|
||||
bool http_tracker_connection::extract_peer_info(const entry& info, peer_entry& ret)
|
||||
bool http_tracker_connection::extract_peer_info(lazy_entry const& info, peer_entry& ret)
|
||||
{
|
||||
// extract peer id (if any)
|
||||
if (info.type() != entry::dictionary_t)
|
||||
if (info.type() != lazy_entry::dict_t)
|
||||
{
|
||||
fail(-1, "invalid response from tracker (invalid peer entry)");
|
||||
return false;
|
||||
}
|
||||
entry const* i = info.find_key("peer id");
|
||||
if (i != 0)
|
||||
lazy_entry const* i = info.dict_find_string("peer id");
|
||||
if (i != 0 && i->string_length() == 20)
|
||||
{
|
||||
if (i->type() != entry::string_t || i->string().length() != 20)
|
||||
{
|
||||
fail(-1, "invalid response from tracker (invalid peer id)");
|
||||
return false;
|
||||
}
|
||||
std::copy(i->string().begin(), i->string().end(), ret.pid.begin());
|
||||
std::copy(i->string_ptr(), i->string_ptr()+20, ret.pid.begin());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -341,44 +336,42 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
// extract ip
|
||||
i = info.find_key("ip");
|
||||
if (i == 0 || i->type() != entry::string_t)
|
||||
i = info.dict_find_string("ip");
|
||||
if (i == 0)
|
||||
{
|
||||
fail(-1, "invalid response from tracker");
|
||||
return false;
|
||||
}
|
||||
ret.ip = i->string();
|
||||
ret.ip = i->string_value();
|
||||
|
||||
// extract port
|
||||
i = info.find_key("port");
|
||||
if (i == 0 || i->type() != entry::int_t)
|
||||
i = info.dict_find_int("port");
|
||||
if (i == 0)
|
||||
{
|
||||
fail(-1, "invalid response from tracker");
|
||||
return false;
|
||||
}
|
||||
ret.port = (unsigned short)i->integer();
|
||||
ret.port = (unsigned short)i->int_value();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void http_tracker_connection::parse(int status_code, entry const& e)
|
||||
void http_tracker_connection::parse(int status_code, lazy_entry const& e)
|
||||
{
|
||||
boost::shared_ptr<request_callback> cb = requester();
|
||||
if (!cb) return;
|
||||
|
||||
// parse the response
|
||||
entry const* failure = e.find_key("failure reason");
|
||||
if (failure && failure->type() == entry::string_t)
|
||||
lazy_entry const* failure = e.dict_find_string("failure reason");
|
||||
if (failure)
|
||||
{
|
||||
fail(status_code, failure->string().c_str());
|
||||
fail(status_code, failure->string_value().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
entry const* warning = e.find_key("warning message");
|
||||
if (warning && warning->type() == entry::string_t)
|
||||
{
|
||||
cb->tracker_warning(tracker_req(), warning->string());
|
||||
}
|
||||
lazy_entry const* warning = e.dict_find_string("warning message");
|
||||
if (warning)
|
||||
cb->tracker_warning(tracker_req(), warning->string_value());
|
||||
|
||||
std::vector<peer_entry> peer_list;
|
||||
|
||||
|
@ -386,67 +379,55 @@ namespace libtorrent
|
|||
{
|
||||
std::string ih = tracker_req().info_hash.to_string();
|
||||
|
||||
entry const* files = e.find_key("files");
|
||||
if (files == 0 || files->type() != entry::dictionary_t)
|
||||
lazy_entry const* files = e.dict_find_dict("files");
|
||||
if (files == 0)
|
||||
{
|
||||
fail(-1, "invalid or missing 'files' entry in scrape response");
|
||||
return;
|
||||
}
|
||||
|
||||
entry const* scrape_data = files->find_key(ih);
|
||||
if (scrape_data == 0 || scrape_data->type() != entry::dictionary_t)
|
||||
lazy_entry const* scrape_data = files->dict_find_dict(ih.c_str());
|
||||
if (scrape_data == 0)
|
||||
{
|
||||
fail(-1, "missing or invalid info-hash entry in scrape response");
|
||||
return;
|
||||
}
|
||||
entry const* complete = scrape_data->find_key("complete");
|
||||
entry const* incomplete = scrape_data->find_key("incomplete");
|
||||
entry const* downloaded = scrape_data->find_key("downloaded");
|
||||
if (complete == 0 || incomplete == 0 || downloaded == 0
|
||||
|| complete->type() != entry::int_t
|
||||
|| incomplete->type() != entry::int_t
|
||||
|| downloaded->type() != entry::int_t)
|
||||
{
|
||||
fail(-1, "missing 'complete' or 'incomplete' entries in scrape response");
|
||||
return;
|
||||
}
|
||||
cb->tracker_scrape_response(tracker_req(), int(complete->integer())
|
||||
, int(incomplete->integer()), int(downloaded->integer()));
|
||||
int complete = scrape_data->dict_find_int_value("complete", -1);
|
||||
int incomplete = scrape_data->dict_find_int_value("incomplete", -1);
|
||||
int downloaded = scrape_data->dict_find_int_value("downloaded", -1);
|
||||
cb->tracker_scrape_response(tracker_req(), complete
|
||||
, incomplete, downloaded);
|
||||
return;
|
||||
}
|
||||
|
||||
entry const* interval = e.find_key("interval");
|
||||
if (interval == 0 || interval->type() != entry::int_t)
|
||||
{
|
||||
fail(-1, "missing or invalid 'interval' entry in tracker response");
|
||||
return;
|
||||
}
|
||||
int interval = e.dict_find_int_value("interval", 1800);
|
||||
int min_interval = e.dict_find_int_value("min interval", 60);
|
||||
|
||||
entry const* peers_ent = e.find_key("peers");
|
||||
if (peers_ent && peers_ent->type() == entry::string_t)
|
||||
lazy_entry const* peers_ent = e.dict_find("peers");
|
||||
if (peers_ent && peers_ent->type() == lazy_entry::string_t)
|
||||
{
|
||||
std::string const& peers = peers_ent->string();
|
||||
for (std::string::const_iterator i = peers.begin();
|
||||
i != peers.end();)
|
||||
char const* peers = peers_ent->string_ptr();
|
||||
int len = peers_ent->string_length();
|
||||
for (int i = 0; i < len; ++i)
|
||||
{
|
||||
if (peers.end() - i < 6) break;
|
||||
if (len - i < 6) break;
|
||||
|
||||
peer_entry p;
|
||||
p.pid.clear();
|
||||
error_code ec;
|
||||
p.ip = detail::read_v4_address(i).to_string(ec);
|
||||
p.ip = detail::read_v4_address(peers).to_string(ec);
|
||||
p.port = detail::read_uint16(peers);
|
||||
if (ec) continue;
|
||||
p.port = detail::read_uint16(i);
|
||||
peer_list.push_back(p);
|
||||
}
|
||||
}
|
||||
else if (peers_ent && peers_ent->type() == entry::list_t)
|
||||
else if (peers_ent && peers_ent->type() == lazy_entry::list_t)
|
||||
{
|
||||
entry::list_type const& l = peers_ent->list();
|
||||
for(entry::list_type::const_iterator i = l.begin(); i != l.end(); ++i)
|
||||
int len = peers_ent->list_size();
|
||||
for (int i = 0; i < len; ++i)
|
||||
{
|
||||
peer_entry p;
|
||||
if (!extract_peer_info(*i, p)) return;
|
||||
if (!extract_peer_info(*peers_ent->list_at(i), p)) return;
|
||||
peer_list.push_back(p);
|
||||
}
|
||||
}
|
||||
|
@ -456,21 +437,21 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
#if TORRENT_USE_IPV6
|
||||
entry const* ipv6_peers = e.find_key("peers6");
|
||||
if (ipv6_peers && ipv6_peers->type() == entry::string_t)
|
||||
lazy_entry const* ipv6_peers = e.dict_find_string("peers6");
|
||||
if (ipv6_peers)
|
||||
{
|
||||
std::string const& peers = ipv6_peers->string();
|
||||
for (std::string::const_iterator i = peers.begin();
|
||||
i != peers.end();)
|
||||
char const* peers = ipv6_peers->string_ptr();
|
||||
int len = ipv6_peers->string_length();
|
||||
for (int i = 0; i < len; ++i)
|
||||
{
|
||||
if (peers.end() - i < 18) break;
|
||||
if (len - i < 18) break;
|
||||
|
||||
peer_entry p;
|
||||
p.pid.clear();
|
||||
error_code ec;
|
||||
p.ip = detail::read_v6_address(i).to_string(ec);
|
||||
p.ip = detail::read_v6_address(peers).to_string(ec);
|
||||
p.port = detail::read_uint16(peers);
|
||||
if (ec) continue;
|
||||
p.port = detail::read_uint16(i);
|
||||
peer_list.push_back(p);
|
||||
}
|
||||
}
|
||||
|
@ -479,7 +460,7 @@ namespace libtorrent
|
|||
ipv6_peers = 0;
|
||||
}
|
||||
#else
|
||||
entry const* ipv6_peers = 0;
|
||||
lazy_entry const* ipv6_peers = 0;
|
||||
#endif
|
||||
|
||||
if (peers_ent == 0 && ipv6_peers == 0)
|
||||
|
@ -490,30 +471,22 @@ namespace libtorrent
|
|||
|
||||
|
||||
// look for optional scrape info
|
||||
int complete = -1;
|
||||
int incomplete = -1;
|
||||
address external_ip;
|
||||
|
||||
entry const* ip_ent = e.find_key("external ip");
|
||||
if (ip_ent && ip_ent->type() == entry::string_t)
|
||||
lazy_entry const* ip_ent = e.dict_find_string("external ip");
|
||||
if (ip_ent)
|
||||
{
|
||||
std::string const& ip = ip_ent->string();
|
||||
char const* p = &ip[0];
|
||||
if (ip.size() == address_v4::bytes_type::static_size)
|
||||
char const* p = ip_ent->string_ptr();
|
||||
if (ip_ent->string_length() == address_v4::bytes_type::static_size)
|
||||
external_ip = detail::read_v4_address(p);
|
||||
#if TORRENT_USE_IPV6
|
||||
else if (ip.size() == address_v6::bytes_type::static_size)
|
||||
else if (ip_ent->string_length() == address_v6::bytes_type::static_size)
|
||||
external_ip = detail::read_v6_address(p);
|
||||
#endif
|
||||
}
|
||||
|
||||
entry const* complete_ent = e.find_key("complete");
|
||||
if (complete_ent && complete_ent->type() == entry::int_t)
|
||||
complete = int(complete_ent->integer());
|
||||
|
||||
entry const* incomplete_ent = e.find_key("incomplete");
|
||||
if (incomplete_ent && incomplete_ent->type() == entry::int_t)
|
||||
incomplete = int(incomplete_ent->integer());
|
||||
int complete = e.dict_find_int_value("complete", -1);
|
||||
int incomplete = e.dict_find_int_value("incomplete", -1);
|
||||
|
||||
std::list<address> ip_list;
|
||||
if (m_tracker_connection)
|
||||
|
@ -527,7 +500,7 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
cb->tracker_response(tracker_req(), m_tracker_ip, ip_list, peer_list
|
||||
, interval->integer(), complete, incomplete, external_ip);
|
||||
, interval, min_interval, complete, incomplete, external_ip);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -286,6 +286,13 @@ namespace libtorrent
|
|||
return e;
|
||||
}
|
||||
|
||||
lazy_entry const* lazy_entry::dict_find_int(char const* name) const
|
||||
{
|
||||
lazy_entry const* e = dict_find(name);
|
||||
if (e == 0 || e->type() != lazy_entry::int_t) return 0;
|
||||
return e;
|
||||
}
|
||||
|
||||
size_type lazy_entry::dict_find_int_value(char const* name, size_type default_val) const
|
||||
{
|
||||
lazy_entry const* e = dict_find(name);
|
||||
|
|
|
@ -1342,6 +1342,8 @@ namespace libtorrent
|
|||
|
||||
void torrent::scrape_tracker()
|
||||
{
|
||||
m_last_scrape = time_now();
|
||||
|
||||
if (m_trackers.empty()) return;
|
||||
|
||||
int i = m_last_working_tracker;
|
||||
|
@ -1354,8 +1356,6 @@ namespace libtorrent
|
|||
req.bind_ip = m_ses.m_listen_interface.address();
|
||||
m_ses.m_tracker_manager.queue_request(m_ses.m_io_service, m_ses.m_half_open, req
|
||||
, tracker_login(), shared_from_this());
|
||||
|
||||
m_last_scrape = time_now();
|
||||
}
|
||||
|
||||
void torrent::tracker_warning(tracker_request const& req, std::string const& msg)
|
||||
|
@ -1392,6 +1392,7 @@ namespace libtorrent
|
|||
, std::list<address> const& tracker_ips // these are all the IPs it resolved to
|
||||
, std::vector<peer_entry>& peer_list
|
||||
, int interval
|
||||
, int min_interval
|
||||
, int complete
|
||||
, int incomplete
|
||||
, address const& external_ip)
|
||||
|
@ -1420,6 +1421,7 @@ namespace libtorrent
|
|||
ae->updating = false;
|
||||
ae->fails = 0;
|
||||
ae->next_announce = now + seconds(interval);
|
||||
ae->min_announce = now + seconds(min_interval);
|
||||
int tracker_index = ae - &m_trackers[0];
|
||||
m_last_working_tracker = prioritize_tracker(tracker_index);
|
||||
}
|
||||
|
@ -4333,6 +4335,7 @@ namespace libtorrent
|
|||
{
|
||||
if (i->complete_sent) continue;
|
||||
i->next_announce = now;
|
||||
i->min_announce = now;
|
||||
}
|
||||
announce_with_tracker();
|
||||
}
|
||||
|
@ -5195,7 +5198,10 @@ namespace libtorrent
|
|||
ptime now = time_now();
|
||||
for (std::vector<announce_entry>::iterator i = m_trackers.begin()
|
||||
, end(m_trackers.end()); i != end; ++i)
|
||||
{
|
||||
i->next_announce = now;
|
||||
i->min_announce = now;
|
||||
}
|
||||
announce_with_tracker(tracker_request::stopped);
|
||||
}
|
||||
|
||||
|
|
|
@ -400,6 +400,12 @@ namespace libtorrent
|
|||
return 0;
|
||||
}
|
||||
|
||||
int announce_entry::next_announce_in() const
|
||||
{ return total_seconds(time_now() - next_announce); }
|
||||
|
||||
int announce_entry::min_announce_in() const
|
||||
{ return total_seconds(time_now() - min_announce); }
|
||||
|
||||
void announce_entry::failed()
|
||||
{
|
||||
++fails;
|
||||
|
|
|
@ -395,6 +395,7 @@ namespace libtorrent
|
|||
buf += 8; // skip header
|
||||
restart_read_timeout();
|
||||
int interval = detail::read_int32(buf);
|
||||
int min_interval = 60;
|
||||
int incomplete = detail::read_int32(buf);
|
||||
int complete = detail::read_int32(buf);
|
||||
int num_peers = (size - 20) / 6;
|
||||
|
@ -446,7 +447,7 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
cb->tracker_response(tracker_req(), m_target.address(), ip_list
|
||||
, peer_list, interval, complete, incomplete, address());
|
||||
, peer_list, interval, min_interval, complete, incomplete, address());
|
||||
|
||||
m_man.remove_request(this);
|
||||
close();
|
||||
|
|
Loading…
Reference in New Issue