added scrape support

This commit is contained in:
Arvid Norberg 2007-11-20 22:46:27 +00:00
parent cf6740e996
commit fabfe6cd50
9 changed files with 167 additions and 40 deletions

View File

@ -82,6 +82,35 @@ namespace libtorrent
{ 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
{
tracker_reply_alert(torrent_handle const& h

View File

@ -309,6 +309,8 @@ namespace libtorrent
virtual void tracker_request_error(tracker_request const& r
, int response_code, const std::string& str);
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
// to the tracker
@ -332,6 +334,7 @@ namespace libtorrent
// forcefully sets next_announce to the current time
void force_tracker_request();
void force_tracker_request(ptime);
void scrape_tracker();
// sets the username and password that will be sent to
// the tracker

View File

@ -94,15 +94,17 @@ namespace libtorrent
, upload_rate(0)
, download_payload_rate(0)
, upload_payload_rate(0)
, num_seeds(0)
, num_peers(0)
, num_complete(-1)
, num_incomplete(-1)
, list_seeds(0)
, list_peers(0)
, pieces(0)
, num_pieces(0)
, total_done(0)
, total_wanted_done(0)
, total_wanted(0)
, num_seeds(0)
, distributed_copies(0.f)
, block_size(0)
, num_uploads(0)
@ -159,8 +161,12 @@ namespace libtorrent
float download_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
// is connected to.
// is connected to (including seeds).
int num_peers;
// if the tracker sends scrape info in its
@ -171,6 +177,15 @@ namespace libtorrent
int num_complete;
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;
// this is the number of pieces the client has
@ -193,10 +208,6 @@ namespace libtorrent
// in case any pieces are filtered as not 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.
// note that one copy may be spread out among many peers.
//
@ -345,6 +356,9 @@ namespace libtorrent
// timed out.
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
// have metadata it returns the name assigned to it
// when it was added.

View File

@ -122,6 +122,8 @@ namespace libtorrent
request_callback(): m_manager(0) {}
virtual ~request_callback() {}
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(
tracker_request const&
, std::vector<peer_entry>& peers
@ -191,7 +193,7 @@ namespace libtorrent
: timeout_handler
{
tracker_connection(tracker_manager& man
, tracker_request req
, tracker_request const& req
, asio::strand& str
, address bind_interface
, boost::weak_ptr<request_callback> r);

View File

@ -797,7 +797,7 @@ namespace libtorrent
return;
}
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))
{
close();
@ -897,21 +897,35 @@ namespace libtorrent
}
catch(type_error const&) {}
std::vector<peer_entry> peer_list;
if (tracker_req().kind == tracker_request::scrape_request)
{
std::string ih;
std::copy(tracker_req().info_hash.begin(), tracker_req().info_hash.end()
, std::back_inserter(ih));
entry scrape_data = e["files"][ih];
int complete = scrape_data["complete"].integer();
int incomplete = scrape_data["incomplete"].integer();
cb->tracker_response(tracker_request(), peer_list, 0, complete
, incomplete);
int complete = -1;
int incomplete = -1;
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;
}
std::vector<peer_entry> peer_list;
int interval = (int)e["interval"].integer();
if (e["peers"].type() == entry::string_t)
@ -965,16 +979,16 @@ namespace libtorrent
try { incomplete = e["incomplete"].integer(); }
catch(type_error&) {}
cb->tracker_response(tracker_request(), peer_list, interval, complete
cb->tracker_response(tracker_req(), peer_list, interval, complete
, incomplete);
}
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)
{
cb->tracker_request_error(tracker_request(), m_parser.status_code(), e.what());
cb->tracker_request_error(tracker_req(), m_parser.status_code(), e.what());
}
}

View File

@ -492,6 +492,21 @@ namespace libtorrent
#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
// tracker 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(
tracker_request const&
, std::vector<peer_entry>& peer_list
@ -530,6 +565,7 @@ namespace libtorrent
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
INVARIANT_CHECK;
TORRENT_ASSERT(r.kind == tracker_request::announce_request);
m_failed_trackers = 0;
// announce intervals less than 5 minutes
@ -606,8 +642,7 @@ namespace libtorrent
if (m_ses.m_alerts.should_post(alert::info))
{
std::stringstream s;
s << "Got response from tracker: "
<< m_trackers[m_last_working_tracker].url;
s << "Got response from tracker: " << r.url;
m_ses.m_alerts.post_alert(tracker_reply_alert(
get_handle(), peer_list.size(), s.str()));
}
@ -2860,8 +2895,12 @@ namespace libtorrent
torrent_status st;
st.num_peers = (int)std::count_if(m_connections.begin(), m_connections.end(),
!boost::bind(&peer_connection::is_connecting, _1));
st.num_peers = (int)std::count_if(m_connections.begin(), m_connections.end()
, !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;
@ -2992,7 +3031,7 @@ namespace libtorrent
}
void torrent::tracker_request_timed_out(
tracker_request const&)
tracker_request const& r)
{
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))
{
std::stringstream s;
s << "tracker: \""
<< m_trackers[m_currently_trying_tracker].url
<< "\" timed out";
m_ses.m_alerts.post_alert(tracker_alert(get_handle()
, m_failed_trackers + 1, 0, s.str()));
s << "tracker: \"" << r.url << "\" timed out";
if (r.kind == tracker_request::announce_request)
{
m_ses.m_alerts.post_alert(tracker_alert(get_handle()
, 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()));
}
}
try_next_tracker();
if (r.kind == tracker_request::announce_request)
try_next_tracker();
}
// TODO: with some response codes, we should just consider
// the tracker as a failure and not retry
// 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)
{
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
@ -3030,14 +3076,20 @@ namespace libtorrent
if (m_ses.m_alerts.should_post(alert::warning))
{
std::stringstream s;
s << "tracker: \""
<< m_trackers[m_currently_trying_tracker].url
<< "\" " << str;
m_ses.m_alerts.post_alert(tracker_alert(get_handle()
, m_failed_trackers + 1, response_code, s.str()));
s << "tracker: \"" << r.url << "\" " << str;
if (r.kind == tracker_request::announce_request)
{
m_ses.m_alerts.post_alert(tracker_alert(get_handle()
, 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()));
}
}
try_next_tracker();
if (r.kind == tracker_request::announce_request)
try_next_tracker();
}

View File

@ -863,6 +863,20 @@ namespace libtorrent
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
{
INVARIANT_CHECK;

View File

@ -359,7 +359,7 @@ namespace libtorrent
tracker_connection::tracker_connection(
tracker_manager& man
, tracker_request req
, tracker_request const& req
, asio::strand& str
, address bind_interface_
, boost::weak_ptr<request_callback> r)

View File

@ -548,7 +548,7 @@ namespace libtorrent
}
int complete = detail::read_int32(buf);
/*int downloaded = */detail::read_int32(buf);
int downloaded = detail::read_int32(buf);
int incomplete = detail::read_int32(buf);
boost::shared_ptr<request_callback> cb = requester();
@ -559,9 +559,8 @@ namespace libtorrent
return;
}
std::vector<peer_entry> peer_list;
cb->tracker_response(tracker_req(), peer_list, 0
, complete, incomplete);
cb->tracker_scrape_response(tracker_req()
, complete, incomplete, downloaded);
m_man.remove_request(this);
close();