Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf: avoid extra work in read_vc() #5527

Merged
merged 1 commit into from May 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
21 changes: 13 additions & 8 deletions libtransmission/handshake.cc
Expand Up @@ -240,27 +240,32 @@ ReadState tr_handshake::read_vc(tr_peerIo* peer_io)
auto const info_hash = peer_io->torrent_hash();
TR_ASSERT_MSG(info_hash != tr_sha1_digest_t{}, "readVC requires an info_hash");

// find the end of PadB by looking for `ENCRYPT(VC)`
auto needle = VC;
auto filter = tr_message_stream_encryption::Filter{};
filter.encryptInit(true, dh_, info_hash);
filter.encrypt(std::size(needle), std::data(needle));
// We need to find the end of PadB by looking for `ENCRYPT(VC)`,
// so calculate and cache the value of `ENCRYPT(VC)`.
if (!encrypted_vc_)
{
auto needle = VC;
auto filter = tr_message_stream_encryption::Filter{};
filter.encryptInit(true, dh_, info_hash);
filter.encrypt(std::size(needle), std::data(needle));
encrypted_vc_ = needle;
}

for (size_t i = 0; i < PadbMaxlen; ++i)
{
if (peer_io->read_buffer_size() < std::size(needle))
if (peer_io->read_buffer_size() < std::size(*encrypted_vc_))
{
tr_logAddTraceHand(this, "not enough bytes... returning read_more");
return READ_LATER;
}

if (peer_io->read_buffer_starts_with(needle))
if (peer_io->read_buffer_starts_with(*encrypted_vc_))
{
tr_logAddTraceHand(this, "got it!");
// We already know it's a match; now we just need to
// consume it from the read buffer.
peer_io->decrypt_init(peer_io->is_incoming(), dh_, info_hash);
peer_io->read_bytes(std::data(needle), std::size(needle));
peer_io->read_bytes(std::data(*encrypted_vc_), std::size(*encrypted_vc_));
set_state(tr_handshake::State::AwaitingCryptoSelect);
return READ_NOW;
}
Expand Down
5 changes: 5 additions & 0 deletions libtransmission/handshake.h
Expand Up @@ -249,6 +249,11 @@ class tr_handshake
using vc_t = std::array<std::byte, 8>;
static auto constexpr VC = vc_t{};

// Used when resynchronizing in read_vc(). This value is cached to avoid
// the cost of recomputing it. MSE spec: "Since the length of [PadB is]
// unknown, A will be able to resynchronize on ENCRYPT(VC)".
std::optional<vc_t> encrypted_vc_;

///

static constexpr auto DhPoolMaxSize = size_t{ 32 };
Expand Down