diff options
author | AnotherTest <ali.mpfard@gmail.com> | 2020-05-03 21:26:23 +0430 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-05-03 19:08:40 +0200 |
commit | b028a123b8c4f1a71e21fe5037a7cfe5f8cf2da4 (patch) | |
tree | ef448ed538e3fdf006f0d75cb370ad894f7b0a87 /Libraries | |
parent | 8aeccf4f024a1e29aac74f86ed072de1a89d94e6 (diff) | |
download | serenity-b028a123b8c4f1a71e21fe5037a7cfe5f8cf2da4.zip |
LibTLS: "Properly" handle the server dropping the connection
Contrary to popular belief, not every implementation of TLS follows the
specs.
Some of them just drop the connection without sending a proper
close_notify, and we should handle that gracefully.
Diffstat (limited to 'Libraries')
-rw-r--r-- | Libraries/LibHTTP/HttpsJob.cpp | 62 | ||||
-rw-r--r-- | Libraries/LibHTTP/HttpsJob.h | 2 | ||||
-rw-r--r-- | Libraries/LibTLS/Socket.cpp | 4 |
3 files changed, 40 insertions, 28 deletions
diff --git a/Libraries/LibHTTP/HttpsJob.cpp b/Libraries/LibHTTP/HttpsJob.cpp index aaa9944ab2..184b4f560c 100644 --- a/Libraries/LibHTTP/HttpsJob.cpp +++ b/Libraries/LibHTTP/HttpsJob.cpp @@ -156,37 +156,47 @@ void HttpsJob::on_socket_connected() } ASSERT(m_state == State::InBody); ASSERT(tls.can_read()); - auto payload = tls.read(64 * KB); - if (!payload) { - if (tls.eof()) - return finish_up(); - return deferred_invoke([this](auto&) { did_fail(Core::NetworkJob::Error::ProtocolFailed); }); - } - m_received_buffers.append(payload); - m_received_size += payload.size(); - auto content_length_header = m_headers.get("Content-Length"); - Optional<u32> content_length {}; + while (tls.can_read()) + read_body(tls); - if (content_length_header.has_value()) { - bool ok; - auto length = content_length_header.value().to_uint(ok); - if (ok) - content_length = length; - } + if (!tls.is_established()) + return finish_up(); + }; +} + +void HttpsJob::read_body(TLS::TLSv12& tls) +{ + auto payload = tls.read(64 * KB); + if (!payload) { + if (tls.eof()) + return finish_up(); + return deferred_invoke([this](auto&) { did_fail(Core::NetworkJob::Error::ProtocolFailed); }); + } + m_received_buffers.append(payload); + m_received_size += payload.size(); - // This needs to be synchronous - // FIXME: Somehow enforce that this should not modify anything - did_progress(content_length, m_received_size); + auto content_length_header = m_headers.get("Content-Length"); + Optional<u32> content_length {}; - if (content_length.has_value()) { - auto length = content_length.value(); - if (m_received_size >= length) { - m_received_size = length; - finish_up(); - } + if (content_length_header.has_value()) { + bool ok; + auto length = content_length_header.value().to_uint(ok); + if (ok) + content_length = length; + } + + // This needs to be synchronous + // FIXME: Somehow enforce that this should not modify anything + did_progress(content_length, m_received_size); + + if (content_length.has_value()) { + auto length = content_length.value(); + if (m_received_size >= length) { + m_received_size = length; + finish_up(); } - }; + } } void HttpsJob::finish_up() diff --git a/Libraries/LibHTTP/HttpsJob.h b/Libraries/LibHTTP/HttpsJob.h index b7a9ba3f38..6b5019c824 100644 --- a/Libraries/LibHTTP/HttpsJob.h +++ b/Libraries/LibHTTP/HttpsJob.h @@ -50,6 +50,7 @@ private: RefPtr<TLS::TLSv12> construct_socket() { return TLS::TLSv12::construct(this); } void on_socket_connected(); void finish_up(); + void read_body(TLS::TLSv12&); enum class State { InStatus, @@ -66,6 +67,7 @@ private: Vector<ByteBuffer> m_received_buffers; size_t m_received_size { 0 }; bool m_sent_data { false }; + bool m_queued_finish { false }; }; } diff --git a/Libraries/LibTLS/Socket.cpp b/Libraries/LibTLS/Socket.cpp index 0fc9018fe0..6b0488104d 100644 --- a/Libraries/LibTLS/Socket.cpp +++ b/Libraries/LibTLS/Socket.cpp @@ -113,7 +113,7 @@ bool TLSv12::common_connect(const struct sockaddr* saddr, socklen_t length) Core::Socket::on_connected = [this] { Core::Socket::on_ready_to_read = [this] { - if (!Core::Socket::is_open()) { + if (!Core::Socket::is_open() || !Core::Socket::is_connected() || Core::Socket::eof()) { // an abrupt closure (the server is a jerk) dbg() << "Socket not open, assuming abrupt closure"; m_context.connection_finished = true; @@ -143,7 +143,7 @@ bool TLSv12::common_connect(const struct sockaddr* saddr, socklen_t length) on_tls_ready_to_read(*this); }; Core::Socket::on_ready_to_write = [this] { - if (!Core::Socket::is_open()) { + if (!Core::Socket::is_open() || !Core::Socket::is_connected() || Core::Socket::eof()) { // an abrupt closure (the server is a jerk) dbg() << "Socket not open, assuming abrupt closure"; m_context.connection_finished = true; |