diff --git a/libtransmission/announcer-udp.cc b/libtransmission/announcer-udp.cc index 5a32b48b7..affaba388 100644 --- a/libtransmission/announcer-udp.cc +++ b/libtransmission/announcer-udp.cc @@ -652,7 +652,7 @@ static void tau_tracker_upkeep_ex(struct tau_tracker* tracker, bool timeout_reqs hints.ai_protocol = IPPROTO_UDP; logtrace(tracker->host, "Trying a new DNS lookup"); tracker->dns_request = evdns_getaddrinfo( - tracker->session->evdns_base, + tracker->session->evdnsBase(), tr_strlower(tracker->host.sv()).c_str(), nullptr, &hints, diff --git a/libtransmission/peer-mgr.cc b/libtransmission/peer-mgr.cc index c40f792db..a504e5c7e 100644 --- a/libtransmission/peer-mgr.cc +++ b/libtransmission/peer-mgr.cc @@ -2219,7 +2219,7 @@ void rechokeUploads(tr_swarm* s, uint64_t const now) for (auto& item : choked) { - if (unchoked_interested >= session->upload_slots_per_torrent) + if (unchoked_interested >= session->uploadSlotsPerTorrent()) { break; } @@ -2813,7 +2813,7 @@ struct peer_candidate void initiateConnection(tr_peerMgr* mgr, tr_swarm* s, peer_atom& atom) { time_t const now = tr_time(); - bool utp = tr_sessionIsUTPEnabled(mgr->session) && !atom.utp_failed; + bool utp = mgr->session->allowsUTP() && !atom.utp_failed; if (atom.fromFirst == TR_PEER_FROM_PEX) { diff --git a/libtransmission/peer-msgs.cc b/libtransmission/peer-msgs.cc index 8974d2168..f0cf1627e 100644 --- a/libtransmission/peer-msgs.cc +++ b/libtransmission/peer-msgs.cc @@ -1548,7 +1548,7 @@ static ReadState readBtId(tr_peerMsgsImpl* msgs, struct evbuffer* inbuf, size_t static void prefetchPieces(tr_peerMsgsImpl* msgs) { - if (!msgs->session->isPrefetchEnabled) + if (!msgs->session->allowsPrefetch()) { return; } diff --git a/libtransmission/rpc-server.cc b/libtransmission/rpc-server.cc index 1044c48b0..64011ab49 100644 --- a/libtransmission/rpc-server.cc +++ b/libtransmission/rpc-server.cc @@ -105,15 +105,6 @@ static bool constexpr tr_rpc_address_is_valid(tr_rpc_address const& a) } #endif -/*** -**** -***/ - -static char const* get_current_session_id(tr_rpc_server const* server) -{ - return server->session->session_id.c_str(); -} - /** *** **/ @@ -398,10 +389,8 @@ static bool isHostnameAllowed(tr_rpc_server const* server, struct evhttp_request static bool test_session_id(tr_rpc_server* server, evhttp_request const* req) { - char const* ours = get_current_session_id(server); - char const* theirs = evhttp_find_header(req->input_headers, TR_RPC_SESSION_ID_HEADER); - bool const success = theirs != nullptr && strcmp(theirs, ours) == 0; - return success; + char const* const session_id = evhttp_find_header(req->input_headers, TR_RPC_SESSION_ID_HEADER); + return session_id != nullptr && server->session->sessionId() == session_id; } static bool isAuthorized(tr_rpc_server const* server, char const* auth_header) @@ -518,7 +507,7 @@ static void handle_request(struct evhttp_request* req, void* arg) #ifdef REQUIRE_SESSION_ID else if (!test_session_id(server, req)) { - char const* sessionId = get_current_session_id(server); + auto const session_id = std::string{ server->session->sessionId() }; auto const tmp = fmt::format( FMT_STRING("

Your request had an invalid session-id header.

" "

To fix this, follow these steps:" @@ -531,8 +520,8 @@ static void handle_request(struct evhttp_request* req, void* arg) "attacks.

" "

{:s}: {:s}

"), TR_RPC_SESSION_ID_HEADER, - sessionId); - evhttp_add_header(req->output_headers, TR_RPC_SESSION_ID_HEADER, sessionId); + session_id); + evhttp_add_header(req->output_headers, TR_RPC_SESSION_ID_HEADER, session_id.c_str()); evhttp_add_header(req->output_headers, "Access-Control-Expose-Headers", TR_RPC_SESSION_ID_HEADER); send_simple_response(req, 409, tmp.c_str()); } diff --git a/libtransmission/rpcimpl.cc b/libtransmission/rpcimpl.cc index ad0d30a38..0b9a707f3 100644 --- a/libtransmission/rpcimpl.cc +++ b/libtransmission/rpcimpl.cc @@ -2188,7 +2188,7 @@ static void addSessionField(tr_session const* s, tr_variant* d, tr_quark key) break; case TR_KEY_utp_enabled: - tr_variantDictAddBool(d, key, tr_sessionIsUTPEnabled(s)); + tr_variantDictAddBool(d, key, s->allowsUTP()); break; case TR_KEY_dht_enabled: @@ -2232,11 +2232,11 @@ static void addSessionField(tr_session const* s, tr_variant* d, tr_quark key) break; case TR_KEY_seedRatioLimited: - tr_variantDictAddBool(d, key, tr_sessionIsRatioLimited(s)); + tr_variantDictAddBool(d, key, s->isRatioLimited()); break; case TR_KEY_idle_seeding_limit: - tr_variantDictAddInt(d, key, tr_sessionGetIdleLimit(s)); + tr_variantDictAddInt(d, key, s->idleLimitMinutes()); break; case TR_KEY_idle_seeding_limit_enabled: @@ -2264,7 +2264,7 @@ static void addSessionField(tr_session const* s, tr_variant* d, tr_quark key) break; case TR_KEY_speed_limit_up_enabled: - tr_variantDictAddBool(d, key, tr_sessionIsSpeedLimited(s, TR_UP)); + tr_variantDictAddBool(d, key, s->isSpeedLimited(TR_UP)); break; case TR_KEY_speed_limit_down: @@ -2272,7 +2272,7 @@ static void addSessionField(tr_session const* s, tr_variant* d, tr_quark key) break; case TR_KEY_speed_limit_down_enabled: - tr_variantDictAddBool(d, key, tr_sessionIsSpeedLimited(s, TR_DOWN)); + tr_variantDictAddBool(d, key, s->isSpeedLimited(TR_DOWN)); break; case TR_KEY_script_torrent_added_filename: @@ -2328,7 +2328,7 @@ static void addSessionField(tr_session const* s, tr_variant* d, tr_quark key) break; case TR_KEY_session_id: - tr_variantDictAddStr(d, key, s->session_id.sv()); + tr_variantDictAddStr(d, key, s->sessionId()); break; } } diff --git a/libtransmission/session.cc b/libtransmission/session.cc index c45518320..a98f15477 100644 --- a/libtransmission/session.cc +++ b/libtransmission/session.cc @@ -25,6 +25,7 @@ #include /* umask() */ #endif +#include #include #include @@ -389,17 +390,17 @@ void tr_sessionGetSettings(tr_session const* s, tr_variant* setme_dictionary) tr_variantDictAddStr(d, TR_KEY_blocklist_url, s->blocklistUrl()); tr_variantDictAddInt(d, TR_KEY_cache_size_mb, tr_sessionGetCacheLimit_MB(s)); tr_variantDictAddBool(d, TR_KEY_dht_enabled, s->allowsDHT()); - tr_variantDictAddBool(d, TR_KEY_utp_enabled, s->isUTPEnabled); + tr_variantDictAddBool(d, TR_KEY_utp_enabled, s->allowsUTP()); tr_variantDictAddBool(d, TR_KEY_lpd_enabled, s->allowsLPD()); tr_variantDictAddStr(d, TR_KEY_download_dir, tr_sessionGetDownloadDir(s)); tr_variantDictAddStr(d, TR_KEY_default_trackers, s->defaultTrackersStr()); tr_variantDictAddInt(d, TR_KEY_download_queue_size, s->queueSize(TR_DOWN)); tr_variantDictAddBool(d, TR_KEY_download_queue_enabled, s->queueEnabled(TR_DOWN)); tr_variantDictAddInt(d, TR_KEY_speed_limit_down, tr_sessionGetSpeedLimit_KBps(s, TR_DOWN)); - tr_variantDictAddBool(d, TR_KEY_speed_limit_down_enabled, tr_sessionIsSpeedLimited(s, TR_DOWN)); + tr_variantDictAddBool(d, TR_KEY_speed_limit_down_enabled, s->isSpeedLimited(TR_DOWN)); tr_variantDictAddInt(d, TR_KEY_encryption, s->encryptionMode()); - tr_variantDictAddInt(d, TR_KEY_idle_seeding_limit, tr_sessionGetIdleLimit(s)); - tr_variantDictAddBool(d, TR_KEY_idle_seeding_limit_enabled, tr_sessionIsIdleLimited(s)); + tr_variantDictAddInt(d, TR_KEY_idle_seeding_limit, s->idleLimitMinutes()); + tr_variantDictAddBool(d, TR_KEY_idle_seeding_limit_enabled, s->isIdleLimited()); tr_variantDictAddStr(d, TR_KEY_incomplete_dir, tr_sessionGetIncompleteDir(s)); tr_variantDictAddBool(d, TR_KEY_incomplete_dir_enabled, tr_sessionIsIncompleteDirEnabled(s)); tr_variantDictAddInt(d, TR_KEY_message_level, tr_logGetLevel()); @@ -414,12 +415,12 @@ void tr_sessionGetSettings(tr_session const* s, tr_variant* setme_dictionary) tr_variantDictAddBool(d, TR_KEY_pex_enabled, s->allowsPEX()); tr_variantDictAddBool(d, TR_KEY_port_forwarding_enabled, tr_sessionIsPortForwardingEnabled(s)); tr_variantDictAddInt(d, TR_KEY_preallocation, s->preallocationMode()); - tr_variantDictAddBool(d, TR_KEY_prefetch_enabled, s->isPrefetchEnabled); - tr_variantDictAddInt(d, TR_KEY_peer_id_ttl_hours, s->peer_id_ttl_hours); + tr_variantDictAddBool(d, TR_KEY_prefetch_enabled, s->allowsPrefetch()); + tr_variantDictAddInt(d, TR_KEY_peer_id_ttl_hours, s->peerIdTTLHours()); tr_variantDictAddBool(d, TR_KEY_queue_stalled_enabled, s->queueStalledEnabled()); tr_variantDictAddInt(d, TR_KEY_queue_stalled_minutes, s->queueStalledMinutes()); tr_variantDictAddReal(d, TR_KEY_ratio_limit, s->desiredRatio()); - tr_variantDictAddBool(d, TR_KEY_ratio_limit_enabled, s->isRatioLimited); + tr_variantDictAddBool(d, TR_KEY_ratio_limit_enabled, s->isRatioLimited()); tr_variantDictAddBool(d, TR_KEY_rename_partial_files, s->isIncompleteFileNamingEnabled()); tr_variantDictAddBool(d, TR_KEY_rpc_authentication_required, tr_sessionIsRPCPasswordEnabled(s)); tr_variantDictAddStr(d, TR_KEY_rpc_bind_address, s->rpc_server_->getBindAddress()); @@ -442,9 +443,9 @@ void tr_sessionGetSettings(tr_session const* s, tr_variant* setme_dictionary) tr_variantDictAddInt(d, TR_KEY_alt_speed_time_end, tr_sessionGetAltSpeedEnd(s)); tr_variantDictAddInt(d, TR_KEY_alt_speed_time_day, tr_sessionGetAltSpeedDay(s)); tr_variantDictAddInt(d, TR_KEY_speed_limit_up, tr_sessionGetSpeedLimit_KBps(s, TR_UP)); - tr_variantDictAddBool(d, TR_KEY_speed_limit_up_enabled, tr_sessionIsSpeedLimited(s, TR_UP)); - tr_variantDictAddStr(d, TR_KEY_umask, fmt::format("{:#o}", s->umask)); - tr_variantDictAddInt(d, TR_KEY_upload_slots_per_torrent, s->upload_slots_per_torrent); + tr_variantDictAddBool(d, TR_KEY_speed_limit_up_enabled, s->isSpeedLimited(TR_UP)); + tr_variantDictAddStr(d, TR_KEY_umask, fmt::format("{:#o}", s->umask_)); + tr_variantDictAddInt(d, TR_KEY_upload_slots_per_torrent, s->uploadSlotsPerTorrent()); tr_variantDictAddStr(d, TR_KEY_bind_address_ipv4, s->bind_ipv4.readable()); tr_variantDictAddStr(d, TR_KEY_bind_address_ipv6, s->bind_ipv6.readable()); tr_variantDictAddBool(d, TR_KEY_start_added_torrents, !s->shouldPauseAddedTorrents()); @@ -646,8 +647,6 @@ void tr_session::onNowTimer() now_timer_->setInterval(std::chrono::duration_cast(target_interval)); } -static void loadBlocklists(tr_session* session); - void tr_session::initImpl(init_data& data) { auto lock = unique_lock(); @@ -679,7 +678,7 @@ void tr_session::initImpl(init_data& data) **/ tr_sys_dir_create(tr_pathbuf{ configDir(), "/blocklists"sv }, TR_SYS_DIR_CREATE_PARENTS, 0777); - loadBlocklists(this); + loadBlocklists(); tr_announcerInit(this); @@ -728,14 +727,14 @@ void tr_session::setImpl(init_data& data) if (tr_variantDictFindStrView(settings, TR_KEY_umask, &sv)) { /* Read a umask as a string representing an octal number. */ - this->umask = static_cast(tr_parseNum(sv, 8).value_or(DefaultUmask)); - ::umask(this->umask); + this->umask_ = static_cast(tr_parseNum(sv, 8).value_or(DefaultUmask)); + ::umask(this->umask_); } else if (tr_variantDictFindInt(settings, TR_KEY_umask, &i)) { /* Or as a base 10 integer to remain compatible with the old settings format. */ - this->umask = (mode_t)i; - ::umask(this->umask); + this->umask_ = (mode_t)i; + ::umask(this->umask_); } #endif @@ -819,7 +818,7 @@ void tr_session::setImpl(init_data& data) if (tr_variantDictFindInt(settings, TR_KEY_peer_id_ttl_hours, &i)) { - this->peer_id_ttl_hours = i; + this->peer_id_ttl_hours_ = i; } /* torrent queues */ @@ -856,7 +855,7 @@ void tr_session::setImpl(init_data& data) /* files and directories */ if (tr_variantDictFindBool(settings, TR_KEY_prefetch_enabled, &boolVal)) { - this->isPrefetchEnabled = boolVal; + this->is_prefetch_enabled_ = boolVal; } if (tr_variantDictFindInt(settings, TR_KEY_preallocation, &i)) @@ -957,7 +956,7 @@ void tr_session::setImpl(init_data& data) if (tr_variantDictFindInt(settings, TR_KEY_upload_slots_per_torrent, &i)) { - this->upload_slots_per_torrent = i; + this->upload_slots_per_torrent_ = i; } if (tr_variantDictFindInt(settings, TR_KEY_speed_limit_up, &i)) @@ -1255,11 +1254,11 @@ tr_port_forwarding tr_sessionGetPortForwarding(tr_session const* session) **** ***/ -void tr_sessionSetRatioLimited(tr_session* session, bool isLimited) +void tr_sessionSetRatioLimited(tr_session* session, bool is_limited) { TR_ASSERT(session != nullptr); - session->isRatioLimited = isLimited; + session->is_ratio_limited_ = is_limited; } void tr_sessionSetRatioLimit(tr_session* session, double desired_ratio) @@ -1273,7 +1272,7 @@ bool tr_sessionIsRatioLimited(tr_session const* session) { TR_ASSERT(session != nullptr); - return session->isRatioLimited; + return session->isRatioLimited(); } double tr_sessionGetRatioLimit(tr_session const* session) @@ -1294,11 +1293,11 @@ void tr_sessionSetIdleLimited(tr_session* session, bool is_limited) session->is_idle_limited_ = is_limited; } -void tr_sessionSetIdleLimit(tr_session* session, uint16_t idleMinutes) +void tr_sessionSetIdleLimit(tr_session* session, uint16_t idle_minutes) { TR_ASSERT(session != nullptr); - session->idleLimitMinutes = idleMinutes; + session->idle_limit_minutes_ = idle_minutes; } bool tr_sessionIsIdleLimited(tr_session const* session) @@ -1312,7 +1311,7 @@ uint16_t tr_sessionGetIdleLimit(tr_session const* session) { TR_ASSERT(session != nullptr); - return session->idleLimitMinutes; + return session->idleLimitMinutes(); } /*** @@ -1330,7 +1329,7 @@ std::optional tr_session::activeSpeedLimitBps(tr_direction dir) co return tr_sessionGetAltSpeed_Bps(this, dir); } - if (tr_sessionIsSpeedLimited(this, dir)) + if (this->isSpeedLimited(dir)) { return speedLimitBps(dir); } @@ -1471,19 +1470,19 @@ static void turtleBootstrap(tr_session* session, struct tr_turtle_info* turtle) **** Primary session speed limits ***/ -static void tr_sessionSetSpeedLimit_Bps(tr_session* s, tr_direction d, unsigned int Bps) +void tr_sessionSetSpeedLimit_Bps(tr_session* session, tr_direction dir, unsigned int Bps) { - TR_ASSERT(s != nullptr); - TR_ASSERT(tr_isDirection(d)); + TR_ASSERT(session != nullptr); + TR_ASSERT(tr_isDirection(dir)); - s->speedLimit_Bps[d] = Bps; + session->speed_limit_Bps_[dir] = Bps; - updateBandwidth(s, d); + updateBandwidth(session, dir); } -void tr_sessionSetSpeedLimit_KBps(tr_session* s, tr_direction d, unsigned int KBps) +void tr_sessionSetSpeedLimit_KBps(tr_session* session, tr_direction dir, unsigned int KBps) { - tr_sessionSetSpeedLimit_Bps(s, d, tr_toSpeedBytes(KBps)); + tr_sessionSetSpeedLimit_Bps(session, dir, tr_toSpeedBytes(KBps)); } unsigned int tr_sessionGetSpeedLimit_KBps(tr_session const* s, tr_direction d) @@ -1491,22 +1490,22 @@ unsigned int tr_sessionGetSpeedLimit_KBps(tr_session const* s, tr_direction d) return tr_toSpeedKBps(s->speedLimitBps(d)); } -void tr_sessionLimitSpeed(tr_session* s, tr_direction d, bool b) +void tr_sessionLimitSpeed(tr_session* session, tr_direction dir, bool limited) { - TR_ASSERT(s != nullptr); - TR_ASSERT(tr_isDirection(d)); + TR_ASSERT(session != nullptr); + TR_ASSERT(tr_isDirection(dir)); - s->speedLimitEnabled[d] = b; + session->speed_limit_enabled_[dir] = limited; - updateBandwidth(s, d); + updateBandwidth(session, dir); } -bool tr_sessionIsSpeedLimited(tr_session const* s, tr_direction d) +bool tr_sessionIsSpeedLimited(tr_session const* session, tr_direction dir) { - TR_ASSERT(s != nullptr); - TR_ASSERT(tr_isDirection(d)); + TR_ASSERT(session != nullptr); + TR_ASSERT(tr_isDirection(dir)); - return s->speedLimitEnabled[d]; + return session->isSpeedLimited(dir); } /*** @@ -1733,8 +1732,6 @@ double tr_sessionGetRawSpeed_KBps(tr_session const* session, tr_direction dir) return tr_toSpeedKBps(tr_sessionGetRawSpeed_Bps(session, dir)); } -static void closeBlocklists(tr_session* /*session*/); - void tr_session::closeImplStart() { is_closing_ = true; @@ -1818,7 +1815,7 @@ void tr_session::closeImplFinish() stats().saveIfDirty(); tr_peerMgrFree(peerMgr); tr_utpClose(this); - closeBlocklists(this); + blocklists_.clear(); openFiles().closeAll(); is_closed_ = true; } @@ -2030,39 +2027,40 @@ void tr_sessionSetDHTEnabled(tr_session* session, bool enabled) **** ***/ -bool tr_sessionIsUTPEnabled(tr_session const* session) +bool tr_session::allowsUTP() const noexcept { - TR_ASSERT(session != nullptr); - #ifdef WITH_UTP - return session->isUTPEnabled; + return is_utp_enabled_; #else return false; #endif } -static void toggle_utp(tr_session* const session) +bool tr_sessionIsUTPEnabled(tr_session const* session) { TR_ASSERT(session != nullptr); - session->isUTPEnabled = !session->isUTPEnabled; - - tr_udpSetSocketBuffers(session); - - tr_udpSetSocketTOS(session); - - /* But don't call tr_utpClose -- see reset_timer in tr-utp.c for an - explanation. */ + return session->allowsUTP(); } void tr_sessionSetUTPEnabled(tr_session* session, bool enabled) { TR_ASSERT(session != nullptr); - if (enabled != session->isUTPEnabled) + if (enabled == session->allowsUTP()) { - tr_runInEventThread(session, toggle_utp, session); + return; } + tr_runInEventThread( + session, + [session, enabled]() + { + session->is_utp_enabled_ = enabled; + tr_udpSetSocketBuffers(session); + tr_udpSetSocketTOS(session); + // But don't call tr_utpClose -- + // see reset_timer in tr-utp.c for an explanation. + }); } /*** @@ -2192,13 +2190,13 @@ bool tr_sessionIsPortForwardingEnabled(tr_session const* session) **** ***/ -static void loadBlocklists(tr_session* session) +void tr_session::loadBlocklists() { auto loadme = std::unordered_set{}; - auto const is_enabled = session->useBlocklist(); + auto const is_enabled = useBlocklist(); /* walk the blocklist directory... */ - auto const dirname = tr_pathbuf{ session->configDir(), "/blocklists"sv }; + auto const dirname = tr_pathbuf{ configDir(), "/blocklists"sv }; auto const odir = tr_sys_dir_open(dirname); if (odir == TR_BAD_SYS_DIR) @@ -2261,26 +2259,39 @@ static void loadBlocklists(tr_session* session) } } - session->blocklists.clear(); + blocklists_.clear(); std::transform( std::begin(loadme), std::end(loadme), - std::back_inserter(session->blocklists), + std::back_inserter(blocklists_), [&is_enabled](auto const& path) { return std::make_unique(path.c_str(), is_enabled); }); /* cleanup */ tr_sys_dir_close(odir); } -static void closeBlocklists(tr_session* session) +void tr_session::useBlocklist(bool enabled) { - session->blocklists.clear(); + this->blocklist_enabled_ = enabled; + + std::for_each( + std::begin(blocklists_), + std::end(blocklists_), + [enabled](auto& blocklist) { blocklist->setEnabled(enabled); }); +} + +bool tr_session::addressIsBlocked(tr_address const& addr) const noexcept +{ + return std::any_of( + std::begin(blocklists_), + std::end(blocklists_), + [&addr](auto& blocklist) { return blocklist->hasAddress(addr); }); } void tr_sessionReloadBlocklists(tr_session* session) { - closeBlocklists(session); - loadBlocklists(session); + session->blocklists_.clear(); + session->loadBlocklists(); tr_peerMgrOnBlocklistChanged(session->peerMgr); } @@ -2289,7 +2300,7 @@ size_t tr_blocklistGetRuleCount(tr_session const* session) { TR_ASSERT(session != nullptr); - auto& src = session->blocklists; + auto& src = session->blocklists_; return std::accumulate(std::begin(src), std::end(src), 0, [](int sum, auto& cur) { return sum + cur->getRuleCount(); }); } @@ -2300,13 +2311,6 @@ bool tr_blocklistIsEnabled(tr_session const* session) return session->useBlocklist(); } -void tr_session::useBlocklist(bool enabled) -{ - this->blocklist_enabled_ = enabled; - - std::for_each(std::begin(blocklists), std::end(blocklists), [enabled](auto& blocklist) { blocklist->setEnabled(enabled); }); -} - void tr_blocklistSetEnabled(tr_session* session, bool enabled) { TR_ASSERT(session != nullptr); @@ -2318,15 +2322,15 @@ bool tr_blocklistExists(tr_session const* session) { TR_ASSERT(session != nullptr); - return !std::empty(session->blocklists); + return !std::empty(session->blocklists_); } -size_t tr_blocklistSetContent(tr_session* session, char const* contentFilename) +size_t tr_blocklistSetContent(tr_session* session, char const* content_filename) { auto const lock = session->unique_lock(); // find (or add) the default blocklist - auto& src = session->blocklists; + auto& src = session->blocklists_; char const* const name = DEFAULT_BLOCKLIST_FILENAME; auto const it = std::find_if( std::begin(src), @@ -2346,16 +2350,8 @@ size_t tr_blocklistSetContent(tr_session* session, char const* contentFilename) } // set the default blocklist's content - int const ruleCount = b->setContent(contentFilename); - return ruleCount; -} - -bool tr_session::addressIsBlocked(tr_address const& addr) const noexcept -{ - return std::any_of( - std::begin(blocklists), - std::end(blocklists), - [&addr](auto& blocklist) { return blocklist->hasAddress(addr); }); + auto const rule_count = b->setContent(content_filename); + return rule_count; } void tr_blocklistSetURL(tr_session* session, char const* url) @@ -2876,8 +2872,14 @@ auto makeEventBase() } // namespace tr_session::tr_session(std::string_view config_dir) - : session_id{ tr_time } + : session_id_{ tr_time } , event_base_{ makeEventBase() } + , evdns_base_{ evdns_base_new(eventBase(), EVDNS_BASE_INITIALIZE_NAMESERVERS), + [](evdns_base* dns) + { + // if zero, active requests will be aborted + evdns_base_free(dns, 0); + } } , timer_maker_{ std::make_unique(eventBase()) } , config_dir_{ config_dir } , resume_dir_{ makeResumeDir(config_dir) } diff --git a/libtransmission/session.h b/libtransmission/session.h index 86c448665..2bda4cf4a 100644 --- a/libtransmission/session.h +++ b/libtransmission/session.h @@ -130,11 +130,21 @@ struct tr_session public: explicit tr_session(std::string_view config_dir); + [[nodiscard]] std::string_view sessionId() const noexcept + { + return session_id_.sv(); + } + [[nodiscard]] event_base* eventBase() noexcept { return event_base_.get(); } + [[nodiscard]] evdns_base* evdnsBase() noexcept + { + return evdns_base_.get(); + } + [[nodiscard]] auto& timerMaker() noexcept { return *timer_maker_; @@ -460,24 +470,10 @@ public: TR_SCRIPT_ON_TORRENT_DONE_SEEDING } } }; - bool isUTPEnabled = false; - bool isPrefetchEnabled = false; - bool isRatioLimited = false; - - uint8_t peer_id_ttl_hours = 0; - - int umask = 0; - - unsigned int speedLimit_Bps[2] = { 0, 0 }; - bool speedLimitEnabled[2] = { false, false }; - struct tr_turtle_info turtle; - struct evdns_base* evdns_base = nullptr; struct tr_event_handle* events = nullptr; - uint16_t upload_slots_per_torrent = 0; - /* The UDP sockets used for the DHT and uTP. */ tr_port udp_port; tr_socket_t udp_socket = TR_BAD_SOCKET; @@ -510,37 +506,13 @@ public: public_peer_port = port; } - std::vector> blocklists; struct tr_peerMgr* peerMgr = nullptr; struct tr_shared* shared = nullptr; std::unique_ptr cache; - class WebMediator final : public tr_web::Mediator - { - public: - explicit WebMediator(tr_session* session) - : session_{ session } - { - } - ~WebMediator() override = default; - - [[nodiscard]] std::optional cookieFile() const override; - [[nodiscard]] std::optional publicAddress() const override; - [[nodiscard]] std::optional userAgent() const override; - [[nodiscard]] unsigned int clamp(int torrent_id, unsigned int byte_count) const override; - void notifyBandwidthConsumed(int torrent_id, size_t byte_count) override; - // runs the tr_web::fetch response callback in the libtransmission thread - void run(tr_web::FetchDoneFunc&& func, tr_web::FetchResponse&& response) const override; - - private: - tr_session* const session_; - }; - std::unique_ptr web; - tr_session_id session_id; - struct tr_announcer* announcer = nullptr; struct tr_announcer_udp* announcer_udp = nullptr; @@ -549,20 +521,11 @@ public: std::vector>> bandwidth_groups_; - uint16_t idleLimitMinutes; - tr_bindinfo bind_ipv4 = tr_bindinfo{ tr_inaddr_any }; tr_bindinfo bind_ipv6 = tr_bindinfo{ tr_in6addr_any }; std::unique_ptr rpc_server_; - tr_announce_list default_trackers_; - - // One of 's IPTOS_ values. - // See tr_netTos*() in libtransmission/net.h for more info - // Only session.cc should use this. - int peer_socket_tos_ = *tr_netTosFromName(TR_DEFAULT_PEER_SOCKET_TOS_STR); - [[nodiscard]] auto constexpr queueEnabled(tr_direction dir) const noexcept { return queue_enabled_[dir]; @@ -593,6 +556,11 @@ public: return peer_limit_per_torrent_; } + [[nodiscard]] auto constexpr uploadSlotsPerTorrent() const noexcept + { + return upload_slots_per_torrent_; + } + [[nodiscard]] auto constexpr isClosing() const noexcept { return is_closing_; @@ -643,11 +611,23 @@ public: return is_pex_enabled_; } + [[nodiscard]] bool allowsUTP() const noexcept; + + [[nodiscard]] auto constexpr allowsPrefetch() const noexcept + { + return is_prefetch_enabled_; + } + [[nodiscard]] auto constexpr isIdleLimited() const noexcept { return is_idle_limited_; } + [[nodiscard]] auto constexpr idleLimitMinutes() const noexcept + { + return idle_limit_minutes_; + } + [[nodiscard]] std::vector getAllTorrents() const { return std::vector{ std::begin(torrents()), std::end(torrents()) }; @@ -681,7 +661,12 @@ public: [[nodiscard]] constexpr auto speedLimitBps(tr_direction dir) const noexcept { - return speedLimit_Bps[dir]; + return speed_limit_Bps_[dir]; + } + + [[nodiscard]] constexpr auto isSpeedLimited(tr_direction dir) const noexcept + { + return speed_limit_enabled_[dir]; } [[nodiscard]] auto pieceSpeedBps(tr_direction dir) const noexcept @@ -701,22 +686,40 @@ public: return is_port_random_; } + [[nodiscard]] auto constexpr isRatioLimited() const noexcept + { + return is_ratio_limited_; + } + [[nodiscard]] constexpr auto desiredRatio() const noexcept { return desired_ratio_; } + [[nodiscard]] constexpr auto peerIdTTLHours() const noexcept + { + return peer_id_ttl_hours_; + } + private: [[nodiscard]] tr_port randomPort() const; + void loadBlocklists(); + + friend bool tr_blocklistExists(tr_session const* session); + friend size_t tr_blocklistGetRuleCount(tr_session const* session); + friend size_t tr_blocklistSetContent(tr_session* session, char const* content_filename); friend tr_session* tr_sessionInit(char const* config_dir, bool message_queueing_enabled, tr_variant* client_settings); friend uint16_t tr_sessionSetPeerPortRandom(tr_session* session); friend void tr_sessionClose(tr_session* session); friend void tr_sessionGetSettings(tr_session const* s, tr_variant* setme_dictionary); + friend void tr_sessionLimitSpeed(tr_session* session, tr_direction dir, bool limited); + friend void tr_sessionReloadBlocklists(tr_session* session); friend void tr_sessionSet(tr_session* session, tr_variant* settings); friend void tr_sessionSetDHTEnabled(tr_session* session, bool enabled); friend void tr_sessionSetDeleteSource(tr_session* session, bool delete_source); friend void tr_sessionSetEncryption(tr_session* session, tr_encryption_mode mode); + friend void tr_sessionSetIdleLimit(tr_session* session, uint16_t idle_minutes); friend void tr_sessionSetIdleLimited(tr_session* session, bool is_limited); friend void tr_sessionSetIncompleteFileNamingEnabled(tr_session* session, bool enabled); friend void tr_sessionSetLPDEnabled(tr_session* session, bool enabled); @@ -731,12 +734,35 @@ private: friend void tr_sessionSetQueueStalledMinutes(tr_session* session, int minutes); friend void tr_sessionSetRPCCallback(tr_session* session, tr_rpc_func func, void* user_data); friend void tr_sessionSetRatioLimit(tr_session* session, double desired_ratio); + friend void tr_sessionSetRatioLimited(tr_session* session, bool is_limited); + friend void tr_sessionSetSpeedLimit_Bps(tr_session* session, tr_direction dir, unsigned int Bps); + friend void tr_sessionSetUTPEnabled(tr_session* session, bool enabled); + std::vector> blocklists_; + + tr_announce_list default_trackers_; + + tr_session_id session_id_; + + std::array speed_limit_Bps_ = { 0U, 0U }; + std::array speed_limit_enabled_ = { false, false }; + + int umask_ = 022; + + // One of 's IPTOS_ values. + // See tr_netTos*() in libtransmission/net.h for more info + int peer_socket_tos_ = *tr_netTosFromName(TR_DEFAULT_PEER_SOCKET_TOS_STR); + + bool is_utp_enabled_ = false; bool is_pex_enabled_ = false; bool is_dht_enabled_ = false; bool is_lpd_enabled_ = false; bool is_idle_limited_ = false; + bool is_prefetch_enabled_ = false; + bool is_ratio_limited_ = false; + + uint8_t peer_id_ttl_hours_ = 6; struct init_data; void initImpl(init_data&); @@ -753,6 +779,8 @@ private: float desired_ratio_ = 2.0F; + uint16_t upload_slots_per_torrent_ = 8; + bool should_pause_added_torrents_ = false; bool should_delete_source_torrents_ = false; bool should_scrape_paused_torrents_ = false; @@ -770,6 +798,8 @@ private: uint16_t peer_limit_ = 200; uint16_t peer_limit_per_torrent_ = 50; + uint16_t idle_limit_minutes_; + std::array queue_enabled_ = { false, false }; std::array queue_size_ = { 0, 0 }; int queue_stalled_minutes_ = 0; @@ -777,9 +807,31 @@ private: static std::recursive_mutex session_mutex_; + class WebMediator final : public tr_web::Mediator + { + public: + explicit WebMediator(tr_session* session) + : session_{ session } + { + } + ~WebMediator() override = default; + + [[nodiscard]] std::optional cookieFile() const override; + [[nodiscard]] std::optional publicAddress() const override; + [[nodiscard]] std::optional userAgent() const override; + [[nodiscard]] unsigned int clamp(int torrent_id, unsigned int byte_count) const override; + void notifyBandwidthConsumed(int torrent_id, size_t byte_count) override; + // runs the tr_web::fetch response callback in the libtransmission thread + void run(tr_web::FetchDoneFunc&& func, tr_web::FetchResponse&& response) const override; + + private: + tr_session* const session_; + }; + WebMediator web_mediator_{ this }; std::shared_ptr const event_base_; + std::shared_ptr const evdns_base_; std::unique_ptr const timer_maker_; void onNowTimer(); diff --git a/libtransmission/torrent.cc b/libtransmission/torrent.cc index 791655c5a..f5dd7f602 100644 --- a/libtransmission/torrent.cc +++ b/libtransmission/torrent.cc @@ -167,7 +167,7 @@ static void tr_torrentUnsetPeerId(tr_torrent* tor) static int peerIdTTL(tr_torrent const* tor) { auto const ctime = tor->peer_id_creation_time_; - return ctime == 0 ? 0 : (int)difftime(ctime + tor->session->peer_id_ttl_hours * 3600, tr_time()); + return ctime == 0 ? 0 : (int)difftime(ctime + tor->session->peerIdTTLHours() * 3600, tr_time()); } tr_peer_id_t const& tr_torrentGetPeerId(tr_torrent* tor) @@ -298,14 +298,14 @@ double tr_torrentGetRatioLimit(tr_torrent const* tor) bool tr_torrentGetSeedRatio(tr_torrent const* tor, double* ratio) { - auto isLimited = bool{}; + auto is_limited = bool{}; TR_ASSERT(tr_isTorrent(tor)); switch (tr_torrentGetRatioMode(tor)) { case TR_RATIOLIMIT_SINGLE: - isLimited = true; + is_limited = true; if (ratio != nullptr) { @@ -315,9 +315,9 @@ bool tr_torrentGetSeedRatio(tr_torrent const* tor, double* ratio) break; case TR_RATIOLIMIT_GLOBAL: - isLimited = tr_sessionIsRatioLimited(tor->session); + is_limited = tor->session->isRatioLimited(); - if (isLimited && ratio != nullptr) + if (is_limited && ratio != nullptr) { *ratio = tor->session->desiredRatio(); } @@ -325,11 +325,11 @@ bool tr_torrentGetSeedRatio(tr_torrent const* tor, double* ratio) break; default: /* TR_RATIOLIMIT_UNLIMITED */ - isLimited = false; + is_limited = false; break; } - return isLimited; + return is_limited; } /* returns true if the seed ratio applies -- @@ -432,7 +432,7 @@ bool tr_torrentGetSeedIdle(tr_torrent const* tor, uint16_t* idleMinutes) if (isLimited && idleMinutes != nullptr) { - *idleMinutes = tr_sessionGetIdleLimit(tor->session); + *idleMinutes = tor->session->idleLimitMinutes(); } break; @@ -770,7 +770,7 @@ static void torrentInit(tr_torrent* tor, tr_ctor const* ctor) if ((loaded & tr_resume::Idlelimit) == 0) { tr_torrentSetIdleMode(tor, TR_IDLELIMIT_GLOBAL); - tr_torrentSetIdleLimit(tor, tr_sessionGetIdleLimit(tor->session)); + tr_torrentSetIdleLimit(tor, tor->session->idleLimitMinutes()); } auto has_local_data = std::optional{}; diff --git a/libtransmission/tr-udp.cc b/libtransmission/tr-udp.cc index 40fd75805..dc42c8ea7 100644 --- a/libtransmission/tr-udp.cc +++ b/libtransmission/tr-udp.cc @@ -92,7 +92,7 @@ static void set_socket_buffers(tr_socket_t fd, bool large) void tr_udpSetSocketBuffers(tr_session* session) { - bool const utp = tr_sessionIsUTPEnabled(session); + bool const utp = session->allowsUTP(); if (session->udp_socket != TR_BAD_SOCKET) { @@ -260,7 +260,7 @@ static void event_callback(evutil_socket_t s, [[maybe_unused]] short type, void* } else { - if (tr_sessionIsUTPEnabled(session)) + if (session->allowsUTP()) { if (!tr_utpPacket(buf, rc, (struct sockaddr*)&from, fromlen, session)) { diff --git a/libtransmission/tr-utp.cc b/libtransmission/tr-utp.cc index 812231ef9..9a5587a57 100644 --- a/libtransmission/tr-utp.cc +++ b/libtransmission/tr-utp.cc @@ -83,7 +83,7 @@ static void utp_on_accept(tr_session* const session, UTPSocket* const s) tr_address addr; tr_port port; - if (!tr_sessionIsUTPEnabled(session)) + if (!session->allowsUTP()) { utp_close(s); return; @@ -161,7 +161,7 @@ static void reset_timer(tr_session* session) auto interval = std::chrono::milliseconds{}; auto const random_percent = tr_rand_int_weak(1000) / 1000.0; - if (tr_sessionIsUTPEnabled(session)) + if (session->allowsUTP()) { static auto constexpr MinInterval = UtpInterval * 0.5; static auto constexpr MaxInterval = UtpInterval * 1.5; diff --git a/libtransmission/transmission.h b/libtransmission/transmission.h index 68060525f..e5663c7bc 100644 --- a/libtransmission/transmission.h +++ b/libtransmission/transmission.h @@ -530,6 +530,7 @@ enum tr_direction **** Primary session speed limits ***/ +void tr_sessionSetSpeedLimit_Bps(tr_session*, tr_direction, unsigned int Bps); void tr_sessionSetSpeedLimit_KBps(tr_session*, tr_direction, unsigned int KBps); unsigned int tr_sessionGetSpeedLimit_KBps(tr_session const*, tr_direction); @@ -582,7 +583,7 @@ void tr_sessionSetAltSpeedFunc(tr_session*, tr_altSpeedFunc, void*); double tr_sessionGetRawSpeed_KBps(tr_session const*, tr_direction); -void tr_sessionSetRatioLimited(tr_session*, bool isLimited); +void tr_sessionSetRatioLimited(tr_session*, bool is_limited); bool tr_sessionIsRatioLimited(tr_session const*); void tr_sessionSetRatioLimit(tr_session*, double desired_ratio); @@ -591,7 +592,7 @@ double tr_sessionGetRatioLimit(tr_session const*); void tr_sessionSetIdleLimited(tr_session*, bool is_limited); bool tr_sessionIsIdleLimited(tr_session const*); -void tr_sessionSetIdleLimit(tr_session*, uint16_t idleMinutes); +void tr_sessionSetIdleLimit(tr_session*, uint16_t idle_minutes); uint16_t tr_sessionGetIdleLimit(tr_session const*); void tr_sessionSetPeerLimit(tr_session*, uint16_t max_global_peers); @@ -754,7 +755,7 @@ bool tr_sessionIsScriptEnabled(tr_session const*, TrScript); * * Passing nullptr for a filename will clear the blocklist. */ -size_t tr_blocklistSetContent(tr_session* session, char const* filename); +size_t tr_blocklistSetContent(tr_session* session, char const* content_filename); size_t tr_blocklistGetRuleCount(tr_session const* session); diff --git a/libtransmission/trevent.cc b/libtransmission/trevent.cc index 3dc166bac..c4db11613 100644 --- a/libtransmission/trevent.cc +++ b/libtransmission/trevent.cc @@ -16,7 +16,6 @@ #include #endif -#include #include #include @@ -188,11 +187,9 @@ static void libeventThreadFunc(tr_event_handle* events) // create the libevent base auto* base = events->session->eventBase(); - auto* const dns_base = evdns_base_new(base, EVDNS_BASE_INITIALIZE_NAMESERVERS); // initialize the session struct's event fields events->work_queue_event = event_new(base, -1, 0, onWorkAvailable, events->session); - events->session->evdns_base = dns_base; events->session->events = events; // tell the thread that's waiting in tr_eventInit() @@ -203,12 +200,7 @@ static void libeventThreadFunc(tr_event_handle* events) event_base_loop(base, EVLOOP_NO_EXIT_ON_EMPTY); // shut down the thread - if (dns_base != nullptr) - { - evdns_base_free(dns_base, 0); - } event_free(events->work_queue_event); - events->session->evdns_base = nullptr; events->session->events = nullptr; delete events; tr_logAddTrace("Closing libevent thread");