1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2025-03-03 10:15:45 +00:00

refactor: remove libtransmission::Buffer (#5676)

* refactor: use StackBuffer in announcer-udp

* chore: update buffer tests

* refactor: remove unused libtransmission::Buffer

superseded by libtransmission::StackBuffer
This commit is contained in:
Charles Kerr 2023-06-27 19:06:25 -05:00 committed by GitHub
parent 635268854b
commit 9afced725a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 32 additions and 144 deletions

View file

@ -50,7 +50,7 @@ using tau_connection_t = uint64_t;
using tau_transaction_t = uint32_t;
using InBuf = libtransmission::BufferReader<std::byte>;
using PayloadBuffer = libtransmission::Buffer;
using PayloadBuffer = libtransmission::StackBuffer<4096, std::byte>;
constexpr auto TauConnectionTtlSecs = time_t{ 45 };

View file

@ -16,12 +16,8 @@
#include <small/vector.hpp>
#include <event2/buffer.h>
#include "error.h"
#include "net.h" // tr_socket_t
#include "tr-assert.h"
#include "utils-ev.h"
#include "utils.h" // for tr_htonll(), tr_ntohll()
namespace libtransmission
@ -285,61 +281,4 @@ private:
size_t end_pos_ = {};
};
class Buffer final
: public BufferReader<std::byte>
, public BufferWriter<std::byte>
{
public:
using value_type = std::byte;
Buffer() = default;
Buffer(Buffer&&) = default;
Buffer(Buffer const&) = delete;
Buffer& operator=(Buffer&&) = default;
Buffer& operator=(Buffer const&) = delete;
template<typename T>
explicit Buffer(T const& data)
{
add(data);
}
[[nodiscard]] size_t size() const noexcept override
{
return evbuffer_get_length(buf_.get());
}
[[nodiscard]] value_type const* data() const override
{
return reinterpret_cast<value_type const*>(evbuffer_pullup(buf_.get(), -1));
}
void drain(size_t n_bytes) override
{
evbuffer_drain(buf_.get(), n_bytes);
}
[[nodiscard]] std::pair<value_type*, size_t> reserve_space(size_t n_bytes) override
{
auto iov = evbuffer_iovec{};
evbuffer_reserve_space(buf_.get(), n_bytes, &iov, 1);
TR_ASSERT(iov.iov_len >= n_bytes);
reserved_space_ = iov;
return { static_cast<value_type*>(iov.iov_base), static_cast<size_t>(iov.iov_len) };
}
void commit_space(size_t n_bytes) override
{
TR_ASSERT(reserved_space_);
TR_ASSERT(reserved_space_->iov_len >= n_bytes);
reserved_space_->iov_len = n_bytes;
evbuffer_commit_space(buf_.get(), &*reserved_space_, 1);
reserved_space_.reset();
}
private:
evhelpers::evbuffer_unique_ptr buf_{ evbuffer_new() };
std::optional<evbuffer_iovec> reserved_space_;
};
} // namespace libtransmission

View file

@ -25,6 +25,8 @@
using namespace std::literals;
using MessageBuffer = libtransmission::StackBuffer<4096, std::byte>;
class AnnouncerUdpTest : public ::testing::Test
{
private:
@ -111,8 +113,9 @@ protected:
}
}
[[nodiscard]] static uint32_t parseConnectionRequest(libtransmission::Buffer& buf)
[[nodiscard]] static uint32_t parseConnectionRequest(std::vector<char> data)
{
auto buf = MessageBuffer(data);
EXPECT_EQ(ProtocolId, buf.to_uint64());
EXPECT_EQ(ConnectAction, buf.to_uint32());
return buf.to_uint32();
@ -147,8 +150,9 @@ protected:
return std::make_pair(buildScrapeRequestFromResponse(response), response);
}
[[nodiscard]] static auto parseScrapeRequest(libtransmission::Buffer& buf, uint64_t expected_connection_id)
[[nodiscard]] static auto parseScrapeRequest(std::vector<char> data, uint64_t expected_connection_id)
{
auto buf = MessageBuffer(data);
EXPECT_EQ(expected_connection_id, buf.to_uint64());
EXPECT_EQ(ScrapeAction, buf.to_uint32());
auto const transaction_id = buf.to_uint32();
@ -165,14 +169,14 @@ protected:
[[nodiscard]] static auto waitForAnnouncerToSendMessage(MockMediator& mediator)
{
libtransmission::test::waitFor(mediator.eventBase(), [&mediator]() { return !std::empty(mediator.sent_); });
auto buf = libtransmission::Buffer(mediator.sent_.back().buf_);
auto buf = std::move(mediator.sent_.back().buf_);
mediator.sent_.pop_back();
return buf;
}
[[nodiscard]] static bool sendError(tr_announcer_udp& announcer, uint32_t transaction_id, std::string_view errmsg)
{
auto buf = libtransmission::Buffer{};
auto buf = MessageBuffer{};
buf.add_uint32(ErrorAction);
buf.add_uint32(transaction_id);
buf.add(errmsg);
@ -187,7 +191,7 @@ protected:
[[nodiscard]] static auto sendConnectionResponse(tr_announcer_udp& announcer, uint32_t transaction_id)
{
auto const connection_id = tr_rand_obj<uint64_t>();
auto buf = libtransmission::Buffer{};
auto buf = MessageBuffer{};
buf.add_uint32(ConnectAction);
buf.add_uint32(transaction_id);
buf.add_uint64(connection_id);
@ -250,8 +254,9 @@ protected:
EXPECT_EQ(actual.external_ip, expected.external_ip);
}
[[nodiscard]] static auto parseAnnounceRequest(libtransmission::Buffer& buf, uint64_t connection_id)
[[nodiscard]] static auto parseAnnounceRequest(std::vector<char> data, uint64_t connection_id)
{
auto buf = MessageBuffer{ data };
auto req = UdpAnnounceReq{};
req.connection_id = buf.to_uint64();
req.action = buf.to_uint32();
@ -313,20 +318,18 @@ TEST_F(AnnouncerUdpTest, canScrape)
// The announcer should have sent a UDP connection request.
// Inspect that request for validity.
auto sent = waitForAnnouncerToSendMessage(mediator);
auto connect_transaction_id = parseConnectionRequest(sent);
auto connect_transaction_id = parseConnectionRequest(waitForAnnouncerToSendMessage(mediator));
// Have the tracker respond to the request
auto const connection_id = sendConnectionResponse(*announcer, connect_transaction_id);
// The announcer should have sent a UDP scrape request.
// Inspect that request for validity.
sent = waitForAnnouncerToSendMessage(mediator);
auto [scrape_transaction_id, info_hashes] = parseScrapeRequest(sent, connection_id);
auto [scrape_transaction_id, info_hashes] = parseScrapeRequest(waitForAnnouncerToSendMessage(mediator), connection_id);
expectEqual(request, info_hashes);
// Have the tracker respond to the request
auto buf = libtransmission::Buffer{};
auto buf = MessageBuffer{};
buf.add_uint32(ScrapeAction);
buf.add_uint32(scrape_transaction_id);
buf.add_uint32(expected_response.rows[0].seeders);
@ -350,8 +353,7 @@ TEST_F(AnnouncerUdpTest, canScrape)
// The announcer should have sent a UDP connection request.
// Inspect that request for validity.
sent = waitForAnnouncerToSendMessage(mediator);
std::tie(scrape_transaction_id, info_hashes) = parseScrapeRequest(sent, connection_id);
std::tie(scrape_transaction_id, info_hashes) = parseScrapeRequest(waitForAnnouncerToSendMessage(mediator), connection_id);
expectEqual(request, info_hashes);
}
@ -368,8 +370,7 @@ TEST_F(AnnouncerUdpTest, canDestructCleanlyEvenWhenBusy)
// The announcer should have sent a UDP connection request.
// Inspect that request for validity.
auto sent = waitForAnnouncerToSendMessage(mediator);
auto const connect_transaction_id = parseConnectionRequest(sent);
auto const connect_transaction_id = parseConnectionRequest(waitForAnnouncerToSendMessage(mediator));
EXPECT_NE(0U, connect_transaction_id);
// now just end the test before responding to the request.
@ -396,18 +397,16 @@ TEST_F(AnnouncerUdpTest, canMultiScrape)
announcer->scrape(request, [&response](tr_scrape_response const& resp) { response = resp; });
// Announcer will request a connection. Verify and grant the request
auto sent = waitForAnnouncerToSendMessage(mediator);
auto connect_transaction_id = parseConnectionRequest(sent);
auto connect_transaction_id = parseConnectionRequest(waitForAnnouncerToSendMessage(mediator));
auto const connection_id = sendConnectionResponse(*announcer, connect_transaction_id);
// The announcer should have sent a UDP scrape request.
// Inspect that request for validity.
sent = waitForAnnouncerToSendMessage(mediator);
auto [scrape_transaction_id, info_hashes] = parseScrapeRequest(sent, connection_id);
auto [scrape_transaction_id, info_hashes] = parseScrapeRequest(waitForAnnouncerToSendMessage(mediator), connection_id);
expectEqual(request, info_hashes);
// Have the tracker respond to the request
auto buf = libtransmission::Buffer{};
auto buf = MessageBuffer{};
buf.add_uint32(ScrapeAction);
buf.add_uint32(scrape_transaction_id);
for (int i = 0; i < expected_response.row_count; ++i)
@ -457,16 +456,16 @@ TEST_F(AnnouncerUdpTest, canHandleScrapeError)
// The announcer should have sent a UDP connection request.
// Inspect that request for validity.
auto sent = waitForAnnouncerToSendMessage(mediator);
auto connect_transaction_id = parseConnectionRequest(sent);
auto connect_transaction_id = parseConnectionRequest(waitForAnnouncerToSendMessage(mediator));
// Have the tracker respond to the request
auto const connection_id = sendConnectionResponse(*announcer, connect_transaction_id);
// The announcer should have sent a UDP scrape request.
// Inspect that request for validity.
sent = waitForAnnouncerToSendMessage(mediator);
auto const [scrape_transaction_id, info_hashes] = parseScrapeRequest(sent, connection_id);
auto const [scrape_transaction_id, info_hashes] = parseScrapeRequest(
waitForAnnouncerToSendMessage(mediator),
connection_id);
// Have the tracker respond to the request with an "unable to scrape" error
EXPECT_TRUE(sendError(*announcer, scrape_transaction_id, expected_response.errmsg));
@ -506,8 +505,7 @@ TEST_F(AnnouncerUdpTest, canHandleConnectError)
// The announcer should have sent a UDP connection request.
// Inspect that request for validity.
auto sent = waitForAnnouncerToSendMessage(mediator);
auto transaction_id = parseConnectionRequest(sent);
auto transaction_id = parseConnectionRequest(waitForAnnouncerToSendMessage(mediator));
// Have the tracker respond to the request with an "unable to connect" error
EXPECT_TRUE(sendError(*announcer, transaction_id, expected_response.errmsg));
@ -537,11 +535,10 @@ TEST_F(AnnouncerUdpTest, handleMessageReturnsFalseOnInvalidMessage)
// The announcer should have sent a UDP connection request.
// Inspect that request for validity.
auto sent = waitForAnnouncerToSendMessage(mediator);
auto transaction_id = parseConnectionRequest(sent);
auto transaction_id = parseConnectionRequest(waitForAnnouncerToSendMessage(mediator));
// send a connection response but with an *invalid* transaction id
auto buf = libtransmission::Buffer{};
auto buf = MessageBuffer{};
buf.add_uint32(ConnectAction);
buf.add_uint32(transaction_id + 1);
buf.add_uint64(tr_rand_obj<uint64_t>());
@ -551,7 +548,7 @@ TEST_F(AnnouncerUdpTest, handleMessageReturnsFalseOnInvalidMessage)
EXPECT_FALSE(announcer->handle_message(std::data(arr), response_size));
// send a connection response but with an *invalid* action
buf = {};
buf.clear();
buf.add_uint32(ScrapeAction);
buf.add_uint32(transaction_id);
buf.add_uint64(tr_rand_obj<uint64_t>());
@ -617,18 +614,16 @@ TEST_F(AnnouncerUdpTest, canAnnounce)
announcer->announce(request, [&response](tr_announce_response const& resp) { response = resp; });
// Announcer will request a connection. Verify and grant the request
auto sent = waitForAnnouncerToSendMessage(mediator);
auto connect_transaction_id = parseConnectionRequest(sent);
auto connect_transaction_id = parseConnectionRequest(waitForAnnouncerToSendMessage(mediator));
auto const connection_id = sendConnectionResponse(*announcer, connect_transaction_id);
// The announcer should have sent a UDP announce request.
// Inspect that request for validity.
sent = waitForAnnouncerToSendMessage(mediator);
auto udp_ann_req = parseAnnounceRequest(sent, connection_id);
auto udp_ann_req = parseAnnounceRequest(waitForAnnouncerToSendMessage(mediator), connection_id);
expectEqual(request, udp_ann_req);
// Have the tracker respond to the request
auto buf = libtransmission::Buffer{};
auto buf = MessageBuffer{};
buf.add_uint32(AnnounceAction);
buf.add_uint32(udp_ann_req.transaction_id);
buf.add_uint32(expected_response.interval);

View file

@ -11,7 +11,7 @@
using BufferTest = ::testing::Test;
using namespace std::literals;
using Buffer = libtransmission::Buffer;
using Buffer = libtransmission::StackBuffer<1024, std::byte>;
TEST_F(BufferTest, startsWithInSingleSegment)
{
@ -62,52 +62,6 @@ TEST_F(BufferTest, startsWithInMultiSegment)
EXPECT_TRUE(buf->starts_with("Hello, World!"sv));
}
TEST_F(BufferTest, Move)
{
auto constexpr TwoChars = "12"sv;
auto constexpr SixChars = "123456"sv;
auto constexpr TenChars = "1234567890"sv;
auto a = Buffer{ TwoChars };
auto b = Buffer{ SixChars };
auto c = Buffer{ TenChars };
auto lens = std::array<size_t, 3>{ std::size(TwoChars), std::size(SixChars), std::size(TenChars) };
EXPECT_EQ(lens[0], std::size(a));
EXPECT_EQ(lens[1], std::size(b));
EXPECT_EQ(lens[2], std::size(c));
std::swap(a, b);
EXPECT_EQ(lens[0], std::size(b));
EXPECT_EQ(lens[1], std::size(a));
EXPECT_EQ(lens[2], std::size(c));
std::swap(a, c);
EXPECT_EQ(lens[0], std::size(b));
EXPECT_EQ(lens[1], std::size(c));
EXPECT_EQ(lens[2], std::size(a));
std::swap(b, c);
EXPECT_EQ(lens[0], std::size(c));
EXPECT_EQ(lens[1], std::size(b));
EXPECT_EQ(lens[2], std::size(a));
a.add(std::data(TwoChars), std::size(TwoChars));
{
auto constexpr OneChar = "1"sv;
auto d = Buffer{ OneChar };
std::swap(a, d);
EXPECT_EQ(1U, std::size(a));
}
EXPECT_EQ(1U, std::size(a));
a.add(std::data(TwoChars), std::size(TwoChars));
EXPECT_EQ(3U, std::size(a));
}
TEST_F(BufferTest, Numbers)
{
for (auto i = 0; i < 100; ++i)