diff --git a/Userland/Libraries/LibTLS/Record.cpp b/Userland/Libraries/LibTLS/Record.cpp index dc541fa238..0488dba089 100644 --- a/Userland/Libraries/LibTLS/Record.cpp +++ b/Userland/Libraries/LibTLS/Record.cpp @@ -37,24 +37,31 @@ void TLSv12::alert(AlertLevel level, AlertDescription code) void TLSv12::write_packet(ByteBuffer& packet) { + auto schedule_or_perform_flush = [&](bool immediate) { + if (m_context.connection_status > ConnectionStatus::Disconnected) { + if (!m_has_scheduled_write_flush && !immediate) { + dbgln_if(TLS_DEBUG, "Scheduling write of {}", m_context.tls_buffer.size()); + deferred_invoke([this] { write_into_socket(); }); + m_has_scheduled_write_flush = true; + } else { + // multiple packet are available, let's flush some out + dbgln_if(TLS_DEBUG, "Flushing scheduled write of {}", m_context.tls_buffer.size()); + write_into_socket(); + // the deferred invoke is still in place + m_has_scheduled_write_flush = true; + } + } + }; + // Record size limit is 18432 bytes, leave some headroom and flush at 16K. + if (m_context.tls_buffer.size() + packet.size() > 16 * KiB) + schedule_or_perform_flush(true); + auto ok = m_context.tls_buffer.try_append(packet.data(), packet.size()); if (!ok) { // Toooooo bad, drop the record on the ground. return; } - if (m_context.connection_status > ConnectionStatus::Disconnected) { - if (!m_has_scheduled_write_flush) { - dbgln_if(TLS_DEBUG, "Scheduling write of {}", m_context.tls_buffer.size()); - deferred_invoke([this] { write_into_socket(); }); - m_has_scheduled_write_flush = true; - } else { - // multiple packet are available, let's flush some out - dbgln_if(TLS_DEBUG, "Flushing scheduled write of {}", m_context.tls_buffer.size()); - write_into_socket(); - // the deferred invoke is still in place - m_has_scheduled_write_flush = true; - } - } + schedule_or_perform_flush(false); } void TLSv12::update_packet(ByteBuffer& packet) diff --git a/Userland/Libraries/LibTLS/Socket.cpp b/Userland/Libraries/LibTLS/Socket.cpp index 82fa714a38..3f3aa3c0e8 100644 --- a/Userland/Libraries/LibTLS/Socket.cpp +++ b/Userland/Libraries/LibTLS/Socket.cpp @@ -10,6 +10,11 @@ #include #include +// Each record can hold at most 18432 bytes, leaving some headroom and rounding down to +// a nice number gives us a maximum of 16 KiB for user-supplied application data, +// which will be sent as a single record containing a single ApplicationData message. +constexpr static size_t MaximumApplicationDataChunkSize = 16 * KiB; + namespace TLS { Optional TLSv12::read() @@ -67,12 +72,14 @@ bool TLSv12::write(ReadonlyBytes buffer) return false; } - PacketBuilder builder { MessageType::ApplicationData, m_context.options.version, buffer.size() }; - builder.append(buffer); - auto packet = builder.build(); + for (size_t offset = 0; offset < buffer.size(); offset += MaximumApplicationDataChunkSize) { + PacketBuilder builder { MessageType::ApplicationData, m_context.options.version, buffer.size() - offset }; + builder.append(buffer.slice(offset, min(buffer.size() - offset, MaximumApplicationDataChunkSize))); + auto packet = builder.build(); - update_packet(packet); - write_packet(packet); + update_packet(packet); + write_packet(packet); + } return true; }