Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package libtorrent for openSUSE:Factory checked in at 2026-05-04 12:53:46 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/libtorrent (Old) and /work/SRC/openSUSE:Factory/.libtorrent.new.30200 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "libtorrent" Mon May 4 12:53:46 2026 rev:32 rq:1350482 version:0.16.11 Changes: -------- --- /work/SRC/openSUSE:Factory/libtorrent/libtorrent.changes 2026-04-23 17:14:30.069093875 +0200 +++ /work/SRC/openSUSE:Factory/.libtorrent.new.30200/libtorrent.changes 2026-05-04 12:56:52.065753787 +0200 @@ -1,0 +2,8 @@ +Sat May 2 10:22:20 UTC 2026 - Jan Engelhardt <[email protected]> + +- Update to release 0.16.11 + * Stopped using std::scoped_lock in CurlStack as it does not + support unlocking just one mutex + * No longer throws when DhtSearch is not found in DhtServer + +------------------------------------------------------------------- Old: ---- libtorrent-0.16.10.tar.gz New: ---- libtorrent-0.16.11.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ libtorrent.spec ++++++ --- /var/tmp/diff_new_pack.cmCyoT/_old 2026-05-04 12:56:53.213801038 +0200 +++ /var/tmp/diff_new_pack.cmCyoT/_new 2026-05-04 12:56:53.213801038 +0200 @@ -16,9 +16,9 @@ # -%define lname libtorrent40 +%define lname libtorrent41 Name: libtorrent -Version: 0.16.10 +Version: 0.16.11 Release: 0 Summary: A BitTorrent library written in C++ License: SUSE-GPL-2.0+-with-openssl-exception ++++++ _scmsync.obsinfo ++++++ --- /var/tmp/diff_new_pack.cmCyoT/_old 2026-05-04 12:56:53.261803013 +0200 +++ /var/tmp/diff_new_pack.cmCyoT/_new 2026-05-04 12:56:53.265803178 +0200 @@ -1,5 +1,5 @@ -mtime: 1776947584 -commit: 8ee7b14eaf0b6b21add8373b5405e2505d613b9ce838c1cc7097cf8fa196774c +mtime: 1777717556 +commit: 46a6a8c9ca7e8b765842415fbe8c3b60b17f1f618f8e6990e5b348d7f8a2d53c url: https://src.opensuse.org/jengelh/libtorrent revision: master ++++++ build.specials.obscpio ++++++ ++++++ build.specials.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/.gitignore new/.gitignore --- old/.gitignore 1970-01-01 01:00:00.000000000 +0100 +++ new/.gitignore 2026-05-02 12:25:56.000000000 +0200 @@ -0,0 +1 @@ +.osc ++++++ libtorrent-0.16.10.tar.gz -> libtorrent-0.16.11.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtorrent-0.16.10/configure new/libtorrent-0.16.11/configure --- old/libtorrent-0.16.10/configure 2026-04-23 10:48:32.000000000 +0200 +++ new/libtorrent-0.16.11/configure 2026-05-01 11:49:09.000000000 +0200 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.72 for libtorrent 0.16.10. +# Generated by GNU Autoconf 2.72 for libtorrent 0.16.11. # # Report bugs to <[email protected]>. # @@ -614,8 +614,8 @@ # Identity of this package. PACKAGE_NAME='libtorrent' PACKAGE_TARNAME='libtorrent' -PACKAGE_VERSION='0.16.10' -PACKAGE_STRING='libtorrent 0.16.10' +PACKAGE_VERSION='0.16.11' +PACKAGE_STRING='libtorrent 0.16.11' PACKAGE_BUGREPORT='[email protected]' PACKAGE_URL='' @@ -1416,7 +1416,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -'configure' configures libtorrent 0.16.10 to adapt to many kinds of systems. +'configure' configures libtorrent 0.16.11 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1487,7 +1487,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of libtorrent 0.16.10:";; + short | recursive ) echo "Configuration of libtorrent 0.16.11:";; esac cat <<\_ACEOF @@ -1649,7 +1649,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -libtorrent configure 0.16.10 +libtorrent configure 0.16.11 generated by GNU Autoconf 2.72 Copyright (C) 2023 Free Software Foundation, Inc. @@ -2367,7 +2367,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by libtorrent $as_me 0.16.10, which was +It was created by libtorrent $as_me 0.16.11, which was generated by GNU Autoconf 2.72. Invocation command line was $ $0$ac_configure_args_raw @@ -4060,7 +4060,7 @@ # Define the identity of the package. PACKAGE='libtorrent' - VERSION='0.16.10' + VERSION='0.16.11' printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h @@ -13706,13 +13706,13 @@ # When releasing the first 1.x.y version, we need to start with 1.1.0 (or higher) as we've already # used 0.16.x. -printf "%s\n" "#define PEER_NAME \"-lt100A-\"" >>confdefs.h +printf "%s\n" "#define PEER_NAME \"-lt100B-\"" >>confdefs.h -printf "%s\n" "#define PEER_VERSION \"lt\\x10\\x0A\"" >>confdefs.h +printf "%s\n" "#define PEER_VERSION \"lt\\x10\\x0B\"" >>confdefs.h -LIBTORRENT_CURRENT=40 +LIBTORRENT_CURRENT=41 LIBTORRENT_REVISION=0 LIBTORRENT_AGE=0 @@ -23879,7 +23879,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by libtorrent $as_me 0.16.10, which was +This file was extended by libtorrent $as_me 0.16.11, which was generated by GNU Autoconf 2.72. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -23947,7 +23947,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -libtorrent config.status 0.16.10 +libtorrent config.status 0.16.11 configured by $0, generated by GNU Autoconf 2.72, with options \\"\$ac_cs_config\\" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtorrent-0.16.10/configure.ac new/libtorrent-0.16.11/configure.ac --- old/libtorrent-0.16.10/configure.ac 2026-04-23 10:48:18.000000000 +0200 +++ new/libtorrent-0.16.11/configure.ac 2026-05-01 11:48:57.000000000 +0200 @@ -1,4 +1,4 @@ -AC_INIT([[libtorrent]],[[0.16.10]],[[[email protected]]]) +AC_INIT([[libtorrent]],[[0.16.11]],[[[email protected]]]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_MACRO_DIRS([scripts]) @@ -8,10 +8,10 @@ # When releasing the first 1.x.y version, we need to start with 1.1.0 (or higher) as we've already # used 0.16.x. -AC_DEFINE([[PEER_NAME]], [["-lt100A-"]], [[Identifier that is part of the default peer id.]]) -AC_DEFINE([[PEER_VERSION]], [["lt\x10\x0A"]], [[4 byte client and version identifier for DHT.]]) +AC_DEFINE([[PEER_NAME]], [["-lt100B-"]], [[Identifier that is part of the default peer id.]]) +AC_DEFINE([[PEER_VERSION]], [["lt\x10\x0B"]], [[4 byte client and version identifier for DHT.]]) -LIBTORRENT_CURRENT=40 +LIBTORRENT_CURRENT=41 LIBTORRENT_REVISION=0 LIBTORRENT_AGE=0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtorrent-0.16.10/src/dht/dht_server.cc new/libtorrent-0.16.11/src/dht/dht_server.cc --- old/libtorrent-0.16.10/src/dht/dht_server.cc 2026-04-23 10:48:18.000000000 +0200 +++ new/libtorrent-0.16.11/src/dht/dht_server.cc 2026-05-01 11:48:57.000000000 +0200 @@ -274,9 +274,8 @@ auto itr = m_searches.find(search); - // TODO: Insert? if (itr == m_searches.end()) - throw internal_error("DhtServer::mark_search_completed search not found."); + return; // throw internal_error("DhtServer::mark_search_completed search not found."); // TODO: Verify we got ref_count == 2. @@ -721,14 +720,14 @@ } } - if (quick) { - return ++itr; // don't actually delete the transaction until the final timeout + // don't actually delete the transaction until the final timeout + if (quick) + return ++itr; - } else { - drop_packet(transaction->packet().get()); - m_transactions.erase(itr++); - return itr; - } + drop_packet(transaction->packet().get()); + + m_transactions.erase(itr++); + return itr; } void @@ -933,6 +932,7 @@ void DhtServer::receive_timeout() { auto itr = m_transactions.begin(); + while (itr != m_transactions.end()) { if (itr->second->has_quick_timeout() && itr->second->quick_timeout() < this_thread::cached_seconds().count()) { itr = failed_transaction(itr, true); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtorrent-0.16.10/src/net/curl_stack.cc new/libtorrent-0.16.11/src/net/curl_stack.cc --- old/libtorrent-0.16.10/src/net/curl_stack.cc 2026-04-23 10:48:18.000000000 +0200 +++ new/libtorrent-0.16.11/src/net/curl_stack.cc 2026-05-01 11:48:57.000000000 +0200 @@ -98,7 +98,10 @@ if (curl_get == nullptr) throw torrent::internal_error("CurlStack::start_get() called with a null curl_get."); - { auto guard = std::scoped_lock(m_mutex, curl_get->mutex()); + { auto lock_main = std::unique_lock(m_mutex, std::defer_lock); + auto lock_get = std::unique_lock(curl_get->mutex(), std::defer_lock); + + std::lock(lock_main, lock_get); // TODO: Check is_running, if not return error. Do not throw internal_error. if (!m_running) @@ -128,7 +131,7 @@ // Calling curl_multi_add_handle() can result in CurlSocket::receive_socket() being called, // which calls CurlStack::is_running(). - m_mutex.unlock(); + lock_main.unlock(); curl_get->activate_unsafe(); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtorrent-0.16.10/src/net/dns_buffer.cc new/libtorrent-0.16.11/src/net/dns_buffer.cc --- old/libtorrent-0.16.10/src/net/dns_buffer.cc 2026-04-23 10:48:18.000000000 +0200 +++ new/libtorrent-0.16.11/src/net/dns_buffer.cc 2026-05-01 11:48:57.000000000 +0200 @@ -37,7 +37,7 @@ } } -// We don't try to resolve numeric addresses here, as that should be done in DnsCache or UdnsResolver. +// Numeric addresses are resolved in torrent/net/resolver, with no use of ThreadNet. void DnsBuffer::resolve(void* requester, const std::string& hostname, int family, resolver_callback&& fn) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtorrent-0.16.10/src/torrent/net/http_stack.cc new/libtorrent-0.16.11/src/torrent/net/http_stack.cc --- old/libtorrent-0.16.10/src/torrent/net/http_stack.cc 2026-04-23 10:48:18.000000000 +0200 +++ new/libtorrent-0.16.11/src/torrent/net/http_stack.cc 2026-05-01 11:48:57.000000000 +0200 @@ -3,6 +3,8 @@ #include "torrent/net/http_stack.h" #include <cassert> +#include <charconv> +#include <curl/curl.h> #include "net/curl_get.h" #include "net/curl_stack.h" @@ -13,6 +15,46 @@ namespace torrent::net { +// TODO: This should be in a net/utils file. +// TODO: Require scheme to also be returned / checked? + +std::tuple<std::string, uint16_t> +parse_uri_host_port(const std::string& uri) { + char* host_ptr{}; + char* port_ptr{}; + CURLU* curlu = curl_url(); + + if (curl_url_set(curlu, CURLUPART_URL, uri.c_str(), CURLU_NON_SUPPORT_SCHEME) != CURLUE_OK) { + curl_url_cleanup(curlu); + return {"", 0}; + } + + if (curl_url_get(curlu, CURLUPART_HOST, &host_ptr, 0) != CURLUE_OK) { + curl_url_cleanup(curlu); + return {"", 0}; + } + + std::string host(host_ptr); + uint16_t port{}; + + curl_free(host_ptr); + + if (curl_url_get(curlu, CURLUPART_PORT, &port_ptr, 0) != CURLUE_OK) { + curl_url_cleanup(curlu); + return {host, 0}; + } + + auto result = std::from_chars(port_ptr, port_ptr + std::strlen(port_ptr), port); + + curl_free(port_ptr); + curl_url_cleanup(curlu); + + if (result.ec != std::errc()) + return {"", 0}; + + return {host, port}; +} + HttpStack::HttpStack(system::Thread* thread) : m_stack(new CurlStack(thread)) { } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtorrent-0.16.10/src/torrent/net/resolver.cc new/libtorrent-0.16.11/src/torrent/net/resolver.cc --- old/libtorrent-0.16.10/src/torrent/net/resolver.cc 2026-04-23 10:48:18.000000000 +0200 +++ new/libtorrent-0.16.11/src/torrent/net/resolver.cc 2026-05-01 11:48:57.000000000 +0200 @@ -14,45 +14,6 @@ namespace torrent::net { -namespace { - -std::pair<sin_shared_ptr, sin6_shared_ptr> -try_resolve_numeric(const std::string& hostname, int family) { - addrinfo hints{}; - addrinfo* result{}; - - hints.ai_family = family; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_NUMERICHOST; - - auto ret = ::getaddrinfo(hostname.c_str(), nullptr, &hints, &result); - - if (ret == EAI_NONAME || ret == EAI_ADDRFAMILY) - return {nullptr, nullptr}; - - if (ret != 0) - throw internal_error("getaddrinfo failed: " + std::string(gai_strerror(ret))); - - if (result->ai_family == AF_INET) { - sin_shared_ptr sin_addr = sin_copy(reinterpret_cast<sockaddr_in*>(result->ai_addr)); - ::freeaddrinfo(result); - - return {sin_addr, nullptr}; - } - - if (result->ai_family == AF_INET6) { - sin6_shared_ptr sin6_addr = sin6_copy(reinterpret_cast<sockaddr_in6*>(result->ai_addr)); - ::freeaddrinfo(result); - - return {nullptr, sin6_addr}; - } - - ::freeaddrinfo(result); - throw internal_error("getaddrinfo returned unsupported family"); -} - -} - const char* gai_enum_error(int status) { switch (status) { @@ -79,7 +40,7 @@ void Resolver::resolve_both(void* requester, const std::string& hostname, int family, both_callback&& callback) { - auto [sin, sin6] = try_resolve_numeric(hostname, family); + auto [sin, sin6] = try_lookup_numeric(hostname, family); if (sin || sin6) { m_thread->callback(requester, [family, callback = std::move(callback), sin = std::move(sin), sin6 = std::move(sin6)]() mutable { @@ -107,7 +68,7 @@ if (preferred != AF_INET && preferred != AF_INET6) throw internal_error("Resolver::resolve_preferred() invalid preferred family."); - auto [sin, sin6] = try_resolve_numeric(hostname, family); + auto [sin, sin6] = try_lookup_numeric(hostname, family); if (sin || sin6) { sa_shared_ptr sa = sin ? sa_copy_in(sin.get()) : sa_copy_in6(sin6.get()); @@ -157,7 +118,7 @@ if (family != AF_INET && family != AF_INET6) throw internal_error("Resolver::resolve_specific() invalid family."); - auto [sin, sin6] = try_resolve_numeric(hostname, family); + auto [sin, sin6] = try_lookup_numeric(hostname, family); if (sin || sin6) { sa_shared_ptr sa = sin ? sa_copy_in(sin.get()) : sa_copy_in6(sin6.get()); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtorrent-0.16.10/src/torrent/net/socket_address.cc new/libtorrent-0.16.11/src/torrent/net/socket_address.cc --- old/libtorrent-0.16.10/src/torrent/net/socket_address.cc 2026-04-23 10:48:18.000000000 +0200 +++ new/libtorrent-0.16.11/src/torrent/net/socket_address.cc 2026-05-01 11:48:57.000000000 +0200 @@ -746,6 +746,45 @@ } } +// +// Other types: +// + +sin46_shared_pair +try_lookup_numeric(const std::string& hostname, int family) { + addrinfo hints{}; + addrinfo* result{}; + + hints.ai_family = family; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_NUMERICHOST; + + auto ret = ::getaddrinfo(hostname.c_str(), nullptr, &hints, &result); + + if (ret == EAI_NONAME || ret == EAI_ADDRFAMILY) + return {nullptr, nullptr}; + + if (ret != 0) + throw internal_error("getaddrinfo failed: " + std::string(gai_strerror(ret))); + + if (result->ai_family == AF_INET) { + sin_shared_ptr sin_addr = sin_copy(reinterpret_cast<sockaddr_in*>(result->ai_addr)); + ::freeaddrinfo(result); + + return {sin_addr, nullptr}; + } + + if (result->ai_family == AF_INET6) { + sin6_shared_ptr sin6_addr = sin6_copy(reinterpret_cast<sockaddr_in6*>(result->ai_addr)); + ::freeaddrinfo(result); + + return {nullptr, sin6_addr}; + } + + ::freeaddrinfo(result); + throw internal_error("getaddrinfo returned unsupported family"); +} + sa_inet_union sa_inet_union_from_sa(const sockaddr* sa) { sa_inet_union su{}; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtorrent-0.16.10/src/torrent/net/socket_address.h new/libtorrent-0.16.11/src/torrent/net/socket_address.h --- old/libtorrent-0.16.10/src/torrent/net/socket_address.h 2026-04-23 10:48:18.000000000 +0200 +++ new/libtorrent-0.16.11/src/torrent/net/socket_address.h 2026-05-01 11:48:57.000000000 +0200 @@ -97,16 +97,12 @@ std::string sin6_pretty_str(const sockaddr_in6* sa) LIBTORRENT_EXPORT; std::string sin6_pretty_or_empty(const sockaddr_in6* sa) LIBTORRENT_EXPORT; -c_sa_shared_ptr sa_lookup_address(const std::string& address_str, int family) LIBTORRENT_EXPORT; - // // Other types: // sa_inet_union sa_inet_union_from_sa(const sockaddr* sa) LIBTORRENT_EXPORT; -const char* family_str(int family) LIBTORRENT_EXPORT; - bool fd_sap_equal(const fd_sap_tuple& lhs, const fd_sap_tuple& rhs) LIBTORRENT_EXPORT; // diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtorrent-0.16.10/src/torrent/net/types.h new/libtorrent-0.16.11/src/torrent/net/types.h --- old/libtorrent-0.16.10/src/torrent/net/types.h 2026-04-23 10:48:18.000000000 +0200 +++ new/libtorrent-0.16.11/src/torrent/net/types.h 2026-05-01 11:48:57.000000000 +0200 @@ -50,6 +50,7 @@ using c_sun_shared_ptr = std::shared_ptr<const sockaddr_un>; using fd_sap_tuple = std::tuple<int, sa_unique_ptr>; +using sin46_shared_pair = std::pair<sin_shared_ptr, sin6_shared_ptr>; using resolver_callback = std::function<void(sin_shared_ptr, int, sin6_shared_ptr, int)>; struct listen_result_type { @@ -64,6 +65,19 @@ sockaddr sa; }; +// TODO: Move to a separate header file. + +c_sa_shared_ptr sa_lookup_address(const std::string& address_str, int family) LIBTORRENT_EXPORT; +sin46_shared_pair try_lookup_numeric(const std::string& hostname, int family) LIBTORRENT_EXPORT; + +const char* family_str(int family) LIBTORRENT_EXPORT; + +namespace net { + +std::tuple<std::string, uint16_t> parse_uri_host_port(const std::string& uri) LIBTORRENT_EXPORT; + +} // namespace net + } // namespace torrent #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtorrent-0.16.10/src/tracker/tracker_http.h new/libtorrent-0.16.11/src/tracker/tracker_http.h --- old/libtorrent-0.16.10/src/tracker/tracker_http.h 2026-04-23 10:48:19.000000000 +0200 +++ new/libtorrent-0.16.11/src/tracker/tracker_http.h 2026-05-01 11:48:57.000000000 +0200 @@ -4,7 +4,6 @@ #include <iosfwd> #include <memory> -#include "torrent/object.h" #include "tracker/tracker_worker.h" #include "torrent/net/http_get.h" #include "torrent/tracker/tracker_state.h" @@ -27,6 +26,7 @@ void send_event(tracker::TrackerState::event_enum new_state) override; void send_scrape() override; + void close() override; private: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtorrent-0.16.10/src/tracker/tracker_udp.cc new/libtorrent-0.16.11/src/tracker/tracker_udp.cc --- old/libtorrent-0.16.10/src/tracker/tracker_udp.cc 2026-04-23 10:48:19.000000000 +0200 +++ new/libtorrent-0.16.11/src/tracker/tracker_udp.cc 2026-05-01 11:48:57.000000000 +0200 @@ -26,6 +26,7 @@ namespace torrent { // TODO: Rewrite this to do resolve every time, since we now have a cache? +// TODO: Add UDP listening socket used by all UDP trackers, make it handle retries and timeouts. It waits for reply. TrackerUdp::TrackerUdp(const TrackerInfo& info, int flags) : TrackerWorker(info, flags) { @@ -49,14 +50,18 @@ // TODO: Don't close fd for every new request. close_directly(); - hostname_type hostname; + auto [hostname, port] = net::parse_uri_host_port(info().url); - if (!parse_udp_url(info().url, hostname, m_port)) - return receive_failed("could not parse hostname or port"); + if (hostname.empty()) + return receive_failed("could not parse hostname from url"); + + if (port == 0) + return receive_failed("could not parse port from url"); lock_and_set_latest_event(new_state); - m_send_state = new_state; + m_port = port; + m_send_state = new_state; m_sending_announce = true; LT_LOG("resolving hostname : address:%s", hostname.data()); @@ -64,35 +69,25 @@ // TODO: Also check failed counter.... // TODO: Check for changes to block (NC should instead clear us on network changes) - // TODO: Change to always do resolve and rely on cache. - - if ((m_inet_address == nullptr && m_inet6_address == nullptr) || - (this_thread::cached_time() - m_time_last_resolved) > 24h || - m_failed_since_last_resolved > 3) { - - int family = AF_UNSPEC; - bool block_ipv4 = config::network_config()->is_block_ipv4(); - bool block_ipv6 = config::network_config()->is_block_ipv6(); - - if (block_ipv4 && block_ipv6) - return receive_failed("cannot send tracker event, both IPv4 and IPv6 are blocked"); - else if (block_ipv4) - family = AF_INET6; - else if (block_ipv6) - family = AF_INET; - - m_resolver_requesting = true; - - auto fn = [this](c_sin_shared_ptr sin, int err, c_sin6_shared_ptr sin6, int err6) { - receive_resolved(sin, err, sin6, err6); - }; - - // Currently discarding SOCK_DGRAM filter. - this_thread::resolver()->resolve_both(static_cast<TrackerWorker*>(this), hostname.data(), family, std::move(fn)); - return; - } + int family = AF_UNSPEC; + bool block_ipv4 = config::network_config()->is_block_ipv4(); + bool block_ipv6 = config::network_config()->is_block_ipv6(); + + if (block_ipv4 && block_ipv6) + return receive_failed("cannot send tracker event, both IPv4 and IPv6 are blocked"); + else if (block_ipv4) + family = AF_INET6; + else if (block_ipv6) + family = AF_INET; + + m_resolver_requesting = true; + + auto fn = [this](c_sin_shared_ptr sin, int err, c_sin6_shared_ptr sin6, int err6) { + receive_resolved(sin, err, sin6, err6); + }; - start_announce(); + // Currently discarding SOCK_DGRAM filter. + this_thread::resolver()->resolve_both(static_cast<TrackerWorker*>(this), hostname.data(), family, std::move(fn)); } void @@ -100,19 +95,6 @@ throw internal_error("Tracker type UDP does not support scrape."); } -bool -TrackerUdp::parse_udp_url(const std::string& url, hostname_type& hostname, int& port) { - if (std::sscanf(url.c_str(), "udp://%1023[^:]:%i", hostname.data(), &port) == 2 && hostname[0] != '\0' && - port > 0 && port < (1 << 16)) - return true; - - if (std::sscanf(url.c_str(), "udp://[%1023[^]]]:%i", hostname.data(), &port) == 2 && hostname[0] != '\0' && - port > 0 && port < (1 << 16)) - return true; - - return false; -} - // TODO: Controller should not need to close the tracker when starting a new request. void @@ -157,14 +139,13 @@ void TrackerUdp::receive_failed(const std::string& msg) { - m_failed_since_last_resolved++; + LT_LOG("received failure : hostname:%s port:%u msg:'%s'", sa_pretty_str(m_current_address).c_str(), m_port, msg.c_str()); close_directly(); + m_slot_failure(msg); } -// TODO: Only resolve when we don't have a valid address, failed too many times or network change -// events. void TrackerUdp::receive_resolved(c_sin_shared_ptr& sin, int err, c_sin6_shared_ptr& sin6, int err6) { if (std::this_thread::get_id() != torrent::main_thread::thread_id()) @@ -184,23 +165,19 @@ "' sin6_error:'" + std::string(gai_strerror(err6)) + "'"); } + m_inet_address = nullptr; + m_inet6_address = nullptr; + if (sin != nullptr) { m_inet_address = sin_copy(sin.get()); sa_set_port(reinterpret_cast<sockaddr*>(m_inet_address.get()), m_port); - } else { - m_inet_address = nullptr; } if (sin6 != nullptr) { m_inet6_address = sin6_copy(sin6.get()); sa_set_port(reinterpret_cast<sockaddr*>(m_inet6_address.get()), m_port); - } else { - m_inet6_address = nullptr; } - m_time_last_resolved = this_thread::cached_time(); - m_failed_since_last_resolved = 0; - start_announce(); } @@ -243,11 +220,11 @@ } } else if (m_inet_address != nullptr) { - bind_address = config::network_config()->bind_address_for_connect(AF_INET); + bind_address = config::network_config()->bind_address_for_connect(AF_INET); m_current_address = reinterpret_cast<sockaddr*>(m_inet_address.get()); } else if (m_inet6_address != nullptr) { - bind_address = config::network_config()->bind_address_for_connect(AF_INET6); + bind_address = config::network_config()->bind_address_for_connect(AF_INET6); m_current_address = reinterpret_cast<sockaddr*>(m_inet6_address.get()); } else { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtorrent-0.16.10/src/tracker/tracker_udp.h new/libtorrent-0.16.11/src/tracker/tracker_udp.h --- old/libtorrent-0.16.10/src/tracker/tracker_udp.h 2026-04-23 10:48:19.000000000 +0200 +++ new/libtorrent-0.16.11/src/tracker/tracker_udp.h 2026-05-01 11:48:57.000000000 +0200 @@ -14,8 +14,6 @@ class TrackerUdp : public SocketDatagram, public TrackerWorker { public: - using hostname_type = std::array<char, 1024>; - using ReadBuffer = ProtocolBuffer<512>; using WriteBuffer = ProtocolBuffer<512>; @@ -58,8 +56,6 @@ bool process_announce_output(); bool process_error_output(); - static bool parse_udp_url(const std::string& url, hostname_type& hostname, int& port); - bool m_resolver_requesting{}; bool m_sending_announce{}; @@ -78,10 +74,8 @@ std::unique_ptr<WriteBuffer> m_write_buffer; uint32_t m_tries{}; - uint32_t m_failed_since_last_resolved{}; - utils::SchedulerEntry m_task_timeout; - std::chrono::microseconds m_time_last_resolved{}; + utils::SchedulerEntry m_task_timeout; }; } // namespace torrent diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtorrent-0.16.10/src/tracker/tracker_worker.cc new/libtorrent-0.16.11/src/tracker/tracker_worker.cc --- old/libtorrent-0.16.10/src/tracker/tracker_worker.cc 2026-04-23 10:48:19.000000000 +0200 +++ new/libtorrent-0.16.11/src/tracker/tracker_worker.cc 2026-05-01 11:48:57.000000000 +0200 @@ -4,6 +4,12 @@ namespace torrent { +TrackerWorker::TrackerWorker(TrackerInfo info, int flags) + : m_info(info) { + + m_state.m_flags = flags; +} + TrackerWorker::~TrackerWorker() = default; } // namespace torrent diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libtorrent-0.16.10/src/tracker/tracker_worker.h new/libtorrent-0.16.11/src/tracker/tracker_worker.h --- old/libtorrent-0.16.10/src/tracker/tracker_worker.h 2026-04-23 10:48:19.000000000 +0200 +++ new/libtorrent-0.16.11/src/tracker/tracker_worker.h 2026-05-01 11:48:57.000000000 +0200 @@ -108,11 +108,6 @@ uint32_t m_group{0}; }; -inline TrackerWorker::TrackerWorker(TrackerInfo info, int flags) - : m_info(std::move(info)) { - m_state.m_flags = flags; -} - inline void TrackerWorker::lock_and_clear_intervals() { auto guard = lock_guard();
