From aa502f93127d7009722ffc884d5a8a222fa8914f Mon Sep 17 00:00:00 2001 From: Dmytro Lytovchenko Date: Sun, 15 May 2022 18:32:22 +0200 Subject: [PATCH] Modernize blocklist.cc: Rename, move members inside struct (#2010) * Modernize blocklist.cc to C++ * Modernize blocklist.cc: Renamed BlocklistFile struct and moved IPv4 range struct inside it Modernize bandwidth.cc: Review notes; Promote container of blocklists in session to vec of unique_ptrs --- libtransmission/blocklist.cc | 284 ++++++++++++--------------------- libtransmission/blocklist.h | 114 ++++++++++++- libtransmission/rpcimpl.cc | 4 +- libtransmission/session.cc | 53 +++--- libtransmission/session.h | 4 +- libtransmission/transmission.h | 2 +- 6 files changed, 229 insertions(+), 232 deletions(-) diff --git a/libtransmission/blocklist.cc b/libtransmission/blocklist.cc index 487796717..ae497905b 100644 --- a/libtransmission/blocklist.cc +++ b/libtransmission/blocklist.cc @@ -3,9 +3,9 @@ // or any future license endorsed by Mnemosyne LLC. // License text can be found in the licenses/ folder. +#include #include #include -#include /* bsearch(), qsort() */ #include #include @@ -18,48 +18,31 @@ #include "file.h" #include "log.h" #include "net.h" -#include "tr-assert.h" #include "utils.h" /*** **** PRIVATE ***/ -struct tr_ipv4_range +void BlocklistFile::close() { - uint32_t begin; - uint32_t end; -}; - -struct tr_blocklistFile -{ - bool isEnabled; - tr_sys_file_t fd; - size_t ruleCount; - uint64_t byteCount; - char* filename; - struct tr_ipv4_range* rules; -}; - -static void blocklistClose(tr_blocklistFile* b) -{ - if (b->rules != nullptr) + if (rules_ != nullptr) { - tr_sys_file_unmap(b->rules, b->byteCount); - tr_sys_file_close(b->fd); - b->rules = nullptr; - b->ruleCount = 0; - b->byteCount = 0; - b->fd = TR_BAD_SYS_FILE; + tr_sys_file_unmap(rules_, byte_count_); + tr_sys_file_close(fd_); + rules_ = nullptr; + rule_count_ = 0; + byte_count_ = 0; + fd_ = TR_BAD_SYS_FILE; } } -static void blocklistLoad(tr_blocklistFile* b) +void BlocklistFile::load() { - blocklistClose(b); + close(); auto info = tr_sys_path_info{}; - if (!tr_sys_path_get_info(b->filename, 0, &info)) + if (!tr_sys_path_get_info(getFilename(), 0, &info)) { return; } @@ -71,24 +54,24 @@ static void blocklistLoad(tr_blocklistFile* b) } tr_error* error = nullptr; - auto const fd = tr_sys_file_open(b->filename, TR_SYS_FILE_READ, 0, &error); + auto const fd = tr_sys_file_open(getFilename(), TR_SYS_FILE_READ, 0, &error); if (fd == TR_BAD_SYS_FILE) { tr_logAddWarn(fmt::format( _("Couldn't read '{path}': {error} ({error_code})"), - fmt::arg("path", b->filename), + fmt::arg("path", getFilename()), fmt::arg("error", error->message), fmt::arg("error_code", error->code))); tr_error_free(error); return; } - b->rules = static_cast(tr_sys_file_map_for_reading(fd, 0, byteCount, &error)); - if (b->rules == nullptr) + rules_ = static_cast(tr_sys_file_map_for_reading(fd, 0, byteCount, &error)); + if (rules_ == nullptr) { tr_logAddWarn(fmt::format( _("Couldn't read '{path}': {error} ({error_code})"), - fmt::arg("path", b->filename), + fmt::arg("path", getFilename()), fmt::arg("error", error->message), fmt::arg("error_code", error->code))); tr_sys_file_close(fd); @@ -96,108 +79,57 @@ static void blocklistLoad(tr_blocklistFile* b) return; } - b->fd = fd; - b->byteCount = byteCount; - b->ruleCount = byteCount / sizeof(struct tr_ipv4_range); + fd_ = fd; + byte_count_ = byteCount; + rule_count_ = byteCount / sizeof(IPv4Range); tr_logAddInfo(fmt::format( - ngettext("Blocklist '{path}' has {count} entry", "Blocklist '{path}' has {count} entries", b->ruleCount), - fmt::arg("path", tr_sys_path_basename(b->filename)), - fmt::arg("count", b->ruleCount))); + ngettext("Blocklist '{path}' has {count} entry", "Blocklist '{path}' has {count} entries", rule_count_), + fmt::arg("path", tr_sys_path_basename(getFilename())), + fmt::arg("count", rule_count_))); } -static void blocklistEnsureLoaded(tr_blocklistFile* b) +void BlocklistFile::ensureLoaded() { - if (b->rules == nullptr) + if (rules_ == nullptr) { - blocklistLoad(b); + load(); } } -static int compareAddressToRange(void const* va, void const* vb) -{ - auto const* a = static_cast(va); - auto const* b = static_cast(vb); - - if (*a < b->begin) - { - return -1; - } - - if (*a > b->end) - { - return 1; - } - - return 0; -} - -static void blocklistDelete(tr_blocklistFile* b) -{ - blocklistClose(b); - tr_sys_path_remove(b->filename); -} +// TODO: unused +//static void blocklistDelete(tr_blocklistFile* b) +//{ +// blocklistClose(b); +// tr_sys_path_remove(b->filename, nullptr); +//} /*** **** PACKAGE-VISIBLE ***/ -tr_blocklistFile* tr_blocklistFileNew(char const* filename, bool isEnabled) +bool BlocklistFile::hasAddress(tr_address const& addr) { - auto* const b = tr_new0(tr_blocklistFile, 1); - b->fd = TR_BAD_SYS_FILE; - b->filename = tr_strdup(filename); - b->isEnabled = isEnabled; + TR_ASSERT(tr_address_is_valid(&addr)); - return b; -} - -char const* tr_blocklistFileGetFilename(tr_blocklistFile const* b) -{ - return b->filename; -} - -void tr_blocklistFileFree(tr_blocklistFile* b) -{ - blocklistClose(b); - tr_free(b->filename); - tr_free(b); -} - -size_t tr_blocklistFileGetRuleCount(tr_blocklistFile const* b) -{ - blocklistEnsureLoaded((tr_blocklistFile*)b); - - return b->ruleCount; -} - -void tr_blocklistFileSetEnabled(tr_blocklistFile* b, bool isEnabled) -{ - TR_ASSERT(b != nullptr); - - b->isEnabled = isEnabled; -} - -bool tr_blocklistFileHasAddress(tr_blocklistFile* b, tr_address const* addr) -{ - TR_ASSERT(tr_address_is_valid(addr)); - - if (!b->isEnabled || addr->type == TR_AF_INET6) + if (!is_enabled_ || addr.type == TR_AF_INET6) { return false; } - blocklistEnsureLoaded(b); + ensureLoaded(); - if (b->rules == nullptr || b->ruleCount == 0) + if (rules_ == nullptr || rule_count_ == 0) { return false; } - auto const needle = ntohl(addr->addr.addr4.s_addr); + auto const needle = ntohl(addr.addr.addr4.s_addr); - auto const* range = static_cast( - bsearch(&needle, b->rules, b->ruleCount, sizeof(struct tr_ipv4_range), compareAddressToRange)); + // std::binary_search works differently and requires a less-than comparison + // and two arguments of the same type. std::bsearch is the right choice. + auto const* range = static_cast( + std::bsearch(&needle, rules_, rule_count_, sizeof(IPv4Range), IPv4Range::compareAddressToRange)); return range != nullptr; } @@ -207,7 +139,7 @@ bool tr_blocklistFileHasAddress(tr_blocklistFile* b, tr_address const* addr) * http://wiki.phoenixlabs.org/wiki/P2P_Format * https://en.wikipedia.org/wiki/PeerGuardian#P2P_plaintext_format */ -static bool parseLine1(std::string_view line, struct tr_ipv4_range* range) +bool BlocklistFile::parseLine1(std::string_view line, struct IPv4Range* range) { // remove leading "comment:" auto pos = line.find(':'); @@ -225,7 +157,7 @@ static bool parseLine1(std::string_view line, struct tr_ipv4_range* range) } if (auto addr = tr_address{}; tr_address_from_string(&addr, line.substr(0, pos))) { - range->begin = ntohl(addr.addr.addr4.s_addr); + range->begin_ = ntohl(addr.addr.addr4.s_addr); } else { @@ -236,7 +168,7 @@ static bool parseLine1(std::string_view line, struct tr_ipv4_range* range) // parse the trailing 'y.y.y.y' if (auto addr = tr_address{}; tr_address_from_string(&addr, line)) { - range->end = ntohl(addr.addr.addr4.s_addr); + range->end_ = ntohl(addr.addr.addr4.s_addr); } else { @@ -250,7 +182,7 @@ static bool parseLine1(std::string_view line, struct tr_ipv4_range* range) * DAT / eMule format: "000.000.000.000 - 000.255.255.255 , 000 , invalid ip"a * https://sourceforge.net/p/peerguardian/wiki/dev-blocklist-format-dat/ */ -static bool parseLine2(std::string_view line, struct tr_ipv4_range* range) +bool BlocklistFile::parseLine2(std::string_view line, struct IPv4Range* range) { static auto constexpr Delim1 = std::string_view{ " - " }; static auto constexpr Delim2 = std::string_view{ " , " }; @@ -263,7 +195,7 @@ static bool parseLine2(std::string_view line, struct tr_ipv4_range* range) if (auto addr = tr_address{}; tr_address_from_string(&addr, line.substr(0, pos))) { - range->begin = ntohl(addr.addr.addr4.s_addr); + range->begin_ = ntohl(addr.addr.addr4.s_addr); } else { @@ -279,7 +211,7 @@ static bool parseLine2(std::string_view line, struct tr_ipv4_range* range) if (auto addr = tr_address{}; tr_address_from_string(&addr, line.substr(0, pos))) { - range->end = ntohl(addr.addr.addr4.s_addr); + range->end_ = ntohl(addr.addr.addr4.s_addr); } else { @@ -293,7 +225,7 @@ static bool parseLine2(std::string_view line, struct tr_ipv4_range* range) * CIDR notation: "0.0.0.0/8", IPv4 only * https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing#CIDR_notation */ -static bool parseLine3(char const* line, struct tr_ipv4_range* range) +bool BlocklistFile::parseLine3(char const* line, IPv4Range* range) { unsigned int ip[4]; unsigned int pflen = 0; @@ -315,48 +247,30 @@ static bool parseLine3(char const* line, struct tr_ipv4_range* range) ip_u = ip[0] << 24 | ip[1] << 16 | ip[2] << 8 | ip[3]; /* fill the non-prefix bits the way we need it */ - range->begin = ip_u & mask; - range->end = ip_u | (~mask); + range->begin_ = ip_u & mask; + range->end_ = ip_u | (~mask); return true; } -static bool parseLine(char const* line, struct tr_ipv4_range* range) +bool BlocklistFile::parseLine(char const* line, IPv4Range* range) { return parseLine1(line, range) || parseLine2(line, range) || parseLine3(line, range); } -static int compareAddressRangesByFirstAddress(void const* va, void const* vb) +bool BlocklistFile::compareAddressRangesByFirstAddress(IPv4Range const& a, IPv4Range const& b) { - auto const* a = static_cast(va); - auto const* b = static_cast(vb); - - if (a->begin < b->begin) - { - return -1; - } - - if (a->begin > b->begin) - { - return 1; - } - - return 0; + return a.begin_ < b.begin_; } -int tr_blocklistFileSetContent(tr_blocklistFile* b, char const* filename) +size_t BlocklistFile::setContent(char const* filename) { int inCount = 0; char line[2048]; - // TODO: should be a vector - struct tr_ipv4_range* ranges = nullptr; - size_t ranges_alloc = 0; - size_t ranges_count = 0; tr_error* error = nullptr; if (filename == nullptr) { - blocklistDelete(b); return 0; } @@ -372,14 +286,18 @@ int tr_blocklistFileSetContent(tr_blocklistFile* b, char const* filename) return 0; } - blocklistClose(b); + close(); - auto const out = tr_sys_file_open(b->filename, TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE | TR_SYS_FILE_TRUNCATE, 0666, &error); + auto const out = tr_sys_file_open( + getFilename(), + TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE | TR_SYS_FILE_TRUNCATE, + 0666, + &error); if (out == TR_BAD_SYS_FILE) { tr_logAddWarn(fmt::format( _("Couldn't read '{path}': {error} ({error_code})"), - fmt::arg("path", b->filename), + fmt::arg("path", getFilename()), fmt::arg("error", error->message), fmt::arg("error_code", error->code))); tr_error_free(error); @@ -388,9 +306,10 @@ int tr_blocklistFileSetContent(tr_blocklistFile* b, char const* filename) } /* load the rules into memory */ + std::vector ranges; while (tr_sys_file_read_line(in, line, sizeof(line))) { - struct tr_ipv4_range range; + IPv4Range range = {}; ++inCount; @@ -401,60 +320,41 @@ int tr_blocklistFileSetContent(tr_blocklistFile* b, char const* filename) continue; } - if (ranges_alloc == ranges_count) - { - ranges_alloc += 4096; /* arbitrary */ - ranges = tr_renew(struct tr_ipv4_range, ranges, ranges_alloc); - } - - ranges[ranges_count++] = range; + ranges.push_back(range); } - if (ranges_count > 0) /* sort and merge */ + if (!std::empty(ranges)) // sort and merge { - struct tr_ipv4_range* keep = ranges; + size_t keep = 0; // index in ranges - /* sort */ - qsort(ranges, ranges_count, sizeof(struct tr_ipv4_range), compareAddressRangesByFirstAddress); + std::sort(std::begin(ranges), std::end(ranges), BlocklistFile::compareAddressRangesByFirstAddress); - /* merge */ - for (size_t i = 1; i < ranges_count; ++i) + // merge + for (auto const& r : ranges) { - struct tr_ipv4_range const* r = &ranges[i]; - - if (keep->end < r->begin) + if (ranges[keep].end_ < r.begin_) { - *++keep = *r; + ranges[++keep] = r; } - else if (keep->end < r->end) + else if (ranges[keep].end_ < r.end_) { - keep->end = r->end; + ranges[keep].end_ = r.end_; } } - ranges_count = keep + 1 - ranges; + TR_ASSERT_MSG(keep + 1 <= std::size(ranges), "Can shrink `ranges` or leave intact, but not grow"); + ranges.resize(keep + 1); #ifdef TR_ENABLE_ASSERTS - - /* sanity checks: make sure the rules are sorted in ascending order and don't overlap */ - for (size_t i = 0; i < ranges_count; ++i) - { - TR_ASSERT(ranges[i].begin <= ranges[i].end); - } - - for (size_t i = 1; i < ranges_count; ++i) - { - TR_ASSERT(ranges[i - 1].end < ranges[i].begin); - } - + assertValidRules(ranges); #endif } - if (!tr_sys_file_write(out, ranges, sizeof(struct tr_ipv4_range) * ranges_count, nullptr, &error)) + if (!tr_sys_file_write(out, ranges.data(), sizeof(IPv4Range) * std::size(ranges), nullptr, &error)) { tr_logAddWarn(fmt::format( _("Couldn't save '{path}': {error} ({error_code})"), - fmt::arg("path", b->filename), + fmt::arg("path", getFilename()), fmt::arg("error", error->message), fmt::arg("error_code", error->code))); tr_error_free(error); @@ -462,16 +362,30 @@ int tr_blocklistFileSetContent(tr_blocklistFile* b, char const* filename) else { tr_logAddInfo(fmt::format( - ngettext("Blocklist '{path}' has {count} entry", "Blocklist '{path}' has {count} entries", b->ruleCount), - fmt::arg("path", tr_sys_path_basename(b->filename)), - fmt::arg("count", b->ruleCount))); + ngettext("Blocklist '{path}' has {count} entry", "Blocklist '{path}' has {count} entries", rule_count_), + fmt::arg("path", tr_sys_path_basename(getFilename())), + fmt::arg("count", rule_count_))); } - tr_free(ranges); tr_sys_file_close(out); tr_sys_file_close(in); - blocklistLoad(b); + load(); - return ranges_count; + return std::size(ranges); } + +#ifdef TR_ENABLE_ASSERTS +void BlocklistFile::assertValidRules(std::vector& ranges) +{ + for (auto const& r : ranges) + { + TR_ASSERT(r.begin_ <= r.end_); + } + + for (size_t i = 1; i < std::size(ranges); ++i) + { + TR_ASSERT(ranges[i - 1].end_ < ranges[i].begin_); + } +} +#endif diff --git a/libtransmission/blocklist.h b/libtransmission/blocklist.h index 853305277..3dcb73a01 100644 --- a/libtransmission/blocklist.h +++ b/libtransmission/blocklist.h @@ -9,19 +9,117 @@ #error only libtransmission should #include this header. #endif +#include +#include +#include + +#include "file.h" // for tr_sys_file_t +#include "tr-assert.h" +#include "tr-macros.h" + struct tr_address; -struct tr_blocklistFile; -tr_blocklistFile* tr_blocklistFileNew(char const* filename, bool isEnabled); +struct BlocklistFile +{ +public: + // Prevent moving to protect the fd_ from accidental destruction + BlocklistFile(BlocklistFile&&) = delete; + BlocklistFile(BlocklistFile const&) = delete; + BlocklistFile& operator=(BlocklistFile const&) = delete; + BlocklistFile& operator=(BlocklistFile&&) = delete; -char const* tr_blocklistFileGetFilename(tr_blocklistFile const* b); + BlocklistFile(char const* filename, bool isEnabled) + : is_enabled_(isEnabled) + , filename_(filename) + { + } -size_t tr_blocklistFileGetRuleCount(tr_blocklistFile const* b); + ~BlocklistFile() + { + close(); + } -void tr_blocklistFileFree(tr_blocklistFile* b); + [[nodiscard]] bool exists() const + { + return tr_sys_path_exists(getFilename(), nullptr); + } -void tr_blocklistFileSetEnabled(tr_blocklistFile* b, bool isEnabled); + [[nodiscard]] char const* getFilename() const + { + return filename_.c_str(); + } -bool tr_blocklistFileHasAddress(tr_blocklistFile* b, struct tr_address const* addr); + // TODO: This function should be const, but cannot be const due to it calling ensureLoaded() + size_t getRuleCount() + { + ensureLoaded(); -int tr_blocklistFileSetContent(tr_blocklistFile* b, char const* filename); + return rule_count_; + } + + [[nodiscard]] constexpr bool isEnabled() const + { + return is_enabled_; + } + + void setEnabled(bool isEnabled) + { + is_enabled_ = isEnabled; + } + + bool hasAddress(tr_address const& addr); + + /// @brief Read the file of ranges, sort and merge, write to our own file, and reload from it + size_t setContent(char const* filename); + +private: + struct IPv4Range + { + uint32_t begin_ = 0; + uint32_t end_ = 0; + + /// @brief Used for std::bsearch of an IPv4 address + static int compareAddressToRange(void const* va, void const* vb) + { + auto const* a = reinterpret_cast(va); + auto const* b = reinterpret_cast(vb); + + if (*a < b->begin_) + { + return -1; + } + + if (*a > b->end_) + { + return 1; + } + + return 0; + } + }; + + void ensureLoaded(); + void load(); + void close(); + + static bool parseLine(char const* line, IPv4Range* range); + static bool compareAddressRangesByFirstAddress(IPv4Range const& a, IPv4Range const& b); + + static bool parseLine1(std::string_view line, struct IPv4Range* range); + static bool parseLine2(std::string_view line, struct IPv4Range* range); + static bool parseLine3(char const* line, IPv4Range* range); + +#ifdef TR_ENABLE_ASSERTS + /// @brief Sanity checks: make sure the rules are sorted in ascending order and don't overlap + void assertValidRules(std::vector& ranges); +#endif + + bool is_enabled_; + tr_sys_file_t fd_{ TR_BAD_SYS_FILE }; + size_t rule_count_ = 0; + uint64_t byte_count_ = 0; + std::string const filename_; + + /// @brief Not a container, memory mapped file + IPv4Range* rules_ = nullptr; +}; diff --git a/libtransmission/rpcimpl.cc b/libtransmission/rpcimpl.cc index c08cae7ad..dd7380e46 100644 --- a/libtransmission/rpcimpl.cc +++ b/libtransmission/rpcimpl.cc @@ -1455,8 +1455,8 @@ static void onBlocklistFetched(tr_web::FetchResponse const& web_response) } // feed it to the session and give the client a response - int const rule_count = tr_blocklistSetContent(session, filename); - tr_variantDictAddInt(data->args_out, TR_KEY_blocklist_size, rule_count); + size_t const rule_count = tr_blocklistSetContent(session, filename); + tr_variantDictAddInt(data->args_out, TR_KEY_blocklist_size, static_cast(rule_count)); tr_sys_path_remove(filename); tr_idle_function_done(data, SuccessResult); } diff --git a/libtransmission/session.cc b/libtransmission/session.cc index 514b2c543..c7b89f18b 100644 --- a/libtransmission/session.cc +++ b/libtransmission/session.cc @@ -2374,14 +2374,11 @@ static void loadBlocklists(tr_session* session) if (!tr_sys_path_get_info(binname, 0, &binname_info)) /* create it */ { - tr_blocklistFile* b = tr_blocklistFileNew(binname, isEnabled); - - if (auto const n = tr_blocklistFileSetContent(b, path); n > 0) + BlocklistFile b(binname, isEnabled); + if (auto const n = b.setContent(path); n > 0) { load = binname; } - - tr_blocklistFileFree(b); } else if ( tr_sys_path_get_info(path, 0, &path_info) && @@ -2390,9 +2387,10 @@ static void loadBlocklists(tr_session* session) auto const old = tr_pathbuf{ binname, ".old"sv }; tr_sys_path_remove(old); tr_sys_path_rename(binname, old); - auto* const b = tr_blocklistFileNew(binname, isEnabled); - if (tr_blocklistFileSetContent(b, path) > 0) + BlocklistFile b(binname, isEnabled); + + if (b.setContent(path) > 0) { tr_sys_path_remove(old); } @@ -2401,8 +2399,6 @@ static void loadBlocklists(tr_session* session) tr_sys_path_remove(binname); tr_sys_path_rename(old, binname); } - - tr_blocklistFileFree(b); } } @@ -2417,7 +2413,7 @@ static void loadBlocklists(tr_session* session) std::begin(loadme), std::end(loadme), std::back_inserter(session->blocklists), - [&isEnabled](auto const& path) { return tr_blocklistFileNew(path.c_str(), isEnabled); }); + [&isEnabled](auto const& path) { return std::make_unique(path.c_str(), isEnabled); }); /* cleanup */ tr_sys_dir_close(odir); @@ -2425,9 +2421,7 @@ static void loadBlocklists(tr_session* session) static void closeBlocklists(tr_session* session) { - auto& src = session->blocklists; - std::for_each(std::begin(src), std::end(src), [](auto* b) { tr_blocklistFileFree(b); }); - src.clear(); + session->blocklists.clear(); } void tr_sessionReloadBlocklists(tr_session* session) @@ -2442,12 +2436,8 @@ size_t tr_blocklistGetRuleCount(tr_session const* session) { TR_ASSERT(tr_isSession(session)); - auto const& src = session->blocklists; - return std::accumulate( - std::begin(src), - std::end(src), - 0, - [](size_t sum, auto const* cur) { return sum + tr_blocklistFileGetRuleCount(cur); }); + auto& src = session->blocklists; + return std::accumulate(std::begin(src), std::end(src), 0, [](int sum, auto& cur) { return sum + cur->getRuleCount(); }); } bool tr_blocklistIsEnabled(tr_session const* session) @@ -2461,10 +2451,7 @@ void tr_session::useBlocklist(bool enabled) { this->blocklist_enabled_ = enabled; - std::for_each( - std::begin(blocklists), - std::end(blocklists), - [enabled](auto* blocklist) { tr_blocklistFileSetEnabled(blocklist, enabled); }); + std::for_each(std::begin(blocklists), std::end(blocklists), [enabled](auto& blocklist) { blocklist->setEnabled(enabled); }); } void tr_blocklistSetEnabled(tr_session* session, bool enabled) @@ -2481,41 +2468,39 @@ bool tr_blocklistExists(tr_session const* session) return !std::empty(session->blocklists); } -int tr_blocklistSetContent(tr_session* session, char const* contentFilename) +size_t tr_blocklistSetContent(tr_session* session, char const* contentFilename) { auto const lock = session->unique_lock(); // find (or add) the default blocklist - tr_blocklistFile* b = nullptr; auto& src = session->blocklists; char const* const name = DEFAULT_BLOCKLIST_FILENAME; auto const it = std::find_if( std::begin(src), std::end(src), - [&name](auto const* blocklist) { return tr_strvEndsWith(tr_blocklistFileGetFilename(blocklist), name); }); + [&name](auto const& blocklist) { return tr_strvEndsWith(blocklist->getFilename(), name); }); + BlocklistFile* b = nullptr; if (it == std::end(src)) { - b = tr_blocklistFileNew(tr_pathbuf{ session->config_dir, "/blocklists/"sv, name }, session->useBlocklist()); - src.push_back(b); + auto path = tr_pathbuf{ session->config_dir, "/blocklists/"sv, name }; + src.push_back(std::make_unique(path, session->useBlocklist())); + b = std::rbegin(src)->get(); } else { - b = *it; + b = it->get(); } // set the default blocklist's content - int const ruleCount = tr_blocklistFileSetContent(b, contentFilename); + int const ruleCount = b->setContent(contentFilename); return ruleCount; } bool tr_sessionIsAddressBlocked(tr_session const* session, tr_address const* addr) { auto const& src = session->blocklists; - return std::any_of( - std::begin(src), - std::end(src), - [&addr](auto* blocklist) { return tr_blocklistFileHasAddress(blocklist, addr); }); + return std::any_of(std::begin(src), std::end(src), [&addr](auto& blocklist) { return blocklist->hasAddress(*addr); }); } void tr_blocklistSetURL(tr_session* session, char const* url) diff --git a/libtransmission/session.h b/libtransmission/session.h index 3c7ea7509..fb26caf88 100644 --- a/libtransmission/session.h +++ b/libtransmission/session.h @@ -53,7 +53,7 @@ struct tr_address; struct tr_announcer; struct tr_announcer_udp; struct tr_bindsockets; -struct tr_blocklistFile; +struct BlocklistFile; struct tr_cache; struct tr_fdInfo; @@ -438,7 +438,7 @@ public: std::string resume_dir; std::string torrent_dir; - std::vector blocklists; + std::vector> blocklists; struct tr_peerMgr* peerMgr; struct tr_shared* shared; diff --git a/libtransmission/transmission.h b/libtransmission/transmission.h index 86904de44..3bb5020a4 100644 --- a/libtransmission/transmission.h +++ b/libtransmission/transmission.h @@ -752,7 +752,7 @@ bool tr_sessionIsScriptEnabled(tr_session const*, TrScript); * * Passing nullptr for a filename will clear the blocklist. */ -int tr_blocklistSetContent(tr_session* session, char const* filename); +size_t tr_blocklistSetContent(tr_session* session, char const* filename); size_t tr_blocklistGetRuleCount(tr_session const* session);