refactor: add tr_interned_string (#2332)

This commit is contained in:
Charles Kerr 2021-12-23 11:16:05 -06:00 committed by GitHub
parent bd68d3a2fd
commit dd1379b0b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 343 additions and 226 deletions

View File

@ -367,6 +367,7 @@
ED8A16422735A8AA000D61F9 /* peer-mgr-wishlist.cc in Sources */ = {isa = PBXBuildFile; fileRef = ED8A163E2735A8AA000D61F9 /* peer-mgr-wishlist.cc */; };
EDBDFA9E25AFCCA60093D9C1 /* evutil_time.c in Sources */ = {isa = PBXBuildFile; fileRef = EDBDFA9D25AFCCA60093D9C1 /* evutil_time.c */; };
F11545ACA7C4D7A464F703AB /* block-info.h in Headers */ = {isa = PBXBuildFile; fileRef = 6A044CBD8C049AFCBD4DB411 /* block-info.h */; settings = {ATTRIBUTES = (Project, ); }; };
E23B55A5FC3B557F7746D510 /* interned-string.h in Headers */ = {isa = PBXBuildFile; fileRef = E23B55A5FC3B557F7746D511 /* interned-string.h */; settings = {ATTRIBUTES = (Project, ); }; };
F63480631E1D7274005B9E09 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F63480621E1D7274005B9E09 /* Images.xcassets */; };
/* End PBXBuildFile section */
@ -544,6 +545,7 @@
4DFBC2DE09C0970D00D5C571 /* Torrent.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = Torrent.mm; sourceTree = "<group>"; };
55869925257074EC00F77A43 /* libcurl.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libcurl.tbd; path = usr/lib/libcurl.tbd; sourceTree = SDKROOT; };
6A044CBD8C049AFCBD4DB411 /* block-info.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "block-info.h"; path = "block-info.h"; sourceTree = SOURCE_ROOT; };
E23B55A5FC3B557F7746D511 /* interned-string.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "interned-string.h"; path = "interned-string.h"; sourceTree = SOURCE_ROOT; };
8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
8D1107320486CEB800E47090 /* Transmission.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Transmission.app; sourceTree = BUILT_PRODUCTS_DIR; };
A200B8390A2263BA007BBB1E /* InfoWindowController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InfoWindowController.h; sourceTree = "<group>"; };
@ -1375,6 +1377,7 @@
children = (
A54D44C6A7AAF131D9AE29F5 /* block-info.cc */,
6A044CBD8C049AFCBD4DB411 /* block-info.h */,
E23B55A5FC3B557F7746D511 /* interned-string.h */,
C17740D3273A002C00E455D2 /* web-utils.cc */,
C17740D4273A002C00E455D2 /* web-utils.h */,
CAB35C62252F6F5E00552A55 /* mime-types.h */,
@ -1897,6 +1900,7 @@
A2AF23C916B44FA0003BC59E /* log.h in Headers */,
A23FAE55178BC2950053DC5B /* platform-quota.h in Headers */,
F11545ACA7C4D7A464F703AB /* block-info.h in Headers */,
E23B55A5FC3B557F7746D510 /* interned-string.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -82,20 +82,20 @@ bool tr_announce_list::add(tr_tracker_tier_t tier, std::string_view announce_url
}
auto tracker = tracker_info{};
tracker.announce_interned = tr_quark_new(announce_url_sv);
tracker.announce = *tr_urlParseTracker(tr_quark_get_string_view(tracker.announce_interned));
tracker.announce_str = announce_url_sv;
tracker.announce = *tr_urlParseTracker(tracker.announce_str.sv());
tracker.tier = getTier(tier, *announce);
tracker.id = nextUniqueId();
auto host = std::string{ tracker.announce.host };
host += ':';
host += tracker.announce.portstr;
tracker.host = tr_quark_new(host);
tracker.host = host;
auto const scrape_str = announceToScrape(announce_url_sv);
if (scrape_str)
{
tracker.scrape_interned = tr_quark_new(*scrape_str);
tracker.scrape = *tr_urlParseTracker(tr_quark_get_string_view(tracker.scrape_interned));
tracker.scrape_str = *scrape_str;
tracker.scrape = *tr_urlParseTracker(tracker.scrape_str.sv());
}
auto const it = std::lower_bound(std::begin(trackers_), std::end(trackers_), tracker);
@ -221,7 +221,7 @@ bool tr_announce_list::save(char const* torrent_file, tr_error** error) const
// add the new fields
if (this->size() == 1)
{
tr_variantDictAddQuark(&metainfo, TR_KEY_announce, at(0).announce_interned);
tr_variantDictAddQuark(&metainfo, TR_KEY_announce, at(0).announce_str.quark());
}
else if (this->size() > 1)
{
@ -238,7 +238,7 @@ bool tr_announce_list::save(char const* torrent_file, tr_error** error) const
current_tier = tracker.tier;
}
tr_variantListAddQuark(tracker_list, tracker.announce_interned);
tr_variantListAddQuark(tracker_list, tracker.announce_str.quark());
}
}

View File

@ -23,7 +23,7 @@
#include "transmission.h"
#include "quark.h"
#include "interned-string.h"
#include "web-utils.h"
struct tr_error;
@ -33,11 +33,11 @@ class tr_announce_list
public:
struct tracker_info
{
tr_quark host;
tr_url_parsed_t announce;
tr_url_parsed_t scrape;
tr_quark announce_interned = TR_KEY_NONE;
tr_quark scrape_interned = TR_KEY_NONE;
tr_interned_string announce_str;
tr_interned_string scrape_str;
tr_interned_string host;
tr_tracker_tier_t tier = 0;
tr_tracker_id_t id = 0;

View File

@ -19,7 +19,7 @@
#include "transmission.h"
#include "quark.h"
#include "interned-string.h"
#include "web-utils.h"
/***
@ -40,7 +40,7 @@ auto inline constexpr TR_MULTISCRAPE_MAX = 60;
struct tr_scrape_request
{
/* the scrape URL */
tr_quark scrape_url;
tr_interned_string scrape_url;
/* the name to use when deep logging is enabled */
char log_name[128];
@ -87,7 +87,7 @@ struct tr_scrape_response
struct tr_scrape_response_row rows[TR_MULTISCRAPE_MAX];
/* the raw scrape url */
tr_quark scrape_url;
tr_interned_string scrape_url;
/* human-readable error string on failure, or nullptr */
std::string errmsg;
@ -155,7 +155,7 @@ struct tr_announce_request
uint64_t leftUntilComplete;
/* the tracker's announce URL */
tr_quark announce_url;
tr_interned_string announce_url;
/* key generated by and returned from an http tracker.
* see tr_announce_response.tracker_id_str */
@ -215,10 +215,10 @@ struct tr_announce_response
struct tr_pex* pex6;
/* human-readable error string on failure, or nullptr */
char* errmsg;
std::string errmsg;
/* human-readable warning string or nullptr */
char* warning;
std::string warning;
/* key generated by and returned from an http tracker.
* if this is provided, subsequent http announces must include this. */
@ -241,20 +241,4 @@ void tr_tracker_udp_announce(
void tr_tracker_udp_start_shutdown(tr_session* session);
tr_quark tr_announcerGetKey(tr_url_parsed_t const& parsed);
inline tr_quark tr_announcerGetKey(std::string_view url)
{
auto const parsed = tr_urlParseTracker(url);
if (!parsed)
{
return TR_KEY_NONE;
}
return tr_announcerGetKey(*parsed);
}
inline tr_quark tr_announcerGetKey(tr_quark url)
{
return tr_announcerGetKey(tr_quark_get_string_view(url));
}
tr_interned_string tr_announcerGetKey(tr_url_parsed_t const& parsed);

View File

@ -43,7 +43,7 @@ static char const* get_event_string(tr_announce_request const* req)
static char* announce_url_new(tr_session const* session, tr_announce_request const* req)
{
auto const announce_sv = tr_quark_get_string_view(req->announce_url);
auto const announce_sv = req->announce_url.sv();
char escaped_info_hash[SHA_DIGEST_LENGTH * 3 + 1];
tr_http_escape_sha1(escaped_info_hash, req->info_hash);
@ -190,8 +190,6 @@ static void on_announce_done_eventthread(void* vdata)
tr_free(data->response.pex6);
tr_free(data->response.pex);
tr_free(data->response.tracker_id_str);
tr_free(data->response.warning);
tr_free(data->response.errmsg);
tr_free(data);
}
@ -251,12 +249,12 @@ static void on_announce_done(
if (tr_variantDictFindStrView(&benc, TR_KEY_failure_reason, &sv))
{
response->errmsg = tr_strvDup(sv);
response->errmsg = sv;
}
if (tr_variantDictFindStrView(&benc, TR_KEY_warning_message, &sv))
{
response->warning = tr_strvDup(sv);
response->warning = sv;
}
if (tr_variantDictFindInt(&benc, TR_KEY_interval, &i))
@ -377,7 +375,7 @@ static void on_scrape_done(
response->did_connect = did_connect;
response->did_timeout = did_timeout;
auto const scrape_url_sv = tr_quark_get_string_view(response->scrape_url);
auto const scrape_url_sv = response->scrape_url.sv();
dbgmsg(data->log_name, "Got scrape response for \"%" TR_PRIsv "\"", TR_PRIsv_ARG(scrape_url_sv));
if (response_code != HTTP_OK)
@ -485,12 +483,12 @@ static void on_scrape_done(
static char* scrape_url_new(tr_scrape_request const* req)
{
auto const sv = tr_quark_get_string_view(req->scrape_url);
auto const sv = req->scrape_url.sv();
auto* const buf = evbuffer_new();
evbuffer_add(buf, std::data(sv), std::size(sv));
char delimiter = sv.find('?') == sv.npos ? '?' : '&';
char delimiter = sv.find('?') == std::string_view::npos ? '?' : '&';
for (int i = 0; i < req->info_hash_count; ++i)
{
char str[SHA_DIGEST_LENGTH * 3 + 1];

View File

@ -30,7 +30,7 @@
#include "tr-udp.h"
#include "utils.h"
#define dbgmsg(key, ...) tr_logAddDeepNamed(tr_quark_get_string(key), __VA_ARGS__)
#define dbgmsg(key, ...) tr_logAddDeepNamed(key.c_str(), __VA_ARGS__)
using namespace std::literals;
@ -356,8 +356,6 @@ static struct tau_announce_request* tau_announce_request_new(
static void tau_announce_request_free(struct tau_announce_request* req)
{
tr_free(req->response.tracker_id_str);
tr_free(req->response.warning);
tr_free(req->response.errmsg);
tr_free(req->response.pex6);
tr_free(req->response.pex);
delete req;
@ -423,8 +421,8 @@ struct tau_tracker
{
tr_session* const session;
tr_quark const key;
tr_quark const host;
tr_interned_string const key;
tr_interned_string const host;
int const port;
struct evdns_getaddrinfo_request* dns_request = nullptr;
@ -441,7 +439,7 @@ struct tau_tracker
tr_ptrArray announces = {};
tr_ptrArray scrapes = {};
tau_tracker(tr_session* session_in, tr_quark key_in, tr_quark host_in, int port_in)
tau_tracker(tr_session* session_in, tr_interned_string key_in, tr_interned_string host_in, int port_in)
: session{ session_in }
, key{ key_in }
, host{ host_in }
@ -687,7 +685,7 @@ static void tau_tracker_upkeep_ex(struct tau_tracker* tracker, bool timeout_reqs
dbgmsg(tracker->host, "Trying a new DNS lookup");
tracker->dns_request = evdns_getaddrinfo(
tracker->session->evdns_base,
tr_quark_get_string(tracker->host),
tracker->host.c_str(),
nullptr,
&hints,
tau_tracker_on_dns,
@ -765,10 +763,10 @@ static struct tr_announcer_udp* announcer_udp_get(tr_session* session)
/* Finds the tau_tracker struct that corresponds to this url.
If it doesn't exist yet, create one. */
static tau_tracker* tau_session_get_tracker(tr_announcer_udp* tau, tr_quark announce_url)
static tau_tracker* tau_session_get_tracker(tr_announcer_udp* tau, tr_interned_string announce_url)
{
// build a lookup key for this tracker
auto const announce_sv = tr_quark_get_string_view(announce_url);
auto const announce_sv = announce_url.sv();
auto parsed = tr_urlParseTracker(announce_sv);
TR_ASSERT(parsed);
if (!parsed)
@ -789,7 +787,7 @@ static tau_tracker* tau_session_get_tracker(tr_announcer_udp* tau, tr_quark anno
}
// we don't have it -- build a new one
auto* const tracker = new tau_tracker{ tau->session, key, tr_quark_new(parsed->host), parsed->port };
auto* const tracker = new tau_tracker{ tau->session, key, tr_interned_string(parsed->host), parsed->port };
tr_ptrArrayAppend(&tau->trackers, tracker);
dbgmsg(tracker->key, "New tau_tracker created");
return tracker;

View File

@ -12,9 +12,9 @@
#include <cstdio>
#include <cstring>
#include <ctime>
#include <map>
#include <set>
#include <string_view>
#include <unordered_map>
#include <vector>
#include <event2/buffer.h>
@ -151,11 +151,11 @@ struct StopsCompare
struct tr_scrape_info
{
tr_quark const scrape_url;
tr_interned_string scrape_url;
int multiscrape_max;
tr_scrape_info(tr_quark scrape_url_in, int const multiscrape_max_in)
tr_scrape_info(tr_interned_string scrape_url_in, int const multiscrape_max_in)
: scrape_url{ scrape_url_in }
, multiscrape_max{ multiscrape_max_in }
{
@ -168,7 +168,7 @@ struct tr_scrape_info
struct tr_announcer
{
std::set<tr_announce_request*, StopsCompare> stops;
std::unordered_map<tr_quark, tr_scrape_info> scrape_info;
std::map<tr_interned_string, tr_scrape_info> scrape_info;
tr_session* session;
struct event* upkeepTimer;
@ -176,9 +176,9 @@ struct tr_announcer
time_t tauUpkeepAt;
};
static tr_scrape_info* tr_announcerGetScrapeInfo(tr_announcer* announcer, tr_quark url)
static tr_scrape_info* tr_announcerGetScrapeInfo(tr_announcer* announcer, tr_interned_string url)
{
if (url == TR_KEY_NONE)
if (std::empty(url))
{
return nullptr;
}
@ -227,8 +227,8 @@ void tr_announcerClose(tr_session* session)
/* a row in tr_tier's list of trackers */
struct tr_tracker
{
tr_quark key;
tr_quark announce_url;
tr_interned_string key;
tr_interned_string announce_url;
struct tr_scrape_info* scrape_info;
char* tracker_id_str;
@ -244,20 +244,19 @@ struct tr_tracker
};
// format: `${host}:${port}`
tr_quark tr_announcerGetKey(tr_url_parsed_t const& parsed)
tr_interned_string tr_announcerGetKey(tr_url_parsed_t const& parsed)
{
std::string buf;
tr_buildBuf(buf, parsed.host, ":"sv, parsed.portstr);
return tr_quark_new(buf);
return tr_interned_string{ buf };
}
static void trackerConstruct(tr_announcer* announcer, tr_tracker* tracker, tr_announce_list::tracker_info const& info)
{
memset(tracker, 0, sizeof(tr_tracker));
tracker->key = info.host;
tracker->announce_url = info.announce_interned;
tracker->scrape_info = info.scrape_interned == TR_KEY_NONE ? nullptr :
tr_announcerGetScrapeInfo(announcer, info.scrape_interned);
tracker->announce_url = info.announce_str;
tracker->scrape_info = std::empty(info.scrape_str) ? nullptr : tr_announcerGetScrapeInfo(announcer, info.scrape_str);
tracker->id = info.id;
tracker->seederCount = -1;
tracker->leecherCount = -1;
@ -369,9 +368,7 @@ static void tierDestruct(tr_tier* tier)
static void tier_build_log_name(tr_tier const* tier, char* buf, size_t buflen)
{
auto const* const name = tier != nullptr && tier->tor != nullptr ? tr_torrentName(tier->tor) : "?";
auto const key_sv = tier != nullptr && tier->currentTracker != nullptr ?
tr_quark_get_string_view(tier->currentTracker->key) :
"?"sv;
auto const key_sv = tier != nullptr && tier->currentTracker != nullptr ? tier->currentTracker->key.sv() : "?"sv;
tr_snprintf(buf, buflen, "[%s---%" TR_PRIsv "]", name, TR_PRIsv_ARG(key_sv));
}
@ -470,7 +467,7 @@ static tr_tier* getTier(tr_announcer* announcer, tr_sha1_digest_t const& info_ha
**** PUBLISH
***/
static void publishMessage(tr_tier* tier, char const* msg, TrackerEventType type)
static void publishMessage(tr_tier* tier, std::string_view msg, TrackerEventType type)
{
if (tier != nullptr && tier->tor != nullptr && tier->tor->announcer_tiers != nullptr &&
tier->tor->announcer_tiers->callback != nullptr)
@ -491,15 +488,15 @@ static void publishMessage(tr_tier* tier, char const* msg, TrackerEventType type
static void publishErrorClear(tr_tier* tier)
{
publishMessage(tier, nullptr, TR_TRACKER_ERROR_CLEAR);
publishMessage(tier, ""sv, TR_TRACKER_ERROR_CLEAR);
}
static void publishWarning(tr_tier* tier, char const* msg)
static void publishWarning(tr_tier* tier, std::string_view msg)
{
publishMessage(tier, msg, TR_TRACKER_WARNING);
}
static void publishError(tr_tier* tier, char const* msg)
static void publishError(tr_tier* tier, std::string_view msg)
{
publishMessage(tier, msg, TR_TRACKER_ERROR);
}
@ -913,7 +910,7 @@ static void on_announce_error(tr_tier* tier, char const* err, tr_announce_event
/* schedule a reannounce */
int const interval = getRetryInterval(tier->currentTracker);
auto const* const key_cstr = tr_quark_get_string(tier->currentTracker->key);
auto const* const key_cstr = tier->currentTracker->key.c_str();
dbgmsg(tier, "Tracker '%s' announce error: %s (Retrying in %d seconds)", key_cstr, err, interval);
tr_logAddTorInfo(tier->tor, "Tracker '%s' announce error: %s (Retrying in %d seconds)", key_cstr, err, interval);
tier_announce_event_push(tier, e, tr_time() + interval);
@ -954,8 +951,8 @@ static void on_announce_done(tr_announce_response const* response, void* vdata)
response->tracker_id_str != nullptr ? response->tracker_id_str : "none",
response->pex_count,
response->pex6_count,
response->errmsg != nullptr ? response->errmsg : "none",
response->warning != nullptr ? response->warning : "none");
(!std::empty(response->errmsg) ? response->errmsg.c_str() : "none"),
(!std::empty(response->warning) ? response->warning.c_str() : "none"));
tier->lastAnnounceTime = now;
tier->lastAnnounceTimedOut = response->did_timeout;
@ -971,7 +968,7 @@ static void on_announce_done(tr_announce_response const* response, void* vdata)
{
on_announce_error(tier, _("Tracker did not respond"), event);
}
else if (response->errmsg != nullptr)
else if (!std::empty(response->errmsg))
{
/* If the torrent's only tracker returned an error, publish it.
Don't bother publishing if there are other trackers -- it's
@ -982,7 +979,7 @@ static void on_announce_done(tr_announce_response const* response, void* vdata)
publishError(tier, response->errmsg);
}
on_announce_error(tier, response->errmsg, event);
on_announce_error(tier, response->errmsg.c_str(), event);
}
else
{
@ -1023,12 +1020,12 @@ static void on_announce_done(tr_announce_response const* response, void* vdata)
}
}
char const* const str = response->warning;
if (str != nullptr)
auto const& warning = response->warning;
if (!std::empty(warning))
{
tr_strlcpy(tier->lastAnnounceStr, str, sizeof(tier->lastAnnounceStr));
dbgmsg(tier, "tracker gave \"%s\"", str);
publishWarning(tier, str);
tr_strlcpy(tier->lastAnnounceStr, warning.c_str(), sizeof(tier->lastAnnounceStr));
dbgmsg(tier, "tracker gave \"%s\"", warning.c_str());
publishWarning(tier, warning);
}
else
{
@ -1127,7 +1124,7 @@ static void announce_request_delegate(
#endif
if (auto const announce_sv = tr_quark_get_string_view(request->announce_url);
if (auto const announce_sv = request->announce_url.sv();
tr_strvStartsWith(announce_sv, "http://"sv) || tr_strvStartsWith(announce_sv, "https://"sv))
{
tr_tracker_http_announce(session, request, callback, callback_data);
@ -1211,14 +1208,14 @@ static void on_scrape_error(tr_session const* session, tr_tier* tier, char const
/* schedule a rescrape */
int const interval = getRetryInterval(tier->currentTracker);
auto const* const key_cstr = tr_quark_get_string(tier->currentTracker->key);
auto const* const key_cstr = tier->currentTracker->key.c_str();
dbgmsg(tier, "Tracker '%s' scrape error: %s (Retrying in %zu seconds)", key_cstr, errmsg, (size_t)interval);
tr_logAddTorInfo(tier->tor, "Tracker '%s' error: %s (Retrying in %zu seconds)", key_cstr, errmsg, (size_t)interval);
tier->lastScrapeSucceeded = false;
tier->scrapeAt = get_next_scrape_time(session, tier, interval);
}
static tr_tier* find_tier(tr_torrent* tor, tr_quark scrape_url)
static tr_tier* find_tier(tr_torrent* tor, tr_interned_string scrape_url)
{
struct tr_announcer_tiers* tt = tor->announcer_tiers;
@ -1263,7 +1260,7 @@ static void checkMultiscrapeMax(tr_announcer* announcer, tr_scrape_response cons
{
// don't log the full URL, since that might have a personal announce id
// (note: we know 'parsed' will be successful since this url has a scrape_info)
auto const parsed = *tr_urlParse(tr_quark_get_string_view(url));
auto const parsed = *tr_urlParse(url.sv());
auto clean_url = std::string{};
tr_buildBuf(clean_url, parsed.scheme, "://"sv, parsed.host, ":"sv, parsed.portstr);
tr_logAddNamedInfo(clean_url.c_str(), "Reducing multiscrape max to %d", n);
@ -1288,7 +1285,7 @@ static void on_scrape_done(tr_scrape_response const* response, void* vsession)
if (tier != nullptr)
{
auto const scrape_url_sv = tr_quark_get_string_view(response->scrape_url);
auto const scrape_url_sv = response->scrape_url.sv();
dbgmsg(
tier,
@ -1378,7 +1375,7 @@ static void scrape_request_delegate(
{
tr_session* session = announcer->session;
auto const scrape_sv = tr_quark_get_string_view(request->scrape_url);
auto const scrape_sv = request->scrape_url.sv();
if (tr_strvStartsWith(scrape_sv, "http://"sv) || tr_strvStartsWith(scrape_sv, "https://"sv))
{
@ -1609,9 +1606,9 @@ static tr_tracker_view trackerView(tr_torrent const& tor, int tier_index, tr_tie
auto const now = tr_time();
auto view = tr_tracker_view{};
view.host = tr_quark_get_string(tracker.key);
view.announce = tr_quark_get_string(tracker.announce_url);
view.scrape = tracker.scrape_info == nullptr ? "" : tr_quark_get_string(tracker.scrape_info->scrape_url);
view.host = tracker.key.c_str();
view.announce = tracker.announce_url.c_str();
view.scrape = tracker.scrape_info == nullptr ? "" : tracker.scrape_info->scrape_url.c_str();
view.id = tracker.id;
view.tier = tier_index;

View File

@ -43,8 +43,8 @@ struct tr_tracker_event
TrackerEventType messageType;
/* for TR_TRACKER_WARNING and TR_TRACKER_ERROR */
char const* text;
tr_quark announce_url;
std::string_view text;
tr_interned_string announce_url;
/* for TR_TRACKER_PEERS */
struct tr_pex const* pex;

1
libtransmission/foo Normal file
View File

@ -0,0 +1 @@
test

View File

@ -26,6 +26,8 @@
#include "tr-assert.h"
#include "utils.h"
using namespace std::literals;
/****
***** Low-level IO functions
****/
@ -227,8 +229,8 @@ static int readOrWritePiece(
if (err != 0 && ioMode == TR_IO_WRITE && tor->error != TR_STAT_LOCAL_ERROR)
{
auto const path = tr_strvPath(tor->downloadDir, file.name);
tr_torrentSetLocalError(tor, "%s (%s)", tr_strerror(err), path.c_str());
auto const path = tr_strvPath(tor->downloadDir().sv(), file.name);
tor->setLocalError(tr_strvJoin(tr_strerror(err), " ("sv, path, ")"sv));
}
}

View File

@ -0,0 +1,142 @@
/*
* This file Copyright (C) Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
*/
#pragma once
#include <string_view>
#include "transmission.h"
#include "quark.h"
/**
* Helper functions wrapped around tr_quark
*/
class tr_interned_string
{
public:
tr_interned_string() = default;
explicit tr_interned_string(tr_quark quark)
: quark_{ quark }
{
}
explicit tr_interned_string(std::string_view sv)
: tr_interned_string{ tr_quark_new(sv) }
{
}
explicit tr_interned_string(char const* c_str)
: tr_interned_string{ std::string_view{ c_str ? c_str : "" } }
{
}
tr_interned_string& operator=(tr_quark quark)
{
quark_ = quark;
return *this;
}
tr_interned_string& operator=(std::string_view sv)
{
return *this = tr_quark_new(sv);
}
tr_interned_string& operator=(char const* c_str)
{
return *this = std::string_view{ c_str != nullptr ? c_str : "" };
}
[[nodiscard]] tr_quark quark() const
{
return quark_;
}
[[nodiscard]] char const* c_str() const
{
return tr_quark_get_string(quark_);
}
[[nodiscard]] std::string_view sv() const
{
return tr_quark_get_string_view(quark_);
}
[[nodiscard]] auto data() const
{
return std::data(this->sv());
}
[[nodiscard]] auto empty() const
{
return quark_ == TR_KEY_NONE;
}
[[nodiscard]] auto size() const
{
return std::size(this->sv());
}
void clear()
{
*this = TR_KEY_NONE;
}
[[nodiscard]] auto begin() const
{
return std::begin(this->sv());
}
[[nodiscard]] auto end() const
{
return std::end(this->sv());
}
[[nodiscard]] auto rbegin() const
{
return std::rbegin(this->sv());
}
[[nodiscard]] auto rend() const
{
return std::rend(this->sv());
}
[[nodiscard]] int compare(tr_interned_string const& that) const // <=>
{
return this->quark() - that.quark();
}
[[nodiscard]] bool operator<(tr_interned_string const& that) const
{
return this->compare(that) < 0;
}
[[nodiscard]] bool operator>(tr_interned_string const& that) const
{
return this->compare(that) > 0;
}
[[nodiscard]] bool operator==(tr_interned_string const& that) const
{
return this->compare(that) == 0;
}
[[nodiscard]] bool operator!=(tr_interned_string const& that) const
{
return this->compare(that) != 0;
}
[[nodiscard]] bool operator==(std::string_view that) const
{
return this->sv() == that;
}
[[nodiscard]] bool operator!=(std::string_view that) const
{
return this->sv() != that;
}
[[nodiscard]] bool operator==(char const* that) const
{
return *this == std::string_view{ that != nullptr ? that : "" };
}
[[nodiscard]] bool operator!=(char const* that) const
{
return *this != std::string_view{ that != nullptr ? that : "" };
}
private:
tr_quark quark_ = TR_KEY_NONE;
};

View File

@ -208,7 +208,7 @@ void tr_magnet_metainfo::toVariant(tr_variant* top) const
auto n = std::size(this->announce_list);
if (n == 1)
{
tr_variantDictAddQuark(top, TR_KEY_announce, this->announce_list.at(0).announce_interned);
tr_variantDictAddQuark(top, TR_KEY_announce, this->announce_list.at(0).announce_str.quark());
}
else
{
@ -224,7 +224,7 @@ void tr_magnet_metainfo::toVariant(tr_variant* top) const
current_tier = tracker.tier;
}
tr_variantListAddQuark(tracker_list, tracker.announce_interned);
tr_variantListAddQuark(tracker_list, tracker.announce_str.quark());
}
}

View File

@ -105,7 +105,7 @@ public:
/* the client name.
For BitTorrent peers, this is the app name derived from the `v' string in LTEP's handshake dictionary */
tr_quark client = TR_KEY_NONE;
tr_interned_string client;
tr_recentHistory blocksSentToClient;
tr_recentHistory blocksSentToPeer;

View File

@ -1722,7 +1722,7 @@ static auto getPeerStats(tr_peerMsgs const* peer, time_t now, uint64_t now_msec)
auto const* const atom = peer->atom;
tr_address_to_string_with_buf(&atom->addr, stats.addr, sizeof(stats.addr));
tr_strlcpy(stats.client, tr_quark_get_string(peer->client), sizeof(stats.client));
stats.client = peer->client.c_str();
stats.port = ntohs(peer->atom->port);
stats.from = atom->fromFirst;
stats.progress = peer->progress;

View File

@ -676,7 +676,7 @@ static void myDebug(char const* file, int line, tr_peerMsgsImpl const* msgs, cha
tr_logGetTimeStr(timestr, sizeof(timestr)),
tr_torrentName(msgs->torrent),
tr_peerIoGetAddrStr(msgs->io, addrstr, sizeof(addrstr)),
tr_quark_get_string(msgs->client));
msgs->client.c_str());
va_start(args, fmt);
evbuffer_add_vprintf(buf, fmt, args);
va_end(args);
@ -2231,10 +2231,11 @@ static size_t fillOutputBuffer(tr_peerMsgsImpl* msgs, time_t now)
err = !msgs->torrent->ensurePieceIsChecked(req.index);
if (err)
{
tr_torrentSetLocalError(
msgs->torrent,
_("Please Verify Local Data! Piece #%zu is corrupt."),
(size_t)req.index);
auto const errmsg = tr_strvJoin(
"Please Verify Local Data! Piece #",
std::to_string(req.index),
" is corrupt.");
msgs->torrent->setLocalError(errmsg);
}
}

View File

@ -1,9 +1,8 @@
/*
* This file Copyright (C) 2013-2014 Mnemosyne LLC
* This file Copyright (C) Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
*
*/
#pragma once

View File

@ -678,11 +678,11 @@ void tr_torrentSaveResume(tr_torrent* tor)
tr_variantDictAddInt(&top, TR_KEY_added_date, tor->addedDate);
tr_variantDictAddInt(&top, TR_KEY_corrupt, tor->corruptPrev + tor->corruptCur);
tr_variantDictAddInt(&top, TR_KEY_done_date, tor->doneDate);
tr_variantDictAddStrView(&top, TR_KEY_destination, tor->downloadDir);
tr_variantDictAddQuark(&top, TR_KEY_destination, tor->downloadDir().quark());
if (tor->incompleteDir != nullptr)
if (!std::empty(tor->incompleteDir()))
{
tr_variantDictAddStr(&top, TR_KEY_incomplete_dir, tor->incompleteDir);
tr_variantDictAddQuark(&top, TR_KEY_incomplete_dir, tor->incompleteDir().quark());
}
tr_variantDictAddInt(&top, TR_KEY_downloaded, tor->downloadedPrev + tor->downloadedCur);
@ -710,7 +710,7 @@ void tr_torrentSaveResume(tr_torrent* tor)
int const err = tr_variantToFile(&top, TR_VARIANT_FMT_BENC, filename.c_str());
if (err != 0)
{
tr_torrentSetLocalError(tor, "Unable to save resume file: %s", tr_strerror(err));
tor->setLocalError(tr_strvJoin("Unable to save resume file: ", tr_strerror(err)));
}
tr_variantFree(&top);
@ -778,13 +778,11 @@ static uint64_t loadFromFile(tr_torrent* tor, uint64_t fieldsToLoad, bool* didRe
if ((fieldsToLoad & (TR_FR_PROGRESS | TR_FR_DOWNLOAD_DIR)) != 0 &&
tr_variantDictFindStrView(&top, TR_KEY_destination, &sv) && !std::empty(sv))
{
bool const is_current_dir = tor->currentDir == tor->downloadDir;
tr_free(tor->downloadDir);
tor->downloadDir = tr_strvDup(sv);
bool const is_current_dir = tor->current_dir == tor->download_dir;
tor->download_dir = sv;
if (is_current_dir)
{
tor->currentDir = tor->downloadDir;
tor->current_dir = sv;
}
fieldsLoaded |= TR_FR_DOWNLOAD_DIR;
@ -793,13 +791,11 @@ static uint64_t loadFromFile(tr_torrent* tor, uint64_t fieldsToLoad, bool* didRe
if ((fieldsToLoad & (TR_FR_PROGRESS | TR_FR_INCOMPLETE_DIR)) != 0 &&
tr_variantDictFindStrView(&top, TR_KEY_incomplete_dir, &sv) && !std::empty(sv))
{
bool const is_current_dir = tor->currentDir == tor->incompleteDir;
tr_free(tor->incompleteDir);
tor->incompleteDir = tr_strvDup(sv);
bool const is_current_dir = tor->current_dir == tor->incomplete_dir;
tor->incomplete_dir = sv;
if (is_current_dir)
{
tor->currentDir = tor->incompleteDir;
tor->current_dir = sv;
}
fieldsLoaded |= TR_FR_INCOMPLETE_DIR;
@ -953,8 +949,7 @@ static uint64_t setFromCtor(tr_torrent* tor, uint64_t fields, tr_ctor const* cto
if (tr_ctorGetDownloadDir(ctor, mode, &path) && !tr_str_is_empty(path))
{
ret |= TR_FR_DOWNLOAD_DIR;
tr_free(tor->downloadDir);
tor->downloadDir = tr_strdup(path);
tor->download_dir = path;
}
}

View File

@ -414,9 +414,9 @@ static void addTrackers(tr_torrent const* tor, tr_variant* trackers)
for (auto const& tracker : tor->announceList())
{
tr_variant* d = tr_variantListAddDict(trackers, 4);
tr_variantDictAddQuark(d, TR_KEY_announce, tracker.announce_interned);
tr_variantDictAddQuark(d, TR_KEY_announce, tracker.announce_str.quark());
tr_variantDictAddInt(d, TR_KEY_id, tracker.id);
tr_variantDictAddQuark(d, TR_KEY_scrape, tracker.scrape_interned);
tr_variantDictAddQuark(d, TR_KEY_scrape, tracker.scrape_str.quark());
tr_variantDictAddInt(d, TR_KEY_tier, tracker.tier);
}
}

View File

@ -299,7 +299,7 @@ void tr_torrentSetMetadataPiece(tr_torrent* tor, int piece, void const* data, in
success = !!info;
if (info && tr_block_info::bestBlockSize(info->info.pieceSize) == 0)
{
tr_torrentSetLocalError(tor, "%s", _("Magnet torrent's metadata is not usable"));
tor->setLocalError(_("Magnet torrent's metadata is not usable"));
success = false;
}

View File

@ -12,7 +12,6 @@
#include <climits> /* INT_MAX */
#include <cmath>
#include <csignal> /* signal() */
#include <cstdarg>
#include <cstdlib> /* qsort */
#include <cstring> /* memcmp */
#include <ctime>
@ -492,31 +491,11 @@ void tr_torrentCheckSeedLimit(tr_torrent* tor)
****
***/
void tr_torrentSetLocalError(tr_torrent* tor, char const* fmt, ...)
{
TR_ASSERT(tr_isTorrent(tor));
va_list ap;
va_start(ap, fmt);
tor->error = TR_STAT_LOCAL_ERROR;
tor->error_announce_url = TR_KEY_NONE;
evutil_vsnprintf(tor->errorString, sizeof(tor->errorString), fmt, ap);
va_end(ap);
tr_logAddTorErr(tor, "%s", tor->errorString);
if (tor->isRunning)
{
tor->isStopping = true;
}
}
static constexpr void tr_torrentClearError(tr_torrent* tor)
static void tr_torrentClearError(tr_torrent* tor)
{
tor->error = TR_STAT_OK;
tor->error_announce_url = TR_KEY_NONE;
tor->errorString[0] = '\0';
tor->error_announce_url.clear();
tor->error_string.clear();
}
static void onTrackerResponse(tr_torrent* tor, tr_tracker_event const* event, void* /*user_data*/)
@ -537,16 +516,16 @@ static void onTrackerResponse(tr_torrent* tor, tr_tracker_event const* event, vo
break;
case TR_TRACKER_WARNING:
tr_logAddTorErr(tor, _("Tracker warning: \"%s\""), event->text);
tr_logAddTorErr(tor, _("Tracker warning: \"%" TR_PRIsv "\""), TR_PRIsv_ARG(event->text));
tor->error = TR_STAT_TRACKER_WARNING;
tor->error_announce_url = event->announce_url;
tr_strlcpy(tor->errorString, event->text, sizeof(tor->errorString));
tor->error_string = event->text;
break;
case TR_TRACKER_ERROR:
tor->error = TR_STAT_TRACKER_ERROR;
tor->error_announce_url = event->announce_url;
tr_strlcpy(tor->errorString, event->text, sizeof(tor->errorString));
tor->error_string = event->text;
break;
case TR_TRACKER_ERROR_CLEAR:
@ -630,11 +609,8 @@ static bool setLocalErrorIfFilesDisappeared(tr_torrent* tor)
if (disappeared)
{
tr_deeplog_tor(tor, "%s", "[LAZY] uh oh, the files disappeared");
tr_torrentSetLocalError(
tor,
"%s",
_("No data found! Ensure your drives are connected or use \"Set Location\". "
"To re-download, remove the torrent and re-add it."));
tor->setLocalError(_(
"No data found! Ensure your drives are connected or use \"Set Location\". To re-download, remove the torrent and re-add it."));
}
return disappeared;
@ -671,7 +647,7 @@ static void torrentInit(tr_torrent* tor, tr_ctor const* ctor)
char const* dir = nullptr;
if (tr_ctorGetDownloadDir(ctor, TR_FORCE, &dir) || tr_ctorGetDownloadDir(ctor, TR_FALLBACK, &dir))
{
tor->downloadDir = tr_strdup(dir);
tor->download_dir = dir;
}
if (!tr_ctorGetIncompleteDir(ctor, &dir))
@ -681,7 +657,7 @@ static void torrentInit(tr_torrent* tor, tr_ctor const* ctor)
if (tr_sessionIsIncompleteDirEnabled(session))
{
tor->incompleteDir = tr_strdup(dir);
tor->incomplete_dir = dir;
}
tor->bandwidth = new Bandwidth(session->bandwidth);
@ -757,7 +733,8 @@ static void torrentInit(tr_torrent* tor, tr_ctor const* ctor)
tr_error* error = nullptr;
if (!tr_ctorSaveContents(ctor, tor->torrentFile(), &error))
{
tr_torrentSetLocalError(tor, "Unable to save torrent file: %s (%d)", error->message, error->code);
tor->setLocalError(
tr_strvJoin("Unable to save torrent file: ", error->message, " ("sv, std::to_string(error->code), ")"sv));
}
tr_error_clear(&error);
}
@ -860,11 +837,9 @@ void tr_torrentSetDownloadDir(tr_torrent* tor, char const* path)
{
TR_ASSERT(tr_isTorrent(tor));
if (path == nullptr || tor->downloadDir == nullptr || strcmp(path, tor->downloadDir) != 0)
if (tor->download_dir != path)
{
tr_free(tor->downloadDir);
tor->downloadDir = tr_strdup(path);
tor->download_dir = path;
tor->markEdited();
tor->setDirty();
}
@ -876,14 +851,14 @@ char const* tr_torrentGetDownloadDir(tr_torrent const* tor)
{
TR_ASSERT(tr_isTorrent(tor));
return tor->downloadDir;
return tor->downloadDir().c_str();
}
char const* tr_torrentGetCurrentDir(tr_torrent const* tor)
{
TR_ASSERT(tr_isTorrent(tor));
return tor->currentDir;
return tor->currentDir().c_str();
}
void tr_torrentChangeMyPort(tr_torrent* tor)
@ -1007,7 +982,7 @@ tr_stat const* tr_torrentStat(tr_torrent* tor)
s->queuePosition = tor->queuePosition;
s->idleSecs = torrentGetIdleSecs(tor, s->activity);
s->isStalled = tr_torrentIsStalled(tor, s->idleSecs);
s->errorString = tor->errorString;
s->errorString = tor->error_string.c_str();
s->manualAnnounceTime = tr_announcerNextManualAnnounce(tor);
s->peersConnected = swarm_stats.peerCount;
@ -1336,9 +1311,6 @@ static void freeTorrent(tr_torrent* tor)
tr_announcerRemoveTorrent(session->announcer, tor);
tr_free(tor->downloadDir);
tr_free(tor->incompleteDir);
tr_sessionRemoveTorrent(session, tor);
if (!session->isClosing())
@ -1830,7 +1802,8 @@ static void torrentCallScript(tr_torrent const* tor, char const* script)
tr_localtime_r(&now, &tm);
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));
auto torrent_dir = std::string{ tor->currentDir().sv() };
tr_sys_path_native_separators(std::data(torrent_dir));
auto const cmd = std::array<char const*, 2>{
script,
@ -1844,7 +1817,7 @@ static void torrentCallScript(tr_torrent const* tor, char const* script)
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_DIR"sv, torrent_dir.c_str() },
{ "TR_TORRENT_HASH"sv, tor->hashString() },
{ "TR_TORRENT_ID"sv, id_str },
{ "TR_TORRENT_LABELS"sv, labels_str },
@ -1861,8 +1834,6 @@ static void torrentCallScript(tr_torrent const* tor, char const* script)
tr_logAddTorErr(tor, "Error executing script \"%s\" (%d): %s", script, error->code, error->message);
tr_error_free(error);
}
tr_free(torrent_dir);
}
void tr_torrent::recheckCompleteness()
@ -1904,9 +1875,9 @@ void tr_torrent::recheckCompleteness()
tr_peerMgrClearInterest(this);
}
if (this->currentDir == this->incompleteDir)
if (this->currentDir() == this->incompleteDir())
{
this->setLocation(this->downloadDir, true, nullptr, nullptr);
this->setLocation(this->downloadDir().sv(), true, nullptr, nullptr);
}
}
@ -2153,7 +2124,7 @@ bool tr_torrentSetAnnounceList(tr_torrent* tor, char const* const* announce_urls
if (std::any_of(
std::begin(tor->announceList()),
std::end(tor->announceList()),
[error_url](auto const& tracker) { return tracker.announce_interned == error_url; }))
[error_url](auto const& tracker) { return tracker.announce_str == error_url; }))
{
tr_torrentClearError(tor);
}
@ -2276,7 +2247,7 @@ static void deleteLocalData(tr_torrent* tor, tr_fileFunc func)
{
auto files = std::vector<std::string>{};
auto folders = std::set<std::string>{};
char const* const top = tor->currentDir;
char const* const top = tor->currentDir().c_str();
/* don't try to delete local data if the directory's gone missing */
if (!tr_sys_path_exists(top, nullptr))
@ -2457,12 +2428,12 @@ static void setLocationImpl(void* vdata)
tr_logAddDebug(
"Moving \"%s\" location from currentDir \"%s\" to \"%s\"",
tr_torrentName(tor),
tor->currentDir,
tor->currentDir().c_str(),
location.c_str());
tr_sys_dir_create(location.c_str(), TR_SYS_DIR_CREATE_PARENTS, 0777, nullptr);
if (!tr_sys_path_is_same(location.c_str(), tor->currentDir, nullptr))
if (!tr_sys_path_is_same(location.c_str(), tor->currentDir().c_str(), nullptr))
{
/* bad idea to move files while they're being verified... */
tr_verifyRemove(tor);
@ -2526,9 +2497,8 @@ static void setLocationImpl(void* vdata)
if (do_move)
{
tr_free(tor->incompleteDir);
tor->incompleteDir = nullptr;
tor->currentDir = tor->downloadDir;
tor->incomplete_dir.clear();
tor->current_dir = tor->downloadDir();
}
}
@ -2710,9 +2680,9 @@ std::optional<tr_torrent::tr_found_file_t> tr_torrent::findFile(std::string& fil
tr_file const& file = this->file(i);
auto file_info = tr_sys_path_info{};
if (this->downloadDir != nullptr)
if (!std::empty(this->downloadDir()))
{
auto base = std::string_view{ this->downloadDir };
auto const base = this->downloadDir().sv();
tr_buildBuf(filename, base, "/"sv, file.name);
if (tr_sys_path_get_info(filename.c_str(), 0, &file_info, nullptr))
@ -2727,9 +2697,9 @@ std::optional<tr_torrent::tr_found_file_t> tr_torrent::findFile(std::string& fil
}
}
if (this->incompleteDir != nullptr)
if (!std::empty(this->incompleteDir()))
{
auto const base = std::string_view{ this->incompleteDir };
auto const base = this->incompleteDir().sv();
tr_buildBuf(filename, base, "/"sv, file.name);
if (tr_sys_path_get_info(filename.c_str(), 0, &file_info, nullptr))
@ -2787,25 +2757,27 @@ char* tr_torrentFindFile(tr_torrent const* tor, tr_file_index_t fileNum)
/* Decide whether we should be looking for files in downloadDir or incompleteDir. */
static void refreshCurrentDir(tr_torrent* tor)
{
char const* dir = nullptr;
tr_interned_string dir;
if (tor->incompleteDir == nullptr)
if (std::empty(tor->incompleteDir()))
{
dir = tor->downloadDir;
dir = tor->downloadDir();
}
else if (!tor->hasMetadata()) /* no files to find */
{
dir = tor->incompleteDir;
dir = tor->incompleteDir();
}
else if (!tr_torrentFindFile2(tor, 0, &dir, nullptr, nullptr))
else
{
dir = tor->incompleteDir;
auto filename = std::string{};
auto const found = tor->findFile(filename, 0);
dir = found ? tr_interned_string{ found->base } : tor->incompleteDir();
}
TR_ASSERT(dir != nullptr);
TR_ASSERT(dir == tor->downloadDir || dir == tor->incompleteDir);
TR_ASSERT(!std::empty(dir));
TR_ASSERT(dir == tor->downloadDir() || dir == tor->incompleteDir());
tor->currentDir = dir;
tor->current_dir = dir;
}
char* tr_torrentBuildPartial(tr_torrent const* tor, tr_file_index_t i)
@ -3001,7 +2973,7 @@ static int renamePath(tr_torrent* tor, char const* oldpath, char const* newname)
{
int err = 0;
char const* const base = !tor->isDone() && tor->incompleteDir != nullptr ? tor->incompleteDir : tor->downloadDir;
auto const base = tor->isDone() || std::empty(tor->incompleteDir()) ? tor->downloadDir().sv() : tor->incompleteDir().sv();
auto src = tr_strvPath(base, oldpath);

View File

@ -29,6 +29,7 @@
#include "completion.h"
#include "file.h"
#include "file-piece-map.h"
#include "interned-string.h"
#include "quark.h"
#include "session.h"
#include "tr-assert.h"
@ -94,8 +95,6 @@ void tr_torrentCheckSeedLimit(tr_torrent* tor);
/** save a torrent's .resume file if it's changed since the last time it was saved */
void tr_torrentSave(tr_torrent* tor);
void tr_torrentSetLocalError(tr_torrent* tor, char const* fmt, ...) TR_GNUC_PRINTF(2, 3);
enum tr_verify_state
{
TR_VERIFY_NONE,
@ -286,6 +285,23 @@ public:
setDirty();
}
/// LOCATION
[[nodiscard]] tr_interned_string currentDir() const
{
return this->current_dir;
}
[[nodiscard]] tr_interned_string downloadDir() const
{
return this->download_dir;
}
[[nodiscard]] tr_interned_string incompleteDir() const
{
return this->incomplete_dir;
}
/// METAINFO - FILES
[[nodiscard]] tr_file_index_t fileCount() const
@ -504,6 +520,13 @@ public:
return this->isPieceTransferAllowed(TR_CLIENT_TO_PEER);
}
void setLocalError(std::string_view errmsg)
{
this->error = TR_STAT_LOCAL_ERROR;
this->error_announce_url = TR_KEY_NONE;
this->error_string = errmsg;
}
void setVerifyState(tr_verify_state state);
void setDateActive(time_t t);
@ -535,8 +558,8 @@ public:
std::optional<double> verify_progress;
tr_stat_errtype error = TR_STAT_OK;
char errorString[128] = {};
tr_quark error_announce_url = TR_KEY_NONE;
tr_interned_string error_announce_url;
std::string error_string;
bool checkPiece(tr_piece_index_t piece);
@ -558,15 +581,16 @@ public:
time_t peer_id_creation_time = 0;
/* Where the files will be when it's complete */
char* downloadDir = nullptr;
// Where the files are when the torrent is complete.
tr_interned_string download_dir;
/* Where the files are when the torrent is incomplete */
char* incompleteDir = nullptr;
// Where the files are when the torrent is incomplete.
// a value of TR_KEY_NONE indicates the 'incomplete_dir' feature is unused
tr_interned_string incomplete_dir;
/* Where the files are now.
* This pointer will be equal to downloadDir or incompleteDir */
char const* currentDir = nullptr;
// Where the files are now.
// Will equal either download_dir or incomplete_dir
tr_interned_string current_dir;
/* Length, in bytes, of the "info" dict in the .torrent file. */
uint64_t infoDictLength = 0;

View File

@ -1343,8 +1343,8 @@ struct tr_peer_stat
tr_port port;
char addr[TR_INET6_ADDRSTRLEN];
char client[80];
char flagStr[32];
char const* client;
float progress;
double rateToPeer_KBps;

View File

@ -171,7 +171,7 @@ OSStatus GeneratePreviewForURL(void* thisInterface, QLPreviewRequestRef preview,
#warning handle tiers?
for (auto const tracker : *inf.announce_list)
{
[listSection appendFormat:@"<tr><td>%s<td></tr>", tr_quark_get_string(tracker.announce_interned)];
[listSection appendFormat:@"<tr><td>%s<td></tr>", tracker.announce_str.c_str()];
}
[listSection appendString:@"</table>"];

View File

@ -36,7 +36,7 @@ TEST_F(AnnounceListTest, canAdd)
EXPECT_EQ(Announce, tracker.announce.full);
EXPECT_EQ("https://example.org/scrape"sv, tracker.scrape.full);
EXPECT_EQ(Tier, tracker.tier);
EXPECT_EQ("example.org:443"sv, tr_quark_get_string_view(tracker.host));
EXPECT_EQ("example.org:443"sv, tracker.host.sv());
}
TEST_F(AnnounceListTest, groupsSiblingsIntoSameTier)
@ -60,9 +60,9 @@ TEST_F(AnnounceListTest, groupsSiblingsIntoSameTier)
EXPECT_EQ(Announce1, announce_list.at(1).announce.full);
EXPECT_EQ(Announce2, announce_list.at(0).announce.full);
EXPECT_EQ(Announce3, announce_list.at(2).announce.full);
EXPECT_EQ("example.org:443"sv, tr_quark_get_string_view(announce_list.at(1).host));
EXPECT_EQ("example.org:80"sv, tr_quark_get_string_view(announce_list.at(0).host));
EXPECT_EQ("example.org:999"sv, tr_quark_get_string_view(announce_list.at(2).host));
EXPECT_EQ("example.org:443"sv, announce_list.at(1).host.sv());
EXPECT_EQ("example.org:80"sv, announce_list.at(0).host.sv());
EXPECT_EQ("example.org:999"sv, announce_list.at(2).host.sv());
}
TEST_F(AnnounceListTest, canAddWithoutScrape)
@ -74,7 +74,7 @@ TEST_F(AnnounceListTest, canAddWithoutScrape)
EXPECT_TRUE(announce_list.add(Tier, Announce));
auto const tracker = announce_list.at(0);
EXPECT_EQ(Announce, tracker.announce.full);
EXPECT_EQ(TR_KEY_NONE, tracker.scrape_interned);
EXPECT_TRUE(std::empty(tracker.scrape_str));
EXPECT_EQ(Tier, tracker.tier);
}

View File

@ -43,13 +43,13 @@ protected:
EXPECT_TRUE(waitFor(test, MaxWaitMsec));
}
void createSingleFileTorrentContents(char const* top)
void createSingleFileTorrentContents(std::string_view top)
{
auto const path = tr_strvPath(top, "hello-world.txt");
createFileWithContents(path, "hello, world!\n");
}
void createMultifileTorrentContents(char const* top)
void createMultifileTorrentContents(std::string_view top)
{
auto path = tr_strvPath(top, "Felidae", "Felinae", "Acinonyx", "Cheetah", "Chester");
createFileWithContents(path, "It ain't easy bein' cheesy.\n");
@ -163,7 +163,7 @@ TEST_F(RenameTest, singleFilenameTorrent)
blockingTorrentVerify(tor);
expectHaveNone(tor, TotalSize);
createSingleFileTorrentContents(tor->currentDir);
createSingleFileTorrentContents(tor->currentDir().sv());
// sanity check the stats again, now that we've added the file
blockingTorrentVerify(tor);
@ -197,7 +197,7 @@ TEST_F(RenameTest, singleFilenameTorrent)
**** Now try a rename that should succeed
***/
auto tmpstr = tr_strvPath(tor->currentDir, "hello-world.txt");
auto tmpstr = tr_strvPath(tor->currentDir().sv(), "hello-world.txt");
EXPECT_TRUE(tr_sys_path_exists(tmpstr.c_str(), nullptr));
EXPECT_STREQ("hello-world.txt", tr_torrentName(tor));
EXPECT_EQ(0, torrentRenameAndWait(tor, tr_torrentName(tor), "foobar"));
@ -206,7 +206,7 @@ TEST_F(RenameTest, singleFilenameTorrent)
EXPECT_STREQ("foobar", tr_torrentName(tor)); // confirm the torrent's name is now 'foobar'
EXPECT_STREQ("foobar", files[0].name); // confirm the file's name is now 'foobar' in our struct
EXPECT_STREQ(nullptr, strstr(tr_torrentView(tor).torrent_filename, "foobar")); // confirm .torrent file hasn't changed
tmpstr = tr_strvPath(tor->currentDir, "foobar");
tmpstr = tr_strvPath(tor->currentDir().sv(), "foobar");
EXPECT_TRUE(tr_sys_path_exists(tmpstr.c_str(), nullptr)); // confirm the file's name is now 'foobar' on the disk
EXPECT_TRUE(testFileExistsAndConsistsOfThisString(tor, 0, "hello, world!\n")); // confirm the contents are right
@ -221,7 +221,7 @@ TEST_F(RenameTest, singleFilenameTorrent)
**** ...and rename it back again
***/
tmpstr = tr_strvPath(tor->currentDir, "foobar");
tmpstr = tr_strvPath(tor->currentDir().sv(), "foobar");
EXPECT_TRUE(tr_sys_path_exists(tmpstr.c_str(), nullptr));
EXPECT_EQ(0, torrentRenameAndWait(tor, "foobar", "hello-world.txt"));
EXPECT_FALSE(tr_sys_path_exists(tmpstr.c_str(), nullptr));
@ -287,7 +287,7 @@ TEST_F(RenameTest, multifileTorrent)
expectHaveNone(tor, TotalSize);
// build the local data
createMultifileTorrentContents(tor->currentDir);
createMultifileTorrentContents(tor->currentDir().sv());
// sanity check the (full) stats
blockingTorrentVerify(tor);
@ -523,7 +523,7 @@ TEST_F(RenameTest, partialFile)
for (tr_file_index_t i = 0; i < 3; ++i)
{
auto const expected = tr_strvPath(tor->currentDir, strings[i]);
auto const expected = tr_strvPath(tor->currentDir().sv(), strings[i]);
char* path = tr_torrentFindFile(tor, i);
EXPECT_EQ(expected, path);
tr_free(path);

View File

@ -399,8 +399,8 @@ protected:
{
auto const file = tr_torrentFile(tor, i);
auto path = (!complete && i == 0) ? tr_strvJoin(tor->currentDir, TR_PATH_DELIMITER_STR, file.name, ".part") :
tr_strvJoin(tor->currentDir, TR_PATH_DELIMITER_STR, file.name);
auto path = (!complete && i == 0) ? tr_strvJoin(tor->currentDir().sv(), TR_PATH_DELIMITER_STR, file.name, ".part") :
tr_strvJoin(tor->currentDir().sv(), TR_PATH_DELIMITER_STR, file.name);
auto const dirname = makeString(tr_sys_path_dirname(path.c_str(), nullptr));
tr_sys_dir_create(dirname.data(), TR_SYS_DIR_CREATE_PARENTS, 0700, nullptr);

View File

@ -218,7 +218,7 @@ static void doScrape(tr_info const* inf)
{
for (auto const& tracker : *inf->announce_list)
{
if (tracker.scrape_interned == TR_KEY_NONE)
if (std::empty(tracker.scrape_str))
{
continue;
}