mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 15:48:12 +00:00
LibTLS: Add segmentation to the application buffer to avoid memcpy churn
We were previously doing a *lot* of unnecessary memcpy work when transferring large files. This patch addresses the issue by introducing a simple segmented buffer with no additional work when appending new data, or when transfering out of the buffer.
This commit is contained in:
parent
40f87f0954
commit
27a294547d
3 changed files with 42 additions and 4 deletions
|
@ -498,7 +498,7 @@ ssize_t TLSv12::handle_message(ReadonlyBytes buffer)
|
||||||
} else {
|
} else {
|
||||||
dbgln_if(TLS_DEBUG, "application data message of size {}", plain.size());
|
dbgln_if(TLS_DEBUG, "application data message of size {}", plain.size());
|
||||||
|
|
||||||
if (m_context.application_buffer.try_append(plain.data(), plain.size()).is_error()) {
|
if (m_context.application_buffer.try_append(plain).is_error()) {
|
||||||
payload_res = (i8)Error::DecryptionFailed;
|
payload_res = (i8)Error::DecryptionFailed;
|
||||||
auto packet = build_alert(true, (u8)AlertDescription::DECRYPTION_FAILED_RESERVED);
|
auto packet = build_alert(true, (u8)AlertDescription::DECRYPTION_FAILED_RESERVED);
|
||||||
write_packet(packet);
|
write_packet(packet);
|
||||||
|
|
|
@ -27,8 +27,7 @@ ErrorOr<Bytes> TLSv12::read_some(Bytes bytes)
|
||||||
return Bytes {};
|
return Bytes {};
|
||||||
}
|
}
|
||||||
|
|
||||||
TRY(m_context.application_buffer.slice(0, size_to_read)).span().copy_to(bytes);
|
m_context.application_buffer.transfer(bytes, size_to_read);
|
||||||
m_context.application_buffer = TRY(m_context.application_buffer.slice(size_to_read, m_context.application_buffer.size() - size_to_read));
|
|
||||||
return Bytes { bytes.data(), size_to_read };
|
return Bytes { bytes.data(), size_to_read };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include "Certificate.h"
|
#include "Certificate.h"
|
||||||
#include <AK/IPv4Address.h>
|
#include <AK/IPv4Address.h>
|
||||||
|
#include <AK/Queue.h>
|
||||||
#include <AK/WeakPtr.h>
|
#include <AK/WeakPtr.h>
|
||||||
#include <LibCore/Notifier.h>
|
#include <LibCore/Notifier.h>
|
||||||
#include <LibCore/Socket.h>
|
#include <LibCore/Socket.h>
|
||||||
|
@ -197,6 +198,44 @@ struct Options {
|
||||||
#undef OPTION_WITH_DEFAULTS
|
#undef OPTION_WITH_DEFAULTS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SegmentedBuffer {
|
||||||
|
public:
|
||||||
|
[[nodiscard]] size_t size() const { return m_size; }
|
||||||
|
[[nodiscard]] bool is_empty() const { return m_size == 0; }
|
||||||
|
void transfer(Bytes dest, size_t size)
|
||||||
|
{
|
||||||
|
VERIFY(size <= dest.size());
|
||||||
|
size_t transferred = 0;
|
||||||
|
while (transferred < size) {
|
||||||
|
auto& buffer = m_buffers.head();
|
||||||
|
size_t to_transfer = min(buffer.size() - m_offset_into_current_buffer, size - transferred);
|
||||||
|
memcpy(dest.offset(transferred), buffer.data() + m_offset_into_current_buffer, to_transfer);
|
||||||
|
transferred += to_transfer;
|
||||||
|
m_offset_into_current_buffer += to_transfer;
|
||||||
|
if (m_offset_into_current_buffer >= buffer.size()) {
|
||||||
|
m_buffers.dequeue();
|
||||||
|
m_offset_into_current_buffer = 0;
|
||||||
|
}
|
||||||
|
m_size -= to_transfer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AK::ErrorOr<void> try_append(ReadonlyBytes data)
|
||||||
|
{
|
||||||
|
if (Checked<size_t>::addition_would_overflow(m_size, data.size()))
|
||||||
|
return AK::Error::from_errno(EOVERFLOW);
|
||||||
|
|
||||||
|
m_size += data.size();
|
||||||
|
m_buffers.enqueue(TRY(ByteBuffer::copy(data)));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t m_size { 0 };
|
||||||
|
Queue<ByteBuffer> m_buffers;
|
||||||
|
size_t m_offset_into_current_buffer { 0 };
|
||||||
|
};
|
||||||
|
|
||||||
struct Context {
|
struct Context {
|
||||||
bool verify_chain(StringView host) const;
|
bool verify_chain(StringView host) const;
|
||||||
bool verify_certificate_pair(Certificate const& subject, Certificate const& issuer) const;
|
bool verify_certificate_pair(Certificate const& subject, Certificate const& issuer) const;
|
||||||
|
@ -237,7 +276,7 @@ struct Context {
|
||||||
|
|
||||||
ByteBuffer tls_buffer;
|
ByteBuffer tls_buffer;
|
||||||
|
|
||||||
ByteBuffer application_buffer;
|
SegmentedBuffer application_buffer;
|
||||||
|
|
||||||
bool is_child { false };
|
bool is_child { false };
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue