Skip to content

Commit

Permalink
Merge pull request #128 from vktr/better-reannounce-action
Browse files Browse the repository at this point in the history
Make reannouncing action better
  • Loading branch information
vktr committed Feb 12, 2023
2 parents 606bc7f + c61fc6e commit b907f70
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 4 deletions.
3 changes: 2 additions & 1 deletion src/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,8 @@ std::unique_ptr<Config> Config::Load(const boost::program_options::variables_map
// the config are applied, and cannot be overwritten by it.
lt::alert_category_t alerts =
lt::alert::status_notification
| lt::alert::storage_notification;
| lt::alert::storage_notification
| lt::alert::tracker_notification;

if (cfg->mediainfo_enabled.value_or(false))
{
Expand Down
12 changes: 12 additions & 0 deletions src/session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -746,6 +746,18 @@ void Session::ReadAlerts()

break;
}
case lt::tracker_error_alert::alert_type:
{
const auto tea = lt::alert_cast<lt::tracker_error_alert>(alert);
m_torrentTrackerError(tea);
break;
}
case lt::tracker_reply_alert::alert_type:
{
const auto tra = lt::alert_cast<lt::tracker_reply_alert>(alert);
m_torrentTrackerReply(tra->handle);
break;
}
}
}
}
15 changes: 15 additions & 0 deletions src/session.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ namespace porla
typedef boost::signals2::signal<void(const libtorrent::torrent_handle&)> TorrentHandleSignal;
typedef boost::signals2::signal<void(const libtorrent::torrent_status&)> TorrentStatusSignal;
typedef boost::signals2::signal<void(const std::vector<libtorrent::torrent_status>&)> TorrentStatusListSignal;
typedef boost::signals2::signal<void(const lt::tracker_error_alert*)> TrackerErrorSignal;

virtual boost::signals2::connection OnSessionStats(const SessionStatsSignal::slot_type& subscriber) = 0;
virtual boost::signals2::connection OnStateUpdate(const TorrentStatusListSignal::slot_type& subscriber) = 0;
Expand All @@ -51,6 +52,8 @@ namespace porla
virtual boost::signals2::connection OnTorrentPaused(const TorrentStatusSignal::slot_type& subscriber) = 0;
virtual boost::signals2::connection OnTorrentRemoved(const InfoHashSignal::slot_type& subscriber) = 0;
virtual boost::signals2::connection OnTorrentResumed(const TorrentStatusSignal::slot_type& subscriber) = 0;
virtual boost::signals2::connection OnTorrentTrackerError(const TrackerErrorSignal::slot_type& subscriber) = 0;
virtual boost::signals2::connection OnTorrentTrackerReply(const TorrentHandleSignal::slot_type& subscriber) = 0;

virtual libtorrent::info_hash_t AddTorrent(libtorrent::add_torrent_params const& p) = 0;
virtual void ApplySettings(const libtorrent::settings_pack& settings) = 0;
Expand Down Expand Up @@ -124,6 +127,16 @@ namespace porla
return m_torrentResumed.connect(subscriber);
}

boost::signals2::connection OnTorrentTrackerError(const TrackerErrorSignal::slot_type& subscriber) override
{
return m_torrentTrackerError.connect(subscriber);
}

boost::signals2::connection OnTorrentTrackerReply(const TorrentHandleSignal::slot_type& subscriber) override
{
return m_torrentTrackerReply.connect(subscriber);
}

void Load();

libtorrent::info_hash_t AddTorrent(libtorrent::add_torrent_params const& p) override;
Expand Down Expand Up @@ -161,6 +174,8 @@ namespace porla
TorrentStatusSignal m_torrentPaused;
InfoHashSignal m_torrentRemoved;
TorrentStatusSignal m_torrentResumed;
TrackerErrorSignal m_torrentTrackerError;
TorrentHandleSignal m_torrentTrackerReply;

sqlite3* m_db;

Expand Down
97 changes: 94 additions & 3 deletions src/workflows/actions/torrents/reannounce.cpp
Original file line number Diff line number Diff line change
@@ -1,16 +1,33 @@
#include "reannounce.hpp"

#include <boost/log/trivial.hpp>
#include <libtorrent/alert_types.hpp>

#include "../../../json/lttorrentstatus.hpp"
#include "../../../session.hpp"

using porla::Workflows::Actions::Torrents::Reannounce;

struct Reannounce::TorrentReannounceState
{
std::shared_ptr<ActionCallback> callback;
int current_tries{0};
int max_tries{24};
int timeout{5};
};

Reannounce::Reannounce(porla::ISession& session)
: m_session(session)
{
m_torrent_tracker_error_connection = m_session.OnTorrentTrackerError([this](auto && th) { OnTorrentTrackerError(th); });
m_torrent_tracker_reply_connection = m_session.OnTorrentTrackerReply([this](auto && th) { OnTorrentTrackerReply(th); });
}

Reannounce::~Reannounce() = default;
Reannounce::~Reannounce()
{
m_torrent_tracker_error_connection.disconnect();
m_torrent_tracker_reply_connection.disconnect();
}

void Reannounce::Invoke(const ActionParams& params, std::shared_ptr<ActionCallback> callback)
{
Expand All @@ -30,7 +47,81 @@ void Reannounce::Invoke(const ActionParams& params, std::shared_ptr<ActionCallba
return;
}

th->second.force_reannounce();
BOOST_LOG_TRIVIAL(info) << "Reannouncing torrent " << th->second.status().name;

// Force an immediate reannounce and ignore the min interval.
th->second.force_reannounce(0, -1, lt::torrent_handle::ignore_min_interval);

auto state = std::make_unique<TorrentReannounceState>();
state->callback = callback;
state->current_tries = 0;
state->max_tries = 10;
state->timeout = 5;

if (params.Input().contains("max_tries"))
{
state->max_tries = params.Input()["max_tries"].get<int>();
}

if (params.Input().contains("timeout"))
{
state->timeout = params.Input()["timeout"].get<int>();
}

m_states.insert({ ts.info_hashes, std::move(state) });
}

void Reannounce::OnTorrentTrackerError(const libtorrent::tracker_error_alert* al)
{
auto ctx = m_states.find(al->handle.info_hashes());
if (ctx == m_states.end()) return;

if (al->error && al->error.value() == lt::errors::tracker_failure)
{
const std::vector<std::string> match_failures =
{
"not exist",
"not found",
"not registered",
"unregistered"
};

const std::string err = al->error_message();

for (const auto& failure_message : match_failures)
{
if (err.find(failure_message) != std::string::npos)
{
ctx->second->current_tries++;

if (ctx->second->current_tries >= ctx->second->max_tries)
{
BOOST_LOG_TRIVIAL(warning) << "Max reannounce attempts reached for " << al->torrent_name();
m_states.erase(ctx);
return;
}

BOOST_LOG_TRIVIAL(info)
<< "Reannouncing torrent " << al->torrent_name()
<< " - attempt " << ctx->second->current_tries << " of " << ctx->second->max_tries;

al->handle.force_reannounce(ctx->second->timeout, -1, lt::torrent_handle::ignore_min_interval);

return;
}
}
}
}

void Reannounce::OnTorrentTrackerReply(const libtorrent::torrent_handle& th)
{
auto ctx = m_states.find(th.info_hashes());
if (ctx == m_states.end()) return;

BOOST_LOG_TRIVIAL(info) << "Reannouncing done";

callback->Complete({});
ctx->second->callback->Complete(true);

m_states.erase(ctx);
}

9 changes: 9 additions & 0 deletions src/workflows/actions/torrents/reannounce.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@ namespace porla::Workflows::Actions::Torrents
void Invoke(const ActionParams& params, std::shared_ptr<ActionCallback> callback) override;

private:
void OnTorrentTrackerError(const libtorrent::tracker_error_alert* al);
void OnTorrentTrackerReply(const libtorrent::torrent_handle& th);

struct TorrentReannounceState;

boost::signals2::connection m_torrent_tracker_error_connection;
boost::signals2::connection m_torrent_tracker_reply_connection;

ISession& m_session;
std::map<libtorrent::info_hash_t, std::unique_ptr<TorrentReannounceState>> m_states;
};
}
12 changes: 12 additions & 0 deletions tests/inmemorysession.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,16 @@ class InMemorySession : public porla::ISession
return m_torrentResumed.connect(subscriber);
}

boost::signals2::connection OnTorrentTrackerError(const TrackerErrorSignal::slot_type& subscriber) override
{
return m_torrentTrackerError.connect(subscriber);
}

boost::signals2::connection OnTorrentTrackerReply(const TorrentHandleSignal::slot_type& subscriber) override
{
return m_torrentTrackerReply.connect(subscriber);
}

libtorrent::info_hash_t AddTorrent(libtorrent::add_torrent_params const& p) override;
void ApplySettings(const libtorrent::settings_pack& settings) override;
void Pause() override;
Expand All @@ -74,6 +84,8 @@ class InMemorySession : public porla::ISession
TorrentStatusSignal m_torrentPaused;
InfoHashSignal m_torrentRemoved;
TorrentStatusSignal m_torrentResumed;
TrackerErrorSignal m_torrentTrackerError;
TorrentHandleSignal m_torrentTrackerReply;

std::map<lt::info_hash_t, lt::torrent_handle> m_torrents;
};

0 comments on commit b907f70

Please sign in to comment.