mirror of
https://github.com/transmission/transmission
synced 2025-02-21 21:57:01 +00:00
fixup: handle unhandled scrape/announce responses (#2701)
followup to the #2531 benc refactor
This commit is contained in:
parent
798022ac77
commit
9c3acc7e8a
7 changed files with 80 additions and 3 deletions
|
@ -214,6 +214,10 @@ struct tr_announce_response
|
|||
/* 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<tr_address> external_ip;
|
||||
};
|
||||
|
||||
using tr_announce_response_func = void (*)(tr_announce_response const* response, void* userdata);
|
||||
|
|
|
@ -253,6 +253,10 @@ void tr_announcerParseHttpAnnounceResponse(tr_announce_response& response, std::
|
|||
{
|
||||
// unused
|
||||
}
|
||||
else if (key == "external ip"sv && std::size(value) == 4)
|
||||
{
|
||||
response_.external_ip = tr_address::from_4byte_ipv4(value);
|
||||
}
|
||||
else if (!tr_error_is_set(context.error))
|
||||
{
|
||||
tr_error_set(context.error, EINVAL, tr_strvJoin("unexpected str: key["sv, key, "] value["sv, value, "]"sv));
|
||||
|
@ -402,6 +406,14 @@ void tr_announcerParseHttpScrapeResponse(tr_scrape_response& response, std::stri
|
|||
{
|
||||
response_.rows[*row_].leechers = value;
|
||||
}
|
||||
else if (row_ && key == "downloaders"sv)
|
||||
{
|
||||
response_.rows[*row_].downloaders = value;
|
||||
}
|
||||
else if (key == "min_request_interval"sv)
|
||||
{
|
||||
response_.min_request_interval = value;
|
||||
}
|
||||
else if (!tr_error_is_set(context.error))
|
||||
{
|
||||
auto const errmsg = tr_strvJoin("unexpected int: key["sv, key, "] value["sv, std::to_string(value), "]"sv);
|
||||
|
|
|
@ -995,6 +995,11 @@ static void on_announce_done(tr_announce_response const* response, void* vdata)
|
|||
tier->isAnnouncing = false;
|
||||
tier->manualAnnounceAllowedAt = now + tier->announceMinIntervalSec;
|
||||
|
||||
if (response->external_ip)
|
||||
{
|
||||
data->session->setExternalIP(*response->external_ip);
|
||||
}
|
||||
|
||||
if (!response->did_connect)
|
||||
{
|
||||
on_announce_error(tier, _("Could not connect to tracker"), event);
|
||||
|
|
|
@ -115,7 +115,7 @@ bool tr_address_from_string(tr_address* dst, std::string_view src)
|
|||
{
|
||||
// inet_pton() requires zero-terminated strings,
|
||||
// so make a zero-terminated copy here on the stack.
|
||||
auto buf = std::array<char, 64>{};
|
||||
auto buf = std::array<char, TR_ADDRSTRLEN>{};
|
||||
if (std::size(src) >= std::size(buf))
|
||||
{
|
||||
// shouldn't ever be that large; malformed address
|
||||
|
@ -127,6 +127,28 @@ bool tr_address_from_string(tr_address* dst, std::string_view src)
|
|||
return tr_address_from_string(dst, std::data(buf));
|
||||
}
|
||||
|
||||
std::optional<tr_address> tr_address::from_string(std::string_view str)
|
||||
{
|
||||
auto addr = tr_address{};
|
||||
|
||||
if (!tr_address_from_string(&addr, str))
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
tr_address tr_address::from_4byte_ipv4(std::string_view in)
|
||||
{
|
||||
TR_ASSERT(std::size(in) == 4);
|
||||
|
||||
auto addr = tr_address{};
|
||||
addr.type = TR_AF_INET;
|
||||
std::copy_n(std::begin(in), 4, reinterpret_cast<char*>(&addr.addr));
|
||||
return addr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare two tr_address structures.
|
||||
* Returns:
|
||||
|
|
|
@ -68,14 +68,37 @@ enum tr_address_type
|
|||
NUM_TR_AF_INET_TYPES
|
||||
};
|
||||
|
||||
struct tr_address;
|
||||
|
||||
int tr_address_compare(tr_address const* a, tr_address const* b);
|
||||
|
||||
struct tr_address
|
||||
{
|
||||
static tr_address from_4byte_ipv4(std::string_view in);
|
||||
|
||||
static std::optional<tr_address> from_string(std::string_view str);
|
||||
|
||||
tr_address_type type;
|
||||
union
|
||||
{
|
||||
struct in6_addr addr6;
|
||||
struct in_addr addr4;
|
||||
} addr;
|
||||
|
||||
bool operator==(tr_address const& that) const
|
||||
{
|
||||
return tr_address_compare(this, &that) == 0;
|
||||
}
|
||||
|
||||
bool operator<(tr_address const& that) const
|
||||
{
|
||||
return tr_address_compare(this, &that) < 0;
|
||||
}
|
||||
|
||||
bool operator>(tr_address const& that) const
|
||||
{
|
||||
return tr_address_compare(this, &that) > 0;
|
||||
}
|
||||
};
|
||||
|
||||
extern tr_address const tr_inaddr_any;
|
||||
|
@ -93,8 +116,6 @@ bool tr_address_from_string(tr_address* dst, std::string_view src);
|
|||
|
||||
bool tr_address_from_sockaddr_storage(tr_address* setme, tr_port* port, struct sockaddr_storage const* src);
|
||||
|
||||
int tr_address_compare(tr_address const* a, tr_address const* b);
|
||||
|
||||
bool tr_address_is_valid_for_peers(tr_address const* addr, tr_port port);
|
||||
|
||||
constexpr bool tr_address_is_valid(tr_address const* a)
|
||||
|
|
|
@ -239,6 +239,16 @@ public:
|
|||
|
||||
bool useRpcWhitelist() const;
|
||||
|
||||
auto externalIP() const
|
||||
{
|
||||
return external_ip_;
|
||||
}
|
||||
|
||||
void setExternalIP(tr_address external_ip)
|
||||
{
|
||||
external_ip_ = external_ip;
|
||||
}
|
||||
|
||||
// peer networking
|
||||
|
||||
std::string const& peerCongestionAlgorithm() const
|
||||
|
@ -419,6 +429,7 @@ private:
|
|||
std::string default_trackers_str_;
|
||||
std::string incomplete_dir_;
|
||||
std::string peer_congestion_algorithm_;
|
||||
std::optional<tr_address> external_ip_;
|
||||
|
||||
std::array<bool, TR_SCRIPT_N_TYPES> scripts_enabled_;
|
||||
bool blocklist_enabled_ = false;
|
||||
|
|
|
@ -32,6 +32,7 @@ TEST_F(AnnouncerTest, parseHttpAnnounceResponseNoPeers)
|
|||
"8:interval" "i1803e"
|
||||
"12:min interval" "i1800e"
|
||||
"5:peers" "0:"
|
||||
"11:external ip" "4:\x01\x02\x03\x04"
|
||||
"e"sv;
|
||||
// clang-format on
|
||||
|
||||
|
@ -42,6 +43,7 @@ TEST_F(AnnouncerTest, parseHttpAnnounceResponseNoPeers)
|
|||
EXPECT_EQ(3, response.seeders);
|
||||
EXPECT_EQ(0, response.leechers);
|
||||
EXPECT_EQ(2, response.downloads);
|
||||
EXPECT_EQ(*tr_address::from_string("1.2.3.4"), response.external_ip);
|
||||
EXPECT_EQ(0, std::size(response.pex));
|
||||
EXPECT_EQ(0, std::size(response.pex6));
|
||||
EXPECT_EQ(""sv, response.errmsg);
|
||||
|
|
Loading…
Reference in a new issue