diff --git a/ChangeLog b/ChangeLog index f6280b660..70baeec7d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,5 @@ + * tracker response alerts from user initiated announces/scrapes are now + posted regardless of alert mask * improve DHT performance when changing external IP (primarily affects bootstrapping). * add feature to stop torrents immediately after checking files is done diff --git a/include/libtorrent/announce_entry.hpp b/include/libtorrent/announce_entry.hpp index 865d86a28..c4308d986 100644 --- a/include/libtorrent/announce_entry.hpp +++ b/include/libtorrent/announce_entry.hpp @@ -157,6 +157,9 @@ namespace libtorrent // this is false the stats sent to this tracker will be 0 bool send_stats:1; + // internal + bool triggered_manually:1; + // reset announce counters and clears the started sent flag. // The announce_entry will look like we've never talked to // the tracker. diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp index 9aae7b2b1..64258f044 100644 --- a/include/libtorrent/torrent.hpp +++ b/include/libtorrent/torrent.hpp @@ -722,7 +722,7 @@ namespace libtorrent // forcefully sets next_announce to the current time void force_tracker_request(time_point, int tracker_idx); - void scrape_tracker(); + void scrape_tracker(bool user_triggered); void announce_with_tracker(boost::uint8_t e = tracker_request::none , address const& bind_interface = address_v4::any()); diff --git a/include/libtorrent/tracker_manager.hpp b/include/libtorrent/tracker_manager.hpp index 3928335bc..c863785a0 100644 --- a/include/libtorrent/tracker_manager.hpp +++ b/include/libtorrent/tracker_manager.hpp @@ -99,6 +99,7 @@ namespace libtorrent , key(0) , num_want(0) , send_stats(true) + , triggered_manually(false) #ifdef TORRENT_USE_OPENSSL , ssl_ctx(0) #endif @@ -154,6 +155,11 @@ namespace libtorrent address bind_ip; bool send_stats; + + // this is set to true if this request was triggered by a "manual" call to + // scrape_tracker() or force_reannounce() + bool triggered_manually; + #ifdef TORRENT_USE_OPENSSL boost::asio::ssl::context* ssl_ctx; #endif diff --git a/src/announce_entry.cpp b/src/announce_entry.cpp index de1e39e07..719aa3d77 100644 --- a/src/announce_entry.cpp +++ b/src/announce_entry.cpp @@ -62,6 +62,7 @@ namespace libtorrent , start_sent(false) , complete_sent(false) , send_stats(true) + , triggered_manually(false) {} announce_entry::announce_entry() @@ -79,6 +80,7 @@ namespace libtorrent , start_sent(false) , complete_sent(false) , send_stats(true) + , triggered_manually(false) {} announce_entry::~announce_entry() {} diff --git a/src/session_impl.cpp b/src/session_impl.cpp index 6b8278282..7753a45be 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -3219,7 +3219,9 @@ retry: torrent& t = *want_scrape[m_next_scrape_torrent]; TORRENT_ASSERT(t.is_paused() && t.is_auto_managed()); - t.scrape_tracker(); + // false means it's not triggered by the user, but automatically + // by libtorrent + t.scrape_tracker(false); ++m_next_scrape_torrent; if (m_next_scrape_torrent >= int(want_scrape.size())) diff --git a/src/torrent.cpp b/src/torrent.cpp index 2a0492f34..82d064375 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -2887,16 +2887,17 @@ namespace libtorrent #if defined TORRENT_ASIO_DEBUGGING complete_async("tracker::on_tracker_announce_disp"); #endif - if (e) return; boost::shared_ptr t = p.lock(); if (!t) return; + t->m_waiting_tracker = false; + + if (e) return; t->on_tracker_announce(); } void torrent::on_tracker_announce() { TORRENT_ASSERT(is_single_thread()); - m_waiting_tracker = false; if (m_abort) return; announce_with_tracker(); } @@ -3148,8 +3149,6 @@ namespace libtorrent , ae.tier, tier, ae.is_working(), ae.fails, ae.fail_limit , ae.updating, ae.can_announce(now, is_seed()), sent_announce); #endif - // if trackerid is not specified for tracker use default one, probably set explicitly - req.trackerid = ae.trackerid.empty() ? m_trackerid : ae.trackerid; if (settings().get_bool(settings_pack::announce_to_all_tiers) && !settings().get_bool(settings_pack::announce_to_all_trackers) && sent_announce @@ -3157,6 +3156,9 @@ namespace libtorrent && tier != INT_MAX) continue; + // if trackerid is not specified for tracker use default one, probably set explicitly + req.trackerid = ae.trackerid.empty() ? m_trackerid : ae.trackerid; + if (ae.tier > tier && sent_announce && !settings().get_bool(settings_pack::announce_to_all_tiers)) break; if (ae.is_working()) { tier = ae.tier; sent_announce = false; } @@ -3175,6 +3177,9 @@ namespace libtorrent else if (!ae.complete_sent && is_seed()) req.event = tracker_request::completed; } + req.triggered_manually = ae.triggered_manually; + ae.triggered_manually = false; + req.bind_ip = bind_interface; if (settings().get_bool(settings_pack::force_proxy)) @@ -3191,7 +3196,8 @@ namespace libtorrent && proxy_type == settings_pack::none) { ae.next_announce = now + minutes(10); - if (m_ses.alerts().should_post()) + if (m_ses.alerts().should_post() + || req.triggered_manually) { m_ses.alerts().emplace_alert(get_handle() , anonymous_mode_alert::tracker_not_anonymous, req.url); @@ -3208,7 +3214,8 @@ namespace libtorrent && proxy_type != settings_pack::i2p_proxy) { ae.next_announce = now + minutes(10); - if (m_ses.alerts().should_post()) + if (m_ses.alerts().should_post() + || req.triggered_manually) { m_ses.alerts().emplace_alert(get_handle() , anonymous_mode_alert::tracker_not_anonymous, req.url); @@ -3268,7 +3275,7 @@ namespace libtorrent update_tracker_timer(now); } - void torrent::scrape_tracker() + void torrent::scrape_tracker(bool user_triggered) { TORRENT_ASSERT(is_single_thread()); m_last_scrape = m_ses.session_time(); @@ -3290,6 +3297,7 @@ namespace libtorrent req.auth = tracker_login(); #endif req.key = tracker_key(); + req.triggered_manually = user_triggered; m_ses.queue_tracker_request(req, shared_from_this()); } @@ -3327,7 +3335,11 @@ namespace libtorrent update_scrape_state(); } - if (m_ses.alerts().should_post()) + // if this was triggered manually we need to post this unconditionally, + // since the client expects a response from its action, regardless of + // whether all tracker events have been enabled by the alert mask + if (m_ses.alerts().should_post() + || req.triggered_manually) { m_ses.alerts().emplace_alert( get_handle(), incomplete, complete, req.url); @@ -3538,7 +3550,9 @@ namespace libtorrent update_want_peers(); - if (m_ses.alerts().should_post()) + // post unconditionally if the announce was triggered manually + if (m_ses.alerts().should_post() + || r.triggered_manually) { m_ses.alerts().emplace_alert( get_handle(), resp.peers.size() + resp.peers4.size() @@ -3681,6 +3695,9 @@ namespace libtorrent return m_waiting_tracker?m_tracker_timer.expires_at():min_time(); } + // this is the entry point for the client to force a re-announce. It's + // considered a client-initiated announce (as opposed to the regular ones, + // issued by libtorrent) void torrent::force_tracker_request(time_point t, int tracker_idx) { if (is_paused()) return; @@ -3688,7 +3705,10 @@ namespace libtorrent { for (std::vector::iterator i = m_trackers.begin() , end(m_trackers.end()); i != end; ++i) + { i->next_announce = (std::max)(t, i->min_announce) + seconds(1); + i->triggered_manually = true; + } } else { @@ -3697,6 +3717,7 @@ namespace libtorrent return; announce_entry& e = m_trackers[tracker_idx]; e.next_announce = (std::max)(t, e.min_announce) + seconds(1); + e.triggered_manually = true; } update_tracker_timer(clock_type::now()); } @@ -12139,6 +12160,7 @@ namespace libtorrent #endif if (0 == (r.kind & tracker_request::scrape_request)) { + // announce request announce_entry* ae = find_tracker(r); if (ae) { @@ -12154,14 +12176,16 @@ namespace libtorrent deprioritize_tracker(tracker_index); } - if (m_ses.alerts().should_post()) + if (m_ses.alerts().should_post() + || r.triggered_manually) { m_ses.alerts().emplace_alert(get_handle() , ae?ae->fails:0, response_code, r.url, ec, msg); } } - else if (0 != (r.kind & tracker_request::scrape_request)) + else { + // scrape request if (response_code == 410) { // never talk to this tracker again @@ -12169,7 +12193,11 @@ namespace libtorrent if (ae) ae->fail_limit = 1; } - if (m_ses.alerts().should_post()) + // if this was triggered manually we need to post this unconditionally, + // since the client expects a response from its action, regardless of + // whether all tracker events have been enabled by the alert mask + if (m_ses.alerts().should_post() + || r.triggered_manually) { m_ses.alerts().emplace_alert(get_handle(), r.url, ec); } diff --git a/src/torrent_handle.cpp b/src/torrent_handle.cpp index b4f951037..14bb9994f 100644 --- a/src/torrent_handle.cpp +++ b/src/torrent_handle.cpp @@ -802,7 +802,7 @@ namespace libtorrent void torrent_handle::scrape_tracker() const { - TORRENT_ASYNC_CALL(scrape_tracker); + TORRENT_ASYNC_CALL1(scrape_tracker, true); } void torrent_handle::super_seeding(bool on) const