mirror of
https://github.com/transmission/transmission
synced 2025-02-20 21:26:53 +00:00
Merge branch 'master' into patch-1
This commit is contained in:
commit
9e69a7d68b
10 changed files with 83 additions and 67 deletions
|
@ -1802,6 +1802,14 @@ static tr_tracker_view trackerView(tr_torrent const& tor, int tier_index, tr_tie
|
|||
return view;
|
||||
}
|
||||
|
||||
size_t tr_announcerTrackerCount(tr_torrent const* tor)
|
||||
{
|
||||
TR_ASSERT(tr_isTorrent(tor));
|
||||
TR_ASSERT(tor->tiers != nullptr);
|
||||
|
||||
return tor->tiers->tracker_count;
|
||||
}
|
||||
|
||||
tr_tracker_view tr_announcerTracker(tr_torrent const* tor, size_t nth)
|
||||
{
|
||||
TR_ASSERT(tr_isTorrent(tor));
|
||||
|
|
|
@ -95,6 +95,8 @@ time_t tr_announcerNextManualAnnounce(tr_torrent const*);
|
|||
|
||||
tr_tracker_view tr_announcerTracker(tr_torrent const* torrent, size_t i);
|
||||
|
||||
size_t tr_announcerTrackerCount(tr_torrent const* tor);
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
|
|
@ -375,7 +375,7 @@ static uint64_t loadName(tr_variant* dict, tr_torrent* tor)
|
|||
return 0;
|
||||
}
|
||||
|
||||
name = tr_strvDup(name);
|
||||
name = tr_strvStrip(name);
|
||||
if (std::empty(name))
|
||||
{
|
||||
return 0;
|
||||
|
|
|
@ -579,30 +579,36 @@ static void onTrackerResponse(tr_torrent* tor, tr_tracker_event const* event, vo
|
|||
****
|
||||
***/
|
||||
|
||||
static void tr_torrentInitFileOffsets(tr_torrent* tor)
|
||||
{
|
||||
auto offset = uint64_t{ 0 };
|
||||
static void torrentStart(tr_torrent* tor, bool bypass_queue);
|
||||
|
||||
static void tr_torrentFireMetadataCompleted(tr_torrent* tor);
|
||||
|
||||
static void torrentInitFromInfoDict(tr_torrent* tor)
|
||||
{
|
||||
tor->initSizes(tor->info.totalSize, tor->info.pieceSize);
|
||||
tor->completion = tr_completion{ tor, tor };
|
||||
tr_sha1(tor->obfuscatedHash, "req2", 4, tor->info.hash, SHA_DIGEST_LENGTH, nullptr);
|
||||
|
||||
// init file offsets
|
||||
auto offset = uint64_t{ 0 };
|
||||
for (tr_file_index_t i = 0, n = tor->fileCount(); i < n; ++i)
|
||||
{
|
||||
auto& file = tor->file(i);
|
||||
file.priv.offset = offset;
|
||||
offset += file.length;
|
||||
}
|
||||
|
||||
tor->fpm_.reset(tor->info);
|
||||
tor->file_priorities_.reset(&tor->fpm_);
|
||||
tor->files_wanted_.reset(&tor->fpm_);
|
||||
|
||||
tor->checked_pieces_ = tr_bitfield{ tor->info.pieceCount };
|
||||
}
|
||||
|
||||
static void torrentStart(tr_torrent* tor, bool bypass_queue);
|
||||
|
||||
static void tr_torrentFireMetadataCompleted(tr_torrent* tor);
|
||||
|
||||
void tr_torrentGotNewInfoDict(tr_torrent* tor)
|
||||
{
|
||||
tor->initSizes(tor->info.totalSize, tor->info.pieceSize);
|
||||
tor->completion = tr_completion{ tor, tor };
|
||||
tr_torrentInitFileOffsets(tor);
|
||||
|
||||
torrentInitFromInfoDict(tor);
|
||||
tr_peerMgrOnTorrentGotMetainfo(tor);
|
||||
|
||||
tr_torrentFireMetadataCompleted(tor);
|
||||
}
|
||||
|
||||
|
@ -654,25 +660,17 @@ static void refreshCurrentDir(tr_torrent* tor);
|
|||
|
||||
static void torrentInit(tr_torrent* tor, tr_ctor const* ctor)
|
||||
{
|
||||
static auto next_unique_id = int{ 1 };
|
||||
auto const lock = tor->unique_lock();
|
||||
|
||||
tr_session* session = tr_ctorGetSession(ctor);
|
||||
TR_ASSERT(session != nullptr);
|
||||
|
||||
static int nextUniqueId = 1;
|
||||
|
||||
tor->fpm_.reset(tor->info);
|
||||
tor->file_priorities_.reset(&tor->fpm_);
|
||||
tor->files_wanted_.reset(&tor->fpm_);
|
||||
|
||||
tor->session = session;
|
||||
tor->uniqueId = nextUniqueId++;
|
||||
tor->uniqueId = next_unique_id++;
|
||||
tor->queuePosition = tr_sessionCountTorrents(session);
|
||||
|
||||
tor->dnd_pieces_ = tr_bitfield{ tor->info.pieceCount };
|
||||
tor->checked_pieces_ = tr_bitfield{ tor->info.pieceCount };
|
||||
|
||||
tr_sha1(tor->obfuscatedHash, "req2", 4, tor->info.hash, SHA_DIGEST_LENGTH, nullptr);
|
||||
torrentInitFromInfoDict(tor);
|
||||
|
||||
char const* dir = nullptr;
|
||||
if (tr_ctorGetDownloadDir(ctor, TR_FORCE, &dir) || tr_ctorGetDownloadDir(ctor, TR_FALLBACK, &dir))
|
||||
|
@ -703,10 +701,6 @@ static void torrentInit(tr_torrent* tor, tr_ctor const* ctor)
|
|||
|
||||
tr_torrentSetDateAdded(tor, tr_time()); /* this is a default value to be overwritten by the resume file */
|
||||
|
||||
tor->initSizes(tor->info.totalSize, tor->info.pieceSize);
|
||||
tor->completion = tr_completion{ tor, tor };
|
||||
tr_torrentInitFileOffsets(tor);
|
||||
|
||||
// tr_torrentLoadResume() calls a lot of tr_torrentSetFoo() methods
|
||||
// that set things as dirty, but... these settings being loaded are
|
||||
// the same ones that would be saved back again, so don't let them
|
||||
|
@ -1260,7 +1254,7 @@ tr_tracker_view tr_torrentTracker(tr_torrent const* tor, size_t i)
|
|||
|
||||
size_t tr_torrentTrackerCount(tr_torrent const* tor)
|
||||
{
|
||||
return tor->trackerCount();
|
||||
return tr_announcerTrackerCount(tor);
|
||||
}
|
||||
|
||||
/***
|
||||
|
@ -1844,7 +1838,7 @@ static void torrentCallScript(tr_torrent const* tor, char const* script)
|
|||
struct tm tm;
|
||||
char ctime_str[32];
|
||||
tr_localtime_r(&now, &tm);
|
||||
strftime(ctime_str, sizeof(ctime_str), "%a %b %2e %T %Y%n", &tm); /* ctime equiv */
|
||||
strftime(ctime_str, sizeof(ctime_str), "%a %b %d %T %Y%n", &tm); /* ctime equiv */
|
||||
|
||||
char* const torrent_dir = tr_sys_path_native_separators(tr_strdup(tor->currentDir));
|
||||
|
||||
|
@ -1853,15 +1847,19 @@ static void torrentCallScript(tr_torrent const* tor, char const* script)
|
|||
nullptr,
|
||||
};
|
||||
|
||||
auto const id_str = std::to_string(tr_torrentId(tor));
|
||||
auto const labels_str = buildLabelsString(tor);
|
||||
auto const trackers_str = buildTrackersString(tor);
|
||||
|
||||
auto const env = std::map<std::string_view, std::string_view>{
|
||||
{ "TR_APP_VERSION"sv, SHORT_VERSION_STRING },
|
||||
{ "TR_TIME_LOCALTIME"sv, ctime_str },
|
||||
{ "TR_TORRENT_DIR"sv, torrent_dir },
|
||||
{ "TR_TORRENT_HASH"sv, tor->info.hashString },
|
||||
{ "TR_TORRENT_ID"sv, std::to_string(tr_torrentId(tor)) },
|
||||
{ "TR_TORRENT_LABELS"sv, buildLabelsString(tor) },
|
||||
{ "TR_TORRENT_ID"sv, id_str },
|
||||
{ "TR_TORRENT_LABELS"sv, labels_str },
|
||||
{ "TR_TORRENT_NAME"sv, tr_torrentName(tor) },
|
||||
{ "TR_TORRENT_TRACKERS"sv, buildTrackersString(tor) },
|
||||
{ "TR_TORRENT_TRACKERS"sv, trackers_str },
|
||||
};
|
||||
|
||||
tr_logAddTorInfo(tor, "Calling script \"%s\"", script);
|
||||
|
|
|
@ -348,13 +348,6 @@ public:
|
|||
return info.webseeds[i];
|
||||
}
|
||||
|
||||
/// TRACKERS
|
||||
|
||||
auto trackerCount() const
|
||||
{
|
||||
return info.trackerCount;
|
||||
}
|
||||
|
||||
/// CHECKSUMS
|
||||
|
||||
bool ensurePieceIsChecked(tr_piece_index_t piece)
|
||||
|
@ -374,7 +367,7 @@ public:
|
|||
return checked;
|
||||
}
|
||||
|
||||
void initCheckedPieces(tr_bitfield const& checked, time_t const* mtimes /*fileCount*/)
|
||||
void initCheckedPieces(tr_bitfield const& checked, time_t const* mtimes /*fileCount()*/)
|
||||
{
|
||||
TR_ASSERT(std::size(checked) == info.pieceCount);
|
||||
checked_pieces_ = checked;
|
||||
|
@ -398,8 +391,6 @@ public:
|
|||
|
||||
tr_info info = {};
|
||||
|
||||
tr_bitfield dnd_pieces_ = tr_bitfield{ 0 };
|
||||
|
||||
tr_bitfield checked_pieces_ = tr_bitfield{ 0 };
|
||||
|
||||
// TODO(ckerr): make private once some of torrent.cc's `tr_torrentFoo()` methods are member functions
|
||||
|
|
|
@ -1209,7 +1209,8 @@ int tr_variantToFile(tr_variant const* v, tr_variant_fmt fmt, char const* filena
|
|||
{
|
||||
auto error_code = int{ 0 };
|
||||
auto contents_len = size_t{};
|
||||
auto const* contents = tr_variantToStr(v, fmt, &contents_len);
|
||||
auto* const contents = tr_variantToStr(v, fmt, &contents_len);
|
||||
|
||||
tr_error* error = nullptr;
|
||||
tr_saveFile(filename, { contents, contents_len }, &error);
|
||||
if (error != nullptr)
|
||||
|
@ -1218,6 +1219,8 @@ int tr_variantToFile(tr_variant const* v, tr_variant_fmt fmt, char const* filena
|
|||
error_code = error->code;
|
||||
tr_error_clear(&error);
|
||||
}
|
||||
|
||||
tr_free(contents);
|
||||
return error_code;
|
||||
}
|
||||
|
||||
|
|
|
@ -248,10 +248,10 @@ static void write_block_func(void* vdata)
|
|||
|
||||
struct connection_succeeded_data
|
||||
{
|
||||
struct tr_webseed* webseed;
|
||||
char* real_url;
|
||||
tr_piece_index_t piece_index;
|
||||
uint32_t piece_offset;
|
||||
tr_webseed* webseed = nullptr;
|
||||
std::string real_url;
|
||||
tr_piece_index_t piece_index = 0;
|
||||
uint32_t piece_offset = 0;
|
||||
};
|
||||
|
||||
static void connection_succeeded(void* vdata)
|
||||
|
@ -265,7 +265,7 @@ static void connection_succeeded(void* vdata)
|
|||
w->consecutive_failures = w->retry_tickcount = w->retry_challenge = 0;
|
||||
}
|
||||
|
||||
if (data->real_url != nullptr)
|
||||
if (!std::empty(data->real_url))
|
||||
{
|
||||
tr_torrent const* const tor = tr_torrentFindFromId(w->session, w->torrent_id);
|
||||
|
||||
|
@ -275,12 +275,10 @@ static void connection_succeeded(void* vdata)
|
|||
auto file_offset = uint64_t{};
|
||||
tr_ioFindFileLocation(tor, data->piece_index, data->piece_offset, &file_index, &file_offset);
|
||||
w->file_urls[file_index].assign(data->real_url);
|
||||
data->real_url = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
tr_free(data->real_url);
|
||||
tr_free(data);
|
||||
delete data;
|
||||
}
|
||||
|
||||
/***
|
||||
|
@ -308,15 +306,17 @@ static void on_content_changed(struct evbuffer* buf, struct evbuffer_cb_info con
|
|||
|
||||
if (task->response_code == 206)
|
||||
{
|
||||
auto* const data = tr_new(struct connection_succeeded_data, 1);
|
||||
data->webseed = w;
|
||||
data->real_url = tr_strdup(tr_webGetTaskRealUrl(task->web_task));
|
||||
data->piece_index = task->piece_index;
|
||||
data->piece_offset = task->piece_offset + task->blocks_done * task->block_size + len - 1;
|
||||
auto const* real_url = tr_webGetTaskRealUrl(task->web_task);
|
||||
|
||||
/* processing this uses a tr_torrent pointer,
|
||||
so push the work to the libevent thread... */
|
||||
tr_runInEventThread(session, connection_succeeded, data);
|
||||
tr_runInEventThread(
|
||||
session,
|
||||
connection_succeeded,
|
||||
new connection_succeeded_data{ w,
|
||||
real_url ? real_url : "",
|
||||
task->piece_index,
|
||||
task->piece_offset + task->blocks_done * task->block_size + len - 1 });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -227,13 +227,13 @@ QIcon IconCache::getThemeIcon(
|
|||
QString const& fallbackName,
|
||||
std::optional<QStyle::StandardPixmap> const& fallbackPixmap) const
|
||||
{
|
||||
static auto const rtlSuffix = qApp->layoutDirection() == Qt::RightToLeft ? QStringLiteral("-rtl") : QString();
|
||||
static auto const RtlSuffix = qApp->layoutDirection() == Qt::RightToLeft ? QStringLiteral("-rtl") : QString();
|
||||
|
||||
auto icon = QIcon::fromTheme(name + rtlSuffix);
|
||||
auto icon = QIcon::fromTheme(name + RtlSuffix);
|
||||
|
||||
if (icon.isNull())
|
||||
{
|
||||
icon = getThemeIcon(fallbackName + rtlSuffix);
|
||||
icon = QIcon::fromTheme(fallbackName + RtlSuffix);
|
||||
}
|
||||
|
||||
if (icon.isNull() && fallbackPixmap.has_value())
|
||||
|
|
|
@ -180,7 +180,7 @@ MainWindow::MainWindow(Session& session, Prefs& prefs, TorrentModel& model, bool
|
|||
ui_.optionsButton->setIcon(icons.getThemeIcon(QStringLiteral("preferences-other")));
|
||||
ui_.statsModeButton->setIcon(icons.getThemeIcon(QStringLiteral("view-statistics")));
|
||||
|
||||
auto make_network_pixmap = [this, &icons](QString name, QSize size = { 16, 16 })
|
||||
auto make_network_pixmap = [&icons](QString name, QSize size = { 16, 16 })
|
||||
{
|
||||
return icons.getThemeIcon(name, QStyle::SP_DriveNetIcon).pixmap(size);
|
||||
};
|
||||
|
|
|
@ -934,7 +934,7 @@ static char* format_date(char* buf, size_t buflen, time_t now)
|
|||
{
|
||||
struct tm tm;
|
||||
tr_localtime_r(&now, &tm);
|
||||
strftime(buf, buflen, "%a %b %2e %T %Y%n", &tm); /* ctime equiv */
|
||||
strftime(buf, buflen, "%a %b %d %T %Y%n", &tm); /* ctime equiv */
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
@ -2754,8 +2754,15 @@ static int processArgs(char const* rpcurl, int argc, char const* const* argv)
|
|||
break;
|
||||
|
||||
case 712:
|
||||
tr_variantListAddInt(tr_variantDictAddList(args, TR_KEY_trackerRemove, 1), atoi(optarg));
|
||||
break;
|
||||
{
|
||||
tr_variant* list;
|
||||
if (!tr_variantDictFindList(args, TR_KEY_trackerRemove, &list))
|
||||
{
|
||||
list = tr_variantDictAddList(args, TR_KEY_trackerRemove, 1);
|
||||
}
|
||||
tr_variantListAddInt(list, atoi(optarg));
|
||||
break;
|
||||
}
|
||||
|
||||
case 950:
|
||||
tr_variantDictAddReal(args, TR_KEY_seedRatioLimit, atof(optarg));
|
||||
|
@ -2831,8 +2838,15 @@ static int processArgs(char const* rpcurl, int argc, char const* const* argv)
|
|||
break;
|
||||
|
||||
case 710:
|
||||
tr_variantListAddStr(tr_variantDictAddList(args, TR_KEY_trackerAdd, 1), optarg);
|
||||
break;
|
||||
{
|
||||
tr_variant* list;
|
||||
if (!tr_variantDictFindList(args, TR_KEY_trackerAdd, &list))
|
||||
{
|
||||
list = tr_variantDictAddList(args, TR_KEY_trackerAdd, 1);
|
||||
}
|
||||
tr_variantListAddStr(list, optarg);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
assert("unhandled value" && 0);
|
||||
|
|
Loading…
Reference in a new issue