added scrape support
This commit is contained in:
parent
cf6740e996
commit
fabfe6cd50
|
@ -82,6 +82,35 @@ namespace libtorrent
|
||||||
{ return std::auto_ptr<alert>(new tracker_warning_alert(*this)); }
|
{ return std::auto_ptr<alert>(new tracker_warning_alert(*this)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct TORRENT_EXPORT scrape_reply_alert: torrent_alert
|
||||||
|
{
|
||||||
|
scrape_reply_alert(torrent_handle const& h
|
||||||
|
, int incomplete_
|
||||||
|
, int complete_
|
||||||
|
, std::string const& msg)
|
||||||
|
: torrent_alert(h, alert::info, msg)
|
||||||
|
, incomplete(incomplete_)
|
||||||
|
, complete(complete_)
|
||||||
|
{}
|
||||||
|
|
||||||
|
int incomplete;
|
||||||
|
int complete;
|
||||||
|
|
||||||
|
virtual std::auto_ptr<alert> clone() const
|
||||||
|
{ return std::auto_ptr<alert>(new scrape_reply_alert(*this)); }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TORRENT_EXPORT scrape_failed_alert: torrent_alert
|
||||||
|
{
|
||||||
|
scrape_failed_alert(torrent_handle const& h
|
||||||
|
, std::string const& msg)
|
||||||
|
: torrent_alert(h, alert::warning, msg)
|
||||||
|
{}
|
||||||
|
|
||||||
|
virtual std::auto_ptr<alert> clone() const
|
||||||
|
{ return std::auto_ptr<alert>(new scrape_failed_alert(*this)); }
|
||||||
|
};
|
||||||
|
|
||||||
struct TORRENT_EXPORT tracker_reply_alert: torrent_alert
|
struct TORRENT_EXPORT tracker_reply_alert: torrent_alert
|
||||||
{
|
{
|
||||||
tracker_reply_alert(torrent_handle const& h
|
tracker_reply_alert(torrent_handle const& h
|
||||||
|
|
|
@ -309,6 +309,8 @@ namespace libtorrent
|
||||||
virtual void tracker_request_error(tracker_request const& r
|
virtual void tracker_request_error(tracker_request const& r
|
||||||
, int response_code, const std::string& str);
|
, int response_code, const std::string& str);
|
||||||
virtual void tracker_warning(std::string const& msg);
|
virtual void tracker_warning(std::string const& msg);
|
||||||
|
virtual void tracker_scrape_response(tracker_request const& req
|
||||||
|
, int complete, int incomplete, int downloaded);
|
||||||
|
|
||||||
// generates a request string for sending
|
// generates a request string for sending
|
||||||
// to the tracker
|
// to the tracker
|
||||||
|
@ -332,6 +334,7 @@ namespace libtorrent
|
||||||
// forcefully sets next_announce to the current time
|
// forcefully sets next_announce to the current time
|
||||||
void force_tracker_request();
|
void force_tracker_request();
|
||||||
void force_tracker_request(ptime);
|
void force_tracker_request(ptime);
|
||||||
|
void scrape_tracker();
|
||||||
|
|
||||||
// sets the username and password that will be sent to
|
// sets the username and password that will be sent to
|
||||||
// the tracker
|
// the tracker
|
||||||
|
|
|
@ -94,15 +94,17 @@ namespace libtorrent
|
||||||
, upload_rate(0)
|
, upload_rate(0)
|
||||||
, download_payload_rate(0)
|
, download_payload_rate(0)
|
||||||
, upload_payload_rate(0)
|
, upload_payload_rate(0)
|
||||||
|
, num_seeds(0)
|
||||||
, num_peers(0)
|
, num_peers(0)
|
||||||
, num_complete(-1)
|
, num_complete(-1)
|
||||||
, num_incomplete(-1)
|
, num_incomplete(-1)
|
||||||
|
, list_seeds(0)
|
||||||
|
, list_peers(0)
|
||||||
, pieces(0)
|
, pieces(0)
|
||||||
, num_pieces(0)
|
, num_pieces(0)
|
||||||
, total_done(0)
|
, total_done(0)
|
||||||
, total_wanted_done(0)
|
, total_wanted_done(0)
|
||||||
, total_wanted(0)
|
, total_wanted(0)
|
||||||
, num_seeds(0)
|
|
||||||
, distributed_copies(0.f)
|
, distributed_copies(0.f)
|
||||||
, block_size(0)
|
, block_size(0)
|
||||||
, num_uploads(0)
|
, num_uploads(0)
|
||||||
|
@ -159,8 +161,12 @@ namespace libtorrent
|
||||||
float download_payload_rate;
|
float download_payload_rate;
|
||||||
float upload_payload_rate;
|
float upload_payload_rate;
|
||||||
|
|
||||||
|
// the number of peers this torrent is connected to
|
||||||
|
// that are seeding.
|
||||||
|
int num_seeds;
|
||||||
|
|
||||||
// the number of peers this torrent
|
// the number of peers this torrent
|
||||||
// is connected to.
|
// is connected to (including seeds).
|
||||||
int num_peers;
|
int num_peers;
|
||||||
|
|
||||||
// if the tracker sends scrape info in its
|
// if the tracker sends scrape info in its
|
||||||
|
@ -171,6 +177,15 @@ namespace libtorrent
|
||||||
int num_complete;
|
int num_complete;
|
||||||
int num_incomplete;
|
int num_incomplete;
|
||||||
|
|
||||||
|
// this is the number of seeds whose IP we know
|
||||||
|
// but are not necessarily connected to
|
||||||
|
int list_seeds;
|
||||||
|
|
||||||
|
// this is the number of peers whose IP we know
|
||||||
|
// (including seeds), but are not necessarily
|
||||||
|
// connected to
|
||||||
|
int list_peers;
|
||||||
|
|
||||||
const std::vector<bool>* pieces;
|
const std::vector<bool>* pieces;
|
||||||
|
|
||||||
// this is the number of pieces the client has
|
// this is the number of pieces the client has
|
||||||
|
@ -193,10 +208,6 @@ namespace libtorrent
|
||||||
// in case any pieces are filtered as not wanted
|
// in case any pieces are filtered as not wanted
|
||||||
size_type total_wanted;
|
size_type total_wanted;
|
||||||
|
|
||||||
// the number of peers this torrent is connected to
|
|
||||||
// that are seeding.
|
|
||||||
int num_seeds;
|
|
||||||
|
|
||||||
// the number of distributed copies of the file.
|
// the number of distributed copies of the file.
|
||||||
// note that one copy may be spread out among many peers.
|
// note that one copy may be spread out among many peers.
|
||||||
//
|
//
|
||||||
|
@ -345,6 +356,9 @@ namespace libtorrent
|
||||||
// timed out.
|
// timed out.
|
||||||
void force_reannounce(boost::posix_time::time_duration) const;
|
void force_reannounce(boost::posix_time::time_duration) const;
|
||||||
|
|
||||||
|
// performs a scrape request
|
||||||
|
void scrape_tracker() const;
|
||||||
|
|
||||||
// returns the name of this torrent, in case it doesn't
|
// returns the name of this torrent, in case it doesn't
|
||||||
// have metadata it returns the name assigned to it
|
// have metadata it returns the name assigned to it
|
||||||
// when it was added.
|
// when it was added.
|
||||||
|
|
|
@ -122,6 +122,8 @@ namespace libtorrent
|
||||||
request_callback(): m_manager(0) {}
|
request_callback(): m_manager(0) {}
|
||||||
virtual ~request_callback() {}
|
virtual ~request_callback() {}
|
||||||
virtual void tracker_warning(std::string const& msg) = 0;
|
virtual void tracker_warning(std::string const& msg) = 0;
|
||||||
|
virtual void tracker_scrape_response(tracker_request const& req
|
||||||
|
, int complete, int incomplete, int downloads) {}
|
||||||
virtual void tracker_response(
|
virtual void tracker_response(
|
||||||
tracker_request const&
|
tracker_request const&
|
||||||
, std::vector<peer_entry>& peers
|
, std::vector<peer_entry>& peers
|
||||||
|
@ -191,7 +193,7 @@ namespace libtorrent
|
||||||
: timeout_handler
|
: timeout_handler
|
||||||
{
|
{
|
||||||
tracker_connection(tracker_manager& man
|
tracker_connection(tracker_manager& man
|
||||||
, tracker_request req
|
, tracker_request const& req
|
||||||
, asio::strand& str
|
, asio::strand& str
|
||||||
, address bind_interface
|
, address bind_interface
|
||||||
, boost::weak_ptr<request_callback> r);
|
, boost::weak_ptr<request_callback> r);
|
||||||
|
|
|
@ -797,7 +797,7 @@ namespace libtorrent
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_buffer.erase(m_buffer.begin(), m_buffer.begin() + m_parser.body_start());
|
m_buffer.erase(m_buffer.begin(), m_buffer.begin() + m_parser.body_start());
|
||||||
if (inflate_gzip(m_buffer, tracker_request(), cb.get(),
|
if (inflate_gzip(m_buffer, tracker_req(), cb.get(),
|
||||||
m_settings.tracker_maximum_response_length))
|
m_settings.tracker_maximum_response_length))
|
||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
|
@ -897,21 +897,35 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
catch(type_error const&) {}
|
catch(type_error const&) {}
|
||||||
|
|
||||||
std::vector<peer_entry> peer_list;
|
|
||||||
|
|
||||||
if (tracker_req().kind == tracker_request::scrape_request)
|
if (tracker_req().kind == tracker_request::scrape_request)
|
||||||
{
|
{
|
||||||
std::string ih;
|
std::string ih;
|
||||||
std::copy(tracker_req().info_hash.begin(), tracker_req().info_hash.end()
|
std::copy(tracker_req().info_hash.begin(), tracker_req().info_hash.end()
|
||||||
, std::back_inserter(ih));
|
, std::back_inserter(ih));
|
||||||
entry scrape_data = e["files"][ih];
|
entry scrape_data = e["files"][ih];
|
||||||
int complete = scrape_data["complete"].integer();
|
|
||||||
int incomplete = scrape_data["incomplete"].integer();
|
int complete = -1;
|
||||||
cb->tracker_response(tracker_request(), peer_list, 0, complete
|
int incomplete = -1;
|
||||||
, incomplete);
|
int downloaded = -1;
|
||||||
|
|
||||||
|
entry const* complete_ent = scrape_data.find_key("complete");
|
||||||
|
if (complete_ent && complete_ent->type() == entry::int_t)
|
||||||
|
complete = complete_ent->integer();
|
||||||
|
|
||||||
|
entry const* incomplete_ent = scrape_data.find_key("incomplete");
|
||||||
|
if (incomplete_ent && incomplete_ent->type() == entry::int_t)
|
||||||
|
incomplete = incomplete_ent->integer();
|
||||||
|
|
||||||
|
entry const* downloaded_ent = scrape_data.find_key("downloaded");
|
||||||
|
if (downloaded_ent && downloaded_ent->type() == entry::int_t)
|
||||||
|
downloaded = downloaded_ent->integer();
|
||||||
|
|
||||||
|
cb->tracker_scrape_response(tracker_req(), complete
|
||||||
|
, incomplete, downloaded);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<peer_entry> peer_list;
|
||||||
int interval = (int)e["interval"].integer();
|
int interval = (int)e["interval"].integer();
|
||||||
|
|
||||||
if (e["peers"].type() == entry::string_t)
|
if (e["peers"].type() == entry::string_t)
|
||||||
|
@ -965,16 +979,16 @@ namespace libtorrent
|
||||||
try { incomplete = e["incomplete"].integer(); }
|
try { incomplete = e["incomplete"].integer(); }
|
||||||
catch(type_error&) {}
|
catch(type_error&) {}
|
||||||
|
|
||||||
cb->tracker_response(tracker_request(), peer_list, interval, complete
|
cb->tracker_response(tracker_req(), peer_list, interval, complete
|
||||||
, incomplete);
|
, incomplete);
|
||||||
}
|
}
|
||||||
catch(type_error& e)
|
catch(type_error& e)
|
||||||
{
|
{
|
||||||
cb->tracker_request_error(tracker_request(), m_parser.status_code(), e.what());
|
cb->tracker_request_error(tracker_req(), m_parser.status_code(), e.what());
|
||||||
}
|
}
|
||||||
catch(std::runtime_error& e)
|
catch(std::runtime_error& e)
|
||||||
{
|
{
|
||||||
cb->tracker_request_error(tracker_request(), m_parser.status_code(), e.what());
|
cb->tracker_request_error(tracker_req(), m_parser.status_code(), e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -492,6 +492,21 @@ namespace libtorrent
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void torrent::scrape_tracker()
|
||||||
|
{
|
||||||
|
if (m_trackers.empty()) return;
|
||||||
|
|
||||||
|
TORRENT_ASSERT(m_currently_trying_tracker >= 0);
|
||||||
|
TORRENT_ASSERT(m_currently_trying_tracker < int(m_trackers.size()));
|
||||||
|
|
||||||
|
tracker_request req;
|
||||||
|
req.info_hash = m_torrent_file->info_hash();
|
||||||
|
req.kind = tracker_request::scrape_request;
|
||||||
|
req.url = m_trackers[m_currently_trying_tracker].url;
|
||||||
|
m_ses.m_tracker_manager.queue_request(m_ses.m_strand, m_ses.m_half_open, req
|
||||||
|
, tracker_login(), m_ses.m_listen_interface.address(), shared_from_this());
|
||||||
|
}
|
||||||
|
|
||||||
// returns true if it is time for this torrent to make another
|
// returns true if it is time for this torrent to make another
|
||||||
// tracker request
|
// tracker request
|
||||||
bool torrent::should_request()
|
bool torrent::should_request()
|
||||||
|
@ -520,6 +535,26 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void torrent::tracker_scrape_response(tracker_request const& req
|
||||||
|
, int complete, int incomplete, int downloaded)
|
||||||
|
{
|
||||||
|
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
||||||
|
|
||||||
|
INVARIANT_CHECK;
|
||||||
|
TORRENT_ASSERT(req.kind == tracker_request::scrape_request);
|
||||||
|
|
||||||
|
if (complete >= 0) m_complete = complete;
|
||||||
|
if (incomplete >= 0) m_incomplete = incomplete;
|
||||||
|
|
||||||
|
if (m_ses.m_alerts.should_post(alert::info))
|
||||||
|
{
|
||||||
|
std::stringstream s;
|
||||||
|
s << "Got scrape response from tracker: " << req.url;
|
||||||
|
m_ses.m_alerts.post_alert(scrape_reply_alert(
|
||||||
|
get_handle(), m_incomplete, m_complete, s.str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void torrent::tracker_response(
|
void torrent::tracker_response(
|
||||||
tracker_request const&
|
tracker_request const&
|
||||||
, std::vector<peer_entry>& peer_list
|
, std::vector<peer_entry>& peer_list
|
||||||
|
@ -530,6 +565,7 @@ namespace libtorrent
|
||||||
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
||||||
|
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
TORRENT_ASSERT(r.kind == tracker_request::announce_request);
|
||||||
|
|
||||||
m_failed_trackers = 0;
|
m_failed_trackers = 0;
|
||||||
// announce intervals less than 5 minutes
|
// announce intervals less than 5 minutes
|
||||||
|
@ -606,8 +642,7 @@ namespace libtorrent
|
||||||
if (m_ses.m_alerts.should_post(alert::info))
|
if (m_ses.m_alerts.should_post(alert::info))
|
||||||
{
|
{
|
||||||
std::stringstream s;
|
std::stringstream s;
|
||||||
s << "Got response from tracker: "
|
s << "Got response from tracker: " << r.url;
|
||||||
<< m_trackers[m_last_working_tracker].url;
|
|
||||||
m_ses.m_alerts.post_alert(tracker_reply_alert(
|
m_ses.m_alerts.post_alert(tracker_reply_alert(
|
||||||
get_handle(), peer_list.size(), s.str()));
|
get_handle(), peer_list.size(), s.str()));
|
||||||
}
|
}
|
||||||
|
@ -2860,8 +2895,12 @@ namespace libtorrent
|
||||||
|
|
||||||
torrent_status st;
|
torrent_status st;
|
||||||
|
|
||||||
st.num_peers = (int)std::count_if(m_connections.begin(), m_connections.end(),
|
st.num_peers = (int)std::count_if(m_connections.begin(), m_connections.end()
|
||||||
!boost::bind(&peer_connection::is_connecting, _1));
|
, !boost::bind(&peer_connection::is_connecting, _1));
|
||||||
|
|
||||||
|
st.list_peers = std::distance(m_policy.begin_peer(), m_policy.end_peer());
|
||||||
|
st.list_seeds = (int)std::count_if(m_policy.begin_peer(), m_policy.end_peer()
|
||||||
|
, boost::bind(&policy::peer::seed, bind(&policy::iterator::value_type::second, _1)));
|
||||||
|
|
||||||
st.storage_mode = m_storage_mode;
|
st.storage_mode = m_storage_mode;
|
||||||
|
|
||||||
|
@ -2992,7 +3031,7 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
|
|
||||||
void torrent::tracker_request_timed_out(
|
void torrent::tracker_request_timed_out(
|
||||||
tracker_request const&)
|
tracker_request const& r)
|
||||||
{
|
{
|
||||||
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
||||||
|
|
||||||
|
@ -3005,19 +3044,26 @@ namespace libtorrent
|
||||||
if (m_ses.m_alerts.should_post(alert::warning))
|
if (m_ses.m_alerts.should_post(alert::warning))
|
||||||
{
|
{
|
||||||
std::stringstream s;
|
std::stringstream s;
|
||||||
s << "tracker: \""
|
s << "tracker: \"" << r.url << "\" timed out";
|
||||||
<< m_trackers[m_currently_trying_tracker].url
|
if (r.kind == tracker_request::announce_request)
|
||||||
<< "\" timed out";
|
{
|
||||||
m_ses.m_alerts.post_alert(tracker_alert(get_handle()
|
m_ses.m_alerts.post_alert(tracker_alert(get_handle()
|
||||||
, m_failed_trackers + 1, 0, s.str()));
|
, m_failed_trackers + 1, 0, s.str()));
|
||||||
}
|
}
|
||||||
|
else if (r.kind == tracker_request::scrape_request)
|
||||||
|
{
|
||||||
|
m_ses.m_alerts.post_alert(scrape_failed_alert(get_handle(), s.str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r.kind == tracker_request::announce_request)
|
||||||
try_next_tracker();
|
try_next_tracker();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: with some response codes, we should just consider
|
// TODO: with some response 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(tracker_request const&
|
void torrent::tracker_request_error(tracker_request const& r
|
||||||
, int response_code, const std::string& str)
|
, int response_code, const std::string& str)
|
||||||
{
|
{
|
||||||
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
||||||
|
@ -3030,13 +3076,19 @@ namespace libtorrent
|
||||||
if (m_ses.m_alerts.should_post(alert::warning))
|
if (m_ses.m_alerts.should_post(alert::warning))
|
||||||
{
|
{
|
||||||
std::stringstream s;
|
std::stringstream s;
|
||||||
s << "tracker: \""
|
s << "tracker: \"" << r.url << "\" " << str;
|
||||||
<< m_trackers[m_currently_trying_tracker].url
|
if (r.kind == tracker_request::announce_request)
|
||||||
<< "\" " << str;
|
{
|
||||||
m_ses.m_alerts.post_alert(tracker_alert(get_handle()
|
m_ses.m_alerts.post_alert(tracker_alert(get_handle()
|
||||||
, m_failed_trackers + 1, response_code, s.str()));
|
, m_failed_trackers + 1, response_code, s.str()));
|
||||||
}
|
}
|
||||||
|
else if (r.kind == tracker_request::scrape_request)
|
||||||
|
{
|
||||||
|
m_ses.m_alerts.post_alert(scrape_failed_alert(get_handle(), s.str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r.kind == tracker_request::announce_request)
|
||||||
try_next_tracker();
|
try_next_tracker();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -863,6 +863,20 @@ namespace libtorrent
|
||||||
t->force_tracker_request();
|
t->force_tracker_request();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void torrent_handle::scrape_tracker() const
|
||||||
|
{
|
||||||
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
|
if (m_ses == 0) throw_invalid_handle();
|
||||||
|
TORRENT_ASSERT(m_chk);
|
||||||
|
|
||||||
|
session_impl::mutex_t::scoped_lock l(m_ses->m_mutex);
|
||||||
|
boost::shared_ptr<torrent> t = m_ses->find_torrent(m_info_hash).lock();
|
||||||
|
if (!t) throw_invalid_handle();
|
||||||
|
|
||||||
|
t->scrape_tracker();
|
||||||
|
}
|
||||||
|
|
||||||
void torrent_handle::set_ratio(float ratio) const
|
void torrent_handle::set_ratio(float ratio) const
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|
|
@ -359,7 +359,7 @@ namespace libtorrent
|
||||||
|
|
||||||
tracker_connection::tracker_connection(
|
tracker_connection::tracker_connection(
|
||||||
tracker_manager& man
|
tracker_manager& man
|
||||||
, tracker_request req
|
, tracker_request const& req
|
||||||
, asio::strand& str
|
, asio::strand& str
|
||||||
, address bind_interface_
|
, address bind_interface_
|
||||||
, boost::weak_ptr<request_callback> r)
|
, boost::weak_ptr<request_callback> r)
|
||||||
|
|
|
@ -548,7 +548,7 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
|
|
||||||
int complete = detail::read_int32(buf);
|
int complete = detail::read_int32(buf);
|
||||||
/*int downloaded = */detail::read_int32(buf);
|
int downloaded = detail::read_int32(buf);
|
||||||
int incomplete = detail::read_int32(buf);
|
int incomplete = detail::read_int32(buf);
|
||||||
|
|
||||||
boost::shared_ptr<request_callback> cb = requester();
|
boost::shared_ptr<request_callback> cb = requester();
|
||||||
|
@ -559,9 +559,8 @@ namespace libtorrent
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<peer_entry> peer_list;
|
cb->tracker_scrape_response(tracker_req()
|
||||||
cb->tracker_response(tracker_req(), peer_list, 0
|
, complete, incomplete, downloaded);
|
||||||
, complete, incomplete);
|
|
||||||
|
|
||||||
m_man.remove_request(this);
|
m_man.remove_request(this);
|
||||||
close();
|
close();
|
||||||
|
|
Loading…
Reference in New Issue