mirror of
https://github.com/transmission/transmission.git
synced 2025-12-20 02:18:42 +00:00
chore: revert small buffer (#5654)
* Revert "perf: use libsmall in libtransmission, pt 3 (#5653)" This reverts commit3b03494580. * Revert "perf: use small in libtransmission (#5650)" This reverts commit559f6f0332.
This commit is contained in:
@@ -50,7 +50,6 @@ using tau_connection_t = uint64_t;
|
|||||||
using tau_transaction_t = uint32_t;
|
using tau_transaction_t = uint32_t;
|
||||||
|
|
||||||
using InBuf = libtransmission::BufferReader<std::byte>;
|
using InBuf = libtransmission::BufferReader<std::byte>;
|
||||||
using PayloadBuffer = libtransmission::SmallBuffer<4096, std::byte>;
|
|
||||||
|
|
||||||
constexpr auto TauConnectionTtlSecs = time_t{ 45 };
|
constexpr auto TauConnectionTtlSecs = time_t{ 45 };
|
||||||
|
|
||||||
@@ -86,7 +85,7 @@ struct tau_scrape_request
|
|||||||
}
|
}
|
||||||
|
|
||||||
// build the payload
|
// build the payload
|
||||||
auto buf = PayloadBuffer{};
|
auto buf = libtransmission::Buffer{};
|
||||||
buf.add_uint32(TAU_ACTION_SCRAPE);
|
buf.add_uint32(TAU_ACTION_SCRAPE);
|
||||||
buf.add_uint32(transaction_id);
|
buf.add_uint32(transaction_id);
|
||||||
for (int i = 0; i < in.info_hash_count; ++i)
|
for (int i = 0; i < in.info_hash_count; ++i)
|
||||||
@@ -180,7 +179,7 @@ struct tau_announce_request
|
|||||||
response.info_hash = in.info_hash;
|
response.info_hash = in.info_hash;
|
||||||
|
|
||||||
// build the payload
|
// build the payload
|
||||||
auto buf = PayloadBuffer{};
|
auto buf = libtransmission::Buffer{};
|
||||||
buf.add_uint32(TAU_ACTION_ANNOUNCE);
|
buf.add_uint32(TAU_ACTION_ANNOUNCE);
|
||||||
buf.add_uint32(transaction_id);
|
buf.add_uint32(transaction_id);
|
||||||
buf.add(in.info_hash);
|
buf.add(in.info_hash);
|
||||||
@@ -375,7 +374,7 @@ struct tau_tracker
|
|||||||
this->connection_transaction_id = tau_transaction_new();
|
this->connection_transaction_id = tau_transaction_new();
|
||||||
logtrace(this->key, fmt::format("Trying to connect. Transaction ID is {}", this->connection_transaction_id));
|
logtrace(this->key, fmt::format("Trying to connect. Transaction ID is {}", this->connection_transaction_id));
|
||||||
|
|
||||||
auto buf = PayloadBuffer{};
|
auto buf = libtransmission::Buffer{};
|
||||||
buf.add_uint64(0x41727101980LL);
|
buf.add_uint64(0x41727101980LL);
|
||||||
buf.add_uint32(TAU_ACTION_CONNECT);
|
buf.add_uint32(TAU_ACTION_CONNECT);
|
||||||
buf.add_uint32(this->connection_transaction_id);
|
buf.add_uint32(this->connection_transaction_id);
|
||||||
@@ -463,7 +462,7 @@ private:
|
|||||||
{
|
{
|
||||||
if (this->connecting_at != 0 && this->connecting_at + ConnectionRequestTtl < now)
|
if (this->connecting_at != 0 && this->connecting_at + ConnectionRequestTtl < now)
|
||||||
{
|
{
|
||||||
auto empty_buf = PayloadBuffer{};
|
auto empty_buf = libtransmission::Buffer{};
|
||||||
on_connection_response(TAU_ACTION_ERROR, empty_buf);
|
on_connection_response(TAU_ACTION_ERROR, empty_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -536,7 +535,7 @@ private:
|
|||||||
{
|
{
|
||||||
logdbg(this->key, fmt::format("sending request w/connection id {}", this->connection_id));
|
logdbg(this->key, fmt::format("sending request w/connection id {}", this->connection_id));
|
||||||
|
|
||||||
auto buf = PayloadBuffer{};
|
auto buf = libtransmission::Buffer{};
|
||||||
buf.add_uint64(this->connection_id);
|
buf.add_uint64(this->connection_id);
|
||||||
buf.add(payload, payload_len);
|
buf.add(payload, payload_len);
|
||||||
|
|
||||||
@@ -623,7 +622,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// extract the action_id and see if it makes sense
|
// extract the action_id and see if it makes sense
|
||||||
auto buf = PayloadBuffer{};
|
auto buf = libtransmission::Buffer{};
|
||||||
buf.add(msg, msglen);
|
buf.add(msg, msglen);
|
||||||
auto const action_id = static_cast<tau_action_t>(buf.to_uint32());
|
auto const action_id = static_cast<tau_action_t>(buf.to_uint32());
|
||||||
|
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ ReadState tr_handshake::read_yb(tr_peerIo* peer_io)
|
|||||||
|
|
||||||
/* now send these: HASH('req1', S), HASH('req2', SKEY) xor HASH('req3', S),
|
/* now send these: HASH('req1', S), HASH('req2', SKEY) xor HASH('req3', S),
|
||||||
* ENCRYPT(VC, crypto_provide, len(PadC), PadC, len(IA)), ENCRYPT(IA) */
|
* ENCRYPT(VC, crypto_provide, len(PadC), PadC, len(IA)), ENCRYPT(IA) */
|
||||||
auto outbuf = libtransmission::SmallBuffer<4096>{};
|
auto outbuf = libtransmission::Buffer{};
|
||||||
|
|
||||||
/* HASH('req1', S) */
|
/* HASH('req1', S) */
|
||||||
outbuf.add(tr_sha1::digest("req1"sv, dh_.secret()));
|
outbuf.add(tr_sha1::digest("req1"sv, dh_.secret()));
|
||||||
@@ -600,7 +600,7 @@ ReadState tr_handshake::read_ia(tr_peerIo* peer_io)
|
|||||||
auto const& info_hash = peer_io->torrent_hash();
|
auto const& info_hash = peer_io->torrent_hash();
|
||||||
TR_ASSERT_MSG(info_hash != tr_sha1_digest_t{}, "readIA requires an info_hash");
|
TR_ASSERT_MSG(info_hash != tr_sha1_digest_t{}, "readIA requires an info_hash");
|
||||||
peer_io->encrypt_init(peer_io->is_incoming(), dh_, info_hash);
|
peer_io->encrypt_init(peer_io->is_incoming(), dh_, info_hash);
|
||||||
auto outbuf = libtransmission::SmallBuffer<4096>{};
|
auto outbuf = libtransmission::Buffer{};
|
||||||
|
|
||||||
// send VC
|
// send VC
|
||||||
tr_logAddTraceHand(this, "sending vc");
|
tr_logAddTraceHand(this, "sending vc");
|
||||||
|
|||||||
@@ -419,7 +419,7 @@ size_t tr_peerIo::try_read(size_t max)
|
|||||||
|
|
||||||
auto& buf = inbuf_;
|
auto& buf = inbuf_;
|
||||||
tr_error* error = nullptr;
|
tr_error* error = nullptr;
|
||||||
auto const n_read = socket_.try_read(buf, max, std::empty(buf), &error);
|
auto const n_read = socket_.try_read(buf, max, &error);
|
||||||
set_enabled(Dir, error == nullptr || canRetryFromError(error->code));
|
set_enabled(Dir, error == nullptr || canRetryFromError(error->code));
|
||||||
|
|
||||||
if (error != nullptr)
|
if (error != nullptr)
|
||||||
|
|||||||
@@ -15,12 +15,9 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <utility> // std::pair
|
#include <utility> // std::pair
|
||||||
|
|
||||||
#include <event2/util.h> // for evutil_socket_t
|
|
||||||
|
|
||||||
#include "transmission.h"
|
#include "transmission.h"
|
||||||
|
|
||||||
#include "bandwidth.h"
|
#include "bandwidth.h"
|
||||||
#include "block-info.h"
|
|
||||||
#include "net.h" // tr_address
|
#include "net.h" // tr_address
|
||||||
#include "peer-mse.h"
|
#include "peer-mse.h"
|
||||||
#include "peer-socket.h"
|
#include "peer-socket.h"
|
||||||
@@ -292,17 +289,8 @@ public:
|
|||||||
static void utp_init(struct_utp_context* ctx);
|
static void utp_init(struct_utp_context* ctx);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// size of the buffer we use to hold incoming & outgoing messages
|
|
||||||
static constexpr auto InitialBufferSize = tr_block_info::BlockSize + sizeof(uint8_t) + sizeof(uint32_t) + sizeof(uint32_t);
|
|
||||||
|
|
||||||
// our target socket receive buffer size
|
|
||||||
static constexpr auto RcvBuf = size_t{ 256 * 1024 };
|
static constexpr auto RcvBuf = size_t{ 256 * 1024 };
|
||||||
|
|
||||||
// start with a buffer size large enough to hold a BT block message,
|
|
||||||
// but avoid repeated reallocs by scaling up very quickly (5X) when
|
|
||||||
// we need more capacity.
|
|
||||||
using Buffer = libtransmission::SmallBuffer<InitialBufferSize, std::byte, std::ratio<5, 1>>;
|
|
||||||
|
|
||||||
friend class libtransmission::test::HandshakeTest;
|
friend class libtransmission::test::HandshakeTest;
|
||||||
|
|
||||||
[[nodiscard]] constexpr auto is_seed() const noexcept
|
[[nodiscard]] constexpr auto is_seed() const noexcept
|
||||||
@@ -354,8 +342,8 @@ private:
|
|||||||
|
|
||||||
tr_sha1_digest_t info_hash_;
|
tr_sha1_digest_t info_hash_;
|
||||||
|
|
||||||
Buffer inbuf_;
|
libtransmission::Buffer inbuf_;
|
||||||
Buffer outbuf_;
|
libtransmission::Buffer outbuf_;
|
||||||
|
|
||||||
tr_session* const session_;
|
tr_session* const session_;
|
||||||
|
|
||||||
|
|||||||
@@ -11,16 +11,53 @@
|
|||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <small/map.hpp>
|
|
||||||
|
|
||||||
#define LIBTRANSMISSION_PEER_MODULE
|
#define LIBTRANSMISSION_PEER_MODULE
|
||||||
|
|
||||||
#include "libtransmission/transmission.h"
|
#include "libtransmission/transmission.h"
|
||||||
|
|
||||||
#include "libtransmission/peer-mgr-active-requests.h"
|
#include "libtransmission/peer-mgr-active-requests.h"
|
||||||
#include "libtransmission/peer-mgr-wishlist.h"
|
|
||||||
#include "libtransmission/tr-assert.h"
|
#include "libtransmission/tr-assert.h"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
struct peer_at
|
||||||
|
{
|
||||||
|
tr_peer* peer;
|
||||||
|
time_t when;
|
||||||
|
|
||||||
|
peer_at(tr_peer* p, time_t w)
|
||||||
|
: peer{ p }
|
||||||
|
, when{ w }
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] int compare(peer_at const& that) const // <=>
|
||||||
|
{
|
||||||
|
if (peer != that.peer)
|
||||||
|
{
|
||||||
|
return peer < that.peer ? -1 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(peer_at const& that) const
|
||||||
|
{
|
||||||
|
return compare(that) == 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PeerAtHash
|
||||||
|
{
|
||||||
|
std::size_t operator()(peer_at const& pa) const noexcept
|
||||||
|
{
|
||||||
|
return std::hash<tr_peer*>{}(pa.peer);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
class ActiveRequests::Impl
|
class ActiveRequests::Impl
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -60,7 +97,7 @@ public:
|
|||||||
|
|
||||||
std::unordered_map<tr_peer const*, size_t> count_;
|
std::unordered_map<tr_peer const*, size_t> count_;
|
||||||
|
|
||||||
std::unordered_map<tr_block_index_t, small::map<tr_peer const*, time_t, Wishlist::EndgameMaxPeers>> blocks_;
|
std::unordered_map<tr_block_index_t, std::unordered_set<peer_at, PeerAtHash>> blocks_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_t size_ = 0;
|
size_t size_ = 0;
|
||||||
@@ -89,7 +126,8 @@ bool ActiveRequests::add(tr_block_index_t block, tr_peer* peer, time_t when)
|
|||||||
bool ActiveRequests::remove(tr_block_index_t block, tr_peer const* peer)
|
bool ActiveRequests::remove(tr_block_index_t block, tr_peer const* peer)
|
||||||
{
|
{
|
||||||
auto const it = impl_->blocks_.find(block);
|
auto const it = impl_->blocks_.find(block);
|
||||||
auto const removed = it != std::end(impl_->blocks_) && it->second.erase(peer) != 0;
|
auto const key = peer_at{ const_cast<tr_peer*>(peer), 0 };
|
||||||
|
auto const removed = it != std::end(impl_->blocks_) && it->second.erase(key) != 0;
|
||||||
|
|
||||||
if (removed)
|
if (removed)
|
||||||
{
|
{
|
||||||
@@ -110,9 +148,10 @@ std::vector<tr_block_index_t> ActiveRequests::remove(tr_peer const* peer)
|
|||||||
auto removed = std::vector<tr_block_index_t>{};
|
auto removed = std::vector<tr_block_index_t>{};
|
||||||
removed.reserve(impl_->blocks_.size());
|
removed.reserve(impl_->blocks_.size());
|
||||||
|
|
||||||
|
auto const key = peer_at{ const_cast<tr_peer*>(peer), 0 };
|
||||||
for (auto const& [block, peers_at] : impl_->blocks_)
|
for (auto const& [block, peers_at] : impl_->blocks_)
|
||||||
{
|
{
|
||||||
if (peers_at.count(peer) != 0U)
|
if (peers_at.count(key) != 0U)
|
||||||
{
|
{
|
||||||
removed.push_back(block);
|
removed.push_back(block);
|
||||||
}
|
}
|
||||||
@@ -139,7 +178,7 @@ std::vector<tr_peer*> ActiveRequests::remove(tr_block_index_t block)
|
|||||||
std::begin(it->second),
|
std::begin(it->second),
|
||||||
std::end(it->second),
|
std::end(it->second),
|
||||||
std::begin(removed),
|
std::begin(removed),
|
||||||
[](auto const& iter) { return const_cast<tr_peer*>(iter.first); });
|
[](auto const& sent) { return sent.peer; });
|
||||||
impl_->blocks_.erase(block);
|
impl_->blocks_.erase(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,7 +194,7 @@ std::vector<tr_peer*> ActiveRequests::remove(tr_block_index_t block)
|
|||||||
bool ActiveRequests::has(tr_block_index_t block, tr_peer const* peer) const
|
bool ActiveRequests::has(tr_block_index_t block, tr_peer const* peer) const
|
||||||
{
|
{
|
||||||
auto const it = impl_->blocks_.find(block);
|
auto const it = impl_->blocks_.find(block);
|
||||||
return it != std::end(impl_->blocks_) && (it->second.count(peer) != 0U);
|
return it != std::end(impl_->blocks_) && (it->second.count(peer_at{ const_cast<tr_peer*>(peer), 0 }) != 0U);
|
||||||
}
|
}
|
||||||
|
|
||||||
// count how many peers we're asking for `block`
|
// count how many peers we're asking for `block`
|
||||||
@@ -186,11 +225,11 @@ std::vector<std::pair<tr_block_index_t, tr_peer*>> ActiveRequests::sentBefore(ti
|
|||||||
|
|
||||||
for (auto const& [block, peers_at] : impl_->blocks_)
|
for (auto const& [block, peers_at] : impl_->blocks_)
|
||||||
{
|
{
|
||||||
for (auto const& [peer, sent_at] : peers_at)
|
for (auto const& sent : peers_at)
|
||||||
{
|
{
|
||||||
if (sent_at < when)
|
if (sent.when < when)
|
||||||
{
|
{
|
||||||
sent_before.emplace_back(block, const_cast<tr_peer*>(peer));
|
sent_before.emplace_back(block, sent.peer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,8 +22,6 @@
|
|||||||
class Wishlist
|
class Wishlist
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static auto constexpr EndgameMaxPeers = size_t{ 2U };
|
|
||||||
|
|
||||||
struct Mediator
|
struct Mediator
|
||||||
{
|
{
|
||||||
[[nodiscard]] virtual bool clientCanRequestBlock(tr_block_index_t block) const = 0;
|
[[nodiscard]] virtual bool clientCanRequestBlock(tr_block_index_t block) const = 0;
|
||||||
|
|||||||
@@ -47,10 +47,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
using namespace std::literals;
|
using namespace std::literals;
|
||||||
|
using MessageBuffer = libtransmission::Buffer;
|
||||||
// sized to hold a piece message
|
|
||||||
using MessageBuffer = libtransmission::
|
|
||||||
SmallBuffer<sizeof(uint8_t) + sizeof(uint32_t) * 2U + tr_block_info::BlockSize, std::byte>;
|
|
||||||
using MessageReader = libtransmission::BufferReader<std::byte>;
|
using MessageReader = libtransmission::BufferReader<std::byte>;
|
||||||
using MessageWriter = libtransmission::BufferWriter<std::byte>;
|
using MessageWriter = libtransmission::BufferWriter<std::byte>;
|
||||||
|
|
||||||
@@ -1387,9 +1384,9 @@ ReadResult read_piece_data(tr_peerMsgsImpl* msgs, MessageReader& payload)
|
|||||||
return { READ_ERR, len };
|
return { READ_ERR, len };
|
||||||
}
|
}
|
||||||
|
|
||||||
logtrace(msgs, fmt::format("got {:d} bytes for req {:d}:{:d}->{:d}", len, piece, offset, len));
|
msgs->publish(tr_peer_event::GotPieceData(len));
|
||||||
|
|
||||||
if (loc.block_offset == 0U && len == block_size) // simple case: got the full block in one message
|
if (loc.block_offset == 0U && len == block_size) // simple case: one message has entire block
|
||||||
{
|
{
|
||||||
auto buf = std::make_unique<Cache::BlockData>(block_size);
|
auto buf = std::make_unique<Cache::BlockData>(block_size);
|
||||||
payload.to_buf(std::data(*buf), len);
|
payload.to_buf(std::data(*buf), len);
|
||||||
@@ -1803,7 +1800,8 @@ ReadState canRead(tr_peerIo* io, void* vmsgs, size_t* piece)
|
|||||||
current_message_len.reset();
|
current_message_len.reset();
|
||||||
auto const message_type = *current_message_type;
|
auto const message_type = *current_message_type;
|
||||||
current_message_type.reset();
|
current_message_type.reset();
|
||||||
auto payload = MessageBuffer{ std::data(current_payload), std::size(current_payload) };
|
auto payload = MessageBuffer{};
|
||||||
|
std::swap(payload, current_payload);
|
||||||
|
|
||||||
auto const [read_state, n_piece_bytes_read] = process_peer_message(msgs, message_type, payload);
|
auto const [read_state, n_piece_bytes_read] = process_peer_message(msgs, message_type, payload);
|
||||||
*piece = n_piece_bytes_read;
|
*piece = n_piece_bytes_read;
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ void tr_peer_socket::close()
|
|||||||
handle = {};
|
handle = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t tr_peer_socket::try_write(OutBuf& buf, size_t max, tr_error** error) const
|
size_t tr_peer_socket::try_write(Buffer& buf, size_t max, tr_error** error) const
|
||||||
{
|
{
|
||||||
if (max == size_t{})
|
if (max == size_t{})
|
||||||
{
|
{
|
||||||
@@ -107,7 +107,7 @@ size_t tr_peer_socket::try_write(OutBuf& buf, size_t max, tr_error** error) cons
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t tr_peer_socket::try_read(InBuf& buf, size_t max, [[maybe_unused]] bool is_buf_empty, tr_error** error) const
|
size_t tr_peer_socket::try_read(Buffer& buf, size_t max, tr_error** error) const
|
||||||
{
|
{
|
||||||
if (max == size_t{})
|
if (max == size_t{})
|
||||||
{
|
{
|
||||||
@@ -123,7 +123,7 @@ size_t tr_peer_socket::try_read(InBuf& buf, size_t max, [[maybe_unused]] bool is
|
|||||||
// utp_read_drained() notifies libutp that this read buffer is empty.
|
// utp_read_drained() notifies libutp that this read buffer is empty.
|
||||||
// It opens up the congestion window by sending an ACK (soonish) if
|
// It opens up the congestion window by sending an ACK (soonish) if
|
||||||
// one was not going to be sent.
|
// one was not going to be sent.
|
||||||
if (is_utp() && is_buf_empty)
|
if (is_utp() && std::empty(buf))
|
||||||
{
|
{
|
||||||
utp_read_drained(handle.utp);
|
utp_read_drained(handle.utp);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ struct tr_session;
|
|||||||
class tr_peer_socket
|
class tr_peer_socket
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using Buffer = libtransmission::Buffer;
|
||||||
|
|
||||||
tr_peer_socket() = default;
|
tr_peer_socket() = default;
|
||||||
tr_peer_socket(tr_session const* session, tr_address const& address, tr_port port, tr_socket_t sock);
|
tr_peer_socket(tr_session const* session, tr_address const& address, tr_port port, tr_socket_t sock);
|
||||||
tr_peer_socket(tr_address const& address, tr_port port, struct UTPSocket* const sock);
|
tr_peer_socket(tr_address const& address, tr_port port, struct UTPSocket* const sock);
|
||||||
@@ -54,11 +56,8 @@ public:
|
|||||||
}
|
}
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
using InBuf = libtransmission::BufferWriter<std::byte>;
|
size_t try_write(Buffer& buf, size_t max, tr_error** error) const;
|
||||||
using OutBuf = libtransmission::BufferReader<std::byte>;
|
size_t try_read(Buffer& buf, size_t max, tr_error** error) const;
|
||||||
|
|
||||||
size_t try_read(InBuf& buf, size_t max, bool is_buf_empty, tr_error** error) const;
|
|
||||||
size_t try_write(OutBuf& buf, size_t max, tr_error** error) const;
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr std::pair<tr_address, tr_port> socketAddress() const noexcept
|
[[nodiscard]] constexpr std::pair<tr_address, tr_port> socketAddress() const noexcept
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
#include <small/vector.hpp>
|
#include <event2/buffer.h>
|
||||||
|
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "net.h" // tr_socket_t
|
#include "net.h" // tr_socket_t
|
||||||
@@ -123,11 +123,6 @@ public:
|
|||||||
tr_error_set(error, err, tr_net_strerror(err));
|
tr_error_set(error, err, tr_net_strerror(err));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear()
|
|
||||||
{
|
|
||||||
drain(size());
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename value_type>
|
template<typename value_type>
|
||||||
@@ -203,11 +198,6 @@ public:
|
|||||||
|
|
||||||
size_t add_socket(tr_socket_t sockfd, size_t n_bytes, tr_error** error = nullptr)
|
size_t add_socket(tr_socket_t sockfd, size_t n_bytes, tr_error** error = nullptr)
|
||||||
{
|
{
|
||||||
if (n_bytes == 0U)
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
auto const [buf, buflen] = reserve_space(n_bytes);
|
auto const [buf, buflen] = reserve_space(n_bytes);
|
||||||
auto const n_read = recv(sockfd, reinterpret_cast<char*>(buf), std::min(n_bytes, buflen), 0);
|
auto const n_read = recv(sockfd, reinterpret_cast<char*>(buf), std::min(n_bytes, buflen), 0);
|
||||||
auto const err = sockerrno;
|
auto const err = sockerrno;
|
||||||
@@ -233,64 +223,61 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<size_t N, typename value_type = std::byte, typename GrowthFactor = std::ratio<3, 2>>
|
class Buffer final
|
||||||
class SmallBuffer final
|
: public BufferReader<std::byte>
|
||||||
: public BufferReader<value_type>
|
, public BufferWriter<std::byte>
|
||||||
, public BufferWriter<value_type>
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SmallBuffer() = default;
|
using value_type = std::byte;
|
||||||
SmallBuffer(SmallBuffer&&) = delete;
|
|
||||||
SmallBuffer& operator=(SmallBuffer&&) = delete;
|
|
||||||
SmallBuffer(SmallBuffer const&) = delete;
|
|
||||||
SmallBuffer& operator=(SmallBuffer const&) = delete;
|
|
||||||
|
|
||||||
explicit SmallBuffer(void const* const data, size_t n_bytes)
|
Buffer() = default;
|
||||||
{
|
Buffer(Buffer&&) = default;
|
||||||
BufferWriter<value_type>::add(data, n_bytes);
|
Buffer(Buffer const&) = delete;
|
||||||
}
|
Buffer& operator=(Buffer&&) = default;
|
||||||
|
Buffer& operator=(Buffer const&) = delete;
|
||||||
|
|
||||||
template<typename ContiguousContainer>
|
template<typename T>
|
||||||
explicit SmallBuffer(ContiguousContainer const& data)
|
explicit Buffer(T const& data)
|
||||||
: SmallBuffer{ std::data(data), std::size(data) }
|
|
||||||
{
|
{
|
||||||
|
add(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] size_t size() const noexcept override
|
[[nodiscard]] size_t size() const noexcept override
|
||||||
{
|
{
|
||||||
return end_pos_ - begin_pos_;
|
return evbuffer_get_length(buf_.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] value_type const* data() const override
|
[[nodiscard]] value_type const* data() const override
|
||||||
{
|
{
|
||||||
return std::data(buf_) + begin_pos_;
|
return reinterpret_cast<value_type const*>(evbuffer_pullup(buf_.get(), -1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void drain(size_t n_bytes) override
|
void drain(size_t n_bytes) override
|
||||||
{
|
{
|
||||||
begin_pos_ += std::min(n_bytes, size());
|
evbuffer_drain(buf_.get(), n_bytes);
|
||||||
|
|
||||||
if (begin_pos_ == end_pos_)
|
|
||||||
{
|
|
||||||
begin_pos_ = end_pos_ = 0U;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::pair<value_type*, size_t> reserve_space(size_t n_bytes) override
|
[[nodiscard]] std::pair<value_type*, size_t> reserve_space(size_t n_bytes) override
|
||||||
{
|
{
|
||||||
buf_.resize(end_pos_ + n_bytes);
|
auto iov = evbuffer_iovec{};
|
||||||
return { &buf_[end_pos_], n_bytes };
|
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) };
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void commit_space(size_t n_bytes) override
|
void commit_space(size_t n_bytes) override
|
||||||
{
|
{
|
||||||
end_pos_ += n_bytes;
|
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:
|
private:
|
||||||
small::vector<value_type, N, std::allocator<value_type>, std::true_type, size_t, GrowthFactor> buf_ = {};
|
evhelpers::evbuffer_unique_ptr buf_{ evbuffer_new() };
|
||||||
size_t begin_pos_ = {};
|
std::optional<evbuffer_iovec> reserved_space_;
|
||||||
size_t end_pos_ = {};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace libtransmission
|
} // namespace libtransmission
|
||||||
|
|||||||
@@ -277,7 +277,7 @@ namespace
|
|||||||
{
|
{
|
||||||
namespace to_string_helpers
|
namespace to_string_helpers
|
||||||
{
|
{
|
||||||
using OutBuf = libtransmission::SmallBuffer<1024 * 16, std::byte>;
|
using OutBuf = libtransmission::Buffer;
|
||||||
|
|
||||||
void saveIntFunc(tr_variant const* val, void* vout)
|
void saveIntFunc(tr_variant const* val, void* vout)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -442,7 +442,7 @@ struct JsonWalk
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::deque<ParentState> parents;
|
std::deque<ParentState> parents;
|
||||||
libtransmission::SmallBuffer<1024 * 16> out;
|
libtransmission::Buffer out;
|
||||||
bool doIndent;
|
bool doIndent;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -14,8 +14,6 @@
|
|||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include <event2/buffer.h>
|
|
||||||
|
|
||||||
struct evbuffer;
|
struct evbuffer;
|
||||||
|
|
||||||
class tr_web
|
class tr_web
|
||||||
|
|||||||
@@ -25,8 +25,6 @@
|
|||||||
|
|
||||||
using namespace std::literals;
|
using namespace std::literals;
|
||||||
|
|
||||||
using Buffer = libtransmission::SmallBuffer<1024>;
|
|
||||||
|
|
||||||
class AnnouncerUdpTest : public ::testing::Test
|
class AnnouncerUdpTest : public ::testing::Test
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
@@ -113,7 +111,7 @@ protected:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] static uint32_t parseConnectionRequest(Buffer& buf)
|
[[nodiscard]] static uint32_t parseConnectionRequest(libtransmission::Buffer& buf)
|
||||||
{
|
{
|
||||||
EXPECT_EQ(ProtocolId, buf.to_uint64());
|
EXPECT_EQ(ProtocolId, buf.to_uint64());
|
||||||
EXPECT_EQ(ConnectAction, buf.to_uint32());
|
EXPECT_EQ(ConnectAction, buf.to_uint32());
|
||||||
@@ -149,7 +147,7 @@ protected:
|
|||||||
return std::make_pair(buildScrapeRequestFromResponse(response), response);
|
return std::make_pair(buildScrapeRequestFromResponse(response), response);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] static auto parseScrapeRequest(Buffer& buf, uint64_t expected_connection_id)
|
[[nodiscard]] static auto parseScrapeRequest(libtransmission::Buffer& buf, uint64_t expected_connection_id)
|
||||||
{
|
{
|
||||||
EXPECT_EQ(expected_connection_id, buf.to_uint64());
|
EXPECT_EQ(expected_connection_id, buf.to_uint64());
|
||||||
EXPECT_EQ(ScrapeAction, buf.to_uint32());
|
EXPECT_EQ(ScrapeAction, buf.to_uint32());
|
||||||
@@ -164,17 +162,17 @@ protected:
|
|||||||
return std::make_pair(transaction_id, info_hashes);
|
return std::make_pair(transaction_id, info_hashes);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void waitForAnnouncerToSendMessage(MockMediator& mediator, Buffer& setme)
|
[[nodiscard]] static auto waitForAnnouncerToSendMessage(MockMediator& mediator)
|
||||||
{
|
{
|
||||||
libtransmission::test::waitFor(mediator.eventBase(), [&mediator]() { return !std::empty(mediator.sent_); });
|
libtransmission::test::waitFor(mediator.eventBase(), [&mediator]() { return !std::empty(mediator.sent_); });
|
||||||
setme.clear();
|
auto buf = libtransmission::Buffer(mediator.sent_.back().buf_);
|
||||||
setme.add(mediator.sent_.back().buf_);
|
|
||||||
mediator.sent_.pop_back();
|
mediator.sent_.pop_back();
|
||||||
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] static bool sendError(tr_announcer_udp& announcer, uint32_t transaction_id, std::string_view errmsg)
|
[[nodiscard]] static bool sendError(tr_announcer_udp& announcer, uint32_t transaction_id, std::string_view errmsg)
|
||||||
{
|
{
|
||||||
auto buf = Buffer{};
|
auto buf = libtransmission::Buffer{};
|
||||||
buf.add_uint32(ErrorAction);
|
buf.add_uint32(ErrorAction);
|
||||||
buf.add_uint32(transaction_id);
|
buf.add_uint32(transaction_id);
|
||||||
buf.add(errmsg);
|
buf.add(errmsg);
|
||||||
@@ -189,7 +187,7 @@ protected:
|
|||||||
[[nodiscard]] static auto sendConnectionResponse(tr_announcer_udp& announcer, uint32_t transaction_id)
|
[[nodiscard]] static auto sendConnectionResponse(tr_announcer_udp& announcer, uint32_t transaction_id)
|
||||||
{
|
{
|
||||||
auto const connection_id = tr_rand_obj<uint64_t>();
|
auto const connection_id = tr_rand_obj<uint64_t>();
|
||||||
auto buf = Buffer{};
|
auto buf = libtransmission::Buffer{};
|
||||||
buf.add_uint32(ConnectAction);
|
buf.add_uint32(ConnectAction);
|
||||||
buf.add_uint32(transaction_id);
|
buf.add_uint32(transaction_id);
|
||||||
buf.add_uint64(connection_id);
|
buf.add_uint64(connection_id);
|
||||||
@@ -252,7 +250,7 @@ protected:
|
|||||||
EXPECT_EQ(actual.external_ip, expected.external_ip);
|
EXPECT_EQ(actual.external_ip, expected.external_ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] static auto parseAnnounceRequest(Buffer& buf, uint64_t connection_id)
|
[[nodiscard]] static auto parseAnnounceRequest(libtransmission::Buffer& buf, uint64_t connection_id)
|
||||||
{
|
{
|
||||||
auto req = UdpAnnounceReq{};
|
auto req = UdpAnnounceReq{};
|
||||||
req.connection_id = buf.to_uint64();
|
req.connection_id = buf.to_uint64();
|
||||||
@@ -315,8 +313,7 @@ TEST_F(AnnouncerUdpTest, canScrape)
|
|||||||
|
|
||||||
// The announcer should have sent a UDP connection request.
|
// The announcer should have sent a UDP connection request.
|
||||||
// Inspect that request for validity.
|
// Inspect that request for validity.
|
||||||
auto sent = Buffer{};
|
auto sent = waitForAnnouncerToSendMessage(mediator);
|
||||||
waitForAnnouncerToSendMessage(mediator, sent);
|
|
||||||
auto connect_transaction_id = parseConnectionRequest(sent);
|
auto connect_transaction_id = parseConnectionRequest(sent);
|
||||||
|
|
||||||
// Have the tracker respond to the request
|
// Have the tracker respond to the request
|
||||||
@@ -324,12 +321,12 @@ TEST_F(AnnouncerUdpTest, canScrape)
|
|||||||
|
|
||||||
// The announcer should have sent a UDP scrape request.
|
// The announcer should have sent a UDP scrape request.
|
||||||
// Inspect that request for validity.
|
// Inspect that request for validity.
|
||||||
waitForAnnouncerToSendMessage(mediator, sent);
|
sent = waitForAnnouncerToSendMessage(mediator);
|
||||||
auto [scrape_transaction_id, info_hashes] = parseScrapeRequest(sent, connection_id);
|
auto [scrape_transaction_id, info_hashes] = parseScrapeRequest(sent, connection_id);
|
||||||
expectEqual(request, info_hashes);
|
expectEqual(request, info_hashes);
|
||||||
|
|
||||||
// Have the tracker respond to the request
|
// Have the tracker respond to the request
|
||||||
auto buf = Buffer{};
|
auto buf = libtransmission::Buffer{};
|
||||||
buf.add_uint32(ScrapeAction);
|
buf.add_uint32(ScrapeAction);
|
||||||
buf.add_uint32(scrape_transaction_id);
|
buf.add_uint32(scrape_transaction_id);
|
||||||
buf.add_uint32(expected_response.rows[0].seeders);
|
buf.add_uint32(expected_response.rows[0].seeders);
|
||||||
@@ -353,7 +350,7 @@ TEST_F(AnnouncerUdpTest, canScrape)
|
|||||||
|
|
||||||
// The announcer should have sent a UDP connection request.
|
// The announcer should have sent a UDP connection request.
|
||||||
// Inspect that request for validity.
|
// Inspect that request for validity.
|
||||||
waitForAnnouncerToSendMessage(mediator, sent);
|
sent = waitForAnnouncerToSendMessage(mediator);
|
||||||
std::tie(scrape_transaction_id, info_hashes) = parseScrapeRequest(sent, connection_id);
|
std::tie(scrape_transaction_id, info_hashes) = parseScrapeRequest(sent, connection_id);
|
||||||
expectEqual(request, info_hashes);
|
expectEqual(request, info_hashes);
|
||||||
}
|
}
|
||||||
@@ -371,8 +368,7 @@ TEST_F(AnnouncerUdpTest, canDestructCleanlyEvenWhenBusy)
|
|||||||
|
|
||||||
// The announcer should have sent a UDP connection request.
|
// The announcer should have sent a UDP connection request.
|
||||||
// Inspect that request for validity.
|
// Inspect that request for validity.
|
||||||
auto sent = Buffer{};
|
auto sent = waitForAnnouncerToSendMessage(mediator);
|
||||||
waitForAnnouncerToSendMessage(mediator, sent);
|
|
||||||
auto const connect_transaction_id = parseConnectionRequest(sent);
|
auto const connect_transaction_id = parseConnectionRequest(sent);
|
||||||
EXPECT_NE(0U, connect_transaction_id);
|
EXPECT_NE(0U, connect_transaction_id);
|
||||||
|
|
||||||
@@ -400,19 +396,18 @@ TEST_F(AnnouncerUdpTest, canMultiScrape)
|
|||||||
announcer->scrape(request, [&response](tr_scrape_response const& resp) { response = resp; });
|
announcer->scrape(request, [&response](tr_scrape_response const& resp) { response = resp; });
|
||||||
|
|
||||||
// Announcer will request a connection. Verify and grant the request
|
// Announcer will request a connection. Verify and grant the request
|
||||||
auto sent = Buffer{};
|
auto sent = waitForAnnouncerToSendMessage(mediator);
|
||||||
waitForAnnouncerToSendMessage(mediator, sent);
|
|
||||||
auto connect_transaction_id = parseConnectionRequest(sent);
|
auto connect_transaction_id = parseConnectionRequest(sent);
|
||||||
auto const connection_id = sendConnectionResponse(*announcer, connect_transaction_id);
|
auto const connection_id = sendConnectionResponse(*announcer, connect_transaction_id);
|
||||||
|
|
||||||
// The announcer should have sent a UDP scrape request.
|
// The announcer should have sent a UDP scrape request.
|
||||||
// Inspect that request for validity.
|
// Inspect that request for validity.
|
||||||
waitForAnnouncerToSendMessage(mediator, sent);
|
sent = waitForAnnouncerToSendMessage(mediator);
|
||||||
auto [scrape_transaction_id, info_hashes] = parseScrapeRequest(sent, connection_id);
|
auto [scrape_transaction_id, info_hashes] = parseScrapeRequest(sent, connection_id);
|
||||||
expectEqual(request, info_hashes);
|
expectEqual(request, info_hashes);
|
||||||
|
|
||||||
// Have the tracker respond to the request
|
// Have the tracker respond to the request
|
||||||
auto buf = Buffer{};
|
auto buf = libtransmission::Buffer{};
|
||||||
buf.add_uint32(ScrapeAction);
|
buf.add_uint32(ScrapeAction);
|
||||||
buf.add_uint32(scrape_transaction_id);
|
buf.add_uint32(scrape_transaction_id);
|
||||||
for (int i = 0; i < expected_response.row_count; ++i)
|
for (int i = 0; i < expected_response.row_count; ++i)
|
||||||
@@ -462,8 +457,7 @@ TEST_F(AnnouncerUdpTest, canHandleScrapeError)
|
|||||||
|
|
||||||
// The announcer should have sent a UDP connection request.
|
// The announcer should have sent a UDP connection request.
|
||||||
// Inspect that request for validity.
|
// Inspect that request for validity.
|
||||||
auto sent = Buffer{};
|
auto sent = waitForAnnouncerToSendMessage(mediator);
|
||||||
waitForAnnouncerToSendMessage(mediator, sent);
|
|
||||||
auto connect_transaction_id = parseConnectionRequest(sent);
|
auto connect_transaction_id = parseConnectionRequest(sent);
|
||||||
|
|
||||||
// Have the tracker respond to the request
|
// Have the tracker respond to the request
|
||||||
@@ -471,7 +465,7 @@ TEST_F(AnnouncerUdpTest, canHandleScrapeError)
|
|||||||
|
|
||||||
// The announcer should have sent a UDP scrape request.
|
// The announcer should have sent a UDP scrape request.
|
||||||
// Inspect that request for validity.
|
// Inspect that request for validity.
|
||||||
waitForAnnouncerToSendMessage(mediator, sent);
|
sent = waitForAnnouncerToSendMessage(mediator);
|
||||||
auto const [scrape_transaction_id, info_hashes] = parseScrapeRequest(sent, connection_id);
|
auto const [scrape_transaction_id, info_hashes] = parseScrapeRequest(sent, connection_id);
|
||||||
|
|
||||||
// Have the tracker respond to the request with an "unable to scrape" error
|
// Have the tracker respond to the request with an "unable to scrape" error
|
||||||
@@ -512,8 +506,7 @@ TEST_F(AnnouncerUdpTest, canHandleConnectError)
|
|||||||
|
|
||||||
// The announcer should have sent a UDP connection request.
|
// The announcer should have sent a UDP connection request.
|
||||||
// Inspect that request for validity.
|
// Inspect that request for validity.
|
||||||
auto sent = Buffer{};
|
auto sent = waitForAnnouncerToSendMessage(mediator);
|
||||||
waitForAnnouncerToSendMessage(mediator, sent);
|
|
||||||
auto transaction_id = parseConnectionRequest(sent);
|
auto transaction_id = parseConnectionRequest(sent);
|
||||||
|
|
||||||
// Have the tracker respond to the request with an "unable to connect" error
|
// Have the tracker respond to the request with an "unable to connect" error
|
||||||
@@ -544,12 +537,11 @@ TEST_F(AnnouncerUdpTest, handleMessageReturnsFalseOnInvalidMessage)
|
|||||||
|
|
||||||
// The announcer should have sent a UDP connection request.
|
// The announcer should have sent a UDP connection request.
|
||||||
// Inspect that request for validity.
|
// Inspect that request for validity.
|
||||||
auto sent = Buffer{};
|
auto sent = waitForAnnouncerToSendMessage(mediator);
|
||||||
waitForAnnouncerToSendMessage(mediator, sent);
|
|
||||||
auto transaction_id = parseConnectionRequest(sent);
|
auto transaction_id = parseConnectionRequest(sent);
|
||||||
|
|
||||||
// send a connection response but with an *invalid* transaction id
|
// send a connection response but with an *invalid* transaction id
|
||||||
auto buf = Buffer{};
|
auto buf = libtransmission::Buffer{};
|
||||||
buf.add_uint32(ConnectAction);
|
buf.add_uint32(ConnectAction);
|
||||||
buf.add_uint32(transaction_id + 1);
|
buf.add_uint32(transaction_id + 1);
|
||||||
buf.add_uint64(tr_rand_obj<uint64_t>());
|
buf.add_uint64(tr_rand_obj<uint64_t>());
|
||||||
@@ -559,7 +551,7 @@ TEST_F(AnnouncerUdpTest, handleMessageReturnsFalseOnInvalidMessage)
|
|||||||
EXPECT_FALSE(announcer->handle_message(std::data(arr), response_size));
|
EXPECT_FALSE(announcer->handle_message(std::data(arr), response_size));
|
||||||
|
|
||||||
// send a connection response but with an *invalid* action
|
// send a connection response but with an *invalid* action
|
||||||
buf.clear();
|
buf = {};
|
||||||
buf.add_uint32(ScrapeAction);
|
buf.add_uint32(ScrapeAction);
|
||||||
buf.add_uint32(transaction_id);
|
buf.add_uint32(transaction_id);
|
||||||
buf.add_uint64(tr_rand_obj<uint64_t>());
|
buf.add_uint64(tr_rand_obj<uint64_t>());
|
||||||
@@ -625,19 +617,18 @@ TEST_F(AnnouncerUdpTest, canAnnounce)
|
|||||||
announcer->announce(request, [&response](tr_announce_response const& resp) { response = resp; });
|
announcer->announce(request, [&response](tr_announce_response const& resp) { response = resp; });
|
||||||
|
|
||||||
// Announcer will request a connection. Verify and grant the request
|
// Announcer will request a connection. Verify and grant the request
|
||||||
auto sent = Buffer{};
|
auto sent = waitForAnnouncerToSendMessage(mediator);
|
||||||
waitForAnnouncerToSendMessage(mediator, sent);
|
|
||||||
auto connect_transaction_id = parseConnectionRequest(sent);
|
auto connect_transaction_id = parseConnectionRequest(sent);
|
||||||
auto const connection_id = sendConnectionResponse(*announcer, connect_transaction_id);
|
auto const connection_id = sendConnectionResponse(*announcer, connect_transaction_id);
|
||||||
|
|
||||||
// The announcer should have sent a UDP announce request.
|
// The announcer should have sent a UDP announce request.
|
||||||
// Inspect that request for validity.
|
// Inspect that request for validity.
|
||||||
waitForAnnouncerToSendMessage(mediator, sent);
|
sent = waitForAnnouncerToSendMessage(mediator);
|
||||||
auto udp_ann_req = parseAnnounceRequest(sent, connection_id);
|
auto udp_ann_req = parseAnnounceRequest(sent, connection_id);
|
||||||
expectEqual(request, udp_ann_req);
|
expectEqual(request, udp_ann_req);
|
||||||
|
|
||||||
// Have the tracker respond to the request
|
// Have the tracker respond to the request
|
||||||
auto buf = Buffer{};
|
auto buf = libtransmission::Buffer{};
|
||||||
buf.add_uint32(AnnounceAction);
|
buf.add_uint32(AnnounceAction);
|
||||||
buf.add_uint32(udp_ann_req.transaction_id);
|
buf.add_uint32(udp_ann_req.transaction_id);
|
||||||
buf.add_uint32(expected_response.interval);
|
buf.add_uint32(expected_response.interval);
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
using BufferTest = ::testing::Test;
|
using BufferTest = ::testing::Test;
|
||||||
using namespace std::literals;
|
using namespace std::literals;
|
||||||
using Buffer = libtransmission::SmallBuffer<1024>;
|
using Buffer = libtransmission::Buffer;
|
||||||
|
|
||||||
TEST_F(BufferTest, startsWithInSingleSegment)
|
TEST_F(BufferTest, startsWithInSingleSegment)
|
||||||
{
|
{
|
||||||
@@ -62,6 +62,52 @@ TEST_F(BufferTest, startsWithInMultiSegment)
|
|||||||
EXPECT_TRUE(buf->starts_with("Hello, World!"sv));
|
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)
|
TEST_F(BufferTest, Numbers)
|
||||||
{
|
{
|
||||||
for (auto i = 0; i < 100; ++i)
|
for (auto i = 0; i < 100; ++i)
|
||||||
@@ -103,7 +149,9 @@ TEST_F(BufferTest, NonBufferWriter)
|
|||||||
auto constexpr Bang = "!"sv;
|
auto constexpr Bang = "!"sv;
|
||||||
|
|
||||||
auto out1 = Buffer{};
|
auto out1 = Buffer{};
|
||||||
auto out2 = libtransmission::SmallBuffer<1024>{};
|
|
||||||
|
auto out2_vec = std::vector<std::byte>{};
|
||||||
|
auto out2 = libtransmission::BufferWriter<std::vector<std::byte>, std::byte>{ &out2_vec };
|
||||||
|
|
||||||
out1.add_uint8(1);
|
out1.add_uint8(1);
|
||||||
out2.add_uint8(1);
|
out2.add_uint8(1);
|
||||||
@@ -124,7 +172,7 @@ TEST_F(BufferTest, NonBufferWriter)
|
|||||||
out2.add(Bang);
|
out2.add(Bang);
|
||||||
|
|
||||||
auto const result1 = out1.to_string_view();
|
auto const result1 = out1.to_string_view();
|
||||||
auto const result2 = out2.to_string();
|
auto const result2 = std::string_view{ reinterpret_cast<char const*>(std::data(out2_vec)), std::size(out2_vec) };
|
||||||
EXPECT_EQ(result1, result2);
|
EXPECT_EQ(result1, result2);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user