summaryrefslogtreecommitdiff
path: root/Libraries
diff options
context:
space:
mode:
authorAnotherTest <ali.mpfard@gmail.com>2020-05-03 21:26:23 +0430
committerAndreas Kling <kling@serenityos.org>2020-05-03 19:08:40 +0200
commitb028a123b8c4f1a71e21fe5037a7cfe5f8cf2da4 (patch)
treeef448ed538e3fdf006f0d75cb370ad894f7b0a87 /Libraries
parent8aeccf4f024a1e29aac74f86ed072de1a89d94e6 (diff)
downloadserenity-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.cpp62
-rw-r--r--Libraries/LibHTTP/HttpsJob.h2
-rw-r--r--Libraries/LibTLS/Socket.cpp4
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;