From e165ae5b60bac9dc26905b3a9d00b60481187f3e Mon Sep 17 00:00:00 2001 From: Florent Castelli Date: Sat, 19 Mar 2022 22:29:12 +0100 Subject: [PATCH] LibHTTP+LibTLS: Better HTTPS Socket EOF detection When the server doesn't signal the Content-Length or use a chunked mode, it may just terminate the connection after sending the data. The TLS sockets would then get stuck in a state with no data to read and not reach the disconnected state, making some requests hang. We know double check the EOF status of HTTP jobs after reading the payload to resolve requests properly and also mark the TLS sockets as EOF after processing all the data and the underlying TCP socket reaches EOF. Fixes #12866. --- Userland/Libraries/LibHTTP/Job.cpp | 8 ++++++++ Userland/Libraries/LibTLS/TLSv12.h | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Userland/Libraries/LibHTTP/Job.cpp b/Userland/Libraries/LibHTTP/Job.cpp index 1c0a901cf1..8a5ea6cc4a 100644 --- a/Userland/Libraries/LibHTTP/Job.cpp +++ b/Userland/Libraries/LibHTTP/Job.cpp @@ -504,6 +504,14 @@ void Job::on_socket_connected() break; } + // Check after reading all the buffered data if we have reached the end of stream + // for cases where the server didn't send a content length, chunked encoding but is + // directly closing the connection. + if (!m_content_length.has_value() && !m_current_chunk_remaining_size.has_value() && m_socket->is_eof()) { + finish_up(); + break; + } + if (m_current_chunk_remaining_size.has_value()) { auto size = m_current_chunk_remaining_size.value() - payload.size(); diff --git a/Userland/Libraries/LibTLS/TLSv12.h b/Userland/Libraries/LibTLS/TLSv12.h index a503c2e4a4..cad8f945ba 100644 --- a/Userland/Libraries/LibTLS/TLSv12.h +++ b/Userland/Libraries/LibTLS/TLSv12.h @@ -365,7 +365,7 @@ public: /// bytes written into the stream, or an errno in the case of failure. virtual ErrorOr write(ReadonlyBytes) override; - virtual bool is_eof() const override { return m_context.connection_finished && m_context.application_buffer.is_empty(); } + virtual bool is_eof() const override { return m_context.application_buffer.is_empty() && (m_context.connection_finished || underlying_stream().is_eof()); } virtual bool is_open() const override { return is_established(); } virtual void close() override;