From 453836f3242046ee1a318563edaec597ebfa16e0 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sun, 1 Jan 2023 13:22:50 -0600 Subject: [PATCH] refactor: make announce key param unique per-torrent (#4508) --- libtransmission/announcer-common.h | 8 ++------ libtransmission/announcer-udp.cc | 4 ++++ libtransmission/announcer.cc | 4 +--- libtransmission/torrent.h | 10 ++++++++++ libtransmission/tr-macros.h | 15 +++++++++++++++ 5 files changed, 32 insertions(+), 9 deletions(-) diff --git a/libtransmission/announcer-common.h b/libtransmission/announcer-common.h index 477db6658..f35f8817b 100644 --- a/libtransmission/announcer-common.h +++ b/libtransmission/announcer-common.h @@ -63,12 +63,8 @@ struct tr_announce_request /* the port we listen for incoming peers on */ tr_port port; - /* Per-session key. BEP 0015 defines this key as a 32-bit number and - * explains its purpose: "Clients that resolve hostnames to v4 and v6 - * and then announce to both should use the same key for both so that - * trackers that care about accurate statistics-keeping can match the - * two announces." */ - uint32_t key; + // see discussion of tr_announce_key_t that type's declaration + tr_announce_key_t key; /* the number of peers we'd like to get back in the response */ int numwant = 0; diff --git a/libtransmission/announcer-udp.cc b/libtransmission/announcer-udp.cc index b43a6cef7..46e052e36 100644 --- a/libtransmission/announcer-udp.cc +++ b/libtransmission/announcer-udp.cc @@ -5,6 +5,7 @@ #include // for std::find_if() #include // for errno, EAFNOSUPPORT +#include // for CHAR_BIT #include // for memset() #include #include @@ -170,6 +171,9 @@ struct tau_announce_request tau_announce_request(uint32_t announce_ip, tr_announce_request const& in, tr_announce_response_func on_response) : on_response_{ std::move(on_response) } { + // https://www.bittorrent.org/beps/bep_0015.html sets key size at 32 bits + static_assert(sizeof(tr_announce_request::key) * CHAR_BIT == 32); + response.seeders = -1; response.leechers = -1; response.downloads = -1; diff --git a/libtransmission/announcer.cc b/libtransmission/announcer.cc index 67860c41a..5dd2a509e 100644 --- a/libtransmission/announcer.cc +++ b/libtransmission/announcer.cc @@ -235,8 +235,6 @@ public: tr_session* const session; - uint32_t const key = tr_rand_obj(); - private: void flushCloseMessages() { @@ -946,7 +944,7 @@ void tr_announcerAddBytes(tr_torrent* tor, int type, uint32_t n_bytes) req.leftUntilComplete = tor->hasMetainfo() ? tor->totalSize() - tor->hasTotal() : INT64_MAX; req.event = event; req.numwant = event == TR_ANNOUNCE_EVENT_STOPPED ? 0 : Numwant; - req.key = announcer->key; + req.key = tor->announce_key(); req.partial_seed = tor->isPartialSeed(); tier->buildLogName(req.log_name, sizeof(req.log_name)); return req; diff --git a/libtransmission/torrent.h b/libtransmission/torrent.h index 35efe10ff..91e977434 100644 --- a/libtransmission/torrent.h +++ b/libtransmission/torrent.h @@ -24,6 +24,7 @@ #include "bitfield.h" #include "block-info.h" #include "completion.h" +#include "crypto-utils.h" #include "file-piece-map.h" #include "interned-string.h" #include "log.h" @@ -788,6 +789,11 @@ public: } } + [[nodiscard]] constexpr auto announce_key() const noexcept + { + return announce_key_; + } + tr_torrent_metainfo metainfo_; tr_bandwidth bandwidth_; @@ -920,7 +926,11 @@ private: } tr_verify_state verify_state_ = TR_VERIFY_NONE; + float verify_progress_ = -1; + + tr_announce_key_t announce_key_ = tr_rand_obj(); + tr_interned_string bandwidth_group_; bool needs_completeness_check_ = true; diff --git a/libtransmission/tr-macros.h b/libtransmission/tr-macros.h index 8fd305783..4be543674 100644 --- a/libtransmission/tr-macros.h +++ b/libtransmission/tr-macros.h @@ -7,6 +7,7 @@ #include #include // size_t +#include // uint32_t /// @@ -88,6 +89,20 @@ // Mostly to enforce better formatting #define TR_ARG_TUPLE(...) __VA_ARGS__ +// https://www.bittorrent.org/beps/bep_0007.html +// "The client SHOULD include a key parameter in its announces. The key +// should remain the same for a particular infohash during a torrent +// session. Together with the peer_id this allows trackers to uniquely +// identify clients for the purpose of statistics-keeping when they +// announce from multiple IP. +// The key should be generated so it has at least 32bits worth of entropy." +// +// https://www.bittorrent.org/beps/bep_0015.html +// "Clients that resolve hostnames to v4 and v6 and then announce to both +// should use the same [32-bit integer] key for both so that trackers that +// care about accurate statistics-keeping can match the two announces." +using tr_announce_key_t = uint32_t; + // https://www.bittorrent.org/beps/bep_0003.html // A string of length 20 which this downloader uses as its id. Each // downloader generates its own id at random at the start of a new