mirror of
https://github.com/transmission/transmission.git
synced 2025-12-25 04:45:56 +00:00
fix: parse all http announce responses (#6223)
This commit is contained in:
@@ -97,7 +97,6 @@ struct http_announce_data
|
||||
std::optional<tr_announce_response> previous_response;
|
||||
|
||||
tr_announce_response_func on_response;
|
||||
bool http_success = false;
|
||||
|
||||
uint8_t requests_sent_count = {};
|
||||
uint8_t requests_answered_count = {};
|
||||
@@ -105,33 +104,33 @@ struct http_announce_data
|
||||
std::string log_name;
|
||||
};
|
||||
|
||||
bool handleAnnounceResponse(tr_web::FetchResponse const& web_response, tr_announce_response* const response)
|
||||
bool handleAnnounceResponse(tr_web::FetchResponse const& web_response, tr_announce_response& response)
|
||||
{
|
||||
auto const& [status, body, did_connect, did_timeout, vdata] = web_response;
|
||||
auto const& log_name = static_cast<http_announce_data const*>(vdata)->log_name;
|
||||
|
||||
response->did_connect = did_connect;
|
||||
response->did_timeout = did_timeout;
|
||||
response.did_connect = did_connect;
|
||||
response.did_timeout = did_timeout;
|
||||
tr_logAddTrace("Got announce response", log_name);
|
||||
|
||||
if (status != HTTP_OK)
|
||||
{
|
||||
auto const* const response_str = tr_webGetResponseStr(status);
|
||||
response->errmsg = fmt::format(FMT_STRING("Tracker HTTP response {:d} ({:s})"), status, response_str);
|
||||
response.errmsg = fmt::format("Tracker HTTP response {:d} ({:s})", status, response_str);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
tr_announcerParseHttpAnnounceResponse(*response, body, log_name);
|
||||
tr_announcerParseHttpAnnounceResponse(response, body, log_name);
|
||||
|
||||
if (!std::empty(response->pex6))
|
||||
if (!std::empty(response.pex6))
|
||||
{
|
||||
tr_logAddTrace(fmt::format("got a peers6 length of {}", std::size(response->pex6)), log_name);
|
||||
tr_logAddTrace(fmt::format("got a peers6 length of {}", std::size(response.pex6)), log_name);
|
||||
}
|
||||
|
||||
if (!std::empty(response->pex))
|
||||
if (!std::empty(response.pex))
|
||||
{
|
||||
tr_logAddTrace(fmt::format("got a peers length of {}", std::size(response->pex)), log_name);
|
||||
tr_logAddTrace(fmt::format("got a peers length of {}", std::size(response.pex)), log_name);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -140,24 +139,21 @@ bool handleAnnounceResponse(tr_web::FetchResponse const& web_response, tr_announ
|
||||
void onAnnounceDone(tr_web::FetchResponse const& web_response)
|
||||
{
|
||||
auto const& [status, body, did_connect, did_timeout, vdata] = web_response;
|
||||
auto* data = static_cast<struct http_announce_data*>(vdata);
|
||||
auto* data = static_cast<http_announce_data*>(vdata);
|
||||
|
||||
++data->requests_answered_count;
|
||||
auto const got_all_responses = ++data->requests_answered_count == data->requests_sent_count;
|
||||
|
||||
// If another request already succeeded (or we don't have a registered callback),
|
||||
// skip processing this response:
|
||||
if (!data->http_success && data->on_response)
|
||||
TR_ASSERT(data->on_response);
|
||||
if (data->on_response)
|
||||
{
|
||||
tr_announce_response response;
|
||||
response.info_hash = data->info_hash;
|
||||
|
||||
data->http_success = handleAnnounceResponse(web_response, &response);
|
||||
|
||||
if (data->http_success)
|
||||
if (handleAnnounceResponse(web_response, response))
|
||||
{
|
||||
data->on_response(response);
|
||||
}
|
||||
else if (data->requests_answered_count == data->requests_sent_count)
|
||||
else if (got_all_responses)
|
||||
{
|
||||
auto const* response_used = &response;
|
||||
|
||||
@@ -179,13 +175,9 @@ void onAnnounceDone(tr_web::FetchResponse const& web_response)
|
||||
data->previous_response = std::move(response);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tr_logAddTrace("Ignoring redundant announce response", data->log_name);
|
||||
}
|
||||
|
||||
// Free data if no more responses are expected:
|
||||
if (data->requests_answered_count == data->requests_sent_count)
|
||||
// Free data if no more responses are expected
|
||||
if (got_all_responses)
|
||||
{
|
||||
delete data;
|
||||
}
|
||||
@@ -288,7 +280,7 @@ void tr_tracker_http_announce(
|
||||
* Before Curl 7.77.0, if we explicitly choose the IP version we want
|
||||
* to use, it is still possible that the wrong one is used. The workaround
|
||||
* is expensive (disabling DNS cache), so instead we have to make do with
|
||||
* a request that we don't know if will go through IPv6 or IPv4.
|
||||
* a request that we don't know whether it will go through IPv6 or IPv4.
|
||||
*/
|
||||
static auto const use_curl_workaround = curl_version_info(CURLVERSION_NOW)->version_num < 0x074D00 /* 7.77.0 */;
|
||||
if (use_curl_workaround || session->useAnnounceIP())
|
||||
@@ -305,12 +297,12 @@ void tr_tracker_http_announce(
|
||||
{
|
||||
d->requests_sent_count = 2;
|
||||
|
||||
// First try to send the announce via IPv4:
|
||||
// First try to send the announce via IPv4
|
||||
auto ipv4_options = options;
|
||||
ipv4_options.ip_proto = tr_web::FetchOptions::IPProtocol::V4;
|
||||
do_make_request("IPv4"sv, std::move(ipv4_options));
|
||||
|
||||
// Then try to send via IPv6:
|
||||
// Then try to send via IPv6
|
||||
options.ip_proto = tr_web::FetchOptions::IPProtocol::V6;
|
||||
do_make_request("IPv6"sv, std::move(options));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user