refactor: use C++ objects in announcer (#2474)
This commit is contained in:
parent
e0c3a7f3e6
commit
b45c831bcb
|
@ -12,6 +12,7 @@
|
|||
#include <array>
|
||||
#include <cstddef> // size_t
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "transmission.h"
|
||||
|
||||
|
@ -45,7 +46,7 @@ struct tr_scrape_request
|
|||
std::array<tr_sha1_digest_t, TR_MULTISCRAPE_MAX> info_hash;
|
||||
|
||||
/* how many hashes to use in the info_hash field */
|
||||
int info_hash_count;
|
||||
int info_hash_count = 0;
|
||||
};
|
||||
|
||||
struct tr_scrape_response_row
|
||||
|
@ -54,33 +55,33 @@ struct tr_scrape_response_row
|
|||
tr_sha1_digest_t info_hash;
|
||||
|
||||
/* how many peers are seeding this torrent */
|
||||
int seeders;
|
||||
int seeders = 0;
|
||||
|
||||
/* how many peers are downloading this torrent */
|
||||
int leechers;
|
||||
int leechers = 0;
|
||||
|
||||
/* how many times this torrent has been downloaded */
|
||||
int downloads;
|
||||
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;
|
||||
int downloaders = 0;
|
||||
};
|
||||
|
||||
struct tr_scrape_response
|
||||
{
|
||||
/* whether or not we managed to connect to the tracker */
|
||||
bool did_connect;
|
||||
bool did_connect = false;
|
||||
|
||||
/* whether or not the scrape timed out */
|
||||
bool did_timeout;
|
||||
bool did_timeout = false;
|
||||
|
||||
/* how many info hashes are in the 'rows' field */
|
||||
int row_count;
|
||||
|
||||
/* the individual torrents' scrape results */
|
||||
struct tr_scrape_response_row rows[TR_MULTISCRAPE_MAX];
|
||||
std::array<tr_scrape_response_row, TR_MULTISCRAPE_MAX> rows;
|
||||
|
||||
/* the raw scrape url */
|
||||
tr_interned_string scrape_url;
|
||||
|
@ -126,36 +127,36 @@ char const* tr_announce_event_get_string(tr_announce_event);
|
|||
|
||||
struct tr_announce_request
|
||||
{
|
||||
tr_announce_event event;
|
||||
bool partial_seed;
|
||||
tr_announce_event event = {};
|
||||
bool partial_seed = false;
|
||||
|
||||
/* the port we listen for incoming peers on */
|
||||
int port;
|
||||
int port = 0;
|
||||
|
||||
/* per-session key */
|
||||
int key;
|
||||
int key = 0;
|
||||
|
||||
/* the number of peers we'd like to get back in the response */
|
||||
int numwant;
|
||||
int numwant = 0;
|
||||
|
||||
/* the number of bytes we uploaded since the last 'started' event */
|
||||
uint64_t up;
|
||||
uint64_t up = 0;
|
||||
|
||||
/* the number of good bytes we downloaded since the last 'started' event */
|
||||
uint64_t down;
|
||||
uint64_t down = 0;
|
||||
|
||||
/* the number of bad bytes we downloaded since the last 'started' event */
|
||||
uint64_t corrupt;
|
||||
uint64_t corrupt = 0;
|
||||
|
||||
/* the total size of the torrent minus the number of bytes completed */
|
||||
uint64_t leftUntilComplete;
|
||||
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 */
|
||||
char* tracker_id_str;
|
||||
std::string tracker_id;
|
||||
|
||||
/* the torrent's peer id.
|
||||
* this changes when a torrent is stopped -> restarted. */
|
||||
|
@ -173,42 +174,36 @@ struct tr_pex;
|
|||
struct tr_announce_response
|
||||
{
|
||||
/* the torrent's info hash */
|
||||
tr_sha1_digest_t info_hash;
|
||||
tr_sha1_digest_t info_hash = {};
|
||||
|
||||
/* whether or not we managed to connect to the tracker */
|
||||
bool did_connect;
|
||||
bool did_connect = false;
|
||||
|
||||
/* whether or not the scrape timed out */
|
||||
bool did_timeout;
|
||||
bool did_timeout = false;
|
||||
|
||||
/* preferred interval between announces.
|
||||
* transmission treats this as the interval for periodic announces */
|
||||
int interval;
|
||||
int interval = 0;
|
||||
|
||||
/* minimum interval between announces. (optional)
|
||||
* transmission treats this as the min interval for manual announces */
|
||||
int min_interval;
|
||||
int min_interval = 0;
|
||||
|
||||
/* how many peers are seeding this torrent */
|
||||
int seeders;
|
||||
int seeders = -1;
|
||||
|
||||
/* how many peers are downloading this torrent */
|
||||
int leechers;
|
||||
int leechers = -1;
|
||||
|
||||
/* how many times this torrent has been downloaded */
|
||||
int downloads;
|
||||
|
||||
/* number of items in the 'pex' field */
|
||||
size_t pex_count;
|
||||
int downloads = -1;
|
||||
|
||||
/* IPv4 peers that we acquired from the tracker */
|
||||
struct tr_pex* pex;
|
||||
|
||||
/* number of items in the 'pex6' field */
|
||||
size_t pex6_count;
|
||||
std::vector<tr_pex> pex;
|
||||
|
||||
/* IPv6 peers that we acquired from the tracker */
|
||||
struct tr_pex* pex6;
|
||||
std::vector<tr_pex> pex6;
|
||||
|
||||
/* human-readable error string on failure, or nullptr */
|
||||
std::string errmsg;
|
||||
|
@ -218,7 +213,7 @@ struct tr_announce_response
|
|||
|
||||
/* key generated by and returned from an http tracker.
|
||||
* if this is provided, subsequent http announces must include this. */
|
||||
char* tracker_id_str;
|
||||
std::string tracker_id;
|
||||
};
|
||||
|
||||
using tr_announce_response_func = void (*)(tr_announce_response const* response, void* userdata);
|
||||
|
|
|
@ -46,8 +46,8 @@ static std::string announce_url_new(tr_session const* session, tr_announce_reque
|
|||
{
|
||||
auto const announce_sv = req->announce_url.sv();
|
||||
|
||||
char escaped_info_hash[SHA_DIGEST_LENGTH * 3 + 1];
|
||||
tr_http_escape_sha1(escaped_info_hash, req->info_hash);
|
||||
auto escaped_info_hash = std::array<char, SHA_DIGEST_LENGTH * 3 + 1>{};
|
||||
tr_http_escape_sha1(std::data(escaped_info_hash), req->info_hash);
|
||||
|
||||
auto* const buf = evbuffer_new();
|
||||
evbuffer_expand(buf, 1024);
|
||||
|
@ -67,7 +67,7 @@ static std::string announce_url_new(tr_session const* session, tr_announce_reque
|
|||
"&supportcrypto=1",
|
||||
TR_PRIsv_ARG(announce_sv),
|
||||
announce_sv.find('?') == announce_sv.npos ? '?' : '&',
|
||||
escaped_info_hash,
|
||||
std::data(escaped_info_hash),
|
||||
TR_PRIsv_ARG(req->peer_id),
|
||||
req->port,
|
||||
req->up,
|
||||
|
@ -92,10 +92,9 @@ static std::string announce_url_new(tr_session const* session, tr_announce_reque
|
|||
evbuffer_add_printf(buf, "&event=%s", str);
|
||||
}
|
||||
|
||||
str = req->tracker_id_str;
|
||||
if (!tr_str_is_empty(str))
|
||||
if (!std::empty(req->tracker_id))
|
||||
{
|
||||
evbuffer_add_printf(buf, "&trackerid=%s", str);
|
||||
evbuffer_add_printf(buf, "&trackerid=%" TR_PRIsv, TR_PRIsv_ARG(req->tracker_id));
|
||||
}
|
||||
|
||||
/* There are two incompatible techniques for announcing an IPv6 address.
|
||||
|
@ -119,11 +118,11 @@ static std::string announce_url_new(tr_session const* session, tr_announce_reque
|
|||
return evbuffer_free_to_str(buf);
|
||||
}
|
||||
|
||||
static tr_pex* listToPex(tr_variant* peerList, size_t* setme_len)
|
||||
static auto listToPex(tr_variant* peerList)
|
||||
{
|
||||
size_t n = 0;
|
||||
size_t const len = tr_variantListSize(peerList);
|
||||
auto* const pex = tr_new0(tr_pex, len);
|
||||
auto pex = std::vector<tr_pex>(len);
|
||||
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
{
|
||||
|
@ -167,7 +166,7 @@ static tr_pex* listToPex(tr_variant* peerList, size_t* setme_len)
|
|||
++n;
|
||||
}
|
||||
|
||||
*setme_len = n;
|
||||
pex.resize(n);
|
||||
return pex;
|
||||
}
|
||||
|
||||
|
@ -188,10 +187,7 @@ static void on_announce_done_eventthread(void* vdata)
|
|||
data->response_func(&data->response, data->response_func_user_data);
|
||||
}
|
||||
|
||||
tr_free(data->response.pex6);
|
||||
tr_free(data->response.pex);
|
||||
tr_free(data->response.tracker_id_str);
|
||||
tr_free(data);
|
||||
delete data;
|
||||
}
|
||||
|
||||
static void on_announce_done(
|
||||
|
@ -264,7 +260,7 @@ static void on_announce_done(
|
|||
|
||||
if (tr_variantDictFindStrView(&benc, TR_KEY_tracker_id, &sv))
|
||||
{
|
||||
response->tracker_id_str = tr_strvDup(sv);
|
||||
response->tracker_id = sv;
|
||||
}
|
||||
|
||||
if (tr_variantDictFindInt(&benc, TR_KEY_complete, &i))
|
||||
|
@ -285,18 +281,18 @@ static void on_announce_done(
|
|||
if (tr_variantDictFindStrView(&benc, TR_KEY_peers6, &sv))
|
||||
{
|
||||
dbgmsg(data->log_name, "got a peers6 length of %zu", std::size(sv));
|
||||
response->pex6 = tr_peerMgrCompact6ToPex(std::data(sv), std::size(sv), nullptr, 0, &response->pex6_count);
|
||||
response->pex6 = tr_peerMgrCompact6ToPex(std::data(sv), std::size(sv), nullptr, 0);
|
||||
}
|
||||
|
||||
if (tr_variantDictFindStrView(&benc, TR_KEY_peers, &sv))
|
||||
{
|
||||
dbgmsg(data->log_name, "got a compact peers length of %zu", std::size(sv));
|
||||
response->pex = tr_peerMgrCompactToPex(std::data(sv), std::size(sv), nullptr, 0, &response->pex_count);
|
||||
response->pex = tr_peerMgrCompactToPex(std::data(sv), std::size(sv), nullptr, 0);
|
||||
}
|
||||
else if (tr_variantDictFindList(&benc, TR_KEY_peers, &tmp))
|
||||
{
|
||||
response->pex = listToPex(tmp, &response->pex_count);
|
||||
dbgmsg(data->log_name, "got a peers list with %zu entries", response->pex_count);
|
||||
response->pex = listToPex(tmp);
|
||||
dbgmsg(data->log_name, "got a peers list with %zu entries", std::size(response->pex));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -315,7 +311,7 @@ void tr_tracker_http_announce(
|
|||
tr_announce_response_func response_func,
|
||||
void* response_func_user_data)
|
||||
{
|
||||
auto* const d = tr_new0(announce_data, 1);
|
||||
auto* const d = new announce_data{};
|
||||
d->response.seeders = -1;
|
||||
d->response.leechers = -1;
|
||||
d->response.downloads = -1;
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#include <cerrno> /* errno, EAFNOSUPPORT */
|
||||
#include <cstring> /* memset() */
|
||||
#include <ctime>
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
|
@ -22,7 +24,6 @@
|
|||
#include "log.h"
|
||||
#include "peer-io.h"
|
||||
#include "peer-mgr.h" /* tr_peerMgrCompactToPex() */
|
||||
#include "ptrarray.h"
|
||||
#include "session.h"
|
||||
#include "tr-assert.h"
|
||||
#include "tr-udp.h"
|
||||
|
@ -154,6 +155,54 @@ static auto constexpr TauRequestTtl = int{ 60 };
|
|||
|
||||
struct tau_scrape_request
|
||||
{
|
||||
void requestFinished()
|
||||
{
|
||||
if (callback != nullptr)
|
||||
{
|
||||
callback(&response, user_data);
|
||||
}
|
||||
}
|
||||
|
||||
void fail(bool did_connect, bool did_timeout, std::string_view errmsg)
|
||||
{
|
||||
response.did_connect = did_connect;
|
||||
response.did_timeout = did_timeout;
|
||||
response.errmsg = errmsg;
|
||||
requestFinished();
|
||||
}
|
||||
|
||||
void onResponse(tau_action_t action, evbuffer* buf)
|
||||
{
|
||||
response.did_connect = true;
|
||||
response.did_timeout = false;
|
||||
|
||||
if (action == TAU_ACTION_SCRAPE)
|
||||
{
|
||||
for (int i = 0; i < response.row_count; ++i)
|
||||
{
|
||||
if (evbuffer_get_length(buf) < sizeof(uint32_t) * 3)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
auto& row = response.rows[i];
|
||||
row.seeders = evbuffer_read_ntoh_32(buf);
|
||||
row.downloads = evbuffer_read_ntoh_32(buf);
|
||||
row.leechers = evbuffer_read_ntoh_32(buf);
|
||||
}
|
||||
|
||||
requestFinished();
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t const buflen = evbuffer_get_length(buf);
|
||||
auto const errmsg = action == TAU_ACTION_ERROR && buflen > 0 ?
|
||||
std::string_view{ reinterpret_cast<char const*>(evbuffer_pullup(buf, -1)), buflen } :
|
||||
_("Unknown error");
|
||||
fail(true, false, errmsg);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<uint8_t> payload;
|
||||
|
||||
time_t sent_at;
|
||||
|
@ -165,7 +214,7 @@ struct tau_scrape_request
|
|||
void* user_data;
|
||||
};
|
||||
|
||||
static struct tau_scrape_request* tau_scrape_request_new(
|
||||
static tau_scrape_request make_tau_scrape_request(
|
||||
tr_scrape_request const* in,
|
||||
tr_scrape_response_func callback,
|
||||
void* user_data)
|
||||
|
@ -185,22 +234,22 @@ static struct tau_scrape_request* tau_scrape_request_new(
|
|||
|
||||
/* build the tau_scrape_request */
|
||||
|
||||
auto* req = new tau_scrape_request{};
|
||||
req->callback = callback;
|
||||
req->created_at = tr_time();
|
||||
req->transaction_id = transaction_id;
|
||||
req->callback = callback;
|
||||
req->user_data = user_data;
|
||||
req->response.scrape_url = in->scrape_url;
|
||||
req->response.row_count = in->info_hash_count;
|
||||
req->payload.assign(payload_begin, payload_end);
|
||||
auto req = tau_scrape_request{};
|
||||
req.callback = callback;
|
||||
req.created_at = tr_time();
|
||||
req.transaction_id = transaction_id;
|
||||
req.callback = callback;
|
||||
req.user_data = user_data;
|
||||
req.response.scrape_url = in->scrape_url;
|
||||
req.response.row_count = in->info_hash_count;
|
||||
req.payload.assign(payload_begin, payload_end);
|
||||
|
||||
for (int i = 0; i < req->response.row_count; ++i)
|
||||
for (int i = 0; i < req.response.row_count; ++i)
|
||||
{
|
||||
req->response.rows[i].seeders = -1;
|
||||
req->response.rows[i].leechers = -1;
|
||||
req->response.rows[i].downloads = -1;
|
||||
req->response.rows[i].info_hash = in->info_hash[i];
|
||||
req.response.rows[i].seeders = -1;
|
||||
req.response.rows[i].leechers = -1;
|
||||
req.response.rows[i].downloads = -1;
|
||||
req.response.rows[i].info_hash = in->info_hash[i];
|
||||
}
|
||||
|
||||
/* cleanup */
|
||||
|
@ -208,63 +257,6 @@ static struct tau_scrape_request* tau_scrape_request_new(
|
|||
return req;
|
||||
}
|
||||
|
||||
static void tau_scrape_request_free(struct tau_scrape_request* req)
|
||||
{
|
||||
delete req;
|
||||
}
|
||||
|
||||
static void tau_scrape_request_finished(struct tau_scrape_request const* request)
|
||||
{
|
||||
if (request->callback != nullptr)
|
||||
{
|
||||
request->callback(&request->response, request->user_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void tau_scrape_request_fail(
|
||||
struct tau_scrape_request* request,
|
||||
bool did_connect,
|
||||
bool did_timeout,
|
||||
std::string_view errmsg)
|
||||
{
|
||||
request->response.did_connect = did_connect;
|
||||
request->response.did_timeout = did_timeout;
|
||||
request->response.errmsg = errmsg;
|
||||
tau_scrape_request_finished(request);
|
||||
}
|
||||
|
||||
static void on_scrape_response(struct tau_scrape_request* request, tau_action_t action, struct evbuffer* buf)
|
||||
{
|
||||
request->response.did_connect = true;
|
||||
request->response.did_timeout = false;
|
||||
|
||||
if (action == TAU_ACTION_SCRAPE)
|
||||
{
|
||||
for (int i = 0; i < request->response.row_count; ++i)
|
||||
{
|
||||
if (evbuffer_get_length(buf) < sizeof(uint32_t) * 3)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
struct tr_scrape_response_row& row = request->response.rows[i];
|
||||
row.seeders = evbuffer_read_ntoh_32(buf);
|
||||
row.downloads = evbuffer_read_ntoh_32(buf);
|
||||
row.leechers = evbuffer_read_ntoh_32(buf);
|
||||
}
|
||||
|
||||
tau_scrape_request_finished(request);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t const buflen = evbuffer_get_length(buf);
|
||||
auto const errmsg = action == TAU_ACTION_ERROR && buflen > 0 ?
|
||||
std::string_view{ reinterpret_cast<char const*>(evbuffer_pullup(buf, -1)), buflen } :
|
||||
_("Unknown error");
|
||||
tau_scrape_request_fail(request, true, false, errmsg);
|
||||
}
|
||||
}
|
||||
|
||||
/****
|
||||
*****
|
||||
***** ANNOUNCE
|
||||
|
@ -273,15 +265,56 @@ static void on_scrape_response(struct tau_scrape_request* request, tau_action_t
|
|||
|
||||
struct tau_announce_request
|
||||
{
|
||||
void requestFinished()
|
||||
{
|
||||
if (this->callback != nullptr)
|
||||
{
|
||||
this->callback(&this->response, this->user_data);
|
||||
}
|
||||
}
|
||||
|
||||
void fail(bool did_connect, bool did_timeout, std::string_view errmsg)
|
||||
{
|
||||
this->response.did_connect = did_connect;
|
||||
this->response.did_timeout = did_timeout;
|
||||
this->response.errmsg = errmsg;
|
||||
this->requestFinished();
|
||||
}
|
||||
|
||||
void onResponse(tau_action_t action, struct evbuffer* buf)
|
||||
{
|
||||
size_t const buflen = evbuffer_get_length(buf);
|
||||
|
||||
this->response.did_connect = true;
|
||||
this->response.did_timeout = false;
|
||||
|
||||
if (action == TAU_ACTION_ANNOUNCE && buflen >= 3 * sizeof(uint32_t))
|
||||
{
|
||||
response.interval = evbuffer_read_ntoh_32(buf);
|
||||
response.leechers = evbuffer_read_ntoh_32(buf);
|
||||
response.seeders = evbuffer_read_ntoh_32(buf);
|
||||
response.pex = tr_peerMgrCompactToPex(evbuffer_pullup(buf, -1), evbuffer_get_length(buf), nullptr, 0);
|
||||
requestFinished();
|
||||
}
|
||||
else
|
||||
{
|
||||
auto const errmsg = action == TAU_ACTION_ERROR && buflen > 0 ?
|
||||
std::string_view{ reinterpret_cast<char const*>(evbuffer_pullup(buf, -1)), buflen } :
|
||||
_("Unknown error");
|
||||
fail(true, false, errmsg);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<uint8_t> payload;
|
||||
|
||||
time_t created_at;
|
||||
time_t sent_at;
|
||||
tau_transaction_t transaction_id;
|
||||
time_t created_at = 0;
|
||||
time_t sent_at = 0;
|
||||
tau_transaction_t transaction_id = 0;
|
||||
|
||||
tr_announce_response response;
|
||||
tr_announce_response_func callback;
|
||||
void* user_data;
|
||||
tr_announce_response response = {};
|
||||
|
||||
tr_announce_response_func callback = nullptr;
|
||||
void* user_data = nullptr;
|
||||
};
|
||||
|
||||
enum tau_announce_event
|
||||
|
@ -311,7 +344,7 @@ static tau_announce_event get_tau_announce_event(tr_announce_event e)
|
|||
}
|
||||
}
|
||||
|
||||
static struct tau_announce_request* tau_announce_request_new(
|
||||
static tau_announce_request make_tau_announce_request(
|
||||
tr_announce_request const* in,
|
||||
tr_announce_response_func callback,
|
||||
void* user_data)
|
||||
|
@ -336,79 +369,21 @@ static struct tau_announce_request* tau_announce_request_new(
|
|||
auto const* const payload_end = payload_begin + evbuffer_get_length(buf);
|
||||
|
||||
/* build the tau_announce_request */
|
||||
auto* req = new tau_announce_request{};
|
||||
req->created_at = tr_time();
|
||||
req->transaction_id = transaction_id;
|
||||
req->callback = callback;
|
||||
req->user_data = user_data;
|
||||
req->payload.assign(payload_begin, payload_end);
|
||||
req->response.seeders = -1;
|
||||
req->response.leechers = -1;
|
||||
req->response.downloads = -1;
|
||||
req->response.info_hash = in->info_hash;
|
||||
auto req = tau_announce_request();
|
||||
req.created_at = tr_time();
|
||||
req.transaction_id = transaction_id;
|
||||
req.callback = callback;
|
||||
req.user_data = user_data;
|
||||
req.payload.assign(payload_begin, payload_end);
|
||||
req.response.seeders = -1;
|
||||
req.response.leechers = -1;
|
||||
req.response.downloads = -1;
|
||||
req.response.info_hash = in->info_hash;
|
||||
|
||||
evbuffer_free(buf);
|
||||
return req;
|
||||
}
|
||||
|
||||
static void tau_announce_request_free(struct tau_announce_request* req)
|
||||
{
|
||||
tr_free(req->response.tracker_id_str);
|
||||
tr_free(req->response.pex6);
|
||||
tr_free(req->response.pex);
|
||||
delete req;
|
||||
}
|
||||
|
||||
static void tau_announce_request_finished(struct tau_announce_request const* request)
|
||||
{
|
||||
if (request->callback != nullptr)
|
||||
{
|
||||
request->callback(&request->response, request->user_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void tau_announce_request_fail(
|
||||
struct tau_announce_request* request,
|
||||
bool did_connect,
|
||||
bool did_timeout,
|
||||
std::string_view errmsg)
|
||||
{
|
||||
request->response.did_connect = did_connect;
|
||||
request->response.did_timeout = did_timeout;
|
||||
request->response.errmsg = errmsg;
|
||||
tau_announce_request_finished(request);
|
||||
}
|
||||
|
||||
static void on_announce_response(struct tau_announce_request* request, tau_action_t action, struct evbuffer* buf)
|
||||
{
|
||||
size_t const buflen = evbuffer_get_length(buf);
|
||||
|
||||
request->response.did_connect = true;
|
||||
request->response.did_timeout = false;
|
||||
|
||||
if (action == TAU_ACTION_ANNOUNCE && buflen >= 3 * sizeof(uint32_t))
|
||||
{
|
||||
tr_announce_response* resp = &request->response;
|
||||
resp->interval = evbuffer_read_ntoh_32(buf);
|
||||
resp->leechers = evbuffer_read_ntoh_32(buf);
|
||||
resp->seeders = evbuffer_read_ntoh_32(buf);
|
||||
resp->pex = tr_peerMgrCompactToPex(
|
||||
evbuffer_pullup(buf, -1),
|
||||
evbuffer_get_length(buf),
|
||||
nullptr,
|
||||
0,
|
||||
&request->response.pex_count);
|
||||
tau_announce_request_finished(request);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto const errmsg = action == TAU_ACTION_ERROR && buflen > 0 ?
|
||||
std::string_view{ reinterpret_cast<char const*>(evbuffer_pullup(buf, -1)), buflen } :
|
||||
_("Unknown error");
|
||||
tau_announce_request_fail(request, true, false, errmsg);
|
||||
}
|
||||
}
|
||||
|
||||
/****
|
||||
*****
|
||||
***** TRACKERS
|
||||
|
@ -417,14 +392,43 @@ static void on_announce_response(struct tau_announce_request* request, tau_actio
|
|||
|
||||
struct tau_tracker
|
||||
{
|
||||
[[nodiscard]] auto isIdle() const
|
||||
{
|
||||
return std::empty(announces) && std::empty(scrapes) && dns_request == nullptr;
|
||||
}
|
||||
|
||||
~tau_tracker()
|
||||
{
|
||||
if (this->addr != nullptr)
|
||||
{
|
||||
evutil_freeaddrinfo(this->addr);
|
||||
}
|
||||
}
|
||||
|
||||
void failAll(bool did_connect, bool did_timeout, std::string_view errmsg)
|
||||
{
|
||||
for (auto& req : this->scrapes)
|
||||
{
|
||||
req.fail(did_connect, did_timeout, errmsg);
|
||||
}
|
||||
|
||||
for (auto& req : this->announces)
|
||||
{
|
||||
req.fail(did_connect, did_timeout, errmsg);
|
||||
}
|
||||
|
||||
this->scrapes.clear();
|
||||
this->announces.clear();
|
||||
}
|
||||
|
||||
tr_session* const session;
|
||||
|
||||
tr_interned_string const key;
|
||||
tr_interned_string const host;
|
||||
int const port;
|
||||
|
||||
struct evdns_getaddrinfo_request* dns_request = nullptr;
|
||||
struct evutil_addrinfo* addr = nullptr;
|
||||
evdns_getaddrinfo_request* dns_request = nullptr;
|
||||
evutil_addrinfo* addr = nullptr;
|
||||
time_t addr_expiration_time = 0;
|
||||
|
||||
time_t connecting_at = 0;
|
||||
|
@ -434,8 +438,8 @@ struct tau_tracker
|
|||
|
||||
time_t close_at = 0;
|
||||
|
||||
tr_ptrArray announces = {};
|
||||
tr_ptrArray scrapes = {};
|
||||
std::list<tau_announce_request> announces;
|
||||
std::list<tau_scrape_request> scrapes;
|
||||
|
||||
tau_tracker(tr_session* session_in, tr_interned_string key_in, tr_interned_string host_in, int port_in)
|
||||
: session{ session_in }
|
||||
|
@ -448,47 +452,6 @@ struct tau_tracker
|
|||
|
||||
static void tau_tracker_upkeep(struct tau_tracker*);
|
||||
|
||||
static void tau_tracker_free(struct tau_tracker* t)
|
||||
{
|
||||
TR_ASSERT(t->dns_request == nullptr);
|
||||
|
||||
if (t->addr != nullptr)
|
||||
{
|
||||
evutil_freeaddrinfo(t->addr);
|
||||
}
|
||||
|
||||
tr_ptrArrayDestruct(&t->announces, (PtrArrayForeachFunc)tau_announce_request_free);
|
||||
tr_ptrArrayDestruct(&t->scrapes, (PtrArrayForeachFunc)tau_scrape_request_free);
|
||||
delete t;
|
||||
}
|
||||
|
||||
static void tau_tracker_fail_all(struct tau_tracker* tracker, bool did_connect, bool did_timeout, std::string_view errmsg)
|
||||
{
|
||||
/* fail all the scrapes */
|
||||
tr_ptrArray* reqs = &tracker->scrapes;
|
||||
|
||||
for (int i = 0, n = tr_ptrArraySize(reqs); i < n; ++i)
|
||||
{
|
||||
auto* req = static_cast<struct tau_scrape_request*>(tr_ptrArrayNth(reqs, i));
|
||||
tau_scrape_request_fail(req, did_connect, did_timeout, errmsg);
|
||||
}
|
||||
|
||||
tr_ptrArrayDestruct(reqs, (PtrArrayForeachFunc)tau_scrape_request_free);
|
||||
*reqs = {};
|
||||
|
||||
/* fail all the announces */
|
||||
reqs = &tracker->announces;
|
||||
|
||||
for (int i = 0, n = tr_ptrArraySize(reqs); i < n; ++i)
|
||||
{
|
||||
auto* req = static_cast<struct tau_announce_request*>(tr_ptrArrayNth(reqs, i));
|
||||
tau_announce_request_fail(req, did_connect, did_timeout, errmsg);
|
||||
}
|
||||
|
||||
tr_ptrArrayDestruct(reqs, (PtrArrayForeachFunc)tau_announce_request_free);
|
||||
*reqs = {};
|
||||
}
|
||||
|
||||
static void tau_tracker_on_dns(int errcode, struct evutil_addrinfo* addr, void* vtracker)
|
||||
{
|
||||
auto* tracker = static_cast<struct tau_tracker*>(vtracker);
|
||||
|
@ -499,7 +462,7 @@ static void tau_tracker_on_dns(int errcode, struct evutil_addrinfo* addr, void*
|
|||
{
|
||||
auto const errmsg = tr_strvJoin("DNS Lookup failed: "sv, evutil_gai_strerror(errcode));
|
||||
dbgmsg(tracker->key, "%s", errmsg.c_str());
|
||||
tau_tracker_fail_all(tracker, false, false, errmsg.c_str());
|
||||
tracker->failAll(false, false, errmsg.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -520,59 +483,45 @@ static void tau_tracker_send_request(struct tau_tracker* tracker, void const* pa
|
|||
evbuffer_free(buf);
|
||||
}
|
||||
|
||||
static void tau_tracker_send_reqs(struct tau_tracker* tracker)
|
||||
template<typename T>
|
||||
static void tau_tracker_send_requests(tau_tracker* tracker, std::list<T>& reqs)
|
||||
{
|
||||
auto const now = tr_time();
|
||||
|
||||
for (auto it = std::begin(reqs); it != std::end(reqs);)
|
||||
{
|
||||
auto& req = *it;
|
||||
|
||||
if (req.sent_at != 0) // it's already been sent; we're awaiting a response
|
||||
{
|
||||
++it;
|
||||
continue;
|
||||
}
|
||||
|
||||
dbgmsg(tracker->key, "sending req %p", (void*)&req);
|
||||
req.sent_at = now;
|
||||
tau_tracker_send_request(tracker, std::data(req.payload), std::size(req.payload));
|
||||
|
||||
if (req.callback != nullptr)
|
||||
{
|
||||
++it;
|
||||
continue;
|
||||
}
|
||||
|
||||
// no response needed, so we can remove it now
|
||||
it = reqs.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
static void tau_tracker_send_reqs(tau_tracker* tracker)
|
||||
{
|
||||
TR_ASSERT(tracker->dns_request == nullptr);
|
||||
TR_ASSERT(tracker->connecting_at == 0);
|
||||
TR_ASSERT(tracker->addr != nullptr);
|
||||
TR_ASSERT(tracker->connection_expiration_time > tr_time());
|
||||
|
||||
time_t const now = tr_time();
|
||||
|
||||
TR_ASSERT(tracker->connection_expiration_time > now);
|
||||
|
||||
tr_ptrArray* reqs = &tracker->announces;
|
||||
|
||||
for (int i = 0, n = tr_ptrArraySize(reqs); i < n; ++i)
|
||||
{
|
||||
auto* req = static_cast<struct tau_announce_request*>(tr_ptrArrayNth(reqs, i));
|
||||
|
||||
if (req->sent_at == 0)
|
||||
{
|
||||
dbgmsg(tracker->key, "sending announce req %p", (void*)req);
|
||||
req->sent_at = now;
|
||||
tau_tracker_send_request(tracker, std::data(req->payload), std::size(req->payload));
|
||||
|
||||
if (req->callback == nullptr)
|
||||
{
|
||||
tau_announce_request_free(req);
|
||||
tr_ptrArrayRemove(reqs, i);
|
||||
--i;
|
||||
--n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reqs = &tracker->scrapes;
|
||||
|
||||
for (int i = 0, n = tr_ptrArraySize(reqs); i < n; ++i)
|
||||
{
|
||||
auto* req = static_cast<struct tau_scrape_request*>(tr_ptrArrayNth(reqs, i));
|
||||
|
||||
if (req->sent_at == 0)
|
||||
{
|
||||
dbgmsg(tracker->key, "sending scrape req %p", (void*)req);
|
||||
req->sent_at = now;
|
||||
tau_tracker_send_request(tracker, std::data(req->payload), std::size(req->payload));
|
||||
|
||||
if (req->callback == nullptr)
|
||||
{
|
||||
tau_scrape_request_free(req);
|
||||
tr_ptrArrayRemove(reqs, i);
|
||||
--i;
|
||||
--n;
|
||||
}
|
||||
}
|
||||
}
|
||||
tau_tracker_send_requests(tracker, tracker->announces);
|
||||
tau_tracker_send_requests(tracker, tracker->scrapes);
|
||||
}
|
||||
|
||||
static void on_tracker_connection_response(struct tau_tracker* tracker, tau_action_t action, struct evbuffer* buf)
|
||||
|
@ -597,7 +546,7 @@ static void on_tracker_connection_response(struct tau_tracker* tracker, tau_acti
|
|||
std::string_view{ _("Connection failed") };
|
||||
|
||||
dbgmsg(tracker->key, "%" TR_PRIsv, TR_PRIsv_ARG(errmsg));
|
||||
tau_tracker_fail_all(tracker, true, false, errmsg);
|
||||
tracker->failAll(true, false, errmsg);
|
||||
}
|
||||
|
||||
tau_tracker_upkeep(tracker);
|
||||
|
@ -613,46 +562,43 @@ static void tau_tracker_timeout_reqs(struct tau_tracker* tracker)
|
|||
on_tracker_connection_response(tracker, TAU_ACTION_ERROR, nullptr);
|
||||
}
|
||||
|
||||
tr_ptrArray* reqs = &tracker->announces;
|
||||
|
||||
for (int i = 0, n = tr_ptrArraySize(reqs); i < n; ++i)
|
||||
if (auto& reqs = tracker->announces; !std::empty(reqs))
|
||||
{
|
||||
auto* req = static_cast<struct tau_announce_request*>(tr_ptrArrayNth(reqs, i));
|
||||
|
||||
if (cancel_all || req->created_at + TauRequestTtl < now)
|
||||
for (auto it = std::begin(reqs); it != std::end(reqs);)
|
||||
{
|
||||
dbgmsg(tracker->key, "timeout announce req %p", (void*)req);
|
||||
tau_announce_request_fail(req, false, true, "");
|
||||
tau_announce_request_free(req);
|
||||
tr_ptrArrayRemove(reqs, i);
|
||||
--i;
|
||||
--n;
|
||||
auto& req = *it;
|
||||
if (cancel_all || req.created_at + TauRequestTtl < now)
|
||||
{
|
||||
dbgmsg(tracker->key, "timeout announce req %p", (void*)&req);
|
||||
req.fail(false, true, "");
|
||||
it = reqs.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reqs = &tracker->scrapes;
|
||||
|
||||
for (int i = 0, n = tr_ptrArraySize(reqs); i < n; ++i)
|
||||
if (auto& reqs = tracker->scrapes; !std::empty(reqs))
|
||||
{
|
||||
auto* const req = static_cast<struct tau_scrape_request*>(tr_ptrArrayNth(reqs, i));
|
||||
|
||||
if (cancel_all || req->created_at + TauRequestTtl < now)
|
||||
for (auto it = std::begin(reqs); it != std::end(reqs);)
|
||||
{
|
||||
dbgmsg(tracker->key, "timeout scrape req %p", (void*)req);
|
||||
tau_scrape_request_fail(req, false, true, "");
|
||||
tau_scrape_request_free(req);
|
||||
tr_ptrArrayRemove(reqs, i);
|
||||
--i;
|
||||
--n;
|
||||
auto& req = *it;
|
||||
if (cancel_all || req.created_at + TauRequestTtl < now)
|
||||
{
|
||||
dbgmsg(tracker->key, "timeout scrape req %p", &req);
|
||||
req.fail(false, true, "");
|
||||
it = reqs.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool tau_tracker_is_idle(struct tau_tracker const* tracker)
|
||||
{
|
||||
return tr_ptrArrayEmpty(&tracker->announces) && tr_ptrArrayEmpty(&tracker->scrapes) && tracker->dns_request == nullptr;
|
||||
}
|
||||
|
||||
static void tau_tracker_upkeep_ex(struct tau_tracker* tracker, bool timeout_reqs)
|
||||
{
|
||||
time_t const now = tr_time();
|
||||
|
@ -667,7 +613,7 @@ static void tau_tracker_upkeep_ex(struct tau_tracker* tracker, bool timeout_reqs
|
|||
}
|
||||
|
||||
/* are there any requests pending? */
|
||||
if (tau_tracker_is_idle(tracker))
|
||||
if (tracker->isIdle())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -739,10 +685,14 @@ static void tau_tracker_upkeep(struct tau_tracker* tracker)
|
|||
|
||||
struct tr_announcer_udp
|
||||
{
|
||||
/* tau_tracker */
|
||||
tr_ptrArray trackers;
|
||||
explicit tr_announcer_udp(tr_session* session_in)
|
||||
: session{ session_in }
|
||||
{
|
||||
}
|
||||
|
||||
tr_session* session;
|
||||
std::list<tau_tracker> trackers;
|
||||
|
||||
tr_session* const session;
|
||||
};
|
||||
|
||||
static struct tr_announcer_udp* announcer_udp_get(tr_session* session)
|
||||
|
@ -752,9 +702,7 @@ static struct tr_announcer_udp* announcer_udp_get(tr_session* session)
|
|||
return session->announcer_udp;
|
||||
}
|
||||
|
||||
auto* const tau = tr_new0(tr_announcer_udp, 1);
|
||||
tau->trackers = {};
|
||||
tau->session = session;
|
||||
auto* const tau = new tr_announcer_udp(session);
|
||||
session->announcer_udp = tau;
|
||||
return tau;
|
||||
}
|
||||
|
@ -773,20 +721,18 @@ static tau_tracker* tau_session_get_tracker(tr_announcer_udp* tau, tr_interned_s
|
|||
}
|
||||
|
||||
// see if we already have it
|
||||
// TODO: replace tr_ptrArray
|
||||
auto const key = tr_announcerGetKey(*parsed);
|
||||
for (int i = 0, n = tr_ptrArraySize(&tau->trackers); i < n; ++i)
|
||||
for (auto& tracker : tau->trackers)
|
||||
{
|
||||
auto* tmp = static_cast<struct tau_tracker*>(tr_ptrArrayNth(&tau->trackers, i));
|
||||
if (tmp->key == key)
|
||||
if (tracker.key == key)
|
||||
{
|
||||
return tmp;
|
||||
return &tracker;
|
||||
}
|
||||
}
|
||||
|
||||
// we don't have it -- build a new one
|
||||
auto* const tracker = new tau_tracker{ tau->session, key, tr_interned_string(parsed->host), parsed->port };
|
||||
tr_ptrArrayAppend(&tau->trackers, tracker);
|
||||
tau->trackers.emplace_back(tau->session, key, tr_interned_string(parsed->host), parsed->port);
|
||||
auto* const tracker = &tau->trackers.back();
|
||||
dbgmsg(tracker->key, "New tau_tracker created");
|
||||
return tracker;
|
||||
}
|
||||
|
@ -799,43 +745,30 @@ static tau_tracker* tau_session_get_tracker(tr_announcer_udp* tau, tr_interned_s
|
|||
|
||||
void tr_tracker_udp_upkeep(tr_session* session)
|
||||
{
|
||||
struct tr_announcer_udp* tau = session->announcer_udp;
|
||||
|
||||
if (tau != nullptr)
|
||||
if (auto* const tau = session->announcer_udp; tau != nullptr)
|
||||
{
|
||||
tr_ptrArrayForeach(&tau->trackers, (PtrArrayForeachFunc)tau_tracker_upkeep);
|
||||
for (auto& tracker : tau->trackers)
|
||||
{
|
||||
tau_tracker_upkeep(&tracker);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool tr_tracker_udp_is_idle(tr_session const* session)
|
||||
{
|
||||
struct tr_announcer_udp* tau = session->announcer_udp;
|
||||
auto const* tau = session->announcer_udp;
|
||||
|
||||
if (tau != nullptr)
|
||||
{
|
||||
for (int i = 0, n = tr_ptrArraySize(&tau->trackers); i < n; ++i)
|
||||
{
|
||||
auto const* tracker = static_cast<struct tau_tracker const*>(tr_ptrArrayNth(&tau->trackers, i));
|
||||
if (!tau_tracker_is_idle(tracker))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return tau == nullptr ||
|
||||
std::all_of(std::begin(tau->trackers), std::end(tau->trackers), [](auto const& tracker) { return tracker.isIdle(); });
|
||||
}
|
||||
|
||||
/* drop dead now. */
|
||||
void tr_tracker_udp_close(tr_session* session)
|
||||
{
|
||||
struct tr_announcer_udp* tau = session->announcer_udp;
|
||||
|
||||
if (tau != nullptr)
|
||||
if (auto* const tau = session->announcer_udp; tau != nullptr)
|
||||
{
|
||||
session->announcer_udp = nullptr;
|
||||
tr_ptrArrayDestruct(&tau->trackers, (PtrArrayForeachFunc)tau_tracker_free);
|
||||
tr_free(tau);
|
||||
delete tau;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -845,21 +778,18 @@ void tr_tracker_udp_close(tr_session* session)
|
|||
void tr_tracker_udp_start_shutdown(tr_session* session)
|
||||
{
|
||||
time_t const now = time(nullptr);
|
||||
struct tr_announcer_udp* tau = session->announcer_udp;
|
||||
|
||||
if (tau != nullptr)
|
||||
if (auto* const tau = session->announcer_udp; tau != nullptr)
|
||||
{
|
||||
for (int i = 0, n = tr_ptrArraySize(&tau->trackers); i < n; ++i)
|
||||
for (auto& tracker : tau->trackers)
|
||||
{
|
||||
auto* tracker = static_cast<struct tau_tracker*>(tr_ptrArrayNth(&tau->trackers, i));
|
||||
|
||||
if (tracker->dns_request != nullptr)
|
||||
if (tracker.dns_request != nullptr)
|
||||
{
|
||||
evdns_getaddrinfo_cancel(tracker->dns_request);
|
||||
evdns_getaddrinfo_cancel(tracker.dns_request);
|
||||
}
|
||||
|
||||
tracker->close_at = now + 3;
|
||||
tau_tracker_upkeep(tracker);
|
||||
tracker.close_at = now + 3;
|
||||
tau_tracker_upkeep(&tracker);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -879,7 +809,7 @@ bool tau_handle_message(tr_session* session, uint8_t const* msg, size_t msglen)
|
|||
}
|
||||
|
||||
/* extract the action_id and see if it makes sense */
|
||||
struct evbuffer* const buf = evbuffer_new();
|
||||
auto* const buf = evbuffer_new();
|
||||
evbuffer_add_reference(buf, msg, msglen, nullptr, nullptr);
|
||||
auto const action_id = tau_action_t(evbuffer_read_ntoh_32(buf));
|
||||
|
||||
|
@ -893,50 +823,48 @@ bool tau_handle_message(tr_session* session, uint8_t const* msg, size_t msglen)
|
|||
struct tr_announcer_udp* const tau = session->announcer_udp;
|
||||
tau_transaction_t const transaction_id = evbuffer_read_ntoh_32(buf);
|
||||
|
||||
for (int i = 0, n = tr_ptrArraySize(&tau->trackers); i < n; ++i)
|
||||
for (auto& tracker : tau->trackers)
|
||||
{
|
||||
auto* tracker = static_cast<struct tau_tracker*>(tr_ptrArrayNth(&tau->trackers, i));
|
||||
|
||||
/* is it a connection response? */
|
||||
if (tracker->connecting_at != 0 && transaction_id == tracker->connection_transaction_id)
|
||||
// is it a connection response?
|
||||
if (tracker.connecting_at != 0 && transaction_id == tracker.connection_transaction_id)
|
||||
{
|
||||
dbgmsg(tracker->key, "%" PRIu32 " is my connection request!", transaction_id);
|
||||
on_tracker_connection_response(tracker, action_id, buf);
|
||||
dbgmsg(tracker.key, "%" PRIu32 " is my connection request!", transaction_id);
|
||||
on_tracker_connection_response(&tracker, action_id, buf);
|
||||
evbuffer_free(buf);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* is it a response to one of this tracker's announces? */
|
||||
tr_ptrArray* reqs = &tracker->announces;
|
||||
|
||||
for (int j = 0, jn = tr_ptrArraySize(reqs); j < jn; ++j)
|
||||
// is it a response to one of this tracker's announces?
|
||||
if (auto& reqs = tracker.announces; !std::empty(reqs))
|
||||
{
|
||||
auto* req = static_cast<struct tau_announce_request*>(tr_ptrArrayNth(reqs, j));
|
||||
|
||||
if (req->sent_at != 0 && transaction_id == req->transaction_id)
|
||||
auto it = std::find_if(
|
||||
std::begin(reqs),
|
||||
std::end(reqs),
|
||||
[&transaction_id](auto const& req) { return req.transaction_id == transaction_id; });
|
||||
if (it != std::end(reqs))
|
||||
{
|
||||
dbgmsg(tracker->key, "%" PRIu32 " is an announce request!", transaction_id);
|
||||
tr_ptrArrayRemove(reqs, j);
|
||||
on_announce_response(req, action_id, buf);
|
||||
tau_announce_request_free(req);
|
||||
dbgmsg(tracker.key, "%" PRIu32 " is an announce request!", transaction_id);
|
||||
auto req = *it;
|
||||
it = reqs.erase(it);
|
||||
req.onResponse(action_id, buf);
|
||||
evbuffer_free(buf);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/* is it a response to one of this tracker's scrapes? */
|
||||
reqs = &tracker->scrapes;
|
||||
|
||||
for (int j = 0, jn = tr_ptrArraySize(reqs); j < jn; ++j)
|
||||
// is it a response to one of this tracker's scrapes?
|
||||
if (auto& reqs = tracker.scrapes; !std::empty(reqs))
|
||||
{
|
||||
auto* const req = static_cast<struct tau_scrape_request*>(tr_ptrArrayNth(reqs, j));
|
||||
|
||||
if (req->sent_at != 0 && transaction_id == req->transaction_id)
|
||||
auto it = std::find_if(
|
||||
std::begin(reqs),
|
||||
std::end(reqs),
|
||||
[&transaction_id](auto const& req) { return req.transaction_id == transaction_id; });
|
||||
if (it != std::end(reqs))
|
||||
{
|
||||
dbgmsg(tracker->key, "%" PRIu32 " is a scrape request!", transaction_id);
|
||||
tr_ptrArrayRemove(reqs, j);
|
||||
on_scrape_response(req, action_id, buf);
|
||||
tau_scrape_request_free(req);
|
||||
dbgmsg(tracker.key, "%" PRIu32 " is a scrape request!", transaction_id);
|
||||
auto req = *it;
|
||||
it = reqs.erase(it);
|
||||
req.onResponse(action_id, buf);
|
||||
evbuffer_free(buf);
|
||||
return true;
|
||||
}
|
||||
|
@ -961,8 +889,7 @@ void tr_tracker_udp_announce(
|
|||
return;
|
||||
}
|
||||
|
||||
tau_announce_request* r = tau_announce_request_new(request, response_func, user_data);
|
||||
tr_ptrArrayAppend(&tracker->announces, r);
|
||||
tracker->announces.push_back(make_tau_announce_request(request, response_func, user_data));
|
||||
tau_tracker_upkeep_ex(tracker, false);
|
||||
}
|
||||
|
||||
|
@ -979,7 +906,6 @@ void tr_tracker_udp_scrape(
|
|||
return;
|
||||
}
|
||||
|
||||
tau_scrape_request* r = tau_scrape_request_new(request, response_func, user_data);
|
||||
tr_ptrArrayAppend(&tracker->scrapes, r);
|
||||
tracker->scrapes.push_back(make_tau_scrape_request(request, response_func, user_data));
|
||||
tau_tracker_upkeep_ex(tracker, false);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -12,13 +12,14 @@
|
|||
#include <cstddef> // size_t
|
||||
#include <ctime>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include "transmission.h"
|
||||
|
||||
#include "interned-string.h"
|
||||
|
||||
struct tr_announcer;
|
||||
struct tr_announcer_tiers;
|
||||
struct tr_torrent_announcer;
|
||||
|
||||
/**
|
||||
* *** Tracker Publish / Subscribe
|
||||
|
@ -46,8 +47,7 @@ struct tr_tracker_event
|
|||
tr_interned_string announce_url;
|
||||
|
||||
/* for TR_TRACKER_PEERS */
|
||||
struct tr_pex const* pex;
|
||||
size_t pexCount;
|
||||
std::vector<tr_pex> pex;
|
||||
|
||||
/* for TR_TRACKER_PEERS and TR_TRACKER_COUNTS */
|
||||
int leechers;
|
||||
|
@ -68,7 +68,7 @@ void tr_announcerClose(tr_session*);
|
|||
*** For torrent customers
|
||||
**/
|
||||
|
||||
struct tr_announcer_tiers* tr_announcerAddTorrent(tr_torrent* torrent, tr_tracker_callback cb, void* cbdata);
|
||||
struct tr_torrent_announcer* tr_announcerAddTorrent(tr_torrent* torrent, tr_tracker_callback cb, void* cbdata);
|
||||
|
||||
void tr_announcerResetTorrent(struct tr_announcer*, tr_torrent*);
|
||||
|
||||
|
|
|
@ -1201,6 +1201,27 @@ tr_pex* tr_peerMgrCompactToPex(
|
|||
return pex;
|
||||
}
|
||||
|
||||
std::vector<tr_pex> tr_peerMgrCompactToPex(void const* compact, size_t compactLen, uint8_t const* added_f, size_t added_f_len)
|
||||
{
|
||||
size_t n = compactLen / 6;
|
||||
auto const* walk = static_cast<std::byte const*>(compact);
|
||||
auto pex = std::vector<tr_pex>(n);
|
||||
|
||||
for (size_t i = 0; i < n; ++i)
|
||||
{
|
||||
pex[i].addr.type = TR_AF_INET;
|
||||
walk = std::copy_n(walk, 4, reinterpret_cast<std::byte*>(&pex[i].addr.addr));
|
||||
walk = std::copy_n(walk, 2, reinterpret_cast<std::byte*>(&pex[i].port));
|
||||
|
||||
if (added_f != nullptr && n == added_f_len)
|
||||
{
|
||||
pex[i].flags = added_f[i];
|
||||
}
|
||||
}
|
||||
|
||||
return pex;
|
||||
}
|
||||
|
||||
tr_pex* tr_peerMgrCompact6ToPex(
|
||||
void const* compact,
|
||||
size_t compactLen,
|
||||
|
@ -1230,6 +1251,27 @@ tr_pex* tr_peerMgrCompact6ToPex(
|
|||
return pex;
|
||||
}
|
||||
|
||||
std::vector<tr_pex> tr_peerMgrCompact6ToPex(void const* compact, size_t compactLen, uint8_t const* added_f, size_t added_f_len)
|
||||
{
|
||||
size_t n = compactLen / 18;
|
||||
auto const* walk = static_cast<std::byte const*>(compact);
|
||||
auto pex = std::vector<tr_pex>(n);
|
||||
|
||||
for (size_t i = 0; i < n; ++i)
|
||||
{
|
||||
pex[i].addr.type = TR_AF_INET6;
|
||||
walk = std::copy_n(walk, 16, reinterpret_cast<std::byte*>(&pex[i].addr.addr.addr6.s6_addr));
|
||||
walk = std::copy_n(walk, 2, reinterpret_cast<std::byte*>(&pex[i].port));
|
||||
|
||||
if (added_f != nullptr && n == added_f_len)
|
||||
{
|
||||
pex[i].flags = added_f[i];
|
||||
}
|
||||
}
|
||||
|
||||
return pex;
|
||||
}
|
||||
|
||||
/**
|
||||
***
|
||||
**/
|
||||
|
|
|
@ -101,6 +101,10 @@ tr_pex* tr_peerMgrCompact6ToPex(
|
|||
size_t added_f_len,
|
||||
size_t* pexCount);
|
||||
|
||||
std::vector<tr_pex> tr_peerMgrCompactToPex(void const* compact, size_t compactLen, uint8_t const* added_f, size_t added_f_len);
|
||||
|
||||
std::vector<tr_pex> tr_peerMgrCompact6ToPex(void const* compact, size_t compactLen, uint8_t const* added_f, size_t added_f_len);
|
||||
|
||||
size_t tr_peerMgrAddPex(tr_torrent* tor, uint8_t from, tr_pex const* pex, size_t n_pex);
|
||||
|
||||
void tr_peerMgrSetSwarmIsAllSeeds(tr_torrent* tor);
|
||||
|
|
|
@ -68,7 +68,6 @@ static char const* getNatStateStr(int state)
|
|||
|
||||
static void natPulse(tr_shared* s, bool do_check)
|
||||
{
|
||||
tr_port received_private_port;
|
||||
tr_port const private_peer_port = s->session->private_peer_port;
|
||||
bool const is_enabled = s->isEnabled && !s->isShuttingDown;
|
||||
|
||||
|
@ -85,6 +84,7 @@ static void natPulse(tr_shared* s, bool do_check)
|
|||
auto const old_status = tr_sharedTraversalStatus(s);
|
||||
|
||||
auto public_peer_port = tr_port{};
|
||||
auto received_private_port = tr_port{};
|
||||
s->natpmpStatus = tr_natpmpPulse(s->natpmp, private_peer_port, is_enabled, &public_peer_port, &received_private_port);
|
||||
|
||||
if (s->natpmpStatus == TR_PORT_MAPPED)
|
||||
|
|
|
@ -103,12 +103,12 @@ struct tr_turtle_info
|
|||
struct tr_session
|
||||
{
|
||||
public:
|
||||
auto unique_lock() const
|
||||
[[nodiscard]] auto unique_lock() const
|
||||
{
|
||||
return std::unique_lock(session_mutex_);
|
||||
}
|
||||
|
||||
bool isClosing() const
|
||||
[[nodiscard]] bool isClosing() const
|
||||
{
|
||||
return is_closing_;
|
||||
}
|
||||
|
|
|
@ -508,8 +508,8 @@ static void onTrackerResponse(tr_torrent* tor, tr_tracker_event const* event, vo
|
|||
switch (event->messageType)
|
||||
{
|
||||
case TR_TRACKER_PEERS:
|
||||
tr_logAddTorDbg(tor, "Got %zu peers from tracker", event->pexCount);
|
||||
tr_peerMgrAddPex(tor, TR_PEER_FROM_TRACKER, event->pex, event->pexCount);
|
||||
tr_logAddTorDbg(tor, "Got %zu peers from tracker", size_t(std::size(event->pex)));
|
||||
tr_peerMgrAddPex(tor, TR_PEER_FROM_TRACKER, std::data(event->pex), std::size(event->pex));
|
||||
break;
|
||||
|
||||
case TR_TRACKER_COUNTS:
|
||||
|
@ -733,7 +733,7 @@ static void torrentInit(tr_torrent* tor, tr_ctor const* ctor)
|
|||
tr_error_clear(&error);
|
||||
}
|
||||
|
||||
tor->announcer_tiers = tr_announcerAddTorrent(tor, onTrackerResponse, nullptr);
|
||||
tor->torrent_announcer = tr_announcerAddTorrent(tor, onTrackerResponse, nullptr);
|
||||
|
||||
if (is_new_torrent)
|
||||
{
|
||||
|
|
|
@ -37,7 +37,7 @@ struct tr_magnet_info;
|
|||
struct tr_metainfo_parsed;
|
||||
struct tr_session;
|
||||
struct tr_torrent;
|
||||
struct tr_announcer_tiers;
|
||||
struct tr_torrent_announcer;
|
||||
|
||||
/**
|
||||
*** Package-visible ctor API
|
||||
|
@ -131,7 +131,7 @@ public:
|
|||
|
||||
void setMetainfo(tr_torrent_metainfo const& tm);
|
||||
|
||||
auto unique_lock() const
|
||||
[[nodiscard]] auto unique_lock() const
|
||||
{
|
||||
return session->unique_lock();
|
||||
}
|
||||
|
@ -140,7 +140,7 @@ public:
|
|||
|
||||
void setSpeedLimitBps(tr_direction, unsigned int Bps);
|
||||
|
||||
unsigned int speedLimitBps(tr_direction) const;
|
||||
[[nodiscard]] unsigned int speedLimitBps(tr_direction) const;
|
||||
|
||||
/// BLOCK INFO
|
||||
|
||||
|
@ -582,7 +582,7 @@ public:
|
|||
|
||||
tr_session* session = nullptr;
|
||||
|
||||
tr_announcer_tiers* announcer_tiers = nullptr;
|
||||
tr_torrent_announcer* torrent_announcer = nullptr;
|
||||
|
||||
// Changed to non-owning pointer temporarily till tr_torrent becomes C++-constructible and destructible
|
||||
// TODO: change tr_bandwidth* to owning pointer to the bandwidth, or remove * and own the value
|
||||
|
|
Loading…
Reference in New Issue