// This file Copyright © 2010-2022 Mnemosyne LLC. // It may be used under GPLv2 (SPDX: GPL-2.0), GPLv3 (SPDX: GPL-3.0), // or any future license endorsed by Mnemosyne LLC. // License text can be found in the licenses/ folder. #pragma once #ifndef LIBTRANSMISSION_ANNOUNCER_MODULE #error only the libtransmission announcer module should #include this header. #endif #include #include // size_t #include #include #include #include "transmission.h" #include "interned-string.h" #include "peer-mgr.h" // tr_pex #include "web-utils.h" /*** **** SCRAPE ***/ /* pick a number small enough for common tracker software: * - ocelot has no upper bound * - opentracker has an upper bound of 64 * - udp protocol has an upper bound of 74 * - xbtt has no upper bound * * This is only an upper bound: if the tracker complains about * length, announcer will incrementally lower the batch size. */ auto inline constexpr TR_MULTISCRAPE_MAX = 60; struct tr_scrape_request { /* the scrape URL */ tr_interned_string scrape_url; /* the name to use when deep logging is enabled */ char log_name[128]; /* info hashes of the torrents to scrape */ std::array info_hash; /* how many hashes to use in the info_hash field */ int info_hash_count = 0; }; struct tr_scrape_response_row { /* the torrent's info_hash */ tr_sha1_digest_t info_hash; /* how many peers are seeding this torrent */ int seeders = 0; /* how many peers are downloading this torrent */ int leechers = 0; /* how many times this torrent has been downloaded */ int downloads = 0; /* the number of active downloaders in the swarm. * this is a BEP 21 extension that some trackers won't support. * http://www.bittorrent.org/beps/bep_0021.html#tracker-scrapes */ int downloaders = 0; }; struct tr_scrape_response { /* whether or not we managed to connect to the tracker */ bool did_connect = false; /* whether or not the scrape timed out */ bool did_timeout = false; /* how many info hashes are in the 'rows' field */ int row_count; /* the individual torrents' scrape results */ std::array rows; /* the raw scrape url */ tr_interned_string scrape_url; /* human-readable error string on failure, or nullptr */ std::string errmsg; /* minimum interval (in seconds) allowed between scrapes. * this is an unofficial extension that some trackers won't support. */ int min_request_interval; }; using tr_scrape_response_func = void (*)(tr_scrape_response const* response, void* user_data); void tr_tracker_http_scrape( tr_session* session, tr_scrape_request const* req, tr_scrape_response_func response_func, void* user_data); void tr_tracker_udp_scrape( tr_session* session, tr_scrape_request const* req, tr_scrape_response_func response_func, void* user_data); /*** **** ANNOUNCE ***/ enum tr_announce_event { /* Note: the ordering of this enum's values is important to * announcer.c's tr_tier.announce_event_priority. If changing * the enum, ensure announcer.c is compatible with the change. */ TR_ANNOUNCE_EVENT_NONE, TR_ANNOUNCE_EVENT_STARTED, TR_ANNOUNCE_EVENT_COMPLETED, TR_ANNOUNCE_EVENT_STOPPED, }; char const* tr_announce_event_get_string(tr_announce_event); struct tr_announce_request { tr_announce_event event = {}; bool partial_seed = false; /* the port we listen for incoming peers on */ int port = 0; /* per-session key */ int key = 0; /* the number of peers we'd like to get back in the response */ int numwant = 0; /* the number of bytes we uploaded since the last 'started' event */ uint64_t up = 0; /* the number of good bytes we downloaded since the last 'started' event */ uint64_t down = 0; /* the number of bad bytes we downloaded since the last 'started' event */ uint64_t corrupt = 0; /* the total size of the torrent minus the number of bytes completed */ uint64_t leftUntilComplete = 0; /* the tracker's announce URL */ tr_interned_string announce_url; /* key generated by and returned from an http tracker. * see tr_announce_response.tracker_id_str */ std::string tracker_id; /* the torrent's peer id. * this changes when a torrent is stopped -> restarted. */ tr_peer_id_t peer_id; /* the torrent's info_hash */ tr_sha1_digest_t info_hash; /* the name to use when deep logging is enabled */ char log_name[128]; }; struct tr_announce_response { /* the torrent's info hash */ tr_sha1_digest_t info_hash = {}; /* whether or not we managed to connect to the tracker */ bool did_connect = false; /* whether or not the scrape timed out */ bool did_timeout = false; /* preferred interval between announces. * transmission treats this as the interval for periodic announces */ int interval = 0; /* minimum interval between announces. (optional) * transmission treats this as the min interval for manual announces */ int min_interval = 0; /* how many peers are seeding this torrent */ int seeders = -1; /* how many peers are downloading this torrent */ int leechers = -1; /* how many times this torrent has been downloaded */ int downloads = -1; /* IPv4 peers that we acquired from the tracker */ std::vector pex; /* IPv6 peers that we acquired from the tracker */ std::vector pex6; /* human-readable error string on failure, or nullptr */ std::string errmsg; /* human-readable warning string or nullptr */ std::string warning; /* key generated by and returned from an http tracker. * if this is provided, subsequent http announces must include this. */ std::string tracker_id; /* tracker extension that returns the client's public IP address. * https://www.bittorrent.org/beps/bep_0024.html */ std::optional external_ip; }; using tr_announce_response_func = void (*)(tr_announce_response const* response, void* userdata); void tr_tracker_http_announce( tr_session* session, tr_announce_request const* req, tr_announce_response_func response_func, void* user_data); void tr_tracker_udp_announce( tr_session* session, tr_announce_request const* req, tr_announce_response_func response_func, void* user_data); void tr_tracker_udp_start_shutdown(tr_session* session); void tr_announcerParseHttpAnnounceResponse(tr_announce_response& response, std::string_view msg, char const* log_name); void tr_announcerParseHttpScrapeResponse(tr_scrape_response& response, std::string_view msg, char const* log_name); tr_interned_string tr_announcerGetKey(tr_url_parsed_t const& parsed);